Moving __init__ functions in xmodule to top of class for consistancy
This commit is contained in:
@@ -72,6 +72,102 @@ class CapaModule(XModule):
|
||||
'''
|
||||
icon_class = 'problem'
|
||||
|
||||
def __init__(self, system, location, definition, instance_state=None, shared_state=None, **kwargs):
|
||||
XModule.__init__(self, system, location, definition, instance_state, shared_state, **kwargs)
|
||||
|
||||
self.attempts = 0
|
||||
self.max_attempts = None
|
||||
|
||||
dom2 = etree.fromstring(definition['data'])
|
||||
|
||||
self.explanation = "problems/" + only_one(dom2.xpath('/problem/@explain'),
|
||||
default="closed")
|
||||
# TODO: Should be converted to: self.explanation=only_one(dom2.xpath('/problem/@explain'), default="closed")
|
||||
self.explain_available = only_one(dom2.xpath('/problem/@explain_available'))
|
||||
|
||||
display_due_date_string = self.metadata.get('due', None)
|
||||
if display_due_date_string is not None:
|
||||
self.display_due_date = dateutil.parser.parse(display_due_date_string)
|
||||
#log.debug("Parsed " + display_due_date_string + " to " + str(self.display_due_date))
|
||||
else:
|
||||
self.display_due_date = None
|
||||
|
||||
grace_period_string = self.metadata.get('graceperiod', None)
|
||||
if grace_period_string is not None and self.display_due_date:
|
||||
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 = only_one(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 = self.metadata.get('showanwser', 'closed')
|
||||
|
||||
if self.show_answer == "":
|
||||
self.show_answer = "closed"
|
||||
|
||||
self.rerandomize = self.metadata.get('rerandomize', 'always')
|
||||
if self.rerandomize == "" or self.rerandomize == "always" or self.rerandomize == "true":
|
||||
self.rerandomize = "always"
|
||||
elif self.rerandomize == "false" or self.rerandomize == "per_student":
|
||||
self.rerandomize = "per_student"
|
||||
elif self.rerandomize == "never":
|
||||
self.rerandomize = "never"
|
||||
else:
|
||||
raise Exception("Invalid rerandomize attribute " + self.rerandomize)
|
||||
|
||||
if instance_state != None:
|
||||
instance_state = json.loads(instance_state)
|
||||
if instance_state != None and 'attempts' in instance_state:
|
||||
self.attempts = instance_state['attempts']
|
||||
|
||||
# TODO: Should be: self.filename=only_one(dom2.xpath('/problem/@filename'))
|
||||
self.filename = "problems/" + only_one(dom2.xpath('/problem/@filename')) + ".xml"
|
||||
self.name = only_one(dom2.xpath('/problem/@name'))
|
||||
|
||||
weight_string = only_one(dom2.xpath('/problem/@weight'))
|
||||
if weight_string:
|
||||
self.weight = float(weight_string)
|
||||
else:
|
||||
self.weight = 1
|
||||
|
||||
if self.rerandomize == 'never':
|
||||
seed = 1
|
||||
elif self.rerandomize == "per_student" and hasattr(system, 'id'):
|
||||
seed = system.id
|
||||
else:
|
||||
seed = None
|
||||
try:
|
||||
fp = self.system.filestore.open(self.filename)
|
||||
except Exception:
|
||||
log.exception('cannot open file %s' % self.filename)
|
||||
if self.system.DEBUG:
|
||||
# create a dummy problem instead of failing
|
||||
fp = StringIO.StringIO('<problem><text><font color="red" size="+2">Problem file %s is missing</font></text></problem>' % self.filename)
|
||||
fp.name = "StringIO"
|
||||
else:
|
||||
raise
|
||||
try:
|
||||
self.lcp = LoncapaProblem(fp, self.location.html_id(), instance_state, seed=seed, system=self.system)
|
||||
except Exception:
|
||||
msg = 'cannot create LoncapaProblem %s' % self.filename
|
||||
log.exception(msg)
|
||||
if self.system.DEBUG:
|
||||
msg = '<p>%s</p>' % msg.replace('<', '<')
|
||||
msg += '<p><pre>%s</pre></p>' % traceback.format_exc().replace('<', '<')
|
||||
# create a dummy problem with error message instead of failing
|
||||
fp = StringIO.StringIO('<problem><text><font color="red" size="+2">Problem file %s has an error:</font>%s</text></problem>' % (self.filename, msg))
|
||||
fp.name = "StringIO"
|
||||
self.lcp = LoncapaProblem(fp, self.location.html_id(), instance_state, seed=seed, system=self.system)
|
||||
else:
|
||||
raise
|
||||
|
||||
def get_instance_state(self):
|
||||
state = self.lcp.get_state()
|
||||
state['attempts'] = self.attempts
|
||||
@@ -171,102 +267,6 @@ class CapaModule(XModule):
|
||||
|
||||
return html
|
||||
|
||||
def __init__(self, system, location, definition, instance_state=None, shared_state=None, **kwargs):
|
||||
XModule.__init__(self, system, location, definition, instance_state, shared_state, **kwargs)
|
||||
|
||||
self.attempts = 0
|
||||
self.max_attempts = None
|
||||
|
||||
dom2 = etree.fromstring(definition['data'])
|
||||
|
||||
self.explanation = "problems/" + only_one(dom2.xpath('/problem/@explain'),
|
||||
default="closed")
|
||||
# TODO: Should be converted to: self.explanation=only_one(dom2.xpath('/problem/@explain'), default="closed")
|
||||
self.explain_available = only_one(dom2.xpath('/problem/@explain_available'))
|
||||
|
||||
display_due_date_string = self.metadata.get('due', None)
|
||||
if display_due_date_string is not None:
|
||||
self.display_due_date = dateutil.parser.parse(display_due_date_string)
|
||||
#log.debug("Parsed " + display_due_date_string + " to " + str(self.display_due_date))
|
||||
else:
|
||||
self.display_due_date = None
|
||||
|
||||
grace_period_string = self.metadata.get('graceperiod', None)
|
||||
if grace_period_string is not None and self.display_due_date:
|
||||
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 = only_one(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 = self.metadata.get('showanwser', 'closed')
|
||||
|
||||
if self.show_answer == "":
|
||||
self.show_answer = "closed"
|
||||
|
||||
self.rerandomize = self.metadata.get('rerandomize', 'always')
|
||||
if self.rerandomize == "" or self.rerandomize == "always" or self.rerandomize == "true":
|
||||
self.rerandomize = "always"
|
||||
elif self.rerandomize == "false" or self.rerandomize == "per_student":
|
||||
self.rerandomize = "per_student"
|
||||
elif self.rerandomize == "never":
|
||||
self.rerandomize = "never"
|
||||
else:
|
||||
raise Exception("Invalid rerandomize attribute " + self.rerandomize)
|
||||
|
||||
if instance_state != None:
|
||||
instance_state = json.loads(instance_state)
|
||||
if instance_state != None and 'attempts' in instance_state:
|
||||
self.attempts = instance_state['attempts']
|
||||
|
||||
# TODO: Should be: self.filename=only_one(dom2.xpath('/problem/@filename'))
|
||||
self.filename = "problems/" + only_one(dom2.xpath('/problem/@filename')) + ".xml"
|
||||
self.name = only_one(dom2.xpath('/problem/@name'))
|
||||
|
||||
weight_string = only_one(dom2.xpath('/problem/@weight'))
|
||||
if weight_string:
|
||||
self.weight = float(weight_string)
|
||||
else:
|
||||
self.weight = 1
|
||||
|
||||
if self.rerandomize == 'never':
|
||||
seed = 1
|
||||
elif self.rerandomize == "per_student" and hasattr(system, 'id'):
|
||||
seed = system.id
|
||||
else:
|
||||
seed = None
|
||||
try:
|
||||
fp = self.system.filestore.open(self.filename)
|
||||
except Exception:
|
||||
log.exception('cannot open file %s' % self.filename)
|
||||
if self.system.DEBUG:
|
||||
# create a dummy problem instead of failing
|
||||
fp = StringIO.StringIO('<problem><text><font color="red" size="+2">Problem file %s is missing</font></text></problem>' % self.filename)
|
||||
fp.name = "StringIO"
|
||||
else:
|
||||
raise
|
||||
try:
|
||||
self.lcp = LoncapaProblem(fp, self.location.html_id(), instance_state, seed=seed, system=self.system)
|
||||
except Exception:
|
||||
msg = 'cannot create LoncapaProblem %s' % self.filename
|
||||
log.exception(msg)
|
||||
if self.system.DEBUG:
|
||||
msg = '<p>%s</p>' % msg.replace('<', '<')
|
||||
msg += '<p><pre>%s</pre></p>' % traceback.format_exc().replace('<', '<')
|
||||
# create a dummy problem with error message instead of failing
|
||||
fp = StringIO.StringIO('<problem><text><font color="red" size="+2">Problem file %s has an error:</font>%s</text></problem>' % (self.filename, msg))
|
||||
fp.name = "StringIO"
|
||||
self.lcp = LoncapaProblem(fp, self.location.html_id(), instance_state, seed=seed, system=self.system)
|
||||
else:
|
||||
raise
|
||||
|
||||
def handle_ajax(self, dispatch, get):
|
||||
'''
|
||||
This is called by courseware.module_render, to handle an AJAX call.
|
||||
|
||||
@@ -18,6 +18,22 @@ class_priority = ['video', 'problem']
|
||||
class SequenceModule(XModule):
|
||||
''' Layout module which lays out content in a temporal sequence
|
||||
'''
|
||||
|
||||
def __init__(self, system, location, definition, instance_state=None, shared_state=None, **kwargs):
|
||||
XModule.__init__(self, system, location, definition, instance_state, shared_state, **kwargs)
|
||||
self.position = 1
|
||||
|
||||
if instance_state is not None:
|
||||
state = json.loads(instance_state)
|
||||
if 'position' in state:
|
||||
self.position = int(state['position'])
|
||||
|
||||
# if position is specified in system, then use that instead
|
||||
if system.get('position'):
|
||||
self.position = int(system.get('position'))
|
||||
|
||||
self.rendered = False
|
||||
|
||||
def get_instance_state(self):
|
||||
return json.dumps({'position': self.position})
|
||||
|
||||
@@ -81,21 +97,6 @@ class SequenceModule(XModule):
|
||||
new_class = c
|
||||
return new_class
|
||||
|
||||
def __init__(self, system, location, definition, instance_state=None, shared_state=None, **kwargs):
|
||||
XModule.__init__(self, system, location, definition, instance_state, shared_state, **kwargs)
|
||||
self.position = 1
|
||||
|
||||
if instance_state is not None:
|
||||
state = json.loads(instance_state)
|
||||
if 'position' in state:
|
||||
self.position = int(state['position'])
|
||||
|
||||
# if position is specified in system, then use that instead
|
||||
if system.get('position'):
|
||||
self.position = int(system.get('position'))
|
||||
|
||||
self.rendered = False
|
||||
|
||||
|
||||
class SequenceDescriptor(MakoModuleDescriptor, XmlDescriptor):
|
||||
mako_template = 'widgets/sequence-edit.html'
|
||||
|
||||
@@ -26,8 +26,6 @@ class CustomTagModule(XModule):
|
||||
Renders to::
|
||||
More information given in <a href="/book/234">the text</a>
|
||||
"""
|
||||
def get_html(self):
|
||||
return self.html
|
||||
|
||||
def __init__(self, system, location, definition, instance_state=None, shared_state=None, **kwargs):
|
||||
XModule.__init__(self, system, location, definition, instance_state, shared_state, **kwargs)
|
||||
@@ -36,6 +34,8 @@ class CustomTagModule(XModule):
|
||||
params = dict(xmltree.items())
|
||||
self.html = self.system.render_template(filename, params, namespace='custom_tags')
|
||||
|
||||
def get_html(self):
|
||||
return self.html
|
||||
|
||||
class CustomTagDescriptor(RawDescriptor):
|
||||
module_class = CustomTagModule
|
||||
|
||||
@@ -9,6 +9,11 @@ class_priority = ['video', 'problem']
|
||||
|
||||
class VerticalModule(XModule):
|
||||
''' Layout module for laying out submodules vertically.'''
|
||||
|
||||
def __init__(self, system, location, definition, instance_state=None, shared_state=None, **kwargs):
|
||||
XModule.__init__(self, system, location, definition, instance_state, shared_state, **kwargs)
|
||||
self.contents = None
|
||||
|
||||
def get_html(self):
|
||||
if self.contents is None:
|
||||
self.contents = [child.get_html() for child in self.get_display_items()]
|
||||
@@ -32,10 +37,6 @@ class VerticalModule(XModule):
|
||||
new_class = c
|
||||
return new_class
|
||||
|
||||
def __init__(self, system, location, definition, instance_state=None, shared_state=None, **kwargs):
|
||||
XModule.__init__(self, system, location, definition, instance_state, shared_state, **kwargs)
|
||||
self.contents = None
|
||||
|
||||
|
||||
class VerticalDescriptor(SequenceDescriptor):
|
||||
module_class = VerticalModule
|
||||
|
||||
@@ -13,6 +13,18 @@ class VideoModule(XModule):
|
||||
video_time = 0
|
||||
icon_class = 'video'
|
||||
|
||||
def __init__(self, system, location, definition, instance_state=None, shared_state=None, **kwargs):
|
||||
XModule.__init__(self, system, location, definition, instance_state, shared_state, **kwargs)
|
||||
xmltree = etree.fromstring(self.definition['data'])
|
||||
self.youtube = xmltree.get('youtube')
|
||||
self.name = xmltree.get('name')
|
||||
self.position = 0
|
||||
|
||||
if instance_state is not None:
|
||||
state = json.loads(instance_state)
|
||||
if 'position' in state:
|
||||
self.position = int(float(state['position']))
|
||||
|
||||
def handle_ajax(self, dispatch, get):
|
||||
'''
|
||||
Handle ajax calls to this video.
|
||||
@@ -52,18 +64,6 @@ class VideoModule(XModule):
|
||||
'name': self.name,
|
||||
})
|
||||
|
||||
def __init__(self, system, location, definition, instance_state=None, shared_state=None, **kwargs):
|
||||
XModule.__init__(self, system, location, definition, instance_state, shared_state, **kwargs)
|
||||
xmltree = etree.fromstring(self.definition['data'])
|
||||
self.youtube = xmltree.get('youtube')
|
||||
self.name = xmltree.get('name')
|
||||
self.position = 0
|
||||
|
||||
if instance_state is not None:
|
||||
state = json.loads(instance_state)
|
||||
if 'position' in state:
|
||||
self.position = int(float(state['position']))
|
||||
|
||||
|
||||
class VideoDescriptor(RawDescriptor):
|
||||
module_class = VideoModule
|
||||
|
||||
@@ -189,6 +189,46 @@ class XModuleDescriptor(Plugin):
|
||||
# A list of metadata that this module can inherit from its parent module
|
||||
inheritable_metadata = ('graded', 'due', 'graceperiod', 'showanswer', 'rerandomize')
|
||||
|
||||
def __init__(self,
|
||||
system,
|
||||
definition=None,
|
||||
**kwargs):
|
||||
"""
|
||||
Construct a new XModuleDescriptor. The only required arguments are the
|
||||
system, used for interaction with external resources, and the definition,
|
||||
which specifies all the data needed to edit and display the problem (but none
|
||||
of the associated metadata that handles recordkeeping around the problem).
|
||||
|
||||
This allows for maximal flexibility to add to the interface while preserving
|
||||
backwards compatibility.
|
||||
|
||||
system: An XModuleSystem for interacting with external resources
|
||||
definition: A dict containing `data` and `children` representing the problem definition
|
||||
|
||||
Current arguments passed in kwargs:
|
||||
location: A keystore.Location object indicating the name and ownership of this problem
|
||||
shared_state_key: The key to use for sharing StudentModules with other
|
||||
modules of this type
|
||||
metadata: A dictionary containing the following optional keys:
|
||||
goals: A list of strings of learning goals associated with this module
|
||||
display_name: The name to use for displaying this module to the user
|
||||
format: The format of this module ('Homework', 'Lab', etc)
|
||||
graded (bool): Whether this module is should be graded or not
|
||||
due (string): The due date for this module
|
||||
graceperiod (string): The amount of grace period to allow when enforcing the due date
|
||||
showanswer (string): When to show answers for this module
|
||||
rerandomize (string): When to generate a newly randomized instance of the module data
|
||||
"""
|
||||
self.system = system
|
||||
self.definition = definition if definition is not None else {}
|
||||
self.name = Location(kwargs.get('location')).name
|
||||
self.type = Location(kwargs.get('location')).category
|
||||
self.url = Location(kwargs.get('location')).url()
|
||||
self.metadata = kwargs.get('metadata', {})
|
||||
self.shared_state_key = kwargs.get('shared_state_key')
|
||||
|
||||
self._child_instances = None
|
||||
|
||||
@staticmethod
|
||||
def load_from_json(json_data, system, default_class=None):
|
||||
"""
|
||||
@@ -269,45 +309,6 @@ class XModuleDescriptor(Plugin):
|
||||
"""
|
||||
return self.js_module
|
||||
|
||||
def __init__(self,
|
||||
system,
|
||||
definition=None,
|
||||
**kwargs):
|
||||
"""
|
||||
Construct a new XModuleDescriptor. The only required arguments are the
|
||||
system, used for interaction with external resources, and the definition,
|
||||
which specifies all the data needed to edit and display the problem (but none
|
||||
of the associated metadata that handles recordkeeping around the problem).
|
||||
|
||||
This allows for maximal flexibility to add to the interface while preserving
|
||||
backwards compatibility.
|
||||
|
||||
system: An XModuleSystem for interacting with external resources
|
||||
definition: A dict containing `data` and `children` representing the problem definition
|
||||
|
||||
Current arguments passed in kwargs:
|
||||
location: A keystore.Location object indicating the name and ownership of this problem
|
||||
shared_state_key: The key to use for sharing StudentModules with other
|
||||
modules of this type
|
||||
metadata: A dictionary containing the following optional keys:
|
||||
goals: A list of strings of learning goals associated with this module
|
||||
display_name: The name to use for displaying this module to the user
|
||||
format: The format of this module ('Homework', 'Lab', etc)
|
||||
graded (bool): Whether this module is should be graded or not
|
||||
due (string): The due date for this module
|
||||
graceperiod (string): The amount of grace period to allow when enforcing the due date
|
||||
showanswer (string): When to show answers for this module
|
||||
rerandomize (string): When to generate a newly randomized instance of the module data
|
||||
"""
|
||||
self.system = system
|
||||
self.definition = definition if definition is not None else {}
|
||||
self.name = Location(kwargs.get('location')).name
|
||||
self.type = Location(kwargs.get('location')).category
|
||||
self.url = Location(kwargs.get('location')).url()
|
||||
self.metadata = kwargs.get('metadata', {})
|
||||
self.shared_state_key = kwargs.get('shared_state_key')
|
||||
|
||||
self._child_instances = None
|
||||
|
||||
def inherit_metadata(self, metadata):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user