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
01411ae6
Commit
01411ae6
authored
Dec 13, 2012
by
Calen Pennington
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
WIP: Trying to get tests working
parent
7e224f58
Hide whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
220 additions
and
198 deletions
+220
-198
common/djangoapps/mitxmako/shortcuts.py
+1
-1
common/djangoapps/xmodule_modifiers.py
+1
-0
common/lib/capa/capa/capa_problem.py
+1
-1
common/lib/capa/capa/customrender.py
+1
-1
common/lib/capa/capa/inputtypes.py
+1
-1
common/lib/capa/capa/responsetypes.py
+1
-1
common/lib/capa/capa/xqueue_interface.py
+1
-1
common/lib/xmodule/xmodule/capa_module.py
+1
-2
common/lib/xmodule/xmodule/course_module.py
+2
-2
common/lib/xmodule/xmodule/error_module.py
+15
-16
common/lib/xmodule/xmodule/fields.py
+30
-0
common/lib/xmodule/xmodule/model.py
+9
-9
common/lib/xmodule/xmodule/modulestore/xml.py
+1
-2
common/lib/xmodule/xmodule/modulestore/xml_importer.py
+28
-24
common/lib/xmodule/xmodule/runtime.py
+23
-9
common/lib/xmodule/xmodule/self_assessment_module.py
+29
-59
common/lib/xmodule/xmodule/tests/__init__.py
+2
-1
common/lib/xmodule/xmodule/tests/test_import.py
+20
-22
common/lib/xmodule/xmodule/tests/test_model.py
+8
-0
common/lib/xmodule/xmodule/tests/test_runtime.py
+0
-0
common/lib/xmodule/xmodule/x_module.py
+2
-27
common/lib/xmodule/xmodule/xml_module.py
+2
-0
lms/djangoapps/courseware/grades.py
+7
-9
lms/djangoapps/courseware/module_render.py
+1
-0
lms/djangoapps/instructor/views.py
+1
-1
lms/lib/comment_client/utils.py
+1
-1
lms/templates/staff_problem_info.html
+16
-3
lms/xmodule_namespace.py
+12
-2
local-requirements.txt
+1
-1
setup.py
+2
-2
No files found.
common/djangoapps/mitxmako/shortcuts.py
View file @
01411ae6
...
@@ -14,7 +14,7 @@
...
@@ -14,7 +14,7 @@
import
logging
import
logging
log
=
logging
.
getLogger
(
"mitx."
+
__name__
)
log
=
logging
.
getLogger
(
__name__
)
from
django.template
import
Context
from
django.template
import
Context
from
django.http
import
HttpResponse
from
django.http
import
HttpResponse
...
...
common/djangoapps/xmodule_modifiers.py
View file @
01411ae6
...
@@ -131,6 +131,7 @@ def add_histogram(get_html, module, user):
...
@@ -131,6 +131,7 @@ def add_histogram(get_html, module, user):
is_released
=
"<font color='red'>Yes!</font>"
if
(
now
>
mstart
)
else
"<font color='green'>Not yet</font>"
is_released
=
"<font color='red'>Yes!</font>"
if
(
now
>
mstart
)
else
"<font color='green'>Not yet</font>"
staff_context
=
{
'fields'
:
[(
field
.
name
,
getattr
(
module
,
field
.
name
))
for
field
in
module
.
fields
],
staff_context
=
{
'fields'
:
[(
field
.
name
,
getattr
(
module
,
field
.
name
))
for
field
in
module
.
fields
],
'lms_fields'
:
[(
field
.
name
,
getattr
(
module
.
lms
,
field
.
name
))
for
field
in
module
.
lms
.
fields
],
'location'
:
module
.
location
,
'location'
:
module
.
location
,
'xqa_key'
:
module
.
lms
.
xqa_key
,
'xqa_key'
:
module
.
lms
.
xqa_key
,
'source_file'
:
source_file
,
'source_file'
:
source_file
,
...
...
common/lib/capa/capa/capa_problem.py
View file @
01411ae6
...
@@ -72,7 +72,7 @@ global_context = {'random': random,
...
@@ -72,7 +72,7 @@ global_context = {'random': random,
# These should be removed from HTML output, including all subelements
# These should be removed from HTML output, including all subelements
html_problem_semantics
=
[
"codeparam"
,
"responseparam"
,
"answer"
,
"script"
,
"hintgroup"
]
html_problem_semantics
=
[
"codeparam"
,
"responseparam"
,
"answer"
,
"script"
,
"hintgroup"
]
log
=
logging
.
getLogger
(
'mitx.'
+
__name__
)
log
=
logging
.
getLogger
(
__name__
)
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# main class for this module
# main class for this module
...
...
common/lib/capa/capa/customrender.py
View file @
01411ae6
...
@@ -17,7 +17,7 @@ from lxml import etree
...
@@ -17,7 +17,7 @@ from lxml import etree
import
xml.sax.saxutils
as
saxutils
import
xml.sax.saxutils
as
saxutils
from
registry
import
TagRegistry
from
registry
import
TagRegistry
log
=
logging
.
getLogger
(
'mitx.'
+
__name__
)
log
=
logging
.
getLogger
(
__name__
)
registry
=
TagRegistry
()
registry
=
TagRegistry
()
...
...
common/lib/capa/capa/inputtypes.py
View file @
01411ae6
...
@@ -44,7 +44,7 @@ import sys
...
@@ -44,7 +44,7 @@ import sys
from
registry
import
TagRegistry
from
registry
import
TagRegistry
log
=
logging
.
getLogger
(
'mitx.'
+
__name__
)
log
=
logging
.
getLogger
(
__name__
)
#########################################################################
#########################################################################
...
...
common/lib/capa/capa/responsetypes.py
View file @
01411ae6
...
@@ -33,7 +33,7 @@ from lxml import etree
...
@@ -33,7 +33,7 @@ from lxml import etree
from
lxml.html.soupparser
import
fromstring
as
fromstring_bs
# uses Beautiful Soup!!! FIXME?
from
lxml.html.soupparser
import
fromstring
as
fromstring_bs
# uses Beautiful Soup!!! FIXME?
import
xqueue_interface
import
xqueue_interface
log
=
logging
.
getLogger
(
'mitx.'
+
__name__
)
log
=
logging
.
getLogger
(
__name__
)
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
...
...
common/lib/capa/capa/xqueue_interface.py
View file @
01411ae6
...
@@ -7,7 +7,7 @@ import logging
...
@@ -7,7 +7,7 @@ import logging
import
requests
import
requests
log
=
logging
.
getLogger
(
'mitx.'
+
__name__
)
log
=
logging
.
getLogger
(
__name__
)
dateformat
=
'
%
Y
%
m
%
d
%
H
%
M
%
S'
dateformat
=
'
%
Y
%
m
%
d
%
H
%
M
%
S'
def
make_hashkey
(
seed
):
def
make_hashkey
(
seed
):
...
...
common/lib/xmodule/xmodule/capa_module.py
View file @
01411ae6
...
@@ -551,8 +551,7 @@ class CapaModule(XModule):
...
@@ -551,8 +551,7 @@ class CapaModule(XModule):
msg = "Error checking problem: " + str(err)
msg = "Error checking problem: " + str(err)
msg += '
\n
Traceback:
\n
' + traceback.format_exc()
msg += '
\n
Traceback:
\n
' + traceback.format_exc()
return {'success': msg}
return {'success': msg}
log.exception("Error in capa_module problem checking")
raise
raise Exception("error in capa_module")
self.attempts = self.attempts + 1
self.attempts = self.attempts + 1
self.lcp.done = True
self.lcp.done = True
...
...
common/lib/xmodule/xmodule/course_module.py
View file @
01411ae6
...
@@ -131,9 +131,9 @@ class CourseDescriptor(SequenceDescriptor):
...
@@ -131,9 +131,9 @@ class CourseDescriptor(SequenceDescriptor):
if
self
.
start
is
None
:
if
self
.
start
is
None
:
msg
=
"Course loaded without a valid start date. id =
%
s"
%
self
.
id
msg
=
"Course loaded without a valid start date. id =
%
s"
%
self
.
id
# hack it -- start in 1970
# hack it -- start in 1970
self
.
lms
.
start
=
time
.
gmtime
(
0
)
self
.
start
=
time
.
gmtime
(
0
)
log
.
critical
(
msg
)
log
.
critical
(
msg
)
system
.
error_tracker
(
msg
)
s
elf
.
s
ystem
.
error_tracker
(
msg
)
# NOTE: relies on the modulestore to call set_grading_policy() right after
# NOTE: relies on the modulestore to call set_grading_policy() right after
# init. (Modulestore is in charge of figuring out where to load the policy from)
# init. (Modulestore is in charge of figuring out where to load the policy from)
...
...
common/lib/xmodule/xmodule/error_module.py
View file @
01411ae6
...
@@ -8,6 +8,7 @@ from xmodule.x_module import XModule
...
@@ -8,6 +8,7 @@ from xmodule.x_module import XModule
from
xmodule.editing_module
import
JSONEditingDescriptor
from
xmodule.editing_module
import
JSONEditingDescriptor
from
xmodule.errortracker
import
exc_info_to_str
from
xmodule.errortracker
import
exc_info_to_str
from
xmodule.modulestore
import
Location
from
xmodule.modulestore
import
Location
from
.model
import
String
,
Scope
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
...
@@ -52,6 +53,10 @@ class ErrorDescriptor(JSONEditingDescriptor):
...
@@ -52,6 +53,10 @@ class ErrorDescriptor(JSONEditingDescriptor):
"""
"""
module_class
=
ErrorModule
module_class
=
ErrorModule
contents
=
String
(
scope
=
Scope
.
content
)
error_msg
=
String
(
scope
=
Scope
.
content
)
display_name
=
String
(
scope
=
Scope
.
settings
)
@classmethod
@classmethod
def
_construct
(
self
,
system
,
contents
,
error_msg
,
location
):
def
_construct
(
self
,
system
,
contents
,
error_msg
,
location
):
...
@@ -66,15 +71,12 @@ class ErrorDescriptor(JSONEditingDescriptor):
...
@@ -66,15 +71,12 @@ class ErrorDescriptor(JSONEditingDescriptor):
name
=
hashlib
.
sha1
(
contents
)
.
hexdigest
()
name
=
hashlib
.
sha1
(
contents
)
.
hexdigest
()
)
)
definition
=
{
'data'
:
{
'error_msg'
:
str
(
error_msg
),
'contents'
:
contents
,
}
}
# real metadata stays in the content, but add a display name
# real metadata stays in the content, but add a display name
model_data
=
{
'display_name'
:
'Error: '
+
location
.
name
}
model_data
=
{
'error_msg'
:
str
(
error_msg
),
'contents'
:
contents
,
'display_name'
:
'Error: '
+
location
.
name
}
return
ErrorDescriptor
(
return
ErrorDescriptor
(
system
,
system
,
location
,
location
,
...
@@ -84,7 +86,7 @@ class ErrorDescriptor(JSONEditingDescriptor):
...
@@ -84,7 +86,7 @@ class ErrorDescriptor(JSONEditingDescriptor):
def
get_context
(
self
):
def
get_context
(
self
):
return
{
return
{
'module'
:
self
,
'module'
:
self
,
'data'
:
self
.
definition
[
'data'
][
'contents'
]
,
'data'
:
self
.
contents
,
}
}
@classmethod
@classmethod
...
@@ -100,10 +102,7 @@ class ErrorDescriptor(JSONEditingDescriptor):
...
@@ -100,10 +102,7 @@ class ErrorDescriptor(JSONEditingDescriptor):
def
from_descriptor
(
cls
,
descriptor
,
error_msg
=
'Error not available'
):
def
from_descriptor
(
cls
,
descriptor
,
error_msg
=
'Error not available'
):
return
cls
.
_construct
(
return
cls
.
_construct
(
descriptor
.
system
,
descriptor
.
system
,
json
.
dumps
({
json
.
dumps
(
descriptor
.
_model_data
,
indent
=
4
),
'definition'
:
descriptor
.
definition
,
'metadata'
:
descriptor
.
metadata
,
},
indent
=
4
),
error_msg
,
error_msg
,
location
=
descriptor
.
location
,
location
=
descriptor
.
location
,
)
)
...
@@ -147,14 +146,14 @@ class ErrorDescriptor(JSONEditingDescriptor):
...
@@ -147,14 +146,14 @@ class ErrorDescriptor(JSONEditingDescriptor):
files, etc. That would just get re-wrapped on import.
files, etc. That would just get re-wrapped on import.
'''
'''
try
:
try
:
xml
=
etree
.
fromstring
(
self
.
definition
[
'data'
][
'contents'
]
)
xml
=
etree
.
fromstring
(
self
.
contents
)
return
etree
.
tostring
(
xml
)
return
etree
.
tostring
(
xml
)
except
etree
.
XMLSyntaxError
:
except
etree
.
XMLSyntaxError
:
# still not valid.
# still not valid.
root
=
etree
.
Element
(
'error'
)
root
=
etree
.
Element
(
'error'
)
root
.
text
=
self
.
definition
[
'data'
][
'contents'
]
root
.
text
=
self
.
contents
err_node
=
etree
.
SubElement
(
root
,
'error_msg'
)
err_node
=
etree
.
SubElement
(
root
,
'error_msg'
)
err_node
.
text
=
self
.
definition
[
'data'
][
'error_msg'
]
err_node
.
text
=
self
.
error_msg
return
etree
.
tostring
(
root
)
return
etree
.
tostring
(
root
)
...
...
common/lib/xmodule/xmodule/fields.py
0 → 100644
View file @
01411ae6
import
time
import
logging
from
.model
import
ModelType
log
=
logging
.
getLogger
(
__name__
)
class
Date
(
ModelType
):
time_format
=
"
%
Y-
%
m-
%
dT
%
H:
%
M"
def
from_json
(
self
,
value
):
"""
Parse an optional metadata key containing a time: if present, complain
if it doesn't parse.
Return None if not present or invalid.
"""
try
:
return
time
.
strptime
(
value
,
self
.
time_format
)
except
ValueError
as
e
:
msg
=
"Field {0} has bad value '{1}': '{2}'"
.
format
(
self
.
_name
,
value
,
e
)
log
.
warning
(
msg
)
return
None
def
to_json
(
self
,
value
):
"""
Convert a time struct to a string
"""
return
time
.
strftime
(
self
.
time_format
,
value
)
common/lib/xmodule/xmodule/model.py
View file @
01411ae6
...
@@ -43,14 +43,14 @@ class ModelType(object):
...
@@ -43,14 +43,14 @@ class ModelType(object):
if
instance
is
None
:
if
instance
is
None
:
return
self
return
self
if
self
.
name
not
in
instance
.
_model_data
:
try
:
return
self
.
from_json
(
instance
.
_model_data
[
self
.
name
])
except
KeyError
:
if
self
.
default
is
None
and
self
.
computed_default
is
not
None
:
if
self
.
default
is
None
and
self
.
computed_default
is
not
None
:
return
self
.
computed_default
(
instance
)
return
self
.
computed_default
(
instance
)
return
self
.
default
return
self
.
default
return
self
.
from_json
(
instance
.
_model_data
[
self
.
name
])
def
__set__
(
self
,
instance
,
value
):
def
__set__
(
self
,
instance
,
value
):
instance
.
_model_data
[
self
.
name
]
=
self
.
to_json
(
value
)
instance
.
_model_data
[
self
.
name
]
=
self
.
to_json
(
value
)
...
@@ -166,18 +166,18 @@ class Namespace(Plugin):
...
@@ -166,18 +166,18 @@ class Namespace(Plugin):
super
(
Namespace
,
self
)
.
__setattr__
(
name
,
value
)
super
(
Namespace
,
self
)
.
__setattr__
(
name
,
value
)
return
return
container_class_attr
=
getattr
(
type
(
container
),
name
,
None
)
namespace_attr
=
getattr
(
type
(
self
),
name
,
None
)
if
container_class_attr
is
None
or
not
isinstance
(
container_class
_attr
,
ModelType
):
if
namespace_attr
is
None
or
not
isinstance
(
namespace
_attr
,
ModelType
):
return
super
(
Namespace
,
self
)
.
__setattr__
(
name
,
value
)
return
super
(
Namespace
,
self
)
.
__setattr__
(
name
,
value
)
return
container_class_attr
.
__set__
(
container
)
return
namespace_attr
.
__set__
(
container
,
value
)
def
__delattr__
(
self
,
name
):
def
__delattr__
(
self
,
name
):
container
=
super
(
Namespace
,
self
)
.
__getattribute__
(
'_container'
)
container
=
super
(
Namespace
,
self
)
.
__getattribute__
(
'_container'
)
container_class_attr
=
getattr
(
type
(
container
),
name
,
None
)
namespace_attr
=
getattr
(
type
(
self
),
name
,
None
)
if
container_class_attr
is
None
or
not
isinstance
(
container_class
_attr
,
ModelType
):
if
namespace_attr
is
None
or
not
isinstance
(
namespace
_attr
,
ModelType
):
return
super
(
Namespace
,
self
)
.
__detattr__
(
name
)
return
super
(
Namespace
,
self
)
.
__detattr__
(
name
)
return
container_class
_attr
.
__delete__
(
container
)
return
namespace
_attr
.
__delete__
(
container
)
common/lib/xmodule/xmodule/modulestore/xml.py
View file @
01411ae6
...
@@ -28,7 +28,7 @@ edx_xml_parser = etree.XMLParser(dtd_validation=False, load_dtd=False,
...
@@ -28,7 +28,7 @@ edx_xml_parser = etree.XMLParser(dtd_validation=False, load_dtd=False,
etree
.
set_default_parser
(
edx_xml_parser
)
etree
.
set_default_parser
(
edx_xml_parser
)
log
=
logging
.
getLogger
(
'mitx.'
+
__name__
)
log
=
logging
.
getLogger
(
__name__
)
# VS[compat]
# VS[compat]
...
@@ -160,7 +160,6 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):
...
@@ -160,7 +160,6 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):
etree
.
tostring
(
xml_data
),
self
,
self
.
org
,
etree
.
tostring
(
xml_data
),
self
,
self
.
org
,
self
.
course
,
xmlstore
.
default_class
)
self
.
course
,
xmlstore
.
default_class
)
except
Exception
as
err
:
except
Exception
as
err
:
print
err
,
self
.
load_error_modules
if
not
self
.
load_error_modules
:
if
not
self
.
load_error_modules
:
raise
raise
...
...
common/lib/xmodule/xmodule/modulestore/xml_importer.py
View file @
01411ae6
...
@@ -8,6 +8,7 @@ from .xml import XMLModuleStore
...
@@ -8,6 +8,7 @@ from .xml import XMLModuleStore
from
.exceptions
import
DuplicateItemError
from
.exceptions
import
DuplicateItemError
from
xmodule.modulestore
import
Location
from
xmodule.modulestore
import
Location
from
xmodule.contentstore.content
import
StaticContent
,
XASSET_SRCREF_PREFIX
from
xmodule.contentstore.content
import
StaticContent
,
XASSET_SRCREF_PREFIX
from
xmodule.model
import
Scope
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
...
@@ -123,7 +124,7 @@ def import_from_xml(store, data_dir, course_dirs=None,
...
@@ -123,7 +124,7 @@ def import_from_xml(store, data_dir, course_dirs=None,
# Quick scan to get course Location as well as the course_data_path
# Quick scan to get course Location as well as the course_data_path
for
module
in
module_store
.
modules
[
course_id
]
.
itervalues
():
for
module
in
module_store
.
modules
[
course_id
]
.
itervalues
():
if
module
.
category
==
'course'
:
if
module
.
category
==
'course'
:
course_data_path
=
path
(
data_dir
)
/
module
.
metadata
[
'data_dir'
]
course_data_path
=
path
(
data_dir
)
/
module
.
data_dir
course_location
=
module
.
location
course_location
=
module
.
location
if
static_content_store
is
not
None
:
if
static_content_store
is
not
None
:
...
@@ -159,18 +160,17 @@ def import_from_xml(store, data_dir, course_dirs=None,
...
@@ -159,18 +160,17 @@ def import_from_xml(store, data_dir, course_dirs=None,
module
.
definition
[
'children'
]
=
new_locs
module
.
definition
[
'children'
]
=
new_locs
if
module
.
category
==
'course'
:
if
module
.
category
==
'course'
:
# HACK: for now we don't support progress tabs. There's a special metadata configuration setting for this.
# HACK: for now we don't support progress tabs. There's a special metadata configuration setting for this.
module
.
metadata
[
'hide_progress_tab'
]
=
True
module
.
hide_progress_tab
=
True
# cdodge: more hacks (what else). Seems like we have a problem when importing a course (like 6.002) which
# cdodge: more hacks (what else). Seems like we have a problem when importing a course (like 6.002) which
# does not have any tabs defined in the policy file. The import goes fine and then displays fine in LMS,
# does not have any tabs defined in the policy file. The import goes fine and then displays fine in LMS,
# but if someone tries to add a new tab in the CMS, then the LMS barfs because it expects that -
# but if someone tries to add a new tab in the CMS, then the LMS barfs because it expects that -
# if there is *any* tabs - then there at least needs to be some predefined ones
# if there is *any* tabs - then there at least needs to be some predefined ones
if
module
.
tabs
is
None
or
len
(
module
.
tabs
)
==
0
:
if
module
.
tabs
is
None
or
len
(
module
.
tabs
)
==
0
:
module
.
tabs
=
[{
"type"
:
"courseware"
},
module
.
tabs
=
[{
"type"
:
"courseware"
},
{
"type"
:
"course_info"
,
"name"
:
"Course Info"
},
{
"type"
:
"course_info"
,
"name"
:
"Course Info"
},
{
"type"
:
"discussion"
,
"name"
:
"Discussion"
},
{
"type"
:
"discussion"
,
"name"
:
"Discussion"
},
{
"type"
:
"wiki"
,
"name"
:
"Wiki"
}]
# note, add 'progress' when we can support it on Edge
{
"type"
:
"wiki"
,
"name"
:
"Wiki"
}]
# note, add 'progress' when we can support it on Edge
...
@@ -180,39 +180,43 @@ def import_from_xml(store, data_dir, course_dirs=None,
...
@@ -180,39 +180,43 @@ def import_from_xml(store, data_dir, course_dirs=None,
course_items
.
append
(
module
)
course_items
.
append
(
module
)
if
'data'
in
module
.
definition
:
if
hasattr
(
module
,
'data'
):
module_data
=
module
.
definition
[
'data'
]
# cdodge: now go through any link references to '/static/' and make sure we've imported
# cdodge: now go through any link references to '/static/' and make sure we've imported
# it as a StaticContent asset
# it as a StaticContent asset
try
:
try
:
remap_dict
=
{}
remap_dict
=
{}
# use the rewrite_links as a utility means to enumerate through all links
# use the rewrite_links as a utility means to enumerate through all links
# in the module data. We use that to load that reference into our asset store
# in the module data. We use that to load that reference into our asset store
# IMPORTANT: There appears to be a bug in lxml.rewrite_link which makes us not be able to
# IMPORTANT: There appears to be a bug in lxml.rewrite_link which makes us not be able to
# do the rewrites natively in that code.
# do the rewrites natively in that code.
# For example, what I'm seeing is <img src='foo.jpg' /> -> <img src='bar.jpg'>
# For example, what I'm seeing is <img src='foo.jpg' /> -> <img src='bar.jpg'>
# Note the dropped element closing tag. This causes the LMS to fail when rendering modules - that's
# Note the dropped element closing tag. This causes the LMS to fail when rendering modules - that's
# no good, so we have to do this kludge
# no good, so we have to do this kludge
if
isinstance
(
module
_data
,
str
)
or
isinstance
(
module_
data
,
unicode
):
# some module 'data' fields are non strings which blows up the link traversal code
if
isinstance
(
module
.
data
,
str
)
or
isinstance
(
module
.
data
,
unicode
):
# some module 'data' fields are non strings which blows up the link traversal code
lxml_rewrite_links
(
module
_data
,
lambda
link
:
verify_content_links
(
module
,
course_data_path
,
lxml_rewrite_links
(
module
.
data
,
lambda
link
:
verify_content_links
(
module
,
course_data_path
,
static_content_store
,
link
,
remap_dict
))
static_content_store
,
link
,
remap_dict
))
for
key
in
remap_dict
.
keys
():
for
key
in
remap_dict
.
keys
():
module
_data
=
module_
data
.
replace
(
key
,
remap_dict
[
key
])
module
.
data
=
module
.
data
.
replace
(
key
,
remap_dict
[
key
])
except
Exception
,
e
:
except
Exception
:
logging
.
exception
(
"failed to rewrite links on {0}. Continuing..."
.
format
(
module
.
location
))
logging
.
exception
(
"failed to rewrite links on {0}. Continuing..."
.
format
(
module
.
location
))
store
.
update_item
(
module
.
location
,
module
_
data
)
store
.
update_item
(
module
.
location
,
module
.
data
)
if
'children'
in
module
.
definitio
n
:
if
module
.
has_childre
n
:
store
.
update_children
(
module
.
location
,
module
.
definition
[
'children'
]
)
store
.
update_children
(
module
.
location
,
module
.
children
)
# NOTE: It's important to use own_metadata here to avoid writing
metadata
=
{}
# inherited metadata everywhere.
for
field
in
module
.
fields
+
module
.
lms
.
fields
:
store
.
update_metadata
(
module
.
location
,
dict
(
module
.
own_metadata
))
# Only save metadata that wasn't inherited
if
(
field
.
scope
==
Scope
.
settings
and
field
.
name
in
module
.
_inherited_metadata
and
field
.
name
in
module
.
_model_data
):
metadata
[
field
.
name
]
=
module
.
_model_data
[
field
.
name
]
store
.
update_metadata
(
module
.
location
,
metadata
)
return
module_store
,
course_items
return
module_store
,
course_items
...
...
common/lib/xmodule/xmodule/runtime.py
View file @
01411ae6
...
@@ -33,19 +33,33 @@ class DbModel(MutableMapping):
...
@@ -33,19 +33,33 @@ class DbModel(MutableMapping):
def
__repr__
(
self
):
def
__repr__
(
self
):
return
"<{0.__class__.__name__} {0._module_cls!r}>"
.
format
(
self
)
return
"<{0.__class__.__name__} {0._module_cls!r}>"
.
format
(
self
)
def
__str__
(
self
):
return
str
(
dict
(
self
.
iteritems
()))
def
_getfield
(
self
,
name
):
def
_getfield
(
self
,
name
):
if
(
not
hasattr
(
self
.
_module_cls
,
name
)
or
# First, get the field from the class, if defined
not
isinstance
(
getattr
(
self
.
_module_cls
,
name
),
ModelType
)):
module_field
=
getattr
(
self
.
_module_cls
,
name
,
None
)
if
module_field
is
not
None
and
isinstance
(
module_field
,
ModelType
):
raise
KeyError
(
name
)
return
module_field
# If the class doesn't have the field, and it also
# doesn't have any namespaces, then the the name isn't a field
# so KeyError
if
not
hasattr
(
self
.
_module_cls
,
'namespaces'
):
return
KeyError
(
name
)
# Resolve the field name in the first namespace where it's
# available
for
namespace_name
in
self
.
_module_cls
.
namespaces
:
namespace
=
getattr
(
self
.
_module_cls
,
namespace_name
)
namespace_field
=
getattr
(
type
(
namespace
),
name
,
None
)
if
namespace_field
is
not
None
and
isinstance
(
module_field
,
ModelType
):
return
namespace_field
return
getattr
(
self
.
_module_cls
,
name
)
# Not in the class or in any of the namespaces, so name
# really doesn't name a field
raise
KeyError
(
name
)
def
_key
(
self
,
name
):
def
_key
(
self
,
name
):
field
=
self
.
_getfield
(
name
)
field
=
self
.
_getfield
(
name
)
print
name
,
field
module
=
field
.
scope
.
module
module
=
field
.
scope
.
module
if
module
==
ModuleScope
.
ALL
:
if
module
==
ModuleScope
.
ALL
:
...
@@ -88,5 +102,5 @@ class DbModel(MutableMapping):
...
@@ -88,5 +102,5 @@ class DbModel(MutableMapping):
def
keys
(
self
):
def
keys
(
self
):
fields
=
[
field
.
name
for
field
in
self
.
_module_cls
.
fields
]
fields
=
[
field
.
name
for
field
in
self
.
_module_cls
.
fields
]
for
namespace_name
in
self
.
_module_cls
.
namespaces
:
for
namespace_name
in
self
.
_module_cls
.
namespaces
:
fields
.
extend
(
field
.
name
for
field
in
getattr
(
self
.
_module_cls
,
namespace_name
))
fields
.
extend
(
field
.
name
for
field
in
getattr
(
self
.
_module_cls
,
namespace_name
)
.
fields
)
return
fields
return
fields
common/lib/xmodule/xmodule/self_assessment_module.py
View file @
01411ae6
...
@@ -25,6 +25,7 @@ from .stringify import stringify_children
...
@@ -25,6 +25,7 @@ from .stringify import stringify_children
from
.x_module
import
XModule
from
.x_module
import
XModule
from
.xml_module
import
XmlDescriptor
from
.xml_module
import
XmlDescriptor
from
xmodule.modulestore
import
Location
from
xmodule.modulestore
import
Location
from
.model
import
List
,
String
,
Scope
,
Int
log
=
logging
.
getLogger
(
"mitx.courseware"
)
log
=
logging
.
getLogger
(
"mitx.courseware"
)
...
@@ -61,67 +62,21 @@ class SelfAssessmentModule(XModule):
...
@@ -61,67 +62,21 @@ class SelfAssessmentModule(XModule):
js
=
{
'coffee'
:
[
resource_string
(
__name__
,
'js/src/selfassessment/display.coffee'
)]}
js
=
{
'coffee'
:
[
resource_string
(
__name__
,
'js/src/selfassessment/display.coffee'
)]}
js_module_name
=
"SelfAssessment"
js_module_name
=
"SelfAssessment"
def
__init__
(
self
,
system
,
location
,
definition
,
descriptor
,
student_answers
=
List
(
scope
=
Scope
.
student_state
,
default
=
[])
instance_state
=
None
,
shared_state
=
None
,
**
kwargs
):
scores
=
List
(
scope
=
Scope
.
student_state
,
default
=
[])
XModule
.
__init__
(
self
,
system
,
location
,
definition
,
descriptor
,
hints
=
List
(
scope
=
Scope
.
student_state
,
default
=
[])
instance_state
,
shared_state
,
**
kwargs
)
state
=
String
(
scope
=
Scope
.
student_state
,
default
=
INITIAL
)
"""
# Used for progress / grading. Currently get credit just for
Definition file should have 4 blocks -- prompt, rubric, submitmessage, hintprompt,
# completion (doesn't matter if you self-assessed correct/incorrect).
and two optional attributes:
max_score
=
Int
(
scope
=
Scope
.
settings
,
default
=
MAX_SCORE
)
attempts, which should be an integer that defaults to 1.
If it's > 1, the student will be able to re-submit after they see
the rubric.
max_score, which should be an integer that defaults to 1.
It defines the maximum number of points a student can get. Assumed to be integer scale
from 0 to max_score, with an interval of 1.
Note: all the submissions are stored.
Sample file:
<selfassessment attempts="1" max_score="1">
<prompt>
Insert prompt text here. (arbitrary html)
</prompt>
<rubric>
Insert grading rubric here. (arbitrary html)
</rubric>
<hintprompt>
Please enter a hint below: (arbitrary html)
</hintprompt>
<submitmessage>
Thanks for submitting! (arbitrary html)
</submitmessage>
</selfassessment>
"""
# Load instance state
if
instance_state
is
not
None
:
instance_state
=
json
.
loads
(
instance_state
)
else
:
instance_state
=
{}
# Note: score responses are on scale from 0 to max_score
self
.
student_answers
=
instance_state
.
get
(
'student_answers'
,
[])
self
.
scores
=
instance_state
.
get
(
'scores'
,
[])
self
.
hints
=
instance_state
.
get
(
'hints'
,
[])
self
.
state
=
instance_state
.
get
(
'state'
,
'initial'
)
# Used for progress / grading. Currently get credit just for
# completion (doesn't matter if you self-assessed correct/incorrect).
self
.
_max_score
=
int
(
self
.
metadata
.
get
(
'max_score'
,
MAX_SCORE
))
attempts
=
Int
(
scope
=
Scope
.
student_state
,
default
=
0
),
Int
max_attempts
=
Int
(
scope
=
Scope
.
settings
,
default
=
MAX_ATTEMPTS
)
self
.
attempts
=
instance_state
.
get
(
'attempts'
,
0
)
rubric
=
String
(
scope
=
Scope
.
content
)
prompt
=
String
(
scope
=
Scope
.
content
)
self
.
max_attempts
=
int
(
self
.
metadata
.
get
(
'attempts'
,
MAX_ATTEMPTS
))
submit_message
=
String
(
scope
=
Scope
.
content
)
hint_prompt
=
String
(
scope
=
Scope
.
content
)
self
.
rubric
=
definition
[
'rubric'
]
self
.
prompt
=
definition
[
'prompt'
]
self
.
submit_message
=
definition
[
'submitmessage'
]
self
.
hint_prompt
=
definition
[
'hintprompt'
]
def
_allow_reset
(
self
):
def
_allow_reset
(
self
):
"""Can the module be reset?"""
"""Can the module be reset?"""
...
@@ -432,6 +387,21 @@ class SelfAssessmentDescriptor(XmlDescriptor, EditingDescriptor):
...
@@ -432,6 +387,21 @@ class SelfAssessmentDescriptor(XmlDescriptor, EditingDescriptor):
js
=
{
'coffee'
:
[
resource_string
(
__name__
,
'js/src/html/edit.coffee'
)]}
js
=
{
'coffee'
:
[
resource_string
(
__name__
,
'js/src/html/edit.coffee'
)]}
js_module_name
=
"HTMLEditingDescriptor"
js_module_name
=
"HTMLEditingDescriptor"
# The capa format specifies that what we call max_attempts in the code
# is the attribute `attempts`. This will do that conversion
metadata_translations
=
dict
(
XmlDescriptor
.
metadata_translations
)
metadata_translations
[
'attempts'
]
=
'max_attempts'
# Used for progress / grading. Currently get credit just for
# completion (doesn't matter if you self-assessed correct/incorrect).
max_score
=
Int
(
scope
=
Scope
.
settings
,
default
=
MAX_SCORE
)
max_attempts
=
Int
(
scope
=
Scope
.
settings
,
default
=
MAX_ATTEMPTS
)
rubric
=
String
(
scope
=
Scope
.
content
)
prompt
=
String
(
scope
=
Scope
.
content
)
submit_message
=
String
(
scope
=
Scope
.
content
)
hint_prompt
=
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/__init__.py
View file @
01411ae6
...
@@ -30,7 +30,8 @@ i4xs = ModuleSystem(
...
@@ -30,7 +30,8 @@ i4xs = ModuleSystem(
debug
=
True
,
debug
=
True
,
xqueue
=
{
'interface'
:
None
,
'callback_url'
:
'/'
,
'default_queuename'
:
'testqueue'
,
'waittime'
:
10
},
xqueue
=
{
'interface'
:
None
,
'callback_url'
:
'/'
,
'default_queuename'
:
'testqueue'
,
'waittime'
:
10
},
node_path
=
os
.
environ
.
get
(
"NODE_PATH"
,
"/usr/local/lib/node_modules"
),
node_path
=
os
.
environ
.
get
(
"NODE_PATH"
,
"/usr/local/lib/node_modules"
),
anonymous_student_id
=
'student'
anonymous_student_id
=
'student'
,
xmodule_model_data
=
lambda
x
:
x
,
)
)
...
...
common/lib/xmodule/xmodule/tests/test_import.py
View file @
01411ae6
...
@@ -91,8 +91,10 @@ class ImportTestCase(unittest.TestCase):
...
@@ -91,8 +91,10 @@ class ImportTestCase(unittest.TestCase):
self
.
assertEqual
(
re_import_descriptor
.
__class__
.
__name__
,
self
.
assertEqual
(
re_import_descriptor
.
__class__
.
__name__
,
'ErrorDescriptor'
)
'ErrorDescriptor'
)
self
.
assertEqual
(
descriptor
.
definition
[
'data'
],
self
.
assertEqual
(
descriptor
.
contents
,
re_import_descriptor
.
definition
[
'data'
])
re_import_descriptor
.
contents
)
self
.
assertEqual
(
descriptor
.
error_msg
,
re_import_descriptor
.
error_msg
)
def
test_fixed_xml_tag
(
self
):
def
test_fixed_xml_tag
(
self
):
"""Make sure a tag that's been fixed exports as the original tag type"""
"""Make sure a tag that's been fixed exports as the original tag type"""
...
@@ -126,23 +128,19 @@ class ImportTestCase(unittest.TestCase):
...
@@ -126,23 +128,19 @@ class ImportTestCase(unittest.TestCase):
url_name
=
'test1'
url_name
=
'test1'
start_xml
=
'''
start_xml
=
'''
<course org="{org}" course="{course}"
<course org="{org}" course="{course}"
graceperiod="{grac
e}" url_name="{url_name}" unicorn="purple">
due="{du
e}" url_name="{url_name}" unicorn="purple">
<chapter url="hi" url_name="ch" display_name="CH">
<chapter url="hi" url_name="ch" display_name="CH">
<html url_name="h" display_name="H">Two houses, ...</html>
<html url_name="h" display_name="H">Two houses, ...</html>
</chapter>
</chapter>
</course>'''
.
format
(
grac
e
=
v
,
org
=
ORG
,
course
=
COURSE
,
url_name
=
url_name
)
</course>'''
.
format
(
du
e
=
v
,
org
=
ORG
,
course
=
COURSE
,
url_name
=
url_name
)
descriptor
=
system
.
process_xml
(
start_xml
)
descriptor
=
system
.
process_xml
(
start_xml
)
print
descriptor
,
descriptor
.
metadata
print
descriptor
,
descriptor
.
_model_data
self
.
assertEqual
(
descriptor
.
metadata
[
'graceperiod'
],
v
)
self
.
assertEqual
(
descriptor
.
lms
.
due
,
v
)
self
.
assertEqual
(
descriptor
.
metadata
[
'unicorn'
],
'purple'
)
# Check that the child inherits
graceperiod
correctly
# Check that the child inherits
due
correctly
child
=
descriptor
.
get_children
()[
0
]
child
=
descriptor
.
get_children
()[
0
]
self
.
assertEqual
(
child
.
metadata
[
'graceperiod'
],
v
)
self
.
assertEqual
(
child
.
lms
.
due
,
v
)
# check that the child does _not_ inherit any unicorns
self
.
assertTrue
(
'unicorn'
not
in
child
.
metadata
)
# Now export and check things
# Now export and check things
resource_fs
=
MemoryFS
()
resource_fs
=
MemoryFS
()
...
@@ -169,12 +167,12 @@ class ImportTestCase(unittest.TestCase):
...
@@ -169,12 +167,12 @@ class ImportTestCase(unittest.TestCase):
# did we successfully strip the url_name from the definition contents?
# did we successfully strip the url_name from the definition contents?
self
.
assertTrue
(
'url_name'
not
in
course_xml
.
attrib
)
self
.
assertTrue
(
'url_name'
not
in
course_xml
.
attrib
)
# Does the chapter tag now have a
graceperiod
attribute?
# Does the chapter tag now have a
due
attribute?
# hardcoded path to child
# hardcoded path to child
with
resource_fs
.
open
(
'chapter/ch.xml'
)
as
f
:
with
resource_fs
.
open
(
'chapter/ch.xml'
)
as
f
:
chapter_xml
=
etree
.
fromstring
(
f
.
read
())
chapter_xml
=
etree
.
fromstring
(
f
.
read
())
self
.
assertEqual
(
chapter_xml
.
tag
,
'chapter'
)
self
.
assertEqual
(
chapter_xml
.
tag
,
'chapter'
)
self
.
assertFalse
(
'
graceperiod
'
in
chapter_xml
.
attrib
)
self
.
assertFalse
(
'
due
'
in
chapter_xml
.
attrib
)
def
test_is_pointer_tag
(
self
):
def
test_is_pointer_tag
(
self
):
"""
"""
...
@@ -216,7 +214,7 @@ class ImportTestCase(unittest.TestCase):
...
@@ -216,7 +214,7 @@ class ImportTestCase(unittest.TestCase):
def
check_for_key
(
key
,
node
):
def
check_for_key
(
key
,
node
):
"recursive check for presence of key"
"recursive check for presence of key"
print
"Checking {0}"
.
format
(
node
.
location
.
url
())
print
"Checking {0}"
.
format
(
node
.
location
.
url
())
self
.
assertTrue
(
key
in
node
.
meta
data
)
self
.
assertTrue
(
key
in
node
.
_model_
data
)
for
c
in
node
.
get_children
():
for
c
in
node
.
get_children
():
check_for_key
(
key
,
c
)
check_for_key
(
key
,
c
)
...
@@ -244,15 +242,15 @@ class ImportTestCase(unittest.TestCase):
...
@@ -244,15 +242,15 @@ class ImportTestCase(unittest.TestCase):
toy_ch
=
toy
.
get_children
()[
0
]
toy_ch
=
toy
.
get_children
()[
0
]
two_toys_ch
=
two_toys
.
get_children
()[
0
]
two_toys_ch
=
two_toys
.
get_children
()[
0
]
self
.
assertEqual
(
toy_ch
.
display_name
,
"Overview"
)
self
.
assertEqual
(
toy_ch
.
lms
.
display_name
,
"Overview"
)
self
.
assertEqual
(
two_toys_ch
.
display_name
,
"Two Toy Overview"
)
self
.
assertEqual
(
two_toys_ch
.
lms
.
display_name
,
"Two Toy Overview"
)
# Also check that the grading policy loaded
# Also check that the grading policy loaded
self
.
assertEqual
(
two_toys
.
grade_cutoffs
[
'C'
],
0.5999
)
self
.
assertEqual
(
two_toys
.
grade_cutoffs
[
'C'
],
0.5999
)
# Also check that keys from policy are run through the
# Also check that keys from policy are run through the
# appropriate attribute maps -- 'graded' should be True, not 'true'
# appropriate attribute maps -- 'graded' should be True, not 'true'
self
.
assertEqual
(
toy
.
metadata
[
'graded'
]
,
True
)
self
.
assertEqual
(
toy
.
lms
.
graded
,
True
)
def
test_definition_loading
(
self
):
def
test_definition_loading
(
self
):
...
@@ -271,8 +269,8 @@ class ImportTestCase(unittest.TestCase):
...
@@ -271,8 +269,8 @@ class ImportTestCase(unittest.TestCase):
location
=
Location
([
"i4x"
,
"edX"
,
"toy"
,
"video"
,
"Welcome"
])
location
=
Location
([
"i4x"
,
"edX"
,
"toy"
,
"video"
,
"Welcome"
])
toy_video
=
modulestore
.
get_instance
(
toy_id
,
location
)
toy_video
=
modulestore
.
get_instance
(
toy_id
,
location
)
two_toy_video
=
modulestore
.
get_instance
(
two_toy_id
,
location
)
two_toy_video
=
modulestore
.
get_instance
(
two_toy_id
,
location
)
self
.
assertEqual
(
toy_video
.
metadata
[
'youtube'
]
,
"1.0:p2Q6BrNhdh8"
)
self
.
assertEqual
(
toy_video
.
youtube
,
"1.0:p2Q6BrNhdh8"
)
self
.
assertEqual
(
two_toy_video
.
metadata
[
'youtube'
]
,
"1.0:p2Q6BrNhdh9"
)
self
.
assertEqual
(
two_toy_video
.
youtube
,
"1.0:p2Q6BrNhdh9"
)
def
test_colon_in_url_name
(
self
):
def
test_colon_in_url_name
(
self
):
...
@@ -306,7 +304,7 @@ class ImportTestCase(unittest.TestCase):
...
@@ -306,7 +304,7 @@ class ImportTestCase(unittest.TestCase):
cloc
=
course
.
location
cloc
=
course
.
location
loc
=
Location
(
cloc
.
tag
,
cloc
.
org
,
cloc
.
course
,
'html'
,
'secret:toylab'
)
loc
=
Location
(
cloc
.
tag
,
cloc
.
org
,
cloc
.
course
,
'html'
,
'secret:toylab'
)
html
=
modulestore
.
get_instance
(
course_id
,
loc
)
html
=
modulestore
.
get_instance
(
course_id
,
loc
)
self
.
assertEquals
(
html
.
display_name
,
"Toy lab"
)
self
.
assertEquals
(
html
.
lms
.
display_name
,
"Toy lab"
)
def
test_url_name_mangling
(
self
):
def
test_url_name_mangling
(
self
):
"""
"""
...
@@ -351,4 +349,4 @@ class ImportTestCase(unittest.TestCase):
...
@@ -351,4 +349,4 @@ class ImportTestCase(unittest.TestCase):
location
=
Location
([
"i4x"
,
"edX"
,
"sa_test"
,
"selfassessment"
,
"SampleQuestion"
])
location
=
Location
([
"i4x"
,
"edX"
,
"sa_test"
,
"selfassessment"
,
"SampleQuestion"
])
sa_sample
=
modulestore
.
get_instance
(
sa_id
,
location
)
sa_sample
=
modulestore
.
get_instance
(
sa_id
,
location
)
#10 attempts is hard coded into SampleQuestion, which is the url_name of a selfassessment xml tag
#10 attempts is hard coded into SampleQuestion, which is the url_name of a selfassessment xml tag
self
.
assertEqual
(
sa_sample
.
m
etadata
[
'attempts'
]
,
'10'
)
self
.
assertEqual
(
sa_sample
.
m
ax_attempts
,
'10'
)
common/lib/xmodule/xmodule/tests/test_model.py
0 → 100644
View file @
01411ae6
class
ModelMetaclassTester
(
object
):
__metaclass__
=
ModelMetaclass
field_a
=
Int
(
scope
=
Scope
.
settings
)
field_b
=
Int
(
scope
=
Scope
.
content
)
def
test_model_metaclass
():
common/lib/xmodule/xmodule/tests/test_runtime.py
0 → 100644
View file @
01411ae6
common/lib/xmodule/xmodule/x_module.py
View file @
01411ae6
import
logging
import
logging
import
yaml
import
yaml
import
os
import
os
import
time
from
lxml
import
etree
from
lxml
import
etree
from
pprint
import
pprint
from
pprint
import
pprint
...
@@ -10,38 +9,14 @@ from pkg_resources import resource_listdir, resource_string, resource_isdir
...
@@ -10,38 +9,14 @@ from pkg_resources import resource_listdir, resource_string, resource_isdir
from
xmodule.modulestore
import
Location
from
xmodule.modulestore
import
Location
from
.model
import
ModelMetaclass
,
ParentModelMetaclass
,
NamespacesMetaclass
,
ModelType
from
.model
import
ModelMetaclass
,
ParentModelMetaclass
,
NamespacesMetaclass
from
.plugin
import
Plugin
from
.plugin
import
Plugin
class
Date
(
ModelType
):
time_format
=
"
%
Y-
%
m-
%
dT
%
H:
%
M"
def
from_json
(
self
,
value
):
"""
Parse an optional metadata key containing a time: if present, complain
if it doesn't parse.
Return None if not present or invalid.
"""
try
:
return
time
.
strptime
(
value
,
self
.
time_format
)
except
ValueError
as
e
:
msg
=
"Field {0} has bad value '{1}': '{2}'"
.
format
(
self
.
_name
,
value
,
e
)
log
.
warning
(
msg
)
return
None
def
to_json
(
self
,
value
):
"""
Convert a time struct to a string
"""
return
time
.
strftime
(
self
.
time_format
,
value
)
class
XModuleMetaclass
(
ParentModelMetaclass
,
NamespacesMetaclass
,
ModelMetaclass
):
class
XModuleMetaclass
(
ParentModelMetaclass
,
NamespacesMetaclass
,
ModelMetaclass
):
pass
pass
log
=
logging
.
getLogger
(
'mitx.'
+
__name__
)
log
=
logging
.
getLogger
(
__name__
)
def
dummy_track
(
event_type
,
event
):
def
dummy_track
(
event_type
,
event
):
...
...
common/lib/xmodule/xmodule/xml_module.py
View file @
01411ae6
...
@@ -311,11 +311,13 @@ class XmlDescriptor(XModuleDescriptor):
...
@@ -311,11 +311,13 @@ class XmlDescriptor(XModuleDescriptor):
# Set/override any metadata specified by policy
# Set/override any metadata specified by policy
k
=
policy_key
(
location
)
k
=
policy_key
(
location
)
if
k
in
system
.
policy
:
if
k
in
system
.
policy
:
if
k
==
'video/labintro'
:
print
k
,
metadata
,
system
.
policy
[
k
]
cls
.
apply_policy
(
metadata
,
system
.
policy
[
k
])
cls
.
apply_policy
(
metadata
,
system
.
policy
[
k
])
model_data
=
{}
model_data
=
{}
model_data
.
update
(
metadata
)
model_data
.
update
(
metadata
)
model_data
.
update
(
definition
)
model_data
.
update
(
definition
)
if
k
==
'video/labintro'
:
print
model_data
return
cls
(
return
cls
(
system
,
system
,
...
...
lms/djangoapps/courseware/grades.py
View file @
01411ae6
...
@@ -148,7 +148,7 @@ def grade(student, request, course, student_module_cache=None, keep_raw_scores=F
...
@@ -148,7 +148,7 @@ def grade(student, request, course, student_module_cache=None, keep_raw_scores=F
format_scores
=
[]
format_scores
=
[]
for
section
in
sections
:
for
section
in
sections
:
section_descriptor
=
section
[
'section_descriptor'
]
section_descriptor
=
section
[
'section_descriptor'
]
section_name
=
section_descriptor
.
display_name
section_name
=
section_descriptor
.
lms
.
display_name
should_grade_section
=
False
should_grade_section
=
False
# If we haven't seen a single problem in the section, we don't have to grade it at all! We can assume 0%
# If we haven't seen a single problem in the section, we don't have to grade it at all! We can assume 0%
...
@@ -276,15 +276,13 @@ def progress_summary(student, request, course, student_module_cache):
...
@@ -276,15 +276,13 @@ def progress_summary(student, request, course, student_module_cache):
# Don't include chapters that aren't displayable (e.g. due to error)
# Don't include chapters that aren't displayable (e.g. due to error)
for
chapter_module
in
course_module
.
get_display_items
():
for
chapter_module
in
course_module
.
get_display_items
():
# Skip if the chapter is hidden
# Skip if the chapter is hidden
hidden
=
chapter_module
.
_model_data
.
get
(
'hide_from_toc'
,
'false'
)
if
chapter_module
.
lms
.
hide_from_toc
:
if
hidden
.
lower
()
==
'true'
:
continue
continue
sections
=
[]
sections
=
[]
for
section_module
in
chapter_module
.
get_display_items
():
for
section_module
in
chapter_module
.
get_display_items
():
# Skip if the section is hidden
# Skip if the section is hidden
hidden
=
section_module
.
_model_data
.
get
(
'hide_from_toc'
,
'false'
)
if
section_module
.
lms
.
hide_from_toc
:
if
hidden
.
lower
()
==
'true'
:
continue
continue
# Same for sections
# Same for sections
...
@@ -309,17 +307,17 @@ def progress_summary(student, request, course, student_module_cache):
...
@@ -309,17 +307,17 @@ def progress_summary(student, request, course, student_module_cache):
format
=
section_module
.
lms
.
format
format
=
section_module
.
lms
.
format
sections
.
append
({
sections
.
append
({
'display_name'
:
section_module
.
display_name
,
'display_name'
:
section_module
.
lms
.
display_name
,
'url_name'
:
section_module
.
url_name
,
'url_name'
:
section_module
.
url_name
,
'scores'
:
scores
,
'scores'
:
scores
,
'section_total'
:
section_total
,
'section_total'
:
section_total
,
'format'
:
format
,
'format'
:
format
,
'due'
:
section_module
.
due
,
'due'
:
section_module
.
lms
.
due
,
'graded'
:
graded
,
'graded'
:
graded
,
})
})
chapters
.
append
({
'course'
:
course
.
display_name
,
chapters
.
append
({
'course'
:
course
.
lms
.
display_name
,
'display_name'
:
chapter_module
.
display_name
,
'display_name'
:
chapter_module
.
lms
.
display_name
,
'url_name'
:
chapter_module
.
url_name
,
'url_name'
:
chapter_module
.
url_name
,
'sections'
:
sections
})
'sections'
:
sections
})
...
...
lms/djangoapps/courseware/module_render.py
View file @
01411ae6
...
@@ -92,6 +92,7 @@ def toc_for_course(user, request, course, active_chapter, active_section):
...
@@ -92,6 +92,7 @@ def toc_for_course(user, request, course, active_chapter, active_section):
chapters
=
list
()
chapters
=
list
()
for
chapter
in
course_module
.
get_display_items
():
for
chapter
in
course_module
.
get_display_items
():
print
chapter
,
chapter
.
_model_data
,
chapter
.
_model_data
.
get
(
'hide_from_toc'
),
chapter
.
lms
.
hide_from_toc
if
chapter
.
lms
.
hide_from_toc
:
if
chapter
.
lms
.
hide_from_toc
:
continue
continue
...
...
lms/djangoapps/instructor/views.py
View file @
01411ae6
...
@@ -76,7 +76,7 @@ def instructor_dashboard(request, course_id):
...
@@ -76,7 +76,7 @@ def instructor_dashboard(request, course_id):
data
=
[[
'# Enrolled'
,
CourseEnrollment
.
objects
.
filter
(
course_id
=
course_id
)
.
count
()]]
data
=
[[
'# Enrolled'
,
CourseEnrollment
.
objects
.
filter
(
course_id
=
course_id
)
.
count
()]]
data
+=
compute_course_stats
(
course
)
.
items
()
data
+=
compute_course_stats
(
course
)
.
items
()
if
request
.
user
.
is_staff
:
if
request
.
user
.
is_staff
:
data
.
append
([
'metadata'
,
escape
(
str
(
course
.
meta
data
))])
data
.
append
([
'metadata'
,
escape
(
str
(
course
.
_model_
data
))])
datatable
[
'data'
]
=
data
datatable
[
'data'
]
=
data
def
return_csv
(
fn
,
datatable
):
def
return_csv
(
fn
,
datatable
):
...
...
lms/lib/comment_client/utils.py
View file @
01411ae6
...
@@ -3,7 +3,7 @@ import logging
...
@@ -3,7 +3,7 @@ import logging
import
requests
import
requests
import
settings
import
settings
log
=
logging
.
getLogger
(
'mitx.'
+
__name__
)
log
=
logging
.
getLogger
(
__name__
)
def
strip_none
(
dic
):
def
strip_none
(
dic
):
return
dict
([(
k
,
v
)
for
k
,
v
in
dic
.
iteritems
()
if
v
is
not
None
])
return
dict
([(
k
,
v
)
for
k
,
v
in
dic
.
iteritems
()
if
v
is
not
None
])
...
...
lms/templates/staff_problem_info.html
View file @
01411ae6
...
@@ -46,9 +46,22 @@ github = <a href="${edit_link}">${edit_link | h}</a>
...
@@ -46,9 +46,22 @@ github = <a href="${edit_link}">${edit_link | h}</a>
%if source_file:
%if source_file:
source_url =
<a
href=
"${source_url}"
>
${source_file | h}
</a>
source_url =
<a
href=
"${source_url}"
>
${source_file | h}
</a>
%endif
%endif
%for name, field in fields:
<div>
${name} =
<pre
style=
"display:inline-block"
>
${field | h}
</pre>
<header><h3>
Module Fields
</h3></header>
%endfor
%for name, field in fields:
<div>
${name} =
<pre
style=
"display:inline-block"
>
${field | h}
</pre>
</div>
%endfor
</div>
<div>
<header><h3>
edX Fields
</h3></header>
%for name, field in lms_fields:
<div>
${name} =
<pre
style=
"display:inline-block"
>
${field | h}
</pre>
</div>
%endfor
</div>
category = ${category | h}
category = ${category | h}
</div>
</div>
%if render_histogram:
%if render_histogram:
...
...
lms/xmodule_namespace.py
View file @
01411ae6
from
xmodule.model
import
Namespace
,
Boolean
,
Scope
,
String
,
List
from
xmodule.model
import
Namespace
,
Boolean
,
Scope
,
String
,
List
from
xmodule.x_module
import
Date
from
xmodule.fields
import
Date
class
StringyBoolean
(
Boolean
):
def
from_json
(
self
,
value
):
print
"StringyBoolean "
,
value
if
isinstance
(
value
,
basestring
):
return
value
.
lower
()
==
'true'
return
value
class
LmsNamespace
(
Namespace
):
class
LmsNamespace
(
Namespace
):
hide_from_toc
=
Boolean
(
hide_from_toc
=
Stringy
Boolean
(
help
=
"Whether to display this module in the table of contents"
,
help
=
"Whether to display this module in the table of contents"
,
default
=
False
,
default
=
False
,
scope
=
Scope
.
settings
scope
=
Scope
.
settings
...
@@ -16,6 +25,7 @@ class LmsNamespace(Namespace):
...
@@ -16,6 +25,7 @@ class LmsNamespace(Namespace):
help
=
"What format this module is in (used for deciding which "
help
=
"What format this module is in (used for deciding which "
"grader to apply, and what to show in the TOC)"
,
"grader to apply, and what to show in the TOC)"
,
scope
=
Scope
.
settings
,
scope
=
Scope
.
settings
,
default
=
''
,
)
)
display_name
=
String
(
display_name
=
String
(
...
...
local-requirements.txt
View file @
01411ae6
# Python libraries to install that are local to the mitx repo
# Python libraries to install that are local to the mitx repo
-e common/lib/capa
-e common/lib/capa
-e common/lib/xmodule
-e common/lib/xmodule
-e
lms
-e
.
lms/
setup.py
→
setup.py
View file @
01411ae6
from
setuptools
import
setup
,
find_packages
from
setuptools
import
setup
,
find_packages
setup
(
setup
(
name
=
"edX
LMS
"
,
name
=
"edX
Apps
"
,
version
=
"0.1"
,
version
=
"0.1"
,
install_requires
=
[
'distribute'
],
install_requires
=
[
'distribute'
],
requires
=
[
requires
=
[
'xmodule'
,
'xmodule'
,
],
],
py_modules
=
[
'lms.xmodule_namespace'
],
# See http://guide.python-distribute.org/creation.html#entry-points
# See http://guide.python-distribute.org/creation.html#entry-points
# for a description of entry_points
# for a description of entry_points
entry_points
=
{
entry_points
=
{
...
...
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