Merge pull request #3931 from edx/sarina/fixup-external-opaque-keys-impls

Use external OpaqueKey implementations
This commit is contained in:
Sarina Canelake
2014-05-29 18:23:08 -04:00
206 changed files with 271 additions and 991 deletions

View File

@@ -5,7 +5,7 @@
from lettuce import world, step
from component_settings_editor_helpers import enter_xml_in_advanced_problem
from nose.tools import assert_true, assert_equal
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from contentstore.utils import reverse_usage_url

View File

@@ -5,7 +5,7 @@ from lettuce import world, step
from common import *
from terrain.steps import reload_the_page
from selenium.common.exceptions import InvalidElementStateException
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from contentstore.utils import reverse_course_url
from nose.tools import assert_in, assert_not_in, assert_equal, assert_not_equal # pylint: disable=E0611

View File

@@ -1,9 +1,9 @@
from django.core.management.base import BaseCommand, CommandError
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.xml_importer import check_module_metadata_editability
from xmodule.modulestore.keys import CourseKey
from opaque_keys.edx.keys import CourseKey
from opaque_keys import InvalidKeyError
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
class Command(BaseCommand):

View File

@@ -6,9 +6,9 @@ from xmodule.modulestore.store_utilities import clone_course
from xmodule.modulestore.django import modulestore
from xmodule.contentstore.django import contentstore
from student.roles import CourseInstructorRole, CourseStaffRole
from xmodule.modulestore.keys import CourseKey
from opaque_keys.edx.keys import CourseKey
from opaque_keys import InvalidKeyError
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
#

View File

@@ -4,9 +4,9 @@
from django.core.management.base import BaseCommand, CommandError
from .prompt import query_yes_no
from contentstore.utils import delete_course_and_groups
from xmodule.modulestore.keys import CourseKey
from opaque_keys.edx.keys import CourseKey
from opaque_keys import InvalidKeyError
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
class Command(BaseCommand):

View File

@@ -14,8 +14,8 @@ from courseware.courses import get_course_by_id
from contentstore.views import tabs
from opaque_keys import InvalidKeyError
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from xmodule.modulestore.keys import CourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from opaque_keys.edx.keys import CourseKey
def print_course(course):

View File

@@ -1,10 +1,10 @@
from django.core.management.base import BaseCommand, CommandError
from xmodule.contentstore.utils import empty_asset_trashcan
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.keys import CourseKey
from opaque_keys.edx.keys import CourseKey
from .prompt import query_yes_no
from opaque_keys import InvalidKeyError
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
class Command(BaseCommand):

View File

@@ -6,10 +6,10 @@ import os
from django.core.management.base import BaseCommand, CommandError
from xmodule.modulestore.xml_exporter import export_to_xml
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.keys import CourseKey
from opaque_keys.edx.keys import CourseKey
from xmodule.contentstore.django import contentstore
from opaque_keys import InvalidKeyError
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
class Command(BaseCommand):

View File

@@ -20,10 +20,10 @@ from django.core.management.base import BaseCommand, CommandError
from django.utils.translation import ugettext as _
import contentstore.git_export_utils as git_export_utils
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from opaque_keys import InvalidKeyError
from contentstore.git_export_utils import GitExportError
from xmodule.modulestore.keys import CourseKey
from opaque_keys.edx.keys import CourseKey
log = logging.getLogger(__name__)

View File

@@ -7,9 +7,9 @@ from django.contrib.auth.models import User
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.split_migrator import SplitMigrator
from xmodule.modulestore.django import loc_mapper
from xmodule.modulestore.keys import CourseKey
from opaque_keys.edx.keys import CourseKey
from opaque_keys import InvalidKeyError
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
def user_from_str(identifier):

View File

@@ -5,7 +5,7 @@ is to delete the course from the split mongo datastore.
from django.core.management.base import BaseCommand, CommandError
from xmodule.modulestore.django import modulestore, loc_mapper
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore.locator import CourseLocator
from opaque_keys.edx.locator import CourseLocator
class Command(BaseCommand):

View File

@@ -18,7 +18,7 @@ from django.test.utils import override_settings
from contentstore.tests.utils import CourseTestCase
import contentstore.git_export_utils as git_export_utils
from contentstore.git_export_utils import GitExportError
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
FEATURES_WITH_EXPORT_GIT = settings.FEATURES.copy()
FEATURES_WITH_EXPORT_GIT['ENABLE_EXPORT_GIT'] = True

View File

@@ -14,7 +14,7 @@ from contentstore.tests.modulestore_config import TEST_MODULESTORE
from django_comment_common.utils import are_permissions_roles_seeded
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
@override_settings(MODULESTORE=TEST_MODULESTORE)

View File

@@ -11,7 +11,7 @@ from contentstore.tests.modulestore_config import TEST_MODULESTORE
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.django import modulestore, clear_existing_modulestores
from xmodule.modulestore.locator import CourseLocator
from opaque_keys.edx.locator import CourseLocator
# pylint: disable=E1101

View File

@@ -33,8 +33,8 @@ from xmodule.modulestore import mongo
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore.inheritance import own_metadata
from xmodule.modulestore.keys import UsageKey
from xmodule.modulestore.locations import SlashSeparatedCourseKey, AssetLocation
from opaque_keys.edx.keys import UsageKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey, AssetLocation
from xmodule.modulestore.store_utilities import clone_course, delete_course
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory

View File

@@ -16,7 +16,7 @@ from student.roles import CourseInstructorRole, CourseStaffRole
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
TOTAL_COURSES_COUNT = 500
USER_COURSES_COUNT = 50

View File

@@ -6,7 +6,7 @@ from xmodule.course_module import CourseDescriptor
from xmodule.modulestore.django import modulestore, loc_mapper, clear_existing_modulestores
from xmodule.seq_module import SequenceDescriptor
from xmodule.capa_module import CapaDescriptor
from xmodule.modulestore.locator import BlockUsageLocator, LocalId
from opaque_keys.edx.locator import BlockUsageLocator, LocalId
from xmodule.modulestore.exceptions import ItemNotFoundError, DuplicateCourseError
from xmodule.html_module import HtmlDescriptor
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase

View File

@@ -17,7 +17,7 @@ from contentstore.tests.modulestore_config import TEST_MODULESTORE
from xmodule.modulestore.django import modulestore
from xmodule.contentstore.django import contentstore
from xmodule.modulestore.locations import SlashSeparatedCourseKey, AssetLocation
from opaque_keys.edx.locations import SlashSeparatedCourseKey, AssetLocation
from xmodule.modulestore.xml_importer import import_from_xml
from xmodule.contentstore.content import StaticContent
from xmodule.contentstore.django import _CONTENTSTORE

View File

@@ -9,7 +9,7 @@ from django.contrib.auth.models import User
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from contentstore.tests.modulestore_config import TEST_MODULESTORE
from contentstore.tests.utils import AjaxEnabledTestClient
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from contentstore.utils import reverse_url, reverse_course_url
from student.roles import CourseInstructorRole, CourseStaffRole
from contentstore.views.access import has_course_access

View File

@@ -7,7 +7,7 @@ from contentstore.utils import delete_course_and_groups, reverse_url
from courseware.tests.factories import UserFactory
from xmodule.modulestore import Location
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from student.models import CourseEnrollment

View File

@@ -8,7 +8,7 @@ from django.test.utils import override_settings
from contentstore import utils
from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
class LMSLinksTestCase(TestCase):

View File

@@ -12,7 +12,7 @@ from xmodule.contentstore.content import StaticContent
from xmodule.contentstore.django import contentstore
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore.locations import SlashSeparatedCourseKey, Location
from opaque_keys.edx.locations import SlashSeparatedCourseKey, Location
from xmodule.modulestore.store_utilities import delete_course
from student.roles import CourseInstructorRole, CourseStaffRole

View File

@@ -19,7 +19,7 @@ from xmodule.modulestore.django import modulestore
from xmodule.contentstore.content import StaticContent
from xmodule.exceptions import NotFoundError
from django.core.exceptions import PermissionDenied
from xmodule.modulestore.keys import CourseKey, AssetKey
from opaque_keys.edx.keys import CourseKey, AssetKey
from util.date_utils import get_default_time_display
from util.json_request import JsonResponse

View File

@@ -9,7 +9,7 @@ from django_future.csrf import ensure_csrf_cookie
from edxmako.shortcuts import render_to_response
from django.http import HttpResponseNotFound
from django.core.exceptions import PermissionDenied
from xmodule.modulestore.keys import CourseKey
from opaque_keys.edx.keys import CourseKey
from xmodule.modulestore.django import modulestore
from contentstore.utils import get_modulestore, reverse_course_url

View File

@@ -25,7 +25,7 @@ from contentstore.utils import get_lms_link_for_item, compute_publish_state, Pub
from contentstore.views.helpers import get_parent_xblock
from models.settings.course_grading import CourseGradingModel
from xmodule.modulestore.keys import UsageKey
from opaque_keys.edx.keys import UsageKey
from .access import has_course_access
from django.utils.translation import ugettext as _

View File

