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
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
196 additions
and
226 deletions
+196
-226
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
+73
-146
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
from
django.core.urlresolvers
import
reverse
from
path
import
path
from
tempdir
import
mkdtemp_clean
from
datetime
import
timedelta
import
json
from
fs.osfs
import
OSFS
import
copy
...
...
@@ -27,6 +28,7 @@ from xmodule.contentstore.django import contentstore
from
xmodule.templates
import
update_templates
from
xmodule.modulestore.xml_exporter
import
export_to_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.capa_module
import
CapaDescriptor
...
...
@@ -218,7 +220,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
# compare what's on disk compared to what we have in our course
with
fs
.
open
(
'grading_policy.json'
,
'r'
)
as
grading_policy
:
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
self
.
assertTrue
(
fs
.
exists
(
'policy.json'
))
...
...
@@ -227,7 +229,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
with
fs
.
open
(
'policy.json'
,
'r'
)
as
course_policy
:
on_disk
=
loads
(
course_policy
.
read
())
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
delete_course
(
ms
,
cs
,
location
)
...
...
@@ -444,8 +446,7 @@ class ContentStoreTest(ModuleStoreTestCase):
# let's assert on the metadata_inheritance on an existing vertical
for
vertical
in
verticals
:
self
.
assertIn
(
'xqa_key'
,
vertical
.
metadata
)
self
.
assertEqual
(
course
.
metadata
[
'xqa_key'
],
vertical
.
metadata
[
'xqa_key'
])
self
.
assertEqual
(
course
.
lms
.
xqa_key
,
vertical
.
lms
.
xqa_key
)
self
.
assertGreater
(
len
(
verticals
),
0
)
...
...
@@ -455,31 +456,28 @@ class ContentStoreTest(ModuleStoreTestCase):
# crate a new module and add it as a child to a vertical
ms
.
clone_item
(
source_template_location
,
new_component_location
)
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
ms
.
get_cached_metadata_inheritance_tree
(
new_component_location
,
-
1
)
new_module
=
ms
.
get_item
(
new_component_location
)
# 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
.
metadata
[
'xqa_key'
],
new_module
.
metadata
[
'xqa_key'
])
self
.
assertEqual
(
course
.
lms
.
xqa_key
,
new_module
.
lms
.
xqa_key
)
#
# now let's define an override at the leaf node level
#
new_module
.
metadata
[
'graceperiod'
]
=
'1 day'
ms
.
update_metadata
(
new_module
.
location
,
new_module
.
metadata
)
new_module
.
lms
.
graceperiod
=
timedelta
(
1
)
ms
.
update_metadata
(
new_module
.
location
,
own_metadata
(
new_module
)
)
# flush the cache and refetch
ms
.
get_cached_metadata_inheritance_tree
(
new_component_location
,
-
1
)
new_module
=
ms
.
get_item
(
new_component_location
)
self
.
assertIn
(
'graceperiod'
,
new_module
.
metadata
)
self
.
assertEqual
(
'1 day'
,
new_module
.
metadata
[
'graceperiod'
])
self
.
assertEqual
(
timedelta
(
1
),
new_module
.
lms
.
graceperiod
)
class
TemplateTestCase
(
ModuleStoreTestCase
):
...
...
cms/djangoapps/contentstore/tests/test_course_settings.py
View file @
b7680f31
...
...
@@ -287,31 +287,31 @@ class CourseMetadataEditingTest(CourseTestCase):
def
test_update_from_json
(
self
):
test_model
=
CourseMetadata
.
update_from_json
(
self
.
course_location
,
{
"a
"
:
1
,
"
b_a_c_h
"
:
{
"c"
:
"test"
},
"
test_text"
:
"a text string"
})
{
"a
dvertised_start"
:
"start A"
,
"
testcenter_info
"
:
{
"c"
:
"test"
},
"
days_early_for_beta"
:
2
})
self
.
update_check
(
test_model
)
# try fresh fetch to ensure persistence
test_model
=
CourseMetadata
.
fetch
(
self
.
course_location
)
self
.
update_check
(
test_model
)
# now change some of the existing metadata
test_model
=
CourseMetadata
.
update_from_json
(
self
.
course_location
,
{
"a
"
:
2
,
{
"a
dvertised_start"
:
"start B"
,
"display_name"
:
"jolly roger"
})
self
.
assertIn
(
'display_name'
,
test_model
,
'Missing editable metadata field'
)
self
.
assertEqual
(
test_model
[
'display_name'
],
'jolly roger'
,
"not expected value"
)
self
.
assertIn
(
'a
'
,
test_model
,
'Missing revised a
metadata field'
)
self
.
assertEqual
(
test_model
[
'a
'
],
2
,
"a
not expected value"
)
self
.
assertIn
(
'a
dvertised_start'
,
test_model
,
'Missing revised advertised_start
metadata field'
)
self
.
assertEqual
(
test_model
[
'a
dvertised_start'
],
'start B'
,
"advertised_start
not expected value"
)
def
update_check
(
self
,
test_model
):
self
.
assertIn
(
'display_name'
,
test_model
,
'Missing editable metadata field'
)
self
.
assertEqual
(
test_model
[
'display_name'
],
'Robot Super Course'
,
"not expected value"
)
self
.
assertIn
(
'a
'
,
test_model
,
'Missing new a
metadata field'
)
self
.
assertEqual
(
test_model
[
'a
'
],
1
,
"a
not expected value"
)
self
.
assertIn
(
'
b_a_c_h'
,
test_model
,
'Missing b_a_c_h
metadata field'
)
self
.
assertDictEqual
(
test_model
[
'
b_a_c_h'
],
{
"c"
:
"test"
},
"b_a_c_h
not expected value"
)
self
.
assertIn
(
'
test_text'
,
test_model
,
'Missing test_text
metadata field'
)
self
.
assertEqual
(
test_model
[
'
test_text'
],
"a text string"
,
"test_text
not expected value"
)
self
.
assertIn
(
'a
dvertised_start'
,
test_model
,
'Missing new advertised_start
metadata field'
)
self
.
assertEqual
(
test_model
[
'a
dvertised_start'
],
'start A'
,
"advertised_start
not expected value"
)
self
.
assertIn
(
'
testcenter_info'
,
test_model
,
'Missing testcenter_info
metadata field'
)
self
.
assertDictEqual
(
test_model
[
'
testcenter_info'
],
{
"c"
:
"test"
},
"testcenter_info
not expected value"
)
self
.
assertIn
(
'
days_early_for_beta'
,
test_model
,
'Missing days_early_for_beta
metadata field'
)
self
.
assertEqual
(
test_model
[
'
days_early_for_beta'
],
2
,
"days_early_for_beta
not expected value"
)
def
test_delete_key
(
self
):
...
...
@@ -322,5 +322,5 @@ class CourseMetadataEditingTest(CourseTestCase):
self
.
assertEqual
(
test_model
[
'display_name'
],
'Testing'
,
"not expected value"
)
self
.
assertIn
(
'rerandomize'
,
test_model
,
'Missing rerandomize metadata field'
)
# check for deletion effectiveness
self
.
assert
NotIn
(
'showanswer'
,
test_model
,
'showanswer field still in'
)
self
.
assert
NotIn
(
'xqa_key'
,
test_model
,
'xqa_key field still in'
)
self
.
assert
Equal
(
'closed'
,
test_model
[
'showanswer'
]
,
'showanswer 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):
except
(
KeyError
,
InvalidScopeError
):
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
):
"""
...
...
@@ -662,7 +665,7 @@ def save_item(request):
# commit to datastore
# 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
()
...
...
cms/djangoapps/models/settings/course_metadata.py
View file @
b7680f31
from
xmodule.modulestore
import
Location
from
contentstore.utils
import
get_modulestore
from
xmodule.x_module
import
XModuleDescriptor
from
xmodule.modulestore.inheritance
import
own_metadata
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
FILTERED_LIST
=
XModuleDescriptor
.
system_metadata_fields
+
[
'start'
,
'end'
,
'enrollment_start'
,
'enrollment_end'
,
'tabs'
,
'graceperiod'
,
'__new_advanced_key__'
]
@classmethod
def
fetch
(
cls
,
course_location
):
"""
...
...
@@ -18,53 +19,60 @@ class CourseMetadata(object):
"""
if
not
isinstance
(
course_location
,
Location
):
course_location
=
Location
(
course_location
)
course
=
{}
descriptor
=
get_modulestore
(
course_location
)
.
get_item
(
course_location
)
for
k
,
v
in
descriptor
.
metadata
.
iteritems
()
:
if
k
not
in
cls
.
FILTERED_LIST
:
course
[
k
]
=
v
for
field
in
descriptor
.
fields
+
descriptor
.
lms
.
fields
:
if
field
.
name
not
in
cls
.
FILTERED_LIST
:
course
[
field
.
name
]
=
field
.
read_from
(
descriptor
)
return
course
@classmethod
def
update_from_json
(
cls
,
course_location
,
jsondict
):
"""
Decode the json into CourseMetadata and save any changed attrs to the db.
Ensures none of the fields are in the blacklist.
"""
descriptor
=
get_modulestore
(
course_location
)
.
get_item
(
course_location
)
dirty
=
False
for
k
,
v
in
jsondict
.
iteritems
():
# 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
descriptor
.
metadata
[
k
]
=
v
setattr
(
descriptor
.
lms
,
k
,
v
)
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
# it persisted correctly
return
cls
.
fetch
(
course_location
)
@classmethod
def
delete_key
(
cls
,
course_location
,
payload
):
'''
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
)
for
key
in
payload
[
'deleteKeys'
]:
if
key
in
descriptor
.
metadata
:
del
descriptor
.
metadata
[
key
]
get_modulestore
(
course_location
)
.
update_metadata
(
course_location
,
descriptor
.
metadata
)
if
hasattr
(
descriptor
,
key
):
delattr
(
descriptor
,
key
)
elif
hasattr
(
descriptor
.
lms
,
key
):
delattr
(
descriptor
.
lms
,
key
)
get_modulestore
(
course_location
)
.
update_metadata
(
course_location
,
own_metadata
(
descriptor
))
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):
try
:
return
time
.
strftime
(
self
.
time_format
,
value
)
except
ValueError
:
except
(
ValueError
,
TypeError
)
:
return
value
...
...
@@ -449,8 +449,10 @@ class CourseDescriptor(SequenceDescriptor):
specified. Returns specified list even if is_cohorted and/or auto_cohort are
false.
"""
return
self
.
metadata
.
get
(
"cohort_config"
,
{})
.
get
(
"auto_cohort_groups"
,
[])
if
self
.
cohort_config
is
None
:
return
[]
else
:
return
self
.
cohort_config
.
get
(
"auto_cohort_groups"
,
[])
@property
...
...
common/lib/xmodule/xmodule/mako_module.py
View file @
b7680f31
...
...
@@ -45,9 +45,9 @@ class MakoModuleDescriptor(XModuleDescriptor):
@property
def
editable_metadata_fields
(
self
):
fields
=
{}
for
field
,
value
in
own_metadata
(
self
):
if
field
.
name
in
self
.
system_metadata_fields
:
for
field
,
value
in
own_metadata
(
self
)
.
items
()
:
if
field
in
self
.
system_metadata_fields
:
continue
fields
[
field
.
name
]
=
value
fields
[
field
]
=
value
return
fields
common/lib/xmodule/xmodule/modulestore/inheritance.py
View file @
b7680f31
...
...
@@ -5,9 +5,6 @@ INHERITABLE_METADATA = (
'graded'
,
'start'
,
'due'
,
'graceperiod'
,
'showanswer'
,
'rerandomize'
,
# TODO (ichuang): used for Fall 2012 xqa server access
'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)
# intended to be set per-course, but can be overridden in for specific
# elements. Can be a float.
...
...
@@ -33,13 +30,13 @@ def inherit_metadata(descriptor, model_data):
be inherited
"""
if
not
hasattr
(
descriptor
,
'_inherited_metadata'
):
setattr
(
descriptor
,
'_inherited_metadata'
,
set
()
)
setattr
(
descriptor
,
'_inherited_metadata'
,
{}
)
# Set all inheritable metadata from kwargs that are
# in self.inheritable_metadata and aren't already set in metadata
for
attr
in
INHERITABLE_METADATA
:
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
]
...
...
@@ -52,15 +49,19 @@ def own_metadata(module):
metadata
=
{}
for
field
in
module
.
fields
+
module
.
lms
.
fields
:
# Only save metadata that wasn't inherited
if
(
field
.
scope
==
Scope
.
settings
and
field
.
name
not
in
inherited_metadata
and
field
.
name
in
module
.
_model_data
):
if
field
.
scope
!=
Scope
.
settings
:
continue
try
:
metadata
[
field
.
name
]
=
field
.
read_from
(
module
)
except
KeyError
:
# Ignore any missing keys in _model_data
pass
if
field
.
name
in
inherited_metadata
and
module
.
_model_data
[
field
.
name
]
==
inherited_metadata
[
field
.
name
]:
continue
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
common/lib/xmodule/xmodule/modulestore/mongo.py
View file @
b7680f31
...
...
@@ -22,7 +22,7 @@ from . import ModuleStoreBase, Location
from
.draft
import
DraftModuleStore
from
.exceptions
import
(
ItemNotFoundError
,
DuplicateItemError
)
from
.inheritance
import
own_metadata
,
INHERITABLE_METADATA
from
.inheritance
import
own_metadata
,
INHERITABLE_METADATA
,
inherit_metadata
log
=
logging
.
getLogger
(
__name__
)
...
...
@@ -84,6 +84,18 @@ class MongoKeyValueStore(KeyValueStore):
else
:
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'
)
...
...
@@ -146,7 +158,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
module
=
class_
(
self
,
location
,
model_data
)
if
self
.
metadata_inheritance_tree
is
not
None
:
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
except
:
log
.
debug
(
"Failed to load descriptor"
,
exc_info
=
True
)
...
...
common/lib/xmodule/xmodule/modulestore/xml_exporter.py
View file @
b7680f31
import
logging
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.inheritance
import
own_metadata
from
fs.osfs
import
OSFS
from
json
import
dumps
...
...
@@ -31,14 +32,12 @@ def export_to_xml(modulestore, contentstore, course_location, root_dir, course_d
# export the grading policy
policies_dir
=
export_fs
.
makeopendir
(
'policies'
)
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
:
grading_policy
.
write
(
dumps
(
course
.
grading_policy
))
with
course_run_policy_dir
.
open
(
'grading_policy.json'
,
'w'
)
as
grading_policy
:
grading_policy
.
write
(
dumps
(
course
.
grading_policy
))
# export all of the course metadata in policy.json
with
course_run_policy_dir
.
open
(
'policy.json'
,
'w'
)
as
course_policy
:
policy
=
{}
policy
=
{
'course/'
+
course
.
location
.
name
:
course
.
metadata
}
policy
=
{
'course/'
+
course
.
location
.
name
:
own_metadata
(
course
)}
course_policy
.
write
(
dumps
(
policy
))
...
...
common/lib/xmodule/xmodule/tests/test_capa_module.py
View file @
b7680f31
...
...
@@ -98,6 +98,8 @@ class CapaFactory(object):
if
correct
:
# TODO: probably better to actually set the internal state properly, but...
module
.
get_score
=
lambda
:
{
'score'
:
1
,
'total'
:
1
}
else
:
module
.
get_score
=
lambda
:
{
'score'
:
0
,
'total'
:
1
}
return
module
...
...
lms/djangoapps/courseware/model_data.py
View file @
b7680f31
...
...
@@ -336,6 +336,25 @@ class LmsKeyValueStore(KeyValueStore):
else
:
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'
)
lms/djangoapps/courseware/tests/test_model_data.py
View file @
b7680f31
...
...
@@ -56,24 +56,24 @@ class StudentModuleFactory(factory.Factory):
class
ContentFactory
(
factory
.
Factory
):
FACTORY_FOR
=
XModuleContentField
field_name
=
'
content
_field'
value
=
json
.
dumps
(
'
content
_value'
)
field_name
=
'
existing
_field'
value
=
json
.
dumps
(
'
old
_value'
)
definition_id
=
location
(
'def_id'
)
.
url
()
class
SettingsFactory
(
factory
.
Factory
):
FACTORY_FOR
=
XModuleSettingsField
field_name
=
'
settings
_field'
value
=
json
.
dumps
(
'
settings
_value'
)
field_name
=
'
existing
_field'
value
=
json
.
dumps
(
'
old
_value'
)
usage_id
=
'
%
s-
%
s'
%
(
course_id
,
location
(
'def_id'
)
.
url
())
class
StudentPrefsFactory
(
factory
.
Factory
):
FACTORY_FOR
=
XModuleStudentPrefsField
field_name
=
'
student_pref
_field'
value
=
json
.
dumps
(
'
student_pref
_value'
)
field_name
=
'
existing
_field'
value
=
json
.
dumps
(
'
old
_value'
)
student
=
factory
.
SubFactory
(
UserFactory
)
module_type
=
'problem'
...
...
@@ -81,8 +81,8 @@ class StudentPrefsFactory(factory.Factory):
class
StudentInfoFactory
(
factory
.
Factory
):
FACTORY_FOR
=
XModuleStudentInfoField
field_name
=
'
student_info
_field'
value
=
json
.
dumps
(
'
student_info
_value'
)
field_name
=
'
existing
_field'
value
=
json
.
dumps
(
'
old
_value'
)
student
=
factory
.
SubFactory
(
UserFactory
)
...
...
@@ -125,6 +125,7 @@ class TestInvalidScopes(TestCase):
self
.
assertRaises
(
InvalidScopeError
,
self
.
kvs
.
get
,
LmsKeyValueStore
.
Key
(
scope
,
None
,
None
,
'field'
))
self
.
assertRaises
(
InvalidScopeError
,
self
.
kvs
.
set
,
LmsKeyValueStore
.
Key
(
scope
,
None
,
None
,
'field'
),
'value'
)
self
.
assertRaises
(
InvalidScopeError
,
self
.
kvs
.
delete
,
LmsKeyValueStore
.
Key
(
scope
,
None
,
None
,
'field'
))
self
.
assertRaises
(
InvalidScopeError
,
self
.
kvs
.
has
,
LmsKeyValueStore
.
Key
(
scope
,
None
,
None
,
'field'
))
class
TestStudentModuleStorage
(
TestCase
):
...
...
@@ -168,6 +169,14 @@ class TestStudentModuleStorage(TestCase):
self
.
assertEquals
(
1
,
StudentModule
.
objects
.
all
()
.
count
())
self
.
assertEquals
({
'a_field'
:
'a_value'
},
json
.
loads
(
StudentModule
.
objects
.
all
()[
0
]
.
state
))
def
test_has_existing_field
(
self
):
"Test that `has` returns True for existing fields in StudentModules"
self
.
assertTrue
(
self
.
kvs
.
has
(
student_state_key
(
'a_field'
)))
def
test_has_missing_field
(
self
):
"Test that `has` returns False for missing fields in StudentModule"
self
.
assertFalse
(
self
.
kvs
.
has
(
student_state_key
(
'not_a_field'
)))
class
TestMissingStudentModule
(
TestCase
):
def
setUp
(
self
):
...
...
@@ -200,172 +209,90 @@ class TestMissingStudentModule(TestCase):
"Test that deleting a field from a missing StudentModule raises a KeyError"
self
.
assertRaises
(
KeyError
,
self
.
kvs
.
delete
,
student_state_key
(
'a_field'
))
class
TestSettingsStorage
(
TestCase
):
def
setUp
(
self
):
settings
=
SettingsFactory
.
create
()
self
.
user
=
UserFactory
.
create
()
self
.
desc_md
=
{}
self
.
mdc
=
ModelDataCache
([
mock_descriptor
([
mock_field
(
Scope
.
settings
,
'settings_field'
)])],
course_id
,
self
.
user
)
self
.
kvs
=
LmsKeyValueStore
(
self
.
desc_md
,
self
.
mdc
)
def
test_get_existing_field
(
self
):
"Test that getting an existing field in an existing SettingsField works"
self
.
assertEquals
(
'settings_value'
,
self
.
kvs
.
get
(
settings_key
(
'settings_field'
)))
def
test_get_missing_field
(
self
):
"Test that getting a missing field from an existing SettingsField raises a KeyError"
self
.
assertRaises
(
KeyError
,
self
.
kvs
.
get
,
settings_key
(
'not_settings_field'
))
def
test_set_existing_field
(
self
):
"Test that setting an existing field changes the value"
self
.
kvs
.
set
(
settings_key
(
'settings_field'
),
'new_value'
)
self
.
assertEquals
(
1
,
XModuleSettingsField
.
objects
.
all
()
.
count
())
self
.
assertEquals
(
'new_value'
,
json
.
loads
(
XModuleSettingsField
.
objects
.
all
()[
0
]
.
value
))
def
test_set_missing_field
(
self
):
"Test that setting a new field changes the value"
self
.
kvs
.
set
(
settings_key
(
'not_settings_field'
),
'new_value'
)
self
.
assertEquals
(
2
,
XModuleSettingsField
.
objects
.
all
()
.
count
())
self
.
assertEquals
(
'settings_value'
,
json
.
loads
(
XModuleSettingsField
.
objects
.
get
(
field_name
=
'settings_field'
)
.
value
))
self
.
assertEquals
(
'new_value'
,
json
.
loads
(
XModuleSettingsField
.
objects
.
get
(
field_name
=
'not_settings_field'
)
.
value
))
def
test_delete_existing_field
(
self
):
"Test that deleting an existing field removes it"
self
.
kvs
.
delete
(
settings_key
(
'settings_field'
))
self
.
assertEquals
(
0
,
XModuleSettingsField
.
objects
.
all
()
.
count
())
def
test_delete_missing_field
(
self
):
"Test that deleting a missing field from an existing SettingsField raises a KeyError"
self
.
assertRaises
(
KeyError
,
self
.
kvs
.
delete
,
settings_key
(
'not_settings_field'
))
self
.
assertEquals
(
1
,
XModuleSettingsField
.
objects
.
all
()
.
count
())
def
test_has_field_for_missing_student_module
(
self
):
"Test that `has` returns False for missing StudentModules"
self
.
assertFalse
(
self
.
kvs
.
has
(
student_state_key
(
'a_field'
)))
class
TestContentStorage
(
TestCase
):
class
StorageTestBase
(
object
):
factory
=
None
scope
=
None
key_factory
=
None
storage_class
=
None
def
setUp
(
self
):
content
=
ContentFactory
.
create
()
self
.
user
=
UserFactory
.
create
()
field_storage
=
self
.
factory
.
create
()
if
hasattr
(
field_storage
,
'student'
):
self
.
user
=
field_storage
.
student
else
:
self
.
user
=
UserFactory
.
create
()
self
.
desc_md
=
{}
self
.
mdc
=
ModelDataCache
([
mock_descriptor
([
mock_field
(
Scope
.
content
,
'content
_field'
)])],
course_id
,
self
.
user
)
self
.
mdc
=
ModelDataCache
([
mock_descriptor
([
mock_field
(
self
.
scope
,
'existing
_field'
)])],
course_id
,
self
.
user
)
self
.
kvs
=
LmsKeyValueStore
(
self
.
desc_md
,
self
.
mdc
)
def
test_get_existing_field
(
self
):
"Test that getting an existing field in an existing
Content
Field works"
self
.
assertEquals
(
'
content_value'
,
self
.
kvs
.
get
(
content_key
(
'content
_field'
)))
"Test that getting an existing field in an existing
Storage
Field works"
self
.
assertEquals
(
'
old_value'
,
self
.
kvs
.
get
(
self
.
key_factory
(
'existing
_field'
)))
def
test_get_missing_field
(
self
):
"Test that getting a missing field from an existing
Content
Field raises a KeyError"
self
.
assertRaises
(
KeyError
,
self
.
kvs
.
get
,
content_key
(
'not_content
_field'
))
"Test that getting a missing field from an existing
Storage
Field raises a KeyError"
self
.
assertRaises
(
KeyError
,
self
.
kvs
.
get
,
self
.
key_factory
(
'missing
_field'
))
def
test_set_existing_field
(
self
):
"Test that setting an existing field changes the value"
self
.
kvs
.
set
(
content_key
(
'content
_field'
),
'new_value'
)
self
.
assertEquals
(
1
,
XModuleContentField
.
objects
.
all
()
.
count
())
self
.
assertEquals
(
'new_value'
,
json
.
loads
(
XModuleContentField
.
objects
.
all
()[
0
]
.
value
))
self
.
kvs
.
set
(
self
.
key_factory
(
'existing
_field'
),
'new_value'
)
self
.
assertEquals
(
1
,
self
.
storage_class
.
objects
.
all
()
.
count
())
self
.
assertEquals
(
'new_value'
,
json
.
loads
(
self
.
storage_class
.
objects
.
all
()[
0
]
.
value
))
def
test_set_missing_field
(
self
):
"Test that setting a new field changes the value"
self
.
kvs
.
set
(
content_key
(
'not_content
_field'
),
'new_value'
)
self
.
assertEquals
(
2
,
XModuleContentField
.
objects
.
all
()
.
count
())
self
.
assertEquals
(
'
content_value'
,
json
.
loads
(
XModuleContentField
.
objects
.
get
(
field_name
=
'content
_field'
)
.
value
))
self
.
assertEquals
(
'new_value'
,
json
.
loads
(
XModuleContentField
.
objects
.
get
(
field_name
=
'not_content
_field'
)
.
value
))
self
.
kvs
.
set
(
self
.
key_factory
(
'missing
_field'
),
'new_value'
)
self
.
assertEquals
(
2
,
self
.
storage_class
.
objects
.
all
()
.
count
())
self
.
assertEquals
(
'
old_value'
,
json
.
loads
(
self
.
storage_class
.
objects
.
get
(
field_name
=
'existing
_field'
)
.
value
))
self
.
assertEquals
(
'new_value'
,
json
.
loads
(
self
.
storage_class
.
objects
.
get
(
field_name
=
'missing
_field'
)
.
value
))
def
test_delete_existing_field
(
self
):
"Test that deleting an existing field removes it"
self
.
kvs
.
delete
(
content_key
(
'content
_field'
))
self
.
assertEquals
(
0
,
XModuleContentField
.
objects
.
all
()
.
count
())
self
.
kvs
.
delete
(
self
.
key_factory
(
'existing
_field'
))
self
.
assertEquals
(
0
,
self
.
storage_class
.
objects
.
all
()
.
count
())
def
test_delete_missing_field
(
self
):
"Test that deleting a missing field from an existing ContentField raises a KeyError"
self
.
assertRaises
(
KeyError
,
self
.
kvs
.
delete
,
content_key
(
'not_content_field'
))
self
.
assertEquals
(
1
,
XModuleContentField
.
objects
.
all
()
.
count
())
class
TestStudentPrefsStorage
(
TestCase
):
def
setUp
(
self
):
student_pref
=
StudentPrefsFactory
.
create
()
self
.
user
=
student_pref
.
student
self
.
desc_md
=
{}
self
.
mdc
=
ModelDataCache
([
mock_descriptor
([
mock_field
(
Scope
.
student_preferences
,
'student_pref_field'
),
mock_field
(
Scope
.
student_preferences
,
'not_student_pref_field'
),
])],
course_id
,
self
.
user
)
self
.
kvs
=
LmsKeyValueStore
(
self
.
desc_md
,
self
.
mdc
)
def
test_get_existing_field
(
self
):
"Test that getting an existing field in an existing StudentPrefsField works"
self
.
assertEquals
(
'student_pref_value'
,
self
.
kvs
.
get
(
student_prefs_key
(
'student_pref_field'
)))
def
test_get_missing_field
(
self
):
"Test that getting a missing field from an existing StudentPrefsField raises a KeyError"
self
.
assertRaises
(
KeyError
,
self
.
kvs
.
get
,
student_prefs_key
(
'not_student_pref_field'
))
def
test_set_existing_field
(
self
):
"Test that setting an existing field changes the value"
self
.
kvs
.
set
(
student_prefs_key
(
'student_pref_field'
),
'new_value'
)
self
.
assertEquals
(
1
,
XModuleStudentPrefsField
.
objects
.
all
()
.
count
())
self
.
assertEquals
(
'new_value'
,
json
.
loads
(
XModuleStudentPrefsField
.
objects
.
all
()[
0
]
.
value
))
def
test_set_missing_field
(
self
):
"Test that setting a new field changes the value"
self
.
kvs
.
set
(
student_prefs_key
(
'not_student_pref_field'
),
'new_value'
)
self
.
assertEquals
(
2
,
XModuleStudentPrefsField
.
objects
.
all
()
.
count
())
self
.
assertEquals
(
'student_pref_value'
,
json
.
loads
(
XModuleStudentPrefsField
.
objects
.
get
(
field_name
=
'student_pref_field'
)
.
value
))
self
.
assertEquals
(
'new_value'
,
json
.
loads
(
XModuleStudentPrefsField
.
objects
.
get
(
field_name
=
'not_student_pref_field'
)
.
value
))
def
test_delete_existing_field
(
self
):
"Test that deleting an existing field removes it"
self
.
kvs
.
delete
(
student_prefs_key
(
'student_pref_field'
))
self
.
assertEquals
(
0
,
XModuleStudentPrefsField
.
objects
.
all
()
.
count
())
"Test that deleting a missing field from an existing Storage Field raises a KeyError"
self
.
assertRaises
(
KeyError
,
self
.
kvs
.
delete
,
self
.
key_factory
(
'missing_field'
))
self
.
assertEquals
(
1
,
self
.
storage_class
.
objects
.
all
()
.
count
())
def
test_delete_missing_field
(
self
):
"Test that deleting a missing field from an existing StudentPrefsField raises a KeyError"
self
.
assertRaises
(
KeyError
,
self
.
kvs
.
delete
,
student_prefs_key
(
'not_student_pref_field'
))
self
.
assertEquals
(
1
,
XModuleStudentPrefsField
.
objects
.
all
()
.
count
())
def
test_has_existing_field
(
self
):
"Test that `has` returns True for an existing Storage Field"
self
.
assertTrue
(
self
.
kvs
.
has
(
self
.
key_factory
(
'existing_field'
)))
def
test_has_missing_field
(
self
):
"Test that `has` return False for an existing Storage Field"
self
.
assertFalse
(
self
.
kvs
.
has
(
self
.
key_factory
(
'missing_field'
)))
class
TestStudentInfoStorage
(
TestCase
):
def
setUp
(
self
):
student_info
=
StudentInfoFactory
.
create
()
self
.
user
=
student_info
.
student
self
.
desc_md
=
{}
self
.
mdc
=
ModelDataCache
([
mock_descriptor
([
mock_field
(
Scope
.
student_info
,
'student_info_field'
),
mock_field
(
Scope
.
student_info
,
'not_student_info_field'
),
])],
course_id
,
self
.
user
)
self
.
kvs
=
LmsKeyValueStore
(
self
.
desc_md
,
self
.
mdc
)
class
TestSettingsStorage
(
StorageTestBase
,
TestCase
):
factory
=
SettingsFactory
scope
=
Scope
.
settings
key_factory
=
settings_key
storage_class
=
XModuleSettingsField
def
test_get_existing_field
(
self
):
"Test that getting an existing field in an existing StudentInfoField works"
self
.
assertEquals
(
'student_info_value'
,
self
.
kvs
.
get
(
student_info_key
(
'student_info_field'
)))
def
test_get_missing_field
(
self
):
"Test that getting a missing field from an existing StudentInfoField raises a KeyError"
self
.
assertRaises
(
KeyError
,
self
.
kvs
.
get
,
student_info_key
(
'not_student_info_field'
))
class
TestContentStorage
(
StorageTestBase
,
TestCase
):
factory
=
ContentFactory
scope
=
Scope
.
content
key_factory
=
content_key
storage_class
=
XModuleContentField
def
test_set_existing_field
(
self
):
"Test that setting an existing field changes the value"
self
.
kvs
.
set
(
student_info_key
(
'student_info_field'
),
'new_value'
)
self
.
assertEquals
(
1
,
XModuleStudentInfoField
.
objects
.
all
()
.
count
())
self
.
assertEquals
(
'new_value'
,
json
.
loads
(
XModuleStudentInfoField
.
objects
.
all
()[
0
]
.
value
))
def
test_set_missing_field
(
self
):
"Test that setting a new field changes the value"
self
.
kvs
.
set
(
student_info_key
(
'not_student_info_field'
),
'new_value'
)
self
.
assertEquals
(
2
,
XModuleStudentInfoField
.
objects
.
all
()
.
count
())
self
.
assertEquals
(
'student_info_value'
,
json
.
loads
(
XModuleStudentInfoField
.
objects
.
get
(
field_name
=
'student_info_field'
)
.
value
))
self
.
assertEquals
(
'new_value'
,
json
.
loads
(
XModuleStudentInfoField
.
objects
.
get
(
field_name
=
'not_student_info_field'
)
.
value
))
class
TestStudentPrefsStorage
(
StorageTestBase
,
TestCase
):
factory
=
StudentPrefsFactory
scope
=
Scope
.
student_preferences
key_factory
=
student_prefs_key
storage_class
=
XModuleStudentPrefsField
def
test_delete_existing_field
(
self
):
"Test that deleting an existing field removes it"
self
.
kvs
.
delete
(
student_info_key
(
'student_info_field'
))
self
.
assertEquals
(
0
,
XModuleStudentInfoField
.
objects
.
all
()
.
count
())
def
test_delete_missing_field
(
self
):
"Test that deleting a missing field from an existing StudentInfoField raises a KeyError"
self
.
assertRaises
(
KeyError
,
self
.
kvs
.
delete
,
student_info_key
(
'not_student_info_field'
))
self
.
assertEquals
(
1
,
XModuleStudentInfoField
.
objects
.
all
()
.
count
())
class
TestStudentInfoStorage
(
StorageTestBase
,
TestCase
):
factory
=
StudentInfoFactory
scope
=
Scope
.
student_info
key_factory
=
student_info_key
storage_class
=
XModuleStudentInfoField
local-requirements.txt
View file @
b7680f31
...
...
@@ -6,4 +6,4 @@
# XBlock:
# Might change frequently, so put it in local-requirements.txt,
# 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