Merge pull request #23996 from edx/ahtisham/PROD-1540
Fixed Import error due to pre tag
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
Unit tests for course import and export
|
||||
"""
|
||||
|
||||
|
||||
import copy
|
||||
import json
|
||||
import logging
|
||||
@@ -55,6 +54,7 @@ class ImportEntranceExamTestCase(CourseTestCase, MilestonesTestCaseMixin):
|
||||
"""
|
||||
Unit tests for importing a course with entrance exam
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(ImportEntranceExamTestCase, self).setUp()
|
||||
self.url = reverse_course_url('import_handler', self.course.id)
|
||||
@@ -533,6 +533,7 @@ class ExportTestCase(CourseTestCase):
|
||||
"""
|
||||
Tests for export_handler.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Sets up the test course.
|
||||
@@ -788,9 +789,9 @@ class ExportTestCase(CourseTestCase):
|
||||
@patch('contentstore.views.import_export._latest_task_status')
|
||||
@patch('user_tasks.models.UserTaskArtifact.objects.get')
|
||||
def test_export_status_handler_other(
|
||||
self,
|
||||
mock_get_user_task_artifact,
|
||||
mock_latest_task_status,
|
||||
self,
|
||||
mock_get_user_task_artifact,
|
||||
mock_latest_task_status,
|
||||
):
|
||||
"""
|
||||
Verify that the export status handler generates the correct export path
|
||||
@@ -808,9 +809,9 @@ class ExportTestCase(CourseTestCase):
|
||||
@patch('contentstore.views.import_export._latest_task_status')
|
||||
@patch('user_tasks.models.UserTaskArtifact.objects.get')
|
||||
def test_export_status_handler_s3(
|
||||
self,
|
||||
mock_get_user_task_artifact,
|
||||
mock_latest_task_status,
|
||||
self,
|
||||
mock_get_user_task_artifact,
|
||||
mock_latest_task_status,
|
||||
):
|
||||
"""
|
||||
Verify that the export status handler generates the correct export path
|
||||
@@ -828,9 +829,9 @@ class ExportTestCase(CourseTestCase):
|
||||
@patch('contentstore.views.import_export._latest_task_status')
|
||||
@patch('user_tasks.models.UserTaskArtifact.objects.get')
|
||||
def test_export_status_handler_filesystem(
|
||||
self,
|
||||
mock_get_user_task_artifact,
|
||||
mock_latest_task_status,
|
||||
self,
|
||||
mock_get_user_task_artifact,
|
||||
mock_latest_task_status,
|
||||
):
|
||||
"""
|
||||
Verify that the export status handler generates the correct export path
|
||||
@@ -849,6 +850,7 @@ class TestLibraryImportExport(CourseTestCase):
|
||||
"""
|
||||
Tests for importing content libraries from XML and exporting them to XML.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestLibraryImportExport, self).setUp()
|
||||
self.export_dir = tempfile.mkdtemp()
|
||||
@@ -906,6 +908,7 @@ class TestCourseExportImport(LibraryTestCase):
|
||||
"""
|
||||
Tests for importing after exporting the course containing content libraries from XML.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestCourseExportImport, self).setUp()
|
||||
self.export_dir = tempfile.mkdtemp()
|
||||
@@ -1022,18 +1025,20 @@ class TestCourseExportImport(LibraryTestCase):
|
||||
)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@override_settings(CONTENTSTORE=TEST_DATA_CONTENTSTORE)
|
||||
class TestCourseExportImportProblem(CourseTestCase):
|
||||
"""
|
||||
Tests for importing after exporting the course containing problem with pre tags from XML.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestCourseExportImportProblem, self).setUp()
|
||||
self.export_dir = tempfile.mkdtemp()
|
||||
self.source_course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split)
|
||||
self.addCleanup(shutil.rmtree, self.export_dir, ignore_errors=True)
|
||||
|
||||
def _setup_source_course_with_problem_content(self, publish_item=False):
|
||||
def _setup_source_course_with_problem_content(self, data, publish_item=False):
|
||||
"""
|
||||
Sets up course with problem content.
|
||||
"""
|
||||
@@ -1058,8 +1063,7 @@ class TestCourseExportImportProblem(CourseTestCase):
|
||||
category='problem',
|
||||
display_name='Test Problem',
|
||||
publish_item=publish_item,
|
||||
data='<problem><pre><code>x=10 print("hello \n")</code></pre>'
|
||||
'<multiplechoiceresponse></multiplechoiceresponse></problem>',
|
||||
data=data,
|
||||
)
|
||||
|
||||
def get_problem_content(self, block_location):
|
||||
@@ -1071,21 +1075,38 @@ class TestCourseExportImportProblem(CourseTestCase):
|
||||
|
||||
return self.get_problem_content(self.store.get_item(block_location).children[0])
|
||||
|
||||
def assert_problem_definition(self, course_location):
|
||||
def assert_problem_definition(self, course_location, expected_problem_content):
|
||||
"""
|
||||
Asserts that problems' data is as expected with pre-tag content maintained.
|
||||
"""
|
||||
expected_problem_content = '<problem>\n <pre>\n <code>x=10 print("hello \n")</code>\n </pre>\n ' \
|
||||
'<multiplechoiceresponse/>\n</problem>\n'
|
||||
problem_content = self.get_problem_content(course_location)
|
||||
self.assertEqual(expected_problem_content, problem_content)
|
||||
|
||||
def test_problem_content_on_course_export_import(self):
|
||||
@ddt.data(
|
||||
[
|
||||
'<problem><pre><code>x=10 print("hello \n")</code></pre>'
|
||||
'<pre><div><pre><code>x=10 print("hello \n")</code></pre></div></pre>'
|
||||
'<multiplechoiceresponse></multiplechoiceresponse></problem>',
|
||||
|
||||
'<problem>\n <pre>\n <code>x=10 print("hello \n")</code>\n </pre>\n <pre>\n <div>\n <pre>\n '
|
||||
' <code>x=10 print("hello \n")</code>\n </pre>\n </div>\n </pre>\n '
|
||||
'<multiplechoiceresponse/>\n</problem>\n'
|
||||
],
|
||||
[
|
||||
'<problem><pre><code>x=10 print("hello \n")</code></pre>'
|
||||
'<multiplechoiceresponse></multiplechoiceresponse></problem>',
|
||||
|
||||
'<problem>\n <pre>\n <code>x=10 print("hello \n")</code>\n </pre>\n '
|
||||
'<multiplechoiceresponse/>\n</problem>\n'
|
||||
]
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_problem_content_on_course_export_import(self, problem_data, expected_problem_content):
|
||||
"""
|
||||
Verify that problem content in destination matches expected problem content,
|
||||
specifically concerned with pre tag data with problem.
|
||||
"""
|
||||
self._setup_source_course_with_problem_content()
|
||||
self._setup_source_course_with_problem_content(problem_data)
|
||||
|
||||
dest_course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split)
|
||||
|
||||
@@ -1109,4 +1130,4 @@ class TestCourseExportImportProblem(CourseTestCase):
|
||||
create_if_not_present=True,
|
||||
)
|
||||
|
||||
self.assert_problem_definition(dest_course.location)
|
||||
self.assert_problem_definition(dest_course.location, expected_problem_content)
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
import logging
|
||||
import re
|
||||
|
||||
@@ -12,7 +10,7 @@ from .exceptions import SerializationError
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
PRE_TAG_REGEX = re.compile(r'<pre>[\s\S]*?</pre>')
|
||||
PRE_TAG_REGEX = re.compile(r'<pre\b[^>]*>(?:(?=([^<]+))\1|<(?!pre\b[^>]*>))*?</pre>')
|
||||
|
||||
|
||||
class RawMixin(object):
|
||||
@@ -25,12 +23,21 @@ class RawMixin(object):
|
||||
|
||||
@classmethod
|
||||
def definition_from_xml(cls, xml_object, system):
|
||||
pre_tag_data = [etree.tostring(pre_tag_info) for pre_tag_info in xml_object.findall('.//pre')]
|
||||
data = etree.tostring(xml_object, pretty_print=True, encoding='unicode')
|
||||
if pre_tag_data:
|
||||
for index, pre_tag in enumerate(re.findall(PRE_TAG_REGEX, data)):
|
||||
data = re.sub(pre_tag, pre_tag_data[index].decode(), data)
|
||||
return {'data': data}, []
|
||||
try:
|
||||
data = etree.tostring(xml_object, pretty_print=True, encoding='unicode')
|
||||
pre_tag_data = []
|
||||
for pre_tag_info in xml_object.findall('.//pre'):
|
||||
if len(pre_tag_info.findall('.//pre')) == 0:
|
||||
pre_tag_data.append(etree.tostring(pre_tag_info))
|
||||
|
||||
if pre_tag_data:
|
||||
matches = re.finditer(PRE_TAG_REGEX, data)
|
||||
for match_num, match in enumerate(matches):
|
||||
data = re.sub(match.group(), pre_tag_data[match_num].decode(), data)
|
||||
etree.XML(data) # it just checks if generated string is valid xml
|
||||
return {'data': data}, []
|
||||
except etree.XMLSyntaxError:
|
||||
return {'data': etree.tostring(xml_object, pretty_print=True, encoding='unicode')}, []
|
||||
|
||||
def definition_to_xml(self, resource_fs):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user