Commit c9430659 by Piotr Mitros

Merge with template view

parents 20ada529 9ab2f591
......@@ -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)
......
......@@ -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+")"
......
......@@ -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
......
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))
......@@ -26,15 +26,18 @@ import courseware.content_parser as content_parser
log = logging.getLogger("mitx.courseware")
class LoncapaModule(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()
......
......@@ -7,14 +7,15 @@ from mitxmako.shortcuts import render_to_response, render_to_string
from x_module import XModule
from lxml import etree
class HtmlModule(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:
......
......@@ -6,14 +6,15 @@ from mitxmako.shortcuts import render_to_response, render_to_string
from x_module import XModule
class SchematicModule(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)
......
......@@ -13,7 +13,7 @@ from x_module import XModule
# OBSOLETE: This obsoletes 'type'
class_priority = ['video', 'problem']
class SequentialModule(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):
......
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)
......@@ -7,14 +7,15 @@ from mitxmako.shortcuts import render_to_response, render_to_string
from x_module import XModule
from lxml import etree
class VerticalModule(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})
......
......@@ -11,8 +11,8 @@ from x_module import XModule
log = logging.getLogger("mitx.courseware.modules")
class VideoModule(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(',')
......
......@@ -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 []
......
"""
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)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment