137 lines
4.3 KiB
Python
137 lines
4.3 KiB
Python
from lxml import etree
|
|
|
|
def dummy_track(event_type, event):
|
|
pass
|
|
|
|
class XModule(object):
|
|
''' Implements a generic learning module.
|
|
Initialized on access with __init__, first time with state=None, and
|
|
then with state
|
|
|
|
See the HTML module for a simple example
|
|
'''
|
|
id_attribute='id' # An attribute guaranteed to be unique
|
|
|
|
@classmethod
|
|
def get_xml_tags(c):
|
|
''' Tags in the courseware file guaranteed to correspond to the module '''
|
|
return []
|
|
|
|
@classmethod
|
|
def get_usage_tags(c):
|
|
''' We should convert to a real module system
|
|
For now, this tells us whether we use this as an xmodule, a CAPA response type
|
|
or a CAPA input type '''
|
|
return ['xmodule']
|
|
|
|
def get_name():
|
|
name = self.__xmltree.get(name)
|
|
if name:
|
|
return name
|
|
else:
|
|
raise "We should iterate through children and find a default name"
|
|
|
|
def rendered_children(self):
|
|
'''
|
|
Render all children.
|
|
This really ought to return a list of xmodules, instead of dictionaries
|
|
'''
|
|
children = [self.render_function(e) for e in self.__xmltree]
|
|
return children
|
|
|
|
def __init__(self, system = None, xml = None, item_id = None,
|
|
json = None, track_url=None, state=None):
|
|
''' In most cases, you must pass state or xml'''
|
|
if not item_id:
|
|
raise ValueError("Missing Index")
|
|
if not xml and not json:
|
|
raise ValueError("xml or json required")
|
|
if not system:
|
|
raise ValueError("System context required")
|
|
|
|
self.xml = xml
|
|
self.json = json
|
|
self.item_id = item_id
|
|
self.state = state
|
|
self.DEBUG = False
|
|
|
|
self.__xmltree = etree.fromstring(xml) # PRIVATE
|
|
|
|
if system:
|
|
## These are temporary; we really should go
|
|
## through self.system.
|
|
self.ajax_url = system.ajax_url
|
|
self.tracker = system.track_function
|
|
self.filestore = system.filestore
|
|
self.render_function = system.render_function
|
|
self.DEBUG = system.DEBUG
|
|
self.system = system
|
|
|
|
### Functions used in the LMS
|
|
|
|
def get_state(self):
|
|
''' State of the object, as stored in the database
|
|
'''
|
|
return ""
|
|
|
|
def get_score(self):
|
|
''' Score the student received on the problem.
|
|
'''
|
|
return None
|
|
|
|
def max_score(self):
|
|
''' Maximum score. Two notes:
|
|
* This is generic; in abstract, a problem could be 3/5 points on one randomization, and 5/7 on another
|
|
* In practice, this is a Very Bad Idea, and (a) will break some code in place (although that code
|
|
should get fixed), and (b) break some analytics we plan to put in place.
|
|
'''
|
|
return None
|
|
|
|
def get_html(self):
|
|
''' HTML, as shown in the browser. This is the only method that must be implemented
|
|
'''
|
|
return "Unimplemented"
|
|
|
|
def handle_ajax(self, dispatch, get):
|
|
''' dispatch is last part of the URL.
|
|
get is a dictionary-like object '''
|
|
return ""
|
|
|
|
|
|
class XModuleDescriptor(object):
|
|
def __init__(self, xml = None, json = None):
|
|
if not xml and not json:
|
|
raise "XModuleDescriptor must be initalized with XML or JSON"
|
|
if not xml:
|
|
raise NotImplementedError("Code does not have support for JSON yet")
|
|
|
|
self.xml = xml
|
|
self.json = json
|
|
|
|
def get_xml(self):
|
|
''' For conversions between JSON and legacy XML representations.
|
|
'''
|
|
if self.xml:
|
|
return self.xml
|
|
else:
|
|
raise NotImplementedError("JSON->XML Translation not implemented")
|
|
|
|
def get_json(self):
|
|
''' For conversions between JSON and legacy XML representations.
|
|
'''
|
|
if self.json:
|
|
raise NotImplementedError
|
|
return self.json # TODO: Return context as well -- files, etc.
|
|
else:
|
|
raise NotImplementedError("XML->JSON Translation not implemented")
|
|
|
|
#def handle_cms_json(self):
|
|
# raise NotImplementedError
|
|
|
|
#def render(self, size):
|
|
# ''' Size: [thumbnail, small, full]
|
|
# Small ==> what we drag around
|
|
# Full ==> what we edit
|
|
# '''
|
|
# raise NotImplementedError
|