Exemplo n.º 1
0
    def translate_location(self, location, published=True,
                           add_entry_if_missing=True, passed_block_id=None):
        """
        Translate the given module location to a Locator.

        The rationale for auto adding entries was that there should be a reasonable default translation
        if the code just trips into this w/o creating translations.

        Will raise ItemNotFoundError if there's no mapping and add_entry_if_missing is False.

        :param location:  a Location pointing to a module
        :param published: a boolean to indicate whether the caller wants the draft or published branch.
        :param add_entry_if_missing: a boolean as to whether to raise ItemNotFoundError or to create an entry if
        the course
        or block is not found in the map.
        :param passed_block_id: what block_id to assign and save if none is found
        (only if add_entry_if_missing)

        NOTE: unlike old mongo, draft branches contain the whole course; so, it applies to all category
        of locations including course.
        """
        course_son = self._interpret_location_course_id(location.course_key)

        cached_value = self._get_locator_from_cache(location, published)
        if cached_value:
            return cached_value

        entry = self.location_map.find_one(course_son)
        if entry is None:
            if add_entry_if_missing:
                # create a new map
                self.create_map_entry(location.course_key)
                entry = self.location_map.find_one(course_son)
            else:
                raise ItemNotFoundError(location)
        else:
            entry = self._migrate_if_necessary([entry])[0]

        block_id = entry['block_map'].get(self.encode_key_for_mongo(location.name))
        category = location.category
        if block_id is None:
            if add_entry_if_missing:
                block_id = self._add_to_block_map(
                    location, course_son, entry['block_map'], passed_block_id
                )
            else:
                raise ItemNotFoundError(location)
        else:
            # jump_to_id uses a None category.
            if category is None:
                if len(block_id) == 1:
                    # unique match (most common case)
                    category = block_id.keys()[0]
                    block_id = block_id.values()[0]
                else:
                    raise InvalidLocationError()
            elif category in block_id:
                block_id = block_id[category]
            elif add_entry_if_missing:
                block_id = self._add_to_block_map(location, course_son, entry['block_map'])
            else:
                raise ItemNotFoundError(location)

        prod_course_locator = CourseLocator(
            org=entry['org'],
            offering=entry['offering'],
            branch=entry['prod_branch']
        )
        published_usage = BlockUsageLocator(
            prod_course_locator,
            block_type=category,
            block_id=block_id
        )
        draft_usage = BlockUsageLocator(
            prod_course_locator.for_branch(entry['draft_branch']),
            block_type=category,
            block_id=block_id
        )
        if published:
            result = published_usage
        else:
            result = draft_usage

        self._cache_location_map_entry(location, published_usage, draft_usage)
        return result
Exemplo n.º 2
0
    def test_translate_locator(self):
        """
        tests translate_locator_to_location(BlockUsageLocator)
        """
        # lookup for non-existent course
        org = "foo_org"
        course = "bar_course"
        run = "baz_run"
        new_style_org = "{}.geek_dept".format(org)
        new_style_offering = "{}.{}".format(course, run)
        prob_course_key = CourseLocator(
            org=new_style_org, offering=new_style_offering, branch=ModuleStoreEnum.BranchName.published
        )
        prob_locator = BlockUsageLocator(prob_course_key, block_type="problem", block_id="problem2")
        prob_location = loc_mapper().translate_locator_to_location(prob_locator)
        self.assertIsNone(prob_location, "found entry in empty map table")

        loc_mapper().create_map_entry(
            SlashSeparatedCourseKey(org, course, run),
            new_style_org,
            new_style_offering,
            block_map={
                "abc123": {"problem": "problem2"},
                "48f23a10395384929234": {"chapter": "chapter48f"},
                "baz_run": {"course": "root"},
            },
        )
        # only one course matches
        prob_location = loc_mapper().translate_locator_to_location(prob_locator)
        # default branch
        self.assertEqual(prob_location, Location(org, course, run, "problem", "abc123", MongoRevisionKey.published))
        # test get_course keyword
        prob_location = loc_mapper().translate_locator_to_location(prob_locator, get_course=True)
        self.assertEqual(prob_location, SlashSeparatedCourseKey(org, course, run))
        # explicit branch
        prob_locator = prob_locator.for_branch(ModuleStoreEnum.BranchName.draft)
        prob_location = loc_mapper().translate_locator_to_location(prob_locator)
        # Even though the problem was set as draft, we always return revision= MongoRevisionKey.published to work
        # with old mongo/draft modulestores.
        self.assertEqual(prob_location, Location(org, course, run, "problem", "abc123", MongoRevisionKey.published))
        prob_locator = BlockUsageLocator(
            prob_course_key.for_branch("production"), block_type="problem", block_id="problem2"
        )
        prob_location = loc_mapper().translate_locator_to_location(prob_locator)
        self.assertEqual(prob_location, Location(org, course, run, "problem", "abc123", MongoRevisionKey.published))
        # same for chapter except chapter cannot be draft in old system
        chap_locator = BlockUsageLocator(
            prob_course_key.for_branch("production"), block_type="chapter", block_id="chapter48f"
        )
        chap_location = loc_mapper().translate_locator_to_location(chap_locator)
        self.assertEqual(chap_location, Location(org, course, run, "chapter", "48f23a10395384929234"))
        # explicit branch
        chap_locator = chap_locator.for_branch(ModuleStoreEnum.BranchName.draft)
        chap_location = loc_mapper().translate_locator_to_location(chap_locator)
        self.assertEqual(chap_location, Location(org, course, run, "chapter", "48f23a10395384929234"))
        chap_locator = BlockUsageLocator(
            prob_course_key.for_branch("production"), block_type="chapter", block_id="chapter48f"
        )
        chap_location = loc_mapper().translate_locator_to_location(chap_locator)
        self.assertEqual(chap_location, Location(org, course, run, "chapter", "48f23a10395384929234"))

        # look for non-existent problem
        prob_locator2 = BlockUsageLocator(
            prob_course_key.for_branch(ModuleStoreEnum.BranchName.draft), block_type="problem", block_id="problem3"
        )
        prob_location = loc_mapper().translate_locator_to_location(prob_locator2)
        self.assertIsNone(prob_location, "Found non-existent problem")

        # add a distractor course
        delta_run = "delta_run"
        new_style_offering = "{}.{}".format(course, delta_run)
        loc_mapper().create_map_entry(
            SlashSeparatedCourseKey(org, course, delta_run),
            new_style_org,
            new_style_offering,
            block_map={"abc123": {"problem": "problem3"}},
        )
        prob_location = loc_mapper().translate_locator_to_location(prob_locator)
        self.assertEqual(prob_location, Location(org, course, run, "problem", "abc123", MongoRevisionKey.published))
Exemplo n.º 3
0
    def translate_location(self,
                           location,
                           published=True,
                           add_entry_if_missing=True,
                           passed_block_id=None):
        """
        Translate the given module location to a Locator.

        The rationale for auto adding entries was that there should be a reasonable default translation
        if the code just trips into this w/o creating translations.

        Will raise ItemNotFoundError if there's no mapping and add_entry_if_missing is False.

        :param location:  a Location pointing to a module
        :param published: a boolean to indicate whether the caller wants the draft or published branch.
        :param add_entry_if_missing: a boolean as to whether to raise ItemNotFoundError or to create an entry if
        the course
        or block is not found in the map.
        :param passed_block_id: what block_id to assign and save if none is found
        (only if add_entry_if_missing)

        NOTE: unlike old mongo, draft branches contain the whole course; so, it applies to all category
        of locations including course.
        """
        course_son = self._interpret_location_course_id(location.course_key)

        cached_value = self._get_locator_from_cache(location, published)
        if cached_value:
            return cached_value

        entry = self.location_map.find_one(course_son)
        if entry is None:
            if add_entry_if_missing:
                # create a new map
                self.create_map_entry(location.course_key)
                entry = self.location_map.find_one(course_son)
            else:
                raise ItemNotFoundError(location)
        else:
            entry = self._migrate_if_necessary([entry])[0]

        block_id = entry['block_map'].get(
            self.encode_key_for_mongo(location.name))
        category = location.category
        if block_id is None:
            if add_entry_if_missing:
                block_id = self._add_to_block_map(location, course_son,
                                                  entry['block_map'],
                                                  passed_block_id)
            else:
                raise ItemNotFoundError(location)
        else:
            # jump_to_id uses a None category.
            if category is None:
                if len(block_id) == 1:
                    # unique match (most common case)
                    category = block_id.keys()[0]
                    block_id = block_id.values()[0]
                else:
                    raise InvalidLocationError()
            elif category in block_id:
                block_id = block_id[category]
            elif add_entry_if_missing:
                block_id = self._add_to_block_map(location, course_son,
                                                  entry['block_map'])
            else:
                raise ItemNotFoundError(location)

        prod_course_locator = CourseLocator(org=entry['org'],
                                            offering=entry['offering'],
                                            branch=entry['prod_branch'])
        published_usage = BlockUsageLocator(prod_course_locator,
                                            block_type=category,
                                            block_id=block_id)
        draft_usage = BlockUsageLocator(prod_course_locator.for_branch(
            entry['draft_branch']),
                                        block_type=category,
                                        block_id=block_id)
        if published:
            result = published_usage
        else:
            result = draft_usage

        self._cache_location_map_entry(location, published_usage, draft_usage)
        return result
Exemplo n.º 4
0
    def test_translate_locator(self):
        """
        tests translate_locator_to_location(BlockUsageLocator)
        """
        # lookup for non-existent course
        org = 'foo_org'
        course = 'bar_course'
        run = 'baz_run'
        new_style_org = '{}.geek_dept'.format(org)
        new_style_offering = '{}.{}'.format(course, run)
        prob_course_key = CourseLocator(
            org=new_style_org, offering=new_style_offering,
            branch=BRANCH_NAME_PUBLISHED,
        )
        prob_locator = BlockUsageLocator(
            prob_course_key,
            block_type='problem',
            block_id='problem2',
        )
        prob_location = loc_mapper().translate_locator_to_location(prob_locator)
        self.assertIsNone(prob_location, 'found entry in empty map table')

        loc_mapper().create_map_entry(
            SlashSeparatedCourseKey(org, course, run),
            new_style_org, new_style_offering,
            block_map={
                'abc123': {'problem': 'problem2'},
                '48f23a10395384929234': {'chapter': 'chapter48f'},
                'baz_run': {'course': 'root'},
            }
        )
        # only one course matches
        prob_location = loc_mapper().translate_locator_to_location(prob_locator)
        # default branch
        self.assertEqual(prob_location, Location(org, course, run, 'problem', 'abc123', KEY_REVISION_PUBLISHED))
        # test get_course keyword
        prob_location = loc_mapper().translate_locator_to_location(prob_locator, get_course=True)
        self.assertEqual(prob_location, SlashSeparatedCourseKey(org, course, run))
        # explicit branch
        prob_locator = prob_locator.for_branch(BRANCH_NAME_DRAFT)
        prob_location = loc_mapper().translate_locator_to_location(prob_locator)
        # Even though the problem was set as draft, we always return revision= KEY_REVISION_PUBLISHED to work
        # with old mongo/draft modulestores.
        self.assertEqual(prob_location, Location(org, course, run, 'problem', 'abc123', KEY_REVISION_PUBLISHED))
        prob_locator = BlockUsageLocator(
            prob_course_key.for_branch('production'),
            block_type='problem', block_id='problem2'
        )
        prob_location = loc_mapper().translate_locator_to_location(prob_locator)
        self.assertEqual(prob_location, Location(org, course, run, 'problem', 'abc123', KEY_REVISION_PUBLISHED))
        # same for chapter except chapter cannot be draft in old system
        chap_locator = BlockUsageLocator(
            prob_course_key.for_branch('production'),
            block_type='chapter', block_id='chapter48f',
        )
        chap_location = loc_mapper().translate_locator_to_location(chap_locator)
        self.assertEqual(chap_location, Location(org, course, run, 'chapter', '48f23a10395384929234'))
        # explicit branch
        chap_locator = chap_locator.for_branch(BRANCH_NAME_DRAFT)
        chap_location = loc_mapper().translate_locator_to_location(chap_locator)
        self.assertEqual(chap_location, Location(org, course, run, 'chapter', '48f23a10395384929234'))
        chap_locator = BlockUsageLocator(
            prob_course_key.for_branch('production'), block_type='chapter', block_id='chapter48f'
        )
        chap_location = loc_mapper().translate_locator_to_location(chap_locator)
        self.assertEqual(chap_location, Location(org, course, run, 'chapter', '48f23a10395384929234'))

        # look for non-existent problem
        prob_locator2 = BlockUsageLocator(
            prob_course_key.for_branch(BRANCH_NAME_DRAFT),
            block_type='problem', block_id='problem3'
        )
        prob_location = loc_mapper().translate_locator_to_location(prob_locator2)
        self.assertIsNone(prob_location, 'Found non-existent problem')

        # add a distractor course
        delta_run = 'delta_run'
        new_style_offering = '{}.{}'.format(course, delta_run)
        loc_mapper().create_map_entry(
            SlashSeparatedCourseKey(org, course, delta_run),
            new_style_org, new_style_offering,
            block_map={'abc123': {'problem': 'problem3'}}
        )
        prob_location = loc_mapper().translate_locator_to_location(prob_locator)
        self.assertEqual(prob_location, Location(org, course, run, 'problem', 'abc123', KEY_REVISION_PUBLISHED))
