Skip to content

Debugging and troubleshooting

cjshawMIT edited this page May 8, 2017 · 3 revisions

Many times it can be difficult to debug and troubleshoot the builder, because it isn't clear where the final code originated from -- a template (and if so, which one?), or a hand-written implementation? To help, we recommend that each template includes a comment about the origin, like in jsonosid_templates/resource.py:

    get_resources_by_query_template = """
        # Implemented from template for
        # osid.resource.ResourceQuerySession.get_resources_by_query

You'll notice that many templates appear in the resource package, while some containable things appear in learning or repository. Unfortunately the templates currently reside in the first place we see the pattern, so it's not consistent where they may appear. We hope to migrate to a system where the templates are standalone, but have not made any progress towards that.

Using the pattern maps

If there is not an obvious comment indicating the source template, you can always check the pattern maps for a specific package. For example, in the assessment.py pattern map, you'll see:

   "AssessmentProfile.init_pattern": "resource.ResourceProfile", 
   "AssessmentProfile.supports_visible_federation": {
      "pattern": "resource.ResourceProfile.supports_visible_federation", 
      "kwargs": {
         "method_name": "supports_visible_federation", 
         "module_name": "managers", 
         "var_name": "supports_visible_federation", 
         "interface_name": "AssessmentProfile", 
         "package_name": "assessment"
      }
   }, 

This means that this pulls from *_templates/resource.py::ResourceProfile::supports_visible_federation_template attribute.

If you see one with an empty pattern field, then that needs to be hand-written, or the pattern has not been identified.

   "MyAssessmentTakenSession.can_get_my_taken_assessments": {
      "pattern": "", 
      "kwargs": {
         "method_name": "can_get_my_taken_assessments", 
         "module_name": "sessions", 
         "interface_name": "MyAssessmentTakenSession", 
         "package_name": "assessment"
      }
   }, 

To hand-write this implementation, you would need to create a class MyAssessmentTakenSession in *_templates/assessment.py, with an attribute can_get_my_taken_assessments:

class MyAssessmentTakenSession:
    can_get_my_taken_assessments = """
        <do stuff>"""

Updating the patterns

If you find new patterns or a wrong pattern, you will need to update the pattern algorithm in the appropriate pattern_mappers/*.py file. Include the right test conditions and the pattern path, like below:

        elif (method['name'].startswith('set_') and
                len(method['arg_types']) == 1 and
                method['arg_types'][0] == 'osid.id.Id[]' and
                method['args'][0]['array'] is True):
            index[interface['shortname'] + '.' + method['name']] = dict(
                pattern='learning.ActivityForm.set_assets',
                kwargs=dict(interface_name=interface['shortname'],
                            package_name=package['name'],
                            module_name=interface['category'],
                            method_name=method['name'],
                            var_name=var_name,
                            arg0_name=method['args'][0]['var_name'],
                            arg0_type_full=method['args'][0]['arg_type']))

Using pdb

Using the pdb library and it's set_trace() method can be particularly helpful in debugging build issues. You may want to target a specific package (i.e. assessment), interface (i.e. Item), or method (i.e. get_items_by_query()). To do so, anywhere in the builder you can set a conditional trace using specific fields, like:

if self.package['name'] == 'assessment':
    import pdb
    pdb.set_trace()
if interface['shortname'] == 'Item':
    import pdb
    pdb.set_trace()
if method['name'] == 'get_items_by_query':
    import pdb
    pdb.set_trace()