Commit 97a9a66c by Calen Pennington

Move CAPA problem specific xml parsing utilities out of content_parser into xmodule

parent c76bab6f
import os
import os.path
import capa_module
import html_module
import schematic_module
......@@ -9,8 +6,6 @@ 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__
#
......
......@@ -4,7 +4,9 @@ import dateutil.parser
import json
import logging
import traceback
import re
from datetime import timedelta
from lxml import etree
## TODO: Abstract out from Django
......@@ -12,11 +14,29 @@ from mitxmako.shortcuts import render_to_string
from x_module import XModule, XModuleDescriptor
from capa.capa_problem import LoncapaProblem, StudentInputError
import courseware.content_parser as content_parser
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:
return default
elif len(l)==1:
return process(l[0])
else:
raise Exception('Malformed XML')
def parse_timedelta(time_str):
parts = TIMEDELTA_REGEX.match(time_str)
if not parts:
return
parts = parts.groupdict()
time_params = {}
for (name, param) in parts.iteritems():
if param:
time_params[name] = int(param)
return timedelta(**time_params)
class ComplexEncoder(json.JSONEncoder):
def default(self, obj):
......@@ -132,11 +152,11 @@ class Module(XModule):
dom2 = etree.fromstring(xml)
self.explanation="problems/"+content_parser.item(dom2.xpath('/problem/@explain'), default="closed")
# TODO: Should be converted to: self.explanation=content_parser.item(dom2.xpath('/problem/@explain'), default="closed")
self.explain_available=content_parser.item(dom2.xpath('/problem/@explain_available'))
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'))
display_due_date_string=content_parser.item(dom2.xpath('/problem/@due'))
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)
#log.debug("Parsed " + display_due_date_string + " to " + str(self.display_due_date))
......@@ -144,27 +164,27 @@ class Module(XModule):
self.display_due_date=None
grace_period_string = content_parser.item(dom2.xpath('/problem/@graceperiod'))
grace_period_string = item(dom2.xpath('/problem/@graceperiod'))
if len(grace_period_string)>0 and self.display_due_date:
self.grace_period = content_parser.parse_timedelta(grace_period_string)
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))
else:
self.grace_period = None
self.close_date = self.display_due_date
self.max_attempts=content_parser.item(dom2.xpath('/problem/@attempts'))
self.max_attempts=item(dom2.xpath('/problem/@attempts'))
if len(self.max_attempts)>0:
self.max_attempts=int(self.max_attempts)
else:
self.max_attempts=None
self.show_answer=content_parser.item(dom2.xpath('/problem/@showanswer'))
self.show_answer=item(dom2.xpath('/problem/@showanswer'))
if self.show_answer=="":
self.show_answer="closed"
self.rerandomize=content_parser.item(dom2.xpath('/problem/@rerandomize'))
self.rerandomize=item(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":
......@@ -179,10 +199,10 @@ class Module(XModule):
if state!=None and 'attempts' in state:
self.attempts=state['attempts']
# TODO: Should be: self.filename=content_parser.item(dom2.xpath('/problem/@filename'))
self.filename= "problems/"+content_parser.item(dom2.xpath('/problem/@filename'))+".xml"
self.name=content_parser.item(dom2.xpath('/problem/@name'))
self.weight=content_parser.item(dom2.xpath('/problem/@weight'))
# 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'))
if self.rerandomize == 'never':
seed = 1
else:
......
......@@ -9,26 +9,20 @@ Does some caching (to be explained).
import logging
import os
import re
import sys
import urllib
from datetime import timedelta
from lxml import etree
from util.memcache import fasthash
try: # This lets us do __name__ == ='__main__'
from django.conf import settings
from django.conf import settings
from student.models import UserProfile
from student.models import UserTestGroup
from mitxmako.shortcuts import render_to_string
from util.cache import cache
from multicourse import multicourse_settings
import xmodule
except:
print "Could not import/content_parser"
settings = None
from student.models import UserProfile
from student.models import UserTestGroup
from mitxmako.shortcuts import render_to_string
from util.cache import cache
from multicourse import multicourse_settings
import xmodule
''' This file will eventually form an abstraction layer between the
course XML file and the rest of the system.
......@@ -41,24 +35,9 @@ class ContentException(Exception):
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 format_url_params(params):
return [ urllib.quote(string.replace(' ','_')) for string in params ]
def parse_timedelta(time_str):
parts = timedelta_regex.match(time_str)
if not parts:
return
parts = parts.groupdict()
time_params = {}
for (name, param) in parts.iteritems():
if param:
time_params[name] = int(param)
return timedelta(**time_params)
def xpath(xml, query_string, **args):
''' Safe xpath query into an xml tree:
* xml is the tree.
......@@ -94,14 +73,6 @@ 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 id_tag(course):
''' Tag all course elements with unique IDs '''
default_ids = xmodule.get_default_ids()
......
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