Commit 15d9883f by Nimisha Asthagiri

Create core/url_utils.py, moving utilities from lms_xblock/runtime

parent 4bb88109
...@@ -50,7 +50,7 @@ from edxmako.shortcuts import render_to_string ...@@ -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.field_data import LmsFieldData
from lms.djangoapps.lms_xblock.models import XBlockAsidesConfig from lms.djangoapps.lms_xblock.models import XBlockAsidesConfig
from openedx.core.djangoapps.bookmarks.services import BookmarksService 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 lms.djangoapps.verify_student.services import VerificationService, ReverificationService
from openedx.core.djangoapps.credit.services import CreditService from openedx.core.djangoapps.credit.services import CreditService
from openedx.core.djangoapps.util.user_utils import SystemUser from openedx.core.djangoapps.util.user_utils import SystemUser
...@@ -62,6 +62,7 @@ from openedx.core.lib.xblock_utils import ( ...@@ -62,6 +62,7 @@ from openedx.core.lib.xblock_utils import (
wrap_xblock, wrap_xblock,
request_token as xblock_request_token, 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.models import anonymous_id_for_user, user_by_anonymous_id
from student.roles import CourseBetaTesterRole from student.roles import CourseBetaTesterRole
from util import milestones_helpers from util import milestones_helpers
......
...@@ -7,21 +7,19 @@ Contains: ...@@ -7,21 +7,19 @@ Contains:
for testing Xmodules with mongo store. for testing Xmodules with mongo store.
""" """
from django.test.utils import override_settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.test.client import Client from django.test.client import Client
from edxmako.shortcuts import render_to_string 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 student.tests.factories import UserFactory, CourseEnrollmentFactory
from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_MODULESTORE
from xblock.field_data import DictFieldData 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 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.django import modulestore
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase 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): class BaseTestXmodule(ModuleStoreTestCase):
......
...@@ -12,7 +12,7 @@ from django.core.urlresolvers import reverse ...@@ -12,7 +12,7 @@ from django.core.urlresolvers import reverse
from courseware.tests import BaseTestXmodule from courseware.tests import BaseTestXmodule
from courseware.views.views import get_course_lti_endpoints 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.django_utils import SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
from xmodule.x_module import STUDENT_VIEW from xmodule.x_module import STUDENT_VIEW
......
...@@ -36,10 +36,10 @@ from courseware.models import StudentModule ...@@ -36,10 +36,10 @@ from courseware.models import StudentModule
from courseware.tests.factories import StudentModuleFactory, UserFactory, GlobalStaffFactory from courseware.tests.factories import StudentModuleFactory, UserFactory, GlobalStaffFactory
from courseware.tests.tests import LoginEnrollmentTestCase from courseware.tests.tests import LoginEnrollmentTestCase
from courseware.tests.test_submitting_problems import TestSubmittingProblems 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 lms.djangoapps.lms_xblock.field_data import LmsFieldData
from openedx.core.lib.courses import course_image_url from openedx.core.lib.courses import course_image_url
from openedx.core.lib.gating import api as gating_api 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 student.models import anonymous_id_for_user
from xmodule.modulestore.tests.django_utils import ( from xmodule.modulestore.tests.django_utils import (
ModuleStoreTestCase, ModuleStoreTestCase,
......
...@@ -19,21 +19,21 @@ from capa.tests.response_xml_factory import ( ...@@ -19,21 +19,21 @@ from capa.tests.response_xml_factory import (
OptionResponseXMLFactory, CustomResponseXMLFactory, SchematicResponseXMLFactory, OptionResponseXMLFactory, CustomResponseXMLFactory, SchematicResponseXMLFactory,
CodeResponseXMLFactory, CodeResponseXMLFactory,
) )
from lms.djangoapps.grades import course_grades, progress
from course_modes.models import CourseMode from course_modes.models import CourseMode
from courseware.models import StudentModule, BaseStudentModuleHistory from courseware.models import StudentModule, BaseStudentModuleHistory
from courseware.tests.helpers import LoginEnrollmentTestCase from courseware.tests.helpers import LoginEnrollmentTestCase
from lms.djangoapps.lms_xblock.runtime import quote_slashes from lms.djangoapps.grades import course_grades, progress
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 openedx.core.djangoapps.credit.api import ( from openedx.core.djangoapps.credit.api import (
set_credit_requirements, get_credit_requirement_status set_credit_requirements, get_credit_requirement_status
) )
from openedx.core.djangoapps.credit.models import CreditCourse, CreditProvider from openedx.core.djangoapps.credit.models import CreditCourse, CreditProvider
from openedx.core.djangoapps.user_api.tests.factories import UserCourseTagFactory 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): class ProblemSubmissionTestMixin(TestCase):
......
...@@ -22,8 +22,8 @@ from django.conf import settings ...@@ -22,8 +22,8 @@ from django.conf import settings
from util.json_request import JsonResponse from util.json_request import JsonResponse
from mock import patch 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.xblock_utils import wrap_xblock
from openedx.core.lib.url_utils import quote_slashes
from xmodule.html_module import HtmlDescriptor from xmodule.html_module import HtmlDescriptor
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.tabs import CourseTab from xmodule.tabs import CourseTab
......
...@@ -14,12 +14,12 @@ from celery.states import SUCCESS, FAILURE ...@@ -14,12 +14,12 @@ from celery.states import SUCCESS, FAILURE
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.test.testcases import TestCase from django.test.testcases import TestCase
from django.contrib.auth.models import User 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 capa.tests.response_xml_factory import OptionResponseXMLFactory
from courseware.model_data import StudentModule from courseware.model_data import StudentModule
from courseware.tests.tests import LoginEnrollmentTestCase 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 student.tests.factories import CourseEnrollmentFactory, UserFactory
from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
......
...@@ -38,8 +38,8 @@ from instructor_task.tests.test_base import ( ...@@ -38,8 +38,8 @@ from instructor_task.tests.test_base import (
OPTION_2, OPTION_2,
) )
from capa.responsetypes import StudentInputError from capa.responsetypes import StudentInputError
from lms.djangoapps.lms_xblock.runtime import quote_slashes
from lms.djangoapps.grades.new.course_grade import CourseGradeFactory from lms.djangoapps.grades.new.course_grade import CourseGradeFactory
from openedx.core.lib.url_utils import quote_slashes
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
......
""" """
Module implementing `xblock.runtime.Runtime` functionality for the LMS Module implementing `xblock.runtime.Runtime` functionality for the LMS
""" """
import re
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
...@@ -10,6 +8,7 @@ from badges.service import BadgingService ...@@ -10,6 +8,7 @@ from badges.service import BadgingService
from badges.utils import badges_enabled from badges.utils import badges_enabled
from openedx.core.djangoapps.user_api.course_tag import api as user_course_tag_api 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.xblock_utils import xblock_local_resource_url
from openedx.core.lib.url_utils import quote_slashes
from request_cache.middleware import RequestCache from request_cache.middleware import RequestCache
import xblock.reference.plugins import xblock.reference.plugins
from xmodule.library_tools import LibraryToolsService from xmodule.library_tools import LibraryToolsService
...@@ -21,55 +20,6 @@ from xmodule.x_module import ModuleSystem ...@@ -21,55 +20,6 @@ from xmodule.x_module import ModuleSystem
from lms.djangoapps.lms_xblock.models import XBlockAsidesConfig 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): def handler_url(block, handler_name, suffix='', query='', thirdparty=False):
""" """
This method matches the signature for `xblock.runtime:Runtime.handler_url()` This method matches the signature for `xblock.runtime:Runtime.handler_url()`
......
...@@ -10,11 +10,10 @@ from urlparse import urlparse ...@@ -10,11 +10,10 @@ from urlparse import urlparse
from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.locations import BlockUsageLocator, CourseLocator, SlashSeparatedCourseKey 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.factories import BadgeClassFactory
from badges.tests.test_models import get_image 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 xblock.fields import ScopeIds
from xmodule.modulestore.django import ModuleI18nService from xmodule.modulestore.django import ModuleI18nService
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
...@@ -23,32 +22,6 @@ from xblock.exceptions import NoSuchServiceError ...@@ -23,32 +22,6 @@ from xblock.exceptions import NoSuchServiceError
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from xmodule.modulestore.tests.factories import CourseFactory 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): class BlockMock(Mock):
"""Mock class that we fill with our "handler" methods.""" """Mock class that we fill with our "handler" methods."""
......
...@@ -11,9 +11,9 @@ from lti_provider.outcomes import store_outcome_parameters ...@@ -11,9 +11,9 @@ from lti_provider.outcomes import store_outcome_parameters
from lti_provider.models import LtiConsumer from lti_provider.models import LtiConsumer
from lti_provider.signature_validator import SignatureValidator from lti_provider.signature_validator import SignatureValidator
from lti_provider.users import authenticate_lti_user 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.edx.keys import CourseKey, UsageKey
from opaque_keys import InvalidKeyError from opaque_keys import InvalidKeyError
from openedx.core.lib.url_utils import unquote_slashes
from util.views import add_p3p_header from util.views import add_p3p_header
log = logging.getLogger("edx.lti_provider") log = logging.getLogger("edx.lti_provider")
......
...@@ -27,8 +27,8 @@ from openedx.core.lib.api.permissions import IsUserInUrl ...@@ -27,8 +27,8 @@ from openedx.core.lib.api.permissions import IsUserInUrl
from xmodule.modulestore.exceptions import ItemNotFoundError 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.api.paginators import DefaultPagination
from openedx.core.lib.url_utils import unquote_slashes
from . import DEFAULT_FIELDS, OPTIONAL_FIELDS, api from . import DEFAULT_FIELDS, OPTIONAL_FIELDS, api
from .serializers import BookmarkSerializer from .serializers import BookmarkSerializer
......
"""
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 ...@@ -9,7 +9,7 @@ import uuid
from django.test.client import RequestFactory 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 xblock.fragment import Fragment
from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
......
"""
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 ...@@ -6,16 +6,14 @@ import unittest
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from django.conf import settings
from django.core.urlresolvers import reverse 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.helpers import LoginEnrollmentTestCase
from lms.djangoapps.courseware.tests.factories import GlobalStaffFactory 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
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from django.conf import settings from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
class TestCrowdsourceHinter(SharedModuleStoreTestCase, LoginEnrollmentTestCase): class TestCrowdsourceHinter(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
......
...@@ -20,7 +20,7 @@ from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase ...@@ -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.helpers import LoginEnrollmentTestCase
from lms.djangoapps.courseware.tests.factories import GlobalStaffFactory 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): class TestRecommender(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment