Changed due date to be display_due_date and close_date. Controlled with due and graceperiod attributes
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import json
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
|
||||
from datetime import timedelta
|
||||
from lxml import etree
|
||||
from mako.template import Template
|
||||
from mako.lookup import TemplateLookup
|
||||
@@ -20,6 +22,20 @@ TODO: Shift everything from xml.dom.minidom to XPath (or XQuery)
|
||||
|
||||
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 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 fasthash(string):
|
||||
m = hashlib.new("md4")
|
||||
m.update(string)
|
||||
@@ -98,7 +114,7 @@ def propogate_downward_tag(element, attribute_name, parent_attribute = None):
|
||||
child (A) already has that attribute, A will keep the same attribute and
|
||||
all of A's children will inherit A's attribute. This is a recursive call.'''
|
||||
|
||||
if (parent_attribute == None): #This is the entry call. Select all due elements
|
||||
if (parent_attribute == None): #This is the entry call. Select all elements with this attribute
|
||||
all_attributed_elements = element.xpath("//*[@" + attribute_name +"]")
|
||||
for attributed_element in all_attributed_elements:
|
||||
attribute_value = attributed_element.get(attribute_name)
|
||||
@@ -106,7 +122,7 @@ def propogate_downward_tag(element, attribute_name, parent_attribute = None):
|
||||
propogate_downward_tag(child_element, attribute_name, attribute_value)
|
||||
else:
|
||||
'''The hack below is because we would get _ContentOnlyELements from the
|
||||
iterator that can't have due dates set. We can't find API for it. If we
|
||||
iterator that can't have attributes set. We can't find API for it. If we
|
||||
ever have an element which subclasses BaseElement, we will not tag it'''
|
||||
if not element.get(attribute_name) and type(element) == etree._Element:
|
||||
element.set(attribute_name, parent_attribute)
|
||||
@@ -133,6 +149,7 @@ def course_file(user):
|
||||
id_tag(tree)
|
||||
propogate_downward_tag(tree, "due")
|
||||
propogate_downward_tag(tree, "graded")
|
||||
propogate_downward_tag(tree, "graceperiod")
|
||||
return tree
|
||||
|
||||
def module_xml(coursefile, module, id_tag, module_id):
|
||||
@@ -170,7 +187,7 @@ def toc_from_xml(dom, active_chapter, active_section):
|
||||
sections.append({'name':s.get("name") or "",
|
||||
'time':s.get("time") or "",
|
||||
'format':s.get("format") or "",
|
||||
'due':s.get("due") or "",
|
||||
'due':s.get("display_due_date") or "",
|
||||
'active':(c.get("name")==active_chapter and \
|
||||
s.get("name")==active_section)})
|
||||
ch.append({'name':c.get("name"),
|
||||
|
||||
@@ -119,18 +119,26 @@ class LoncapaModule(XModule):
|
||||
|
||||
self.attempts = 0
|
||||
self.max_attempts = None
|
||||
self.due_date = None
|
||||
|
||||
|
||||
dom2 = etree.fromstring(xml)
|
||||
|
||||
self.explanation=content_parser.item(dom2.xpath('/problem/@explain'), default="closed")
|
||||
self.explain_available=content_parser.item(dom2.xpath('/problem/@explain_available'))
|
||||
|
||||
self.due_date=content_parser.item(dom2.xpath('/problem/@due'))
|
||||
if len(self.due_date)>0:
|
||||
self.due_date=dateutil.parser.parse(self.due_date)
|
||||
display_due_date_string=content_parser.item(dom2.xpath('/problem/@due'))
|
||||
if len(display_due_date_string)>0:
|
||||
self.display_due_date=dateutil.parser.parse(display_due_date_string)
|
||||
else:
|
||||
self.due_date=None
|
||||
self.display_due_date=None
|
||||
|
||||
|
||||
grace_period_string = content_parser.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.close_date = self.display_due_date + self.grace_period
|
||||
else:
|
||||
self.grace_period = None
|
||||
self.close_date = self.display_due_date
|
||||
|
||||
self.max_attempts=content_parser.item(dom2.xpath('/problem/@attempts'))
|
||||
if len(self.max_attempts)>0:
|
||||
@@ -166,7 +174,7 @@ class LoncapaModule(XModule):
|
||||
def handle_ajax(self, dispatch, get):
|
||||
if dispatch=='problem_get':
|
||||
response = self.get_problem(get)
|
||||
elif False: #self.due_date >
|
||||
elif False: #self.close_date >
|
||||
return json.dumps({"error":"Past due date"})
|
||||
elif dispatch=='problem_check':
|
||||
response = self.check_problem(get)
|
||||
@@ -184,7 +192,7 @@ class LoncapaModule(XModule):
|
||||
''' Is the student still allowed to submit answers? '''
|
||||
if self.attempts == self.max_attempts:
|
||||
return True
|
||||
if self.due_date != None and datetime.datetime.utcnow() > self.due_date:
|
||||
if self.close_date != None and datetime.datetime.utcnow() > self.close_date:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user