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
dbc35abb
Commit
dbc35abb
authored
Jun 07, 2012
by
David Ormsbee
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #89 from MITx/cpennington/courseware_documentation
Update documentation for functions inside common/xmodule
parents
69d412df
770bc4c3
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
86 additions
and
45 deletions
+86
-45
common/lib/xmodule/capa_module.py
+59
-42
common/lib/xmodule/template_module.py
+27
-3
No files found.
common/lib/xmodule/capa_module.py
View file @
dbc35abb
...
...
@@ -17,15 +17,31 @@ log = logging.getLogger("mitx.courseware")
#-----------------------------------------------------------------------------
TIMEDELTA_REGEX
=
re
.
compile
(
r'^((?P<days>\d+?) day(?:s?))?(\s)?((?P<hours>\d+?) hour(?:s?))?(\s)?((?P<minutes>\d+?) minute(?:s)?)?(\s)?((?P<seconds>\d+?) second(?:s)?)?$'
)
def
item
(
l
,
default
=
""
,
process
=
lambda
x
:
x
):
if
len
(
l
)
==
0
:
def
only_one
(
lst
,
default
=
""
,
process
=
lambda
x
:
x
):
"""
If lst is empty, returns default
If lst has a single element, applies process to that element and returns it
Otherwise, raises an exeception
"""
if
len
(
l
)
==
0
:
return
default
elif
len
(
l
)
==
1
:
elif
len
(
l
)
==
1
:
return
process
(
l
[
0
])
else
:
raise
Exception
(
'Malformed XML'
)
def
parse_timedelta
(
time_str
):
"""
time_str: A string with the following components:
<D> day[s] (optional)
<H> hour[s] (optional)
<M> minute[s] (optional)
<S> second[s] (optional)
Returns a datetime.timedelta parsed from the string
"""
parts
=
TIMEDELTA_REGEX
.
match
(
time_str
)
if
not
parts
:
return
...
...
@@ -36,15 +52,18 @@ def parse_timedelta(time_str):
time_params
[
name
]
=
int
(
param
)
return
timedelta
(
**
time_params
)
class
ComplexEncoder
(
json
.
JSONEncoder
):
def
default
(
self
,
obj
):
if
isinstance
(
obj
,
complex
):
return
"{real:.7g}{imag:+.7g}*j"
.
format
(
real
=
obj
.
real
,
imag
=
obj
.
imag
)
return
"{real:.7g}{imag:+.7g}*j"
.
format
(
real
=
obj
.
real
,
imag
=
obj
.
imag
)
return
json
.
JSONEncoder
.
default
(
self
,
obj
)
class
ModuleDescriptor
(
XModuleDescriptor
):
pass
class
Module
(
XModule
):
''' Interface between capa_problem and x_module. Originally a hack
meant to be refactored out, but it seems to be serving a useful
...
...
@@ -77,8 +96,8 @@ class Module(XModule):
def
get_problem_html
(
self
,
encapsulate
=
True
):
html
=
self
.
lcp
.
get_html
()
content
=
{
'name'
:
self
.
name
,
'html'
:
html
,
content
=
{
'name'
:
self
.
name
,
'html'
:
html
,
'weight'
:
self
.
weight
,
}
...
...
@@ -95,7 +114,6 @@ class Module(XModule):
reset_button
=
False
save_button
=
False
# User submitted a problem, and hasn't reset. We don't want
# more submissions.
if
self
.
lcp
.
done
and
self
.
rerandomize
==
"always"
:
...
...
@@ -115,22 +133,22 @@ class Module(XModule):
save_button
=
False
# Check if explanation is available, and if so, give a link
explain
=
""
if
self
.
lcp
.
done
and
self
.
explain_available
==
'attempted'
:
explain
=
self
.
explanation
if
self
.
closed
()
and
self
.
explain_available
==
'closed'
:
explain
=
self
.
explanation
explain
=
""
if
self
.
lcp
.
done
and
self
.
explain_available
==
'attempted'
:
explain
=
self
.
explanation
if
self
.
closed
()
and
self
.
explain_available
==
'closed'
:
explain
=
self
.
explanation
if
len
(
explain
)
==
0
:
explain
=
False
context
=
{
'problem'
:
content
,
'id'
:
self
.
item_id
,
'check_button'
:
check_button
,
'reset_button'
:
reset_button
,
'save_button'
:
save_button
,
'answer_available'
:
self
.
answer_available
(),
'ajax_url'
:
self
.
ajax_url
,
context
=
{
'problem'
:
content
,
'id'
:
self
.
item_id
,
'check_button'
:
check_button
,
'reset_button'
:
reset_button
,
'save_button'
:
save_button
,
'answer_available'
:
self
.
answer_available
(),
'ajax_url'
:
self
.
ajax_url
,
'attempts_used'
:
self
.
attempts
,
'attempts_allowed'
:
self
.
max_attempts
,
'explain'
:
explain
,
...
...
@@ -138,7 +156,7 @@ class Module(XModule):
html
=
self
.
system
.
render_template
(
'problem.html'
,
context
)
if
encapsulate
:
html
=
'<div id="problem_{id}" class="problem" data-url="{ajax_url}">'
.
format
(
id
=
self
.
item_id
,
ajax_url
=
self
.
ajax_url
)
+
html
+
"</div>"
html
=
'<div id="problem_{id}" class="problem" data-url="{ajax_url}">'
.
format
(
id
=
self
.
item_id
,
ajax_url
=
self
.
ajax_url
)
+
html
+
"</div>"
return
html
...
...
@@ -150,20 +168,19 @@ class Module(XModule):
dom2
=
etree
.
fromstring
(
xml
)
self
.
explanation
=
"problems/"
+
item
(
dom2
.
xpath
(
'/problem/@explain'
),
default
=
"closed"
)
# TODO: Should be converted to: self.explanation=
item
(dom2.xpath('/problem/@explain'), default="closed")
self
.
explain_available
=
item
(
dom2
.
xpath
(
'/problem/@explain_available'
))
self
.
explanation
=
"problems/"
+
only_one
(
dom2
.
xpath
(
'/problem/@explain'
),
default
=
"closed"
)
# TODO: Should be converted to: self.explanation=
only_one
(dom2.xpath('/problem/@explain'), default="closed")
self
.
explain_available
=
only_one
(
dom2
.
xpath
(
'/problem/@explain_available'
))
display_due_date_string
=
item
(
dom2
.
xpath
(
'/problem/@due'
))
if
len
(
display_due_date_string
)
>
0
:
self
.
display_due_date
=
dateutil
.
parser
.
parse
(
display_due_date_string
)
display_due_date_string
=
only_one
(
dom2
.
xpath
(
'/problem/@due'
))
if
len
(
display_due_date_string
)
>
0
:
self
.
display_due_date
=
dateutil
.
parser
.
parse
(
display_due_date_string
)
#log.debug("Parsed " + display_due_date_string + " to " + str(self.display_due_date))
else
:
self
.
display_due_date
=
None
self
.
display_due_date
=
None
grace_period_string
=
item
(
dom2
.
xpath
(
'/problem/@graceperiod'
))
if
len
(
grace_period_string
)
>
0
and
self
.
display_due_date
:
grace_period_string
=
only_one
(
dom2
.
xpath
(
'/problem/@graceperiod'
))
if
len
(
grace_period_string
)
>
0
and
self
.
display_due_date
:
self
.
grace_period
=
parse_timedelta
(
grace_period_string
)
self
.
close_date
=
self
.
display_due_date
+
self
.
grace_period
#log.debug("Then parsed " + grace_period_string + " to closing date" + str(self.close_date))
...
...
@@ -171,19 +188,19 @@ class Module(XModule):
self
.
grace_period
=
None
self
.
close_date
=
self
.
display_due_date
self
.
max_attempts
=
item
(
dom2
.
xpath
(
'/problem/@attempts'
))
self
.
max_attempts
=
only_one
(
dom2
.
xpath
(
'/problem/@attempts'
))
if
len
(
self
.
max_attempts
)
>
0
:
self
.
max_attempts
=
int
(
self
.
max_attempts
)
self
.
max_attempts
=
int
(
self
.
max_attempts
)
else
:
self
.
max_attempts
=
None
self
.
max_attempts
=
None
self
.
show_answer
=
item
(
dom2
.
xpath
(
'/problem/@showanswer'
))
self
.
show_answer
=
only_one
(
dom2
.
xpath
(
'/problem/@showanswer'
))
if
self
.
show_answer
==
""
:
self
.
show_answer
=
"closed"
if
self
.
show_answer
==
""
:
self
.
show_answer
=
"closed"
self
.
rerandomize
=
item
(
dom2
.
xpath
(
'/problem/@rerandomize'
))
if
self
.
rerandomize
==
""
or
self
.
rerandomize
==
"always"
or
self
.
rerandomize
==
"true"
:
self
.
rerandomize
=
only_one
(
dom2
.
xpath
(
'/problem/@rerandomize'
))
if
self
.
rerandomize
==
""
or
self
.
rerandomize
==
"always"
or
self
.
rerandomize
==
"true"
:
self
.
rerandomize
=
"always"
elif
self
.
rerandomize
==
"false"
or
self
.
rerandomize
==
"per_student"
:
self
.
rerandomize
=
"per_student"
...
...
@@ -197,10 +214,10 @@ class Module(XModule):
if
state
!=
None
and
'attempts'
in
state
:
self
.
attempts
=
state
[
'attempts'
]
# TODO: Should be: self.filename=
item(dom2.xpath('/problem/@filename'))
self
.
filename
=
"problems/"
+
item
(
dom2
.
xpath
(
'/problem/@filename'
))
+
".xml"
self
.
name
=
item
(
dom2
.
xpath
(
'/problem/@name'
))
self
.
weight
=
item
(
dom2
.
xpath
(
'/problem/@weight'
))
# TODO: Should be: self.filename=
only_one(dom2.xpath('/problem/@filename'))
self
.
filename
=
"problems/"
+
only_one
(
dom2
.
xpath
(
'/problem/@filename'
))
+
".xml"
self
.
name
=
only_one
(
dom2
.
xpath
(
'/problem/@name'
))
self
.
weight
=
only_one
(
dom2
.
xpath
(
'/problem/@weight'
))
if
self
.
rerandomize
==
'never'
:
seed
=
1
else
:
...
...
common/lib/xmodule/template_module.py
View file @
dbc35abb
...
...
@@ -3,12 +3,36 @@ import json
from
x_module
import
XModule
,
XModuleDescriptor
from
lxml
import
etree
class
ModuleDescriptor
(
XModuleDescriptor
):
pass
class
Module
(
XModule
):
"""
This module supports tags of the form
<customtag option="val" option2="val2">
<impl>$tagname</impl>
</customtag>
In this case, $tagname should refer to a file in data/custom_tags, which contains
a mako template that uses ${option} and ${option2} for the content.
For instance:
data/custom_tags/book::
More information given in <a href="/book/${page}">the text</a>
course.xml::
...
<customtag page="234"><impl>book</impl></customtag>
...
Renders to::
More information given in <a href="/book/234">the text</a>
"""
def
get_state
(
self
):
return
json
.
dumps
({
})
return
json
.
dumps
({})
@classmethod
def
get_xml_tags
(
c
):
...
...
@@ -20,6 +44,6 @@ class Module(XModule):
def
__init__
(
self
,
system
,
xml
,
item_id
,
state
=
None
):
XModule
.
__init__
(
self
,
system
,
xml
,
item_id
,
state
)
xmltree
=
etree
.
fromstring
(
xml
)
filename
=
xmltree
[
0
]
.
text
filename
=
xmltree
.
find
(
'impl'
)
.
text
params
=
dict
(
xmltree
.
items
())
self
.
html
=
self
.
system
.
render_template
(
filename
,
params
,
namespace
=
'custom_tags'
)
self
.
html
=
self
.
system
.
render_template
(
filename
,
params
,
namespace
=
'custom_tags'
)
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