From 80b5f38239862adfee9b9014c37a03ca5811b1e4 Mon Sep 17 00:00:00 2001 From: John Eskew Date: Tue, 24 Feb 2015 16:36:17 -0500 Subject: [PATCH 1/2] Upon import, only raise when none of multiple parents are found for a block. --- .../xmodule/modulestore/split_mongo/split.py | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py b/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py index e7cb99df06..5fe3fdeb18 100644 --- a/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py +++ b/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py @@ -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( From 4b9dc74cadbfa0cfd24ec7f5c7454c85ab4c467b Mon Sep 17 00:00:00 2001 From: Waqas Khalid Date: Wed, 25 Feb 2015 20:21:35 +0500 Subject: [PATCH 2/2] Add tests for rename import error --- .../contentstore/tests/test_contentstore.py | 27 +++++++++++ .../course_after_rename/about/overview.html | 47 +++++++++++++++++++ .../course_after_rename/assets/assets.xml | 1 + .../chapter/renamed_chapter.xml | 3 ++ .../test/data/course_after_rename/course.xml | 1 + .../course_after_rename/course/course.xml | 4 ++ .../f8ee1d2026e048b884d2ff6c4daa9def.xml | 1 + .../policies/2015/grading_policy.json | 34 ++++++++++++++ .../policies/2015/policy.json | 37 +++++++++++++++ .../course_after_rename/policies/assets.json | 1 + .../761dd4188c3e49f390a8d2a47156f503.xml | 3 ++ .../f8ee1d2026e048b884d2ff6c4daa9def.xml | 1 + .../course_before_rename/about/overview.html | 47 +++++++++++++++++++ .../course_before_rename/assets/assets.xml | 1 + .../b9870b9af59841a49e6e02765d0e3bbf.xml | 3 ++ .../test/data/course_before_rename/course.xml | 1 + .../course_before_rename/course/course.xml | 4 ++ .../f8ee1d2026e048b884d2ff6c4daa9def.xml | 1 + .../policies/2015/grading_policy.json | 34 ++++++++++++++ .../policies/2015/policy.json | 37 +++++++++++++++ .../course_before_rename/policies/assets.json | 1 + .../761dd4188c3e49f390a8d2a47156f503.xml | 3 ++ .../f8ee1d2026e048b884d2ff6c4daa9def.xml | 1 + 23 files changed, 293 insertions(+) create mode 100644 common/test/data/course_after_rename/about/overview.html create mode 100644 common/test/data/course_after_rename/assets/assets.xml create mode 100644 common/test/data/course_after_rename/chapter/renamed_chapter.xml create mode 100644 common/test/data/course_after_rename/course.xml create mode 100644 common/test/data/course_after_rename/course/course.xml create mode 100644 common/test/data/course_after_rename/drafts/vertical/f8ee1d2026e048b884d2ff6c4daa9def.xml create mode 100644 common/test/data/course_after_rename/policies/2015/grading_policy.json create mode 100644 common/test/data/course_after_rename/policies/2015/policy.json create mode 100644 common/test/data/course_after_rename/policies/assets.json create mode 100644 common/test/data/course_after_rename/sequential/761dd4188c3e49f390a8d2a47156f503.xml create mode 100644 common/test/data/course_after_rename/vertical/f8ee1d2026e048b884d2ff6c4daa9def.xml create mode 100644 common/test/data/course_before_rename/about/overview.html create mode 100644 common/test/data/course_before_rename/assets/assets.xml create mode 100644 common/test/data/course_before_rename/chapter/b9870b9af59841a49e6e02765d0e3bbf.xml create mode 100644 common/test/data/course_before_rename/course.xml create mode 100644 common/test/data/course_before_rename/course/course.xml create mode 100644 common/test/data/course_before_rename/drafts/vertical/f8ee1d2026e048b884d2ff6c4daa9def.xml create mode 100644 common/test/data/course_before_rename/policies/2015/grading_policy.json create mode 100644 common/test/data/course_before_rename/policies/2015/policy.json create mode 100644 common/test/data/course_before_rename/policies/assets.json create mode 100644 common/test/data/course_before_rename/sequential/761dd4188c3e49f390a8d2a47156f503.xml create mode 100644 common/test/data/course_before_rename/vertical/f8ee1d2026e048b884d2ff6c4daa9def.xml diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py index a6ca0aa2f4..d0def23ee9 100644 --- a/cms/djangoapps/contentstore/tests/test_contentstore.py +++ b/cms/djangoapps/contentstore/tests/test_contentstore.py @@ -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 diff --git a/common/test/data/course_after_rename/about/overview.html b/common/test/data/course_after_rename/about/overview.html new file mode 100644 index 0000000000..5bdbd4428f --- /dev/null +++ b/common/test/data/course_after_rename/about/overview.html @@ -0,0 +1,47 @@ +
+

About This Course

+

Include your long course description here. The long course description should contain 150-400 words.

+ +

This is paragraph 2 of the long course description. Add more paragraphs as needed. Make sure to enclose them in paragraph tags.

+
+ +
+

Requirements

+

Add information about the skills and knowledge students need to take this course.

+
+ +
+

Course Staff

+
+
+ Course Staff Image #1 +
+ +

Staff Member #1

+

Biography of instructor/staff member #1

+
+ +
+
+ Course Staff Image #2 +
+ +

Staff Member #2

+

Biography of instructor/staff member #2

+
+
+ +
+
+

Frequently Asked Questions

+
+

Do I need to buy a textbook?

+

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.

+
+ +
+

Question #2

+

Your answer would be displayed here.

+
+
+
diff --git a/common/test/data/course_after_rename/assets/assets.xml b/common/test/data/course_after_rename/assets/assets.xml new file mode 100644 index 0000000000..816a689e24 --- /dev/null +++ b/common/test/data/course_after_rename/assets/assets.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/common/test/data/course_after_rename/chapter/renamed_chapter.xml b/common/test/data/course_after_rename/chapter/renamed_chapter.xml new file mode 100644 index 0000000000..bf7e48afcd --- /dev/null +++ b/common/test/data/course_after_rename/chapter/renamed_chapter.xml @@ -0,0 +1,3 @@ + + + diff --git a/common/test/data/course_after_rename/course.xml b/common/test/data/course_after_rename/course.xml new file mode 100644 index 0000000000..1c3c9bbbf8 --- /dev/null +++ b/common/test/data/course_after_rename/course.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/common/test/data/course_after_rename/course/course.xml b/common/test/data/course_after_rename/course/course.xml new file mode 100644 index 0000000000..7ef51edfe0 --- /dev/null +++ b/common/test/data/course_after_rename/course/course.xml @@ -0,0 +1,4 @@ + + + + diff --git a/common/test/data/course_after_rename/drafts/vertical/f8ee1d2026e048b884d2ff6c4daa9def.xml b/common/test/data/course_after_rename/drafts/vertical/f8ee1d2026e048b884d2ff6c4daa9def.xml new file mode 100644 index 0000000000..b877fa91e5 --- /dev/null +++ b/common/test/data/course_after_rename/drafts/vertical/f8ee1d2026e048b884d2ff6c4daa9def.xml @@ -0,0 +1 @@ + diff --git a/common/test/data/course_after_rename/policies/2015/grading_policy.json b/common/test/data/course_after_rename/policies/2015/grading_policy.json new file mode 100644 index 0000000000..3fe56c2dff --- /dev/null +++ b/common/test/data/course_after_rename/policies/2015/grading_policy.json @@ -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 + } +} \ No newline at end of file diff --git a/common/test/data/course_after_rename/policies/2015/policy.json b/common/test/data/course_after_rename/policies/2015/policy.json new file mode 100644 index 0000000000..a5db6180cf --- /dev/null +++ b/common/test/data/course_after_rename/policies/2015/policy.json @@ -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" + } + ] + } +} \ No newline at end of file diff --git a/common/test/data/course_after_rename/policies/assets.json b/common/test/data/course_after_rename/policies/assets.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/common/test/data/course_after_rename/policies/assets.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/common/test/data/course_after_rename/sequential/761dd4188c3e49f390a8d2a47156f503.xml b/common/test/data/course_after_rename/sequential/761dd4188c3e49f390a8d2a47156f503.xml new file mode 100644 index 0000000000..aef65ba24e --- /dev/null +++ b/common/test/data/course_after_rename/sequential/761dd4188c3e49f390a8d2a47156f503.xml @@ -0,0 +1,3 @@ + + + diff --git a/common/test/data/course_after_rename/vertical/f8ee1d2026e048b884d2ff6c4daa9def.xml b/common/test/data/course_after_rename/vertical/f8ee1d2026e048b884d2ff6c4daa9def.xml new file mode 100644 index 0000000000..38fbf79deb --- /dev/null +++ b/common/test/data/course_after_rename/vertical/f8ee1d2026e048b884d2ff6c4daa9def.xml @@ -0,0 +1 @@ + diff --git a/common/test/data/course_before_rename/about/overview.html b/common/test/data/course_before_rename/about/overview.html new file mode 100644 index 0000000000..5bdbd4428f --- /dev/null +++ b/common/test/data/course_before_rename/about/overview.html @@ -0,0 +1,47 @@ +
+

About This Course

+

Include your long course description here. The long course description should contain 150-400 words.

+ +

This is paragraph 2 of the long course description. Add more paragraphs as needed. Make sure to enclose them in paragraph tags.

+
+ +
+

Requirements

+

Add information about the skills and knowledge students need to take this course.

+
+ +
+

Course Staff

+
+
+ Course Staff Image #1 +
+ +

Staff Member #1

+

Biography of instructor/staff member #1

+
+ +
+
+ Course Staff Image #2 +
+ +

Staff Member #2

+

Biography of instructor/staff member #2

+
+
+ +
+
+

Frequently Asked Questions

+
+

Do I need to buy a textbook?

+

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.

+
+ +
+

Question #2

+

Your answer would be displayed here.

+
+
+
diff --git a/common/test/data/course_before_rename/assets/assets.xml b/common/test/data/course_before_rename/assets/assets.xml new file mode 100644 index 0000000000..816a689e24 --- /dev/null +++ b/common/test/data/course_before_rename/assets/assets.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/common/test/data/course_before_rename/chapter/b9870b9af59841a49e6e02765d0e3bbf.xml b/common/test/data/course_before_rename/chapter/b9870b9af59841a49e6e02765d0e3bbf.xml new file mode 100644 index 0000000000..bf7e48afcd --- /dev/null +++ b/common/test/data/course_before_rename/chapter/b9870b9af59841a49e6e02765d0e3bbf.xml @@ -0,0 +1,3 @@ + + + diff --git a/common/test/data/course_before_rename/course.xml b/common/test/data/course_before_rename/course.xml new file mode 100644 index 0000000000..1c3c9bbbf8 --- /dev/null +++ b/common/test/data/course_before_rename/course.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/common/test/data/course_before_rename/course/course.xml b/common/test/data/course_before_rename/course/course.xml new file mode 100644 index 0000000000..f5de49bf1c --- /dev/null +++ b/common/test/data/course_before_rename/course/course.xml @@ -0,0 +1,4 @@ + + + + diff --git a/common/test/data/course_before_rename/drafts/vertical/f8ee1d2026e048b884d2ff6c4daa9def.xml b/common/test/data/course_before_rename/drafts/vertical/f8ee1d2026e048b884d2ff6c4daa9def.xml new file mode 100644 index 0000000000..b877fa91e5 --- /dev/null +++ b/common/test/data/course_before_rename/drafts/vertical/f8ee1d2026e048b884d2ff6c4daa9def.xml @@ -0,0 +1 @@ + diff --git a/common/test/data/course_before_rename/policies/2015/grading_policy.json b/common/test/data/course_before_rename/policies/2015/grading_policy.json new file mode 100644 index 0000000000..3fe56c2dff --- /dev/null +++ b/common/test/data/course_before_rename/policies/2015/grading_policy.json @@ -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 + } +} \ No newline at end of file diff --git a/common/test/data/course_before_rename/policies/2015/policy.json b/common/test/data/course_before_rename/policies/2015/policy.json new file mode 100644 index 0000000000..a5db6180cf --- /dev/null +++ b/common/test/data/course_before_rename/policies/2015/policy.json @@ -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" + } + ] + } +} \ No newline at end of file diff --git a/common/test/data/course_before_rename/policies/assets.json b/common/test/data/course_before_rename/policies/assets.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/common/test/data/course_before_rename/policies/assets.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/common/test/data/course_before_rename/sequential/761dd4188c3e49f390a8d2a47156f503.xml b/common/test/data/course_before_rename/sequential/761dd4188c3e49f390a8d2a47156f503.xml new file mode 100644 index 0000000000..aef65ba24e --- /dev/null +++ b/common/test/data/course_before_rename/sequential/761dd4188c3e49f390a8d2a47156f503.xml @@ -0,0 +1,3 @@ + + + diff --git a/common/test/data/course_before_rename/vertical/f8ee1d2026e048b884d2ff6c4daa9def.xml b/common/test/data/course_before_rename/vertical/f8ee1d2026e048b884d2ff6c4daa9def.xml new file mode 100644 index 0000000000..38fbf79deb --- /dev/null +++ b/common/test/data/course_before_rename/vertical/f8ee1d2026e048b884d2ff6c4daa9def.xml @@ -0,0 +1 @@ +