diff --git a/common/lib/xmodule/xmodule/conditional_module.py b/common/lib/xmodule/xmodule/conditional_module.py index 7ea3483aef..6e73ed3509 100644 --- a/common/lib/xmodule/xmodule/conditional_module.py +++ b/common/lib/xmodule/xmodule/conditional_module.py @@ -8,6 +8,8 @@ import logging from lazy import lazy from lxml import etree from pkg_resources import resource_string + +from opaque_keys.edx.locator import BlockUsageLocator from xblock.fields import ReferenceList, Scope, String from xblock.fragment import Fragment @@ -265,7 +267,11 @@ class ConditionalDescriptor(ConditionalFields, SequenceDescriptor, StudioEditabl if not self.sources_list: if 'sources' in self.xml_attributes and isinstance(self.xml_attributes['sources'], basestring): self.sources_list = [ - self.location.course_key.make_usage_key_from_deprecated_string(item) + # TODO: it is not clear why we are replacing the run here (which actually is a no-op + # for old-style course locators. However, this is the implementation of + # CourseLocator.make_usage_key_from_deprecated_string, which was previously + # being called in this location. + BlockUsageLocator.from_string(item).replace(run=self.location.course_key.run) for item in ConditionalDescriptor.parse_sources(self.xml_attributes) ] diff --git a/common/lib/xmodule/xmodule/modulestore/mongo/base.py b/common/lib/xmodule/xmodule/modulestore/mongo/base.py index e1dc91afb4..aa9edf474a 100644 --- a/common/lib/xmodule/xmodule/modulestore/mongo/base.py +++ b/common/lib/xmodule/xmodule/modulestore/mongo/base.py @@ -837,7 +837,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo # first get non-draft in a round-trip query = { '_id': {'$in': [ - course_key.make_usage_key_from_deprecated_string(item).to_deprecated_son() for item in items + UsageKey.from_string(item).map_into_course(course_key).to_deprecated_son() for item in items ]} } return list(self.collection.find(query)) @@ -1741,7 +1741,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo ) all_reachable = all_reachable.union(item.get('definition', {}).get('children', [])) item_locs -= all_reachable - return [course_key.make_usage_key_from_deprecated_string(item_loc) for item_loc in item_locs] + return [UsageKey.from_string(item_loc).map_into_course(course_key) for item_loc in item_locs] def get_courses_for_wiki(self, wiki_slug, **kwargs): """ diff --git a/common/lib/xmodule/xmodule/modulestore/mongo/draft.py b/common/lib/xmodule/xmodule/modulestore/mongo/draft.py index c7585a6ecc..9429f9d76b 100644 --- a/common/lib/xmodule/xmodule/modulestore/mongo/draft.py +++ b/common/lib/xmodule/xmodule/modulestore/mongo/draft.py @@ -9,6 +9,7 @@ and otherwise returns i4x://org/course/cat/name). import pymongo import logging +from opaque_keys.edx.keys import UsageKey from opaque_keys.edx.locations import Location from openedx.core.lib.cache_utils import memoize_in_request_cache from xmodule.exceptions import InvalidVersionError @@ -424,7 +425,7 @@ class DraftModuleStore(MongoModuleStore): # collect the children's ids for future processing next_tier = [] for child in item.get('definition', {}).get('children', []): - child_loc = Location.from_deprecated_string(child) + child_loc = Location.from_string(child) next_tier.append(child_loc.to_deprecated_son()) # insert a new DRAFT version of the item @@ -582,7 +583,7 @@ class DraftModuleStore(MongoModuleStore): to_be_deleted.append(self._id_dict_to_son(current_entry['_id'])) next_tier = [] for child_loc in current_entry.get('definition', {}).get('children', []): - child_loc = course_key.make_usage_key_from_deprecated_string(child_loc) + child_loc = UsageKey.from_string(child_loc).map_into_course(course_key) # single parent can have 2 versions: draft and published # get draft parents only while deleting draft module @@ -813,7 +814,7 @@ class DraftModuleStore(MongoModuleStore): item = versions_found[0] assert item.get('_id').get('revision') != MongoRevisionKey.draft for child in item.get('definition', {}).get('children', []): - child_loc = Location.from_deprecated_string(child) + child_loc = Location.from_string(child) delete_draft_only(child_loc) delete_draft_only(location) @@ -829,7 +830,7 @@ class DraftModuleStore(MongoModuleStore): user_id (int) : User id """ for child_location in published_version.get('definition', {}).get('children', []): - item_location = original_parent_location.course_key.make_usage_key_from_deprecated_string(child_location) + item_location = UsageKey.from_string(child_location).map_into_course(original_parent_location.course_key) try: source_item = self.get_item(item_location) except ItemNotFoundError: @@ -838,7 +839,7 @@ class DraftModuleStore(MongoModuleStore): if source_item.parent and source_item.parent.block_id != original_parent_location.block_id: if self.update_item_parent(item_location, original_parent_location, source_item.parent, user_id): - delete_draft_only(Location.from_deprecated_string(child_location)) + delete_draft_only(Location.from_string(child_location)) def _query_children_for_cache_children(self, course_key, items): # first get non-draft in a round-trip @@ -852,7 +853,7 @@ class DraftModuleStore(MongoModuleStore): # now query all draft content in another round-trip query = [] for item in items: - item_usage_key = course_key.make_usage_key_from_deprecated_string(item) + item_usage_key = UsageKey.from_string(item).map_into_course(course_key) if item_usage_key.category not in DIRECT_ONLY_CATEGORIES: query.append(as_draft(item_usage_key).to_deprecated_son()) if query: diff --git a/common/lib/xmodule/xmodule/modulestore/mongoengine_fields.py b/common/lib/xmodule/xmodule/modulestore/mongoengine_fields.py index 03a033f857..6c3f422e6c 100644 --- a/common/lib/xmodule/xmodule/modulestore/mongoengine_fields.py +++ b/common/lib/xmodule/xmodule/modulestore/mongoengine_fields.py @@ -73,7 +73,7 @@ class UsageKeyField(mongoengine.StringField): return None if isinstance(location, basestring): location = super(UsageKeyField, self).to_python(location) - return Location.from_deprecated_string(location) + return Location.from_string(location) else: return location diff --git a/common/lib/xmodule/xmodule/modulestore/xml_importer.py b/common/lib/xmodule/xmodule/modulestore/xml_importer.py index 382e0cbde2..b7ed7c00a4 100644 --- a/common/lib/xmodule/xmodule/modulestore/xml_importer.py +++ b/common/lib/xmodule/xmodule/modulestore/xml_importer.py @@ -829,7 +829,7 @@ def _import_course_draft( # filtered out from the non-draft store export. if parent_url is not None and index is not None: course_key = descriptor.location.course_key - parent_location = course_key.make_usage_key_from_deprecated_string(parent_url) + parent_location = UsageKey.from_string(parent_url).map_into_course(course_key) # IMPORTANT: Be sure to update the parent in the NEW namespace parent_location = parent_location.map_into_course(target_id) diff --git a/common/lib/xmodule/xmodule/tests/test_conditional.py b/common/lib/xmodule/xmodule/tests/test_conditional.py index 73d9ddd041..5704e439bf 100644 --- a/common/lib/xmodule/xmodule/tests/test_conditional.py +++ b/common/lib/xmodule/xmodule/tests/test_conditional.py @@ -10,6 +10,7 @@ from xblock.fields import ScopeIds from xmodule.error_module import NonStaffErrorDescriptor from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.locations import Location +from opaque_keys.edx.locator import BlockUsageLocator from xmodule.modulestore.xml import ImportSystem, XMLModuleStore, CourseLocationManager from xmodule.conditional_module import ConditionalDescriptor from xmodule.tests import DATA_DIR, get_test_system, get_test_descriptor_system @@ -318,9 +319,11 @@ class ConditionalModuleXmlTest(unittest.TestCase): dummy_field_data, dummy_scope_ids, ) + new_run = conditional.location.course_key.run self.assertEqual( conditional.sources_list[0], - conditional.location.course_key.make_usage_key_from_deprecated_string(conditional.xml_attributes['sources']) + # Matching what is in ConditionalDescriptor.__init__. + BlockUsageLocator.from_string(conditional.xml_attributes['sources']).replace(run=new_run) ) def test_conditional_module_parse_sources(self): diff --git a/common/lib/xmodule/xmodule/x_module.py b/common/lib/xmodule/xmodule/x_module.py index 7e707f4884..b4a6e41264 100644 --- a/common/lib/xmodule/xmodule/x_module.py +++ b/common/lib/xmodule/xmodule/x_module.py @@ -1632,7 +1632,8 @@ class XMLParsingSystem(DescriptorSystem): """ if isinstance(value, UsageKey): return value - return course_key.make_usage_key_from_deprecated_string(value) + usage_key = UsageKey.from_string(value) + return usage_key.map_into_course(course_key) def _convert_reference_fields_to_keys(self, xblock): """ diff --git a/lms/djangoapps/class_dashboard/dashboard_data.py b/lms/djangoapps/class_dashboard/dashboard_data.py index f078258664..77944a2206 100644 --- a/lms/djangoapps/class_dashboard/dashboard_data.py +++ b/lms/djangoapps/class_dashboard/dashboard_data.py @@ -5,6 +5,8 @@ import json from django.db.models import Count from django.utils.translation import ugettext as _ + +from opaque_keys.edx.keys import UsageKey from opaque_keys.edx.locations import Location from courseware import models @@ -43,7 +45,7 @@ def get_problem_grade_distribution(course_id): # Loop through resultset building data for each problem for row in db_query: - curr_problem = course_id.make_usage_key_from_deprecated_string(row['module_state_key']) + curr_problem = UsageKey.from_string(row['module_state_key']).map_into_course(course_id) # Build set of grade distributions for each problem that has student responses if curr_problem in prob_grade_distrib: @@ -83,7 +85,7 @@ def get_sequential_open_distrib(course_id): # Build set of "opened" data for each subsection that has "opened" data sequential_open_distrib = {} for row in db_query: - row_loc = course_id.make_usage_key_from_deprecated_string(row['module_state_key']) + row_loc = UsageKey.from_string(row['module_state_key']).map_into_course(course_id) sequential_open_distrib[row_loc] = row['count_sequential'] return sequential_open_distrib @@ -120,7 +122,7 @@ def get_problem_set_grade_distrib(course_id, problem_set): # Loop through resultset building data for each problem for row in db_query: - row_loc = course_id.make_usage_key_from_deprecated_string(row['module_state_key']) + row_loc = UsageKey.from_string(row['module_state_key']).map_into_course(course_id) if row_loc not in prob_grade_distrib: prob_grade_distrib[row_loc] = { 'max_grade': 0, @@ -433,7 +435,7 @@ def get_students_opened_subsection(request, csv=False): If 'csv' is True, returns a header array, and an array of arrays in the format: student names, usernames for CSV download. """ - module_state_key = Location.from_deprecated_string(request.GET.get('module_id')) + module_state_key = Location.from_string(request.GET.get('module_id')) csv = request.GET.get('csv') # Query for "opened a subsection" students @@ -485,7 +487,7 @@ def get_students_problem_grades(request, csv=False): If 'csv' is True, returns a header array, and an array of arrays in the format: student names, usernames, grades, percents for CSV download. """ - module_state_key = Location.from_deprecated_string(request.GET.get('module_id')) + module_state_key = Location.from_string(request.GET.get('module_id')) csv = request.GET.get('csv') # Query for "problem grades" students diff --git a/lms/djangoapps/courseware/entrance_exams.py b/lms/djangoapps/courseware/entrance_exams.py index 00c5d70ee5..cbdd0f19bf 100644 --- a/lms/djangoapps/courseware/entrance_exams.py +++ b/lms/djangoapps/courseware/entrance_exams.py @@ -3,6 +3,7 @@ This file contains all entrance exam related utils/logic. """ from courseware.access import has_access +from opaque_keys.edx.keys import UsageKey from student.models import EntranceExamConfiguration from util.milestones_helpers import get_required_content, is_entrance_exams_enabled from xmodule.modulestore.django import modulestore @@ -59,7 +60,7 @@ def get_entrance_exam_content(user, course): exam_module = None for content in required_content: - usage_key = course.id.make_usage_key_from_deprecated_string(content) + usage_key = UsageKey.from_string(content).map_into_course(course.id) module_item = modulestore().get_item(usage_key) if not module_item.hide_from_toc and module_item.is_entrance_exam: exam_module = module_item diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index 02e8e4b0af..46872723d4 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -886,7 +886,7 @@ def get_module_by_usage_id(request, course_id, usage_id, disable_staff_debug_inf try: course_id = CourseKey.from_string(course_id) - usage_key = course_id.make_usage_key_from_deprecated_string(unquote_slashes(usage_id)) + usage_key = UsageKey.from_string(unquote_slashes(usage_id)).map_into_course(course_id) except InvalidKeyError: raise Http404("Invalid location") diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py index 691792de19..8cfe2fd71a 100644 --- a/lms/djangoapps/courseware/views/views.py +++ b/lms/djangoapps/courseware/views/views.py @@ -1086,7 +1086,7 @@ def submission_history(request, course_id, student_username, location): course_key = CourseKey.from_string(course_id) try: - usage_key = course_key.make_usage_key_from_deprecated_string(location) + usage_key = UsageKey.from_string(location).map_into_course(course_key) except (InvalidKeyError, AssertionError): return HttpResponse(escape(_(u'Invalid location.'))) diff --git a/lms/djangoapps/instructor/views/api.py b/lms/djangoapps/instructor/views/api.py index ae87e1d753..f3f4d8ea55 100644 --- a/lms/djangoapps/instructor/views/api.py +++ b/lms/djangoapps/instructor/views/api.py @@ -987,7 +987,7 @@ def get_problem_responses(request, course_id): # Are we dealing with an "old-style" problem location? run = problem_key.run if not run: - problem_key = course_key.make_usage_key_from_deprecated_string(problem_location) + problem_key = UsageKey.from_string(problem_location).map_into_course(course_key) if problem_key.course_key != course_key: raise InvalidKeyError(type(problem_key), problem_key) except InvalidKeyError: @@ -1937,7 +1937,7 @@ def reset_student_attempts(request, course_id): return HttpResponseForbidden("Requires instructor access.") try: - module_state_key = course_id.make_usage_key_from_deprecated_string(problem_to_reset) + module_state_key = UsageKey.from_string(problem_to_reset).map_into_course(course_id) except InvalidKeyError: return HttpResponseBadRequest() @@ -2025,7 +2025,7 @@ def reset_student_attempts_for_entrance_exam(request, course_id): # pylint: dis return HttpResponseForbidden(_("Requires instructor access.")) try: - entrance_exam_key = course_id.make_usage_key_from_deprecated_string(course.entrance_exam_id) + entrance_exam_key = UsageKey.from_string(course.entrance_exam_id).map_into_course(course_id) if delete_module: lms.djangoapps.instructor_task.api.submit_delete_entrance_exam_state_for_student( request, @@ -2083,7 +2083,7 @@ def rescore_problem(request, course_id): ) try: - module_state_key = course_id.make_usage_key_from_deprecated_string(problem_to_reset) + module_state_key = UsageKey.from_string(problem_to_reset).map_into_course(course_id) except InvalidKeyError: return HttpResponseBadRequest("Unable to parse problem id") @@ -2215,7 +2215,7 @@ def rescore_entrance_exam(request, course_id): ) try: - entrance_exam_key = course_id.make_usage_key_from_deprecated_string(course.entrance_exam_id) + entrance_exam_key = UsageKey.from_string(course.entrance_exam_id).map_into_course(course_id) except InvalidKeyError: return HttpResponseBadRequest(_("Course has no valid entrance exam section.")) @@ -2300,7 +2300,7 @@ def list_instructor_tasks(request, course_id): if problem_location_str: try: - module_state_key = course_id.make_usage_key_from_deprecated_string(problem_location_str) + module_state_key = UsageKey.from_string(problem_location_str).map_into_course(course_id) except InvalidKeyError: return HttpResponseBadRequest() if student: @@ -2338,7 +2338,7 @@ def list_entrance_exam_instructor_tasks(request, course_id): # pylint: disable= student = get_student_from_identifier(student) try: - entrance_exam_key = course_id.make_usage_key_from_deprecated_string(course.entrance_exam_id) + entrance_exam_key = UsageKey.from_string(course.entrance_exam_id).map_into_course(course_id) except InvalidKeyError: return HttpResponseBadRequest(_("Course has no valid entrance exam section.")) if student: diff --git a/lms/djangoapps/instructor_analytics/basic.py b/lms/djangoapps/instructor_analytics/basic.py index 3393e19530..4622b55589 100644 --- a/lms/djangoapps/instructor_analytics/basic.py +++ b/lms/djangoapps/instructor_analytics/basic.py @@ -414,7 +414,7 @@ def list_problem_responses(course_key, problem_location): # Are we dealing with an "old-style" problem location? run = problem_key.run if not run: - problem_key = course_key.make_usage_key_from_deprecated_string(problem_location) + problem_key = UsageKey.from_string(problem_location).map_into_course(course_key) if problem_key.course_key != course_key: return [] diff --git a/lms/djangoapps/instructor_task/tasks_helper/module_state.py b/lms/djangoapps/instructor_task/tasks_helper/module_state.py index e27b67f777..175943c5ea 100644 --- a/lms/djangoapps/instructor_task/tasks_helper/module_state.py +++ b/lms/djangoapps/instructor_task/tasks_helper/module_state.py @@ -81,7 +81,7 @@ def perform_module_state_update(update_fcn, filter_fcn, _entry_id, course_id, ta # if problem_url is present make a usage key from it if problem_url: - usage_key = course_id.make_usage_key_from_deprecated_string(problem_url) + usage_key = UsageKey.from_string(problem_url).map_into_course(course_id) usage_keys.append(usage_key) # find the problem descriptor: diff --git a/lms/djangoapps/instructor_task/tests/test_base.py b/lms/djangoapps/instructor_task/tests/test_base.py index 3bc4a6baad..9bfce46389 100644 --- a/lms/djangoapps/instructor_task/tests/test_base.py +++ b/lms/djangoapps/instructor_task/tests/test_base.py @@ -207,7 +207,7 @@ class InstructorTaskModuleTestCase(InstructorTaskCourseTestCase): Create an internal location for a test problem. """ if "i4x:" in problem_url_name: - return Location.from_deprecated_string(problem_url_name) + return Location.from_string(problem_url_name) elif course_key: return course_key.make_usage_key('problem', problem_url_name) else: diff --git a/lms/lib/courseware_search/lms_result_processor.py b/lms/lib/courseware_search/lms_result_processor.py index c1045c9de3..633528c03e 100644 --- a/lms/lib/courseware_search/lms_result_processor.py +++ b/lms/lib/courseware_search/lms_result_processor.py @@ -4,7 +4,7 @@ This file contains implementation override of SearchResultProcessor which will a * Confirms user access to object """ from django.core.urlresolvers import reverse -from opaque_keys.edx.keys import CourseKey +from opaque_keys.edx.keys import CourseKey, UsageKey from search.result_processor import SearchResultProcessor from lms.djangoapps.course_blocks.api import get_course_blocks @@ -28,7 +28,8 @@ class LmsSearchResultProcessor(SearchResultProcessor): def get_usage_key(self): """ fetch usage key for component from string representation - retain result for subsequent uses """ if self._usage_key is None: - self._usage_key = self.get_course_key().make_usage_key_from_deprecated_string(self._results_fields["id"]) + usage_key = UsageKey.from_string(self._results_fields["id"]) + self._usage_key = usage_key.map_into_course(self.get_course_key()) return self._usage_key def get_module_store(self):