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
c9430659
Commit
c9430659
authored
Feb 13, 2012
by
Piotr Mitros
Browse files
Options
Browse Files
Download
Plain Diff
Merge with template view
parents
20ada529
9ab2f591
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
172 additions
and
60 deletions
+172
-60
courseware/content_parser.py
+12
-6
courseware/management/commands/check_course.py
+1
-0
courseware/module_render.py
+9
-23
courseware/modules/__init__.py
+61
-0
courseware/modules/capa_module.py
+5
-2
courseware/modules/html_module.py
+4
-3
courseware/modules/schematic_module.py
+4
-3
courseware/modules/seq_module.py
+3
-2
courseware/modules/template_module.py
+29
-0
courseware/modules/vertical_module.py
+4
-3
courseware/modules/video_module.py
+5
-4
courseware/modules/x_module.py
+3
-2
courseware/tests.py
+32
-12
No files found.
courseware/content_parser.py
View file @
c9430659
...
...
@@ -49,7 +49,7 @@ def xpath(xml, query_string, **args):
We should remove this with the move to lxml.
We should also use lxml argument passing. '''
doc
=
etree
.
fromstring
(
xml
)
print
type
(
doc
)
#
print type(doc)
def
escape
(
x
):
# TODO: This should escape the string. For now, we just assume it's made of valid characters.
# Couldn't figure out how to escape for lxml in a few quick Googles
...
...
@@ -60,7 +60,7 @@ def xpath(xml, query_string, **args):
return
x
args
=
dict
(
((
k
,
escape
(
args
[
k
]))
for
k
in
args
)
)
print
args
#
print args
results
=
doc
.
xpath
(
query_string
.
format
(
**
args
))
return
results
...
...
@@ -86,14 +86,20 @@ def item(l, default="", process=lambda x:x):
def
id_tag
(
course
):
''' Tag all course elements with unique IDs '''
default
_ids
=
{
'video'
:
'youtube'
,
old
_ids
=
{
'video'
:
'youtube'
,
'problem'
:
'filename'
,
'sequential'
:
'id'
,
'html'
:
'filename'
,
'vertical'
:
'id'
,
'tab'
:
'id'
,
'schematic'
:
'id'
}
'schematic'
:
'id'
,
'book'
:
'id'
}
import
courseware.modules
default_ids
=
courseware
.
modules
.
get_default_ids
()
#print default_ids, old_ids
#print default_ids == old_ids
# Tag elements with unique IDs
elements
=
course
.
xpath
(
"|"
.
join
([
'//'
+
c
for
c
in
default_ids
]))
for
elem
in
elements
:
...
...
@@ -143,7 +149,7 @@ def course_file(user):
filename
=
UserProfile
.
objects
.
get
(
user
=
user
)
.
courseware
data_template
=
template_lookup
.
get_template
(
filename
)
options
=
{
'dev_content'
:
True
}
options
=
{
'dev_content'
:
settings
.
DEV_CONTENT
}
tree
=
etree
.
XML
(
data_template
.
render
(
**
options
))
id_tag
(
tree
)
...
...
courseware/management/commands/check_course.py
View file @
c9430659
...
...
@@ -41,6 +41,7 @@ class Command(BaseCommand):
if
os
.
path
.
exists
(
sections_dir
):
print
"Checking all section includes are valid XML"
for
f
in
os
.
listdir
(
sections_dir
):
print
f
etree
.
parse
(
sections_dir
+
'/'
+
f
)
else
:
print
"Skipping check of include files -- no section includes dir ("
+
sections_dir
+
")"
...
...
courseware/module_render.py
View file @
c9430659
...
...
@@ -26,24 +26,10 @@ import track.views
import
courseware.content_parser
as
content_parser
import
courseware.modules.capa_module
import
courseware.modules.html_module
import
courseware.modules.schematic_module
import
courseware.modules.seq_module
import
courseware.modules.vertical_module
import
courseware.modules.video_module
import
courseware.modules
log
=
logging
.
getLogger
(
"mitx.courseware"
)
## TODO: Add registration mechanism
modx_modules
=
{
'problem'
:
courseware
.
modules
.
capa_module
.
LoncapaModule
,
'video'
:
courseware
.
modules
.
video_module
.
VideoModule
,
'html'
:
courseware
.
modules
.
html_module
.
HtmlModule
,
'vertical'
:
courseware
.
modules
.
vertical_module
.
VerticalModule
,
'sequential'
:
courseware
.
modules
.
seq_module
.
SequentialModule
,
'tab'
:
courseware
.
modules
.
seq_module
.
SequentialModule
,
'schematic'
:
courseware
.
modules
.
schematic_module
.
SchematicModule
}
def
object_cache
(
cache
,
user
,
module_type
,
module_id
):
# We don't look up on user -- all queries include user
# Additional lookup would require a DB hit the way Django
...
...
@@ -74,18 +60,18 @@ def modx_dispatch(request, module=None, dispatch=None, id=None):
ajax_url
=
'/modx/'
+
module
+
'/'
+
id
+
'/'
id_tag
=
modx_modules
[
module
]
.
id_attribute
id_tag
=
courseware
.
modules
.
get_module_class
(
module
.
id_attribute
)
# Grab the XML corresponding to the request from course.xml
xml
=
content_parser
.
module_xml
(
content_parser
.
course_file
(
request
.
user
),
module
,
id_tag
,
id
)
# Create the module
instance
=
modx_modules
[
module
]
(
xml
,
s
.
module_id
,
ajax_url
=
ajax_url
,
state
=
s
.
state
,
track_function
=
make_track_function
(
request
),
render_function
=
None
)
instance
=
courseware
.
modules
.
get_module_class
(
module
)
(
xml
,
s
.
module_id
,
ajax_url
=
ajax_url
,
state
=
s
.
state
,
track_function
=
make_track_function
(
request
),
render_function
=
None
)
# Let the module handle the AJAX
ajax_return
=
instance
.
handle_ajax
(
dispatch
,
request
.
POST
)
# Save the state back to the database
...
...
@@ -100,7 +86,7 @@ def render_x_module(user, request, xml_module, module_object_preload):
''' Generic module for extensions. This renders to HTML. '''
# Check if problem has an instance in DB
module_type
=
xml_module
.
tag
module_class
=
modx_modules
[
module_type
]
module_class
=
courseware
.
modules
.
get_module_class
(
module_type
)
module_id
=
xml_module
.
get
(
'id'
)
#module_class.id_attribute) or ""
# Grab state from database
...
...
courseware/modules/__init__.py
View file @
c9430659
import
os
import
os.path
from
django.conf
import
settings
import
capa_module
import
html_module
import
schematic_module
import
seq_module
import
template_module
import
vertical_module
import
video_module
from
courseware
import
content_parser
# Import all files in modules directory, excluding backups (# and . in name)
# and __init__
#
# Stick them in a list
# modx_module_list = []
# for f in os.listdir(os.path.dirname(__file__)):
# if f!='__init__.py' and \
# f[-3:] == ".py" and \
# "." not in f[:-3] \
# and '#' not in f:
# mod_path = 'courseware.modules.'+f[:-3]
# mod = __import__(mod_path, fromlist = "courseware.modules")
# if 'Module' in mod.__dict__:
# modx_module_list.append(mod)
#print modx_module_list
modx_module_list
=
[
capa_module
,
html_module
,
schematic_module
,
seq_module
,
template_module
,
vertical_module
,
video_module
]
#print modx_module_list
# Convert list to a dictionary for lookup by tag
modx_modules
=
{}
for
module
in
modx_module_list
:
for
tag
in
module
.
Module
.
get_xml_tags
():
modx_modules
[
tag
]
=
module
.
Module
def
get_module_class
(
tag
):
''' Given an XML tag (e.g. 'video'), return
the associated module (e.g. video_module.Module).
'''
return
modx_modules
[
tag
]
def
get_module_id
(
tag
):
''' Given an XML tag (e.g. 'video'), return
the default ID for that module (e.g. 'youtube_id')
'''
return
modx_modules
[
tag
]
.
id_attribute
def
get_valid_tags
():
return
modx_modules
.
keys
()
def
get_default_ids
():
tags
=
get_valid_tags
()
ids
=
map
(
get_module_id
,
tags
)
return
dict
(
zip
(
tags
,
ids
))
courseware/modules/capa_module.py
View file @
c9430659
...
...
@@ -26,15 +26,18 @@ import courseware.content_parser as content_parser
log
=
logging
.
getLogger
(
"mitx.courseware"
)
class
Loncapa
Module
(
XModule
):
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
prupose now. We can e.g .destroy and create the capa_problem on a
reset.
'''
xml_tags
=
[
"problem"
]
id_attribute
=
"filename"
@classmethod
def
get_xml_tags
(
c
):
return
[
"problem"
]
def
get_state
(
self
):
state
=
self
.
lcp
.
get_state
()
...
...
courseware/modules/html_module.py
View file @
c9430659
...
...
@@ -7,14 +7,15 @@ from mitxmako.shortcuts import render_to_response, render_to_string
from
x_module
import
XModule
from
lxml
import
etree
class
Html
Module
(
XModule
):
class
Module
(
XModule
):
id_attribute
=
'filename'
def
get_state
(
self
):
return
json
.
dumps
({
})
def
get_xml_tags
():
return
"html"
@classmethod
def
get_xml_tags
(
c
):
return
[
"html"
]
def
get_html
(
self
):
if
self
.
filename
==
None
:
...
...
courseware/modules/schematic_module.py
View file @
c9430659
...
...
@@ -6,14 +6,15 @@ from mitxmako.shortcuts import render_to_response, render_to_string
from
x_module
import
XModule
class
Schematic
Module
(
XModule
):
class
Module
(
XModule
):
id_attribute
=
'id'
def
get_state
(
self
):
return
json
.
dumps
({
})
def
get_xml_tags
():
return
"schematic"
@classmethod
def
get_xml_tags
(
c
):
return
[
"schematic"
]
def
get_html
(
self
):
return
'<input type="hidden" class="schematic" name="{item_id}" height="480" width="640">'
.
format
(
item_id
=
self
.
item_id
)
...
...
courseware/modules/seq_module.py
View file @
c9430659
...
...
@@ -13,7 +13,7 @@ from x_module import XModule
# OBSOLETE: This obsoletes 'type'
class_priority
=
[
'video'
,
'problem'
]
class
Sequential
Module
(
XModule
):
class
Module
(
XModule
):
''' Layout module which lays out content in a temporal sequence
'''
id_attribute
=
'id'
...
...
@@ -21,7 +21,8 @@ class SequentialModule(XModule):
def
get_state
(
self
):
return
json
.
dumps
({
'position'
:
self
.
position
})
def
get_xml_tags
():
@classmethod
def
get_xml_tags
(
c
):
return
[
"sequential"
,
'tab'
]
def
get_html
(
self
):
...
...
courseware/modules/template_module.py
0 → 100644
View file @
c9430659
import
json
import
os
## TODO: Abstract out from Django
from
django.conf
import
settings
from
mitxmako.shortcuts
import
render_to_response
,
render_to_string
from
x_module
import
XModule
from
lxml
import
etree
class
Module
(
XModule
):
def
get_state
(
self
):
return
json
.
dumps
({
})
@classmethod
def
get_xml_tags
(
c
):
tags
=
os
.
listdir
(
settings
.
DATA_DIR
+
'/custom_tags'
)
return
tags
def
get_html
(
self
):
return
self
.
html
def
__init__
(
self
,
xml
,
item_id
,
ajax_url
=
None
,
track_url
=
None
,
state
=
None
,
track_function
=
None
,
render_function
=
None
):
XModule
.
__init__
(
self
,
xml
,
item_id
,
ajax_url
,
track_url
,
state
,
track_function
,
render_function
)
xmltree
=
etree
.
fromstring
(
xml
)
filename
=
xmltree
.
tag
params
=
dict
(
xmltree
.
items
())
# print params
self
.
html
=
render_to_string
(
'custom_tags/'
+
filename
,
params
)
courseware/modules/vertical_module.py
View file @
c9430659
...
...
@@ -7,14 +7,15 @@ from mitxmako.shortcuts import render_to_response, render_to_string
from
x_module
import
XModule
from
lxml
import
etree
class
Vertical
Module
(
XModule
):
class
Module
(
XModule
):
id_attribute
=
'id'
def
get_state
(
self
):
return
json
.
dumps
({
})
def
get_xml_tags
():
return
"vertical"
@classmethod
def
get_xml_tags
(
c
):
return
[
"vertical"
]
def
get_html
(
self
):
return
render_to_string
(
'vert_module.html'
,{
'items'
:
self
.
contents
})
...
...
courseware/modules/video_module.py
View file @
c9430659
...
...
@@ -11,8 +11,8 @@ from x_module import XModule
log
=
logging
.
getLogger
(
"mitx.courseware.modules"
)
class
Video
Module
(
XModule
):
#
id_attribute = 'youtube'
class
Module
(
XModule
):
id_attribute
=
'youtube'
video_time
=
0
def
handle_ajax
(
self
,
dispatch
,
get
):
...
...
@@ -28,9 +28,10 @@ class VideoModule(XModule):
log
.
debug
(
u"STATE POSITION {0}"
.
format
(
self
.
position
))
return
json
.
dumps
({
'position'
:
self
.
position
})
def
get_xml_tags
():
@classmethod
def
get_xml_tags
(
c
):
'''Tags in the courseware file guaranteed to correspond to the module'''
return
"video"
return
[
"video"
]
def
video_list
(
self
):
l
=
self
.
youtube
.
split
(
','
)
...
...
courseware/modules/x_module.py
View file @
c9430659
...
...
@@ -8,9 +8,10 @@ class XModule(object):
Initialized on access with __init__, first time with state=None, and
then with state
'''
id_attribute
=
'
name
'
# An attribute guaranteed to be unique
id_attribute
=
'
id
'
# An attribute guaranteed to be unique
def
get_xml_tags
():
@classmethod
def
get_xml_tags
(
c
):
''' Tags in the courseware file guaranteed to correspond to the module '''
return
[]
...
...
courseware/tests.py
View file @
c9430659
"""
This file demonstrates writing tests using the unittest module. These will pass
when you run "manage.py test".
import
unittest
Replace this with more appropriate tests for your application.
"""
import
numpy
from
django.test
import
TestCase
import
courseware.modules
import
courseware.capa.calc
as
calc
class
ModelsTest
(
unittest
.
TestCase
):
def
setUp
(
self
):
pass
class
SimpleTest
(
TestCase
):
def
test_basic_addition
(
self
):
"""
Tests that 1 + 1 always equals 2.
"""
self
.
assertEqual
(
1
+
1
,
2
)
def
test_get_module_class
(
self
):
vc
=
courseware
.
modules
.
get_module_class
(
'video'
)
vc_str
=
"<class 'courseware.modules.video_module.Module'>"
self
.
assertEqual
(
str
(
vc
),
vc_str
)
video_id
=
courseware
.
modules
.
get_default_ids
()[
'video'
]
self
.
assertEqual
(
video_id
,
'youtube'
)
def
test_calc
(
self
):
variables
=
{
'R1'
:
2.0
,
'R3'
:
4.0
}
functions
=
{
'sin'
:
numpy
.
sin
,
'cos'
:
numpy
.
cos
}
self
.
assertEqual
(
calc
.
evaluator
(
variables
,
functions
,
"10000||sin(7+5)-6k"
),
4000.0
)
self
.
assertEqual
(
calc
.
evaluator
({
'R1'
:
2.0
,
'R3'
:
4.0
},
{},
"13"
),
13
)
self
.
assertEqual
(
calc
.
evaluator
(
variables
,
functions
,
"13"
),
13
)
self
.
assertEqual
(
calc
.
evaluator
({
'a'
:
2.2997471478310274
,
'k'
:
9
,
'm'
:
8
,
'x'
:
0.66009498411213041
},
{},
"5"
),
5
)
self
.
assertEqual
(
calc
.
evaluator
({},{},
"-1"
),
-
1
)
self
.
assertEqual
(
calc
.
evaluator
({},{},
"-0.33"
),
-.
33
)
self
.
assertEqual
(
calc
.
evaluator
({},{},
"-.33"
),
-.
33
)
exception_happened
=
False
try
:
evaluator
({},{},
"5+7 QWSEKO"
)
except
:
exception_happened
=
True
self
.
assertTrue
(
exception_happened
)
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