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
d919d2ae
Commit
d919d2ae
authored
Dec 05, 2014
by
Calen Pennington
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Teach LMS how to render XBlockAsides
[PLAT-217]
parent
e20fe2b8
Show whitespace changes
Inline
Side-by-side
Showing
47 changed files
with
655 additions
and
169 deletions
+655
-169
cms/djangoapps/contentstore/views/assets.py
+2
-1
cms/djangoapps/contentstore/views/item.py
+2
-1
cms/djangoapps/contentstore/views/preview.py
+7
-2
cms/lib/xblock/runtime.py
+11
-0
cms/static/coffee/spec/main.coffee
+1
-0
cms/static/coffee/spec/main_squire.coffee
+1
-0
cms/static/js_test.yml
+1
-0
cms/static/js_test_squire.yml
+1
-0
cms/static/require-config.js
+1
-0
common/djangoapps/xmodule_django/models.py
+24
-5
common/djangoapps/xmodule_modifiers.py
+6
-1
common/lib/xmodule/xmodule/fields.py
+3
-3
common/lib/xmodule/xmodule/modulestore/mongo/base.py
+4
-0
common/lib/xmodule/xmodule/modulestore/split_mongo/caching_descriptor_system.py
+9
-4
common/lib/xmodule/xmodule/modulestore/split_mongo/id_manager.py
+32
-0
common/lib/xmodule/xmodule/modulestore/tests/test_libraries.py
+1
-0
common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py
+1
-1
common/lib/xmodule/xmodule/modulestore/xml.py
+21
-6
common/lib/xmodule/xmodule/tests/__init__.py
+19
-9
common/lib/xmodule/xmodule/tests/test_conditional.py
+2
-2
common/lib/xmodule/xmodule/tests/test_error_module.py
+4
-4
common/lib/xmodule/xmodule/tests/xml/__init__.py
+2
-2
common/lib/xmodule/xmodule/x_module.py
+125
-7
common/static/coffee/spec/xblock/core_spec.coffee
+5
-5
common/static/coffee/src/xblock/core.coffee
+0
-57
common/static/js/xblock/core.js
+142
-0
common/static/js_test.yml
+1
-0
common/test/acceptance/pages/studio/container.py
+1
-1
common/test/acceptance/tests/lms/test_lms_acid_xblock.py
+53
-13
lms/djangoapps/courseware/model_data.py
+52
-19
lms/djangoapps/courseware/models.py
+5
-8
lms/djangoapps/courseware/module_render.py
+10
-4
lms/djangoapps/courseware/tests/test_model_data.py
+3
-2
lms/djangoapps/courseware/views.py
+4
-1
lms/djangoapps/instructor/views/instructor_dashboard.py
+12
-0
lms/djangoapps/lms_xblock/admin.py
+4
-0
lms/djangoapps/lms_xblock/field_data.py
+1
-1
lms/djangoapps/lms_xblock/models.py
+18
-0
lms/djangoapps/lms_xblock/runtime.py
+50
-2
lms/djangoapps/lms_xblock/test/test_runtime.py
+2
-2
lms/djangoapps/open_ended_grading/tests.py
+1
-1
lms/envs/common.py
+3
-1
lms/static/js/spec/main.js
+1
-1
lms/static/js_test.yml
+1
-0
lms/static/js_test_coffee.yml
+1
-0
pylintrc
+2
-0
requirements/edx/github.txt
+3
-3
No files found.
cms/djangoapps/contentstore/views/assets.py
View file @
d919d2ae
...
@@ -201,7 +201,8 @@ def _upload_asset(request, course_key):
...
@@ -201,7 +201,8 @@ def _upload_asset(request, course_key):
'File {filename} exceeds maximum size of '
'File {filename} exceeds maximum size of '
'{size_mb} MB. Please follow the instructions here '
'{size_mb} MB. Please follow the instructions here '
'to upload a file elsewhere and link to it instead: '
'to upload a file elsewhere and link to it instead: '
'{faq_url}'
)
.
format
(
'{faq_url}'
)
.
format
(
filename
=
filename
,
filename
=
filename
,
size_mb
=
settings
.
MAX_ASSET_UPLOAD_FILE_SIZE_IN_MB
,
size_mb
=
settings
.
MAX_ASSET_UPLOAD_FILE_SIZE_IN_MB
,
faq_url
=
settings
.
MAX_ASSET_UPLOAD_FILE_SIZE_URL
,
faq_url
=
settings
.
MAX_ASSET_UPLOAD_FILE_SIZE_URL
,
...
...
cms/djangoapps/contentstore/views/item.py
View file @
d919d2ae
...
@@ -45,7 +45,7 @@ from contentstore.views.helpers import is_unit, xblock_studio_url, xblock_primar
...
@@ -45,7 +45,7 @@ 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
cms.lib.xblock.runtime
import
handler_url
,
local_resource_url
,
get_asides
from
opaque_keys.edx.keys
import
UsageKey
,
CourseKey
from
opaque_keys.edx.keys
import
UsageKey
,
CourseKey
__all__
=
[
'orphan_handler'
,
'xblock_handler'
,
'xblock_view_handler'
,
'xblock_outline_handler'
]
__all__
=
[
'orphan_handler'
,
'xblock_handler'
,
'xblock_view_handler'
,
'xblock_outline_handler'
]
...
@@ -64,6 +64,7 @@ ALWAYS = lambda x: True
...
@@ -64,6 +64,7 @@ ALWAYS = lambda x: True
# TODO: Remove this code when Runtimes are no longer created by modulestores
# 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_handler_url
=
handler_url
xmodule
.
x_module
.
descriptor_global_local_resource_url
=
local_resource_url
xmodule
.
x_module
.
descriptor_global_local_resource_url
=
local_resource_url
xmodule
.
x_module
.
descriptor_global_get_asides
=
get_asides
def
hash_resource
(
resource
):
def
hash_resource
(
resource
):
...
...
cms/djangoapps/contentstore/views/preview.py
View file @
d919d2ae
...
@@ -95,6 +95,10 @@ class PreviewModuleSystem(ModuleSystem): # pylint: disable=abstract-method
...
@@ -95,6 +95,10 @@ class PreviewModuleSystem(ModuleSystem): # pylint: disable=abstract-method
def
local_resource_url
(
self
,
block
,
uri
):
def
local_resource_url
(
self
,
block
,
uri
):
return
local_resource_url
(
block
,
uri
)
return
local_resource_url
(
block
,
uri
)
def
get_asides
(
self
,
block
):
# TODO: Implement this to enable XBlockAsides on previews in Studio
return
[]
class
StudioUserService
(
object
):
class
StudioUserService
(
object
):
"""
"""
...
@@ -110,7 +114,7 @@ class StudioUserService(object):
...
@@ -110,7 +114,7 @@ class StudioUserService(object):
return
self
.
_request
.
user
.
id
return
self
.
_request
.
user
.
id
def
_preview_module_system
(
request
,
descriptor
):
def
_preview_module_system
(
request
,
descriptor
,
field_data
):
"""
"""
Returns a ModuleSystem for the specified descriptor that is specialized for
Returns a ModuleSystem for the specified descriptor that is specialized for
rendering module previews.
rendering module previews.
...
@@ -163,6 +167,7 @@ def _preview_module_system(request, descriptor):
...
@@ -163,6 +167,7 @@ def _preview_module_system(request, descriptor):
descriptor_runtime
=
descriptor
.
runtime
,
descriptor_runtime
=
descriptor
.
runtime
,
services
=
{
services
=
{
"i18n"
:
ModuleI18nService
(),
"i18n"
:
ModuleI18nService
(),
"field-data"
:
field_data
,
},
},
)
)
...
@@ -181,7 +186,7 @@ def _load_preview_module(request, descriptor):
...
@@ -181,7 +186,7 @@ def _load_preview_module(request, descriptor):
else
:
else
:
field_data
=
LmsFieldData
(
descriptor
.
_field_data
,
student_data
)
# pylint: disable=protected-access
field_data
=
LmsFieldData
(
descriptor
.
_field_data
,
student_data
)
# pylint: disable=protected-access
descriptor
.
bind_for_student
(
descriptor
.
bind_for_student
(
_preview_module_system
(
request
,
descriptor
),
_preview_module_system
(
request
,
descriptor
,
field_data
),
field_data
field_data
)
)
return
descriptor
return
descriptor
...
...
cms/lib/xblock/runtime.py
View file @
d919d2ae
...
@@ -33,3 +33,14 @@ def local_resource_url(block, uri):
...
@@ -33,3 +33,14 @@ def local_resource_url(block, uri):
'block_type'
:
block
.
scope_ids
.
block_type
,
'block_type'
:
block
.
scope_ids
.
block_type
,
'uri'
:
uri
,
'uri'
:
uri
,
})
})
def
get_asides
(
block
):
# pylint: disable=unused-argument
"""
Return all of the asides which might be decorating this `block`.
Arguments:
block (:class:`.XBlock`): The block to render retrieve asides for.
"""
# TODO: Implement this method to make XBlockAsides for editing views in Studio
return
[]
cms/static/coffee/spec/main.coffee
View file @
d919d2ae
...
@@ -32,6 +32,7 @@ requirejs.config({
...
@@ -32,6 +32,7 @@ requirejs.config({
"jquery.tinymce"
:
"xmodule_js/common_static/js/vendor/tinymce/js/tinymce/jquery.tinymce"
,
"jquery.tinymce"
:
"xmodule_js/common_static/js/vendor/tinymce/js/tinymce/jquery.tinymce"
,
"xmodule"
:
"xmodule_js/src/xmodule"
,
"xmodule"
:
"xmodule_js/src/xmodule"
,
"xblock/cms.runtime.v1"
:
"coffee/src/xblock/cms.runtime.v1"
,
"xblock/cms.runtime.v1"
:
"coffee/src/xblock/cms.runtime.v1"
,
"xblock/core"
:
"xmodule_js/common_static/js/xblock/core"
,
"xblock"
:
"xmodule_js/common_static/coffee/src/xblock"
,
"xblock"
:
"xmodule_js/common_static/coffee/src/xblock"
,
"utility"
:
"xmodule_js/common_static/js/src/utility"
,
"utility"
:
"xmodule_js/common_static/js/src/utility"
,
"accessibility"
:
"xmodule_js/common_static/js/src/accessibility_tools"
,
"accessibility"
:
"xmodule_js/common_static/js/src/accessibility_tools"
,
...
...
cms/static/coffee/spec/main_squire.coffee
View file @
d919d2ae
...
@@ -30,6 +30,7 @@ requirejs.config({
...
@@ -30,6 +30,7 @@ requirejs.config({
"jquery.tinymce"
:
"xmodule_js/common_static/js/vendor/tinymce/js/tinymce/jquery.tinymce"
,
"jquery.tinymce"
:
"xmodule_js/common_static/js/vendor/tinymce/js/tinymce/jquery.tinymce"
,
"xmodule"
:
"xmodule_js/src/xmodule"
,
"xmodule"
:
"xmodule_js/src/xmodule"
,
"xblock/cms.runtime.v1"
:
"coffee/src/xblock/cms.runtime.v1"
,
"xblock/cms.runtime.v1"
:
"coffee/src/xblock/cms.runtime.v1"
,
"xblock/core"
:
"xmodule_js/common_static/js/xblock/core"
,
"xblock"
:
"xmodule_js/common_static/coffee/src/xblock"
,
"xblock"
:
"xmodule_js/common_static/coffee/src/xblock"
,
"utility"
:
"xmodule_js/common_static/js/src/utility"
,
"utility"
:
"xmodule_js/common_static/js/src/utility"
,
"sinon"
:
"xmodule_js/common_static/js/vendor/sinon-1.7.1"
,
"sinon"
:
"xmodule_js/common_static/js/vendor/sinon-1.7.1"
,
...
...
cms/static/js_test.yml
View file @
d919d2ae
...
@@ -60,6 +60,7 @@ lib_paths:
...
@@ -60,6 +60,7 @@ lib_paths:
-
xmodule_js/common_static/js/vendor/URI.min.js
-
xmodule_js/common_static/js/vendor/URI.min.js
-
xmodule_js/common_static/js/vendor/jquery.smooth-scroll.min.js
-
xmodule_js/common_static/js/vendor/jquery.smooth-scroll.min.js
-
xmodule_js/common_static/coffee/src/jquery.immediateDescendents.js
-
xmodule_js/common_static/coffee/src/jquery.immediateDescendents.js
-
xmodule_js/common_static/js/xblock/
-
xmodule_js/common_static/coffee/src/xblock/
-
xmodule_js/common_static/coffee/src/xblock/
-
xmodule_js/common_static/js/vendor/URI.min.js
-
xmodule_js/common_static/js/vendor/URI.min.js
-
xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport.js
-
xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport.js
...
...
cms/static/js_test_squire.yml
View file @
d919d2ae
...
@@ -55,6 +55,7 @@ lib_paths:
...
@@ -55,6 +55,7 @@ lib_paths:
-
xmodule_js/src/xmodule.js
-
xmodule_js/src/xmodule.js
-
xmodule_js/common_static/coffee/src/jquery.immediateDescendents.js
-
xmodule_js/common_static/coffee/src/jquery.immediateDescendents.js
-
xmodule_js/common_static/js/test/i18n.js
-
xmodule_js/common_static/js/test/i18n.js
-
xmodule_js/common_static/js/xblock/
-
xmodule_js/common_static/coffee/src/xblock/
-
xmodule_js/common_static/coffee/src/xblock/
-
xmodule_js/common_static/js/vendor/URI.min.js
-
xmodule_js/common_static/js/vendor/URI.min.js
-
xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport.js
-
xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport.js
...
...
cms/static/require-config.js
View file @
d919d2ae
...
@@ -35,6 +35,7 @@ require.config({
...
@@ -35,6 +35,7 @@ require.config({
"tinymce"
:
"js/vendor/tinymce/js/tinymce/tinymce.full.min"
,
"tinymce"
:
"js/vendor/tinymce/js/tinymce/tinymce.full.min"
,
"jquery.tinymce"
:
"js/vendor/tinymce/js/tinymce/jquery.tinymce.min"
,
"jquery.tinymce"
:
"js/vendor/tinymce/js/tinymce/jquery.tinymce.min"
,
"xmodule"
:
"/xmodule/xmodule"
,
"xmodule"
:
"/xmodule/xmodule"
,
"xblock/core"
:
"js/xblock/core"
,
"xblock"
:
"coffee/src/xblock"
,
"xblock"
:
"coffee/src/xblock"
,
"utility"
:
"js/src/utility"
,
"utility"
:
"js/src/utility"
,
"accessibility"
:
"js/src/accessibility_tools"
,
"accessibility"
:
"js/src/accessibility_tools"
,
...
...
common/djangoapps/xmodule_django/models.py
View file @
d919d2ae
"""
Useful django models for implementing XBlock infrastructure in django.
"""
import
warnings
import
warnings
from
django.db
import
models
from
django.db
import
models
from
django.core.exceptions
import
ValidationError
from
django.core.exceptions
import
ValidationError
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
,
Location
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
,
Location
from
opaque_keys.edx.keys
import
CourseKey
,
UsageKey
from
opaque_keys.edx.keys
import
CourseKey
,
UsageKey
,
BlockTypeKey
from
opaque_keys.edx.locator
import
Locator
from
opaque_keys.edx.locator
import
Locator
from
south.modelsinspector
import
add_introspection_rules
from
south.modelsinspector
import
add_introspection_rules
...
@@ -91,7 +95,6 @@ class OpaqueKeyField(models.CharField):
...
@@ -91,7 +95,6 @@ class OpaqueKeyField(models.CharField):
super
(
OpaqueKeyField
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
super
(
OpaqueKeyField
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
def
to_python
(
self
,
value
):
def
to_python
(
self
,
value
):
if
value
is
self
.
Empty
or
value
is
None
:
if
value
is
self
.
Empty
or
value
is
None
:
return
None
return
None
...
@@ -140,22 +143,38 @@ class OpaqueKeyField(models.CharField):
...
@@ -140,22 +143,38 @@ class OpaqueKeyField(models.CharField):
class
CourseKeyField
(
OpaqueKeyField
):
class
CourseKeyField
(
OpaqueKeyField
):
"""
A django Field that stores a CourseKey object as a string.
"""
description
=
"A CourseKey object, saved to the DB in the form of a string"
description
=
"A CourseKey object, saved to the DB in the form of a string"
KEY_CLASS
=
CourseKey
KEY_CLASS
=
CourseKey
class
UsageKeyField
(
OpaqueKeyField
):
class
UsageKeyField
(
OpaqueKeyField
):
"""
A django Field that stores a UsageKey object as a string.
"""
description
=
"A Location object, saved to the DB in the form of a string"
description
=
"A Location object, saved to the DB in the form of a string"
KEY_CLASS
=
UsageKey
KEY_CLASS
=
UsageKey
class
LocationKeyField
(
UsageKeyField
):
class
LocationKeyField
(
UsageKeyField
):
"""
A django Field that stores a UsageKey object as a string.
"""
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
warnings
.
warn
(
"LocationKeyField is deprecated. Please use UsageKeyField instead."
,
stacklevel
=
2
)
warnings
.
warn
(
"LocationKeyField is deprecated. Please use UsageKeyField instead."
,
stacklevel
=
2
)
super
(
LocationKeyField
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
super
(
LocationKeyField
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
class
BlockTypeKeyField
(
OpaqueKeyField
):
"""
A django Field that stores a BlockTypeKey object as a string.
"""
description
=
"A BlockTypeKey object, saved to the DB in the form of a string."
KEY_CLASS
=
BlockTypeKey
add_introspection_rules
([],
[
"^xmodule_django
\
.models
\
.CourseKeyField"
])
add_introspection_rules
([],
[
r
"^xmodule_django\.models\.CourseKeyField"
])
add_introspection_rules
([],
[
"^xmodule_django
\
.models
\
.LocationKeyField"
])
add_introspection_rules
([],
[
r
"^xmodule_django\.models\.LocationKeyField"
])
add_introspection_rules
([],
[
"^xmodule_django
\
.models
\
.UsageKeyField"
])
add_introspection_rules
([],
[
r
"^xmodule_django\.models\.UsageKeyField"
])
common/djangoapps/xmodule_modifiers.py
View file @
d919d2ae
...
@@ -72,7 +72,11 @@ def wrap_xblock(runtime_class, block, view, frag, context, usage_id_serializer,
...
@@ -72,7 +72,11 @@ def wrap_xblock(runtime_class, block, view, frag, context, usage_id_serializer,
data
=
{}
data
=
{}
data
.
update
(
extra_data
)
data
.
update
(
extra_data
)
css_classes
=
[
'xblock'
,
'xblock-{}'
.
format
(
markupsafe
.
escape
(
view
))]
css_classes
=
[
'xblock'
,
'xblock-{}'
.
format
(
markupsafe
.
escape
(
view
))
]
if
isinstance
(
block
,
(
XModule
,
XModuleDescriptor
)):
if
isinstance
(
block
,
(
XModule
,
XModuleDescriptor
)):
if
view
in
PREVIEW_VIEWS
:
if
view
in
PREVIEW_VIEWS
:
...
@@ -90,6 +94,7 @@ def wrap_xblock(runtime_class, block, view, frag, context, usage_id_serializer,
...
@@ -90,6 +94,7 @@ def wrap_xblock(runtime_class, block, view, frag, context, usage_id_serializer,
data
[
'init'
]
=
frag
.
js_init_fn
data
[
'init'
]
=
frag
.
js_init_fn
data
[
'runtime-class'
]
=
runtime_class
data
[
'runtime-class'
]
=
runtime_class
data
[
'runtime-version'
]
=
frag
.
js_init_version
data
[
'runtime-version'
]
=
frag
.
js_init_version
data
[
'block-type'
]
=
block
.
scope_ids
.
block_type
data
[
'block-type'
]
=
block
.
scope_ids
.
block_type
data
[
'usage-id'
]
=
usage_id_serializer
(
block
.
scope_ids
.
usage_id
)
data
[
'usage-id'
]
=
usage_id_serializer
(
block
.
scope_ids
.
usage_id
)
data
[
'request-token'
]
=
request_token
data
[
'request-token'
]
=
request_token
...
...
common/lib/xmodule/xmodule/fields.py
View file @
d919d2ae
...
@@ -33,7 +33,7 @@ class Date(JSONField):
...
@@ -33,7 +33,7 @@ class Date(JSONField):
result
=
dateutil
.
parser
.
parse
(
field
,
default
=
self
.
PREVENT_DEFAULT_DAY_MON_SEED1
)
result
=
dateutil
.
parser
.
parse
(
field
,
default
=
self
.
PREVENT_DEFAULT_DAY_MON_SEED1
)
result_other
=
dateutil
.
parser
.
parse
(
field
,
default
=
self
.
PREVENT_DEFAULT_DAY_MON_SEED2
)
result_other
=
dateutil
.
parser
.
parse
(
field
,
default
=
self
.
PREVENT_DEFAULT_DAY_MON_SEED2
)
if
result
!=
result_other
:
if
result
!=
result_other
:
log
.
warning
(
"Field {0} is missing month or day"
.
format
(
self
.
_name
,
field
))
log
.
warning
(
"Field {0} is missing month or day"
.
format
(
self
.
name
))
return
None
return
None
if
result
.
tzinfo
is
None
:
if
result
.
tzinfo
is
None
:
result
=
result
.
replace
(
tzinfo
=
UTC
)
result
=
result
.
replace
(
tzinfo
=
UTC
)
...
@@ -59,7 +59,7 @@ class Date(JSONField):
...
@@ -59,7 +59,7 @@ class Date(JSONField):
return
field
return
field
else
:
else
:
msg
=
"Field {0} has bad value '{1}'"
.
format
(
msg
=
"Field {0} has bad value '{1}'"
.
format
(
self
.
_
name
,
field
)
self
.
name
,
field
)
raise
TypeError
(
msg
)
raise
TypeError
(
msg
)
def
to_json
(
self
,
value
):
def
to_json
(
self
,
value
):
...
@@ -199,7 +199,7 @@ class RelativeTime(JSONField):
...
@@ -199,7 +199,7 @@ class RelativeTime(JSONField):
if
isinstance
(
value
,
basestring
):
if
isinstance
(
value
,
basestring
):
return
self
.
isotime_to_timedelta
(
value
)
return
self
.
isotime_to_timedelta
(
value
)
msg
=
"RelativeTime Field {0} has bad value '{1!r}'"
.
format
(
self
.
_
name
,
value
)
msg
=
"RelativeTime Field {0} has bad value '{1!r}'"
.
format
(
self
.
name
,
value
)
raise
TypeError
(
msg
)
raise
TypeError
(
msg
)
def
to_json
(
self
,
value
):
def
to_json
(
self
,
value
):
...
...
common/lib/xmodule/xmodule/modulestore/mongo/base.py
View file @
d919d2ae
...
@@ -50,6 +50,7 @@ from xmodule.modulestore.draft_and_published import ModuleStoreDraftAndPublished
...
@@ -50,6 +50,7 @@ from xmodule.modulestore.draft_and_published import ModuleStoreDraftAndPublished
from
xmodule.modulestore.edit_info
import
EditInfoRuntimeMixin
from
xmodule.modulestore.edit_info
import
EditInfoRuntimeMixin
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
,
DuplicateCourseError
,
ReferentialIntegrityError
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
,
DuplicateCourseError
,
ReferentialIntegrityError
from
xmodule.modulestore.inheritance
import
InheritanceMixin
,
inherit_metadata
,
InheritanceKeyValueStore
from
xmodule.modulestore.inheritance
import
InheritanceMixin
,
inherit_metadata
,
InheritanceKeyValueStore
from
xmodule.modulestore.xml
import
CourseLocationManager
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
...
@@ -173,6 +174,9 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin):
...
@@ -173,6 +174,9 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin):
render_template: a function for rendering templates, as per
render_template: a function for rendering templates, as per
MakoDescriptorSystem
MakoDescriptorSystem
"""
"""
id_manager
=
CourseLocationManager
(
course_key
)
kwargs
.
setdefault
(
'id_reader'
,
id_manager
)
kwargs
.
setdefault
(
'id_generator'
,
id_manager
)
super
(
CachingDescriptorSystem
,
self
)
.
__init__
(
super
(
CachingDescriptorSystem
,
self
)
.
__init__
(
field_data
=
None
,
field_data
=
None
,
load_item
=
self
.
load_item
,
load_item
=
self
.
load_item
,
...
...
common/lib/xmodule/xmodule/modulestore/split_mongo/caching_descriptor_system.py
View file @
d919d2ae
import
sys
import
sys
import
logging
import
logging
from
contracts
import
contract
,
new_contract
from
contracts
import
contract
,
new_contract
from
fs.osfs
import
OSFS
from
lazy
import
lazy
from
lazy
import
lazy
from
xblock.runtime
import
KvsFieldData
from
xblock.runtime
import
KvsFieldData
from
xblock.fields
import
ScopeIds
from
xblock.fields
import
ScopeIds
...
@@ -8,13 +9,13 @@ from opaque_keys.edx.locator import BlockUsageLocator, LocalId, CourseLocator, L
...
@@ -8,13 +9,13 @@ from opaque_keys.edx.locator import BlockUsageLocator, LocalId, CourseLocator, L
from
xmodule.mako_module
import
MakoDescriptorSystem
from
xmodule.mako_module
import
MakoDescriptorSystem
from
xmodule.error_module
import
ErrorDescriptor
from
xmodule.error_module
import
ErrorDescriptor
from
xmodule.errortracker
import
exc_info_to_str
from
xmodule.errortracker
import
exc_info_to_str
from
..exceptions
import
ItemNotFoundError
from
.split_mongo_kvs
import
SplitMongoKVS
from
fs.osfs
import
OSFS
from
.definition_lazy_loader
import
DefinitionLazyLoader
from
xmodule.modulestore.edit_info
import
EditInfoRuntimeMixin
from
xmodule.modulestore.edit_info
import
EditInfoRuntimeMixin
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
xmodule.modulestore.inheritance
import
inheriting_field_data
,
InheritanceMixin
from
xmodule.modulestore.inheritance
import
inheriting_field_data
,
InheritanceMixin
from
xmodule.modulestore.split_mongo
import
BlockKey
,
CourseEnvelope
from
xmodule.modulestore.split_mongo
import
BlockKey
,
CourseEnvelope
from
xmodule.modulestore.split_mongo.id_manager
import
SplitMongoIdManager
from
xmodule.modulestore.split_mongo.definition_lazy_loader
import
DefinitionLazyLoader
from
xmodule.modulestore.split_mongo.split_mongo_kvs
import
SplitMongoKVS
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
...
@@ -54,6 +55,10 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin):
...
@@ -54,6 +55,10 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin):
root
=
modulestore
.
fs_root
/
course_entry
.
structure
[
'_id'
]
root
=
modulestore
.
fs_root
/
course_entry
.
structure
[
'_id'
]
root
.
makedirs_p
()
# create directory if it doesn't exist
root
.
makedirs_p
()
# create directory if it doesn't exist
id_manager
=
SplitMongoIdManager
(
self
)
kwargs
.
setdefault
(
'id_reader'
,
id_manager
)
kwargs
.
setdefault
(
'id_generator'
,
id_manager
)
super
(
CachingDescriptorSystem
,
self
)
.
__init__
(
super
(
CachingDescriptorSystem
,
self
)
.
__init__
(
field_data
=
None
,
field_data
=
None
,
load_item
=
self
.
_load_item
,
load_item
=
self
.
_load_item
,
...
...
common/lib/xmodule/xmodule/modulestore/split_mongo/id_manager.py
0 → 100644
View file @
d919d2ae
"""
An implementation of IdReader and IdGenerator that manages ids for the SplitMongo storage
mechanism.
"""
from
opaque_keys.edx.locator
import
LocalId
,
DefinitionLocator
from
xmodule.x_module
import
OpaqueKeyReader
,
AsideKeyGenerator
from
xmodule.modulestore.split_mongo
import
BlockKey
# TODO: Migrate split_mongo to use this class for all key mapping/creation.
class
SplitMongoIdManager
(
OpaqueKeyReader
,
AsideKeyGenerator
):
# pylint: disable=abstract-method
"""
An IdManager that knows how to retrieve the DefinitionLocator, given
a usage_id and a :class:`.CachingDescriptorSystem`.
"""
def
__init__
(
self
,
caching_descriptor_system
):
self
.
_cds
=
caching_descriptor_system
def
get_definition_id
(
self
,
usage_id
):
if
isinstance
(
usage_id
.
block_id
,
LocalId
):
# a LocalId indicates that this block hasn't been persisted yet, and is instead stored
# in-memory in the local_modules dictionary.
return
self
.
_cds
.
local_modules
[
usage_id
]
.
scope_ids
.
def_id
else
:
block_key
=
BlockKey
.
from_usage_key
(
usage_id
)
module_data
=
self
.
_cds
.
get_module_data
(
block_key
,
usage_id
.
course_key
)
if
'definition'
in
module_data
:
return
DefinitionLocator
(
usage_id
.
block_type
,
module_data
[
'definition'
])
else
:
raise
ValueError
(
"All non-local blocks should have a definition specified"
)
common/lib/xmodule/xmodule/modulestore/tests/test_libraries.py
View file @
d919d2ae
...
@@ -203,5 +203,6 @@ class TestLibraries(MixedSplitTestCase):
...
@@ -203,5 +203,6 @@ class TestLibraries(MixedSplitTestCase):
message
=
u"Hello world"
message
=
u"Hello world"
hello_render
=
lambda
_
,
context
:
Fragment
(
message
)
hello_render
=
lambda
_
,
context
:
Fragment
(
message
)
with
patch
(
'xmodule.html_module.HtmlDescriptor.author_view'
,
hello_render
,
create
=
True
):
with
patch
(
'xmodule.html_module.HtmlDescriptor.author_view'
,
hello_render
,
create
=
True
):
with
patch
(
'xmodule.x_module.descriptor_global_get_asides'
,
lambda
block
:
[]):
result
=
library
.
render
(
AUTHOR_VIEW
,
context
)
result
=
library
.
render
(
AUTHOR_VIEW
,
context
)
self
.
assertIn
(
message
,
result
.
content
)
self
.
assertIn
(
message
,
result
.
content
)
common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py
View file @
d919d2ae
...
@@ -420,7 +420,7 @@ class TestMongoModuleStore(TestMongoModuleStoreBase):
...
@@ -420,7 +420,7 @@ class TestMongoModuleStore(TestMongoModuleStoreBase):
assert_equals
(
len
(
course_locations
),
1
)
assert_equals
(
len
(
course_locations
),
1
)
assert_in
(
SlashSeparatedCourseKey
(
'edX'
,
'simple'
,
'2012_Fall'
),
course_locations
)
assert_in
(
SlashSeparatedCourseKey
(
'edX'
,
'simple'
,
'2012_Fall'
),
course_locations
)
@
Plugin
.register_temp_plugin
(
ReferenceTestXBlock
,
'ref_test'
)
@
XBlock
.register_temp_plugin
(
ReferenceTestXBlock
,
'ref_test'
)
def
test_reference_converters
(
self
):
def
test_reference_converters
(
self
):
"""
"""
Test that references types get deserialized correctly
Test that references types get deserialized correctly
...
...
common/lib/xmodule/xmodule/modulestore/xml.py
View file @
d919d2ae
...
@@ -18,7 +18,7 @@ from contextlib import contextmanager
...
@@ -18,7 +18,7 @@ from contextlib import contextmanager
from
xmodule.error_module
import
ErrorDescriptor
from
xmodule.error_module
import
ErrorDescriptor
from
xmodule.errortracker
import
make_error_tracker
,
exc_info_to_str
from
xmodule.errortracker
import
make_error_tracker
,
exc_info_to_str
from
xmodule.mako_module
import
MakoDescriptorSystem
from
xmodule.mako_module
import
MakoDescriptorSystem
from
xmodule.x_module
import
XMLParsingSystem
,
policy_key
from
xmodule.x_module
import
XMLParsingSystem
,
policy_key
,
OpaqueKeyReader
,
AsideKeyGenerator
from
xmodule.modulestore.xml_exporter
import
DEFAULT_CONTENT_FIELDS
from
xmodule.modulestore.xml_exporter
import
DEFAULT_CONTENT_FIELDS
from
xmodule.modulestore
import
ModuleStoreEnum
,
ModuleStoreReadBase
from
xmodule.modulestore
import
ModuleStoreEnum
,
ModuleStoreReadBase
from
xmodule.tabs
import
CourseTabList
from
xmodule.tabs
import
CourseTabList
...
@@ -27,7 +27,7 @@ from opaque_keys.edx.locations import SlashSeparatedCourseKey, Location
...
@@ -27,7 +27,7 @@ from opaque_keys.edx.locations import SlashSeparatedCourseKey, Location
from
opaque_keys.edx.locator
import
CourseLocator
from
opaque_keys.edx.locator
import
CourseLocator
from
xblock.field_data
import
DictFieldData
from
xblock.field_data
import
DictFieldData
from
xblock.runtime
import
DictKeyValueStore
,
IdGenerator
from
xblock.runtime
import
DictKeyValueStore
from
.exceptions
import
ItemNotFoundError
from
.exceptions
import
ItemNotFoundError
...
@@ -64,7 +64,6 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):
...
@@ -64,7 +64,6 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):
"""
"""
self
.
unnamed
=
defaultdict
(
int
)
# category -> num of new url_names for that category
self
.
unnamed
=
defaultdict
(
int
)
# category -> num of new url_names for that category
self
.
used_names
=
defaultdict
(
set
)
# category -> set of used url_names
self
.
used_names
=
defaultdict
(
set
)
# category -> set of used url_names
id_generator
=
CourseLocationGenerator
(
course_id
)
# cdodge: adding the course_id as passed in for later reference rather than having to recomine the org/course/url_name
# cdodge: adding the course_id as passed in for later reference rather than having to recomine the org/course/url_name
self
.
course_id
=
course_id
self
.
course_id
=
course_id
...
@@ -175,7 +174,7 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):
...
@@ -175,7 +174,7 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):
descriptor
=
create_block_from_xml
(
descriptor
=
create_block_from_xml
(
etree
.
tostring
(
xml_data
,
encoding
=
'unicode'
),
etree
.
tostring
(
xml_data
,
encoding
=
'unicode'
),
self
,
self
,
id_
generato
r
,
id_
manage
r
,
)
)
except
Exception
as
err
:
# pylint: disable=broad-except
except
Exception
as
err
:
# pylint: disable=broad-except
if
not
self
.
load_error_modules
:
if
not
self
.
load_error_modules
:
...
@@ -201,7 +200,7 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):
...
@@ -201,7 +200,7 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):
descriptor
=
ErrorDescriptor
.
from_xml
(
descriptor
=
ErrorDescriptor
.
from_xml
(
xml
,
xml
,
self
,
self
,
id_
generato
r
,
id_
manage
r
,
err_msg
err_msg
)
)
...
@@ -229,12 +228,16 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):
...
@@ -229,12 +228,16 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):
resources_fs
=
OSFS
(
xmlstore
.
data_dir
/
course_dir
)
resources_fs
=
OSFS
(
xmlstore
.
data_dir
/
course_dir
)
id_manager
=
CourseLocationManager
(
course_id
)
super
(
ImportSystem
,
self
)
.
__init__
(
super
(
ImportSystem
,
self
)
.
__init__
(
load_item
=
load_item
,
load_item
=
load_item
,
resources_fs
=
resources_fs
,
resources_fs
=
resources_fs
,
render_template
=
render_template
,
render_template
=
render_template
,
error_tracker
=
error_tracker
,
error_tracker
=
error_tracker
,
process_xml
=
process_xml
,
process_xml
=
process_xml
,
id_generator
=
id_manager
,
id_reader
=
id_manager
,
**
kwargs
**
kwargs
)
)
...
@@ -245,12 +248,13 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):
...
@@ -245,12 +248,13 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):
block
.
children
.
append
(
child_block
.
scope_ids
.
usage_id
)
block
.
children
.
append
(
child_block
.
scope_ids
.
usage_id
)
class
CourseLocation
Generator
(
Id
Generator
):
class
CourseLocation
Manager
(
OpaqueKeyReader
,
AsideKey
Generator
):
"""
"""
IdGenerator for Location-based definition ids and usage ids
IdGenerator for Location-based definition ids and usage ids
based within a course
based within a course
"""
"""
def
__init__
(
self
,
course_id
):
def
__init__
(
self
,
course_id
):
super
(
CourseLocationManager
,
self
)
.
__init__
()
self
.
course_id
=
course_id
self
.
course_id
=
course_id
self
.
autogen_ids
=
itertools
.
count
(
0
)
self
.
autogen_ids
=
itertools
.
count
(
0
)
...
@@ -263,6 +267,17 @@ class CourseLocationGenerator(IdGenerator):
...
@@ -263,6 +267,17 @@ class CourseLocationGenerator(IdGenerator):
slug
=
'autogen_{}_{}'
.
format
(
block_type
,
self
.
autogen_ids
.
next
())
slug
=
'autogen_{}_{}'
.
format
(
block_type
,
self
.
autogen_ids
.
next
())
return
self
.
course_id
.
make_usage_key
(
block_type
,
slug
)
return
self
.
course_id
.
make_usage_key
(
block_type
,
slug
)
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
def
_make_usage_key
(
course_key
,
value
):
def
_make_usage_key
(
course_key
,
value
):
"""
"""
...
...
common/lib/xmodule/xmodule/tests/__init__.py
View file @
d919d2ae
...
@@ -28,6 +28,7 @@ from xmodule.mako_module import MakoDescriptorSystem
...
@@ -28,6 +28,7 @@ from xmodule.mako_module import MakoDescriptorSystem
from
xmodule.error_module
import
ErrorDescriptor
from
xmodule.error_module
import
ErrorDescriptor
from
xmodule.modulestore
import
ModuleStoreEnum
from
xmodule.modulestore
import
ModuleStoreEnum
from
xmodule.modulestore.mongo.draft
import
DraftModuleStore
from
xmodule.modulestore.mongo.draft
import
DraftModuleStore
from
xmodule.modulestore.xml
import
CourseLocationManager
from
xmodule.modulestore.draft_and_published
import
DIRECT_ONLY_CATEGORIES
,
ModuleStoreDraftAndPublished
from
xmodule.modulestore.draft_and_published
import
DIRECT_ONLY_CATEGORIES
,
ModuleStoreDraftAndPublished
...
@@ -51,9 +52,16 @@ class TestModuleSystem(ModuleSystem): # pylint: disable=abstract-method
...
@@ -51,9 +52,16 @@ class TestModuleSystem(ModuleSystem): # pylint: disable=abstract-method
"""
"""
ModuleSystem for testing
ModuleSystem for testing
"""
"""
def
__init__
(
self
,
**
kwargs
):
id_manager
=
CourseLocationManager
(
kwargs
[
'course_id'
])
kwargs
.
setdefault
(
'id_reader'
,
id_manager
)
kwargs
.
setdefault
(
'id_generator'
,
id_manager
)
kwargs
.
setdefault
(
'services'
,
{})
.
setdefault
(
'field-data'
,
DictFieldData
({}))
super
(
TestModuleSystem
,
self
)
.
__init__
(
**
kwargs
)
def
handler_url
(
self
,
block
,
handler
,
suffix
=
''
,
query
=
''
,
thirdparty
=
False
):
def
handler_url
(
self
,
block
,
handler
,
suffix
=
''
,
query
=
''
,
thirdparty
=
False
):
return
'{usage_id}/{handler}{suffix}?{query}'
.
format
(
return
'{usage_id}/{handler}{suffix}?{query}'
.
format
(
usage_id
=
block
.
scope_ids
.
usage_id
.
to_deprecated_string
(
),
usage_id
=
unicode
(
block
.
scope_ids
.
usage_id
),
handler
=
handler
,
handler
=
handler
,
suffix
=
suffix
,
suffix
=
suffix
,
query
=
query
,
query
=
query
,
...
@@ -61,10 +69,14 @@ class TestModuleSystem(ModuleSystem): # pylint: disable=abstract-method
...
@@ -61,10 +69,14 @@ class TestModuleSystem(ModuleSystem): # pylint: disable=abstract-method
def
local_resource_url
(
self
,
block
,
uri
):
def
local_resource_url
(
self
,
block
,
uri
):
return
'resource/{usage_id}/{uri}'
.
format
(
return
'resource/{usage_id}/{uri}'
.
format
(
usage_id
=
block
.
scope_ids
.
usage_id
.
to_deprecated_string
(
),
usage_id
=
unicode
(
block
.
scope_ids
.
usage_id
),
uri
=
uri
,
uri
=
uri
,
)
)
# Disable XBlockAsides in most tests
def
get_asides
(
self
,
block
):
return
[]
def
get_test_system
(
course_id
=
SlashSeparatedCourseKey
(
'org'
,
'course'
,
'run'
)):
def
get_test_system
(
course_id
=
SlashSeparatedCourseKey
(
'org'
,
'course'
,
'run'
)):
"""
"""
...
@@ -113,13 +125,16 @@ def get_test_descriptor_system():
...
@@ -113,13 +125,16 @@ def get_test_descriptor_system():
"""
"""
Construct a test DescriptorSystem instance.
Construct a test DescriptorSystem instance.
"""
"""
field_data
=
DictFieldData
({})
return
MakoDescriptorSystem
(
return
MakoDescriptorSystem
(
load_item
=
Mock
(),
load_item
=
Mock
(),
resources_fs
=
Mock
(),
resources_fs
=
Mock
(),
error_tracker
=
Mock
(),
error_tracker
=
Mock
(),
render_template
=
mock_render_template
,
render_template
=
mock_render_template
,
mixins
=
(
InheritanceMixin
,
XModuleMixin
),
mixins
=
(
InheritanceMixin
,
XModuleMixin
),
field_data
=
DictFieldData
({}),
field_data
=
field_data
,
services
=
{
'field-data'
:
field_data
},
)
)
...
@@ -149,13 +164,8 @@ class LogicTest(unittest.TestCase):
...
@@ -149,13 +164,8 @@ class LogicTest(unittest.TestCase):
raw_field_data
=
{}
raw_field_data
=
{}
def
setUp
(
self
):
def
setUp
(
self
):
class
EmptyClass
:
"""Empty object."""
url_name
=
''
category
=
'test'
self
.
system
=
get_test_system
()
self
.
system
=
get_test_system
()
self
.
descriptor
=
EmptyClass
(
)
self
.
descriptor
=
Mock
(
name
=
"descriptor"
,
url_name
=
''
,
category
=
'test'
)
self
.
xmodule_class
=
self
.
descriptor_class
.
module_class
self
.
xmodule_class
=
self
.
descriptor_class
.
module_class
usage_key
=
self
.
system
.
course_id
.
make_usage_key
(
self
.
descriptor
.
category
,
'test_loc'
)
usage_key
=
self
.
system
.
course_id
.
make_usage_key
(
self
.
descriptor
.
category
,
'test_loc'
)
...
...
common/lib/xmodule/xmodule/tests/test_conditional.py
View file @
d919d2ae
...
@@ -8,7 +8,7 @@ from xblock.field_data import DictFieldData
...
@@ -8,7 +8,7 @@ from xblock.field_data import DictFieldData
from
xblock.fields
import
ScopeIds
from
xblock.fields
import
ScopeIds
from
xmodule.error_module
import
NonStaffErrorDescriptor
from
xmodule.error_module
import
NonStaffErrorDescriptor
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
,
Location
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
,
Location
from
xmodule.modulestore.xml
import
ImportSystem
,
XMLModuleStore
,
CourseLocation
Generato
r
from
xmodule.modulestore.xml
import
ImportSystem
,
XMLModuleStore
,
CourseLocation
Manage
r
from
xmodule.conditional_module
import
ConditionalDescriptor
from
xmodule.conditional_module
import
ConditionalDescriptor
from
xmodule.tests
import
DATA_DIR
,
get_test_system
,
get_test_descriptor_system
from
xmodule.tests
import
DATA_DIR
,
get_test_system
,
get_test_descriptor_system
from
xmodule.x_module
import
STUDENT_VIEW
from
xmodule.x_module
import
STUDENT_VIEW
...
@@ -60,7 +60,7 @@ class ConditionalFactory(object):
...
@@ -60,7 +60,7 @@ class ConditionalFactory(object):
source_descriptor
=
NonStaffErrorDescriptor
.
from_xml
(
source_descriptor
=
NonStaffErrorDescriptor
.
from_xml
(
'some random xml data'
,
'some random xml data'
,
system
,
system
,
id_generator
=
CourseLocation
Generator
(
SlashSeparatedCourseKey
(
'edX'
,
'conditional_test'
,
'test_run'
)
),
id_generator
=
CourseLocation
Manager
(
source_location
.
course_key
),
error_msg
=
'random error message'
error_msg
=
'random error message'
)
)
else
:
else
:
...
...
common/lib/xmodule/xmodule/tests/test_error_module.py
View file @
d919d2ae
...
@@ -4,7 +4,7 @@ Tests for ErrorModule and NonStaffErrorModule
...
@@ -4,7 +4,7 @@ Tests for ErrorModule and NonStaffErrorModule
import
unittest
import
unittest
from
xmodule.tests
import
get_test_system
from
xmodule.tests
import
get_test_system
from
xmodule.error_module
import
ErrorDescriptor
,
ErrorModule
,
NonStaffErrorDescriptor
from
xmodule.error_module
import
ErrorDescriptor
,
ErrorModule
,
NonStaffErrorDescriptor
from
xmodule.modulestore.xml
import
CourseLocation
Generato
r
from
xmodule.modulestore.xml
import
CourseLocation
Manage
r
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
,
Location
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
,
Location
from
xmodule.x_module
import
XModuleDescriptor
,
XModule
,
STUDENT_VIEW
from
xmodule.x_module
import
XModuleDescriptor
,
XModule
,
STUDENT_VIEW
from
mock
import
MagicMock
,
Mock
,
patch
from
mock
import
MagicMock
,
Mock
,
patch
...
@@ -34,7 +34,7 @@ class TestErrorModule(unittest.TestCase, SetupTestErrorModules):
...
@@ -34,7 +34,7 @@ class TestErrorModule(unittest.TestCase, SetupTestErrorModules):
descriptor
=
ErrorDescriptor
.
from_xml
(
descriptor
=
ErrorDescriptor
.
from_xml
(
self
.
valid_xml
,
self
.
valid_xml
,
self
.
system
,
self
.
system
,
CourseLocation
Generato
r
(
self
.
course_id
),
CourseLocation
Manage
r
(
self
.
course_id
),
self
.
error_msg
self
.
error_msg
)
)
self
.
assertIsInstance
(
descriptor
,
ErrorDescriptor
)
self
.
assertIsInstance
(
descriptor
,
ErrorDescriptor
)
...
@@ -69,7 +69,7 @@ class TestNonStaffErrorModule(unittest.TestCase, SetupTestErrorModules):
...
@@ -69,7 +69,7 @@ class TestNonStaffErrorModule(unittest.TestCase, SetupTestErrorModules):
descriptor
=
NonStaffErrorDescriptor
.
from_xml
(
descriptor
=
NonStaffErrorDescriptor
.
from_xml
(
self
.
valid_xml
,
self
.
valid_xml
,
self
.
system
,
self
.
system
,
CourseLocation
Generato
r
(
self
.
course_id
)
CourseLocation
Manage
r
(
self
.
course_id
)
)
)
self
.
assertIsInstance
(
descriptor
,
NonStaffErrorDescriptor
)
self
.
assertIsInstance
(
descriptor
,
NonStaffErrorDescriptor
)
...
@@ -77,7 +77,7 @@ class TestNonStaffErrorModule(unittest.TestCase, SetupTestErrorModules):
...
@@ -77,7 +77,7 @@ class TestNonStaffErrorModule(unittest.TestCase, SetupTestErrorModules):
descriptor
=
NonStaffErrorDescriptor
.
from_xml
(
descriptor
=
NonStaffErrorDescriptor
.
from_xml
(
self
.
valid_xml
,
self
.
valid_xml
,
self
.
system
,
self
.
system
,
CourseLocation
Generato
r
(
self
.
course_id
)
CourseLocation
Manage
r
(
self
.
course_id
)
)
)
descriptor
.
xmodule_runtime
=
self
.
system
descriptor
.
xmodule_runtime
=
self
.
system
context_repr
=
self
.
system
.
render
(
descriptor
,
STUDENT_VIEW
)
.
content
context_repr
=
self
.
system
.
render
(
descriptor
,
STUDENT_VIEW
)
.
content
...
...
common/lib/xmodule/xmodule/tests/xml/__init__.py
View file @
d919d2ae
...
@@ -7,7 +7,7 @@ from unittest import TestCase
...
@@ -7,7 +7,7 @@ from unittest import TestCase
from
xmodule.x_module
import
XMLParsingSystem
,
policy_key
from
xmodule.x_module
import
XMLParsingSystem
,
policy_key
from
xmodule.mako_module
import
MakoDescriptorSystem
from
xmodule.mako_module
import
MakoDescriptorSystem
from
xmodule.modulestore.xml
import
create_block_from_xml
,
CourseLocation
Generato
r
from
xmodule.modulestore.xml
import
create_block_from_xml
,
CourseLocation
Manage
r
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
,
Location
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
,
Location
from
xblock.runtime
import
KvsFieldData
,
DictKeyValueStore
from
xblock.runtime
import
KvsFieldData
,
DictKeyValueStore
...
@@ -43,7 +43,7 @@ class InMemorySystem(XMLParsingSystem, MakoDescriptorSystem): # pylint: disable
...
@@ -43,7 +43,7 @@ class InMemorySystem(XMLParsingSystem, MakoDescriptorSystem): # pylint: disable
descriptor
=
create_block_from_xml
(
descriptor
=
create_block_from_xml
(
xml
,
xml
,
self
,
self
,
CourseLocation
Generato
r
(
self
.
course_id
),
CourseLocation
Manage
r
(
self
.
course_id
),
)
)
self
.
_descriptors
[
descriptor
.
location
.
to_deprecated_string
()]
=
descriptor
self
.
_descriptors
[
descriptor
.
location
.
to_deprecated_string
()]
=
descriptor
return
descriptor
return
descriptor
...
...
common/lib/xmodule/xmodule/x_module.py
View file @
d919d2ae
...
@@ -18,12 +18,13 @@ from webob.multidict import MultiDict
...
@@ -18,12 +18,13 @@ from webob.multidict import MultiDict
from
xblock.core
import
XBlock
from
xblock.core
import
XBlock
from
xblock.fields
import
Scope
,
Integer
,
Float
,
List
,
XBlockMixin
,
String
,
Dict
from
xblock.fields
import
Scope
,
Integer
,
Float
,
List
,
XBlockMixin
,
String
,
Dict
from
xblock.fragment
import
Fragment
from
xblock.fragment
import
Fragment
from
xblock.runtime
import
Runtime
,
IdReader
from
xblock.runtime
import
Runtime
,
IdReader
,
IdGenerator
from
xmodule.fields
import
RelativeTime
from
xmodule.fields
import
RelativeTime
from
xmodule.errortracker
import
exc_info_to_str
from
xmodule.errortracker
import
exc_info_to_str
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
opaque_keys.edx.keys
import
UsageKey
from
opaque_keys.edx.keys
import
UsageKey
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
...
@@ -65,7 +66,7 @@ class OpaqueKeyReader(IdReader):
...
@@ -65,7 +66,7 @@ class OpaqueKeyReader(IdReader):
Returns:
Returns:
The `definition_id` the usage is derived from
The `definition_id` the usage is derived from
"""
"""
r
eturn
usage_id
.
definition_key
r
aise
NotImplementedError
(
"Specific Modulestores must implement get_definition_id"
)
def
get_block_type
(
self
,
def_id
):
def
get_block_type
(
self
,
def_id
):
"""Retrieve the block_type of a particular definition
"""Retrieve the block_type of a particular definition
...
@@ -78,6 +79,91 @@ class OpaqueKeyReader(IdReader):
...
@@ -78,6 +79,91 @@ class OpaqueKeyReader(IdReader):
"""
"""
return
def_id
.
block_type
return
def_id
.
block_type
def
get_usage_id_from_aside
(
self
,
aside_id
):
"""
Retrieve the XBlock `usage_id` associated with this aside usage id.
Args:
aside_id: The usage id of the XBlockAside.
Returns:
The `usage_id` of the usage the aside is commenting on.
"""
return
aside_id
.
usage_key
def
get_definition_id_from_aside
(
self
,
aside_id
):
"""
Retrieve the XBlock `definition_id` associated with this aside definition id.
Args:
aside_id: The usage id of the XBlockAside.
Returns:
The `definition_id` of the usage the aside is commenting on.
"""
return
aside_id
.
definition_key
def
get_aside_type_from_usage
(
self
,
aside_id
):
"""
Retrieve the XBlockAside `aside_type` associated with this aside
usage id.
Args:
aside_id: The usage id of the XBlockAside.
Returns:
The `aside_type` of the aside.
"""
return
aside_id
.
aside_type
def
get_aside_type_from_definition
(
self
,
aside_id
):
"""
Retrieve the XBlockAside `aside_type` associated with this aside
definition id.
Args:
aside_id: The definition id of the XBlockAside.
Returns:
The `aside_type` of the aside.
"""
return
aside_id
.
aside_type
class
AsideKeyGenerator
(
IdGenerator
):
# pylint: disable=abstract-method
"""
An :class:`.IdGenerator` that only provides facilities for constructing new XBlockAsides.
"""
def
create_aside
(
self
,
definition_id
,
usage_id
,
aside_type
):
"""
Make a new aside definition and usage ids, indicating an :class:`.XBlockAside` of type `aside_type`
commenting on an :class:`.XBlock` usage `usage_id`
Returns:
(aside_definition_id, aside_usage_id)
"""
def_key
=
AsideDefinitionKeyV1
(
definition_id
,
aside_type
)
usage_key
=
AsideUsageKeyV1
(
usage_id
,
aside_type
)
return
(
def_key
,
usage_key
)
def
create_usage
(
self
,
def_id
):
"""Make a usage, storing its definition id.
Returns the newly-created usage id.
"""
raise
NotImplementedError
(
"Specific Modulestores must provide implementations of create_usage"
)
def
create_definition
(
self
,
block_type
,
slug
=
None
):
"""Make a definition, storing its block type.
If `slug` is provided, it is a suggestion that the definition id
incorporate the slug somehow.
Returns the newly-created definition id.
"""
raise
NotImplementedError
(
"Specific Modulestores must provide implementations of create_definition"
)
def
dummy_track
(
_event_type
,
_event
):
def
dummy_track
(
_event_type
,
_event
):
pass
pass
...
@@ -160,6 +246,8 @@ class XModuleMixin(XBlockMixin):
...
@@ -160,6 +246,8 @@ class XModuleMixin(XBlockMixin):
Adding this Mixin to an :class:`XBlock` allows it to cooperate with old-style :class:`XModules`
Adding this Mixin to an :class:`XBlock` allows it to cooperate with old-style :class:`XModules`
"""
"""
entry_point
=
"xmodule.v1"
# Attributes for inspection of the descriptor
# Attributes for inspection of the descriptor
# This indicates whether the xmodule is a problem-type.
# This indicates whether the xmodule is a problem-type.
...
@@ -526,6 +614,7 @@ class XModule(XModuleMixin, HTMLSnippet, XBlock): # pylint: disable=abstract-me
...
@@ -526,6 +614,7 @@ class XModule(XModuleMixin, HTMLSnippet, XBlock): # pylint: disable=abstract-me
field_data: A dictionary-like object that maps field names to values
field_data: A dictionary-like object that maps field names to values
for those fields.
for those fields.
"""
"""
# Set the descriptor first so that we can proxy to it
# Set the descriptor first so that we can proxy to it
self
.
descriptor
=
descriptor
self
.
descriptor
=
descriptor
super
(
XModule
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
super
(
XModule
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
...
@@ -715,7 +804,6 @@ class XModuleDescriptor(XModuleMixin, HTMLSnippet, ResourceTemplates, XBlock):
...
@@ -715,7 +804,6 @@ class XModuleDescriptor(XModuleMixin, HTMLSnippet, ResourceTemplates, XBlock):
create a problem, and can generate XModules (which do know about student
create a problem, and can generate XModules (which do know about student
state).
state).
"""
"""
entry_point
=
"xmodule.v1"
module_class
=
XModule
module_class
=
XModule
# VS[compat]. Backwards compatibility code that can go away after
# VS[compat]. Backwards compatibility code that can go away after
...
@@ -997,7 +1085,7 @@ class XModuleDescriptor(XModuleMixin, HTMLSnippet, ResourceTemplates, XBlock):
...
@@ -997,7 +1085,7 @@ class XModuleDescriptor(XModuleMixin, HTMLSnippet, ResourceTemplates, XBlock):
class
ConfigurableFragmentWrapper
(
object
):
# pylint: disable=abstract-method
class
ConfigurableFragmentWrapper
(
object
):
# pylint: disable=abstract-method
"""
"""
Runtime mixin that allows for composition of many `wrap_
child
` wrappers
Runtime mixin that allows for composition of many `wrap_
xblock
` wrappers
"""
"""
def
__init__
(
self
,
wrappers
=
None
,
**
kwargs
):
def
__init__
(
self
,
wrappers
=
None
,
**
kwargs
):
"""
"""
...
@@ -1013,7 +1101,7 @@ class ConfigurableFragmentWrapper(object): # pylint: disable=abstract-method
...
@@ -1013,7 +1101,7 @@ class ConfigurableFragmentWrapper(object): # pylint: disable=abstract-method
else
:
else
:
self
.
wrappers
=
[]
self
.
wrappers
=
[]
def
wrap_
child
(
self
,
block
,
view
,
frag
,
context
):
def
wrap_
xblock
(
self
,
block
,
view
,
frag
,
context
):
"""
"""
See :func:`Runtime.wrap_child`
See :func:`Runtime.wrap_child`
"""
"""
...
@@ -1043,6 +1131,16 @@ def descriptor_global_local_resource_url(block, uri): # pylint: disable=invalid
...
@@ -1043,6 +1131,16 @@ def descriptor_global_local_resource_url(block, uri): # pylint: disable=invalid
raise
NotImplementedError
(
"Applications must monkey-patch this function before using local_resource_url for studio_view"
)
raise
NotImplementedError
(
"Applications must monkey-patch this function before using local_resource_url for studio_view"
)
# 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
# the Runtime part of its interface. This function matches the Runtime.get_asides interface
def
descriptor_global_get_asides
(
block
):
# pylint: disable=unused-argument
"""
See :meth:`xblock.runtime.Runtime.get_asides`.
"""
raise
NotImplementedError
(
"Applications must monkey-patch this function before using get_asides from a DescriptorSystem."
)
class
MetricsMixin
(
object
):
class
MetricsMixin
(
object
):
"""
"""
Mixin for adding metric logging for render and handle methods in the DescriptorSystem and ModuleSystem.
Mixin for adding metric logging for render and handle methods in the DescriptorSystem and ModuleSystem.
...
@@ -1137,7 +1235,9 @@ class DescriptorSystem(MetricsMixin, ConfigurableFragmentWrapper, Runtime): # p
...
@@ -1137,7 +1235,9 @@ class DescriptorSystem(MetricsMixin, ConfigurableFragmentWrapper, Runtime): # p
local_resource_url: an implementation of :meth:`xblock.runtime.Runtime.local_resource_url`
local_resource_url: an implementation of :meth:`xblock.runtime.Runtime.local_resource_url`
"""
"""
super
(
DescriptorSystem
,
self
)
.
__init__
(
id_reader
=
OpaqueKeyReader
(),
**
kwargs
)
kwargs
.
setdefault
(
'id_reader'
,
OpaqueKeyReader
())
kwargs
.
setdefault
(
'id_generator'
,
AsideKeyGenerator
())
super
(
DescriptorSystem
,
self
)
.
__init__
(
**
kwargs
)
# This is used by XModules to write out separate files during xml export
# This is used by XModules to write out separate files during xml export
self
.
export_fs
=
None
self
.
export_fs
=
None
...
@@ -1215,6 +1315,19 @@ class DescriptorSystem(MetricsMixin, ConfigurableFragmentWrapper, Runtime): # p
...
@@ -1215,6 +1315,19 @@ class DescriptorSystem(MetricsMixin, ConfigurableFragmentWrapper, Runtime): # p
# global function that the application can override.
# global function that the application can override.
return
descriptor_global_local_resource_url
(
block
,
uri
)
return
descriptor_global_local_resource_url
(
block
,
uri
)
def
get_asides
(
self
,
block
):
"""
See :meth:`xblock.runtime.Runtime:get_asides` for documentation.
"""
if
getattr
(
block
,
'xmodule_runtime'
,
None
)
is
not
None
:
return
block
.
xmodule_runtime
.
get_asides
(
block
)
else
:
# Currently, Modulestore is responsible for instantiating DescriptorSystems
# This means that LMS/CMS don't have a way to define a subclass of DescriptorSystem
# that implements the correct get_asides. So, for now, instead, we will reference a
# global function that the application can override.
return
descriptor_global_get_asides
(
block
)
def
resource_url
(
self
,
resource
):
def
resource_url
(
self
,
resource
):
"""
"""
See :meth:`xblock.runtime.Runtime:resource_url` for documentation.
See :meth:`xblock.runtime.Runtime:resource_url` for documentation.
...
@@ -1335,7 +1448,9 @@ class ModuleSystem(MetricsMixin, ConfigurableFragmentWrapper, Runtime): # pylin
...
@@ -1335,7 +1448,9 @@ class ModuleSystem(MetricsMixin, ConfigurableFragmentWrapper, Runtime): # pylin
# Usage_store is unused, and field_data is often supplanted with an
# Usage_store is unused, and field_data is often supplanted with an
# explicit field_data during construct_xblock.
# explicit field_data during construct_xblock.
super
(
ModuleSystem
,
self
)
.
__init__
(
id_reader
=
OpaqueKeyReader
(),
field_data
=
field_data
,
**
kwargs
)
kwargs
.
setdefault
(
'id_reader'
,
getattr
(
descriptor_runtime
,
'id_reader'
,
OpaqueKeyReader
()))
kwargs
.
setdefault
(
'id_generator'
,
getattr
(
descriptor_runtime
,
'id_generator'
,
AsideKeyGenerator
()))
super
(
ModuleSystem
,
self
)
.
__init__
(
field_data
=
field_data
,
**
kwargs
)
self
.
STATIC_URL
=
static_url
self
.
STATIC_URL
=
static_url
self
.
xqueue
=
xqueue
self
.
xqueue
=
xqueue
...
@@ -1373,6 +1488,9 @@ class ModuleSystem(MetricsMixin, ConfigurableFragmentWrapper, Runtime): # pylin
...
@@ -1373,6 +1488,9 @@ class ModuleSystem(MetricsMixin, ConfigurableFragmentWrapper, Runtime): # pylin
self
.
descriptor_runtime
=
descriptor_runtime
self
.
descriptor_runtime
=
descriptor_runtime
self
.
rebind_noauth_module_to_user
=
rebind_noauth_module_to_user
self
.
rebind_noauth_module_to_user
=
rebind_noauth_module_to_user
if
user
:
self
.
user_id
=
user
.
id
def
get
(
self
,
attr
):
def
get
(
self
,
attr
):
""" provide uniform access to attributes (like etree)."""
""" provide uniform access to attributes (like etree)."""
return
self
.
__dict__
.
get
(
attr
)
return
self
.
__dict__
.
get
(
attr
)
...
...
common/static/coffee/spec/xblock/core_spec.coffee
View file @
d919d2ae
...
@@ -35,7 +35,7 @@ describe "XBlock", ->
...
@@ -35,7 +35,7 @@ describe "XBlock", ->
window
.
initFnZ
=
jasmine
.
createSpy
()
window
.
initFnZ
=
jasmine
.
createSpy
()
@
fakeChildren
=
[
'list'
,
'of'
,
'children'
]
@
fakeChildren
=
[
'list'
,
'of'
,
'children'
]
spyOn
(
XBlock
,
'initializeBlocks'
).
andReturn
(
@
fakeChildren
)
spyOn
(
XBlock
,
'initialize
X
Blocks'
).
andReturn
(
@
fakeChildren
)
@
vANode
=
$
(
'#vA'
)[
0
]
@
vANode
=
$
(
'#vA'
)[
0
]
@
vZNode
=
$
(
'#vZ'
)[
0
]
@
vZNode
=
$
(
'#vZ'
)[
0
]
...
@@ -50,8 +50,8 @@ describe "XBlock", ->
...
@@ -50,8 +50,8 @@ describe "XBlock", ->
expect
(
TestRuntime
.
vZ
).
toHaveBeenCalledWith
()
expect
(
TestRuntime
.
vZ
).
toHaveBeenCalledWith
()
it
"loads the right init function"
,
->
it
"loads the right init function"
,
->
expect
(
window
.
initFnA
).
toHaveBeenCalledWith
(
@
runtimeA
,
@
vANode
)
expect
(
window
.
initFnA
).
toHaveBeenCalledWith
(
@
runtimeA
,
@
vANode
,
{}
)
expect
(
window
.
initFnZ
).
toHaveBeenCalledWith
(
@
runtimeZ
,
@
vZNode
)
expect
(
window
.
initFnZ
).
toHaveBeenCalledWith
(
@
runtimeZ
,
@
vZNode
,
{}
)
it
"loads when missing versions"
,
->
it
"loads when missing versions"
,
->
expect
(
@
missingVersionBlock
.
element
).
toBe
(
$
(
'#missing-version'
))
expect
(
@
missingVersionBlock
.
element
).
toBe
(
$
(
'#missing-version'
))
...
@@ -74,8 +74,8 @@ describe "XBlock", ->
...
@@ -74,8 +74,8 @@ describe "XBlock", ->
expect
(
@
missingInitBlock
.
element
).
toBe
(
$
(
'#missing-init'
)[
0
])
expect
(
@
missingInitBlock
.
element
).
toBe
(
$
(
'#missing-init'
)[
0
])
it
"passes through the request token"
,
->
it
"passes through the request token"
,
->
expect
(
XBlock
.
initializeBlocks
).
toHaveBeenCalledWith
(
$
(
@
vANode
),
'req-token-a'
)
expect
(
XBlock
.
initialize
X
Blocks
).
toHaveBeenCalledWith
(
$
(
@
vANode
),
'req-token-a'
)
expect
(
XBlock
.
initializeBlocks
).
toHaveBeenCalledWith
(
$
(
@
vZNode
),
'req-token-z'
)
expect
(
XBlock
.
initialize
X
Blocks
).
toHaveBeenCalledWith
(
$
(
@
vZNode
),
'req-token-z'
)
describe
"initializeBlocks"
,
->
describe
"initializeBlocks"
,
->
...
...
common/static/coffee/src/xblock/core.coffee
deleted
100644 → 0
View file @
e20fe2b8
@
XBlock
=
Runtime
:
{}
###
Initialize the javascript for a single xblock element, and for all of it's
xblock children that match requestToken. If requestToken is omitted, use the
data-request-token attribute from element, or use the request-tokens specified on
the children themselves.
###
initializeBlock
:
(
element
,
requestToken
)
->
$element
=
$
(
element
)
requestToken
=
requestToken
or
$element
.
data
(
'request-token'
)
children
=
@
initializeBlocks
(
$element
,
requestToken
)
runtime
=
$element
.
data
(
"runtime-class"
)
version
=
$element
.
data
(
"runtime-version"
)
initFnName
=
$element
.
data
(
"init"
)
$element
.
prop
(
'xblock_children'
,
children
)
if
runtime
?
and
version
?
and
initFnName
?
runtime
=
new
window
[
runtime
][
"v
#{
version
}
"
]
initFn
=
window
[
initFnName
]
if
initFn
.
length
>
2
initargs
=
$
(
".xblock_json_init_args"
,
element
)
if
initargs
.
length
==
0
console
.
log
(
"Warning: XBlock expects data parameters"
)
data
=
JSON
.
parse
(
initargs
.
text
())
block
=
initFn
(
runtime
,
element
,
data
)
?
{}
else
block
=
initFn
(
runtime
,
element
)
?
{}
block
.
runtime
=
runtime
else
elementTag
=
$
(
'<div>'
).
append
(
$element
.
clone
()).
html
();
console
.
log
(
"Block
#{
elementTag
}
is missing data-runtime, data-runtime-version or data-init, and can't be initialized"
)
block
=
{}
block
.
element
=
element
block
.
name
=
$element
.
data
(
"name"
)
block
.
type
=
$element
.
data
(
"block-type"
)
$element
.
trigger
(
"xblock-initialized"
)
$element
.
data
(
"initialized"
,
true
)
$element
.
addClass
(
"xblock-initialized"
)
block
###
Initialize all XBlocks inside element that were rendered with requestToken.
If requestToken is omitted, and element has a 'data-request-token' attribute, use that.
If neither is available, then use the request tokens of the immediateDescendent xblocks.
###
initializeBlocks
:
(
element
,
requestToken
)
->
requestToken
=
requestToken
or
$
(
element
).
data
(
'request-token'
)
if
requestToken
selector
=
".xblock[data-request-token='
#{
requestToken
}
']"
else
selector
=
".xblock"
$
(
element
).
immediateDescendents
(
selector
).
map
((
idx
,
elem
)
=>
@
initializeBlock
(
elem
,
requestToken
)
).
toArray
()
common/static/js/xblock/core.js
0 → 100644
View file @
d919d2ae
(
function
(
$
,
JSON
)
{
'use strict'
;
function
initializeBlockLikes
(
block_class
,
initializer
,
element
,
requestToken
)
{
var
requestToken
=
requestToken
||
$
(
element
).
data
(
'request-token'
);
if
(
requestToken
)
{
var
selector
=
'.'
+
block_class
+
'[data-request-token="'
+
requestToken
+
'"]'
;
}
else
{
var
selector
=
'.'
+
block_class
;
}
return
$
(
element
).
immediateDescendents
(
selector
).
map
(
function
(
idx
,
elem
)
{
return
initializer
(
elem
,
requestToken
);
}).
toArray
();
}
function
elementRuntime
(
element
)
{
var
$element
=
$
(
element
);
var
runtime
=
$element
.
data
(
'runtime-class'
);
var
version
=
$element
.
data
(
'runtime-version'
);
var
initFnName
=
$element
.
data
(
'init'
);
if
(
runtime
&&
version
&&
initFnName
)
{
return
new
window
[
runtime
][
'v'
+
version
];
}
else
{
if
(
!
runtime
||
!
version
||
!
initFnName
)
{
var
elementTag
=
$
(
'<div>'
).
append
(
$element
.
clone
()).
html
();
console
.
log
(
'Block '
+
elementTag
+
' is missing data-runtime, data-runtime-version or data-init, and can
\'
t be initialized'
);
}
return
null
;
}
}
function
initArgs
(
element
)
{
var
initargs
=
$
(
'.xblock_json_init_args'
,
element
).
text
();
return
initargs
?
JSON
.
parse
(
initargs
)
:
{};
}
/**
* Construct an XBlock family object from an element. The constructor
* function is loaded from the 'data-init' attribute of the element.
* The constructor is called with the arguments 'runtime', 'element',
* and then all of 'block_args'.
*/
function
constructBlock
(
element
,
block_args
)
{
var
block
;
var
$element
=
$
(
element
);
var
runtime
=
elementRuntime
(
element
);
block_args
.
unshift
(
element
);
block_args
.
unshift
(
runtime
);
if
(
runtime
)
{
block
=
(
function
()
{
var
initFn
=
window
[
$element
.
data
(
'init'
)];
// This create a new constructor that can then apply() the block_args
// to the initFn.
function
Block
()
{
return
initFn
.
apply
(
this
,
block_args
);
}
Block
.
prototype
=
initFn
.
prototype
;
return
new
Block
();
})();
block
.
runtime
=
runtime
;
}
else
{
block
=
{};
}
block
.
element
=
element
;
block
.
name
=
$element
.
data
(
'name'
);
block
.
type
=
$element
.
data
(
'block-type'
);
$element
.
trigger
(
'xblock-initialized'
);
$element
.
data
(
'initialized'
,
true
);
$element
.
addClass
(
'xblock-initialized'
);
return
block
;
}
var
XBlock
=
{
Runtime
:
{},
/**
* Initialize the javascript for a single xblock element, and for all of it's
* xblock children that match requestToken. If requestToken is omitted, use the
* data-request-token attribute from element, or use the request-tokens specified on
* the children themselves.
*/
initializeBlock
:
function
(
element
,
requestToken
)
{
var
$element
=
$
(
element
);
var
requestToken
=
requestToken
||
$element
.
data
(
'request-token'
);
var
children
=
XBlock
.
initializeXBlocks
(
$element
,
requestToken
);
$element
.
prop
(
'xblock_children'
,
children
);
return
constructBlock
(
element
,
[
initArgs
(
element
)]);
},
/**
* Initialize the javascript for a single xblock aside element that matches requestToken.
* If requestToken is omitted, use the data-request-token attribute from element, or use
* the request-tokens specified on the children themselves.
*/
initializeAside
:
function
(
element
,
requestToken
)
{
var
blockUsageId
=
$
(
element
).
data
(
'block-id'
);
var
blockElement
=
$
(
element
).
siblings
(
'[data-usage-id="'
+
blockUsageId
+
'"]'
)[
0
];
return
constructBlock
(
element
,
[
blockElement
,
initArgs
(
element
)]);
},
/**
* Initialize all XBlocks inside element that were rendered with requestToken.
* If requestToken is omitted, and element has a 'data-request-token' attribute, use that.
* If neither is available, then use the request tokens of the immediateDescendent xblocks.
*/
initializeXBlocks
:
function
(
element
,
requestToken
)
{
return
initializeBlockLikes
(
'xblock'
,
XBlock
.
initializeBlock
,
element
,
requestToken
);
},
/**
* Initialize all XBlockAsides inside element that were rendered with requestToken.
* If requestToken is omitted, and element has a 'data-request-token' attribute, use that.
* If neither is available, then use the request tokens of the immediateDescendent xblocks.
*/
initializeXBlockAsides
:
function
(
element
,
requestToken
)
{
return
initializeBlockLikes
(
'xblock_asides-v1'
,
XBlock
.
initializeAside
,
element
,
requestToken
);
},
/**
* Initialize all XBlock-family blocks inside element that were rendered with requestToken.
* If requestToken is omitted, and element has a 'data-request-token' attribute, use that.
* If neither is available, then use the request tokens of the immediateDescendent xblocks.
*/
initializeBlocks
:
function
(
element
,
requestToken
)
{
XBlock
.
initializeXBlockAsides
(
element
,
requestToken
);
return
XBlock
.
initializeXBlocks
(
element
,
requestToken
);
}
};
this
.
XBlock
=
XBlock
;
}).
call
(
this
,
$
,
JSON
);
common/static/js_test.yml
View file @
d919d2ae
...
@@ -45,6 +45,7 @@ lib_paths:
...
@@ -45,6 +45,7 @@ lib_paths:
# Paths to source JavaScript files
# Paths to source JavaScript files
src_paths
:
src_paths
:
-
js/xblock
-
coffee/src
-
coffee/src
-
js/src
-
js/src
-
js/utils
-
js/utils
...
...
common/test/acceptance/pages/studio/container.py
View file @
d919d2ae
...
@@ -51,7 +51,7 @@ class ContainerPage(PageObject):
...
@@ -51,7 +51,7 @@ class ContainerPage(PageObject):
num_wrappers
=
len
(
self
.
q
(
css
=
'{} [data-request-token="{}"]'
.
format
(
XBlockWrapper
.
BODY_SELECTOR
,
request_token
))
.
results
)
num_wrappers
=
len
(
self
.
q
(
css
=
'{} [data-request-token="{}"]'
.
format
(
XBlockWrapper
.
BODY_SELECTOR
,
request_token
))
.
results
)
# Wait until all components have been loaded and marked as either initialized or failed.
# Wait until all components have been loaded and marked as either initialized or failed.
# See:
# See:
# - common/static/
coffee/src/xblock/core.coffee
which adds the class "xblock-initialized"
# - common/static/
js/xblock/core.js
which adds the class "xblock-initialized"
# at the end of initializeBlock.
# at the end of initializeBlock.
# - common/static/js/views/xblock.js which adds the class "xblock-initialization-failed"
# - common/static/js/views/xblock.js which adds the class "xblock-initialization-failed"
# if the xblock threw an error while initializing.
# if the xblock threw an error while initializing.
...
...
common/test/acceptance/tests/lms/test_lms_acid_xblock.py
View file @
d919d2ae
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
End-to-end tests for the LMS.
End-to-end tests for the LMS.
"""
"""
from
unittest
import
skip
from
unittest
import
expectedFailure
from
..helpers
import
UniqueCourseTest
from
..helpers
import
UniqueCourseTest
from
...pages.lms.auto_auth
import
AutoAuthPage
from
...pages.lms.auto_auth
import
AutoAuthPage
...
@@ -44,17 +44,6 @@ class XBlockAcidBase(UniqueCourseTest):
...
@@ -44,17 +44,6 @@ class XBlockAcidBase(UniqueCourseTest):
self
.
assertTrue
(
acid_block
.
scope_passed
(
'preferences'
))
self
.
assertTrue
(
acid_block
.
scope_passed
(
'preferences'
))
self
.
assertTrue
(
acid_block
.
scope_passed
(
'user_info'
))
self
.
assertTrue
(
acid_block
.
scope_passed
(
'user_info'
))
def
test_acid_block
(
self
):
"""
Verify that all expected acid block tests pass in the lms.
"""
self
.
course_info_page
.
visit
()
self
.
tab_nav
.
go_to_tab
(
'Courseware'
)
acid_block
=
AcidView
(
self
.
browser
,
'.xblock-student_view[data-block-type=acid]'
)
self
.
validate_acid_block_view
(
acid_block
)
class
XBlockAcidNoChildTest
(
XBlockAcidBase
):
class
XBlockAcidNoChildTest
(
XBlockAcidBase
):
"""
"""
...
@@ -81,7 +70,15 @@ class XBlockAcidNoChildTest(XBlockAcidBase):
...
@@ -81,7 +70,15 @@ class XBlockAcidNoChildTest(XBlockAcidBase):
)
.
install
()
)
.
install
()
def
test_acid_block
(
self
):
def
test_acid_block
(
self
):
super
(
XBlockAcidNoChildTest
,
self
)
.
test_acid_block
()
"""
Verify that all expected acid block tests pass in the lms.
"""
self
.
course_info_page
.
visit
()
self
.
tab_nav
.
go_to_tab
(
'Courseware'
)
acid_block
=
AcidView
(
self
.
browser
,
'.xblock-student_view[data-block-type=acid]'
)
self
.
validate_acid_block_view
(
acid_block
)
class
XBlockAcidChildTest
(
XBlockAcidBase
):
class
XBlockAcidChildTest
(
XBlockAcidBase
):
...
@@ -129,3 +126,46 @@ class XBlockAcidChildTest(XBlockAcidBase):
...
@@ -129,3 +126,46 @@ class XBlockAcidChildTest(XBlockAcidBase):
acid_block
=
AcidView
(
self
.
browser
,
'.xblock-student_view[data-block-type=acid]'
)
acid_block
=
AcidView
(
self
.
browser
,
'.xblock-student_view[data-block-type=acid]'
)
self
.
validate_acid_block_view
(
acid_block
)
self
.
validate_acid_block_view
(
acid_block
)
class
XBlockAcidAsideTest
(
XBlockAcidBase
):
"""
Tests of an AcidBlock with children
"""
__test__
=
True
def
setup_fixtures
(
self
):
course_fix
=
CourseFixture
(
self
.
course_info
[
'org'
],
self
.
course_info
[
'number'
],
self
.
course_info
[
'run'
],
self
.
course_info
[
'display_name'
]
)
course_fix
.
add_children
(
XBlockFixtureDesc
(
'chapter'
,
'Test Section'
)
.
add_children
(
XBlockFixtureDesc
(
'sequential'
,
'Test Subsection'
)
.
add_children
(
XBlockFixtureDesc
(
'vertical'
,
'Test Unit'
)
.
add_children
(
XBlockFixtureDesc
(
'acid'
,
'Acid Block'
)
)
)
)
)
.
install
()
@expectedFailure
def
test_acid_block
(
self
):
"""
Verify that all expected acid block tests pass in the lms.
"""
self
.
course_info_page
.
visit
()
self
.
tab_nav
.
go_to_tab
(
'Courseware'
)
acid_aside
=
AcidView
(
self
.
browser
,
'.xblock_asides-v1-student_view[data-block-type=acid_aside]'
)
self
.
validate_acid_aside_view
(
acid_aside
)
acid_block
=
AcidView
(
self
.
browser
,
'.xblock-student_view[data-block-type=acid]'
)
self
.
validate_acid_block_view
(
acid_block
)
def
validate_acid_aside_view
(
self
,
acid_aside
):
self
.
validate_acid_block_view
(
acid_aside
)
lms/djangoapps/courseware/model_data.py
View file @
d919d2ae
...
@@ -12,16 +12,17 @@ from .models import (
...
@@ -12,16 +12,17 @@ from .models import (
XModuleStudentInfoField
XModuleStudentInfoField
)
)
import
logging
import
logging
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
,
Location
from
opaque_keys.edx.keys
import
CourseKey
from
opaque_keys.edx.keys
import
CourseKey
,
UsageKey
from
opaque_keys.edx.block_types
import
BlockTypeKeyV1
from
opaque_keys.edx.asides
import
AsideUsageKeyV1
from
django.db
import
DatabaseError
from
django.db
import
DatabaseError
from
django.contrib.auth.models
import
User
from
xblock.runtime
import
KeyValueStore
from
xblock.runtime
import
KeyValueStore
from
xblock.exceptions
import
KeyValueMultiSaveError
,
InvalidScopeError
from
xblock.exceptions
import
KeyValueMultiSaveError
,
InvalidScopeError
from
xblock.fields
import
Scope
,
UserScope
from
xblock.fields
import
Scope
,
UserScope
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
from
xblock.core
import
XBlockAside
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
...
@@ -46,7 +47,7 @@ class FieldDataCache(object):
...
@@ -46,7 +47,7 @@ class FieldDataCache(object):
A cache of django model objects needed to supply the data
A cache of django model objects needed to supply the data
for a module and its decendants
for a module and its decendants
"""
"""
def
__init__
(
self
,
descriptors
,
course_id
,
user
,
select_for_update
=
False
):
def
__init__
(
self
,
descriptors
,
course_id
,
user
,
select_for_update
=
False
,
asides
=
None
):
'''
'''
Find any courseware.models objects that are needed by any descriptor
Find any courseware.models objects that are needed by any descriptor
in descriptors. Attempts to minimize the number of queries to the database.
in descriptors. Attempts to minimize the number of queries to the database.
...
@@ -58,11 +59,17 @@ class FieldDataCache(object):
...
@@ -58,11 +59,17 @@ class FieldDataCache(object):
course_id: The id of the current course
course_id: The id of the current course
user: The user for which to cache data
user: The user for which to cache data
select_for_update: True if rows should be locked until end of transaction
select_for_update: True if rows should be locked until end of transaction
asides: The list of aside types to load, or None to prefetch no asides.
'''
'''
self
.
cache
=
{}
self
.
cache
=
{}
self
.
descriptors
=
descriptors
self
.
descriptors
=
descriptors
self
.
select_for_update
=
select_for_update
self
.
select_for_update
=
select_for_update
if
asides
is
None
:
self
.
asides
=
[]
else
:
self
.
asides
=
asides
assert
isinstance
(
course_id
,
CourseKey
)
assert
isinstance
(
course_id
,
CourseKey
)
self
.
course_id
=
course_id
self
.
course_id
=
course_id
self
.
user
=
user
self
.
user
=
user
...
@@ -75,7 +82,7 @@ class FieldDataCache(object):
...
@@ -75,7 +82,7 @@ class FieldDataCache(object):
@classmethod
@classmethod
def
cache_for_descriptor_descendents
(
cls
,
course_id
,
user
,
descriptor
,
depth
=
None
,
def
cache_for_descriptor_descendents
(
cls
,
course_id
,
user
,
descriptor
,
depth
=
None
,
descriptor_filter
=
lambda
descriptor
:
True
,
descriptor_filter
=
lambda
descriptor
:
True
,
select_for_update
=
False
):
select_for_update
=
False
,
asides
=
None
):
"""
"""
course_id: the course in the context of which we want StudentModules.
course_id: the course in the context of which we want StudentModules.
user: the django user for whom to load modules.
user: the django user for whom to load modules.
...
@@ -113,7 +120,7 @@ class FieldDataCache(object):
...
@@ -113,7 +120,7 @@ class FieldDataCache(object):
with
modulestore
()
.
bulk_operations
(
descriptor
.
location
.
course_key
):
with
modulestore
()
.
bulk_operations
(
descriptor
.
location
.
course_key
):
descriptors
=
get_child_descriptors
(
descriptor
,
depth
,
descriptor_filter
)
descriptors
=
get_child_descriptors
(
descriptor
,
depth
,
descriptor_filter
)
return
FieldDataCache
(
descriptors
,
course_id
,
user
,
select_for_update
)
return
FieldDataCache
(
descriptors
,
course_id
,
user
,
select_for_update
,
asides
=
asides
)
def
_query
(
self
,
model_class
,
**
kwargs
):
def
_query
(
self
,
model_class
,
**
kwargs
):
"""
"""
...
@@ -140,6 +147,35 @@ class FieldDataCache(object):
...
@@ -140,6 +147,35 @@ class FieldDataCache(object):
)
)
return
res
return
res
@property
def
_all_usage_ids
(
self
):
"""
Return a set of all usage_ids for the descriptors that this FieldDataCache is caching
against, and well as all asides for those descriptors.
"""
usage_ids
=
set
()
for
descriptor
in
self
.
descriptors
:
usage_ids
.
add
(
descriptor
.
scope_ids
.
usage_id
)
for
aside_type
in
self
.
asides
:
usage_ids
.
add
(
AsideUsageKeyV1
(
descriptor
.
scope_ids
.
usage_id
,
aside_type
))
return
usage_ids
@property
def
_all_block_types
(
self
):
"""
Return a set of all block_types that are cached by this FieldDataCache.
"""
block_types
=
set
()
for
descriptor
in
self
.
descriptors
:
block_types
.
add
(
BlockTypeKeyV1
(
descriptor
.
entry_point
,
descriptor
.
scope_ids
.
block_type
))
for
aside_type
in
self
.
asides
:
block_types
.
add
(
BlockTypeKeyV1
(
XBlockAside
.
entry_point
,
aside_type
))
return
block_types
def
_retrieve_fields
(
self
,
scope
,
fields
):
def
_retrieve_fields
(
self
,
scope
,
fields
):
"""
"""
Queries the database for all of the fields in the specified scope
Queries the database for all of the fields in the specified scope
...
@@ -148,7 +184,7 @@ class FieldDataCache(object):
...
@@ -148,7 +184,7 @@ class FieldDataCache(object):
return
self
.
_chunked_query
(
return
self
.
_chunked_query
(
StudentModule
,
StudentModule
,
'module_state_key__in'
,
'module_state_key__in'
,
(
descriptor
.
scope_ids
.
usage_id
for
descriptor
in
self
.
descriptors
)
,
self
.
_all_usage_ids
,
course_id
=
self
.
course_id
,
course_id
=
self
.
course_id
,
student
=
self
.
user
.
pk
,
student
=
self
.
user
.
pk
,
)
)
...
@@ -156,14 +192,14 @@ class FieldDataCache(object):
...
@@ -156,14 +192,14 @@ class FieldDataCache(object):
return
self
.
_chunked_query
(
return
self
.
_chunked_query
(
XModuleUserStateSummaryField
,
XModuleUserStateSummaryField
,
'usage_id__in'
,
'usage_id__in'
,
(
descriptor
.
scope_ids
.
usage_id
for
descriptor
in
self
.
descriptors
)
,
self
.
_all_usage_ids
,
field_name__in
=
set
(
field
.
name
for
field
in
fields
),
field_name__in
=
set
(
field
.
name
for
field
in
fields
),
)
)
elif
scope
==
Scope
.
preferences
:
elif
scope
==
Scope
.
preferences
:
return
self
.
_chunked_query
(
return
self
.
_chunked_query
(
XModuleStudentPrefsField
,
XModuleStudentPrefsField
,
'module_type__in'
,
'module_type__in'
,
se
t
(
descriptor
.
scope_ids
.
block_type
for
descriptor
in
self
.
descriptors
)
,
se
lf
.
_all_block_types
,
student
=
self
.
user
.
pk
,
student
=
self
.
user
.
pk
,
field_name__in
=
set
(
field
.
name
for
field
in
fields
),
field_name__in
=
set
(
field
.
name
for
field
in
fields
),
)
)
...
@@ -195,7 +231,7 @@ class FieldDataCache(object):
...
@@ -195,7 +231,7 @@ class FieldDataCache(object):
elif
key
.
scope
==
Scope
.
user_state_summary
:
elif
key
.
scope
==
Scope
.
user_state_summary
:
return
(
key
.
scope
,
key
.
block_scope_id
,
key
.
field_name
)
return
(
key
.
scope
,
key
.
block_scope_id
,
key
.
field_name
)
elif
key
.
scope
==
Scope
.
preferences
:
elif
key
.
scope
==
Scope
.
preferences
:
return
(
key
.
scope
,
key
.
block_scope_id
,
key
.
field_name
)
return
(
key
.
scope
,
BlockTypeKeyV1
(
key
.
block_family
,
key
.
block_scope_id
)
,
key
.
field_name
)
elif
key
.
scope
==
Scope
.
user_info
:
elif
key
.
scope
==
Scope
.
user_info
:
return
(
key
.
scope
,
key
.
field_name
)
return
(
key
.
scope
,
key
.
field_name
)
...
@@ -239,31 +275,28 @@ class FieldDataCache(object):
...
@@ -239,31 +275,28 @@ class FieldDataCache(object):
return
field_object
return
field_object
if
key
.
scope
==
Scope
.
user_state
:
if
key
.
scope
==
Scope
.
user_state
:
# When we start allowing block_scope_ids to be either Locations or Locators,
field_object
,
__
=
StudentModule
.
objects
.
get_or_create
(
# this assertion will fail. Fix the code here when that happens!
assert
(
isinstance
(
key
.
block_scope_id
,
UsageKey
))
field_object
,
_
=
StudentModule
.
objects
.
get_or_create
(
course_id
=
self
.
course_id
,
course_id
=
self
.
course_id
,
student_id
=
key
.
user_id
,
student_id
=
key
.
user_id
,
module_state_key
=
key
.
block_scope_id
,
module_state_key
=
key
.
block_scope_id
,
defaults
=
{
defaults
=
{
'state'
:
json
.
dumps
({}),
'state'
:
json
.
dumps
({}),
'module_type'
:
key
.
block_scope_id
.
category
,
'module_type'
:
key
.
block_scope_id
.
block_type
,
},
},
)
)
elif
key
.
scope
==
Scope
.
user_state_summary
:
elif
key
.
scope
==
Scope
.
user_state_summary
:
field_object
,
_
=
XModuleUserStateSummaryField
.
objects
.
get_or_create
(
field_object
,
_
_
=
XModuleUserStateSummaryField
.
objects
.
get_or_create
(
field_name
=
key
.
field_name
,
field_name
=
key
.
field_name
,
usage_id
=
key
.
block_scope_id
usage_id
=
key
.
block_scope_id
)
)
elif
key
.
scope
==
Scope
.
preferences
:
elif
key
.
scope
==
Scope
.
preferences
:
field_object
,
_
=
XModuleStudentPrefsField
.
objects
.
get_or_create
(
field_object
,
_
_
=
XModuleStudentPrefsField
.
objects
.
get_or_create
(
field_name
=
key
.
field_name
,
field_name
=
key
.
field_name
,
module_type
=
key
.
block_scope_id
,
module_type
=
BlockTypeKeyV1
(
key
.
block_family
,
key
.
block_scope_id
)
,
student_id
=
key
.
user_id
,
student_id
=
key
.
user_id
,
)
)
elif
key
.
scope
==
Scope
.
user_info
:
elif
key
.
scope
==
Scope
.
user_info
:
field_object
,
_
=
XModuleStudentInfoField
.
objects
.
get_or_create
(
field_object
,
_
_
=
XModuleStudentInfoField
.
objects
.
get_or_create
(
field_name
=
key
.
field_name
,
field_name
=
key
.
field_name
,
student_id
=
key
.
user_id
,
student_id
=
key
.
user_id
,
)
)
...
...
lms/djangoapps/courseware/models.py
View file @
d919d2ae
...
@@ -18,7 +18,7 @@ from django.db import models
...
@@ -18,7 +18,7 @@ from django.db import models
from
django.db.models.signals
import
post_save
from
django.db.models.signals
import
post_save
from
django.dispatch
import
receiver
from
django.dispatch
import
receiver
from
xmodule_django.models
import
CourseKeyField
,
LocationKeyField
from
xmodule_django.models
import
CourseKeyField
,
LocationKeyField
,
BlockTypeKeyField
class
StudentModule
(
models
.
Model
):
class
StudentModule
(
models
.
Model
):
...
@@ -36,10 +36,7 @@ class StudentModule(models.Model):
...
@@ -36,10 +36,7 @@ class StudentModule(models.Model):
## These three are the key for the object
## These three are the key for the object
module_type
=
models
.
CharField
(
max_length
=
32
,
choices
=
MODULE_TYPES
,
default
=
'problem'
,
db_index
=
True
)
module_type
=
models
.
CharField
(
max_length
=
32
,
choices
=
MODULE_TYPES
,
default
=
'problem'
,
db_index
=
True
)
# Key used to share state. By default, this is the module_id,
# Key used to share state. This is the XBlock usage_id
# but for abtests and the like, this can be set to a shared value
# for many instances of the module.
# Filename for homeworks, etc.
module_state_key
=
LocationKeyField
(
max_length
=
255
,
db_index
=
True
,
db_column
=
'module_id'
)
module_state_key
=
LocationKeyField
(
max_length
=
255
,
db_index
=
True
,
db_column
=
'module_id'
)
student
=
models
.
ForeignKey
(
User
,
db_index
=
True
)
student
=
models
.
ForeignKey
(
User
,
db_index
=
True
)
...
@@ -150,7 +147,7 @@ class XBlockFieldBase(models.Model):
...
@@ -150,7 +147,7 @@ class XBlockFieldBase(models.Model):
return
u'{}<{!r}'
.
format
(
return
u'{}<{!r}'
.
format
(
self
.
__class__
.
__name__
,
self
.
__class__
.
__name__
,
{
{
key
:
getattr
(
self
,
key
)
key
:
getattr
(
self
,
key
)
for
key
in
self
.
_meta
.
get_all_field_names
()
for
key
in
self
.
_meta
.
get_all_field_names
()
if
key
not
in
(
'created'
,
'modified'
)
if
key
not
in
(
'created'
,
'modified'
)
}
}
...
@@ -174,11 +171,11 @@ class XModuleStudentPrefsField(XBlockFieldBase):
...
@@ -174,11 +171,11 @@ class XModuleStudentPrefsField(XBlockFieldBase):
Stores data set in the Scope.preferences scope by an xmodule field
Stores data set in the Scope.preferences scope by an xmodule field
"""
"""
class
Meta
:
class
Meta
:
# pylint: disable=missing-docstring
unique_together
=
((
'student'
,
'module_type'
,
'field_name'
),)
unique_together
=
((
'student'
,
'module_type'
,
'field_name'
),)
# The type of the module for these preferences
# The type of the module for these preferences
module_type
=
models
.
Char
Field
(
max_length
=
64
,
db_index
=
True
)
module_type
=
BlockTypeKey
Field
(
max_length
=
64
,
db_index
=
True
)
student
=
models
.
ForeignKey
(
User
,
db_index
=
True
)
student
=
models
.
ForeignKey
(
User
,
db_index
=
True
)
...
...
lms/djangoapps/courseware/module_render.py
View file @
d919d2ae
...
@@ -23,6 +23,7 @@ from courseware.masquerade import setup_masquerade
...
@@ -23,6 +23,7 @@ from courseware.masquerade import setup_masquerade
from
courseware.model_data
import
FieldDataCache
,
DjangoKeyValueStore
from
courseware.model_data
import
FieldDataCache
,
DjangoKeyValueStore
from
lms.djangoapps.lms_xblock.field_data
import
LmsFieldData
from
lms.djangoapps.lms_xblock.field_data
import
LmsFieldData
from
lms.djangoapps.lms_xblock.runtime
import
LmsModuleSystem
,
unquote_slashes
,
quote_slashes
from
lms.djangoapps.lms_xblock.runtime
import
LmsModuleSystem
,
unquote_slashes
,
quote_slashes
from
lms.djangoapps.lms_xblock.models
import
XBlockAsidesConfig
from
edxmako.shortcuts
import
render_to_string
from
edxmako.shortcuts
import
render_to_string
from
eventtracking
import
tracker
from
eventtracking
import
tracker
from
psychometrics.psychoanalyze
import
make_psychometrics_data_update_handler
from
psychometrics.psychoanalyze
import
make_psychometrics_data_update_handler
...
@@ -405,7 +406,8 @@ def get_module_system_for_user(user, field_data_cache,
...
@@ -405,7 +406,8 @@ def get_module_system_for_user(user, field_data_cache,
field_data_cache_real_user
=
FieldDataCache
.
cache_for_descriptor_descendents
(
field_data_cache_real_user
=
FieldDataCache
.
cache_for_descriptor_descendents
(
course_id
,
course_id
,
real_user
,
real_user
,
module
.
descriptor
module
.
descriptor
,
asides
=
XBlockAsidesConfig
.
possible_asides
(),
)
)
(
inner_system
,
inner_student_data
)
=
get_module_system_for_user
(
(
inner_system
,
inner_student_data
)
=
get_module_system_for_user
(
...
@@ -496,6 +498,8 @@ def get_module_system_for_user(user, field_data_cache,
...
@@ -496,6 +498,8 @@ def get_module_system_for_user(user, field_data_cache,
else
:
else
:
anonymous_student_id
=
anonymous_id_for_user
(
user
,
None
)
anonymous_student_id
=
anonymous_id_for_user
(
user
,
None
)
field_data
=
LmsFieldData
(
descriptor
.
_field_data
,
student_data
)
# pylint: disable=protected-access
system
=
LmsModuleSystem
(
system
=
LmsModuleSystem
(
track_function
=
track_function
,
track_function
=
track_function
,
render_template
=
render_to_string
,
render_template
=
render_to_string
,
...
@@ -541,11 +545,13 @@ def get_module_system_for_user(user, field_data_cache,
...
@@ -541,11 +545,13 @@ def get_module_system_for_user(user, field_data_cache,
services
=
{
services
=
{
'i18n'
:
ModuleI18nService
(),
'i18n'
:
ModuleI18nService
(),
'fs'
:
xblock
.
reference
.
plugins
.
FSService
(),
'fs'
:
xblock
.
reference
.
plugins
.
FSService
(),
'field-data'
:
field_data
,
},
},
get_user_role
=
lambda
:
get_user_role
(
user
,
course_id
),
get_user_role
=
lambda
:
get_user_role
(
user
,
course_id
),
descriptor_runtime
=
descriptor
.
runtime
,
descriptor_runtime
=
descriptor
.
runtime
,
rebind_noauth_module_to_user
=
rebind_noauth_module_to_user
,
rebind_noauth_module_to_user
=
rebind_noauth_module_to_user
,
user_location
=
user_location
,
user_location
=
user_location
,
request_token
=
request_token
,
)
)
# pass position specified in URL to module through ModuleSystem
# pass position specified in URL to module through ModuleSystem
...
@@ -572,7 +578,7 @@ def get_module_system_for_user(user, field_data_cache,
...
@@ -572,7 +578,7 @@ def get_module_system_for_user(user, field_data_cache,
else
:
else
:
system
.
error_descriptor_class
=
NonStaffErrorDescriptor
system
.
error_descriptor_class
=
NonStaffErrorDescriptor
return
system
,
student
_data
return
system
,
field
_data
def
get_module_for_descriptor_internal
(
user
,
descriptor
,
field_data_cache
,
course_id
,
# pylint: disable=invalid-name
def
get_module_for_descriptor_internal
(
user
,
descriptor
,
field_data_cache
,
course_id
,
# pylint: disable=invalid-name
...
@@ -594,7 +600,7 @@ def get_module_for_descriptor_internal(user, descriptor, field_data_cache, cours
...
@@ -594,7 +600,7 @@ def get_module_for_descriptor_internal(user, descriptor, field_data_cache, cours
if
not
has_access
(
user
,
'load'
,
descriptor
,
course_id
):
if
not
has_access
(
user
,
'load'
,
descriptor
,
course_id
):
return
None
return
None
(
system
,
student
_data
)
=
get_module_system_for_user
(
(
system
,
field
_data
)
=
get_module_system_for_user
(
user
=
user
,
user
=
user
,
field_data_cache
=
field_data_cache
,
# These have implicit user bindings, the rest of args are considered not to
field_data_cache
=
field_data_cache
,
# These have implicit user bindings, the rest of args are considered not to
descriptor
=
descriptor
,
descriptor
=
descriptor
,
...
@@ -609,7 +615,7 @@ def get_module_for_descriptor_internal(user, descriptor, field_data_cache, cours
...
@@ -609,7 +615,7 @@ def get_module_for_descriptor_internal(user, descriptor, field_data_cache, cours
request_token
=
request_token
request_token
=
request_token
)
)
descriptor
.
bind_for_student
(
system
,
LmsFieldData
(
descriptor
.
_field_data
,
student_data
)
)
# pylint: disable=protected-access
descriptor
.
bind_for_student
(
system
,
field_data
)
# pylint: disable=protected-access
descriptor
.
scope_ids
=
descriptor
.
scope_ids
.
_replace
(
user_id
=
user
.
id
)
# pylint: disable=protected-access
descriptor
.
scope_ids
=
descriptor
.
scope_ids
.
_replace
(
user_id
=
user
.
id
)
# pylint: disable=protected-access
return
descriptor
return
descriptor
...
...
lms/djangoapps/courseware/tests/test_model_data.py
View file @
d919d2ae
...
@@ -16,9 +16,10 @@ from courseware.tests.factories import UserStateSummaryFactory
...
@@ -16,9 +16,10 @@ from courseware.tests.factories import UserStateSummaryFactory
from
courseware.tests.factories
import
StudentPrefsFactory
,
StudentInfoFactory
from
courseware.tests.factories
import
StudentPrefsFactory
,
StudentInfoFactory
from
xblock.fields
import
Scope
,
BlockScope
,
ScopeIds
from
xblock.fields
import
Scope
,
BlockScope
,
ScopeIds
from
xblock.exceptions
import
KeyValueMultiSaveError
from
xblock.core
import
XBlock
from
django.test
import
TestCase
from
django.test
import
TestCase
from
django.db
import
DatabaseError
from
django.db
import
DatabaseError
from
xblock.exceptions
import
KeyValueMultiSaveError
def
mock_field
(
scope
,
name
):
def
mock_field
(
scope
,
name
):
...
@@ -29,7 +30,7 @@ def mock_field(scope, name):
...
@@ -29,7 +30,7 @@ def mock_field(scope, name):
def
mock_descriptor
(
fields
=
[]):
def
mock_descriptor
(
fields
=
[]):
descriptor
=
Mock
()
descriptor
=
Mock
(
entry_point
=
XBlock
.
entry_point
)
descriptor
.
scope_ids
=
ScopeIds
(
'user1'
,
'mock_problem'
,
location
(
'def_id'
),
location
(
'usage_id'
))
descriptor
.
scope_ids
=
ScopeIds
(
'user1'
,
'mock_problem'
,
location
(
'def_id'
),
location
(
'usage_id'
))
descriptor
.
module_class
.
fields
.
values
.
return_value
=
fields
descriptor
.
module_class
.
fields
.
values
.
return_value
=
fields
descriptor
.
fields
.
values
.
return_value
=
fields
descriptor
.
fields
.
values
.
return_value
=
fields
...
...
lms/djangoapps/courseware/views.py
View file @
d919d2ae
...
@@ -39,6 +39,8 @@ from .module_render import toc_for_course, get_module_for_descriptor, get_module
...
@@ -39,6 +39,8 @@ from .module_render import toc_for_course, get_module_for_descriptor, get_module
from
courseware.models
import
StudentModule
,
StudentModuleHistory
from
courseware.models
import
StudentModule
,
StudentModuleHistory
from
course_modes.models
import
CourseMode
from
course_modes.models
import
CourseMode
from
lms.djangoapps.lms_xblock.models
import
XBlockAsidesConfig
from
open_ended_grading
import
open_ended_notifications
from
open_ended_grading
import
open_ended_notifications
from
student.models
import
UserTestGroup
,
CourseEnrollment
from
student.models
import
UserTestGroup
,
CourseEnrollment
from
student.views
import
single_course_reverification_info
,
is_course_blocked
from
student.views
import
single_course_reverification_info
,
is_course_blocked
...
@@ -444,7 +446,8 @@ def _index_bulk_op(request, course_key, chapter, section, position):
...
@@ -444,7 +446,8 @@ def _index_bulk_op(request, course_key, chapter, section, position):
# Load all descendants of the section, because we're going to display its
# Load all descendants of the section, because we're going to display its
# html, which in general will need all of its children
# html, which in general will need all of its children
section_field_data_cache
=
FieldDataCache
.
cache_for_descriptor_descendents
(
section_field_data_cache
=
FieldDataCache
.
cache_for_descriptor_descendents
(
course_key
,
user
,
section_descriptor
,
depth
=
None
)
course_key
,
user
,
section_descriptor
,
depth
=
None
,
asides
=
XBlockAsidesConfig
.
possible_asides
()
)
# Verify that position a string is in fact an int
# Verify that position a string is in fact an int
if
position
is
not
None
:
if
position
is
not
None
:
...
...
lms/djangoapps/instructor/views/instructor_dashboard.py
View file @
d919d2ae
...
@@ -18,6 +18,7 @@ from django.utils.html import escape
...
@@ -18,6 +18,7 @@ from django.utils.html import escape
from
django.http
import
Http404
from
django.http
import
Http404
from
django.conf
import
settings
from
django.conf
import
settings
from
util.json_request
import
JsonResponse
from
util.json_request
import
JsonResponse
from
mock
import
patch
from
lms.djangoapps.lms_xblock.runtime
import
quote_slashes
from
lms.djangoapps.lms_xblock.runtime
import
quote_slashes
from
xmodule_modifiers
import
wrap_xblock
from
xmodule_modifiers
import
wrap_xblock
...
@@ -323,10 +324,21 @@ def _section_data_download(course, access):
...
@@ -323,10 +324,21 @@ def _section_data_download(course, access):
return
section_data
return
section_data
def
null_get_asides
(
block
):
# pylint: disable=unused-argument
"""
get_aside method for monkey-patching into descriptor_global_get_asides
while rendering an HtmlDescriptor for email text editing. This returns
an empty list.
"""
return
[]
def
_section_send_email
(
course
,
access
):
def
_section_send_email
(
course
,
access
):
""" Provide data for the corresponding bulk email section """
""" Provide data for the corresponding bulk email section """
course_key
=
course
.
id
course_key
=
course
.
id
# Monkey-patch descriptor_global_get_asides to return no asides for the duration of this render
with
patch
(
'xmodule.x_module.descriptor_global_get_asides'
,
null_get_asides
):
# This HtmlDescriptor is only being used to generate a nice text editor.
# This HtmlDescriptor is only being used to generate a nice text editor.
html_module
=
HtmlDescriptor
(
html_module
=
HtmlDescriptor
(
course
.
system
,
course
.
system
,
...
...
lms/djangoapps/lms_xblock/admin.py
View file @
d919d2ae
"""
Django admin dashboard configuration for LMS XBlock infrastructure.
"""
from
django.contrib
import
admin
from
django.contrib
import
admin
from
config_models.admin
import
ConfigurationModelAdmin
from
config_models.admin
import
ConfigurationModelAdmin
from
lms.djangoapps.lms_xblock.models
import
XBlockAsidesConfig
from
lms.djangoapps.lms_xblock.models
import
XBlockAsidesConfig
...
...
lms/djangoapps/lms_xblock/field_data.py
View file @
d919d2ae
...
@@ -16,7 +16,7 @@ class LmsFieldData(SplitFieldData):
...
@@ -16,7 +16,7 @@ class LmsFieldData(SplitFieldData):
def
__init__
(
self
,
authored_data
,
student_data
):
def
__init__
(
self
,
authored_data
,
student_data
):
# Make sure that we don't repeatedly nest LmsFieldData instances
# Make sure that we don't repeatedly nest LmsFieldData instances
if
isinstance
(
authored_data
,
LmsFieldData
):
if
isinstance
(
authored_data
,
LmsFieldData
):
authored_data
=
authored_data
.
_authored_data
# pylint: disable=protected-
member
authored_data
=
authored_data
.
_authored_data
# pylint: disable=protected-
access
else
:
else
:
authored_data
=
ReadOnlyFieldData
(
authored_data
)
authored_data
=
ReadOnlyFieldData
(
authored_data
)
...
...
lms/djangoapps/lms_xblock/models.py
View file @
d919d2ae
"""
Models used by LMS XBlock infrastructure.
Includes:
XBlockAsidesConfig: A ConfigurationModel for managing how XBlockAsides are
rendered in the LMS.
"""
from
django.db.models
import
TextField
from
django.db.models
import
TextField
from
config_models.models
import
ConfigurationModel
from
config_models.models
import
ConfigurationModel
from
xblock.core
import
XBlockAside
class
XBlockAsidesConfig
(
ConfigurationModel
):
class
XBlockAsidesConfig
(
ConfigurationModel
):
"""
"""
Configuration for XBlockAsides.
Configuration for XBlockAsides.
...
@@ -11,3 +22,10 @@ class XBlockAsidesConfig(ConfigurationModel):
...
@@ -11,3 +22,10 @@ class XBlockAsidesConfig(ConfigurationModel):
default
=
"about course_info static_tab"
,
default
=
"about course_info static_tab"
,
help_text
=
"Space-separated list of XBlocks on which XBlockAsides should never render."
help_text
=
"Space-separated list of XBlocks on which XBlockAsides should never render."
)
)
@classmethod
def
possible_asides
(
cls
):
"""
Return a list of all asides that are enabled across all XBlocks.
"""
return
[
aside_type
for
aside_type
,
__
in
XBlockAside
.
load_classes
()]
lms/djangoapps/lms_xblock/runtime.py
View file @
d919d2ae
...
@@ -7,7 +7,9 @@ import xblock.reference.plugins
...
@@ -7,7 +7,9 @@ import xblock.reference.plugins
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
from
django.conf
import
settings
from
django.conf
import
settings
from
lms.djangoapps.lms_xblock.models
import
XBlockAsidesConfig
from
openedx.core.djangoapps.user_api.api
import
course_tag
as
user_course_tag_api
from
openedx.core.djangoapps.user_api.api
import
course_tag
as
user_course_tag_api
from
xblock.core
import
XBlockAside
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
from
xmodule.x_module
import
ModuleSystem
from
xmodule.x_module
import
ModuleSystem
from
xmodule.partitions.partitions_service
import
PartitionService
from
xmodule.partitions.partitions_service
import
PartitionService
...
@@ -87,8 +89,8 @@ class LmsHandlerUrls(object):
...
@@ -87,8 +89,8 @@ class LmsHandlerUrls(object):
view_name
=
'xblock_handler_noauth'
view_name
=
'xblock_handler_noauth'
url
=
reverse
(
view_name
,
kwargs
=
{
url
=
reverse
(
view_name
,
kwargs
=
{
'course_id'
:
self
.
course_id
.
to_deprecated_string
(
),
'course_id'
:
unicode
(
self
.
course_id
),
'usage_id'
:
quote_slashes
(
block
.
scope_ids
.
usage_id
.
to_deprecated_string
(
)
.
encode
(
'utf-8'
)),
'usage_id'
:
quote_slashes
(
unicode
(
block
.
scope_ids
.
usage_id
)
.
encode
(
'utf-8'
)),
'handler'
:
handler_name
,
'handler'
:
handler_name
,
'suffix'
:
suffix
,
'suffix'
:
suffix
,
})
})
...
@@ -198,4 +200,50 @@ class LmsModuleSystem(LmsHandlerUrls, ModuleSystem): # pylint: disable=abstract
...
@@ -198,4 +200,50 @@ class LmsModuleSystem(LmsHandlerUrls, ModuleSystem): # pylint: disable=abstract
track_function
=
kwargs
.
get
(
'track_function'
,
None
),
track_function
=
kwargs
.
get
(
'track_function'
,
None
),
)
)
services
[
'fs'
]
=
xblock
.
reference
.
plugins
.
FSService
()
services
[
'fs'
]
=
xblock
.
reference
.
plugins
.
FSService
()
self
.
request_token
=
kwargs
.
pop
(
'request_token'
,
None
)
super
(
LmsModuleSystem
,
self
)
.
__init__
(
**
kwargs
)
super
(
LmsModuleSystem
,
self
)
.
__init__
(
**
kwargs
)
def
wrap_aside
(
self
,
block
,
aside
,
view
,
frag
,
context
):
"""
Creates a div which identifies the aside, points to the original block,
and writes out the json_init_args into a script tag.
The default implementation creates a frag to wraps frag w/ a div identifying the xblock. If you have
javascript, you'll need to override this impl
"""
extra_data
=
{
'block-id'
:
quote_slashes
(
unicode
(
block
.
scope_ids
.
usage_id
)),
'url-selector'
:
'asideBaseUrl'
,
'runtime-class'
:
'LmsRuntime'
,
}
if
self
.
request_token
:
extra_data
[
'request-token'
]
=
self
.
request_token
return
self
.
_wrap_ele
(
aside
,
view
,
frag
,
extra_data
,
)
def
get_asides
(
self
,
block
):
"""
Return all of the asides which might be decorating this `block`.
Arguments:
block (:class:`.XBlock`): The block to render retrieve asides for.
"""
config
=
XBlockAsidesConfig
.
current
()
if
not
config
.
enabled
:
return
[]
if
block
.
scope_ids
.
block_type
in
config
.
disabled_blocks
.
split
():
return
[]
return
[
self
.
get_aside_of_type
(
block
,
aside_type
)
for
aside_type
,
__
in
XBlockAside
.
load_classes
()
]
lms/djangoapps/lms_xblock/test/test_runtime.py
View file @
d919d2ae
...
@@ -10,6 +10,7 @@ from unittest import TestCase
...
@@ -10,6 +10,7 @@ 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
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
TEST_STRINGS
=
[
TEST_STRINGS
=
[
''
,
''
,
...
@@ -42,8 +43,7 @@ class TestHandlerUrl(TestCase):
...
@@ -42,8 +43,7 @@ class TestHandlerUrl(TestCase):
"""Test the LMS handler_url"""
"""Test the LMS handler_url"""
def
setUp
(
self
):
def
setUp
(
self
):
self
.
block
=
Mock
()
self
.
block
=
Mock
(
name
=
'block'
,
scope_ids
=
ScopeIds
(
None
,
None
,
None
,
'dummy'
))
self
.
block
.
scope_ids
.
usage_id
.
to_deprecated_string
.
return_value
.
encode
.
return_value
=
'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/djangoapps/open_ended_grading/tests.py
View file @
d919d2ae
...
@@ -21,7 +21,7 @@ from xblock.fields import ScopeIds
...
@@ -21,7 +21,7 @@ from xblock.fields import ScopeIds
from
courseware.tests
import
factories
from
courseware.tests
import
factories
from
courseware.tests.helpers
import
LoginEnrollmentTestCase
from
courseware.tests.helpers
import
LoginEnrollmentTestCase
from
lms.
lib.
xblock.runtime
import
LmsModuleSystem
from
lms.
djangoapps.lms_
xblock.runtime
import
LmsModuleSystem
from
student.roles
import
CourseStaffRole
from
student.roles
import
CourseStaffRole
from
student.models
import
unique_id_for_user
from
student.models
import
unique_id_for_user
from
xmodule
import
peer_grading_module
from
xmodule
import
peer_grading_module
...
...
lms/envs/common.py
View file @
d919d2ae
...
@@ -1165,7 +1165,7 @@ PIPELINE_JS = {
...
@@ -1165,7 +1165,7 @@ PIPELINE_JS = {
'application'
:
{
'application'
:
{
# Application will contain all paths not in courseware_only_js
# Application will contain all paths not in courseware_only_js
'source_filenames'
:
sorted
(
common_js
)
+
sorted
(
project_js
)
+
[
'source_filenames'
:
[
'js/xblock/core.js'
]
+
sorted
(
common_js
)
+
sorted
(
project_js
)
+
[
'js/form.ext.js'
,
'js/form.ext.js'
,
'js/my_courses_dropdown.js'
,
'js/my_courses_dropdown.js'
,
'js/toggle_login_modal.js'
,
'js/toggle_login_modal.js'
,
...
@@ -1514,6 +1514,8 @@ INSTALLED_APPS = (
...
@@ -1514,6 +1514,8 @@ INSTALLED_APPS = (
# Surveys
# Surveys
'survey'
,
'survey'
,
'lms.djangoapps.lms_xblock'
,
)
)
######################### MARKETING SITE ###############################
######################### MARKETING SITE ###############################
...
...
lms/static/js/spec/main.js
View file @
d919d2ae
...
@@ -49,7 +49,7 @@
...
@@ -49,7 +49,7 @@
'tender'
:
'//edxedge.tenderapp.com/tender_widget'
,
'tender'
:
'//edxedge.tenderapp.com/tender_widget'
,
'coffee/src/ajax_prefix'
:
'xmodule_js/common_static/coffee/src/ajax_prefix'
,
'coffee/src/ajax_prefix'
:
'xmodule_js/common_static/coffee/src/ajax_prefix'
,
'xmodule_js/common_static/js/test/add_ajax_prefix'
:
'xmodule_js/common_static/js/test/add_ajax_prefix'
,
'xmodule_js/common_static/js/test/add_ajax_prefix'
:
'xmodule_js/common_static/js/test/add_ajax_prefix'
,
'xblock/core'
:
'xmodule_js/common_static/
coffee/src
/xblock/core'
,
'xblock/core'
:
'xmodule_js/common_static/
js
/xblock/core'
,
'xblock/runtime.v1'
:
'xmodule_js/common_static/coffee/src/xblock/runtime.v1'
,
'xblock/runtime.v1'
:
'xmodule_js/common_static/coffee/src/xblock/runtime.v1'
,
'xblock/lms.runtime.v1'
:
'coffee/src/xblock/lms.runtime.v1'
,
'xblock/lms.runtime.v1'
:
'coffee/src/xblock/lms.runtime.v1'
,
'capa/display'
:
'xmodule_js/src/capa/display'
,
'capa/display'
:
'xmodule_js/src/capa/display'
,
...
...
lms/static/js_test.yml
View file @
d919d2ae
...
@@ -45,6 +45,7 @@ lib_paths:
...
@@ -45,6 +45,7 @@ lib_paths:
-
xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport.js
-
xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport.js
-
xmodule_js/common_static/js/vendor/url.min.js
-
xmodule_js/common_static/js/vendor/url.min.js
-
xmodule_js/common_static/coffee/src/jquery.immediateDescendents.js
-
xmodule_js/common_static/coffee/src/jquery.immediateDescendents.js
-
xmodule_js/common_static/js/xblock
-
xmodule_js/common_static/coffee/src/xblock
-
xmodule_js/common_static/coffee/src/xblock
-
xmodule_js/common_static/js/vendor/sinon-1.7.1.js
-
xmodule_js/common_static/js/vendor/sinon-1.7.1.js
-
xmodule_js/src/capa/
-
xmodule_js/src/capa/
...
...
lms/static/js_test_coffee.yml
View file @
d919d2ae
...
@@ -42,6 +42,7 @@ lib_paths:
...
@@ -42,6 +42,7 @@ lib_paths:
-
xmodule_js/common_static/js/vendor/CodeMirror/codemirror.js
-
xmodule_js/common_static/js/vendor/CodeMirror/codemirror.js
-
xmodule_js/common_static/js/vendor/URI.min.js
-
xmodule_js/common_static/js/vendor/URI.min.js
-
xmodule_js/common_static/coffee/src/jquery.immediateDescendents.js
-
xmodule_js/common_static/coffee/src/jquery.immediateDescendents.js
-
xmodule_js/common_static/js/xblock
-
xmodule_js/common_static/coffee/src/xblock
-
xmodule_js/common_static/coffee/src/xblock
-
xmodule_js/src/capa/
-
xmodule_js/src/capa/
-
xmodule_js/src/video/
-
xmodule_js/src/video/
...
...
pylintrc
View file @
d919d2ae
...
@@ -137,6 +137,8 @@ generated-members=
...
@@ -137,6 +137,8 @@ generated-members=
category,
category,
name,
name,
revision,
revision,
# For django models
_meta,
[BASIC]
[BASIC]
...
...
requirements/edx/github.txt
View file @
d919d2ae
...
@@ -22,16 +22,16 @@
...
@@ -22,16 +22,16 @@
git+https://github.com/mitocw/django-cas.git@60a5b8e5a62e63e0d5d224a87f0b489201a0c695#egg=django-cas
git+https://github.com/mitocw/django-cas.git@60a5b8e5a62e63e0d5d224a87f0b489201a0c695#egg=django-cas
# Our libraries:
# Our libraries:
-e git+https://github.com/edx/XBlock.git@
2029af2a4b524310847decfb34ef39da8a30dc4
e#egg=XBlock
-e git+https://github.com/edx/XBlock.git@
9c634481dfc85a17dcb3351ca232d7098a38e10
e#egg=XBlock
-e git+https://github.com/edx/codejail.git@75307b25032d8b0040b1408c01fd6cc9a1989bd5#egg=codejail
-e git+https://github.com/edx/codejail.git@75307b25032d8b0040b1408c01fd6cc9a1989bd5#egg=codejail
-e git+https://github.com/edx/diff-cover.git@v0.7.2#egg=diff_cover
-e git+https://github.com/edx/diff-cover.git@v0.7.2#egg=diff_cover
-e git+https://github.com/edx/js-test-tool.git@v0.1.6#egg=js_test_tool
-e git+https://github.com/edx/js-test-tool.git@v0.1.6#egg=js_test_tool
-e git+https://github.com/edx/event-tracking.git@0.1.0#egg=event-tracking
-e git+https://github.com/edx/event-tracking.git@0.1.0#egg=event-tracking
-e git+https://github.com/edx/bok-choy.git@4a259e3548a19e41cc39433caf68ea58d10a27ba#egg=bok_choy
-e git+https://github.com/edx/bok-choy.git@4a259e3548a19e41cc39433caf68ea58d10a27ba#egg=bok_choy
-e git+https://github.com/edx-solutions/django-splash.git@7579d052afcf474ece1239153cffe1c89935bc4f#egg=django-splash
-e git+https://github.com/edx-solutions/django-splash.git@7579d052afcf474ece1239153cffe1c89935bc4f#egg=django-splash
-e git+https://github.com/edx/acid-block.git@
df1a7f0cae46567c251d507b8c72168aed8ec042
#egg=acid-xblock
-e git+https://github.com/edx/acid-block.git@
e46f9cda8a03e121a00c7e347084d142d22ebfb7
#egg=acid-xblock
-e git+https://github.com/edx/edx-ora2.git@release-2014-10-27T19.33#egg=edx-ora2
-e git+https://github.com/edx/edx-ora2.git@release-2014-10-27T19.33#egg=edx-ora2
-e git+https://github.com/edx/opaque-keys.git@
b12401384921c075e5a4ed7aedc3bea57f56ec32
#egg=opaque-keys
-e git+https://github.com/edx/opaque-keys.git@
1254ed4d615a428591850656f39f26509b86d30a
#egg=opaque-keys
-e git+https://github.com/edx/ease.git@97de68448e5495385ba043d3091f570a699d5b5f#egg=ease
-e git+https://github.com/edx/ease.git@97de68448e5495385ba043d3091f570a699d5b5f#egg=ease
-e git+https://github.com/edx/i18n-tools.git@56f048af9b6868613c14aeae760548834c495011#egg=i18n-tools
-e git+https://github.com/edx/i18n-tools.git@56f048af9b6868613c14aeae760548834c495011#egg=i18n-tools
-e git+https://github.com/edx/edx-oauth2-provider.git@0.4.0#egg=oauth2-provider
-e git+https://github.com/edx/edx-oauth2-provider.git@0.4.0#egg=oauth2-provider
...
...
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