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
344cb133
Commit
344cb133
authored
Dec 21, 2012
by
Calen Pennington
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make import/export tests pass
parent
6a612a6e
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
51 additions
and
29 deletions
+51
-29
common/lib/xmodule/xmodule/capa_module.py
+8
-8
common/lib/xmodule/xmodule/modulestore/inheritance.py
+10
-1
common/lib/xmodule/xmodule/self_assessment_module.py
+6
-6
common/lib/xmodule/xmodule/tests/test_import.py
+2
-0
common/lib/xmodule/xmodule/x_module.py
+6
-12
common/lib/xmodule/xmodule/xml_module.py
+16
-2
lms/xmodule_namespace.py
+3
-0
No files found.
common/lib/xmodule/xmodule/capa_module.py
View file @
344cb133
...
@@ -61,7 +61,7 @@ class CapaModule(XModule):
...
@@ -61,7 +61,7 @@ class CapaModule(XModule):
max_attempts
=
StringyInt
(
help
=
"Maximum number of attempts that a student is allowed"
,
scope
=
Scope
.
settings
)
max_attempts
=
StringyInt
(
help
=
"Maximum number of attempts that a student is allowed"
,
scope
=
Scope
.
settings
)
due
=
String
(
help
=
"Date that this problem is due by"
,
scope
=
Scope
.
settings
)
due
=
String
(
help
=
"Date that this problem is due by"
,
scope
=
Scope
.
settings
)
graceperiod
=
Timedelta
(
help
=
"Amount of time after the due date that submissions will be accepted"
,
scope
=
Scope
.
settings
)
graceperiod
=
Timedelta
(
help
=
"Amount of time after the due date that submissions will be accepted"
,
scope
=
Scope
.
settings
)
show
_
answer
=
String
(
help
=
"When to show the problem answer to the student"
,
scope
=
Scope
.
settings
,
default
=
"closed"
)
showanswer
=
String
(
help
=
"When to show the problem answer to the student"
,
scope
=
Scope
.
settings
,
default
=
"closed"
)
force_save_button
=
Boolean
(
help
=
"Whether to force the save button to appear on the page"
,
scope
=
Scope
.
settings
,
default
=
False
)
force_save_button
=
Boolean
(
help
=
"Whether to force the save button to appear on the page"
,
scope
=
Scope
.
settings
,
default
=
False
)
rerandomize
=
Randomization
(
help
=
"When to rerandomize the problem"
,
default
=
"always"
,
scope
=
Scope
.
settings
)
rerandomize
=
Randomization
(
help
=
"When to rerandomize the problem"
,
default
=
"always"
,
scope
=
Scope
.
settings
)
data
=
String
(
help
=
"XML data for the problem"
,
scope
=
Scope
.
content
)
data
=
String
(
help
=
"XML data for the problem"
,
scope
=
Scope
.
content
)
...
@@ -359,26 +359,26 @@ class CapaModule(XModule):
...
@@ -359,26 +359,26 @@ class CapaModule(XModule):
def
answer_available
(
self
):
def
answer_available
(
self
):
''' Is the user allowed to see an answer?
''' Is the user allowed to see an answer?
'''
'''
if
self
.
show
_
answer
==
''
:
if
self
.
showanswer
==
''
:
return
False
return
False
if
self
.
show
_
answer
==
"never"
:
if
self
.
showanswer
==
"never"
:
return
False
return
False
# Admins can see the answer, unless the problem explicitly prevents it
# Admins can see the answer, unless the problem explicitly prevents it
if
self
.
system
.
user_is_staff
:
if
self
.
system
.
user_is_staff
:
return
True
return
True
if
self
.
show
_
answer
==
'attempted'
:
if
self
.
showanswer
==
'attempted'
:
return
self
.
attempts
>
0
return
self
.
attempts
>
0
if
self
.
show
_
answer
==
'answered'
:
if
self
.
showanswer
==
'answered'
:
return
self
.
done
return
self
.
done
if
self
.
show
_
answer
==
'closed'
:
if
self
.
showanswer
==
'closed'
:
return
self
.
closed
()
return
self
.
closed
()
if
self
.
show
_
answer
==
'always'
:
if
self
.
showanswer
==
'always'
:
return
True
return
True
return
False
return
False
...
@@ -409,7 +409,7 @@ class CapaModule(XModule):
...
@@ -409,7 +409,7 @@ class CapaModule(XModule):
'''
'''
event_info
=
dict
()
event_info
=
dict
()
event_info
[
'problem_id'
]
=
self
.
location
.
url
()
event_info
[
'problem_id'
]
=
self
.
location
.
url
()
self
.
system
.
track_function
(
'show
_
answer'
,
event_info
)
self
.
system
.
track_function
(
'showanswer'
,
event_info
)
if
not
self
.
answer_available
():
if
not
self
.
answer_available
():
raise
NotFoundError
(
'Answer is not available'
)
raise
NotFoundError
(
'Answer is not available'
)
else
:
else
:
...
...
common/lib/xmodule/xmodule/modulestore/inheritance.py
View file @
344cb133
from
xmodule.model
import
Scope
from
xmodule.model
import
Scope
# A list of metadata that this module can inherit from its parent module
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'
)
def
compute_inherited_metadata
(
descriptor
):
def
compute_inherited_metadata
(
descriptor
):
"""Given a descriptor, traverse all of its descendants and do metadata
"""Given a descriptor, traverse all of its descendants and do metadata
...
@@ -24,7 +33,7 @@ def inherit_metadata(descriptor, model_data):
...
@@ -24,7 +33,7 @@ def inherit_metadata(descriptor, model_data):
# 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
descriptor
.
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
.
add
(
attr
)
descriptor
.
_model_data
[
attr
]
=
model_data
[
attr
]
descriptor
.
_model_data
[
attr
]
=
model_data
[
attr
]
...
...
common/lib/xmodule/xmodule/self_assessment_module.py
View file @
344cb133
...
@@ -73,8 +73,8 @@ class SelfAssessmentModule(XModule):
...
@@ -73,8 +73,8 @@ class SelfAssessmentModule(XModule):
max_attempts
=
Int
(
scope
=
Scope
.
settings
,
default
=
MAX_ATTEMPTS
)
max_attempts
=
Int
(
scope
=
Scope
.
settings
,
default
=
MAX_ATTEMPTS
)
rubric
=
String
(
scope
=
Scope
.
content
)
rubric
=
String
(
scope
=
Scope
.
content
)
prompt
=
String
(
scope
=
Scope
.
content
)
prompt
=
String
(
scope
=
Scope
.
content
)
submit
_
message
=
String
(
scope
=
Scope
.
content
)
submitmessage
=
String
(
scope
=
Scope
.
content
)
hint
_
prompt
=
String
(
scope
=
Scope
.
content
)
hintprompt
=
String
(
scope
=
Scope
.
content
)
def
_allow_reset
(
self
):
def
_allow_reset
(
self
):
"""Can the module be reset?"""
"""Can the module be reset?"""
...
@@ -209,7 +209,7 @@ class SelfAssessmentModule(XModule):
...
@@ -209,7 +209,7 @@ class SelfAssessmentModule(XModule):
else
:
else
:
hint
=
''
hint
=
''
context
=
{
'hint_prompt'
:
self
.
hint
_
prompt
,
context
=
{
'hint_prompt'
:
self
.
hintprompt
,
'hint'
:
hint
}
'hint'
:
hint
}
if
self
.
state
==
self
.
REQUEST_HINT
:
if
self
.
state
==
self
.
REQUEST_HINT
:
...
@@ -228,7 +228,7 @@ class SelfAssessmentModule(XModule):
...
@@ -228,7 +228,7 @@ class SelfAssessmentModule(XModule):
if
self
.
state
!=
self
.
DONE
:
if
self
.
state
!=
self
.
DONE
:
return
""
return
""
return
"""<div class="save_message">{0}</div>"""
.
format
(
self
.
submit
_
message
)
return
"""<div class="save_message">{0}</div>"""
.
format
(
self
.
submitmessage
)
def
save_answer
(
self
,
get
):
def
save_answer
(
self
,
get
):
...
@@ -397,8 +397,8 @@ class SelfAssessmentDescriptor(XmlDescriptor, EditingDescriptor):
...
@@ -397,8 +397,8 @@ class SelfAssessmentDescriptor(XmlDescriptor, EditingDescriptor):
max_attempts
=
Int
(
scope
=
Scope
.
settings
,
default
=
MAX_ATTEMPTS
)
max_attempts
=
Int
(
scope
=
Scope
.
settings
,
default
=
MAX_ATTEMPTS
)
rubric
=
String
(
scope
=
Scope
.
content
)
rubric
=
String
(
scope
=
Scope
.
content
)
prompt
=
String
(
scope
=
Scope
.
content
)
prompt
=
String
(
scope
=
Scope
.
content
)
submit
_
message
=
String
(
scope
=
Scope
.
content
)
submitmessage
=
String
(
scope
=
Scope
.
content
)
hint
_
prompt
=
String
(
scope
=
Scope
.
content
)
hintprompt
=
String
(
scope
=
Scope
.
content
)
@classmethod
@classmethod
def
definition_from_xml
(
cls
,
xml_object
,
system
):
def
definition_from_xml
(
cls
,
xml_object
,
system
):
...
...
common/lib/xmodule/xmodule/tests/test_import.py
View file @
344cb133
...
@@ -12,6 +12,7 @@ from xmodule.errortracker import make_error_tracker
...
@@ -12,6 +12,7 @@ from xmodule.errortracker import make_error_tracker
from
xmodule.modulestore
import
Location
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.xml
import
ImportSystem
,
XMLModuleStore
from
xmodule.modulestore.xml
import
ImportSystem
,
XMLModuleStore
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
xmodule.modulestore.inheritance
import
compute_inherited_metadata
from
.test_export
import
DATA_DIR
from
.test_export
import
DATA_DIR
...
@@ -134,6 +135,7 @@ class ImportTestCase(unittest.TestCase):
...
@@ -134,6 +135,7 @@ class ImportTestCase(unittest.TestCase):
</chapter>
</chapter>
</course>'''
.
format
(
due
=
v
,
org
=
ORG
,
course
=
COURSE
,
url_name
=
url_name
)
</course>'''
.
format
(
due
=
v
,
org
=
ORG
,
course
=
COURSE
,
url_name
=
url_name
)
descriptor
=
system
.
process_xml
(
start_xml
)
descriptor
=
system
.
process_xml
(
start_xml
)
compute_inherited_metadata
(
descriptor
)
print
descriptor
,
descriptor
.
_model_data
print
descriptor
,
descriptor
.
_model_data
self
.
assertEqual
(
descriptor
.
lms
.
due
,
v
)
self
.
assertEqual
(
descriptor
.
lms
.
due
,
v
)
...
...
common/lib/xmodule/xmodule/x_module.py
View file @
344cb133
...
@@ -281,21 +281,15 @@ class XModuleDescriptor(Plugin, HTMLSnippet, ResourceTemplates):
...
@@ -281,21 +281,15 @@ class XModuleDescriptor(Plugin, HTMLSnippet, ResourceTemplates):
__metaclass__
=
XModuleMetaclass
__metaclass__
=
XModuleMetaclass
# Attributes for inspection of the descriptor
# Attributes for inspection of the descriptor
stores_state
=
False
# Indicates whether the xmodule state should be
# Indicates whether the xmodule state should be
# stored in a database (independent of shared state)
# stored in a database (independent of shared state)
has_score
=
False
# This indicates whether the xmodule is a problem-type.
stores_state
=
False
# This indicates whether the xmodule is a problem-type.
# It should respond to max_score() and grade(). It can be graded or ungraded
# It should respond to max_score() and grade(). It can be graded or ungraded
# (like a practice problem).
# (like a practice problem).
has_score
=
False
# A list of metadata that this module can inherit from its parent module
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'
)
# cdodge: this is a list of metadata names which are 'system' metadata
# cdodge: this is a list of metadata names which are 'system' metadata
# and should not be edited by an end-user
# and should not be edited by an end-user
...
...
common/lib/xmodule/xmodule/xml_module.py
View file @
344cb133
from
xmodule.x_module
import
(
XModuleDescriptor
,
policy_key
)
from
xmodule.x_module
import
(
XModuleDescriptor
,
policy_key
)
from
xmodule.modulestore
import
Location
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.inheritance
import
own_metadata
from
xmodule.modulestore.inheritance
import
own_metadata
from
xmodule.model
import
Object
,
Scope
from
lxml
import
etree
from
lxml
import
etree
import
json
import
json
import
copy
import
copy
...
@@ -78,6 +79,8 @@ class XmlDescriptor(XModuleDescriptor):
...
@@ -78,6 +79,8 @@ class XmlDescriptor(XModuleDescriptor):
Mixin class for standardized parsing of from xml
Mixin class for standardized parsing of from xml
"""
"""
xml_attributes
=
Object
(
help
=
"Map of unhandled xml attributes, used only for storage between import and export"
,
default
=
{},
scope
=
Scope
.
settings
)
# Extension to append to filename paths
# Extension to append to filename paths
filename_extension
=
'xml'
filename_extension
=
'xml'
...
@@ -102,7 +105,9 @@ class XmlDescriptor(XModuleDescriptor):
...
@@ -102,7 +105,9 @@ class XmlDescriptor(XModuleDescriptor):
'tabs'
,
'grading_policy'
,
'is_draft'
,
'published_by'
,
'published_date'
,
'tabs'
,
'grading_policy'
,
'is_draft'
,
'published_by'
,
'published_date'
,
'discussion_blackouts'
,
'discussion_blackouts'
,
# VS[compat] -- remove the below attrs once everything is in the CMS
# VS[compat] -- remove the below attrs once everything is in the CMS
'course'
,
'org'
,
'url_name'
,
'filename'
)
'course'
,
'org'
,
'url_name'
,
'filename'
,
# Used for storing xml attributes between import and export, for roundtrips
'xml_attributes'
)
metadata_to_export_to_policy
=
(
'discussion_topics'
)
metadata_to_export_to_policy
=
(
'discussion_topics'
)
...
@@ -319,6 +324,11 @@ class XmlDescriptor(XModuleDescriptor):
...
@@ -319,6 +324,11 @@ class XmlDescriptor(XModuleDescriptor):
model_data
.
update
(
definition
)
model_data
.
update
(
definition
)
model_data
[
'children'
]
=
children
model_data
[
'children'
]
=
children
model_data
[
'xml_attributes'
]
=
{}
for
key
,
value
in
metadata
.
items
():
if
key
not
in
set
(
f
.
name
for
f
in
cls
.
fields
+
cls
.
lms
.
fields
):
model_data
[
'xml_attributes'
][
key
]
=
value
return
cls
(
return
cls
(
system
,
system
,
location
,
location
,
...
@@ -343,7 +353,7 @@ class XmlDescriptor(XModuleDescriptor):
...
@@ -343,7 +353,7 @@ class XmlDescriptor(XModuleDescriptor):
def
export_to_xml
(
self
,
resource_fs
):
def
export_to_xml
(
self
,
resource_fs
):
"""
"""
Returns an xml string representi
ng
this module, and all modules
Returns an xml string representi
gn
this module, and all modules
underneath it. May also write required resources out to resource_fs
underneath it. May also write required resources out to resource_fs
Assumes that modules have single parentage (that no module appears twice
Assumes that modules have single parentage (that no module appears twice
...
@@ -379,6 +389,10 @@ class XmlDescriptor(XModuleDescriptor):
...
@@ -379,6 +389,10 @@ class XmlDescriptor(XModuleDescriptor):
#logging.debug('location.category = {0}, attr = {1}'.format(self.location.category, attr))
#logging.debug('location.category = {0}, attr = {1}'.format(self.location.category, attr))
xml_object
.
set
(
attr
,
val
)
xml_object
.
set
(
attr
,
val
)
for
key
,
value
in
self
.
xml_attributes
.
items
():
if
key
not
in
self
.
metadata_to_strip
:
xml_object
.
set
(
key
,
value
)
if
self
.
export_to_file
():
if
self
.
export_to_file
():
# Write the definition to a file
# Write the definition to a file
url_path
=
name_to_pathname
(
self
.
url_name
)
url_path
=
name_to_pathname
(
self
.
url_name
)
...
...
lms/xmodule_namespace.py
View file @
344cb133
...
@@ -40,3 +40,6 @@ class LmsNamespace(Namespace):
...
@@ -40,3 +40,6 @@ class LmsNamespace(Namespace):
xqa_key
=
String
(
help
=
"DO NOT USE"
,
scope
=
Scope
.
settings
)
xqa_key
=
String
(
help
=
"DO NOT USE"
,
scope
=
Scope
.
settings
)
ispublic
=
Boolean
(
help
=
"Whether this course is open to the public, or only to admins"
,
scope
=
Scope
.
settings
)
ispublic
=
Boolean
(
help
=
"Whether this course is open to the public, or only to admins"
,
scope
=
Scope
.
settings
)
graceperiod
=
Timedelta
(
help
=
"Amount of time after the due date that submissions will be accepted"
,
scope
=
Scope
.
settings
)
graceperiod
=
Timedelta
(
help
=
"Amount of time after the due date that submissions will be accepted"
,
scope
=
Scope
.
settings
)
showanswer
=
String
(
help
=
"When to show the problem answer to the student"
,
scope
=
Scope
.
settings
,
default
=
"closed"
)
rerandomize
=
String
(
help
=
"When to rerandomize the problem"
,
default
=
"always"
,
scope
=
Scope
.
settings
)
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