Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
87ded08d
Commit
87ded08d
authored
Oct 29, 2015
by
David Ormsbee
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #10389 from edx/mobile/handler-url
Changes to handler URL generation
parents
2206b8a0
9b88bdb0
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
144 additions
and
70 deletions
+144
-70
cms/djangoapps/contentstore/views/item.py
+0
-7
cms/startup.py
+10
-0
common/lib/xmodule/xmodule/x_module.py
+7
-2
lms/djangoapps/lms_xblock/runtime.py
+87
-59
lms/djangoapps/lms_xblock/test/test_runtime.py
+30
-2
lms/startup.py
+10
-0
No files found.
cms/djangoapps/contentstore/views/item.py
View file @
87ded08d
...
@@ -51,7 +51,6 @@ from contentstore.views.helpers import is_unit, xblock_studio_url, xblock_primar
...
@@ -51,7 +51,6 @@ from contentstore.views.helpers import is_unit, xblock_studio_url, xblock_primar
from
contentstore.views.preview
import
get_preview_fragment
from
contentstore.views.preview
import
get_preview_fragment
from
edxmako.shortcuts
import
render_to_string
from
edxmako.shortcuts
import
render_to_string
from
models.settings.course_grading
import
CourseGradingModel
from
models.settings.course_grading
import
CourseGradingModel
from
cms.lib.xblock.runtime
import
handler_url
,
local_resource_url
from
opaque_keys.edx.keys
import
CourseKey
from
opaque_keys.edx.keys
import
CourseKey
from
opaque_keys.edx.locator
import
LibraryUsageLocator
from
opaque_keys.edx.locator
import
LibraryUsageLocator
from
cms.lib.xblock.authoring_mixin
import
VISIBILITY_VIEW
from
cms.lib.xblock.authoring_mixin
import
VISIBILITY_VIEW
...
@@ -68,12 +67,6 @@ CREATE_IF_NOT_FOUND = ['course_info']
...
@@ -68,12 +67,6 @@ CREATE_IF_NOT_FOUND = ['course_info']
NEVER
=
lambda
x
:
False
NEVER
=
lambda
x
:
False
ALWAYS
=
lambda
x
:
True
ALWAYS
=
lambda
x
:
True
# In order to allow descriptors to use a handler url, we need to
# monkey-patch the x_module library.
# TODO: Remove this code when Runtimes are no longer created by modulestores
xmodule
.
x_module
.
descriptor_global_handler_url
=
handler_url
xmodule
.
x_module
.
descriptor_global_local_resource_url
=
local_resource_url
def
hash_resource
(
resource
):
def
hash_resource
(
resource
):
"""
"""
...
...
cms/startup.py
View file @
87ded08d
...
@@ -10,6 +10,9 @@ settings.INSTALLED_APPS # pylint: disable=pointless-statement
...
@@ -10,6 +10,9 @@ settings.INSTALLED_APPS # pylint: disable=pointless-statement
from
openedx.core.lib.django_startup
import
autostartup
from
openedx.core.lib.django_startup
import
autostartup
from
monkey_patch
import
django_utils_translation
from
monkey_patch
import
django_utils_translation
import
xmodule.x_module
import
cms.lib.xblock.runtime
def
run
():
def
run
():
"""
"""
...
@@ -24,6 +27,13 @@ def run():
...
@@ -24,6 +27,13 @@ def run():
if
settings
.
FEATURES
.
get
(
'USE_CUSTOM_THEME'
,
False
):
if
settings
.
FEATURES
.
get
(
'USE_CUSTOM_THEME'
,
False
):
enable_theme
()
enable_theme
()
# In order to allow descriptors to use a handler url, we need to
# monkey-patch the x_module library.
# TODO: Remove this code when Runtimes are no longer created by modulestores
# https://openedx.atlassian.net/wiki/display/PLAT/Convert+from+Storage-centric+runtimes+to+Application-centric+runtimes
xmodule
.
x_module
.
descriptor_global_handler_url
=
cms
.
lib
.
xblock
.
runtime
.
handler_url
xmodule
.
x_module
.
descriptor_global_local_resource_url
=
cms
.
lib
.
xblock
.
runtime
.
local_resource_url
def
add_mimetypes
():
def
add_mimetypes
():
"""
"""
...
...
common/lib/xmodule/xmodule/x_module.py
View file @
87ded08d
...
@@ -36,7 +36,6 @@ from opaque_keys.edx.asides import AsideUsageKeyV1, AsideDefinitionKeyV1
...
@@ -36,7 +36,6 @@ from opaque_keys.edx.asides import AsideUsageKeyV1, AsideDefinitionKeyV1
from
xmodule.exceptions
import
UndefinedContext
from
xmodule.exceptions
import
UndefinedContext
import
dogstats_wrapper
as
dog_stats_api
import
dogstats_wrapper
as
dog_stats_api
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
XMODULE_METRIC_NAME
=
'edxapp.xmodule'
XMODULE_METRIC_NAME
=
'edxapp.xmodule'
...
@@ -1207,7 +1206,10 @@ class ConfigurableFragmentWrapper(object): # pylint: disable=abstract-method
...
@@ -1207,7 +1206,10 @@ class ConfigurableFragmentWrapper(object): # pylint: disable=abstract-method
# This function exists to give applications (LMS/CMS) a place to monkey-patch until
# This function exists to give applications (LMS/CMS) a place to monkey-patch until
# we can refactor modulestore to split out the FieldData half of its interface from
# we can refactor modulestore to split out the FieldData half of its interface from
# the Runtime part of its interface. This function matches the Runtime.handler_url interface
# the Runtime part of its interface. This function mostly matches the
# Runtime.handler_url interface.
#
# The monkey-patching happens in (lms|cms)/startup.py
def
descriptor_global_handler_url
(
block
,
handler_name
,
suffix
=
''
,
query
=
''
,
thirdparty
=
False
):
# pylint: disable=invalid-name, unused-argument
def
descriptor_global_handler_url
(
block
,
handler_name
,
suffix
=
''
,
query
=
''
,
thirdparty
=
False
):
# pylint: disable=invalid-name, unused-argument
"""
"""
See :meth:`xblock.runtime.Runtime.handler_url`.
See :meth:`xblock.runtime.Runtime.handler_url`.
...
@@ -1218,6 +1220,8 @@ def descriptor_global_handler_url(block, handler_name, suffix='', query='', thir
...
@@ -1218,6 +1220,8 @@ def descriptor_global_handler_url(block, handler_name, suffix='', query='', thir
# This function exists to give applications (LMS/CMS) a place to monkey-patch until
# This function exists to give applications (LMS/CMS) a place to monkey-patch until
# we can refactor modulestore to split out the FieldData half of its interface from
# we can refactor modulestore to split out the FieldData half of its interface from
# the Runtime part of its interface. This function matches the Runtime.local_resource_url interface
# the Runtime part of its interface. This function matches the Runtime.local_resource_url interface
#
# The monkey-patching happens in (lms|cms)/startup.py
def
descriptor_global_local_resource_url
(
block
,
uri
):
# pylint: disable=invalid-name, unused-argument
def
descriptor_global_local_resource_url
(
block
,
uri
):
# pylint: disable=invalid-name, unused-argument
"""
"""
See :meth:`xblock.runtime.Runtime.local_resource_url`.
See :meth:`xblock.runtime.Runtime.local_resource_url`.
...
@@ -1821,6 +1825,7 @@ class CombinedSystem(object):
...
@@ -1821,6 +1825,7 @@ class CombinedSystem(object):
DescriptorSystem, instead. This allows XModuleDescriptors that are bound as XModules
DescriptorSystem, instead. This allows XModuleDescriptors that are bound as XModules
to still function as XModuleDescriptors.
to still function as XModuleDescriptors.
"""
"""
# First we try a lookup in the module system...
try
:
try
:
return
getattr
(
self
.
_module_system
,
name
)
return
getattr
(
self
.
_module_system
,
name
)
except
AttributeError
:
except
AttributeError
:
...
...
lms/djangoapps/lms_xblock/runtime.py
View file @
87ded08d
...
@@ -66,64 +66,68 @@ def unquote_slashes(text):
...
@@ -66,64 +66,68 @@ def unquote_slashes(text):
return
re
.
sub
(
r'(;;|;_)'
,
_unquote_slashes
,
text
)
return
re
.
sub
(
r'(;;|;_)'
,
_unquote_slashes
,
text
)
class
LmsHandlerUrls
(
object
):
def
handler_url
(
block
,
handler_name
,
suffix
=
''
,
query
=
''
,
thirdparty
=
False
):
"""
"""
A runtime mixin that provides a handler_url function that routes
This method matches the signature for `xblock.runtime:Runtime.handler_url()`
to the LMS' xblock handler view.
See :method:`xblock.runtime:Runtime.handler_url`
This must be mixed in to a runtime that already accepts and stores
"""
a course_id
view_name
=
'xblock_handler'
"""
if
handler_name
:
# pylint: disable=unused-argument
# Be sure this is really a handler.
def
handler_url
(
self
,
block
,
handler_name
,
suffix
=
''
,
query
=
''
,
thirdparty
=
False
):
#
"""See :method:`xblock.runtime:Runtime.handler_url`"""
# We're checking the .__class__ instead of the block itself to avoid
view_name
=
'xblock_handler'
# auto-proxying from Descriptor -> Module, in case descriptors want
if
handler_name
:
# to ask for handler URLs without a student context.
# Be sure this is really a handler.
func
=
getattr
(
block
.
__class__
,
handler_name
,
None
)
func
=
getattr
(
block
,
handler_name
,
None
)
if
not
func
:
if
not
func
:
raise
ValueError
(
"{!r} is not a function name"
.
format
(
handler_name
))
raise
ValueError
(
"{!r} is not a function name"
.
format
(
handler_name
))
if
not
getattr
(
func
,
"_is_xblock_handler"
,
False
):
# Is the following necessary? ProxyAttribute causes an UndefinedContext error
raise
ValueError
(
"{!r} is not a handler name"
.
format
(
handler_name
))
# if trying this without the module system.
#
if
thirdparty
:
#if not getattr(func, "_is_xblock_handler", False):
view_name
=
'xblock_handler_noauth'
# raise ValueError("{!r} is not a handler name".format(handler_name))
url
=
reverse
(
view_name
,
kwargs
=
{
if
thirdparty
:
'course_id'
:
unicode
(
self
.
course_id
),
view_name
=
'xblock_handler_noauth'
'usage_id'
:
quote_slashes
(
unicode
(
block
.
scope_ids
.
usage_id
)
.
encode
(
'utf-8'
)),
'handler'
:
handler_name
,
url
=
reverse
(
view_name
,
kwargs
=
{
'suffix'
:
suffix
,
'course_id'
:
unicode
(
block
.
location
.
course_key
),
})
'usage_id'
:
quote_slashes
(
unicode
(
block
.
scope_ids
.
usage_id
)
.
encode
(
'utf-8'
)),
'handler'
:
handler_name
,
# If suffix is an empty string, remove the trailing '/'
'suffix'
:
suffix
,
if
not
suffix
:
})
url
=
url
.
rstrip
(
'/'
)
# If suffix is an empty string, remove the trailing '/'
# If there is a query string, append it
if
not
suffix
:
if
query
:
url
=
url
.
rstrip
(
'/'
)
url
+=
'?'
+
query
# If there is a query string, append it
# If third-party, return fully-qualified url
if
query
:
if
thirdparty
:
url
+=
'?'
+
query
scheme
=
"https"
if
settings
.
HTTPS
==
"on"
else
"http"
url
=
'{scheme}://{host}{path}'
.
format
(
# If third-party, return fully-qualified url
scheme
=
scheme
,
if
thirdparty
:
host
=
settings
.
SITE_NAME
,
scheme
=
"https"
if
settings
.
HTTPS
==
"on"
else
"http"
path
=
url
url
=
'{scheme}://{host}{path}'
.
format
(
)
scheme
=
scheme
,
host
=
settings
.
SITE_NAME
,
return
url
path
=
url
)
def
local_resource_url
(
self
,
block
,
uri
):
"""
return
url
local_resource_url for Studio
"""
path
=
reverse
(
'xblock_resource_url'
,
kwargs
=
{
def
local_resource_url
(
block
,
uri
):
'block_type'
:
block
.
scope_ids
.
block_type
,
"""
'uri'
:
uri
,
local_resource_url for Studio
})
"""
return
'//{}{}'
.
format
(
settings
.
SITE_NAME
,
path
)
path
=
reverse
(
'xblock_resource_url'
,
kwargs
=
{
'block_type'
:
block
.
scope_ids
.
block_type
,
'uri'
:
uri
,
})
return
'//{}{}'
.
format
(
settings
.
SITE_NAME
,
path
)
class
LmsPartitionService
(
PartitionService
):
class
LmsPartitionService
(
PartitionService
):
...
@@ -190,7 +194,7 @@ class UserTagsService(object):
...
@@ -190,7 +194,7 @@ class UserTagsService(object):
)
)
class
LmsModuleSystem
(
LmsHandlerUrls
,
ModuleSystem
):
# pylint: disable=abstract-method
class
LmsModuleSystem
(
ModuleSystem
):
# pylint: disable=abstract-method
"""
"""
ModuleSystem specialized to the LMS
ModuleSystem specialized to the LMS
"""
"""
...
@@ -210,6 +214,30 @@ class LmsModuleSystem(LmsHandlerUrls, ModuleSystem): # pylint: disable=abstract
...
@@ -210,6 +214,30 @@ class LmsModuleSystem(LmsHandlerUrls, ModuleSystem): # pylint: disable=abstract
self
.
request_token
=
kwargs
.
pop
(
'request_token'
,
None
)
self
.
request_token
=
kwargs
.
pop
(
'request_token'
,
None
)
super
(
LmsModuleSystem
,
self
)
.
__init__
(
**
kwargs
)
super
(
LmsModuleSystem
,
self
)
.
__init__
(
**
kwargs
)
def
handler_url
(
self
,
*
args
,
**
kwargs
):
"""
Implement the XBlock runtime handler_url interface.
This is mostly just proxying to the module level `handler_url` function
defined higher up in this file.
We're doing this indirection because the module level `handler_url`
logic is also needed by the `DescriptorSystem`. The particular
`handler_url` that a `DescriptorSystem` needs will be different when
running an LMS process or a CMS/Studio process. That's accomplished by
monkey-patching a global. It's a long story, but please know that you
can't just refactor and fold that logic into here without breaking
things.
https://openedx.atlassian.net/wiki/display/PLAT/Convert+from+Storage-centric+runtimes+to+Application-centric+runtimes
See :method:`xblock.runtime:Runtime.handler_url`
"""
return
handler_url
(
*
args
,
**
kwargs
)
def
local_resource_url
(
self
,
*
args
,
**
kwargs
):
return
local_resource_url
(
*
args
,
**
kwargs
)
def
wrap_aside
(
self
,
block
,
aside
,
view
,
frag
,
context
):
def
wrap_aside
(
self
,
block
,
aside
,
view
,
frag
,
context
):
"""
"""
Creates a div which identifies the aside, points to the original block,
Creates a div which identifies the aside, points to the original block,
...
...
lms/djangoapps/lms_xblock/test/test_runtime.py
View file @
87ded08d
...
@@ -8,7 +8,7 @@ from ddt import ddt, data
...
@@ -8,7 +8,7 @@ from ddt import ddt, data
from
mock
import
Mock
from
mock
import
Mock
from
unittest
import
TestCase
from
unittest
import
TestCase
from
urlparse
import
urlparse
from
urlparse
import
urlparse
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
from
opaque_keys.edx.locations
import
BlockUsageLocator
,
CourseLocator
,
SlashSeparatedCourseKey
from
lms.djangoapps.lms_xblock.runtime
import
quote_slashes
,
unquote_slashes
,
LmsModuleSystem
from
lms.djangoapps.lms_xblock.runtime
import
quote_slashes
,
unquote_slashes
,
LmsModuleSystem
from
xblock.fields
import
ScopeIds
from
xblock.fields
import
ScopeIds
...
@@ -39,12 +39,40 @@ class TestQuoteSlashes(TestCase):
...
@@ -39,12 +39,40 @@ class TestQuoteSlashes(TestCase):
self
.
assertNotIn
(
'/'
,
quote_slashes
(
test_string
))
self
.
assertNotIn
(
'/'
,
quote_slashes
(
test_string
))
class
BlockMock
(
Mock
):
"""Mock class that we fill with our "handler" methods."""
def
handler
(
self
,
_context
):
"""
A test handler method.
"""
pass
def
handler1
(
self
,
_context
):
"""
A test handler method.
"""
pass
def
handler_a
(
self
,
_context
):
"""
A test handler method.
"""
pass
@property
def
location
(
self
):
"""Create a functional BlockUsageLocator for testing URL generation."""
course_key
=
CourseLocator
(
org
=
"mockx"
,
course
=
"100"
,
run
=
"2015"
)
return
BlockUsageLocator
(
course_key
,
block_type
=
'mock_type'
,
block_id
=
"mock_id"
)
class
TestHandlerUrl
(
TestCase
):
class
TestHandlerUrl
(
TestCase
):
"""Test the LMS handler_url"""
"""Test the LMS handler_url"""
def
setUp
(
self
):
def
setUp
(
self
):
super
(
TestHandlerUrl
,
self
)
.
setUp
()
super
(
TestHandlerUrl
,
self
)
.
setUp
()
self
.
block
=
Mock
(
name
=
'block'
,
scope_ids
=
ScopeIds
(
None
,
None
,
None
,
'dummy'
))
self
.
block
=
Block
Mock
(
name
=
'block'
,
scope_ids
=
ScopeIds
(
None
,
None
,
None
,
'dummy'
))
self
.
course_key
=
SlashSeparatedCourseKey
(
"org"
,
"course"
,
"run"
)
self
.
course_key
=
SlashSeparatedCourseKey
(
"org"
,
"course"
,
"run"
)
self
.
runtime
=
LmsModuleSystem
(
self
.
runtime
=
LmsModuleSystem
(
static_url
=
'/static'
,
static_url
=
'/static'
,
...
...
lms/startup.py
View file @
87ded08d
...
@@ -16,6 +16,9 @@ from monkey_patch import django_utils_translation
...
@@ -16,6 +16,9 @@ from monkey_patch import django_utils_translation
import
analytics
import
analytics
import
xmodule.x_module
import
lms_xblock.runtime
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
...
@@ -54,6 +57,13 @@ def run():
...
@@ -54,6 +57,13 @@ def run():
set_runtime_service
(
'credit'
,
CreditService
())
set_runtime_service
(
'credit'
,
CreditService
())
set_runtime_service
(
'instructor'
,
InstructorService
())
set_runtime_service
(
'instructor'
,
InstructorService
())
# In order to allow modules to use a handler url, we need to
# monkey-patch the x_module library.
# TODO: Remove this code when Runtimes are no longer created by modulestores
# https://openedx.atlassian.net/wiki/display/PLAT/Convert+from+Storage-centric+runtimes+to+Application-centric+runtimes
xmodule
.
x_module
.
descriptor_global_handler_url
=
lms_xblock
.
runtime
.
handler_url
xmodule
.
x_module
.
descriptor_global_local_resource_url
=
lms_xblock
.
runtime
.
local_resource_url
def
add_mimetypes
():
def
add_mimetypes
():
"""
"""
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment