feat: delete XModuleDescriptorToXBlockMixin (#29927)
This:
1. Deletes XModuleDescriptorToXBlockMixin
2. Deletes `metadata_traslations` and `_translate()` from `XmlParserMixin`,
and all related implementations.
3. Removes translations of deprecated OLX attributes during import/export:
<old_attr> : <new_attr>
- 'slug' : 'url_name'
- 'name' : 'display_name'
- 'id' : 'discussion_id' (Discussion XBlock)
- 'for' : 'discussion_target' (Discussion XBlock)
- 'attempts' : 'max_attempts' (CAPA)
This commit is contained in:
@@ -19,7 +19,6 @@ from xmodule.x_module import (
|
||||
ResourceTemplates,
|
||||
shim_xmodule_js,
|
||||
XModuleMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
)
|
||||
|
||||
@@ -35,7 +34,6 @@ class AnnotatableBlock(
|
||||
RawMixin,
|
||||
XmlMixin,
|
||||
EditingMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
HTMLSnippet,
|
||||
ResourceTemplates,
|
||||
|
||||
@@ -41,7 +41,6 @@ from xmodule.util.xmodule_django import add_webpack_to_fragment
|
||||
from xmodule.x_module import (
|
||||
HTMLSnippet,
|
||||
ResourceTemplates,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleMixin,
|
||||
XModuleToXBlockMixin,
|
||||
shim_xmodule_js
|
||||
@@ -132,7 +131,6 @@ class ProblemBlock(
|
||||
RawMixin,
|
||||
XmlMixin,
|
||||
EditingMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
HTMLSnippet,
|
||||
ResourceTemplates,
|
||||
@@ -164,11 +162,6 @@ class ProblemBlock(
|
||||
mako_template = "widgets/problem-edit.html"
|
||||
has_author_view = True
|
||||
|
||||
# The capa format specifies that what we call max_attempts in the code
|
||||
# is the attribute `attempts`. This will do that conversion
|
||||
metadata_translations = dict(XmlMixin.metadata_translations)
|
||||
metadata_translations['attempts'] = 'max_attempts'
|
||||
|
||||
icon_class = 'problem'
|
||||
|
||||
uses_xmodule_styles_setup = True
|
||||
|
||||
@@ -27,7 +27,6 @@ from xmodule.x_module import (
|
||||
ResourceTemplates,
|
||||
shim_xmodule_js,
|
||||
STUDENT_VIEW,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleMixin,
|
||||
XModuleToXBlockMixin,
|
||||
)
|
||||
@@ -44,7 +43,6 @@ class ConditionalBlock(
|
||||
SequenceMixin,
|
||||
MakoTemplateBlockBase,
|
||||
XmlMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
HTMLSnippet,
|
||||
ResourceTemplates,
|
||||
|
||||
@@ -21,7 +21,6 @@ from xmodule.x_module import (
|
||||
HTMLSnippet,
|
||||
ResourceTemplates,
|
||||
XModuleMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
)
|
||||
|
||||
@@ -47,7 +46,6 @@ class ErrorFields:
|
||||
@XBlock.needs('mako')
|
||||
class ErrorBlock(
|
||||
ErrorFields,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
HTMLSnippet,
|
||||
ResourceTemplates,
|
||||
@@ -181,6 +179,16 @@ class ErrorBlock(
|
||||
|
||||
return cls._construct(system, xml_data, error_msg, location=id_generator.create_definition('error'))
|
||||
|
||||
@classmethod
|
||||
def parse_xml(cls, node, runtime, keys, id_generator): # lint-amnesty, pylint: disable=unused-argument
|
||||
"""
|
||||
Interpret the parsed XML in `node`, creating an XModuleDescriptor.
|
||||
"""
|
||||
# It'd be great to not reserialize and deserialize the xml
|
||||
xml = etree.tostring(node).decode('utf-8')
|
||||
block = cls.from_xml(xml, runtime, id_generator)
|
||||
return block
|
||||
|
||||
def export_to_xml(self, resource_fs):
|
||||
'''
|
||||
If the definition data is invalid xml, export it wrapped in an "error"
|
||||
@@ -201,6 +209,25 @@ class ErrorBlock(
|
||||
err_node.text = self.error_msg
|
||||
return etree.tostring(root, encoding='unicode')
|
||||
|
||||
def add_xml_to_node(self, node):
|
||||
"""
|
||||
Export this :class:`XModuleDescriptor` as XML, by setting attributes on the provided
|
||||
`node`.
|
||||
"""
|
||||
xml_string = self.export_to_xml(self.runtime.export_fs)
|
||||
exported_node = etree.fromstring(xml_string)
|
||||
node.tag = exported_node.tag
|
||||
node.text = exported_node.text
|
||||
node.tail = exported_node.tail
|
||||
|
||||
for key, value in exported_node.items():
|
||||
if key == 'url_name' and value == 'course' and key in node.attrib:
|
||||
# if url_name is set in ExportManager then do not override it here.
|
||||
continue
|
||||
node.set(key, value)
|
||||
|
||||
node.extend(list(exported_node))
|
||||
|
||||
|
||||
class NonStaffErrorBlock(ErrorBlock): # pylint: disable=abstract-method
|
||||
"""
|
||||
|
||||
@@ -7,7 +7,6 @@ from xblock.core import XBlock
|
||||
from xmodule.raw_module import RawMixin
|
||||
from xmodule.xml_module import XmlMixin
|
||||
from xmodule.x_module import (
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleMixin,
|
||||
XModuleToXBlockMixin,
|
||||
)
|
||||
@@ -17,7 +16,6 @@ from xmodule.x_module import (
|
||||
class HiddenDescriptor(
|
||||
RawMixin,
|
||||
XmlMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
XModuleMixin,
|
||||
):
|
||||
|
||||
@@ -30,7 +30,6 @@ from xmodule.x_module import (
|
||||
ResourceTemplates,
|
||||
shim_xmodule_js,
|
||||
XModuleMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
)
|
||||
from xmodule.xml_module import XmlMixin, name_to_pathname
|
||||
@@ -47,7 +46,7 @@ _ = lambda text: text
|
||||
@XBlock.needs("user")
|
||||
class HtmlBlockMixin( # lint-amnesty, pylint: disable=abstract-method
|
||||
XmlMixin, EditingMixin,
|
||||
XModuleDescriptorToXBlockMixin, XModuleToXBlockMixin, HTMLSnippet, ResourceTemplates, XModuleMixin,
|
||||
XModuleToXBlockMixin, HTMLSnippet, ResourceTemplates, XModuleMixin,
|
||||
):
|
||||
"""
|
||||
The HTML XBlock mixin.
|
||||
|
||||
@@ -35,7 +35,6 @@ from xmodule.x_module import (
|
||||
shim_xmodule_js,
|
||||
STUDENT_VIEW,
|
||||
XModuleMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
)
|
||||
|
||||
@@ -75,7 +74,6 @@ def _get_capa_types():
|
||||
class LibraryContentBlock(
|
||||
MakoTemplateBlockBase,
|
||||
XmlMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
HTMLSnippet,
|
||||
ResourceTemplates,
|
||||
|
||||
@@ -90,7 +90,6 @@ from xmodule.x_module import (
|
||||
HTMLSnippet,
|
||||
ResourceTemplates,
|
||||
shim_xmodule_js,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleMixin,
|
||||
XModuleToXBlockMixin,
|
||||
)
|
||||
@@ -282,7 +281,6 @@ class LTIBlock(
|
||||
XmlMixin,
|
||||
EditingMixin,
|
||||
MakoTemplateBlockBase,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
HTMLSnippet,
|
||||
ResourceTemplates,
|
||||
|
||||
@@ -242,10 +242,6 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin): # li
|
||||
|
||||
definition = json_data.get('definition', {})
|
||||
metadata = json_data.get('metadata', {})
|
||||
for old_name, new_name in getattr(class_, 'metadata_translations', {}).items():
|
||||
if old_name in metadata:
|
||||
metadata[new_name] = metadata[old_name]
|
||||
del metadata[old_name]
|
||||
|
||||
children = [
|
||||
self._convert_reference_to_key(childloc)
|
||||
|
||||
@@ -28,7 +28,6 @@ from xmodule.x_module import (
|
||||
ResourceTemplates,
|
||||
shim_xmodule_js,
|
||||
XModuleMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
)
|
||||
from xmodule.xml_module import XmlMixin
|
||||
@@ -41,7 +40,6 @@ _ = lambda text: text
|
||||
class PollBlock(
|
||||
MakoTemplateBlockBase,
|
||||
XmlMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
HTMLSnippet,
|
||||
ResourceTemplates,
|
||||
|
||||
@@ -14,7 +14,6 @@ from xmodule.x_module import (
|
||||
HTMLSnippet,
|
||||
ResourceTemplates,
|
||||
STUDENT_VIEW,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleMixin,
|
||||
XModuleToXBlockMixin,
|
||||
)
|
||||
@@ -26,7 +25,6 @@ class RandomizeBlock(
|
||||
SequenceMixin,
|
||||
MakoTemplateBlockBase,
|
||||
XmlMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
HTMLSnippet,
|
||||
ResourceTemplates,
|
||||
|
||||
@@ -29,7 +29,6 @@ from xmodule.x_module import (
|
||||
ResourceTemplates,
|
||||
shim_xmodule_js,
|
||||
STUDENT_VIEW,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleMixin,
|
||||
XModuleToXBlockMixin,
|
||||
)
|
||||
@@ -260,7 +259,6 @@ class SequenceBlock(
|
||||
ProctoringFields,
|
||||
MakoTemplateBlockBase,
|
||||
XmlMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
HTMLSnippet,
|
||||
ResourceTemplates,
|
||||
|
||||
@@ -30,7 +30,6 @@ from xmodule.x_module import (
|
||||
ResourceTemplates,
|
||||
shim_xmodule_js,
|
||||
STUDENT_VIEW,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleMixin,
|
||||
XModuleToXBlockMixin,
|
||||
)
|
||||
@@ -132,7 +131,6 @@ class SplitTestBlock( # lint-amnesty, pylint: disable=abstract-method
|
||||
ProctoringFields,
|
||||
MakoTemplateBlockBase,
|
||||
XmlMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
HTMLSnippet,
|
||||
ResourceTemplates,
|
||||
|
||||
@@ -16,7 +16,6 @@ from xmodule.x_module import (
|
||||
ResourceTemplates,
|
||||
shim_xmodule_js,
|
||||
XModuleMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
)
|
||||
from xmodule.xml_module import XmlMixin
|
||||
@@ -28,7 +27,6 @@ class CustomTagTemplateBlock( # pylint: disable=abstract-method
|
||||
RawMixin,
|
||||
XmlMixin,
|
||||
EditingMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
HTMLSnippet,
|
||||
ResourceTemplates,
|
||||
@@ -139,7 +137,6 @@ class CustomTagBlock(CustomTagTemplateBlock): # pylint: disable=abstract-method
|
||||
|
||||
|
||||
class TranslateCustomTagBlock( # pylint: disable=abstract-method
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
XModuleMixin,
|
||||
):
|
||||
|
||||
@@ -45,7 +45,7 @@ from xmodule.video_module import manage_video_subtitles_save
|
||||
from xmodule.x_module import (
|
||||
PUBLIC_VIEW, STUDENT_VIEW,
|
||||
HTMLSnippet, ResourceTemplates, shim_xmodule_js,
|
||||
XModuleMixin, XModuleToXBlockMixin, XModuleDescriptorToXBlockMixin,
|
||||
XModuleMixin, XModuleToXBlockMixin,
|
||||
)
|
||||
from xmodule.xml_module import XmlMixin, deserialize_field, is_pointer_tag, name_to_pathname
|
||||
|
||||
@@ -113,7 +113,7 @@ EXPORT_IMPORT_STATIC_DIR = 'static'
|
||||
class VideoBlock(
|
||||
VideoFields, VideoTranscriptsMixin, VideoStudioViewHandlers, VideoStudentViewHandlers,
|
||||
TabsEditingMixin, EmptyDataRawMixin, XmlMixin, EditingMixin,
|
||||
XModuleDescriptorToXBlockMixin, XModuleToXBlockMixin, HTMLSnippet, ResourceTemplates, XModuleMixin,
|
||||
XModuleToXBlockMixin, HTMLSnippet, ResourceTemplates, XModuleMixin,
|
||||
LicenseMixin):
|
||||
"""
|
||||
XML source example:
|
||||
|
||||
@@ -24,7 +24,6 @@ from xmodule.x_module import (
|
||||
ResourceTemplates,
|
||||
shim_xmodule_js,
|
||||
XModuleMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
)
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -49,7 +48,6 @@ class WordCloudBlock( # pylint: disable=abstract-method
|
||||
EmptyDataRawMixin,
|
||||
XmlMixin,
|
||||
EditingMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
HTMLSnippet,
|
||||
ResourceTemplates,
|
||||
|
||||
@@ -1104,99 +1104,8 @@ class ResourceTemplates:
|
||||
return template
|
||||
|
||||
|
||||
class XModuleDescriptorToXBlockMixin:
|
||||
"""
|
||||
Common code needed by XModuleDescriptor and XBlocks converted from XModules.
|
||||
"""
|
||||
# VS[compat]. Backwards compatibility code that can go away after
|
||||
# importing 2012 courses.
|
||||
# A set of metadata key conversions that we want to make
|
||||
metadata_translations = {
|
||||
'slug': 'url_name',
|
||||
'name': 'display_name',
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def _translate(cls, key):
|
||||
return cls.metadata_translations.get(key, key)
|
||||
|
||||
# ================================= XML PARSING ============================
|
||||
@classmethod
|
||||
def parse_xml(cls, node, runtime, keys, id_generator): # lint-amnesty, pylint: disable=unused-argument
|
||||
"""
|
||||
Interpret the parsed XML in `node`, creating an XModuleDescriptor.
|
||||
"""
|
||||
# It'd be great to not reserialize and deserialize the xml
|
||||
xml = etree.tostring(node).decode('utf-8')
|
||||
block = cls.from_xml(xml, runtime, id_generator)
|
||||
return block
|
||||
|
||||
@classmethod
|
||||
def parse_xml_new_runtime(cls, node, runtime, keys):
|
||||
"""
|
||||
This XML lives within Blockstore and the new runtime doesn't need this
|
||||
legacy XModule code. Use the "normal" XBlock parsing code.
|
||||
"""
|
||||
try:
|
||||
return super().parse_xml_new_runtime(node, runtime, keys)
|
||||
except AttributeError:
|
||||
return super().parse_xml(node, runtime, keys, id_generator=None)
|
||||
|
||||
@classmethod
|
||||
def from_xml(cls, xml_data, system, id_generator):
|
||||
"""
|
||||
Creates an instance of this descriptor from the supplied xml_data.
|
||||
This may be overridden by subclasses.
|
||||
|
||||
Args:
|
||||
xml_data (str): A string of xml that will be translated into data and children
|
||||
for this module
|
||||
|
||||
system (:class:`.XMLParsingSystem):
|
||||
|
||||
id_generator (:class:`xblock.runtime.IdGenerator`): Used to generate the
|
||||
usage_ids and definition_ids when loading this xml
|
||||
|
||||
"""
|
||||
raise NotImplementedError('Modules must implement from_xml to be parsable from xml')
|
||||
|
||||
def add_xml_to_node(self, node):
|
||||
"""
|
||||
Export this :class:`XModuleDescriptor` as XML, by setting attributes on the provided
|
||||
`node`.
|
||||
"""
|
||||
xml_string = self.export_to_xml(self.runtime.export_fs)
|
||||
exported_node = etree.fromstring(xml_string)
|
||||
node.tag = exported_node.tag
|
||||
node.text = exported_node.text
|
||||
node.tail = exported_node.tail
|
||||
|
||||
for key, value in exported_node.items():
|
||||
if key == 'url_name' and value == 'course' and key in node.attrib:
|
||||
# if url_name is set in ExportManager then do not override it here.
|
||||
continue
|
||||
node.set(key, value)
|
||||
|
||||
node.extend(list(exported_node))
|
||||
|
||||
def export_to_xml(self, resource_fs):
|
||||
"""
|
||||
Returns an xml string representing this module, and all modules
|
||||
underneath it. May also write required resources out to resource_fs.
|
||||
|
||||
Assumes that modules have single parentage (that no module appears twice
|
||||
in the same course), and that it is thus safe to nest modules as xml
|
||||
children as appropriate.
|
||||
|
||||
The returned XML should be able to be parsed back into an identical
|
||||
XModuleDescriptor using the from_xml method with the same system, org,
|
||||
and course
|
||||
"""
|
||||
raise NotImplementedError('Modules must implement export_to_xml to enable xml export')
|
||||
|
||||
|
||||
@XBlock.needs("i18n")
|
||||
class XModuleDescriptor(XModuleDescriptorToXBlockMixin, HTMLSnippet, ResourceTemplates, XModuleMixin): # lint-amnesty, pylint: disable=abstract-method
|
||||
class XModuleDescriptor(HTMLSnippet, ResourceTemplates, XModuleMixin): # lint-amnesty, pylint: disable=abstract-method
|
||||
"""
|
||||
An XModuleDescriptor is a specification for an element of a course. This
|
||||
could be a problem, an organizational element (a group of content), or a
|
||||
|
||||
@@ -112,21 +112,6 @@ class XmlParserMixin:
|
||||
xml_attributes = Dict(help="Map of unhandled xml attributes, used only for storage between import and export",
|
||||
default={}, scope=Scope.settings)
|
||||
|
||||
# VS[compat]. Backwards compatibility code that can go away after
|
||||
# importing 2012 courses.
|
||||
# A set of metadata key conversions that we want to make
|
||||
metadata_translations = {
|
||||
'slug': 'url_name',
|
||||
'name': 'display_name',
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def _translate(cls, key):
|
||||
"""
|
||||
VS[compat]
|
||||
"""
|
||||
return cls.metadata_translations.get(key, key)
|
||||
|
||||
# The attributes will be removed from the definition xml passed
|
||||
# to definition_from_xml, and from the xml returned by definition_to_xml
|
||||
|
||||
@@ -275,8 +260,6 @@ class XmlParserMixin:
|
||||
"""
|
||||
metadata = {'xml_attributes': {}}
|
||||
for attr, val in xml_object.attrib.items():
|
||||
# VS[compat]. Remove after all key translations done
|
||||
attr = cls._translate(attr)
|
||||
|
||||
if attr in cls.metadata_to_strip:
|
||||
# don't load these
|
||||
@@ -295,7 +278,6 @@ class XmlParserMixin:
|
||||
through the attrmap. Updates the metadata dict in place.
|
||||
"""
|
||||
for attr, value in policy.items():
|
||||
attr = cls._translate(attr)
|
||||
if attr not in cls.fields:
|
||||
# Store unknown attributes coming from policy.json
|
||||
# in such a way that they will export to xml unchanged
|
||||
@@ -561,9 +543,9 @@ class XmlMixin(XmlParserMixin): # lint-amnesty, pylint: disable=abstract-method
|
||||
Interpret the parsed XML in `node`, creating an XModuleDescriptor.
|
||||
"""
|
||||
if cls.from_xml != XmlMixin.from_xml:
|
||||
# Skip the parse_xml from XmlParserMixin to get the shim parse_xml
|
||||
# from XModuleDescriptor, which actually calls `from_xml`.
|
||||
return super(XmlParserMixin, cls).parse_xml(node, runtime, keys, id_generator) # pylint: disable=bad-super-call
|
||||
xml = etree.tostring(node).decode('utf-8')
|
||||
block = cls.from_xml(xml, runtime, id_generator)
|
||||
return block
|
||||
else:
|
||||
return super().parse_xml(node, runtime, keys, id_generator)
|
||||
|
||||
@@ -605,9 +587,19 @@ class XmlMixin(XmlParserMixin): # lint-amnesty, pylint: disable=abstract-method
|
||||
`node`.
|
||||
"""
|
||||
if self.export_to_xml != XmlMixin.export_to_xml: # lint-amnesty, pylint: disable=comparison-with-callable
|
||||
# Skip the add_xml_to_node from XmlParserMixin to get the shim add_xml_to_node
|
||||
# from XModuleDescriptor, which actually calls `export_to_xml`.
|
||||
super(XmlParserMixin, self).add_xml_to_node(node) # pylint: disable=bad-super-call
|
||||
xml_string = self.export_to_xml(self.runtime.export_fs)
|
||||
exported_node = etree.fromstring(xml_string)
|
||||
node.tag = exported_node.tag
|
||||
node.text = exported_node.text
|
||||
node.tail = exported_node.tail
|
||||
|
||||
for key, value in exported_node.items():
|
||||
if key == 'url_name' and value == 'course' and key in node.attrib:
|
||||
# if url_name is set in ExportManager then do not override it here.
|
||||
continue
|
||||
node.set(key, value)
|
||||
|
||||
node.extend(list(exported_node))
|
||||
else:
|
||||
super().add_xml_to_node(node)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<course name="Conditional Course" org="edX" course="cond_test" graceperiod="1 day 5 hours 59 minutes 59 seconds"
|
||||
slug="2012_Fall" start="2012-07-17T12:00">
|
||||
<chapter name="Problems with Condition">
|
||||
<course display_name="Conditional Course" org="edX" course="cond_test" graceperiod="1 day 5 hours 59 minutes 59 seconds"
|
||||
url_name="2012_Fall" start="2012-07-17T12:00">
|
||||
<chapter display_name="Problems with Condition">
|
||||
<!-- In order for the conditional to reference modules via "show",
|
||||
they must be defined elsewhere in the course. Therefore, add them to a
|
||||
non-released sequential. -->
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Take note of this name exactly, you'll need to use it everywhere. -->
|
||||
<course>
|
||||
<chapter url_name="Staff"/>
|
||||
<chapter name="Problems with Condition">
|
||||
<chapter display_name="Problems with Condition">
|
||||
<sequential>
|
||||
<problem url_name="choiceprob" />
|
||||
<conditional url_name="condone"/>
|
||||
|
||||
@@ -1 +1 @@
|
||||
<course org="edX" course="course_ignore" slug="2014_Fall"/>
|
||||
<course org="edX" course="course_ignore" url_name="2014_Fall"/>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<problem attempts="10" weight="null" max_attempts="null" markdown="null">
|
||||
<problem weight="null" max_attempts="10" markdown="null">
|
||||
<script type="loncapa/python">
|
||||
|
||||
def two_d_grader(expect,ans):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<problem attempts="10" weight="null" max_attempts="null" markdown="null">
|
||||
<problem weight="null" max_attempts="10" markdown="null">
|
||||
<script type="loncapa/python">
|
||||
|
||||
def two_d_grader(expect,ans):
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<course name="A Simple Course" org="edX" course="simple" graceperiod="1 day 5 hours 59 minutes 59 seconds" slug="2012_Fall">
|
||||
<chapter name="Overview">
|
||||
<course display_name="A Simple Course" org="edX" course="simple" graceperiod="1 day 5 hours 59 minutes 59 seconds" url_name="2012_Fall">
|
||||
<chapter display_name="Overview">
|
||||
<video name="Welcome" youtube_id_0_75="izygArpw-Qo" youtube_id_1_0="p2Q6BrNhdh8" youtube_id_1_25="1EeWXzPdhSA" youtube_id_1_5="rABDYkeK0x8"/>
|
||||
<sequential format="Lecture Sequence" name="A simple sequence">
|
||||
<html name="toylab" filename="toylab"/>
|
||||
<sequential format="Lecture Sequence" display_name="A simple sequence">
|
||||
<html display_name="toylab" filename="toylab"/>
|
||||
<video name="S0V1: Video Resources" youtube_id_0_75="EuzkdzfR0i8" youtube_id_1_0="1bK-WdDi6Qw" youtube_id_1_25="0v1VzoDVUTM" youtube_id_1_5="Bxk_-ZJb240"/>
|
||||
</sequential>
|
||||
<sequential name="Lecture 2">>
|
||||
<sequential display_name="Lecture 2">
|
||||
<video youtube_id_1_0="TBvX7HzxexQ"/>
|
||||
<problem name="L1 Problem 1" points="1" type="lecture" showanswer="attempted" filename="L1_Problem_1" rerandomize="never"/>
|
||||
<problem display_name="L1 Problem 1" points="1" type="lecture" showanswer="attempted" filename="L1_Problem_1" rerandomize="never"/>
|
||||
</sequential>
|
||||
</chapter>
|
||||
<chapter name="Chapter 2" url_name='chapter_2'>
|
||||
<sequential name="Problem Set 1">
|
||||
<problem type="lecture" showanswer="attempted" rerandomize="true" display_name="A simple coding problem" name="Simple coding problem" filename="ps01-simple" url_name="ps01-simple"/>
|
||||
<chapter display_name="Chapter 2" url_name='chapter_2'>
|
||||
<sequential display_name="Problem Set 1">
|
||||
<problem type="lecture" showanswer="attempted" rerandomize="true" display_name="Simple coding problem" filename="ps01-simple" url_name="ps01-simple"/>
|
||||
</sequential>
|
||||
<video name="Lost Video" youtube_id_1_0="TBvX7HzxexQ"/>
|
||||
<sequential format="Lecture Sequence" url_name='test_sequence'>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<course name="A Simple Course" org="edX" course="simple_with_draft" graceperiod="1 day 5 hours 59 minutes 59 seconds" slug="2012_Fall">
|
||||
<chapter name="Overview">
|
||||
<course display_name="A Simple Course" org="edX" course="simple_with_draft" graceperiod="1 day 5 hours 59 minutes 59 seconds" url_name="2012_Fall">
|
||||
<chapter display_name="Overview">
|
||||
<video name="Welcome" youtube_id_0_75="izygArpw-Qo" youtube_id_1_0="p2Q6BrNhdh8" youtube_id_1_25="1EeWXzPdhSA" youtube_id_1_5="rABDYkeK0x8"/>
|
||||
<sequential format="Lecture Sequence" name="A simple sequence">
|
||||
<html name="toylab" filename="toylab"/>
|
||||
<sequential format="Lecture Sequence" display_name="A simple sequence">
|
||||
<html display_name="toylab" filename="toylab"/>
|
||||
<video name="S0V1: Video Resources" youtube_id_0_75="EuzkdzfR0i8" youtube_id_1_0="1bK-WdDi6Qw" youtube_id_1_25="0v1VzoDVUTM" youtube_id_1_5="Bxk_-ZJb240"/>
|
||||
</sequential>
|
||||
<sequential name="Lecture 2">
|
||||
<sequential display_name="Lecture 2">
|
||||
<video youtube_id_1_0="TBvX7HzxexQ"/>
|
||||
<problem name="L1 Problem 1" points="1" type="lecture" showanswer="attempted" filename="L1_Problem_1" rerandomize="never"/>
|
||||
<problem display_name="L1 Problem 1" points="1" type="lecture" showanswer="attempted" filename="L1_Problem_1" rerandomize="never"/>
|
||||
</sequential>
|
||||
</chapter>
|
||||
<chapter name="Chapter 2" url_name='chapter_2'>
|
||||
<sequential name="Problem Set 1">
|
||||
<problem type="lecture" showanswer="attempted" rerandomize="true" display_name="A simple coding problem" name="Simple coding problem" filename="ps01-simple" url_name="ps01-simple"/>
|
||||
<chapter display_name="Chapter 2" url_name='chapter_2'>
|
||||
<sequential display_name="Problem Set 1">
|
||||
<problem type="lecture" showanswer="attempted" rerandomize="true" display_name="Simple coding problem" filename="ps01-simple" url_name="ps01-simple"/>
|
||||
</sequential>
|
||||
<video name="Lost Video" youtube_id_1_0="TBvX7HzxexQ"/>
|
||||
<sequential format="Lecture Sequence" url_name='test_sequence'>
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
<split_test url_name="split1" user_partition_id="0" group_id_to_child='{"0": "i4x://split_test/split_test/vertical/sample_0", "2": "i4x://split_test/split_test/vertical/sample_2"}'>
|
||||
<vertical url_name="sample_0">
|
||||
<html>Here is a prompt for group 0, please respond in the discussion.</html>
|
||||
<discussion for="split test discussion 0" id="split_test_d0" discussion_category="Lectures"/>
|
||||
<discussion discussion_target="split test discussion 0" discussion_id="split_test_d0" discussion_category="Lectures"/>
|
||||
</vertical>
|
||||
|
||||
<vertical url_name="sample_2">
|
||||
<html>Here is a prompt for group 2, please respond in the discussion.</html>
|
||||
<discussion for="split test discussion 2" id="split_test_d2" discussion_category="Lectures"/>
|
||||
<discussion discussion_target="split test discussion 2" discussion_id="split_test_d2" discussion_category="Lectures"/>
|
||||
</vertical>
|
||||
</split_test>
|
||||
</vertical>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<sequential>
|
||||
<sequential filename='vertical_sequential' slug='vertical_sequential' />
|
||||
<sequential filename='vertical_sequential' url_name='vertical_sequential' />
|
||||
</sequential>
|
||||
@@ -1,4 +1,4 @@
|
||||
<sequential>
|
||||
<vertical filename="vertical_test" slug="vertical_test" />
|
||||
<html slug="unicode">…</html>
|
||||
<vertical filename="vertical_test" url_name="vertical_test" />
|
||||
<html url_name="unicode">…</html>
|
||||
</sequential>
|
||||
@@ -1,3 +1,3 @@
|
||||
<sequential>
|
||||
<sequential filename='vertical_sequential' slug='vertical_sequential' />
|
||||
<sequential filename='vertical_sequential' url_name='vertical_sequential' />
|
||||
</sequential>
|
||||
@@ -1,4 +1,4 @@
|
||||
<sequential>
|
||||
<vertical filename="vertical_test" slug="vertical_test" />
|
||||
<html slug="unicode">…</html>
|
||||
<vertical filename="vertical_test" url_name="vertical_test" />
|
||||
<html url_name="unicode">…</html>
|
||||
</sequential>
|
||||
@@ -1,4 +1,4 @@
|
||||
<sequential>
|
||||
<vertical filename="vertical_test" slug="vertical_test" />
|
||||
<html slug="unicode">…</html>
|
||||
<vertical filename="vertical_test" url_name="vertical_test" />
|
||||
<html url_name="unicode">…</html>
|
||||
</sequential>
|
||||
@@ -1,3 +1,3 @@
|
||||
<sequential>
|
||||
<sequential filename='vertical_sequential' slug='vertical_sequential' />
|
||||
<sequential filename='vertical_sequential' url_name='vertical_sequential' />
|
||||
</sequential>
|
||||
@@ -1,4 +1,4 @@
|
||||
<sequential>
|
||||
<vertical filename="vertical_test" slug="vertical_test" />
|
||||
<html slug="unicode">…</html>
|
||||
<vertical filename="vertical_test" url_name="vertical_test" />
|
||||
<html url_name="unicode">…</html>
|
||||
</sequential>
|
||||
@@ -1,5 +1,5 @@
|
||||
<sequential>
|
||||
<vertical name="test_vertical">
|
||||
<vertical display_name="test_vertical">
|
||||
<word_cloud name="cloud1" display_name="cloud" num_inputs="5" num_top_words="250" />
|
||||
</vertical>
|
||||
</sequential>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<course course_image="just_a_test.jpg">
|
||||
<chapter url_name="Overview">
|
||||
<sequential>
|
||||
<vertical filename="vertical_test" slug="vertical_test" />
|
||||
<vertical filename="vertical_test" url_name="vertical_test" />
|
||||
</sequential>
|
||||
<sequential>
|
||||
<vertical url_name="zeta">
|
||||
<html url_name="toyhtml"/>
|
||||
<discussion id="duplicate_def" slug="duplicate_def" discussion_category="Lectures"/>
|
||||
<discussion discussion_id="duplicate_def" url_name="duplicate_def" discussion_category="Lectures"/>
|
||||
</vertical>
|
||||
</sequential>
|
||||
</chapter>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<sequential>
|
||||
<html url_name="toyhtml"/>
|
||||
<discussion for="topic 0" id="duplicate_def" slug="duplicate_def" discussion_category="Lecture"/>
|
||||
<discussion discussion_target="topic 0" discussion_id="duplicate_def" url_name="duplicate_def" discussion_category="Lecture"/>
|
||||
</sequential>
|
||||
|
||||
@@ -29,9 +29,9 @@ AttributePair = namedtuple("AttributePair", ["name", "value"])
|
||||
AttributePair.__repr__ = attribute_pair_repr
|
||||
|
||||
|
||||
ID_ATTR_NAMES = ("discussion_id", "id",)
|
||||
ID_ATTR_NAMES = ("discussion_id",)
|
||||
CATEGORY_ATTR_NAMES = ("discussion_category",)
|
||||
TARGET_ATTR_NAMES = ("discussion_target", "for", )
|
||||
TARGET_ATTR_NAMES = ("discussion_target",)
|
||||
|
||||
|
||||
def _random_string():
|
||||
|
||||
@@ -72,11 +72,6 @@ class DiscussionXBlock(XBlock, StudioEditableXBlockMixin, XmlParserMixin): # li
|
||||
|
||||
has_author_view = True # Tells Studio to use author_view
|
||||
|
||||
# support for legacy OLX format - consumed by XmlParserMixin.load_metadata
|
||||
metadata_translations = dict(XmlParserMixin.metadata_translations)
|
||||
metadata_translations['id'] = 'discussion_id'
|
||||
metadata_translations['for'] = 'discussion_target'
|
||||
|
||||
@property
|
||||
def course_key(self):
|
||||
"""
|
||||
@@ -243,20 +238,10 @@ class DiscussionXBlock(XBlock, StudioEditableXBlockMixin, XmlParserMixin): # li
|
||||
"""
|
||||
block = super().parse_xml(node, runtime, keys, id_generator)
|
||||
|
||||
cls._apply_translations_to_node_attributes(block, node)
|
||||
cls._apply_metadata_and_policy(block, node, runtime)
|
||||
|
||||
return block
|
||||
|
||||
@classmethod
|
||||
def _apply_translations_to_node_attributes(cls, block, node):
|
||||
"""
|
||||
Applies metadata translations for attributes stored on an inlined XML element.
|
||||
"""
|
||||
for old_attr, target_attr in cls.metadata_translations.items():
|
||||
if old_attr in node.attrib and hasattr(block, target_attr):
|
||||
setattr(block, target_attr, node.attrib[old_attr])
|
||||
|
||||
@classmethod
|
||||
def _apply_metadata_and_policy(cls, block, node, runtime):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user