Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions common/lib/xmodule/xmodule/poll_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,13 @@ def definition_from_xml(cls, xml_object, system):

def definition_to_xml(self, resource_fs):
"""Return an xml element representing to this definition."""
poll_str = '<{tag_name}>{text}</{tag_name}>'.format(
poll_str = u'<{tag_name}>{text}</{tag_name}>'.format(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised we're grinding the xml out literally rather than using a library like etree. I don't know what different it would make to use a library tho (I'm wondering if it handles the {text} payload better if it has tags and such). (the code would be

  # if self.question is parsable xml
  xml_object = etree.Element(self._tag_name)
  xml_object.append(etree.fromstring(self.question))
  # if self.question is just text
  xml_object = etree.Element(self._tag_name, text=self.question)
  xml_object.set('display_name', self.display_name)
  ...

but that assumes self.question is itself parsable xml. Otherwise

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is interesting, and I did play around with it. However, it does not appear to be straightforward.

I don't think self.question is necessarily parsable XML (and using the first suggested option leads to a unit test error related to unexpected end of document).

Using text=self.question stores the question as a text attribute, which is different from how it is currently stored. This leads to roundtrip export unit test failures (different failures from the first suggested option).

It does appear that using etree properly handles unicode. Nonetheless, with my very limited understanding of this code, I think that changing how the XML is generated is beyond the scope of this bug fix.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's ok. I can hold my nose and fully agree you're not responsible :-)

As to how to do it, if self.question may sometimes be parsable xml, then surround the fromstring call w/ try/except and do xml_object.set('text', self.question) in the except (I think). BUT, I'm cool w/ leaving it as is (do no harm).

tag_name=self._tag_name, text=self.question)
xml_object = etree.fromstring(poll_str)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do the 'reset' and 'name' attrs get set? (see test: <poll_question name="T1_changemind_poll_foo" display_name="Change your answer" reset="false">)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reset attribute gets written out in xml_module's export_to_xml code, after the subclassed definition_to_xml has returned:

for key, value in self.xml_attributes.items():
if key not in self.metadata_to_strip:
xml_object.set(key, value)

The name attribute is more circuitous. It is an old, but still recognized, format of url_name. It is used to create the output file (also in xml_module's exort_to_xml method):

url_path = name_to_pathname(self.url_name)
filepath = self._format_filepath(self.category, url_path)

xml_object.set('display_name', self.display_name)

def add_child(xml_obj, answer):
child_str = '<{tag_name} id="{id}">{text}</{tag_name}>'.format(
child_str = u'<{tag_name} id="{id}">{text}</{tag_name}>'.format(
tag_name=self._child_tag_name, id=answer['id'],
text=answer['text'])
child_node = etree.fromstring(child_str)
Expand Down
5 changes: 4 additions & 1 deletion common/lib/xmodule/xmodule/xml_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,10 @@ def export_to_xml(self, resource_fs):
try:
xml_object.set(attr, val)
except Exception, e:
logging.exception('Failed to serialize metadata attribute {0} with value {1}. This could mean data loss!!! Exception: {2}'.format(attr, val, e))
logging.exception(
u'Failed to serialize metadata attribute %s with value %s in module %s. This could mean data loss!!! Exception: %s',
attr, val, self.url_name, e
)
pass

for key, value in self.xml_attributes.items():
Expand Down
2 changes: 1 addition & 1 deletion common/test/data/toy/chapter/poll_test.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<sequential>
<poll_question name="T1_changemind_poll_foo" display_name="Change your answer" reset="false">
<p>Have you changed your mind?</p>
<p>Have you changed your mind?</p>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, this is a test. Never mind.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I added it to the existing toy test course so that it covered the bug fix (a unit test fails without the fix).

<answer id="yes">Yes</answer>
<answer id="no">No</answer>
</poll_question>
Expand Down