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:
Kaustav Banerjee
2022-04-21 20:45:00 +05:30
committed by GitHub
parent 48b0df4f99
commit 702866b225
38 changed files with 93 additions and 215 deletions

View File

@@ -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,

View File

@@ -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

View File

@@ -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,

View File

@@ -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
"""

View File

@@ -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,
):

View File

@@ -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.

View File

@@ -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,

View File

@@ -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,

View File

@@ -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)

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,
):

View File

@@ -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:

View File

@@ -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,

View File

@@ -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

View File

@@ -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)

View File

@@ -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. -->

View File

@@ -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"/>

View File

@@ -1 +1 @@
<course org="edX" course="course_ignore" slug="2014_Fall"/>
<course org="edX" course="course_ignore" url_name="2014_Fall"/>

View File

@@ -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):

View File

@@ -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):

View File

@@ -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'>

View File

@@ -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'>

View File

@@ -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>

View File

@@ -1,3 +1,3 @@
<sequential>
<sequential filename='vertical_sequential' slug='vertical_sequential' />
<sequential filename='vertical_sequential' url_name='vertical_sequential' />
</sequential>

View File

@@ -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>

View File

@@ -1,3 +1,3 @@
<sequential>
<sequential filename='vertical_sequential' slug='vertical_sequential' />
<sequential filename='vertical_sequential' url_name='vertical_sequential' />
</sequential>

View File

@@ -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>

View File

@@ -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>

View File

@@ -1,3 +1,3 @@
<sequential>
<sequential filename='vertical_sequential' slug='vertical_sequential' />
<sequential filename='vertical_sequential' url_name='vertical_sequential' />
</sequential>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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():

View File

@@ -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):
"""