@@ -23,7 +23,7 @@ from xmodule.tabs import PDFTextbookTabs
from xmodule.modulestore.exceptions import ItemNotFoundError, InvalidLocationError
from opaque_keys import InvalidKeyError
from xmodule.modulestore.locations import Location, SlashSeparatedCourseKey
from opaque_keys.edx.locations import Location, SlashSeparatedCourseKey
from contentstore.course_info_model import get_course_updates, update_course_updates, delete_course_update
from contentstore.utils import (
@@ -53,7 +53,7 @@ from django_comment_common.utils import seed_permissions_roles
from student.models import CourseEnrollment
from student.roles import CourseRole, UserBasedRole
from xmodule.modulestore.keys import CourseKey
from opaque_keys.edx.keys import CourseKey
from course_creators.views import get_course_creator_status, add_user_with_status_unrequested
from contentstore import utils
from student.roles import CourseInstructorRole, CourseStaffRole, CourseCreatorRole, GlobalStaff

View File

@@ -14,7 +14,7 @@ from .access import has_course_access
import contentstore.git_export_utils as git_export_utils
from edxmako.shortcuts import render_to_response
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.keys import CourseKey
from opaque_keys.edx.keys import CourseKey
log = logging.getLogger(__name__)

View File

@@ -24,7 +24,7 @@ from edxmako.shortcuts import render_to_response
from xmodule.contentstore.django import contentstore
from xmodule.exceptions import SerializationError
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.keys import CourseKey
from opaque_keys.edx.keys import CourseKey
from xmodule.modulestore.xml_importer import import_from_xml
from xmodule.modulestore.xml_exporter import export_to_xml

View File

@@ -38,7 +38,7 @@ from contentstore.views.preview import get_preview_fragment
from edxmako.shortcuts import render_to_string
from models.settings.course_grading import CourseGradingModel
from cms.lib.xblock.runtime import handler_url, local_resource_url
from xmodule.modulestore.keys import UsageKey, CourseKey
from opaque_keys.edx.keys import UsageKey, CourseKey
__all__ = ['orphan_handler', 'xblock_handler', 'xblock_view_handler']

View File

@@ -13,7 +13,7 @@ from xmodule_modifiers import replace_static_urls, wrap_xblock, wrap_fragment
from xmodule.error_module import ErrorDescriptor
from xmodule.exceptions import NotFoundError, ProcessingError
from xmodule.modulestore.django import modulestore, ModuleI18nService
from xmodule.modulestore.keys import UsageKey
from opaque_keys.edx.keys import UsageKey
from xmodule.x_module import ModuleSystem
from xblock.runtime import KvsFieldData
from xblock.django.request import webob_to_django_response, django_to_webob_request

View File

@@ -13,7 +13,7 @@ from django.views.decorators.http import require_http_methods
from edxmako.shortcuts import render_to_response
from xmodule.modulestore.django import modulestore
from xmodule.tabs import CourseTabList, StaticTab, CourseTab, InvalidTabsException
from xmodule.modulestore.keys import CourseKey, UsageKey
from opaque_keys.edx.keys import CourseKey, UsageKey
from ..utils import get_lms_link_for_item

View File

@@ -8,7 +8,7 @@ from student.roles import CourseInstructorRole, CourseStaffRole
from student.tests.factories import AdminFactory
from student.auth import add_users
from contentstore.views.access import get_user_role
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
class RolesTest(TestCase):

View File

@@ -18,7 +18,7 @@ from xmodule.contentstore.django import contentstore
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.xml_importer import import_from_xml
from django.test.utils import override_settings
from xmodule.modulestore.locations import SlashSeparatedCourseKey, AssetLocation
from opaque_keys.edx.locations import SlashSeparatedCourseKey, AssetLocation
class AssetsTestCase(CourseTestCase):

View File

@@ -7,7 +7,7 @@ import lxml
from contentstore.tests.utils import CourseTestCase
from contentstore.utils import reverse_course_url
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
from xmodule.modulestore.locator import Locator
from opaque_keys.edx.locator import Locator
class TestCourseIndex(CourseTestCase):

View File

@@ -5,7 +5,7 @@ import json
from contentstore.tests.test_course_settings import CourseTestCase
from contentstore.utils import reverse_course_url, reverse_usage_url
from xmodule.modulestore.locations import Location, SlashSeparatedCourseKey
from opaque_keys.edx.locations import Location, SlashSeparatedCourseKey
from xmodule.modulestore.django import modulestore

View File

@@ -22,8 +22,8 @@ from student.tests.factories import UserFactory
from xmodule.capa_module import CapaDescriptor
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore.keys import UsageKey
from xmodule.modulestore.locations import Location
from opaque_keys.edx.keys import UsageKey
from opaque_keys.edx.locations import Location
class ItemTest(CourseTestCase):

View File

@@ -18,7 +18,7 @@ from xmodule.modulestore.django import modulestore
from xmodule.contentstore.django import contentstore, _CONTENTSTORE
from xmodule.contentstore.content import StaticContent
from xmodule.exceptions import NotFoundError
from xmodule.modulestore.keys import UsageKey
from opaque_keys.edx.keys import UsageKey
from xmodule.video_module import transcripts_utils
from contentstore.tests.modulestore_config import TEST_MODULESTORE

View File

@@ -22,7 +22,7 @@ from opaque_keys import InvalidKeyError
from xmodule.contentstore.content import StaticContent
from xmodule.exceptions import NotFoundError
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.keys import UsageKey
from opaque_keys.edx.keys import UsageKey
from xmodule.contentstore.django import contentstore
from xmodule.modulestore.exceptions import ItemNotFoundError

View File

@@ -8,7 +8,7 @@ from django_future.csrf import ensure_csrf_cookie
from edxmako.shortcuts import render_to_response
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.keys import CourseKey
from opaque_keys.edx.keys import CourseKey
from util.json_request import JsonResponse, expect_json
from student.roles import CourseInstructorRole, CourseStaffRole
from course_creators.views import user_requested_access

View File

@@ -17,7 +17,7 @@ from student.models import CourseEnrollment
from xmodule.contentstore.django import contentstore, _CONTENTSTORE
from xmodule.contentstore.content import StaticContent
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from xmodule.modulestore.tests.django_utils import (studio_store_config,
ModuleStoreTestCase)
from xmodule.modulestore.xml_importer import import_from_xml

View File

@@ -9,7 +9,7 @@ from course_groups.cohorts import (get_cohort, get_course_cohorts,
is_commentable_cohorted, get_cohort_by_name)
from xmodule.modulestore.django import modulestore, clear_existing_modulestores
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from xmodule.modulestore.tests.django_utils import mixed_store_config

View File

@@ -8,7 +8,7 @@ import json
import logging
import re
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from courseware.courses import get_course_with_access
from edxmako.shortcuts import render_to_response

View File

@@ -4,8 +4,8 @@ from django import forms
from opaque_keys import InvalidKeyError
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.keys import CourseKey
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
class CourseModeForm(forms.ModelForm):

View File

@@ -8,7 +8,7 @@ Replace this with more appropriate tests for your application.
from datetime import datetime, timedelta
import pytz
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from django.test import TestCase
from course_modes.models import CourseMode, Mode

View File

@@ -20,7 +20,7 @@ from courseware.access import has_access
from student.models import CourseEnrollment
from student.views import course_from_id
from verify_student.models import SoftwareSecurePhotoVerification
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
class ChooseModeView(View):

View File

@@ -1,6 +1,6 @@
from django.test import TestCase
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from django_comment_common.models import Role
from student.models import CourseEnrollment, User
@@ -37,7 +37,7 @@ class RoleAssignmentTest(TestCase):
# The following was written on the assumption that unenrolling from a course
# should remove all forum Roles for that student for that course. This is
# not necessarily the case -- please see comments at the top of
# not necessarily the case -- please see comments at the top of
# django_comment_client.models.assign_default_role(). Leaving it for the
# forums team to sort out.
#

View File

@@ -11,8 +11,8 @@ import ipaddr
from xmodule.modulestore.django import modulestore
from opaque_keys import InvalidKeyError
from xmodule.modulestore.keys import CourseKey
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
class EmbargoedCourseForm(forms.ModelForm): # pylint: disable=incomplete-protocol

View File

@@ -1,7 +1,7 @@
"""Test of models for embargo middleware app"""
from django.test import TestCase
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from embargo.models import EmbargoedCourse, EmbargoedState, IPFilter

View File

@@ -19,7 +19,7 @@ from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, mixed_store_config
from xmodule.modulestore.inheritance import own_metadata
from xmodule.modulestore.django import editable_modulestore
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from external_auth.models import ExternalAuthMap
from external_auth.views import shib_login, course_specific_login, course_specific_register, _flatten_to_ascii

View File

@@ -207,7 +207,7 @@ class SSLClientTest(ModuleStoreTestCase):
# Expect an InvalidKeyError from course page as we don't have anything else built
with self.assertRaisesRegexp(
InvalidKeyError,
"<class 'xmodule.modulestore.keys.CourseKey'>: None"
"<class 'opaque_keys.edx.keys.CourseKey'>: None"
):
self.client.get(
reverse('signup'), follow=True,
@@ -219,7 +219,7 @@ class SSLClientTest(ModuleStoreTestCase):
# Now that we are logged in, make sure we don't see the registration page
with self.assertRaisesRegexp(
InvalidKeyError,
"<class 'xmodule.modulestore.keys.CourseKey'>: None"
"<class 'opaque_keys.edx.keys.CourseKey'>: None"
):
self.client.get(reverse('signup'), follow=True)

View File

@@ -5,7 +5,7 @@ from reverification.models import MidcourseReverificationWindow
from factory.django import DjangoModelFactory
import pytz
from datetime import timedelta, datetime
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
# Factories don't have __init__ methods, and are self documenting

View File

@@ -5,7 +5,7 @@ from static_replace import (replace_static_urls, replace_course_urls,
_url_replace_regex)
from mock import patch, Mock
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from xmodule.modulestore.mongo import MongoModuleStore
from xmodule.modulestore.xml import XMLModuleStore

View File

@@ -14,7 +14,7 @@ from django.contrib.auth.models import User
from django.core.management.base import BaseCommand, CommandError
from student.models import anonymous_id_for_user
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
class Command(BaseCommand):

View File

@@ -3,8 +3,8 @@ from opaque_keys import InvalidKeyError
from optparse import make_option
from student.models import CourseEnrollment, User
from xmodule.modulestore.keys import CourseKey
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
class Command(BaseCommand):

View File

@@ -4,8 +4,8 @@ A script to create some dummy users
from django.core.management.base import BaseCommand
from student.models import CourseEnrollment
from opaque_keys import InvalidKeyError
from xmodule.modulestore.keys import CourseKey
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from student.views import _do_create_account, get_random_post_override

View File

@@ -6,8 +6,8 @@ from django.core.management.base import BaseCommand
from django.utils import translation
from opaque_keys import InvalidKeyError
from xmodule.modulestore.keys import CourseKey
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from student.models import CourseEnrollment, Registration, create_comments_service_user
from student.views import _do_create_account, AccountValidationError
from track.management.tracked_command import TrackedCommand

View File

@@ -8,8 +8,8 @@ from django.test.client import RequestFactory
from django.core.management.base import BaseCommand, CommandError
import os
from opaque_keys import InvalidKeyError
from xmodule.modulestore.keys import CourseKey
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from django.contrib.auth.models import User
from optparse import make_option
import datetime

View File

@@ -3,7 +3,7 @@ from django.core.management.base import BaseCommand
from django.contrib.auth.models import User
from student.models import CourseEnrollment
from shoppingcart.models import CertificateItem
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
class Command(BaseCommand):

View File

@@ -4,7 +4,7 @@ from south.v2 import DataMigration
from django.db import models
from xmodule.modulestore.django import loc_mapper
import re
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from opaque_keys import InvalidKeyError
import bson.son
import logging

View File

@@ -2,7 +2,7 @@
from south.v2 import DataMigration
from xmodule.modulestore.django import loc_mapper, modulestore
import re
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from opaque_keys import InvalidKeyError
import logging
from django.db.models.query_utils import Q

View File

@@ -34,13 +34,13 @@ from track import contexts
from eventtracking import tracker
from importlib import import_module
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from course_modes.models import CourseMode
import lms.lib.comment_client as cc
from util.query import use_read_replica_if_available
from xmodule_django.models import CourseKeyField, NoneToEmptyManager
from xmodule.modulestore.keys import CourseKey
from opaque_keys.edx.keys import CourseKey
from functools import total_ordering
unenroll_done = Signal(providing_args=["course_enrollment"])

View File

@@ -10,7 +10,7 @@ from django.core.exceptions import PermissionDenied
from student.roles import CourseInstructorRole, CourseStaffRole, CourseCreatorRole
from student.tests.factories import AdminFactory
from student.auth import has_access, add_users, remove_users
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
class CreatorGroupTest(TestCase):

View File

@@ -6,7 +6,7 @@ from django_comment_common.models import (
from django_comment_common.utils import seed_permissions_roles
from student.models import CourseEnrollment, UserProfile
from util.testing import UrlResetMixin
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from mock import patch

View File

@@ -15,7 +15,7 @@ from student.tests.factories import UserFactory, CourseEnrollmentFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from bulk_email.models import CourseAuthorization

View File

@@ -20,7 +20,7 @@ from xmodule.modulestore.inheritance import own_metadata
from xmodule.modulestore.django import editable_modulestore
from external_auth.models import ExternalAuthMap
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
TEST_DATA_MIXED_MODULESTORE = mixed_store_config(settings.COMMON_TEST_DATA_ROOT, {})

View File

@@ -9,7 +9,7 @@ from student.tests.factories import AnonymousUserFactory
from student.roles import GlobalStaff, CourseRole, CourseStaffRole, OrgStaffRole, OrgInstructorRole, \
CourseInstructorRole
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
class RolesTestCase(TestCase):

View File

@@ -21,7 +21,7 @@ from unittest.case import SkipTest
from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from courseware.tests.tests import TEST_DATA_MIXED_MODULESTORE
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from mock import Mock, patch

View File

@@ -52,7 +52,7 @@ from dark_lang.models import DarkLangConfig
from xmodule.course_module import CourseDescriptor
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from xmodule.modulestore import XML_MODULESTORE_TYPE, Location
from collections import namedtuple

View File

@@ -21,7 +21,7 @@ from .course_helpers import *
from .ui_helpers import *
from nose.tools import assert_equals # pylint: disable=E0611
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from logging import getLogger
logger = getLogger(__name__)

View File

@@ -1,7 +1,7 @@
"""Generates common contexts"""
import logging
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from opaque_keys import InvalidKeyError
from util.request import COURSE_REGEX

View File

@@ -5,7 +5,7 @@ Adds user's tags to tracking event context.
from track.contexts import COURSE_REGEX
from eventtracking import tracker
from user_api.models import UserCourseTag
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
class UserTagsEventContextMiddleware(object):

View File

@@ -3,7 +3,7 @@ from factory.django import DjangoModelFactory
from factory import SubFactory
from student.tests.factories import UserFactory
from user_api.models import UserPreference, UserCourseTag
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
# Factories don't have __init__ methods, and are self documenting
# pylint: disable=W0232, C0111

View File

@@ -5,7 +5,7 @@ from django.test import TestCase
from student.tests.factories import UserFactory
from user_api import user_service
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
class TestUserService(TestCase):

View File

@@ -9,7 +9,7 @@ from unittest import SkipTest
from user_api.models import UserPreference
from user_api.tests.factories import UserPreferenceFactory
from django_comment_common import models
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
TEST_API_KEY = "test_api_key"

View File

@@ -11,7 +11,7 @@ from rest_framework.response import Response
from user_api.serializers import UserSerializer, UserPreferenceSerializer
from user_api.models import UserPreference
from django_comment_common.models import Role
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
class ApiKeyHeaderPermission(permissions.BasePermission):

View File

@@ -3,7 +3,7 @@ import re
from django.conf import settings
from microsite_configuration import microsite
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
COURSE_REGEX = re.compile(r'^.*?/courses/(?P<course_id>[^/]+/[^/]+/[^/]+)')

View File

@@ -5,7 +5,7 @@ Tests for sandboxing.py in util app
from django.test import TestCase
from util.sandboxing import can_execute_unsafe_code
from django.test.utils import override_settings
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
class SandboxingTest(TestCase):

View File

@@ -1,6 +1,6 @@
from django.db import models
from django.core.exceptions import ValidationError
from xmodule.modulestore.locations import SlashSeparatedCourseKey, Location
from opaque_keys.edx.locations import SlashSeparatedCourseKey, Location
from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^xmodule_django\.models\.CourseKeyField"])

View File

@@ -55,6 +55,7 @@ setup(
'capa',
'path.py',
'webob',
'opaque-keys',
],
package_data={
'xmodule': ['js/module/*'],
@@ -68,19 +69,5 @@ setup(
'console_scripts': [
'xmodule_assets = xmodule.static_content:main',
],
'course_key': [
'slashes = xmodule.modulestore.locations:SlashSeparatedCourseKey',
'course-locator = xmodule.modulestore.locator:CourseLocator',
],
'usage_key': [
'location = xmodule.modulestore.locations:Location',
'edx = xmodule.modulestore.locator:BlockUsageLocator',
],
'asset_key': [
'asset-location = xmodule.modulestore.locations:AssetLocation',
],
'definition_key': [
'defx = xmodule.modulestore.locator:DefinitionLocator',
],
},
)

View File

@@ -10,7 +10,7 @@ import StringIO
from urlparse import urlparse, urlunparse, parse_qsl
from urllib import urlencode
from xmodule.modulestore.locations import AssetLocation, SlashSeparatedCourseKey
from opaque_keys.edx.locations import AssetLocation, SlashSeparatedCourseKey
from .django import contentstore
from PIL import Image

View File

@@ -13,7 +13,7 @@ from fs.osfs import OSFS
import os
import json
import bson.son
from xmodule.modulestore.locations import AssetLocation
from opaque_keys.edx.locations import AssetLocation
class MongoContentStore(ContentStore):

View File

@@ -17,7 +17,7 @@ import json
from xblock.fields import Scope, List, String, Dict, Boolean, Integer
from .fields import Date
from xmodule.modulestore.locator import CourseLocator
from opaque_keys.edx.locator import CourseLocator
from django.utils.timezone import UTC
log = logging.getLogger(__name__)

View File

@@ -14,10 +14,10 @@ from xblock.plugin import default_select
from .exceptions import InvalidLocationError, InsufficientSpecificationError
from xmodule.errortracker import make_error_tracker
from xmodule.modulestore.keys import CourseKey, UsageKey
from xmodule.modulestore.locations import Location # For import backwards compatibility
from opaque_keys.edx.keys import CourseKey, UsageKey
from opaque_keys.edx.locations import Location # For import backwards compatibility
from opaque_keys import InvalidKeyError
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from xblock.runtime import Mixologist
from xblock.core import XBlock
import datetime

View File

@@ -1,157 +0,0 @@
"""
OpaqueKey abstract classes for edx-platform object types (courses, definitions, usages, and assets).
"""
from abc import abstractmethod, abstractproperty
from opaque_keys import OpaqueKey
from xblock.runtime import IdReader
class CourseKey(OpaqueKey):
"""
An :class:`opaque_keys.OpaqueKey` identifying a particular Course object.
"""
KEY_TYPE = 'course_key'
__slots__ = ()
@abstractproperty
def org(self):
"""
The organization that this course belongs to.
"""
raise NotImplementedError()
@abstractproperty
def offering(self):
"""
The offering identifier for this course.
This is complement of the org; in old-style IDs, "course/run"
"""
raise NotImplementedError()
@abstractmethod
def make_usage_key(self, block_type, block_id):
"""
Return a usage key, given the given the specified block_type and block_id.
This function should not actually create any new ids, but should simply
return one that already exists.
"""
raise NotImplementedError()
@abstractmethod
def make_asset_key(self, asset_type, path):
"""
Return an asset key, given the given the specified path.
This function should not actually create any new ids, but should simply
return one that already exists.
"""
raise NotImplementedError()
class DefinitionKey(OpaqueKey):
"""
An :class:`opaque_keys.OpaqueKey` identifying an XBlock definition.
"""
KEY_TYPE = 'definition_key'
__slots__ = ()
@abstractproperty
def block_type(self):
"""
The XBlock type of this definition.
"""
raise NotImplementedError()
class CourseObjectMixin(object):
"""
An abstract :class:`opaque_keys.OpaqueKey` mixin
for keys that belong to courses.
"""
__slots__ = ()
@abstractproperty
def course_key(self):
"""
Return the :class:`CourseKey` for the course containing this usage.
"""
raise NotImplementedError()
@abstractmethod
def map_into_course(self, course_key):
"""
Return a new :class:`UsageKey` or :class:`AssetKey` representing this usage inside the
course identified by the supplied :class:`CourseKey`. It returns the same type as
`self`
Args:
course_key (:class:`CourseKey`): The course to map this object into.
Returns:
A new :class:`CourseObjectMixin` instance.
"""
raise NotImplementedError()
class AssetKey(CourseObjectMixin, OpaqueKey):
"""
An :class:`opaque_keys.OpaqueKey` identifying a course asset.
"""
KEY_TYPE = 'asset_key'
__slots__ = ()
@abstractproperty
def path(self):
"""
Return the path for this asset.
"""
raise NotImplementedError()
class UsageKey(CourseObjectMixin, OpaqueKey):
"""
An :class:`opaque_keys.OpaqueKey` identifying an XBlock usage.
"""
KEY_TYPE = 'usage_key'
__slots__ = ()
@abstractproperty
def definition_key(self):
"""
Return the :class:`DefinitionKey` for the XBlock containing this usage.
"""
raise NotImplementedError()
@property
def block_type(self):
return self.category
class OpaqueKeyReader(IdReader):
"""
IdReader for :class:`DefinitionKey` and :class:`UsageKey`s.
"""
def get_definition_id(self, usage_id):
"""Retrieve the definition that a usage is derived from.
Args:
usage_id: The id of the usage to query
Returns:
The `definition_id` the usage is derived from
"""
return usage_id.definition_key
def get_block_type(self, def_id):
"""Retrieve the block_type of a particular definition
Args:
def_id: The id of the definition to query
Returns:
The `block_type` of the definition
"""
return def_id.block_type

View File

@@ -8,8 +8,8 @@ import bson.son
import urllib
from xmodule.modulestore.exceptions import InvalidLocationError, ItemNotFoundError
from xmodule.modulestore.locator import BlockUsageLocator, CourseLocator
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator
from opaque_keys.edx.locations import SlashSeparatedCourseKey
class LocMapperStore(object):

View File

@@ -1,356 +0,0 @@
"""OpaqueKey implementations used by XML and Mongo modulestores"""
import logging
import re
from bson.son import SON
from opaque_keys import InvalidKeyError, OpaqueKey
from xmodule.modulestore.keys import CourseKey, UsageKey, DefinitionKey, AssetKey
import json
log = logging.getLogger(__name__)
URL_RE = re.compile("""
([^:/]+://?|/[^/]+)
(?P<org>[^/]+)/
(?P<course>[^/]+)/
(?P<category>[^/]+)/
(?P<name>[^@]+)
(@(?P<revision>[^/]+))?
""", re.VERBOSE)
# TODO (cpennington): We should decide whether we want to expand the
# list of valid characters in a location
INVALID_CHARS = re.compile(r"[^\w.%-]", re.UNICODE)
# Names are allowed to have colons.
INVALID_CHARS_NAME = re.compile(r"[^\w.:%-]", re.UNICODE)
# html ids can contain word chars and dashes
INVALID_HTML_CHARS = re.compile(r"[^\w-]", re.UNICODE)
class SlashSeparatedCourseKey(CourseKey):
"""Course key for old style org/course/run course identifiers"""
CANONICAL_NAMESPACE = 'slashes'
KEY_FIELDS = ('org', 'course', 'run')
__slots__ = KEY_FIELDS
def __init__(self, org, course, run):
"""
checks that the values are syntactically valid before creating object
"""
for part in (org, course, run):
LocationBase._check_location_part(part, INVALID_CHARS)
super(SlashSeparatedCourseKey, self).__init__(org, course, run)
@classmethod
def _from_string(cls, serialized):
serialized = serialized.replace("+", "/")
if serialized.count('/') != 2:
raise InvalidKeyError(cls, serialized)
# Turns encoded slashes into actual slashes
return cls(*serialized.split('/'))
def _to_string(self):
# Turns slashes into pluses
return u'+'.join([self.org, self.course, self.run])
@property
def offering(self):
return u'/'.join([self.course, self.run])
def make_asset_key(self, asset_type, path):
return AssetLocation(self.org, self.course, self.run, asset_type, path, None)
def make_usage_key(self, block_type, name):
return Location(self.org, self.course, self.run, block_type, name, None)
def to_deprecated_string(self):
return u'/'.join([self.org, self.course, self.run])
@classmethod
def from_deprecated_string(cls, serialized):
return cls._from_string(serialized)
def make_usage_key_from_deprecated_string(self, location_url):
"""
Temporary mechanism for creating a UsageKey given a CourseKey and a serialized Location. NOTE:
this prejudicially takes the tag, org, and course from the url not self.
Raises:
InvalidKeyError: if the url does not parse
"""
match = URL_RE.match(location_url)
if match is None:
raise InvalidKeyError(Location, location_url)
groups = match.groupdict()
return Location(run=self.run, **groups)
class LocationBase(object):
"""
Encodes a type of Location, which identifies a piece of
content situated in a course.
"""
KEY_FIELDS = ('org', 'course', 'run', 'category', 'name', 'revision')
SERIALIZED_PATTERN = re.compile("""
(?P<org>[^/]+)\+
(?P<course>[^/]+)\+
(?P<run>[^/]+)\+
(?P<category>[^/]+)\+
(?P<name>[^@/]+)
(@(?P<revision>[^/]+))?
""", re.VERBOSE)
@classmethod
def _check_location_part(cls, val, regexp):
"""
Check that `regexp` doesn't match inside `val`. If it does, raise an exception
Args:
val (string): The value to check
regexp (re.RegexObject): The regular expression specifying invalid characters
Raises:
InvalidKeyError: Raised if any invalid character is found in `val`
"""
if val is None:
return
if not isinstance(val, basestring):
raise InvalidKeyError(cls, "{!r} is not a string".format(val))
if regexp.search(val) is not None:
raise InvalidKeyError(cls, "Invalid characters in {!r}.".format(val))
@classmethod
def _clean(cls, value, invalid):
"""
invalid should be a compiled regexp of chars to replace with '_'
"""
return re.sub('_+', '_', invalid.sub('_', value))
@classmethod
def clean(cls, value):
"""
Return value, made into a form legal for locations
"""
return cls._clean(value, INVALID_CHARS)
@classmethod
def clean_keeping_underscores(cls, value):
"""
Return value, replacing INVALID_CHARS, but not collapsing multiple '_' chars.
This for cleaning asset names, as the YouTube ID's may have underscores in them, and we need the
transcript asset name to match. In the future we may want to change the behavior of _clean.
"""
return INVALID_CHARS.sub('_', value)
@classmethod
def clean_for_url_name(cls, value):
"""
Convert value into a format valid for location names (allows colons).
"""
return cls._clean(value, INVALID_CHARS_NAME)
@classmethod
def clean_for_html(cls, value):
"""
Convert a string into a form that's safe for use in html ids, classes, urls, etc.
Replaces all INVALID_HTML_CHARS with '_', collapses multiple '_' chars
"""
return cls._clean(value, INVALID_HTML_CHARS)
def __init__(self, org, course, run, category, name, revision=None):
"""
Create a new Location that is a clone of the specifed one.
Components must be composed of alphanumeric characters, or the
characters '_', '-', and '.'. The name component is additionally allowed to have ':',
which is interpreted specially for xml storage.
Components may be set to None, which may be interpreted in some contexts
to mean wildcard selection.
"""
# check that the values are syntactically valid before creating object
for part in (org, course, run, category, revision):
self._check_location_part(part, INVALID_CHARS)
self._check_location_part(name, INVALID_CHARS_NAME)
# call the OpaqueKey constructor ensuring the args in the same order as KEY_FIELDS above
super(LocationBase, self).__init__(org, course, run, category, name, revision)
@property
def tag(self):
return self.DEPRECATED_TAG
@property
def definition_key(self):
# Locations are both UsageKeys and DefinitionKeys
return self
@property
def block_type(self):
return self.category
@classmethod
def from_deprecated_string(cls, serialized):
match = URL_RE.match(serialized)
if match is None:
raise InvalidKeyError(Location, serialized)
groups = match.groupdict()
return cls(run=None, **groups)
def to_deprecated_string(self):
url = u"{0.DEPRECATED_TAG}://{0.org}/{0.course}/{0.category}/{0.name}".format(self)
if self.revision:
url += u"@{rev}".format(rev=self.revision) # pylint: disable=E1101
return url
def _to_string(self):
output = u"+".join(
unicode(val)
for val in (self.org, self.course, self.run, self.category, self.name)
)
if self.revision:
output += u'@{}'.format(self.revision)
return output
@classmethod
def _from_string(cls, serialized):
match = cls.SERIALIZED_PATTERN.match(serialized)
if not match:
raise InvalidKeyError(cls, serialized)
return cls(**match.groupdict())
def html_id(self):
"""
Return a string with a version of the location that is safe for use in
html id attributes
"""
id_fields = [self.DEPRECATED_TAG, self.org, self.course, self.category, self.name, self.revision]
id_string = u"-".join([v for v in id_fields if v is not None])
return Location.clean_for_html(id_string)
@property
def course_key(self):
return SlashSeparatedCourseKey(self.org, self.course, self.run)
def to_deprecated_son(self, prefix='', tag='i4x'):
"""
Returns a SON object that represents this location
"""
# adding tag b/c deprecated form used it
son = SON({prefix + 'tag': tag})
for field_name in self.KEY_FIELDS:
# Temporary filtering of run field because deprecated form left it out
if field_name != 'run':
son[prefix + field_name] = getattr(self, field_name)
return son
@classmethod
def _from_deprecated_son(cls, id_dict, run):
"""
Return the Location decoding this id_dict and run
"""
return cls(id_dict['org'], id_dict['course'], run, id_dict['category'], id_dict['name'], id_dict['revision'])
class Location(LocationBase, UsageKey, DefinitionKey):
"""
UsageKey and DefinitionKey implementation class for use with
XML and Mongo modulestores.
"""
CANONICAL_NAMESPACE = 'location'
DEPRECATED_TAG = 'i4x'
__slots__ = LocationBase.KEY_FIELDS
def map_into_course(self, course_key):
"""
Return a new :class:`UsageKey` representing this usage inside the
course identified by the supplied :class:`CourseKey`.
Args:
course_key (CourseKey): The course to map this object into.
Returns:
A new :class:`CourseObjectMixin` instance.
"""
return Location(course_key.org, course_key.course, course_key.run, self.category, self.name, self.revision)
class AssetLocation(LocationBase, AssetKey):
"""
An AssetKey implementation class.
"""
CANONICAL_NAMESPACE = 'asset-location'
DEPRECATED_TAG = 'c4x'
__slots__ = LocationBase.KEY_FIELDS
def __init__(self, org, course, run, category, name, revision=None):
super(AssetLocation, self).__init__(org, course, run, category, name, revision)
@property
def path(self):
return self.name
def to_deprecated_string(self):
url = u"/{0.DEPRECATED_TAG}/{0.org}/{0.course}/{0.category}/{0.name}".format(self)
return url
ASSET_URL_RE = re.compile(r"""
/?c4x/
(?P<org>[^/]+)/
(?P<course>[^/]+)/
(?P<category>[^/]+)/
(?P<name>[^/]+)
""", re.VERBOSE | re.IGNORECASE)
@classmethod
def from_deprecated_string(cls, serialized):
match = cls.ASSET_URL_RE.match(serialized)
if match is None:
raise InvalidKeyError(Location, serialized)
groups = match.groupdict()
return cls(run=None, **groups)
def map_into_course(self, course_key):
"""
Return a new :class:`UsageKey` representing this usage inside the
course identified by the supplied :class:`CourseKey`.
Args:
course_key (CourseKey): The course to map this object into.
Returns:
A new :class:`CourseObjectMixin` instance.
"""
return AssetLocation(course_key.org, course_key.course, course_key.run, self.category, self.name, self.revision)
def to_deprecated_list_repr(self):
"""
Thumbnail locations are stored as lists [c4x, org, course, thumbnail, path, None] in contentstore.mongo
That should be the only use of this method, but the method is general enough to provide the pre-opaque
Location fields as an array in the old order with the tag.
"""
return ['c4x', self.org, self.course, self.block_type, self.name, None]
class i4xEncoder(json.JSONEncoder):
"""
If provided as the cls to json.dumps, will serialize and Locations as i4x strings and other
keys using the unicode strings.
"""
def default(self, key):
if isinstance(key, OpaqueKey):
if isinstance(key, (LocationBase, SlashSeparatedCourseKey)):
return key.to_deprecated_string()
else:
return unicode(key)
super(i4xEncoder, self).default(key)

View File

@@ -13,7 +13,7 @@ from bson.errors import InvalidId
from opaque_keys import OpaqueKey, InvalidKeyError
from xmodule.modulestore.keys import CourseKey, UsageKey, DefinitionKey
from opaque_keys.edx.keys import CourseKey, UsageKey, DefinitionKey
log = logging.getLogger(__name__)

View File

@@ -12,12 +12,12 @@ from opaque_keys import InvalidKeyError
from . import ModuleStoreWriteBase
from xmodule.modulestore.django import create_modulestore_instance, loc_mapper
from xmodule.modulestore import Location, XML_MODULESTORE_TYPE
from xmodule.modulestore.locator import CourseLocator, Locator, BlockUsageLocator
from opaque_keys.edx.locator import CourseLocator, Locator, BlockUsageLocator
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore.keys import CourseKey, UsageKey
from opaque_keys.edx.keys import CourseKey, UsageKey
from xmodule.modulestore.mongo.base import MongoModuleStore
from xmodule.modulestore.split_mongo.split import SplitMongoModuleStore
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
log = logging.getLogger(__name__)

View File

@@ -36,7 +36,7 @@ from xmodule.modulestore.exceptions import ItemNotFoundError, InvalidLocationErr
from xmodule.modulestore.inheritance import own_metadata, InheritanceMixin, inherit_metadata, InheritanceKeyValueStore
from xmodule.tabs import StaticTab, CourseTabList
from xblock.core import XBlock
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
log = logging.getLogger(__name__)

View File

@@ -13,7 +13,7 @@ from pytz import UTC
from xmodule.exceptions import InvalidVersionError
from xmodule.modulestore.exceptions import ItemNotFoundError, DuplicateItemError
from xmodule.modulestore.mongo.base import MongoModuleStore
from xmodule.modulestore.locations import Location
from opaque_keys.edx.locations import Location
DRAFT = 'draft'
# Things w/ these categories should never be marked as version='draft'

View File

@@ -2,9 +2,9 @@
Custom field types for mongoengine
"""
import mongoengine
from xmodule.modulestore.locations import SlashSeparatedCourseKey, Location
from opaque_keys.edx.locations import SlashSeparatedCourseKey, Location
from types import NoneType
from xmodule.modulestore.keys import CourseKey
from opaque_keys.edx.keys import CourseKey
class CourseKeyField(mongoengine.StringField):

View File

@@ -1,7 +1,7 @@
import sys
import logging
from xmodule.mako_module import MakoDescriptorSystem
from xmodule.modulestore.locator import BlockUsageLocator, LocalId, CourseLocator
from opaque_keys.edx.locator import BlockUsageLocator, LocalId, CourseLocator
from xmodule.error_module import ErrorDescriptor
from xmodule.errortracker import exc_info_to_str
from xblock.runtime import KvsFieldData

View File

@@ -1,4 +1,4 @@
from xmodule.modulestore.locator import DefinitionLocator
from opaque_keys.edx.locator import DefinitionLocator
class DefinitionLazyLoader(object):

View File

@@ -54,7 +54,7 @@ import copy
from pytz import UTC
from xmodule.errortracker import null_error_tracker
from xmodule.modulestore.locator import (
from opaque_keys.edx.locator import (
BlockUsageLocator, DefinitionLocator, CourseLocator, VersionTree,
LocalId, Locator
)

View File

@@ -3,7 +3,7 @@ from factory.containers import CyclicDefinitionError
from uuid import uuid4
from xmodule.modulestore import prefer_xmodules
from xmodule.modulestore.locations import Location
from opaque_keys.edx.locations import Location
from xblock.core import XBlock

View File

@@ -1,197 +0,0 @@
"""
Thorough tests of the Location class
"""
import ddt
from unittest import TestCase
from opaque_keys import InvalidKeyError
from xmodule.modulestore.locations import Location, AssetLocation, SlashSeparatedCourseKey
# Pairs for testing the clean* functions.
# The first item in the tuple is the input string.
# The second item in the tuple is what the result of
# replacement should be.
GENERAL_PAIRS = [
('', ''),
(' ', '_'),
('abc,', 'abc_'),
('ab fg!@//\\aj', 'ab_fg_aj'),
(u"ab\xA9", "ab_"), # no unicode allowed for now
]
@ddt.ddt
class TestLocations(TestCase):
"""
Tests of :class:`.Location`
"""
@ddt.data(
"org+course+run+category+name",
"org+course+run+category+name@revision"
)
def test_string_roundtrip(self, url):
self.assertEquals(url, Location._from_string(url)._to_string()) # pylint: disable=protected-access
@ddt.data(
"i4x://org/course/category/name",
"i4x://org/course/category/name@revision"
)
def test_deprecated_roundtrip(self, url):
course_id = SlashSeparatedCourseKey('org', 'course', 'run')
self.assertEquals(
url,
course_id.make_usage_key_from_deprecated_string(url).to_deprecated_string()
)
def test_invalid_chars_ssck(self):
"""
Test that the ssck constructor fails if given invalid chars
"""
valid_base = SlashSeparatedCourseKey(u'org.dept-1%2', u'course.sub-2%3', u'run.faster-4%5')
for key in SlashSeparatedCourseKey.KEY_FIELDS:
with self.assertRaises(InvalidKeyError):
# this ends up calling the constructor where the legality check should occur
valid_base.replace(**{key: u'funny thing'})
def test_invalid_chars_location(self):
"""
Test that the location constructor fails if given invalid chars
"""
course_key = SlashSeparatedCourseKey(u'org.dept-1%2', u'course.sub-2%3', u'run.faster-4%5')
valid_base = course_key.make_usage_key('tomato-again%9', 'block-head:sub-4%9')
for key in SlashSeparatedCourseKey.KEY_FIELDS:
with self.assertRaises(InvalidKeyError):
# this ends up calling the constructor where the legality check should occur
valid_base.replace(**{key: u'funny thing'})
@ddt.data(
((), {
'org': 'org',
'course': 'course',
'run': 'run',
'category': 'category',
'name': 'name',
}, 'org', 'course', 'run', 'category', 'name', None),
((), {
'org': 'org',
'course': 'course',
'run': 'run',
'category': 'category',
'name': 'name:more_name',
}, 'org', 'course', 'run', 'category', 'name:more_name', None),
(['org', 'course', 'run', 'category', 'name'], {}, 'org', 'course', 'run', 'category', 'name', None),
)
@ddt.unpack
def test_valid_locations(self, args, kwargs, org, course, run, category, name, revision):
location = Location(*args, **kwargs)
self.assertEquals(org, location.org)
self.assertEquals(course, location.course)
self.assertEquals(run, location.run)
self.assertEquals(category, location.category)
self.assertEquals(name, location.name)
self.assertEquals(revision, location.revision)
@ddt.data(
(("foo",), {}),
(["foo", "bar"], {}),
(["foo", "bar", "baz", "blat/blat", "foo"], {}),
(["foo", "bar", "baz", "blat", "foo/bar"], {}),
(["foo", "bar", "baz", "blat:blat", "foo:bar"], {}), # ':' ok in name, not in category
(('org', 'course', 'run', 'category', 'name with spaces', 'revision'), {}),
(('org', 'course', 'run', 'category', 'name/with/slashes', 'revision'), {}),
(('org', 'course', 'run', 'category', 'name', u'\xae'), {}),
(('org', 'course', 'run', 'category', u'\xae', 'revision'), {}),
((), {
'tag': 'tag',
'course': 'course',
'category': 'category',
'name': 'name@more_name',
'org': 'org'
}),
((), {
'tag': 'tag',
'course': 'course',
'category': 'category',
'name': 'name ', # extra space
'org': 'org'
}),
)
@ddt.unpack
def test_invalid_locations(self, *args, **kwargs):
with self.assertRaises(TypeError):
Location(*args, **kwargs)
def test_equality(self):
self.assertEquals(
Location('tag', 'org', 'course', 'run', 'category', 'name'),
Location('tag', 'org', 'course', 'run', 'category', 'name')
)
self.assertNotEquals(
Location('tag', 'org', 'course', 'run', 'category', 'name1'),
Location('tag', 'org', 'course', 'run', 'category', 'name')
)
@ddt.data(
('a:b', 'a_b'), # no colons in non-name components
('a-b', 'a-b'), # dashes ok
('a.b', 'a.b'), # dot ok
*GENERAL_PAIRS
)
def test_clean(self, pair):
self.assertEquals(Location.clean(pair[0]), pair[1])
@ddt.data(
('a:b', 'a:b'), # colons ok in names
('a-b', 'a-b'), # dashes ok in names
('a.b', 'a.b'), # dot ok in names
*GENERAL_PAIRS
)
def test_clean_for_url_name(self, pair):
self.assertEquals(Location.clean_for_url_name(pair[0]), pair[1])
@ddt.data(
("a:b", "a_b"), # no colons for html use
("a-b", "a-b"), # dashes ok (though need to be replaced in various use locations. ugh.)
('a.b', 'a_b'), # no dots.
*GENERAL_PAIRS
)
def test_clean_for_html(self, pair):
self.assertEquals(Location.clean_for_html(pair[0]), pair[1])
def test_html_id(self):
loc = Location('org', 'course', 'run', 'cat', 'name:more_name', 'rev')
self.assertEquals(loc.html_id(), "i4x-org-course-cat-name_more_name-rev")
def test_replacement(self):
# pylint: disable=protected-access
self.assertEquals(
Location('o', 'c', 'r', 'c', 'n', 'r').replace(name='new_name'),
Location('o', 'c', 'r', 'c', 'new_name', 'r'),
)
with self.assertRaises(InvalidKeyError):
Location('o', 'c', 'r', 'c', 'n', 'r').replace(name=u'name\xae')
@ddt.data('org', 'course', 'category', 'name', 'revision')
def test_immutable(self, attr):
loc = Location('o', 'c', 'r', 'c', 'n', 'r')
with self.assertRaises(AttributeError):
setattr(loc, attr, attr)
def test_map_into_course_location(self):
loc = Location('org', 'course', 'run', 'cat', 'name:more_name', 'rev')
course_key = SlashSeparatedCourseKey("edX", "toy", "2012_Fall")
self.assertEquals(
Location("edX", "toy", "2012_Fall", 'cat', 'name:more_name', 'rev'),
loc.map_into_course(course_key)
)
def test_map_into_course_asset_location(self):
loc = AssetLocation('org', 'course', 'run', 'asset', 'foo.bar')
course_key = SlashSeparatedCourseKey("edX", "toy", "2012_Fall")
self.assertEquals(
AssetLocation("edX", "toy", "2012_Fall", 'asset', 'foo.bar'),
loc.map_into_course(course_key)
)

View File

@@ -4,11 +4,11 @@ Test the loc mapper store
import unittest
import uuid
from xmodule.modulestore import Location
from xmodule.modulestore.locator import BlockUsageLocator, CourseLocator
from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator
from xmodule.modulestore.exceptions import ItemNotFoundError, InvalidLocationError
from xmodule.modulestore.loc_mapper_store import LocMapperStore
from mock import Mock
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
import bson.son

View File

@@ -1,14 +1,14 @@
"""
Tests for xmodule.modulestore.locator.
Tests for opaque_keys.edx.locator.
"""
from unittest import TestCase
import random
from bson.objectid import ObjectId
from opaque_keys import InvalidKeyError
from xmodule.modulestore.locator import Locator, CourseLocator, BlockUsageLocator, DefinitionLocator
from opaque_keys.edx.locator import Locator, CourseLocator, BlockUsageLocator, DefinitionLocator
from ddt import ddt, data
from xmodule.modulestore.keys import UsageKey, CourseKey, DefinitionKey
from opaque_keys.edx.keys import UsageKey, CourseKey, DefinitionKey
@ddt

View File

@@ -9,12 +9,12 @@ from xmodule.modulestore import Location, MONGO_MODULESTORE_TYPE, SPLIT_MONGO_MO
XML_MODULESTORE_TYPE
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore.locator import BlockUsageLocator, CourseLocator
from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator
from xmodule.modulestore.tests.test_location_mapper import LocMapperSetupSansDjango, loc_mapper
# Mixed modulestore depends on django, so we'll manually configure some django settings
# before importing the module
from django.conf import settings
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
import bson.son
if not settings.configured:
settings.configure()

View File

@@ -2,7 +2,7 @@ from nose.tools import assert_equals, assert_raises, assert_true, assert_false
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore.search import path_to_location
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
def check_path_to_location(modulestore):

Some files were not shown because too many files have changed in this diff Show More