Skip to content

Commit

Permalink
Parse the short-lived slashes and locations syntax
Browse files Browse the repository at this point in the history
which solutions bravely picked up
  • Loading branch information
Don Mitchell committed Oct 14, 2014
1 parent 33f2b09 commit cba8e23
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 6 deletions.
33 changes: 32 additions & 1 deletion opaque_keys/edx/locations.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
from __future__ import absolute_import
import warnings

from opaque_keys.edx.locator import AssetLocator, BlockUsageLocator, CourseLocator
from opaque_keys.edx.locator import AssetLocator, BlockUsageLocator, CourseLocator, Locator
from opaque_keys.edx.keys import i4xEncoder as real_i4xEncoder
import re

# This file passes through to protected members of the non-deprecated classes,
# and that's ok. It also may not implement all of the current UsageKey methods.
Expand Down Expand Up @@ -201,6 +202,36 @@ def replace(self, **kwargs):
)


class DeprecatedLocation(BlockUsageLocator):
'''
The short-lived location:org+course+run+block_type+block_id syntax
'''
CANONICAL_NAMESPACE = 'location'
URL_RE_SOURCE = r"""
(?P<org>{ALLOWED_ID_CHARS}+)\+(?P<course>{ALLOWED_ID_CHARS}+)\+(?P<run>{ALLOWED_ID_CHARS}+)\+
(?P<block_type>{ALLOWED_ID_CHARS}+)\+
(?P<block_id>{ALLOWED_ID_CHARS}+)
""".format(
ALLOWED_ID_CHARS=Locator.ALLOWED_ID_CHARS,
)

URL_RE = re.compile('^' + URL_RE_SOURCE + '$', re.IGNORECASE | re.VERBOSE | re.UNICODE)

@classmethod
def _from_string(cls, serialized):
"""
see super
"""
# Allow access to _from_string protected method
parsed_parts = cls.parse_url(serialized)
course_key = CourseLocator(
parsed_parts.get('org'), parsed_parts.get('course'), parsed_parts.get('run'),
# specifically not saying deprecated=True b/c that would lose the run on serialization
)
block_id = parsed_parts.get('block_id')
return cls(course_key, parsed_parts.get('block_type'), block_id)


class AssetLocation(LocationBase, AssetLocator):
"""Deprecated. Use :class:`locator.AssetLocator`"""

Expand Down
34 changes: 29 additions & 5 deletions opaque_keys/edx/tests/test_deprecated_locations.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from opaque_keys.edx.locator import AssetLocator, BlockUsageLocator, CourseLocator
from opaque_keys.edx.locations import AssetLocation, Location, SlashSeparatedCourseKey
from opaque_keys.edx.tests import TestDeprecated
from opaque_keys.edx.keys import CourseKey, UsageKey

# Allow protected method access throughout this test file
# pylint: disable=protected-access
Expand Down Expand Up @@ -43,11 +44,6 @@ def test_deprecated_init(self):
self.assertTrue(isinstance(ssck, CourseLocator))
self.assertTrue(ssck.deprecated)

def test_deprecated_from_string(self):
with self.assertDeprecationWarning():
with self.assertRaises(InvalidKeyError):
SlashSeparatedCourseKey.from_string("slashes:foo+bar+baz")

def test_deprecated_from_string_bad(self):
with self.assertDeprecationWarning():
with self.assertRaises(InvalidKeyError):
Expand Down Expand Up @@ -76,6 +72,34 @@ def test_deprecated_replace(self):
self.assertEquals(ssck, ssck_copy)


class TestV0Strings(TestDeprecated):
"""
Test that we can parse slashes:org+course+run and locations:org+course+run+type+id
strings which were short-lived
"""
def test_parse_slashes(self):
"""
Test that we can parse slashes:org+course+run strings which were short-lived
"""
parsed_key = CourseKey.from_string('slashes:DemoUniversity+DM01+2014')
self.assertEqual(parsed_key.org, 'DemoUniversity')
self.assertEqual(parsed_key.course, 'DM01')
self.assertEqual(parsed_key.run, '2014')

def test_parse_location(self):
"""
Test that we can parse location:org+course+run+type+id
"""
parsed_key = UsageKey.from_string(
'location:GradingUniv+GT101+2014+chapter+4420ef6679b34ee8ba0cfd6d514b1b38'
)
self.assertEqual(parsed_key.org, 'GradingUniv')
self.assertEqual(parsed_key.course, 'GT101')
self.assertEqual(parsed_key.run, '2014')
self.assertEqual(parsed_key.block_type, 'chapter')
self.assertEqual(parsed_key.block_id, '4420ef6679b34ee8ba0cfd6d514b1b38')


class TestLocation(TestLocationDeprecatedBase):
"""Tests that Location raises a deprecation warning and returns a BlockUsageLocator"""
def test_deprecated_init(self):
Expand Down
3 changes: 3 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@
],
'course_key': [
'course-v1 = opaque_keys.edx.locator:CourseLocator',
# don't use slashes in any new code
'slashes = opaque_keys.edx.locator:CourseLocator',
],
'usage_key': [
'block-v1 = opaque_keys.edx.locator:BlockUsageLocator',
'location = opaque_keys.edx.locations:DeprecatedLocation',
],
'asset_key': [
'asset-v1 = opaque_keys.edx.locator:AssetLocator',
Expand Down

0 comments on commit cba8e23

Please sign in to comment.