Exemplo n.º 5
0
    def test_translate_locator(self):
        """
        tests translate_locator_to_location(BlockUsageLocator)
        """
        # lookup for non-existent course
        org = 'foo_org'
        course = 'bar_course'
        run = 'baz_run'
        new_style_org = '{}.geek_dept'.format(org)
        new_style_offering = '{}.{}'.format(course, run)
        prob_course_key = CourseLocator(
            org=new_style_org, offering=new_style_offering,
            branch='published',
        )
        prob_locator = BlockUsageLocator(
            prob_course_key,
            block_type='problem',
            block_id='problem2',
        )
        prob_location = loc_mapper().translate_locator_to_location(prob_locator)
        self.assertIsNone(prob_location, 'found entry in empty map table')

        loc_mapper().create_map_entry(
            SlashSeparatedCourseKey(org, course, run),
            new_style_org, new_style_offering,
            block_map={
                'abc123': {'problem': 'problem2'},
                '48f23a10395384929234': {'chapter': 'chapter48f'},
                'baz_run': {'course': 'root'},
            }
        )
        # only one course matches
        prob_location = loc_mapper().translate_locator_to_location(prob_locator)
        # default branch
        self.assertEqual(prob_location, Location(org, course, run, 'problem', 'abc123', None))
        # test get_course keyword
        prob_location = loc_mapper().translate_locator_to_location(prob_locator, get_course=True)
        self.assertEqual(prob_location, SlashSeparatedCourseKey(org, course, run))
        # explicit branch
        prob_locator = prob_locator.for_branch('draft')
        prob_location = loc_mapper().translate_locator_to_location(prob_locator)
        # Even though the problem was set as draft, we always return revision=None to work
        # with old mongo/draft modulestores.
        self.assertEqual(prob_location, Location(org, course, run, 'problem', 'abc123', None))
        prob_locator = BlockUsageLocator(
            prob_course_key.for_branch('production'),
            block_type='problem', block_id='problem2'
        )
        prob_location = loc_mapper().translate_locator_to_location(prob_locator)
        self.assertEqual(prob_location, Location(org, course, run, 'problem', 'abc123', None))
        # same for chapter except chapter cannot be draft in old system
        chap_locator = BlockUsageLocator(
            prob_course_key.for_branch('production'),
            block_type='chapter', block_id='chapter48f',
        )
        chap_location = loc_mapper().translate_locator_to_location(chap_locator)
        self.assertEqual(chap_location, Location(org, course, run, 'chapter', '48f23a10395384929234'))
        # explicit branch
        chap_locator = chap_locator.for_branch('draft')
        chap_location = loc_mapper().translate_locator_to_location(chap_locator)
        self.assertEqual(chap_location, Location(org, course, run, 'chapter', '48f23a10395384929234'))
        chap_locator = BlockUsageLocator(
            prob_course_key.for_branch('production'), block_type='chapter', block_id='chapter48f'
        )
        chap_location = loc_mapper().translate_locator_to_location(chap_locator)
        self.assertEqual(chap_location, Location(org, course, run, 'chapter', '48f23a10395384929234'))

        # look for non-existent problem
        prob_locator2 = BlockUsageLocator(
            prob_course_key.for_branch('draft'),
            block_type='problem', block_id='problem3'
        )
        prob_location = loc_mapper().translate_locator_to_location(prob_locator2)
        self.assertIsNone(prob_location, 'Found non-existent problem')

        # add a distractor course
        delta_run = 'delta_run'
        new_style_offering = '{}.{}'.format(course, delta_run)
        loc_mapper().create_map_entry(
            SlashSeparatedCourseKey(org, course, delta_run),
            new_style_org, new_style_offering,
            block_map={'abc123': {'problem': 'problem3'}}
        )
        prob_location = loc_mapper().translate_locator_to_location(prob_locator)
        self.assertEqual(prob_location, Location(org, course, run, 'problem', 'abc123', None))