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
b7680f31
Commit
b7680f31
authored
Mar 05, 2013
by
Calen Pennington
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix tests except for conditional module and open ended grading
parent
0d83fefe
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
123 additions
and
80 deletions
+123
-80
cms/djangoapps/contentstore/tests/test_contentstore.py
+11
-13
cms/djangoapps/contentstore/tests/test_course_settings.py
+14
-14
cms/djangoapps/contentstore/views.py
+4
-1
cms/djangoapps/models/settings/course_metadata.py
+32
-25
common/lib/xmodule/xmodule/course_module.py
+5
-3
common/lib/xmodule/xmodule/mako_module.py
+3
-3
common/lib/xmodule/xmodule/modulestore/inheritance.py
+14
-13
common/lib/xmodule/xmodule/modulestore/mongo.py
+14
-2
common/lib/xmodule/xmodule/modulestore/xml_exporter.py
+4
-5
common/lib/xmodule/xmodule/tests/test_capa_module.py
+2
-0
lms/djangoapps/courseware/model_data.py
+19
-0
lms/djangoapps/courseware/tests/test_model_data.py
+0
-0
local-requirements.txt
+1
-1
No files found.
cms/djangoapps/contentstore/tests/test_contentstore.py
View file @
b7680f31
...
@@ -6,6 +6,7 @@ from django.conf import settings
...
@@ -6,6 +6,7 @@ from django.conf import settings
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
from
path
import
path
from
path
import
path
from
tempdir
import
mkdtemp_clean
from
tempdir
import
mkdtemp_clean
from
datetime
import
timedelta
import
json
import
json
from
fs.osfs
import
OSFS
from
fs.osfs
import
OSFS
import
copy
import
copy
...
@@ -27,6 +28,7 @@ from xmodule.contentstore.django import contentstore
...
@@ -27,6 +28,7 @@ from xmodule.contentstore.django import contentstore
from
xmodule.templates
import
update_templates
from
xmodule.templates
import
update_templates
from
xmodule.modulestore.xml_exporter
import
export_to_xml
from
xmodule.modulestore.xml_exporter
import
export_to_xml
from
xmodule.modulestore.xml_importer
import
import_from_xml
from
xmodule.modulestore.xml_importer
import
import_from_xml
from
xmodule.modulestore.inheritance
import
own_metadata
from
xmodule.templates
import
update_templates
from
xmodule.templates
import
update_templates
from
xmodule.capa_module
import
CapaDescriptor
from
xmodule.capa_module
import
CapaDescriptor
...
@@ -218,7 +220,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
...
@@ -218,7 +220,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
# compare what's on disk compared to what we have in our course
# compare what's on disk compared to what we have in our course
with
fs
.
open
(
'grading_policy.json'
,
'r'
)
as
grading_policy
:
with
fs
.
open
(
'grading_policy.json'
,
'r'
)
as
grading_policy
:
on_disk
=
loads
(
grading_policy
.
read
())
on_disk
=
loads
(
grading_policy
.
read
())
self
.
assertEqual
(
on_disk
,
course
.
definition
[
'data'
][
'grading_policy'
]
)
self
.
assertEqual
(
on_disk
,
course
.
grading_policy
)
#check for policy.json
#check for policy.json
self
.
assertTrue
(
fs
.
exists
(
'policy.json'
))
self
.
assertTrue
(
fs
.
exists
(
'policy.json'
))
...
@@ -227,7 +229,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
...
@@ -227,7 +229,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
with
fs
.
open
(
'policy.json'
,
'r'
)
as
course_policy
:
with
fs
.
open
(
'policy.json'
,
'r'
)
as
course_policy
:
on_disk
=
loads
(
course_policy
.
read
())
on_disk
=
loads
(
course_policy
.
read
())
self
.
assertIn
(
'course/6.002_Spring_2012'
,
on_disk
)
self
.
assertIn
(
'course/6.002_Spring_2012'
,
on_disk
)
self
.
assertEqual
(
on_disk
[
'course/6.002_Spring_2012'
],
course
.
metadata
)
self
.
assertEqual
(
on_disk
[
'course/6.002_Spring_2012'
],
own_metadata
(
course
)
)
# remove old course
# remove old course
delete_course
(
ms
,
cs
,
location
)
delete_course
(
ms
,
cs
,
location
)
...
@@ -444,8 +446,7 @@ class ContentStoreTest(ModuleStoreTestCase):
...
@@ -444,8 +446,7 @@ class ContentStoreTest(ModuleStoreTestCase):
# let's assert on the metadata_inheritance on an existing vertical
# let's assert on the metadata_inheritance on an existing vertical
for
vertical
in
verticals
:
for
vertical
in
verticals
:
self
.
assertIn
(
'xqa_key'
,
vertical
.
metadata
)
self
.
assertEqual
(
course
.
lms
.
xqa_key
,
vertical
.
lms
.
xqa_key
)
self
.
assertEqual
(
course
.
metadata
[
'xqa_key'
],
vertical
.
metadata
[
'xqa_key'
])
self
.
assertGreater
(
len
(
verticals
),
0
)
self
.
assertGreater
(
len
(
verticals
),
0
)
...
@@ -455,31 +456,28 @@ class ContentStoreTest(ModuleStoreTestCase):
...
@@ -455,31 +456,28 @@ class ContentStoreTest(ModuleStoreTestCase):
# crate a new module and add it as a child to a vertical
# crate a new module and add it as a child to a vertical
ms
.
clone_item
(
source_template_location
,
new_component_location
)
ms
.
clone_item
(
source_template_location
,
new_component_location
)
parent
=
verticals
[
0
]
parent
=
verticals
[
0
]
ms
.
update_children
(
parent
.
location
,
parent
.
definition
.
get
(
'children'
,
[])
+
[
new_component_location
.
url
()])
ms
.
update_children
(
parent
.
location
,
parent
.
children
+
[
new_component_location
.
url
()])
# flush the cache
# flush the cache
ms
.
get_cached_metadata_inheritance_tree
(
new_component_location
,
-
1
)
ms
.
get_cached_metadata_inheritance_tree
(
new_component_location
,
-
1
)
new_module
=
ms
.
get_item
(
new_component_location
)
new_module
=
ms
.
get_item
(
new_component_location
)
# check for grace period definition which should be defined at the course level
# check for grace period definition which should be defined at the course level
self
.
assert
In
(
'graceperiod'
,
new_module
.
metadata
)
self
.
assert
Equal
(
parent
.
lms
.
graceperiod
,
new_module
.
lms
.
graceperiod
)
self
.
assertEqual
(
parent
.
metadata
[
'graceperiod'
],
new_module
.
metadata
[
'graceperiod'
])
self
.
assertEqual
(
course
.
lms
.
xqa_key
,
new_module
.
lms
.
xqa_key
)
self
.
assertEqual
(
course
.
metadata
[
'xqa_key'
],
new_module
.
metadata
[
'xqa_key'
])
#
#
# now let's define an override at the leaf node level
# now let's define an override at the leaf node level
#
#
new_module
.
metadata
[
'graceperiod'
]
=
'1 day'
new_module
.
lms
.
graceperiod
=
timedelta
(
1
)
ms
.
update_metadata
(
new_module
.
location
,
new_module
.
metadata
)
ms
.
update_metadata
(
new_module
.
location
,
own_metadata
(
new_module
)
)
# flush the cache and refetch
# flush the cache and refetch
ms
.
get_cached_metadata_inheritance_tree
(
new_component_location
,
-
1
)
ms
.
get_cached_metadata_inheritance_tree
(
new_component_location
,
-
1
)
new_module
=
ms
.
get_item
(
new_component_location
)
new_module
=
ms
.
get_item
(
new_component_location
)
self
.
assertIn
(
'graceperiod'
,
new_module
.
metadata
)
self
.
assertEqual
(
timedelta
(
1
),
new_module
.
lms
.
graceperiod
)
self
.
assertEqual
(
'1 day'
,
new_module
.
metadata
[
'graceperiod'
])
class
TemplateTestCase
(
ModuleStoreTestCase
):
class
TemplateTestCase
(
ModuleStoreTestCase
):
...
...
cms/djangoapps/contentstore/tests/test_course_settings.py
View file @
b7680f31
...
@@ -287,31 +287,31 @@ class CourseMetadataEditingTest(CourseTestCase):
...
@@ -287,31 +287,31 @@ class CourseMetadataEditingTest(CourseTestCase):
def
test_update_from_json
(
self
):
def
test_update_from_json
(
self
):
test_model
=
CourseMetadata
.
update_from_json
(
self
.
course_location
,
test_model
=
CourseMetadata
.
update_from_json
(
self
.
course_location
,
{
"a
"
:
1
,
{
"a
dvertised_start"
:
"start A"
,
"
b_a_c_h
"
:
{
"c"
:
"test"
},
"
testcenter_info
"
:
{
"c"
:
"test"
},
"
test_text"
:
"a text string"
})
"
days_early_for_beta"
:
2
})
self
.
update_check
(
test_model
)
self
.
update_check
(
test_model
)
# try fresh fetch to ensure persistence
# try fresh fetch to ensure persistence
test_model
=
CourseMetadata
.
fetch
(
self
.
course_location
)
test_model
=
CourseMetadata
.
fetch
(
self
.
course_location
)
self
.
update_check
(
test_model
)
self
.
update_check
(
test_model
)
# now change some of the existing metadata
# now change some of the existing metadata
test_model
=
CourseMetadata
.
update_from_json
(
self
.
course_location
,
test_model
=
CourseMetadata
.
update_from_json
(
self
.
course_location
,
{
"a
"
:
2
,
{
"a
dvertised_start"
:
"start B"
,
"display_name"
:
"jolly roger"
})
"display_name"
:
"jolly roger"
})
self
.
assertIn
(
'display_name'
,
test_model
,
'Missing editable metadata field'
)
self
.
assertIn
(
'display_name'
,
test_model
,
'Missing editable metadata field'
)
self
.
assertEqual
(
test_model
[
'display_name'
],
'jolly roger'
,
"not expected value"
)
self
.
assertEqual
(
test_model
[
'display_name'
],
'jolly roger'
,
"not expected value"
)
self
.
assertIn
(
'a
'
,
test_model
,
'Missing revised a
metadata field'
)
self
.
assertIn
(
'a
dvertised_start'
,
test_model
,
'Missing revised advertised_start
metadata field'
)
self
.
assertEqual
(
test_model
[
'a
'
],
2
,
"a
not expected value"
)
self
.
assertEqual
(
test_model
[
'a
dvertised_start'
],
'start B'
,
"advertised_start
not expected value"
)
def
update_check
(
self
,
test_model
):
def
update_check
(
self
,
test_model
):
self
.
assertIn
(
'display_name'
,
test_model
,
'Missing editable metadata field'
)
self
.
assertIn
(
'display_name'
,
test_model
,
'Missing editable metadata field'
)
self
.
assertEqual
(
test_model
[
'display_name'
],
'Robot Super Course'
,
"not expected value"
)
self
.
assertEqual
(
test_model
[
'display_name'
],
'Robot Super Course'
,
"not expected value"
)
self
.
assertIn
(
'a
'
,
test_model
,
'Missing new a
metadata field'
)
self
.
assertIn
(
'a
dvertised_start'
,
test_model
,
'Missing new advertised_start
metadata field'
)
self
.
assertEqual
(
test_model
[
'a
'
],
1
,
"a
not expected value"
)
self
.
assertEqual
(
test_model
[
'a
dvertised_start'
],
'start A'
,
"advertised_start
not expected value"
)
self
.
assertIn
(
'
b_a_c_h'
,
test_model
,
'Missing b_a_c_h
metadata field'
)
self
.
assertIn
(
'
testcenter_info'
,
test_model
,
'Missing testcenter_info
metadata field'
)
self
.
assertDictEqual
(
test_model
[
'
b_a_c_h'
],
{
"c"
:
"test"
},
"b_a_c_h
not expected value"
)
self
.
assertDictEqual
(
test_model
[
'
testcenter_info'
],
{
"c"
:
"test"
},
"testcenter_info
not expected value"
)
self
.
assertIn
(
'
test_text'
,
test_model
,
'Missing test_text
metadata field'
)
self
.
assertIn
(
'
days_early_for_beta'
,
test_model
,
'Missing days_early_for_beta
metadata field'
)
self
.
assertEqual
(
test_model
[
'
test_text'
],
"a text string"
,
"test_text
not expected value"
)
self
.
assertEqual
(
test_model
[
'
days_early_for_beta'
],
2
,
"days_early_for_beta
not expected value"
)
def
test_delete_key
(
self
):
def
test_delete_key
(
self
):
...
@@ -322,5 +322,5 @@ class CourseMetadataEditingTest(CourseTestCase):
...
@@ -322,5 +322,5 @@ class CourseMetadataEditingTest(CourseTestCase):
self
.
assertEqual
(
test_model
[
'display_name'
],
'Testing'
,
"not expected value"
)
self
.
assertEqual
(
test_model
[
'display_name'
],
'Testing'
,
"not expected value"
)
self
.
assertIn
(
'rerandomize'
,
test_model
,
'Missing rerandomize metadata field'
)
self
.
assertIn
(
'rerandomize'
,
test_model
,
'Missing rerandomize metadata field'
)
# check for deletion effectiveness
# check for deletion effectiveness
self
.
assert
NotIn
(
'showanswer'
,
test_model
,
'showanswer field still in'
)
self
.
assert
Equal
(
'closed'
,
test_model
[
'showanswer'
]
,
'showanswer field still in'
)
self
.
assert
NotIn
(
'xqa_key'
,
test_model
,
'xqa_key field still in'
)
self
.
assert
Equal
(
None
,
test_model
[
'xqa_key'
]
,
'xqa_key field still in'
)
cms/djangoapps/contentstore/views.py
View file @
b7680f31
...
@@ -464,6 +464,9 @@ class SessionKeyValueStore(KeyValueStore):
...
@@ -464,6 +464,9 @@ class SessionKeyValueStore(KeyValueStore):
except
(
KeyError
,
InvalidScopeError
):
except
(
KeyError
,
InvalidScopeError
):
del
self
.
_session
[
tuple
(
key
)]
del
self
.
_session
[
tuple
(
key
)]
def
has
(
self
,
key
):
return
key
in
self
.
_model_data
or
key
in
self
.
_session
def
preview_module_system
(
request
,
preview_id
,
descriptor
):
def
preview_module_system
(
request
,
preview_id
,
descriptor
):
"""
"""
...
@@ -662,7 +665,7 @@ def save_item(request):
...
@@ -662,7 +665,7 @@ def save_item(request):
# commit to datastore
# commit to datastore
# TODO (cpennington): This really shouldn't have to do this much reaching in to get the metadata
# TODO (cpennington): This really shouldn't have to do this much reaching in to get the metadata
store
.
update_metadata
(
item_location
,
existing_item
.
_model_data
.
_kvs
.
_metadata
)
store
.
update_metadata
(
item_location
,
own_metadat
(
existing_item
)
)
return
HttpResponse
()
return
HttpResponse
()
...
...
cms/djangoapps/models/settings/course_metadata.py
View file @
b7680f31
from
xmodule.modulestore
import
Location
from
xmodule.modulestore
import
Location
from
contentstore.utils
import
get_modulestore
from
contentstore.utils
import
get_modulestore
from
xmodule.x_module
import
XModuleDescriptor
from
xmodule.x_module
import
XModuleDescriptor
from
xmodule.modulestore.inheritance
import
own_metadata
class
CourseMetadata
(
object
):
class
CourseMetadata
(
object
):
...
@@ -10,7 +11,7 @@ class CourseMetadata(object):
...
@@ -10,7 +11,7 @@ class CourseMetadata(object):
'''
'''
# __new_advanced_key__ is used by client not server; so, could argue against it being here
# __new_advanced_key__ is used by client not server; so, could argue against it being here
FILTERED_LIST
=
XModuleDescriptor
.
system_metadata_fields
+
[
'start'
,
'end'
,
'enrollment_start'
,
'enrollment_end'
,
'tabs'
,
'graceperiod'
,
'__new_advanced_key__'
]
FILTERED_LIST
=
XModuleDescriptor
.
system_metadata_fields
+
[
'start'
,
'end'
,
'enrollment_start'
,
'enrollment_end'
,
'tabs'
,
'graceperiod'
,
'__new_advanced_key__'
]
@classmethod
@classmethod
def
fetch
(
cls
,
course_location
):
def
fetch
(
cls
,
course_location
):
"""
"""
...
@@ -18,53 +19,60 @@ class CourseMetadata(object):
...
@@ -18,53 +19,60 @@ class CourseMetadata(object):
"""
"""
if
not
isinstance
(
course_location
,
Location
):
if
not
isinstance
(
course_location
,
Location
):
course_location
=
Location
(
course_location
)
course_location
=
Location
(
course_location
)
course
=
{}
course
=
{}
descriptor
=
get_modulestore
(
course_location
)
.
get_item
(
course_location
)
descriptor
=
get_modulestore
(
course_location
)
.
get_item
(
course_location
)
for
k
,
v
in
descriptor
.
metadata
.
iteritems
()
:
for
field
in
descriptor
.
fields
+
descriptor
.
lms
.
fields
:
if
k
not
in
cls
.
FILTERED_LIST
:
if
field
.
name
not
in
cls
.
FILTERED_LIST
:
course
[
k
]
=
v
course
[
field
.
name
]
=
field
.
read_from
(
descriptor
)
return
course
return
course
@classmethod
@classmethod
def
update_from_json
(
cls
,
course_location
,
jsondict
):
def
update_from_json
(
cls
,
course_location
,
jsondict
):
"""
"""
Decode the json into CourseMetadata and save any changed attrs to the db.
Decode the json into CourseMetadata and save any changed attrs to the db.
Ensures none of the fields are in the blacklist.
Ensures none of the fields are in the blacklist.
"""
"""
descriptor
=
get_modulestore
(
course_location
)
.
get_item
(
course_location
)
descriptor
=
get_modulestore
(
course_location
)
.
get_item
(
course_location
)
dirty
=
False
dirty
=
False
for
k
,
v
in
jsondict
.
iteritems
():
for
k
,
v
in
jsondict
.
iteritems
():
# should it be an error if one of the filtered list items is in the payload?
# should it be an error if one of the filtered list items is in the payload?
if
k
not
in
cls
.
FILTERED_LIST
and
(
k
not
in
descriptor
.
metadata
or
descriptor
.
metadata
[
k
]
!=
v
):
if
k
in
cls
.
FILTERED_LIST
:
continue
if
hasattr
(
descriptor
,
k
)
and
getattr
(
descriptor
,
k
)
!=
v
:
dirty
=
True
setattr
(
descriptor
,
k
,
v
)
elif
hasattr
(
descriptor
.
lms
,
k
)
and
getattr
(
descriptor
.
lms
,
k
)
!=
k
:
dirty
=
True
dirty
=
True
descriptor
.
metadata
[
k
]
=
v
setattr
(
descriptor
.
lms
,
k
,
v
)
if
dirty
:
if
dirty
:
get_modulestore
(
course_location
)
.
update_metadata
(
course_location
,
descriptor
.
metadata
)
get_modulestore
(
course_location
)
.
update_metadata
(
course_location
,
own_metadata
(
descriptor
)
)
# Could just generate and return a course obj w/o doing any db reads, but I put the reads in as a means to confirm
# Could just generate and return a course obj w/o doing any db reads, but I put the reads in as a means to confirm
# it persisted correctly
# it persisted correctly
return
cls
.
fetch
(
course_location
)
return
cls
.
fetch
(
course_location
)
@classmethod
@classmethod
def
delete_key
(
cls
,
course_location
,
payload
):
def
delete_key
(
cls
,
course_location
,
payload
):
'''
'''
Remove the given metadata key(s) from the course. payload can be a single key or [key..]
Remove the given metadata key(s) from the course. payload can be a single key or [key..]
'''
'''
descriptor
=
get_modulestore
(
course_location
)
.
get_item
(
course_location
)
descriptor
=
get_modulestore
(
course_location
)
.
get_item
(
course_location
)
for
key
in
payload
[
'deleteKeys'
]:
for
key
in
payload
[
'deleteKeys'
]:
if
key
in
descriptor
.
metadata
:
if
hasattr
(
descriptor
,
key
):
del
descriptor
.
metadata
[
key
]
delattr
(
descriptor
,
key
)
elif
hasattr
(
descriptor
.
lms
,
key
):
get_modulestore
(
course_location
)
.
update_metadata
(
course_location
,
descriptor
.
metadata
)
delattr
(
descriptor
.
lms
,
key
)
get_modulestore
(
course_location
)
.
update_metadata
(
course_location
,
own_metadata
(
descriptor
))
return
cls
.
fetch
(
course_location
)
return
cls
.
fetch
(
course_location
)
\ No newline at end of file
common/lib/xmodule/xmodule/course_module.py
View file @
b7680f31
...
@@ -50,7 +50,7 @@ class StringOrDate(Date):
...
@@ -50,7 +50,7 @@ class StringOrDate(Date):
try
:
try
:
return
time
.
strftime
(
self
.
time_format
,
value
)
return
time
.
strftime
(
self
.
time_format
,
value
)
except
ValueError
:
except
(
ValueError
,
TypeError
)
:
return
value
return
value
...
@@ -449,8 +449,10 @@ class CourseDescriptor(SequenceDescriptor):
...
@@ -449,8 +449,10 @@ class CourseDescriptor(SequenceDescriptor):
specified. Returns specified list even if is_cohorted and/or auto_cohort are
specified. Returns specified list even if is_cohorted and/or auto_cohort are
false.
false.
"""
"""
return
self
.
metadata
.
get
(
"cohort_config"
,
{})
.
get
(
if
self
.
cohort_config
is
None
:
"auto_cohort_groups"
,
[])
return
[]
else
:
return
self
.
cohort_config
.
get
(
"auto_cohort_groups"
,
[])
@property
@property
...
...
common/lib/xmodule/xmodule/mako_module.py
View file @
b7680f31
...
@@ -45,9 +45,9 @@ class MakoModuleDescriptor(XModuleDescriptor):
...
@@ -45,9 +45,9 @@ class MakoModuleDescriptor(XModuleDescriptor):
@property
@property
def
editable_metadata_fields
(
self
):
def
editable_metadata_fields
(
self
):
fields
=
{}
fields
=
{}
for
field
,
value
in
own_metadata
(
self
):
for
field
,
value
in
own_metadata
(
self
)
.
items
()
:
if
field
.
name
in
self
.
system_metadata_fields
:
if
field
in
self
.
system_metadata_fields
:
continue
continue
fields
[
field
.
name
]
=
value
fields
[
field
]
=
value
return
fields
return
fields
common/lib/xmodule/xmodule/modulestore/inheritance.py
View file @
b7680f31
...
@@ -5,9 +5,6 @@ INHERITABLE_METADATA = (
...
@@ -5,9 +5,6 @@ INHERITABLE_METADATA = (
'graded'
,
'start'
,
'due'
,
'graceperiod'
,
'showanswer'
,
'rerandomize'
,
'graded'
,
'start'
,
'due'
,
'graceperiod'
,
'showanswer'
,
'rerandomize'
,
# TODO (ichuang): used for Fall 2012 xqa server access
# TODO (ichuang): used for Fall 2012 xqa server access
'xqa_key'
,
'xqa_key'
,
# TODO: This is used by the XMLModuleStore to provide for locations for
# static files, and will need to be removed when that code is removed
'data_dir'
# How many days early to show a course element to beta testers (float)
# How many days early to show a course element to beta testers (float)
# intended to be set per-course, but can be overridden in for specific
# intended to be set per-course, but can be overridden in for specific
# elements. Can be a float.
# elements. Can be a float.
...
@@ -33,13 +30,13 @@ def inherit_metadata(descriptor, model_data):
...
@@ -33,13 +30,13 @@ def inherit_metadata(descriptor, model_data):
be inherited
be inherited
"""
"""
if
not
hasattr
(
descriptor
,
'_inherited_metadata'
):
if
not
hasattr
(
descriptor
,
'_inherited_metadata'
):
setattr
(
descriptor
,
'_inherited_metadata'
,
set
()
)
setattr
(
descriptor
,
'_inherited_metadata'
,
{}
)
# Set all inheritable metadata from kwargs that are
# Set all inheritable metadata from kwargs that are
# in self.inheritable_metadata and aren't already set in metadata
# in self.inheritable_metadata and aren't already set in metadata
for
attr
in
INHERITABLE_METADATA
:
for
attr
in
INHERITABLE_METADATA
:
if
attr
not
in
descriptor
.
_model_data
and
attr
in
model_data
:
if
attr
not
in
descriptor
.
_model_data
and
attr
in
model_data
:
descriptor
.
_inherited_metadata
.
add
(
attr
)
descriptor
.
_inherited_metadata
[
attr
]
=
model_data
[
attr
]
descriptor
.
_model_data
[
attr
]
=
model_data
[
attr
]
descriptor
.
_model_data
[
attr
]
=
model_data
[
attr
]
...
@@ -52,15 +49,19 @@ def own_metadata(module):
...
@@ -52,15 +49,19 @@ def own_metadata(module):
metadata
=
{}
metadata
=
{}
for
field
in
module
.
fields
+
module
.
lms
.
fields
:
for
field
in
module
.
fields
+
module
.
lms
.
fields
:
# Only save metadata that wasn't inherited
# Only save metadata that wasn't inherited
if
(
field
.
scope
==
Scope
.
settings
and
if
field
.
scope
!=
Scope
.
settings
:
field
.
name
not
in
inherited_metadata
and
continue
field
.
name
in
module
.
_model_data
):
try
:
if
field
.
name
in
inherited_metadata
and
module
.
_model_data
[
field
.
name
]
==
inherited_metadata
[
field
.
name
]:
metadata
[
field
.
name
]
=
field
.
read_from
(
module
)
continue
except
KeyError
:
# Ignore any missing keys in _model_data
pass
if
field
.
name
not
in
module
.
_model_data
:
continue
try
:
metadata
[
field
.
name
]
=
module
.
_model_data
[
field
.
name
]
except
KeyError
:
# Ignore any missing keys in _model_data
pass
return
metadata
return
metadata
common/lib/xmodule/xmodule/modulestore/mongo.py
View file @
b7680f31
...
@@ -22,7 +22,7 @@ from . import ModuleStoreBase, Location
...
@@ -22,7 +22,7 @@ from . import ModuleStoreBase, Location
from
.draft
import
DraftModuleStore
from
.draft
import
DraftModuleStore
from
.exceptions
import
(
ItemNotFoundError
,
from
.exceptions
import
(
ItemNotFoundError
,
DuplicateItemError
)
DuplicateItemError
)
from
.inheritance
import
own_metadata
,
INHERITABLE_METADATA
from
.inheritance
import
own_metadata
,
INHERITABLE_METADATA
,
inherit_metadata
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
...
@@ -84,6 +84,18 @@ class MongoKeyValueStore(KeyValueStore):
...
@@ -84,6 +84,18 @@ class MongoKeyValueStore(KeyValueStore):
else
:
else
:
raise
InvalidScopeError
(
key
.
scope
)
raise
InvalidScopeError
(
key
.
scope
)
def
has
(
self
,
key
):
if
key
.
scope
in
(
Scope
.
children
,
Scope
.
parent
):
return
True
elif
key
.
scope
==
Scope
.
settings
:
return
key
.
field_name
in
self
.
_metadata
elif
key
.
scope
==
Scope
.
content
:
if
key
.
field_name
==
'data'
and
not
isinstance
(
self
.
_data
,
dict
):
return
True
else
:
return
key
.
field_name
in
self
.
_data
else
:
raise
InvalidScopeError
(
key
.
scope
)
MongoUsage
=
namedtuple
(
'MongoUsage'
,
'id, def_id'
)
MongoUsage
=
namedtuple
(
'MongoUsage'
,
'id, def_id'
)
...
@@ -146,7 +158,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
...
@@ -146,7 +158,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
module
=
class_
(
self
,
location
,
model_data
)
module
=
class_
(
self
,
location
,
model_data
)
if
self
.
metadata_inheritance_tree
is
not
None
:
if
self
.
metadata_inheritance_tree
is
not
None
:
metadata_to_inherit
=
self
.
metadata_inheritance_tree
.
get
(
'parent_metadata'
,
{})
.
get
(
location
.
url
(),
{})
metadata_to_inherit
=
self
.
metadata_inheritance_tree
.
get
(
'parent_metadata'
,
{})
.
get
(
location
.
url
(),
{})
module
.
inherit_metadata
(
metadata_to_inherit
)
inherit_metadata
(
module
,
metadata_to_inherit
)
return
module
return
module
except
:
except
:
log
.
debug
(
"Failed to load descriptor"
,
exc_info
=
True
)
log
.
debug
(
"Failed to load descriptor"
,
exc_info
=
True
)
...
...
common/lib/xmodule/xmodule/modulestore/xml_exporter.py
View file @
b7680f31
import
logging
import
logging
from
xmodule.modulestore
import
Location
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.inheritance
import
own_metadata
from
fs.osfs
import
OSFS
from
fs.osfs
import
OSFS
from
json
import
dumps
from
json
import
dumps
...
@@ -31,14 +32,12 @@ def export_to_xml(modulestore, contentstore, course_location, root_dir, course_d
...
@@ -31,14 +32,12 @@ def export_to_xml(modulestore, contentstore, course_location, root_dir, course_d
# export the grading policy
# export the grading policy
policies_dir
=
export_fs
.
makeopendir
(
'policies'
)
policies_dir
=
export_fs
.
makeopendir
(
'policies'
)
course_run_policy_dir
=
policies_dir
.
makeopendir
(
course
.
location
.
name
)
course_run_policy_dir
=
policies_dir
.
makeopendir
(
course
.
location
.
name
)
if
'grading_policy'
in
course
.
definition
[
'data'
]:
with
course_run_policy_dir
.
open
(
'grading_policy.json'
,
'w'
)
as
grading_policy
:
with
course_run_policy_dir
.
open
(
'grading_policy.json'
,
'w'
)
as
grading_policy
:
grading_policy
.
write
(
dumps
(
course
.
grading_policy
))
grading_policy
.
write
(
dumps
(
course
.
grading_policy
))
# export all of the course metadata in policy.json
# export all of the course metadata in policy.json
with
course_run_policy_dir
.
open
(
'policy.json'
,
'w'
)
as
course_policy
:
with
course_run_policy_dir
.
open
(
'policy.json'
,
'w'
)
as
course_policy
:
policy
=
{}
policy
=
{
'course/'
+
course
.
location
.
name
:
own_metadata
(
course
)}
policy
=
{
'course/'
+
course
.
location
.
name
:
course
.
metadata
}
course_policy
.
write
(
dumps
(
policy
))
course_policy
.
write
(
dumps
(
policy
))
...
...
common/lib/xmodule/xmodule/tests/test_capa_module.py
View file @
b7680f31
...
@@ -98,6 +98,8 @@ class CapaFactory(object):
...
@@ -98,6 +98,8 @@ class CapaFactory(object):
if
correct
:
if
correct
:
# TODO: probably better to actually set the internal state properly, but...
# TODO: probably better to actually set the internal state properly, but...
module
.
get_score
=
lambda
:
{
'score'
:
1
,
'total'
:
1
}
module
.
get_score
=
lambda
:
{
'score'
:
1
,
'total'
:
1
}
else
:
module
.
get_score
=
lambda
:
{
'score'
:
0
,
'total'
:
1
}
return
module
return
module
...
...
lms/djangoapps/courseware/model_data.py
View file @
b7680f31
...
@@ -336,6 +336,25 @@ class LmsKeyValueStore(KeyValueStore):
...
@@ -336,6 +336,25 @@ class LmsKeyValueStore(KeyValueStore):
else
:
else
:
field_object
.
delete
()
field_object
.
delete
()
def
has
(
self
,
key
):
if
key
.
field_name
in
self
.
_descriptor_model_data
:
return
key
.
field_name
in
self
.
_descriptor_model_data
if
key
.
scope
==
Scope
.
parent
:
return
True
if
key
.
scope
not
in
self
.
_allowed_scopes
:
raise
InvalidScopeError
(
key
.
scope
)
field_object
=
self
.
_model_data_cache
.
find
(
key
)
if
field_object
is
None
:
return
False
if
key
.
scope
==
Scope
.
student_state
:
return
key
.
field_name
in
json
.
loads
(
field_object
.
state
)
else
:
return
True
LmsUsage
=
namedtuple
(
'LmsUsage'
,
'id, def_id'
)
LmsUsage
=
namedtuple
(
'LmsUsage'
,
'id, def_id'
)
lms/djangoapps/courseware/tests/test_model_data.py
View file @
b7680f31
This diff is collapsed.
Click to expand it.
local-requirements.txt
View file @
b7680f31
...
@@ -6,4 +6,4 @@
...
@@ -6,4 +6,4 @@
# XBlock:
# XBlock:
# Might change frequently, so put it in local-requirements.txt,
# Might change frequently, so put it in local-requirements.txt,
# but conceptually is an external package, so it is in a separate repo.
# but conceptually is an external package, so it is in a separate repo.
-e git+ssh://git@github.com/MITx/xmodule-debugger@
8f82a3b7f
c#egg=XBlock
-e git+ssh://git@github.com/MITx/xmodule-debugger@
e3c4b
c#egg=XBlock
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