Fixed Import error due to pre tag

Fixed regex for nested pre tags

Updated import export test

fixed quality test issue

fixed No exception type(s) specified

updated tests

fixed linter issue

fixed linter issue

fixed linter issue
This commit is contained in:
Ahtisham Shahid
2020-05-14 13:16:28 +05:00
parent fe2abafcc1
commit 4f5496f02c
2 changed files with 57 additions and 28 deletions

View File

@@ -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,39 @@ 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()
# import pdb;pdb.set_trace()
self._setup_source_course_with_problem_content(problem_data)
dest_course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split)
@@ -1109,4 +1131,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)

View File

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