Commit 7e177fc6 by Bridger Maxwell

Merge

--HG--
branch : bridgerwiki
parents f2f6f0c1 81e70347
......@@ -11,11 +11,12 @@ import calc, eia
from util import contextualize_text
from inputtypes import textline, schematic
from responsetypes import numericalresponse, formularesponse, customresponse
from responsetypes import numericalresponse, formularesponse, customresponse, schematicresponse
response_types = {'numericalresponse':numericalresponse,
'formularesponse':formularesponse,
'customresponse':customresponse}
'customresponse':customresponse,
'schematicresponse':schematicresponse}
entry_types = ['textline', 'schematic']
response_properties = ["responseparam", "answer"]
# How to convert from original XML to HTML
......@@ -23,6 +24,7 @@ response_properties = ["responseparam", "answer"]
html_transforms = {'problem': {'tag':'div'},
"numericalresponse": {'tag':'span'},
"customresponse": {'tag':'span'},
"schematicresponse": {'tag':'span'},
"formularesponse": {'tag':'span'},
"text": {'tag':'span'}}
......@@ -36,7 +38,7 @@ global_context={'random':random,
# These should be removed from HTML output, including all subelements
html_problem_semantics = ["responseparam", "answer", "script"]
# These should be removed from HTML output, but keeping subelements
html_skip = ["numericalresponse", "customresponse", "formularesponse", "text"]
html_skip = ["numericalresponse", "customresponse", "schematicresponse", "formularesponse", "text"]
# These should be transformed
html_special_response = {"textline":textline.render,
"schematic":schematic.render}
......
try:
from django.conf import settings
from auth.models import UserProfile
except:
settings = None
from xml.dom.minidom import parse, parseString
from lxml import etree
''' This file will eventually form an abstraction layer between the
course XML file and the rest of the system.
TODO: Shift everything from xml.dom.minidom to XPath (or XQuery)
'''
def xpath(xml, query_string, **args):
''' Safe xpath query into an xml tree:
* xml is the tree.
* query_string is the query
* args are the parameters. Substitute for {params}.
We should remove this with the move to lxml.
We should also use lxml argument passing. '''
doc = etree.fromstring(xml)
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
valid_chars="".join(map(chr, range(ord('a'),ord('z')+1)+range(ord('A'),ord('Z')+1)+range(ord('0'), ord('9')+1)))+"_ "
for e in x:
if e not in valid_chars:
raise Exception("Invalid char in xpath expression. TODO: Escape")
return x
args=dict( ((k, escape(args[k])) for k in args) )
print args
results = doc.xpath(query_string.format(**args))
return results
def xpath_remove(tree, path):
''' Remove all items matching path from lxml tree. Works in
place.'''
items = tree.xpath(path)
for item in items:
item.getparent().remove(item)
return tree
if __name__=='__main__':
print xpath('<html><problem name="Bob"></problem></html>', '/{search}/problem[@name="{name}"]', search='html', name="Bob")
def item(l, default="", process=lambda x:x):
if len(l)==0:
return default
elif len(l)==1:
return process(l[0])
else:
raise Exception('Malformed XML')
def course_file(user):
# TODO: Cache. Also, return the libxml2 object.
return settings.DATA_DIR+UserProfile.objects.get(user=user).courseware
def module_xml(coursefile, module, id_tag, module_id):
''' Get XML for a module based on module and module_id. Assumes
module occurs once in courseware XML file.. '''
doc = etree.parse(coursefile)
# Sanitize input
if not module.isalnum():
raise Exception("Module is not alphanumeric")
if not module_id.isalnum():
raise Exception("Module ID is not alphanumeric")
xpath_search='//*/{module}[(@{id_tag} = "{id}") or (@id = "{id}")]'.format(module=module,
id_tag=id_tag,
id=module_id)
#result_set=doc.xpathEval(xpath_search)
result_set=doc.xpath(xpath_search)
if len(result_set)>1:
print "WARNING: Potentially malformed course file", module, module_id
if len(result_set)==0:
return None
return etree.tostring(result_set[0])
#return result_set[0].serialize()
def toc_from_xml(coursefile, active_chapter, active_section):
dom=parse(coursefile)
course = dom.getElementsByTagName('course')[0]
name=course.getAttribute("name")
chapters = course.getElementsByTagName('chapter')
ch=list()
for c in chapters:
if c.getAttribute("name") == 'hidden':
continue
sections=list()
for s in c.getElementsByTagName('section'):
sections.append({'name':s.getAttribute("name"),
'time':s.getAttribute("time"),
'format':s.getAttribute("format"),
'due':s.getAttribute("due"),
'active':(c.getAttribute("name")==active_chapter and \
s.getAttribute("name")==active_section)})
ch.append({'name':c.getAttribute("name"),
'sections':sections,
'active':(c.getAttribute("name")==active_chapter)})
return ch
def dom_select(dom, element_type, element_name):
if dom==None:
return None
elements=dom.getElementsByTagName(element_type)
for e in elements:
if e.getAttribute("name")==element_name:
return e
return None
......@@ -17,7 +17,19 @@ class schematic(object):
eid = element.get('id')
height = element.get('height')
width = element.get('width')
context = {'id':eid, 'value':value, 'state':state, 'width':width, 'height':height}
parts = element.get('parts')
analyses = element.get('analyses')
initial_value = element.get('initial_value')
context = {
'id':eid,
'value':value,
'initial_value':initial_value,
'state':state,
'width':width,
'height':height,
'parts':parts,
'analyses':analyses,
}
html=render_to_string("schematicinput.html", context)
return etree.XML(html)
......
import random, numpy, math, scipy
import random, numpy, math, scipy, json
from util import contextualize_text
from calc import evaluator
import random, math
......@@ -63,7 +63,6 @@ class customresponse(object):
# be handled by capa_problem
return {}
class formularesponse(object):
def __init__(self, xml, context):
self.xml = xml
......@@ -114,3 +113,28 @@ class formularesponse(object):
def get_answers(self):
return {self.answer_id:self.correct_answer}
class schematicresponse(object):
def __init__(self, xml, context):
self.xml = xml
self.answer_ids = xml.xpath('//*[@id=$id]//schematic/@id',
id=xml.get('id'))
self.context = context
answer = xml.xpath('//*[@id=$id]//answer',
id=xml.get('id'))[0]
answer_src = answer.get('src')
if answer_src != None:
self.code = open(settings.DATA_DIR+'src/'+answer_src).read()
else:
self.code = answer.text
def grade(self, student_answers):
submission = [json.loads(student_answers[k]) for k in sorted(self.answer_ids)]
self.context.update({'submission':submission})
exec self.code in global_context, self.context
return zip(sorted(self.answer_ids), self.context['correct'])
def get_answers(self):
# Since this is explicitly specified in the problem, this will
# be handled by capa_problem
return {}
from django.conf import settings
from xml.dom.minidom import parse, parseString
try:
from django.conf import settings
from auth.models import UserProfile
except:
settings = None
from lxml import etree
from auth.models import UserProfile
import json
import hashlib
''' This file will eventually form an abstraction layer between the
course XML file and the rest of the system.
......@@ -11,11 +15,18 @@ course XML file and the rest of the system.
TODO: Shift everything from xml.dom.minidom to XPath (or XQuery)
'''
def fasthash(string):
m = hashlib.new("md4")
m.update(string)
return "id"+m.hexdigest()
def xpath(xml, query_string, **args):
''' Safe xpath query into an xml tree:
* xml is the tree.
* query_string is the query
* args are the parameters. Substitute for {params}. '''
* args are the parameters. Substitute for {params}.
We should remove this with the move to lxml.
We should also use lxml argument passing. '''
doc = etree.fromstring(xml)
print type(doc)
def escape(x):
......@@ -32,8 +43,17 @@ def xpath(xml, query_string, **args):
results = doc.xpath(query_string.format(**args))
return results
def xpath_remove(tree, path):
''' Remove all items matching path from lxml tree. Works in
place.'''
items = tree.xpath(path)
for item in items:
item.getparent().remove(item)
return tree
if __name__=='__main__':
print xpath('<html><problem name="Bob"></problem></html>', '/{search}/problem[@name="{name}"]', search='html', name="Bob")
print xpath('<html><problem name="Bob"></problem></html>', '/{search}/problem[@name="{name}"]',
search='html', name="Bob")
def item(l, default="", process=lambda x:x):
if len(l)==0:
......@@ -42,16 +62,39 @@ def item(l, default="", process=lambda x:x):
return process(l[0])
else:
raise Exception('Malformed XML')
def id_tag(course):
''' Tag all course elements with unique IDs '''
default_ids = {'video':'youtube',
'problem':'filename',
'sequential':'id',
'html':'filename',
'vertical':'id',
'tab':'id',
'schematic':'id'}
# Tag elements with unique IDs
elements = course.xpath("|".join(['//'+c for c in default_ids]))
for elem in elements:
if elem.get('id'):
pass
elif elem.get(default_ids[elem.tag]):
new_id = elem.get(default_ids[elem.tag]) # Convert to alphanumeric
new_id = "".join([a for a in new_id if a.isalnum()])
elem.set('id', new_id)
else:
elem.set('id', fasthash(etree.tostring(elem)))
def course_file(user):
# TODO: Cache. Also, return the libxml2 object.
return settings.DATA_DIR+UserProfile.objects.get(user=user).courseware
# TODO: Cache.
tree = etree.parse(settings.DATA_DIR+UserProfile.objects.get(user=user).courseware)
id_tag(tree)
return tree
def module_xml(coursefile, module, id_tag, module_id):
''' Get XML for a module based on module and module_id. Assumes
module occurs once in courseware XML file.. '''
doc = etree.parse(coursefile)
doc = coursefile
# Sanitize input
if not module.isalnum():
......@@ -70,35 +113,24 @@ def module_xml(coursefile, module, id_tag, module_id):
return etree.tostring(result_set[0])
#return result_set[0].serialize()
def toc_from_xml(coursefile, active_chapter, active_section):
dom=parse(coursefile)
def toc_from_xml(dom, active_chapter, active_section):
name = dom.xpath('//course/@name')[0]
course = dom.getElementsByTagName('course')[0]
name=course.getAttribute("name")
chapters = course.getElementsByTagName('chapter')
chapters = dom.xpath('//course[@name=$name]/chapter', name=name)
ch=list()
for c in chapters:
if c.getAttribute("name") == 'hidden':
if c.get('name') == 'hidden':
continue
sections=list()
for s in c.getElementsByTagName('section'):
sections.append({'name':s.getAttribute("name"),
'time':s.getAttribute("time"),
'format':s.getAttribute("format"),
'due':s.getAttribute("due"),
'active':(c.getAttribute("name")==active_chapter and \
s.getAttribute("name")==active_section)})
ch.append({'name':c.getAttribute("name"),
for s in dom.xpath('//course[@name=$name]/chapter[@name=$chname]/section', name=name, chname=c.get('name')):
sections.append({'name':s.get("name") or "",
'time':s.get("time") or "",
'format':s.get("format") or "",
'due':s.get("due") or "",
'active':(c.get("name")==active_chapter and \
s.get("name")==active_section)})
ch.append({'name':c.get("name"),
'sections':sections,
'active':(c.getAttribute("name")==active_chapter)})
'active':(c.get("name")==active_chapter)})
return ch
def dom_select(dom, element_type, element_name):
if dom==None:
return None
elements=dom.getElementsByTagName(element_type)
for e in elements:
if e.getAttribute("name")==element_name:
return e
return None
......@@ -16,10 +16,12 @@ from django.http import Http404
import urllib
import capa_module
import video_module
import html_module
import schematic_module
import courseware.modules.capa_module
import courseware.modules.video_module
import courseware.modules.vertical_module
import courseware.modules.html_module
import courseware.modules.schematic_module
import courseware.modules.seq_module
from models import StudentModule
......@@ -29,12 +31,18 @@ from django.conf import settings
import content_parser
import sys
from lxml import etree
import uuid
modx_modules={'problem':capa_module.LoncapaModule,
'video':video_module.VideoModule,
'html':html_module.HtmlModule,
'schematic':schematic_module.SchematicModule}
## 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,
'schematic':courseware.modules.schematic_module.SchematicModule}
def make_track_function(request):
def f(event_type, event):
......@@ -44,11 +52,12 @@ def make_track_function(request):
def modx_dispatch(request, module=None, dispatch=None, id=None):
''' Generic view for extensions. '''
# Grab the student information for the module from the database
print module, request.user, id
s = StudentModule.objects.filter(module_type=module,
student=request.user,
module_id=id)
if len(s) == 0:
print "ls404"
print "ls404", module, request.user, id
raise Http404
s=s[0]
......@@ -67,83 +76,25 @@ def modx_dispatch(request, module=None, dispatch=None, id=None):
s.module_id,
ajax_url=ajax_url,
state=s.state,
track_function = make_track_function(request))
track_function = make_track_function(request),
render_function = render_module,
meta = request)
# Let the module handle the AJAX
ajax_return=instance.handle_ajax(dispatch, request.POST)
# Save the state back to the database
s.state=instance.get_state()
s.grade=instance.get_score()['score']
if instance.get_score() != None:
s.grade=instance.get_score()['score']
s.save()
# Return whatever the module wanted to return to the client/caller
return HttpResponse(ajax_return)
def vertical_module(request, module):
''' Layout module which lays out content vertically.
'''
contents=[(e.getAttribute("name"),render_module(request, e)) \
for e in module.childNodes \
if e.nodeType==1]
init_js="".join([e[1]['init_js'] for e in contents if 'init_js' in e[1]])
destroy_js="".join([e[1]['destroy_js'] for e in contents if 'destroy_js' in e[1]])
return {'init_js':init_js,
'destroy_js':destroy_js,
'content':render_to_string('vert_module.html',{'items':contents}),
'type':'vertical'}
def seq_module(request, module):
''' Layout module which lays out content in a temporal sequence
'''
def j(m):
# jsonify contents so it can be embedded in a js array
# We also need to split </script> tags so they don't break
# mid-string
if 'init_js' not in m: m['init_js']=""
if 'type' not in m: m['init_js']=""
content=json.dumps(m['content'])
content=content.replace('</script>', '<"+"/script>')
return {'content':content,
"destroy_js":m['destroy_js'],
'init_js':m['init_js'],
'type':m['type']}
contents=[(e.getAttribute("name"),j(render_module(request, e))) \
for e in module.childNodes \
if e.nodeType==1]
js=""
iid=uuid.uuid1().hex
params={'items':contents,
'id':"seq"}
# TODO/BUG: Destroy JavaScript should only be called for the active view
# This calls it for all the views
#
# To fix this, we'd probably want to have some way of assigning unique
# IDs to sequences.
destroy_js="".join([e[1]['destroy_js'] for e in contents if 'destroy_js' in e[1]])
if module.nodeName == 'sequential':
return {'init_js':js+render_to_string('seq_module.js',params),
"destroy_js":destroy_js,
'content':render_to_string('seq_module.html',params),
'type':'sequential'}
if module.nodeName == 'tab':
params['id'] = 'tab'
return {'init_js':js+render_to_string('tab_module.js',params),
"destroy_js":destroy_js,
'content':render_to_string('tab_module.html',params),
'type':'tab'}
def render_x_module(request, xml_module):
''' Generic module for extensions. This renders to HTML. '''
# Check if problem has an instance in DB
module_type=xml_module.nodeName
module_type=xml_module.tag
module_class=modx_modules[module_type]
module_id=xml_module.getAttribute(module_class.id_attribute)
module_id=xml_module.get('id') #module_class.id_attribute) or ""
# Grab state from database
s = StudentModule.objects.filter(student=request.user,
......@@ -157,11 +108,13 @@ def render_x_module(request, xml_module):
# Create a new instance
ajax_url = '/modx/'+module_type+'/'+module_id+'/'
instance=module_class(xml_module.toxml(),
instance=module_class(etree.tostring(xml_module),
module_id,
ajax_url=ajax_url,
state=state,
track_function = make_track_function(request))
track_function = make_track_function(request),
render_function = render_module,
meta = request)
# If instance wasn't already in the database, create it
if len(s) == 0:
......@@ -179,20 +132,8 @@ def render_x_module(request, xml_module):
return content
module_types={'video':render_x_module,
'html':render_x_module,
'tab':seq_module,
'vertical':vertical_module,
'sequential':seq_module,
'problem':render_x_module,
'schematic':render_x_module
}
def render_module(request, module):
''' Generic dispatch for internal modules. '''
if module==None:
if module==None :
return {"content":""}
if str(module.localName) in module_types:
return module_types[module.localName](request, module)
print "rm404"
raise Http404
return render_x_module(request, module)
......@@ -2,14 +2,14 @@ import random, numpy, math, scipy, sys, StringIO, os, struct, json
from x_module import XModule
import sys
from capa.capa_problem import LoncapaProblem
from courseware.capa.capa_problem import LoncapaProblem
from django.http import Http404
import dateutil
import dateutil.parser
import datetime
import content_parser
import courseware.content_parser as content_parser
from lxml import etree
......@@ -108,8 +108,8 @@ class LoncapaModule(XModule):
return html
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None):
XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function)
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None, render_function = None, meta = None):
XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function, render_function)
self.attempts = 0
self.max_attempts = None
......
......@@ -25,8 +25,8 @@ class HtmlModule(XModule):
textlist=[i for i in textlist if type(i)==str]
return "".join(textlist)
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None):
XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function)
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None, render_function = None, meta = None):
XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function, render_function)
xmltree=etree.fromstring(xml)
self.filename = None
filename_l=xmltree.xpath("/html/@filename")
......
......@@ -18,6 +18,6 @@ class SchematicModule(XModule):
def get_html(self):
return '<input type="hidden" class="schematic" name="{item_id}" height="480" width="640">'.format(item_id=self.item_id)
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None):
XModule.__init__(self, xml, item_id, ajax_url, track_url, state)
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, render_function = None, meta = None):
XModule.__init__(self, xml, item_id, ajax_url, track_url, state, render_function)
from x_module import XModule
from lxml import etree
from django.http import Http404
import json
## TODO: Abstract out from Django
from django.conf import settings
from djangomako.shortcuts import render_to_response, render_to_string
class SequentialModule(XModule):
''' Layout module which lays out content in a temporal sequence
'''
id_attribute = 'id'
def get_state(self):
return json.dumps({ 'position':self.position })
def get_xml_tags():
return ["sequential", 'tab']
def get_html(self):
return self.content
def get_init_js(self):
return self.init_js
def get_destroy_js(self):
return self.destroy_js
def handle_ajax(self, dispatch, get):
print "GET", get
print "DISPATCH", dispatch
if dispatch=='goto_position':
self.position = int(get['position'])
return json.dumps({'success':True})
raise Http404()
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None, render_function = None, meta = None):
XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function, render_function)
xmltree=etree.fromstring(xml)
self.position = 1
if state!=None:
state = json.loads(state)
if 'position' in state: self.position = int(state['position'])
def j(m):
''' jsonify contents so it can be embedded in a js array
We also need to split </script> tags so they don't break
mid-string'''
if 'init_js' not in m: m['init_js']=""
if 'type' not in m: m['init_js']=""
content=json.dumps(m['content'])
content=content.replace('</script>', '<"+"/script>')
return {'content':content,
"destroy_js":m['destroy_js'],
'init_js':m['init_js'],
'type':m['type']}
contents=[(e.get("name"),j(render_function(meta, e))) \
for e in xmltree]
js=""
params={'items':contents,
'id':item_id,
'position': self.position}
# TODO/BUG: Destroy JavaScript should only be called for the active view
# This calls it for all the views
#
# To fix this, we'd probably want to have some way of assigning unique
# IDs to sequences.
destroy_js="".join([e[1]['destroy_js'] for e in contents if 'destroy_js' in e[1]])
if xmltree.tag == 'sequential':
self.init_js=js+render_to_string('seq_module.js',params)
self.destroy_js=destroy_js
self.content=render_to_string('seq_module.html',params)
if xmltree.tag == 'tab':
params['id'] = 'tab'
self.init_js=js+render_to_string('tab_module.js',params)
self.destroy_js=destroy_js
self.content=render_to_string('tab_module.html',params)
from x_module import XModule
from lxml import etree
import json
## TODO: Abstract out from Django
from django.conf import settings
from djangomako.shortcuts import render_to_response, render_to_string
class VerticalModule(XModule):
id_attribute = 'id'
def get_state(self):
return json.dumps({ })
def get_xml_tags():
return "vertical"
def get_html(self):
return render_to_string('vert_module.html',{'items':self.contents})
def get_init_js(self):
return self.init_js_text
def get_destroy_js(self):
return self.destroy_js_text
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None, render_function = None, meta = None):
XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function, render_function)
xmltree=etree.fromstring(xml)
self.contents=[(e.get("name"),self.render_function(meta, e)) \
for e in xmltree]
self.init_js_text="".join([e[1]['init_js'] for e in self.contents if 'init_js' in e[1]])
self.destroy_js_text="".join([e[1]['destroy_js'] for e in self.contents if 'destroy_js' in e[1]])
from x_module import XModule
from lxml import etree
import json
......@@ -7,47 +8,55 @@ from django.conf import settings
from djangomako.shortcuts import render_to_response, render_to_string
class VideoModule(XModule):
id_attribute = 'youtube'
#id_attribute = 'youtube'
video_time = 0
def handle_ajax(self, dispatch, get):
if dispatch == 'time':
self.video_time = int(get['time'])
print self.video_time
return json.dumps("True")
print "GET", get
print "DISPATCH", dispatch
if dispatch=='goto_position':
self.position = int(float(get['position']))
print "NEW POSITION", self.position
return json.dumps({'success':True})
raise Http404()
def get_state(self):
return json.dumps({ 'time':self.video_time })
print "STATE POSITION", self.position
return json.dumps({ 'position':self.position })
def get_xml_tags():
''' Tags in the courseware file guaranteed to correspond to the module '''
return "video"
def video_list(self):
l=self.item_id.split(',')
l=self.youtube.split(',')
l=[i.split(":") for i in l]
return json.dumps(dict(l))
def get_html(self):
return render_to_string('video.html',{'streams':self.video_list(),
'id':self.item_id,
'video_time':self.video_time})
'position':self.position})
def get_init_js(self):
''' JavaScript code to be run when problem is shown. Be aware
that this may happen several times on the same page
(e.g. student switching tabs). Common functions should be put
in the main course .js files for now. '''
print "INIT POSITION", self.position
return render_to_string('video_init.js',{'streams':self.video_list(),
'id':self.item_id,
'video_time':self.video_time})
'position':self.position})
def get_destroy_js(self):
return "videoDestroy();"
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None):
XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function)
print state
if state!=None and "time" not in json.loads(state):
self.video_time = 0
return "videoDestroy(\""+self.item_id+"\");"
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None, render_function = None, meta = None):
XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function, render_function)
self.youtube = etree.XML(xml).get('youtube')
self.position = 0
if state!=None:
state = json.loads(state)
if 'position' in state: self.position = int(float(state['position']))
print "POOSITION IN STATE"
print "LOAD POSITION", self.position
......@@ -39,11 +39,13 @@ class XModule(object):
get is a dictionary-like object '''
return ""
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None):
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None, render_function = None, meta = None):
''' In most cases, you must pass state or xml'''
self.xml=xml
self.item_id=item_id
self.ajax_url=ajax_url
self.track_url=track_url
self.state=state
self.tracker=track_function
self.xml = xml
self.item_id = item_id
self.ajax_url = ajax_url
self.track_url = track_url
self.state = state
self.tracker = track_function
self.render_function = render_function
self.meta = meta
from django.http import HttpResponse
from django.template import Context, loader
from djangomako.shortcuts import render_to_response, render_to_string
from xml.dom.minidom import parse, parseString
import json, os, sys
from django.core.context_processors import csrf
......@@ -14,11 +13,6 @@ import StringIO
from django.http import Http404
import urllib
import capa_module
import video_module
from models import StudentModule
import urllib
......@@ -31,6 +25,11 @@ import uuid
from module_render import *
from lxml import etree
etree.set_default_parser(etree.XMLParser(dtd_validation=False, load_dtd=False,
remove_comments = True))
template_imports={'urllib':urllib}
def profile(request):
......@@ -39,20 +38,23 @@ def profile(request):
if not request.user.is_authenticated():
return redirect('/')
dom=parse(content_parser.course_file(request.user))
dom=content_parser.course_file(request.user)
hw=[]
course = dom.getElementsByTagName('course')[0]
chapters = course.getElementsByTagName('chapter')
course = dom.xpath('//course/@name')[0]
chapters = dom.xpath('//course[@name=$course]/chapter', course=course)
responses=StudentModule.objects.filter(student=request.user)
for c in chapters:
for s in c.getElementsByTagName('section'):
problems=s.getElementsByTagName('problem')
chname=c.get('name')
for s in dom.xpath('//course[@name=$course]/chapter[@name=$chname]/section',
course=course, chname=chname):
problems=dom.xpath('//course[@name=$course]/chapter[@name=$chname]/section[@name=$section]//problem',
course=course, chname=chname, section=s.get('name'))
scores=[]
if len(problems)>0:
for p in problems:
id = p.getAttribute('filename')
id = p.get('filename')
correct = 0
for response in responses:
if response.module_id == id:
......@@ -60,11 +62,11 @@ def profile(request):
correct=response.grade
else:
correct=0
total=capa_module.LoncapaModule(p.toxml(), "id").max_score() # TODO: Add state. Not useful now, but maybe someday problems will have randomized max scores?
total=courseware.modules.capa_module.LoncapaModule(etree.tostring(p), "id").max_score() # TODO: Add state. Not useful now, but maybe someday problems will have randomized max scores?
scores.append((int(correct),total))
score={'course':course.getAttribute('name'),
'section':s.getAttribute("name"),
'chapter':c.getAttribute("name"),
score={'course':course,
'section':s.get("name"),
'chapter':c.get("name"),
'scores':scores,
}
hw.append(score)
......@@ -109,6 +111,7 @@ def index(request, course="6.002 Spring 2012", chapter="Using the System", secti
# Fixes URLs -- we don't get funny encoding characters from spaces
# so they remain readable
## TODO: Properly replace underscores
course=course.replace("_"," ")
chapter=chapter.replace("_"," ")
section=section.replace("_"," ")
......@@ -118,15 +121,13 @@ def index(request, course="6.002 Spring 2012", chapter="Using the System", secti
if course!="6.002 Spring 2012":
return redirect('/')
cf = content_parser.course_file(request.user)
dom=parse(cf)
dom_course=content_parser.dom_select(dom, 'course', course)
dom_chapter=content_parser.dom_select(dom_course, 'chapter', chapter)
dom_section=content_parser.dom_select(dom_chapter, 'section', section)
if dom_section!=None:
module=[e for e in dom_section.childNodes if e.nodeType==1][0]
dom = content_parser.course_file(request.user)
dom_module = dom.xpath("//course[@name=$course]/chapter[@name=$chapter]//section[@name=$section]/*[1]",
course=course, chapter=chapter, section=section)
if len(dom_module) == 0:
module = None
else:
module=None
module = dom_module[0]
accordion=render_accordion(request, course, chapter, section)
......@@ -135,6 +136,8 @@ def index(request, course="6.002 Spring 2012", chapter="Using the System", secti
if 'init_js' not in module:
module['init_js']=''
context={'init':accordion['init_js']+module['init_js'],
'accordion':accordion['content'],
'content':module['content'],
......
settings_old_askbot.py
\ No newline at end of file
import os
import sys
import djcelery
COURSEWARE_ENABLED = True
ASKBOT_ENABLED = True
CSRF_COOKIE_DOMAIN = '127.0.0.1'
# Defaults to be overridden
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
SITE_NAME = "localhost:8000"
DEFAULT_FROM_EMAIL = 'registration@mitx.mit.edu'
DEFAULT_FEEDBACK_EMAIL = 'feedback@mitx.mit.edu'
GENERATE_RANDOM_USER_CREDENTIALS = False
WIKI_REQUIRE_LOGIN_EDIT = True
WIKI_REQUIRE_LOGIN_VIEW = True
PERFSTATS = False
HTTPS = 'on'
MEDIA_URL = ''
MEDIA_ROOT = ''
DEBUG = True
TEMPLATE_DEBUG = DEBUG
ADMINS = (
('Piotr Mitros', 'pmitros@csail.mit.edu'),
)
MANAGERS = ADMINS
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
TIME_ZONE = 'America/Chicago'
# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'en'
SITE_ID = 1
# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True
# If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale
USE_L10N = True
STATIC_URL = '/static/'
# URL prefix for admin static files -- CSS, JavaScript and images.
# Make sure to use a trailing slash.
# Examples: "http://foo.com/static/admin/", "/static/admin/".
ADMIN_MEDIA_PREFIX = '/static/admin/'
# List of finder classes that know how to find static files in
# various locations.
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
# 'django.template.loaders.eggs.Loader',
)
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'track.middleware.TrackMiddleware',
'djangomako.middleware.MakoMiddleware',
#'debug_toolbar.middleware.DebugToolbarMiddleware',
)
ROOT_URLCONF = 'mitx.urls'
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'courseware',
'auth',
'django.contrib.humanize',
'static_template_view',
'staticbook',
'simplewiki',
'track',
'circuit',
'perfstats',
# Uncomment the next line to enable the admin:
# 'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
# 'django.contrib.admindocs',
)
# A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to
# the site admins on every HTTP 500 error.
# See http://docs.djangoproject.com/en/dev/topics/logging for
# more details on how to customize your logging configuration.
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler'
}
},
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
},
}
}
#TRACK_DIR = None
DEBUG_TRACK_LOG = False
# Maximum length of a tracking string. We don't want e.g. a file upload in our log
TRACK_MAX_EVENT = 1000
# Maximum length of log file before starting a new one.
MAXLOG = 500
# Our parent dir (mitx_all) is the BASE_DIR
BASE_DIR = os.path.abspath(os.path.join(__file__, "..", ".."))
# Make sure we execute correctly regardless of where we're called from
execfile(os.path.join(BASE_DIR, "settings.py"))
if PERFSTATS :
MIDDLEWARE_CLASSES = ( 'perfstats.middleware.ProfileMiddleware',) + MIDDLEWARE_CLASSES
if 'TRACK_DIR' not in locals():
TRACK_DIR = BASE_DIR+'/track_dir/'
if 'STATIC_ROOT' not in locals():
STATIC_ROOT = BASE_DIR+'/staticroot/'
if 'DATA_DIR' not in locals():
DATA_DIR = BASE_DIR+'/data/'
if 'TEXTBOOK_DIR' not in locals():
TEXTBOOK_DIR = BASE_DIR+'/textbook/'
if 'TEMPLATE_DIRS' not in locals():
TEMPLATE_DIRS = (
BASE_DIR+'/templates/',
DATA_DIR+'/templates',
TEXTBOOK_DIR,
)
if 'STATICFILES_DIRS' not in locals():
STATICFILES_DIRS = (
BASE_DIR+'/3rdParty/static',
BASE_DIR+'/static',
)
if 'ASKBOT_EXTRA_SKINS_DIR' not in locals():
ASKBOT_EXTRA_SKINS_DIR = BASE_DIR+'/askbot-devel/askbot/skins'
if 'ASKBOT_DIR' not in locals():
ASKBOT_DIR = BASE_DIR+'/askbot-devel'
sys.path.append(ASKBOT_DIR)
import askbot
import site
STATICFILES_DIRS = STATICFILES_DIRS + ( ASKBOT_DIR+'/askbot/skins',)
# Needed for Askbot
# Critical TODO: Move to S3
MEDIA_URL = '/discussion/upfiles/'
MEDIA_ROOT = ASKBOT_DIR+'/askbot/upfiles'
ASKBOT_ROOT = os.path.dirname(askbot.__file__)
site.addsitedir(os.path.join(os.path.dirname(askbot.__file__), 'deps'))
TEMPLATE_LOADERS = TEMPLATE_LOADERS + ('askbot.skins.loaders.filesystem_load_template_source',)
MIDDLEWARE_CLASSES = MIDDLEWARE_CLASSES + (
'askbot.middleware.anon_user.ConnectToSessionMessagesMiddleware',
'askbot.middleware.forum_mode.ForumModeMiddleware',
'askbot.middleware.cancel.CancelActionMiddleware',
'django.middleware.transaction.TransactionMiddleware',
#'debug_toolbar.middleware.DebugToolbarMiddleware',
'askbot.middleware.view_log.ViewLogMiddleware',
'askbot.middleware.spaceless.SpacelessMiddleware',
# 'askbot.middleware.pagesize.QuestionsPageSizeMiddleware',
)
FILE_UPLOAD_TEMP_DIR = os.path.join(os.path.dirname(__file__), 'tmp').replace('\\','/')
FILE_UPLOAD_HANDLERS = (
'django.core.files.uploadhandler.MemoryFileUploadHandler',
'django.core.files.uploadhandler.TemporaryFileUploadHandler',
)
ASKBOT_ALLOWED_UPLOAD_FILE_TYPES = ('.jpg', '.jpeg', '.gif', '.bmp', '.png', '.tiff')
ASKBOT_MAX_UPLOAD_FILE_SIZE = 1024 * 1024 #result in bytes
# ASKBOT_FILE_UPLOAD_DIR = os.path.join(os.path.dirname(__file__), 'askbot', 'upfiles')
DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'
PROJECT_ROOT = os.path.dirname(__file__)
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.request',
'askbot.context.application_settings',
#'django.core.context_processors.i18n',
'askbot.user_messages.context_processors.user_messages',#must be before auth
'django.core.context_processors.auth', #this is required for admin
'django.core.context_processors.csrf', #necessary for csrf protection
)
INSTALLED_APPS = INSTALLED_APPS + (
'django.contrib.sitemaps',
'django.contrib.admin',
'south',
'askbot.deps.livesettings',
'askbot',
#'keyedcache', # TODO: Main askbot tree has this installed, but we get intermittent errors if we include it.
'robots',
'django_countries',
'djcelery',
'djkombu',
'followit',
)
CACHE_MIDDLEWARE_ANONYMOUS_ONLY = True
ASKBOT_URL = 'discussion/'
LOGIN_REDIRECT_URL = '/'
LOGIN_URL = '/'
# ASKBOT_UPLOADED_FILES_URL = '%s%s' % (ASKBOT_URL, 'upfiles/')
ALLOW_UNICODE_SLUGS = False
ASKBOT_USE_STACKEXCHANGE_URLS = False #mimic url scheme of stackexchange
ASKBOT_CSS_DEVEL = True
# Celery Settings
BROKER_TRANSPORT = "djkombu.transport.DatabaseTransport"
CELERY_ALWAYS_EAGER = True
djcelery.setup_loader()
......@@ -48,7 +48,7 @@ def root_redirect(request):
try:
root = Article.get_root()
except:
err = not_found(request, 'mainpage')
err = not_found(request, '/')
return err
return HttpResponseRedirect(reverse('wiki_view', args=(root.get_url())))
......@@ -92,7 +92,7 @@ def create(request, wiki_url):
#except ShouldHaveExactlyOneRootSlug, (e):
except:
if Article.objects.filter(parent=None).count() > 0:
return HttpResponseRedirect(reverse('wiki_view', args=('',)))
return HttpResponseRedirect(reverse('wiki_view', args=('/',)))
# Root not found...
path = []
url_path = [""]
......@@ -380,7 +380,7 @@ def fetch_from_url(request, url):
try:
root = Article.get_root()
except:
err = not_found(request, '')
err = not_found(request, '/')
return (article, path, err)
if url_path and root.slug == url_path[0]:
......
......@@ -8,7 +8,12 @@ from django.shortcuts import redirect
from django.core.context_processors import csrf
#valid_templates=['index.html', 'staff.html', 'info.html', 'credits.html']
valid_templates=['mitx_global.html', 'index.html']
valid_templates=['mitx_global.html',
'index.html',
'tos.html',
'privacy.html',
'honor.html',
'copyright.html']
def index(request, template):
csrf_token = csrf(request)['csrf_token']
......
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