Merge pull request #10390 from edx/mobile/make-course-usage-key
Add make_course_usage_key method to modulestore
This commit is contained in:
@@ -906,6 +906,14 @@ class ModuleStoreRead(ModuleStoreAssetBase):
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def make_course_usage_key(self, course_key):
|
||||
"""
|
||||
Return a valid :class:`~opaque_keys.edx.keys.UsageKey` for this modulestore
|
||||
that matches the supplied course_key.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_courses(self, **kwargs):
|
||||
'''
|
||||
|
||||
@@ -313,6 +313,15 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
|
||||
# Otherwise, return the key created by the default store
|
||||
return self.default_modulestore.make_course_key(org, course, run)
|
||||
|
||||
def make_course_usage_key(self, course_key):
|
||||
"""
|
||||
Return a valid :class:`~opaque_keys.edx.keys.UsageKey` for the modulestore
|
||||
that matches the supplied course_key.
|
||||
"""
|
||||
assert isinstance(course_key, CourseKey)
|
||||
store = self._get_modulestore_for_courselike(course_key)
|
||||
return store.make_course_usage_key(course_key)
|
||||
|
||||
@strip_key
|
||||
def get_course(self, course_key, depth=0, **kwargs):
|
||||
"""
|
||||
|
||||
@@ -1033,6 +1033,13 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
|
||||
"""
|
||||
return CourseLocator(org, course, run, deprecated=True)
|
||||
|
||||
def make_course_usage_key(self, course_key):
|
||||
"""
|
||||
Return a valid :class:`~opaque_keys.edx.keys.UsageKey` for this modulestore
|
||||
that matches the supplied course_key.
|
||||
"""
|
||||
return BlockUsageLocator(course_key, 'course', course_key.run)
|
||||
|
||||
def get_course(self, course_key, depth=0, **kwargs):
|
||||
"""
|
||||
Get the course with the given courseid (org/course/run)
|
||||
|
||||
@@ -70,6 +70,7 @@ from xmodule.errortracker import null_error_tracker
|
||||
from opaque_keys.edx.locator import (
|
||||
BlockUsageLocator, DefinitionLocator, CourseLocator, LibraryLocator, VersionTree, LocalId,
|
||||
)
|
||||
from ccx_keys.locator import CCXLocator, CCXBlockUsageLocator
|
||||
from xmodule.modulestore.exceptions import InsufficientSpecificationError, VersionConflictError, DuplicateItemError, \
|
||||
DuplicateCourseError
|
||||
from xmodule.modulestore import (
|
||||
@@ -949,6 +950,14 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
"""
|
||||
return CourseLocator(org, course, run)
|
||||
|
||||
def make_course_usage_key(self, course_key):
|
||||
"""
|
||||
Return a valid :class:`~opaque_keys.edx.keys.UsageKey` for this modulestore
|
||||
that matches the supplied course_key.
|
||||
"""
|
||||
locator_cls = CCXBlockUsageLocator if isinstance(course_key, CCXLocator) else BlockUsageLocator
|
||||
return locator_cls(course_key, 'course', 'course')
|
||||
|
||||
def _get_structure(self, structure_id, depth, head_validation=True, **kwargs):
|
||||
"""
|
||||
Gets Course or Library by locator
|
||||
|
||||
@@ -758,6 +758,13 @@ class TestMongoModuleStore(TestMongoModuleStoreBase):
|
||||
# Clean up the data so we don't break other tests which apparently expect a particular state
|
||||
self.draft_store.delete_course(course.id, self.dummy_user)
|
||||
|
||||
def test_make_course_usage_key(self):
|
||||
"""Test that we get back the appropriate usage key for the root of a course key."""
|
||||
course_key = CourseLocator(org="edX", course="101", run="2015")
|
||||
root_block_key = self.draft_store.make_course_usage_key(course_key)
|
||||
self.assertEqual(root_block_key.block_type, "course")
|
||||
self.assertEqual(root_block_key.name, "2015")
|
||||
|
||||
|
||||
class TestMongoModuleStoreWithNoAssetCollection(TestMongoModuleStore):
|
||||
'''
|
||||
|
||||
@@ -10,6 +10,7 @@ import re
|
||||
import unittest
|
||||
import uuid
|
||||
|
||||
import ddt
|
||||
from contracts import contract
|
||||
from nose.plugins.attrib import attr
|
||||
from django.core.cache import get_cache, InvalidCacheBackendError
|
||||
@@ -23,7 +24,8 @@ from xmodule.modulestore.exceptions import (
|
||||
DuplicateItemError, DuplicateCourseError,
|
||||
InsufficientSpecificationError
|
||||
)
|
||||
from opaque_keys.edx.locator import CourseLocator, BlockUsageLocator, VersionTree, LocalId
|
||||
from opaque_keys.edx.locator import CourseKey, CourseLocator, BlockUsageLocator, VersionTree, LocalId
|
||||
from ccx_keys.locator import CCXBlockUsageLocator
|
||||
from xmodule.modulestore.inheritance import InheritanceMixin
|
||||
from xmodule.x_module import XModuleMixin
|
||||
from xmodule.fields import Date, Timedelta
|
||||
@@ -596,6 +598,7 @@ class TestHasChildrenAtDepth(SplitModuleTest):
|
||||
self.assertFalse(ch3.has_children_at_depth(1))
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class SplitModuleCourseTests(SplitModuleTest):
|
||||
'''
|
||||
Course CRUD operation tests
|
||||
@@ -908,6 +911,22 @@ class SplitModuleCourseTests(SplitModuleTest):
|
||||
version_history = modulestore().get_block_generations(second_problem.location)
|
||||
self.assertNotEqual(version_history.locator.version_guid, first_problem.location.version_guid)
|
||||
|
||||
@ddt.data(
|
||||
("course-v1:edx+test_course+test_run", BlockUsageLocator),
|
||||
("ccx-v1:edX+test_course+test_run+ccx@1", CCXBlockUsageLocator),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_make_course_usage_key(self, course_id, root_block_cls):
|
||||
"""Test that we get back the appropriate usage key for the root of a course key.
|
||||
|
||||
In particular, we want to make sure that it properly handles CCX courses.
|
||||
"""
|
||||
course_key = CourseKey.from_string(course_id)
|
||||
root_block_key = modulestore().make_course_usage_key(course_key)
|
||||
self.assertIsInstance(root_block_key, root_block_cls)
|
||||
self.assertEqual(root_block_key.block_type, "course")
|
||||
self.assertEqual(root_block_key.name, "course")
|
||||
|
||||
|
||||
class TestCourseStructureCache(SplitModuleTest):
|
||||
"""Tests for the CourseStructureCache"""
|
||||
|
||||
@@ -27,7 +27,7 @@ from xmodule.modulestore.xml_exporter import DEFAULT_CONTENT_FIELDS
|
||||
from xmodule.modulestore import ModuleStoreEnum, ModuleStoreReadBase, LIBRARY_ROOT, COURSE_ROOT
|
||||
from xmodule.tabs import CourseTabList
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey, Location
|
||||
from opaque_keys.edx.locator import CourseLocator, LibraryLocator
|
||||
from opaque_keys.edx.locator import CourseLocator, LibraryLocator, BlockUsageLocator
|
||||
|
||||
from xblock.field_data import DictFieldData
|
||||
from xblock.runtime import DictKeyValueStore
|
||||
@@ -821,6 +821,13 @@ class XMLModuleStore(ModuleStoreReadBase):
|
||||
"""
|
||||
return CourseLocator(org, course, run, deprecated=True)
|
||||
|
||||
def make_course_usage_key(self, course_key):
|
||||
"""
|
||||
Return a valid :class:`~opaque_keys.edx.keys.UsageKey` for this modulestore
|
||||
that matches the supplied course_key.
|
||||
"""
|
||||
return BlockUsageLocator(course_key, 'course', course_key.run)
|
||||
|
||||
def get_courses(self, **kwargs):
|
||||
"""
|
||||
Returns a list of course descriptors. If there were errors on loading,
|
||||
|
||||
Reference in New Issue
Block a user