XModule Conversion to XBlock
This page documents hackathon work on converting XModules to XBlocks. Here's the first steps we'll take:
- Convert the "vertical" XModule.
- This is a core module that all courses use.
- It's also theoretically easy to convert.
- And we'll know immediately if we've broken it.
Cale advises us to start with these items:
- Take the XModule and XModuleDescriptor-derived classes for "vertical" and munge the methods into a single class.
- Derive the new class from XBlock.
- Split the get_html() method into a student_view() and a studio_view() method.
- Tend to XML serialization and any Javascript/Coffeescript that might need to be converted.
We created a branch for the initial work: jeskew/xmodule_to_xblock_vertical
.
- First error, __init__ in XBlock and XModule classes differ.
We switched the VerticalModule to inherit from XBlock instead of XModule and munged the methods from VerticalDescriptor into VerticalModule.
Roadblocks:
- The test_vertical.py unittests failed - it's likely due to the tests no longer being set up correctly. XBlocks need to be created instead of XModules.
- When starting up the LMS, the static asset collection of assets fails due to not finding a get_javascript() method.
- The code is still calling VerticalModule like an XModule instead of an XBlock.
A WrapperModule and WrapperDescriptor class also existed that derived from VerticalModule/VerticalDescriptor. The WrapperDescriptor class was also removed.
We were able to make the static asset collection work by removing the VerticalDescriptor class completely. BUT that wasn't enough - we had to remove the "vertical" and "wrapper" lines from the common/lib/xmodule/setup.py
file as well and rerun "pip install -r requirements/edx/local.txt
". This action removed the entry points from the common/lib/xmodule/XModule.egg-info/entry_points.txt
file - and removed the exceptions occurring upon XBlock creation.
All these actions brought us to a non-exception error on a vertical: "ERROR: This module is unknown–students will not see it at all"
A HiddenModule was being constructed for the XBlock due to no entry point being found for the vertical. Nimisha added the entry points back into setup.py, pointing at the VerticalModule/WrapperModule and only in the "xblock.v1" section. We then ran "pip install -r requirements/edx/local.txt" to fix the XModule entry_points.txt file. This brought us to a "UndefinedContext" exception being raised by the XModuleDescriptor._xmodule property.
We then hacked in a PureSystem() as a runtime for vertical children only. But we found that in some calls to cache_for_descriptor_descendents() called only to a depth of 2, providing get_module_for_descriptor() with a proper cache and setting up bind_for_student() properly underneath. Basically, the problem is that we're sometime constructing a PureSystem() with a None module runtime.
Questions:
- When an XBlock/XModule is constructed, can we always assume that it'll have an associated module runtime? An associated descriptor runtime?
- Answer: Seems to be "No" for a module runtime. For an XModule, the runtime seems to be course- and student- specific. A descriptor runtime is course- and student-agnostic.
A PR was created against the branch for this work - it's here:
https://github.com/edx/edx-platform/pull/6035
A separate branch was created for converting the HTMLDescriptor class - it's here:
https://github.com/itsbenweeks/edx-platform/tree/itsbenweeks/html_xmodule_to_xblock