Commit db57dc30 by Bridger Maxwell

Changed due date to be display_due_date and close_date. Controlled with due and…

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