Create core/url_utils.py, moving utilities from lms_xblock/runtime
This commit is contained in:
@@ -50,7 +50,7 @@ from edxmako.shortcuts import render_to_string
|
||||
from lms.djangoapps.lms_xblock.field_data import LmsFieldData
|
||||
from lms.djangoapps.lms_xblock.models import XBlockAsidesConfig
|
||||
from openedx.core.djangoapps.bookmarks.services import BookmarksService
|
||||
from lms.djangoapps.lms_xblock.runtime import LmsModuleSystem, unquote_slashes, quote_slashes
|
||||
from lms.djangoapps.lms_xblock.runtime import LmsModuleSystem
|
||||
from lms.djangoapps.verify_student.services import VerificationService, ReverificationService
|
||||
from openedx.core.djangoapps.credit.services import CreditService
|
||||
from openedx.core.djangoapps.util.user_utils import SystemUser
|
||||
@@ -62,6 +62,7 @@ from openedx.core.lib.xblock_utils import (
|
||||
wrap_xblock,
|
||||
request_token as xblock_request_token,
|
||||
)
|
||||
from openedx.core.lib.url_utils import unquote_slashes, quote_slashes
|
||||
from student.models import anonymous_id_for_user, user_by_anonymous_id
|
||||
from student.roles import CourseBetaTesterRole
|
||||
from util import milestones_helpers
|
||||
|
||||
@@ -7,21 +7,19 @@ Contains:
|
||||
for testing Xmodules with mongo store.
|
||||
"""
|
||||
|
||||
from django.test.utils import override_settings
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.test.client import Client
|
||||
|
||||
from edxmako.shortcuts import render_to_string
|
||||
from lms.djangoapps.lms_xblock.field_data import LmsFieldData
|
||||
from openedx.core.lib.url_utils import quote_slashes
|
||||
from student.tests.factories import UserFactory, CourseEnrollmentFactory
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_MODULESTORE
|
||||
from xblock.field_data import DictFieldData
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_MODULESTORE
|
||||
from xmodule.tests import get_test_system, get_test_descriptor_system
|
||||
from opaque_keys.edx.locations import Location
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from lms.djangoapps.lms_xblock.field_data import LmsFieldData
|
||||
from lms.djangoapps.lms_xblock.runtime import quote_slashes
|
||||
|
||||
|
||||
class BaseTestXmodule(ModuleStoreTestCase):
|
||||
|
||||
@@ -12,7 +12,7 @@ from django.core.urlresolvers import reverse
|
||||
|
||||
from courseware.tests import BaseTestXmodule
|
||||
from courseware.views.views import get_course_lti_endpoints
|
||||
from lms.djangoapps.lms_xblock.runtime import quote_slashes
|
||||
from openedx.core.lib.url_utils import quote_slashes
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
from xmodule.x_module import STUDENT_VIEW
|
||||
|
||||
@@ -36,10 +36,10 @@ from courseware.models import StudentModule
|
||||
from courseware.tests.factories import StudentModuleFactory, UserFactory, GlobalStaffFactory
|
||||
from courseware.tests.tests import LoginEnrollmentTestCase
|
||||
from courseware.tests.test_submitting_problems import TestSubmittingProblems
|
||||
from lms.djangoapps.lms_xblock.runtime import quote_slashes
|
||||
from lms.djangoapps.lms_xblock.field_data import LmsFieldData
|
||||
from openedx.core.lib.courses import course_image_url
|
||||
from openedx.core.lib.gating import api as gating_api
|
||||
from openedx.core.lib.url_utils import quote_slashes
|
||||
from student.models import anonymous_id_for_user
|
||||
from xmodule.modulestore.tests.django_utils import (
|
||||
ModuleStoreTestCase,
|
||||
|
||||
@@ -19,21 +19,21 @@ from capa.tests.response_xml_factory import (
|
||||
OptionResponseXMLFactory, CustomResponseXMLFactory, SchematicResponseXMLFactory,
|
||||
CodeResponseXMLFactory,
|
||||
)
|
||||
from lms.djangoapps.grades import course_grades, progress
|
||||
from course_modes.models import CourseMode
|
||||
from courseware.models import StudentModule, BaseStudentModuleHistory
|
||||
from courseware.tests.helpers import LoginEnrollmentTestCase
|
||||
from lms.djangoapps.lms_xblock.runtime import quote_slashes
|
||||
from student.models import anonymous_id_for_user, CourseEnrollment
|
||||
from submissions import api as submissions_api
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
from xmodule.partitions.partitions import Group, UserPartition
|
||||
from lms.djangoapps.grades import course_grades, progress
|
||||
from openedx.core.djangoapps.credit.api import (
|
||||
set_credit_requirements, get_credit_requirement_status
|
||||
)
|
||||
from openedx.core.djangoapps.credit.models import CreditCourse, CreditProvider
|
||||
from openedx.core.djangoapps.user_api.tests.factories import UserCourseTagFactory
|
||||
from openedx.core.lib.url_utils import quote_slashes
|
||||
from student.models import anonymous_id_for_user, CourseEnrollment
|
||||
from submissions import api as submissions_api
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
from xmodule.partitions.partitions import Group, UserPartition
|
||||
|
||||
|
||||
class ProblemSubmissionTestMixin(TestCase):
|
||||
|
||||
@@ -22,8 +22,8 @@ from django.conf import settings
|
||||
from util.json_request import JsonResponse
|
||||
from mock import patch
|
||||
|
||||
from lms.djangoapps.lms_xblock.runtime import quote_slashes
|
||||
from openedx.core.lib.xblock_utils import wrap_xblock
|
||||
from openedx.core.lib.url_utils import quote_slashes
|
||||
from xmodule.html_module import HtmlDescriptor
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.tabs import CourseTab
|
||||
|
||||
@@ -14,12 +14,12 @@ from celery.states import SUCCESS, FAILURE
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.test.testcases import TestCase
|
||||
from django.contrib.auth.models import User
|
||||
from lms.djangoapps.lms_xblock.runtime import quote_slashes
|
||||
from opaque_keys.edx.locations import Location, SlashSeparatedCourseKey
|
||||
|
||||
from capa.tests.response_xml_factory import OptionResponseXMLFactory
|
||||
from courseware.model_data import StudentModule
|
||||
from courseware.tests.tests import LoginEnrollmentTestCase
|
||||
from opaque_keys.edx.locations import Location, SlashSeparatedCourseKey
|
||||
from openedx.core.lib.url_utils import quote_slashes
|
||||
from student.tests.factories import CourseEnrollmentFactory, UserFactory
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
@@ -38,8 +38,8 @@ from instructor_task.tests.test_base import (
|
||||
OPTION_2,
|
||||
)
|
||||
from capa.responsetypes import StudentInputError
|
||||
from lms.djangoapps.lms_xblock.runtime import quote_slashes
|
||||
from lms.djangoapps.grades.new.course_grade import CourseGradeFactory
|
||||
from openedx.core.lib.url_utils import quote_slashes
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
"""
|
||||
Module implementing `xblock.runtime.Runtime` functionality for the LMS
|
||||
"""
|
||||
import re
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
@@ -10,6 +8,7 @@ from badges.service import BadgingService
|
||||
from badges.utils import badges_enabled
|
||||
from openedx.core.djangoapps.user_api.course_tag import api as user_course_tag_api
|
||||
from openedx.core.lib.xblock_utils import xblock_local_resource_url
|
||||
from openedx.core.lib.url_utils import quote_slashes
|
||||
from request_cache.middleware import RequestCache
|
||||
import xblock.reference.plugins
|
||||
from xmodule.library_tools import LibraryToolsService
|
||||
@@ -21,55 +20,6 @@ from xmodule.x_module import ModuleSystem
|
||||
from lms.djangoapps.lms_xblock.models import XBlockAsidesConfig
|
||||
|
||||
|
||||
def _quote_slashes(match):
|
||||
"""
|
||||
Helper function for `quote_slashes`
|
||||
"""
|
||||
matched = match.group(0)
|
||||
# We have to escape ';', because that is our
|
||||
# escape sequence identifier (otherwise, the escaping)
|
||||
# couldn't distinguish between us adding ';_' to the string
|
||||
# and ';_' appearing naturally in the string
|
||||
if matched == ';':
|
||||
return ';;'
|
||||
elif matched == '/':
|
||||
return ';_'
|
||||
else:
|
||||
return matched
|
||||
|
||||
|
||||
def quote_slashes(text):
|
||||
"""
|
||||
Quote '/' characters so that they aren't visible to
|
||||
django's url quoting, unquoting, or url regex matching.
|
||||
|
||||
Escapes '/'' to the sequence ';_', and ';' to the sequence
|
||||
';;'. By making the escape sequence fixed length, and escaping
|
||||
identifier character ';', we are able to reverse the escaping.
|
||||
"""
|
||||
return re.sub(ur'[;/]', _quote_slashes, text)
|
||||
|
||||
|
||||
def _unquote_slashes(match):
|
||||
"""
|
||||
Helper function for `unquote_slashes`
|
||||
"""
|
||||
matched = match.group(0)
|
||||
if matched == ';;':
|
||||
return ';'
|
||||
elif matched == ';_':
|
||||
return '/'
|
||||
else:
|
||||
return matched
|
||||
|
||||
|
||||
def unquote_slashes(text):
|
||||
"""
|
||||
Unquote slashes quoted by `quote_slashes`
|
||||
"""
|
||||
return re.sub(r'(;;|;_)', _unquote_slashes, text)
|
||||
|
||||
|
||||
def handler_url(block, handler_name, suffix='', query='', thirdparty=False):
|
||||
"""
|
||||
This method matches the signature for `xblock.runtime:Runtime.handler_url()`
|
||||
|
||||
@@ -10,11 +10,10 @@ from urlparse import urlparse
|
||||
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from opaque_keys.edx.locations import BlockUsageLocator, CourseLocator, SlashSeparatedCourseKey
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
|
||||
from badges.tests.factories import BadgeClassFactory
|
||||
from badges.tests.test_models import get_image
|
||||
from lms.djangoapps.lms_xblock.runtime import quote_slashes, unquote_slashes, LmsModuleSystem
|
||||
from lms.djangoapps.lms_xblock.runtime import LmsModuleSystem
|
||||
from xblock.fields import ScopeIds
|
||||
from xmodule.modulestore.django import ModuleI18nService
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
@@ -23,32 +22,6 @@ from xblock.exceptions import NoSuchServiceError
|
||||
from student.tests.factories import UserFactory
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
TEST_STRINGS = [
|
||||
'',
|
||||
'foobar',
|
||||
'foo/bar',
|
||||
'foo/bar;',
|
||||
'foo;;bar',
|
||||
'foo;_bar',
|
||||
'foo/',
|
||||
'/bar',
|
||||
'foo//bar',
|
||||
'foo;;;bar',
|
||||
]
|
||||
|
||||
|
||||
@ddt
|
||||
class TestQuoteSlashes(TestCase):
|
||||
"""Test the quote_slashes and unquote_slashes functions"""
|
||||
|
||||
@data(*TEST_STRINGS)
|
||||
def test_inverse(self, test_string):
|
||||
self.assertEquals(test_string, unquote_slashes(quote_slashes(test_string)))
|
||||
|
||||
@data(*TEST_STRINGS)
|
||||
def test_escaped(self, test_string):
|
||||
self.assertNotIn('/', quote_slashes(test_string))
|
||||
|
||||
|
||||
class BlockMock(Mock):
|
||||
"""Mock class that we fill with our "handler" methods."""
|
||||
|
||||
@@ -11,9 +11,9 @@ from lti_provider.outcomes import store_outcome_parameters
|
||||
from lti_provider.models import LtiConsumer
|
||||
from lti_provider.signature_validator import SignatureValidator
|
||||
from lti_provider.users import authenticate_lti_user
|
||||
from lms_xblock.runtime import unquote_slashes
|
||||
from opaque_keys.edx.keys import CourseKey, UsageKey
|
||||
from opaque_keys import InvalidKeyError
|
||||
from openedx.core.lib.url_utils import unquote_slashes
|
||||
from util.views import add_p3p_header
|
||||
|
||||
log = logging.getLogger("edx.lti_provider")
|
||||
|
||||
@@ -27,8 +27,8 @@ from openedx.core.lib.api.permissions import IsUserInUrl
|
||||
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError
|
||||
|
||||
from lms.djangoapps.lms_xblock.runtime import unquote_slashes
|
||||
from openedx.core.lib.api.paginators import DefaultPagination
|
||||
from openedx.core.lib.url_utils import unquote_slashes
|
||||
|
||||
from . import DEFAULT_FIELDS, OPTIONAL_FIELDS, api
|
||||
from .serializers import BookmarkSerializer
|
||||
|
||||
33
openedx/core/lib/tests/test_url_utils.py
Normal file
33
openedx/core/lib/tests/test_url_utils.py
Normal file
@@ -0,0 +1,33 @@
|
||||
"""
|
||||
Tests for url_utils module.
|
||||
"""
|
||||
from ddt import ddt, data
|
||||
from django.test import TestCase
|
||||
from openedx.core.lib.url_utils import quote_slashes, unquote_slashes
|
||||
|
||||
|
||||
TEST_STRINGS = [
|
||||
'',
|
||||
'foobar',
|
||||
'foo/bar',
|
||||
'foo/bar;',
|
||||
'foo;;bar',
|
||||
'foo;_bar',
|
||||
'foo/',
|
||||
'/bar',
|
||||
'foo//bar',
|
||||
'foo;;;bar',
|
||||
]
|
||||
|
||||
|
||||
@ddt
|
||||
class TestQuoteSlashes(TestCase):
|
||||
"""Test the quote_slashes and unquote_slashes functions"""
|
||||
|
||||
@data(*TEST_STRINGS)
|
||||
def test_inverse(self, test_string):
|
||||
self.assertEquals(test_string, unquote_slashes(quote_slashes(test_string)))
|
||||
|
||||
@data(*TEST_STRINGS)
|
||||
def test_escaped(self, test_string):
|
||||
self.assertNotIn('/', quote_slashes(test_string))
|
||||
@@ -9,7 +9,7 @@ import uuid
|
||||
|
||||
from django.test.client import RequestFactory
|
||||
|
||||
from lms.djangoapps.lms_xblock.runtime import quote_slashes
|
||||
from openedx.core.lib.url_utils import quote_slashes
|
||||
from xblock.fragment import Fragment
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
|
||||
53
openedx/core/lib/url_utils.py
Normal file
53
openedx/core/lib/url_utils.py
Normal file
@@ -0,0 +1,53 @@
|
||||
"""
|
||||
Contains common utilities for URL escaping.
|
||||
"""
|
||||
import re
|
||||
|
||||
|
||||
def quote_slashes(text):
|
||||
"""
|
||||
Quote '/' characters so that they aren't visible to
|
||||
django's url quoting, unquoting, or url regex matching.
|
||||
|
||||
Escapes '/'' to the sequence ';_', and ';' to the sequence
|
||||
';;'. By making the escape sequence fixed length, and escaping
|
||||
identifier character ';', we are able to reverse the escaping.
|
||||
"""
|
||||
return re.sub(ur'[;/]', _quote_slashes, text)
|
||||
|
||||
|
||||
def unquote_slashes(text):
|
||||
"""
|
||||
Unquote slashes quoted by `quote_slashes`
|
||||
"""
|
||||
return re.sub(r'(;;|;_)', _unquote_slashes, text)
|
||||
|
||||
|
||||
def _quote_slashes(match):
|
||||
"""
|
||||
Helper function for `quote_slashes`
|
||||
"""
|
||||
matched = match.group(0)
|
||||
# We have to escape ';', because that is our
|
||||
# escape sequence identifier (otherwise, the escaping)
|
||||
# couldn't distinguish between us adding ';_' to the string
|
||||
# and ';_' appearing naturally in the string
|
||||
if matched == ';':
|
||||
return ';;'
|
||||
elif matched == '/':
|
||||
return ';_'
|
||||
else:
|
||||
return matched
|
||||
|
||||
|
||||
def _unquote_slashes(match):
|
||||
"""
|
||||
Helper function for `unquote_slashes`
|
||||
"""
|
||||
matched = match.group(0)
|
||||
if matched == ';;':
|
||||
return ';'
|
||||
elif matched == ';_':
|
||||
return '/'
|
||||
else:
|
||||
return matched
|
||||
@@ -6,16 +6,14 @@ import unittest
|
||||
|
||||
from nose.plugins.attrib import attr
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
|
||||
from lms.djangoapps.courseware.tests.helpers import LoginEnrollmentTestCase
|
||||
from lms.djangoapps.courseware.tests.factories import GlobalStaffFactory
|
||||
from lms.djangoapps.lms_xblock.runtime import quote_slashes
|
||||
|
||||
from django.conf import settings
|
||||
from openedx.core.lib.url_utils import quote_slashes
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
|
||||
|
||||
class TestCrowdsourceHinter(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
|
||||
@@ -20,7 +20,7 @@ from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
|
||||
from lms.djangoapps.courseware.tests.helpers import LoginEnrollmentTestCase
|
||||
from lms.djangoapps.courseware.tests.factories import GlobalStaffFactory
|
||||
from lms.djangoapps.lms_xblock.runtime import quote_slashes
|
||||
from openedx.core.lib.url_utils import quote_slashes
|
||||
|
||||
|
||||
class TestRecommender(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
|
||||
Reference in New Issue
Block a user