Merge pull request #7096 from edx/jeskew/PLAT_454_import_500_error
PLAT-454: Fix import error when exported course edited.
This commit is contained in:
@@ -52,6 +52,7 @@ from course_action_state.models import CourseRerunState, CourseRerunUIStateManag
|
||||
|
||||
from course_action_state.managers import CourseActionStateItemNotFoundError
|
||||
from xmodule.contentstore.content import StaticContent
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
|
||||
TEST_DATA_CONTENTSTORE = copy.deepcopy(settings.CONTENTSTORE)
|
||||
@@ -387,6 +388,32 @@ class ImportRequiredTestCases(ContentStoreTestCase):
|
||||
|
||||
shutil.rmtree(root_dir)
|
||||
|
||||
def test_import_after_renaming_xml_data(self):
|
||||
"""
|
||||
Test that import works fine on split mongo after renaming the blocks url.
|
||||
"""
|
||||
split_store = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.split) # pylint: disable=W0212
|
||||
import_from_xml(
|
||||
split_store, self.user.id, TEST_DATA_DIR,
|
||||
['course_before_rename'],
|
||||
create_course_if_not_present=True
|
||||
)
|
||||
course_after_rename = import_from_xml(
|
||||
split_store, self.user.id, TEST_DATA_DIR,
|
||||
['course_after_rename'],
|
||||
create_course_if_not_present=True
|
||||
)
|
||||
all_items = split_store.get_items(course_after_rename[0].id, qualifiers={'category': 'chapter'})
|
||||
renamed_chapter = [item for item in all_items if item.location.block_id == 'renamed_chapter'][0]
|
||||
self.assertIsNotNone(renamed_chapter.published_on)
|
||||
self.assertIsNotNone(renamed_chapter.parent)
|
||||
self.assertTrue(renamed_chapter.location in course_after_rename[0].children)
|
||||
original_chapter = [item for item in all_items
|
||||
if item.location.block_id == 'b9870b9af59841a49e6e02765d0e3bbf'][0]
|
||||
self.assertIsNone(original_chapter.published_on)
|
||||
self.assertIsNone(original_chapter.parent)
|
||||
self.assertFalse(original_chapter.location in course_after_rename[0].children)
|
||||
|
||||
def test_empty_data_roundtrip(self):
|
||||
"""
|
||||
Test that an empty `data` field is preserved through
|
||||
|
||||
@@ -2118,16 +2118,21 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
if BlockKey.from_usage_key(subtree_root) != source_structure['root']:
|
||||
# find the parents and put root in the right sequence
|
||||
parents = self._get_parents_from_structure(BlockKey.from_usage_key(subtree_root), source_structure)
|
||||
parent_found = False
|
||||
for parent in parents:
|
||||
if parent not in destination_blocks:
|
||||
raise ItemNotFoundError(parent)
|
||||
orphans.update(
|
||||
self._sync_children(
|
||||
source_structure['blocks'][parent],
|
||||
destination_blocks[parent],
|
||||
BlockKey.from_usage_key(subtree_root)
|
||||
# If a parent isn't found in the destination_blocks, it's possible it was renamed
|
||||
# in the course export. Continue and only throw an exception if *no* parents are found.
|
||||
if parent in destination_blocks:
|
||||
parent_found = True
|
||||
orphans.update(
|
||||
self._sync_children(
|
||||
source_structure['blocks'][parent],
|
||||
destination_blocks[parent],
|
||||
BlockKey.from_usage_key(subtree_root)
|
||||
)
|
||||
)
|
||||
)
|
||||
if len(parents) and not parent_found:
|
||||
raise ItemNotFoundError(parents)
|
||||
# update/create the subtree and its children in destination (skipping blacklist)
|
||||
orphans.update(
|
||||
self._copy_subdag(
|
||||
|
||||
47
common/test/data/course_after_rename/about/overview.html
Normal file
47
common/test/data/course_after_rename/about/overview.html
Normal file
@@ -0,0 +1,47 @@
|
||||
<section class="about">
|
||||
<h2>About This Course</h2>
|
||||
<p>Include your long course description here. The long course description should contain 150-400 words.</p>
|
||||
|
||||
<p>This is paragraph 2 of the long course description. Add more paragraphs as needed. Make sure to enclose them in paragraph tags.</p>
|
||||
</section>
|
||||
|
||||
<section class="prerequisites">
|
||||
<h2>Requirements</h2>
|
||||
<p>Add information about the skills and knowledge students need to take this course.</p>
|
||||
</section>
|
||||
|
||||
<section class="course-staff">
|
||||
<h2>Course Staff</h2>
|
||||
<article class="teacher">
|
||||
<div class="teacher-image">
|
||||
<img src="/static/images/placeholder-faculty.png" align="left" style="margin:0 20 px 0" alt="Course Staff Image #1">
|
||||
</div>
|
||||
|
||||
<h3>Staff Member #1</h3>
|
||||
<p>Biography of instructor/staff member #1</p>
|
||||
</article>
|
||||
|
||||
<article class="teacher">
|
||||
<div class="teacher-image">
|
||||
<img src="/static/images/placeholder-faculty.png" align="left" style="margin:0 20 px 0" alt="Course Staff Image #2">
|
||||
</div>
|
||||
|
||||
<h3>Staff Member #2</h3>
|
||||
<p>Biography of instructor/staff member #2</p>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="faq">
|
||||
<section class="responses">
|
||||
<h2>Frequently Asked Questions</h2>
|
||||
<article class="response">
|
||||
<h3>Do I need to buy a textbook?</h3>
|
||||
<p>No, a free online version of Chemistry: Principles, Patterns, and Applications, First Edition by Bruce Averill and Patricia Eldredge will be available, though you can purchase a printed version (published by FlatWorld Knowledge) if you’d like.</p>
|
||||
</article>
|
||||
|
||||
<article class="response">
|
||||
<h3>Question #2</h3>
|
||||
<p>Your answer would be displayed here.</p>
|
||||
</article>
|
||||
</section>
|
||||
</section>
|
||||
1
common/test/data/course_after_rename/assets/assets.xml
Normal file
1
common/test/data/course_after_rename/assets/assets.xml
Normal file
@@ -0,0 +1 @@
|
||||
<assets/>
|
||||
@@ -0,0 +1,3 @@
|
||||
<chapter display_name="Discussion">
|
||||
<sequential url_name="761dd4188c3e49f390a8d2a47156f503"/>
|
||||
</chapter>
|
||||
1
common/test/data/course_after_rename/course.xml
Normal file
1
common/test/data/course_after_rename/course.xml
Normal file
@@ -0,0 +1 @@
|
||||
<course url_name="course" org="malikx" course="cs101"/>
|
||||
4
common/test/data/course_after_rename/course/course.xml
Normal file
4
common/test/data/course_after_rename/course/course.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<course display_name="Import testing" start=""2030-01-01T00:00:00+00:00"">
|
||||
<chapter url_name="renamed_chapter"/>
|
||||
<wiki slug="malikx.cs101.2014"/>
|
||||
</course>
|
||||
@@ -0,0 +1 @@
|
||||
<vertical display_name="Unit" parent_url="block-v1:malikx+cs101+2015+type@sequential+block@761dd4188c3e49f390a8d2a47156f503" index_in_children_list="0"/>
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"GRADER": [
|
||||
{
|
||||
"drop_count": 2,
|
||||
"min_count": 12,
|
||||
"short_label": "HW",
|
||||
"type": "Homework",
|
||||
"weight": 0.15
|
||||
},
|
||||
{
|
||||
"drop_count": 2,
|
||||
"min_count": 12,
|
||||
"type": "Lab",
|
||||
"weight": 0.15
|
||||
},
|
||||
{
|
||||
"drop_count": 0,
|
||||
"min_count": 1,
|
||||
"short_label": "Midterm",
|
||||
"type": "Midterm Exam",
|
||||
"weight": 0.3
|
||||
},
|
||||
{
|
||||
"drop_count": 0,
|
||||
"min_count": 1,
|
||||
"short_label": "Final",
|
||||
"type": "Final Exam",
|
||||
"weight": 0.4
|
||||
}
|
||||
],
|
||||
"GRADE_CUTOFFS": {
|
||||
"Pass": 0.5
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"course/course": {
|
||||
"discussion_topics": {
|
||||
"General": {
|
||||
"id": "i4x-malikx-cs101-course-2014"
|
||||
}
|
||||
},
|
||||
"display_name": "Import testing",
|
||||
"start": "2030-01-01T00:00:00Z",
|
||||
"tabs": [
|
||||
{
|
||||
"name": "Courseware",
|
||||
"type": "courseware"
|
||||
},
|
||||
{
|
||||
"name": "Course Info",
|
||||
"type": "course_info"
|
||||
},
|
||||
{
|
||||
"name": "Textbooks",
|
||||
"type": "textbooks"
|
||||
},
|
||||
{
|
||||
"name": "Discussion",
|
||||
"type": "discussion"
|
||||
},
|
||||
{
|
||||
"name": "Wiki",
|
||||
"type": "wiki"
|
||||
},
|
||||
{
|
||||
"name": "Progress",
|
||||
"type": "progress"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1,3 @@
|
||||
<sequential display_name="Subsection">
|
||||
<vertical url_name="f8ee1d2026e048b884d2ff6c4daa9def"/>
|
||||
</sequential>
|
||||
@@ -0,0 +1 @@
|
||||
<vertical display_name="Unit"/>
|
||||
47
common/test/data/course_before_rename/about/overview.html
Normal file
47
common/test/data/course_before_rename/about/overview.html
Normal file
@@ -0,0 +1,47 @@
|
||||
<section class="about">
|
||||
<h2>About This Course</h2>
|
||||
<p>Include your long course description here. The long course description should contain 150-400 words.</p>
|
||||
|
||||
<p>This is paragraph 2 of the long course description. Add more paragraphs as needed. Make sure to enclose them in paragraph tags.</p>
|
||||
</section>
|
||||
|
||||
<section class="prerequisites">
|
||||
<h2>Requirements</h2>
|
||||
<p>Add information about the skills and knowledge students need to take this course.</p>
|
||||
</section>
|
||||
|
||||
<section class="course-staff">
|
||||
<h2>Course Staff</h2>
|
||||
<article class="teacher">
|
||||
<div class="teacher-image">
|
||||
<img src="/static/images/placeholder-faculty.png" align="left" style="margin:0 20 px 0" alt="Course Staff Image #1">
|
||||
</div>
|
||||
|
||||
<h3>Staff Member #1</h3>
|
||||
<p>Biography of instructor/staff member #1</p>
|
||||
</article>
|
||||
|
||||
<article class="teacher">
|
||||
<div class="teacher-image">
|
||||
<img src="/static/images/placeholder-faculty.png" align="left" style="margin:0 20 px 0" alt="Course Staff Image #2">
|
||||
</div>
|
||||
|
||||
<h3>Staff Member #2</h3>
|
||||
<p>Biography of instructor/staff member #2</p>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="faq">
|
||||
<section class="responses">
|
||||
<h2>Frequently Asked Questions</h2>
|
||||
<article class="response">
|
||||
<h3>Do I need to buy a textbook?</h3>
|
||||
<p>No, a free online version of Chemistry: Principles, Patterns, and Applications, First Edition by Bruce Averill and Patricia Eldredge will be available, though you can purchase a printed version (published by FlatWorld Knowledge) if you’d like.</p>
|
||||
</article>
|
||||
|
||||
<article class="response">
|
||||
<h3>Question #2</h3>
|
||||
<p>Your answer would be displayed here.</p>
|
||||
</article>
|
||||
</section>
|
||||
</section>
|
||||
1
common/test/data/course_before_rename/assets/assets.xml
Normal file
1
common/test/data/course_before_rename/assets/assets.xml
Normal file
@@ -0,0 +1 @@
|
||||
<assets/>
|
||||
@@ -0,0 +1,3 @@
|
||||
<chapter display_name="Discussion">
|
||||
<sequential url_name="761dd4188c3e49f390a8d2a47156f503"/>
|
||||
</chapter>
|
||||
1
common/test/data/course_before_rename/course.xml
Normal file
1
common/test/data/course_before_rename/course.xml
Normal file
@@ -0,0 +1 @@
|
||||
<course url_name="course" org="malikx" course="cs101"/>
|
||||
4
common/test/data/course_before_rename/course/course.xml
Normal file
4
common/test/data/course_before_rename/course/course.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<course display_name="Import testing" start=""2030-01-01T00:00:00+00:00"">
|
||||
<chapter url_name="b9870b9af59841a49e6e02765d0e3bbf"/>
|
||||
<wiki slug="malikx.cs101.2014"/>
|
||||
</course>
|
||||
@@ -0,0 +1 @@
|
||||
<vertical display_name="Unit" parent_url="block-v1:malikx+cs101+2015+type@sequential+block@761dd4188c3e49f390a8d2a47156f503" index_in_children_list="0"/>
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"GRADER": [
|
||||
{
|
||||
"drop_count": 2,
|
||||
"min_count": 12,
|
||||
"short_label": "HW",
|
||||
"type": "Homework",
|
||||
"weight": 0.15
|
||||
},
|
||||
{
|
||||
"drop_count": 2,
|
||||
"min_count": 12,
|
||||
"type": "Lab",
|
||||
"weight": 0.15
|
||||
},
|
||||
{
|
||||
"drop_count": 0,
|
||||
"min_count": 1,
|
||||
"short_label": "Midterm",
|
||||
"type": "Midterm Exam",
|
||||
"weight": 0.3
|
||||
},
|
||||
{
|
||||
"drop_count": 0,
|
||||
"min_count": 1,
|
||||
"short_label": "Final",
|
||||
"type": "Final Exam",
|
||||
"weight": 0.4
|
||||
}
|
||||
],
|
||||
"GRADE_CUTOFFS": {
|
||||
"Pass": 0.5
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"course/course": {
|
||||
"discussion_topics": {
|
||||
"General": {
|
||||
"id": "i4x-malikx-cs101-course-2014"
|
||||
}
|
||||
},
|
||||
"display_name": "Import testing",
|
||||
"start": "2030-01-01T00:00:00Z",
|
||||
"tabs": [
|
||||
{
|
||||
"name": "Courseware",
|
||||
"type": "courseware"
|
||||
},
|
||||
{
|
||||
"name": "Course Info",
|
||||
"type": "course_info"
|
||||
},
|
||||
{
|
||||
"name": "Textbooks",
|
||||
"type": "textbooks"
|
||||
},
|
||||
{
|
||||
"name": "Discussion",
|
||||
"type": "discussion"
|
||||
},
|
||||
{
|
||||
"name": "Wiki",
|
||||
"type": "wiki"
|
||||
},
|
||||
{
|
||||
"name": "Progress",
|
||||
"type": "progress"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1,3 @@
|
||||
<sequential display_name="Subsection">
|
||||
<vertical url_name="f8ee1d2026e048b884d2ff6c4daa9def"/>
|
||||
</sequential>
|
||||
@@ -0,0 +1 @@
|
||||
<vertical display_name="Unit"/>
|
||||
Reference in New Issue
Block a user