diff --git a/common/djangoapps/mitxmako/shortcuts.py b/common/djangoapps/mitxmako/shortcuts.py index ba22f2db20..ebeb0fc180 100644 --- a/common/djangoapps/mitxmako/shortcuts.py +++ b/common/djangoapps/mitxmako/shortcuts.py @@ -12,10 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import logging - -log = logging.getLogger("mitx." + __name__) - from django.template import Context from django.http import HttpResponse @@ -42,7 +38,7 @@ def render_to_string(template_name, dictionary, context=None, namespace='main'): context_dictionary.update(context) # fetch and render template template = middleware.lookup[namespace].get_template(template_name) - return template.render(**context_dictionary) + return template.render_unicode(**context_dictionary) def render_to_response(template_name, dictionary, context_instance=None, namespace='main', **kwargs): diff --git a/common/djangoapps/mitxmako/template.py b/common/djangoapps/mitxmako/template.py index 56096fe173..947dc8c1a4 100644 --- a/common/djangoapps/mitxmako/template.py +++ b/common/djangoapps/mitxmako/template.py @@ -54,5 +54,4 @@ class Template(MakoTemplate): context_dictionary['MITX_ROOT_URL'] = settings.MITX_ROOT_URL context_dictionary['django_context'] = context_instance - return super(Template, self).render(**context_dictionary) - + return super(Template, self).render_unicode(**context_dictionary) diff --git a/common/lib/xmodule/xmodule/error_module.py b/common/lib/xmodule/xmodule/error_module.py index 65fceb77c7..2df47e05e6 100644 --- a/common/lib/xmodule/xmodule/error_module.py +++ b/common/lib/xmodule/xmodule/error_module.py @@ -149,14 +149,14 @@ class ErrorDescriptor(JSONEditingDescriptor): ''' try: xml = etree.fromstring(self.definition['data']['contents']) - return etree.tostring(xml) + return etree.tostring(xml, encoding='unicode') except etree.XMLSyntaxError: # still not valid. root = etree.Element('error') root.text = self.definition['data']['contents'] err_node = etree.SubElement(root, 'error_msg') err_node.text = self.definition['data']['error_msg'] - return etree.tostring(root) + return etree.tostring(root, encoding='unicode') class NonStaffErrorDescriptor(ErrorDescriptor): diff --git a/common/lib/xmodule/xmodule/html_module.py b/common/lib/xmodule/xmodule/html_module.py index 2023ac7017..c11c7d22e7 100644 --- a/common/lib/xmodule/xmodule/html_module.py +++ b/common/lib/xmodule/xmodule/html_module.py @@ -7,15 +7,14 @@ from lxml import etree from lxml.html import rewrite_links from path import path -from .x_module import XModule from pkg_resources import resource_string -from .xml_module import XmlDescriptor, name_to_pathname -from .editing_module import EditingDescriptor -from .stringify import stringify_children -from .html_checker import check_html -from xmodule.modulestore import Location - from xmodule.contentstore.content import XASSET_SRCREF_PREFIX, StaticContent +from xmodule.editing_module import EditingDescriptor +from xmodule.html_checker import check_html +from xmodule.modulestore import Location +from xmodule.stringify import stringify_children +from xmodule.x_module import XModule +from xmodule.xml_module import XmlDescriptor, name_to_pathname log = logging.getLogger("mitx.courseware") @@ -123,7 +122,7 @@ class HtmlDescriptor(XmlDescriptor, EditingDescriptor): try: with system.resources_fs.open(filepath) as file: - html = file.read() + html = file.read().decode('utf-8') # Log a warning if we can't parse the file, but don't error if not check_html(html): msg = "Couldn't parse html in {0}.".format(filepath) @@ -164,7 +163,7 @@ class HtmlDescriptor(XmlDescriptor, EditingDescriptor): resource_fs.makedir(os.path.dirname(filepath), allow_recreate=True) with resource_fs.open(filepath, 'w') as file: - file.write(self.definition['data']) + file.write(self.definition['data'].encode('utf-8')) # write out the relative name relname = path(pathname).basename() diff --git a/common/lib/xmodule/xmodule/modulestore/xml.py b/common/lib/xmodule/xmodule/modulestore/xml.py index 6f8430917d..6b3ff9bff4 100644 --- a/common/lib/xmodule/xmodule/modulestore/xml.py +++ b/common/lib/xmodule/xmodule/modulestore/xml.py @@ -152,7 +152,7 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem): make_name_unique(xml_data) descriptor = XModuleDescriptor.load_from_xml( - etree.tostring(xml_data), self, self.org, + etree.tostring(xml_data, encoding='unicode'), self, self.org, self.course, xmlstore.default_class) except Exception as err: print err, self.load_error_modules @@ -436,7 +436,7 @@ class XMLModuleStore(ModuleStoreBase): self.load_error_modules, ) - course_descriptor = system.process_xml(etree.tostring(course_data)) + course_descriptor = system.process_xml(etree.tostring(course_data, encoding='unicode')) # NOTE: The descriptors end up loading somewhat bottom up, which # breaks metadata inheritance via get_children(). Instead diff --git a/common/lib/xmodule/xmodule/raw_module.py b/common/lib/xmodule/xmodule/raw_module.py index 5ff16098ac..efdd2e7ba0 100644 --- a/common/lib/xmodule/xmodule/raw_module.py +++ b/common/lib/xmodule/xmodule/raw_module.py @@ -13,7 +13,7 @@ class RawDescriptor(XmlDescriptor, XMLEditingDescriptor): """ @classmethod def definition_from_xml(cls, xml_object, system): - return {'data': etree.tostring(xml_object, pretty_print=True)} + return {'data': etree.tostring(xml_object, pretty_print=True,encoding='unicode')} def definition_to_xml(self, resource_fs): try: diff --git a/common/lib/xmodule/xmodule/seq_module.py b/common/lib/xmodule/xmodule/seq_module.py index b625646e66..9aec275e90 100644 --- a/common/lib/xmodule/xmodule/seq_module.py +++ b/common/lib/xmodule/xmodule/seq_module.py @@ -124,7 +124,7 @@ class SequenceDescriptor(MakoModuleDescriptor, XmlDescriptor): children = [] for child in xml_object: try: - children.append(system.process_xml(etree.tostring(child)).location.url()) + children.append(system.process_xml(etree.tostring(child, encoding='unicode')).location.url()) except: log.exception("Unable to load child when parsing Sequence. Continuing...") continue diff --git a/common/lib/xmodule/xmodule/stringify.py b/common/lib/xmodule/xmodule/stringify.py index 1e3fa91210..dab8ff0425 100644 --- a/common/lib/xmodule/xmodule/stringify.py +++ b/common/lib/xmodule/xmodule/stringify.py @@ -22,7 +22,7 @@ def stringify_children(node): # next element. parts = [node.text] for c in node.getchildren(): - parts.append(etree.tostring(c, with_tail=True)) + parts.append(etree.tostring(c, with_tail=True, encoding='unicode')) # filter removes possible Nones in texts and tails - return ''.join(filter(None, parts)) + return u''.join(filter(None, parts)) diff --git a/common/lib/xmodule/xmodule/template_module.py b/common/lib/xmodule/xmodule/template_module.py index 13eab038ec..d3fb0aab5e 100644 --- a/common/lib/xmodule/xmodule/template_module.py +++ b/common/lib/xmodule/xmodule/template_module.py @@ -58,7 +58,7 @@ class CustomTagDescriptor(RawDescriptor): params = dict(xmltree.items()) with system.resources_fs.open('custom_tags/{name}' .format(name=template_name)) as template: - return Template(template.read()).render(**params) + return Template(template.read().decode('utf-8')).render(**params) def __init__(self, system, definition, **kwargs): diff --git a/common/lib/xmodule/xmodule/xml_module.py b/common/lib/xmodule/xmodule/xml_module.py index ec755af4ef..bb5b44c67f 100644 --- a/common/lib/xmodule/xmodule/xml_module.py +++ b/common/lib/xmodule/xmodule/xml_module.py @@ -1,19 +1,20 @@ -from xmodule.x_module import (XModuleDescriptor, policy_key) -from xmodule.modulestore import Location -from lxml import etree import json import copy import logging -import traceback -from collections import namedtuple -from fs.errors import ResourceNotFoundError import os import sys +from collections import namedtuple +from lxml import etree + +from xmodule.x_module import (XModuleDescriptor, policy_key) +from xmodule.modulestore import Location log = logging.getLogger(__name__) +# assume all XML files are persisted as utf-8. edx_xml_parser = etree.XMLParser(dtd_validation=False, load_dtd=False, - remove_comments=True, remove_blank_text=True) + remove_comments=True, remove_blank_text=True, + encoding='utf-8') def name_to_pathname(name): """ @@ -366,7 +367,7 @@ class XmlDescriptor(XModuleDescriptor): filepath = self.__class__._format_filepath(self.category, url_path) resource_fs.makedir(os.path.dirname(filepath), allow_recreate=True) with resource_fs.open(filepath, 'w') as file: - file.write(etree.tostring(xml_object, pretty_print=True)) + file.write(etree.tostring(xml_object, pretty_print=True, encoding='utf-8')) # And return just a pointer with the category and filename. record_object = etree.Element(self.category) @@ -381,7 +382,7 @@ class XmlDescriptor(XModuleDescriptor): record_object.set('org', self.location.org) record_object.set('course', self.location.course) - return etree.tostring(record_object, pretty_print=True) + return etree.tostring(record_object, pretty_print=True, encoding='utf-8') def definition_to_xml(self, resource_fs): """ diff --git a/common/test/data/full/about/faq.html b/common/test/data/full/about/faq.html index a5e54c9f15..a173e46753 100644 --- a/common/test/data/full/about/faq.html +++ b/common/test/data/full/about/faq.html @@ -6,7 +6,7 @@
No - anyone and everyone is welcome to take this course.
Although the lectures are designed to be self-contained, we recommend (but do not require) that students refer to the book Worlds Together, Worlds Apart: A History of the World: From 1000 CE to the Present (W W Norton, 3rd edition) -- Volume II, which was written specifically for this course.
+Although the lectures are designed to be self-contained, we recommend (but do not require) that students refer to the book Worlds Together, Worlds Apart: A History of the World: From 1000 CE to the Present (W W Norton, 3rd edition) — Volume II, which was written specifically for this course.
Princeton does not award credentials or issue reports for student work in this course. However, Coursera could maintain a record of your score on the assessments and, with your permission, verify that score for authorized parties.
diff --git a/common/test/data/full/chapter/Overview.xml b/common/test/data/full/chapter/Overview.xml index a11a11a1e0..8ad44b366c 100644 --- a/common/test/data/full/chapter/Overview.xml +++ b/common/test/data/full/chapter/Overview.xml @@ -2,7 +2,7 @@Since the course has students from a diverse set of backgrounds, the first week's tutorials includes several extra segments, worked out with greater detail, to help bring everyone up to speed.
+Since the course has students from a diverse set of backgrounds, the first week's tutorials includes several extra segments, worked out with greater detail, to help bring everyone up to speed. Gratuitous ≥ entity.