Merge pull request #396 from MITx/feature/ichuang/xqa-and-patches

Provide content QA (quality assessment) interface
This commit is contained in:
Calen Pennington
2012-08-13 06:55:05 -07:00
70 changed files with 522 additions and 190 deletions

View File

@@ -297,6 +297,7 @@ def _do_create_account(post_vars):
try:
user.save()
except IntegrityError:
js = {'success': False}
# Figure out the cause of the integrity error
if len(User.objects.filter(username=post_vars['username'])) > 0:
js['value'] = "An account with this username already exists."
@@ -402,7 +403,10 @@ def create_account(request, post_override=None):
return HttpResponse(json.dumps(js))
# Ok, looks like everything is legit. Create the account.
(user, profile, registration) = _do_create_account(post_vars)
ret = _do_create_account(post_vars)
if isinstance(ret,HttpResponse): # if there was an error then return that
return ret
(user, profile, registration) = ret
d = {'name': post_vars['name'],
'key': registration.activation_key,

View File

@@ -34,7 +34,7 @@ def wrap_xmodule(get_html, module, template):
return _get_html
def replace_static_urls(get_html, prefix):
def replace_static_urls(get_html, prefix, module):
"""
Updates the supplied module with a new get_html function that wraps
the old get_html function and substitutes urls of the form /static/...
@@ -69,14 +69,14 @@ def grade_histogram(module_id):
return grades
def add_histogram(get_html, module):
def add_histogram(get_html, module, user):
"""
Updates the supplied module with a new get_html function that wraps
the output of the old get_html function with additional information
for admin users only, including a histogram of student answers and the
definition of the xmodule
Does nothing if module is a SequenceModule
Does nothing if module is a SequenceModule or a VerticalModule.
"""
@wraps(get_html)
def _get_html():
@@ -97,14 +97,20 @@ def add_histogram(get_html, module):
# doesn't like symlinks)
filepath = filename
data_dir = osfs.root_path.rsplit('/')[-1]
edit_link = "https://github.com/MITx/%s/tree/master/%s" % (data_dir,filepath)
giturl = module.metadata.get('giturl','https://github.com/MITx')
edit_link = "%s/%s/tree/master/%s" % (giturl,data_dir,filepath)
else:
edit_link = False
staff_context = {'definition': module.definition.get('data'),
'metadata': json.dumps(module.metadata, indent=4),
'element_id': module.location.html_id(),
'location': module.location,
'xqa_key': module.metadata.get('xqa_key',''),
'category': str(module.__class__.__name__),
'element_id': module.location.html_id().replace('-','_'),
'edit_link': edit_link,
'user': user,
'xqa_server' : settings.MITX_FEATURES.get('USE_XQA_SERVER','http://xqa:server@content-qa.mitx.mit.edu/xqa'),
'histogram': json.dumps(histogram),
'render_histogram': render_histogram,
'module_content': get_html()}

View File

@@ -393,9 +393,10 @@ class LoncapaProblem(object):
context['script_code'] += code # store code source in context
try:
exec code in context, context # use "context" for global context; thus defs in code are global within code
except Exception:
except Exception as err:
log.exception("Error while execing script code: " + code)
raise responsetypes.LoncapaProblemError("Error while executing script code")
msg = "Error while executing script code: %s" % str(err).replace('<','&lt;')
raise responsetypes.LoncapaProblemError(msg)
finally:
sys.path = original_path

View File

@@ -319,7 +319,8 @@ class XModuleDescriptor(Plugin, HTMLSnippet):
# A list of metadata that this module can inherit from its parent module
inheritable_metadata = (
'graded', 'start', 'due', 'graceperiod', 'showanswer', 'rerandomize',
# TODO (ichuang): used for Fall 2012 xqa server access
'xqa_key',
# TODO: This is used by the XMLModuleStore to provide for locations for
# static files, and will need to be removed when that code is removed
'data_dir'

View File

@@ -1,6 +1,7 @@
from xmodule.x_module import XModuleDescriptor
from xmodule.modulestore import Location
from lxml import etree
import json
import copy
import logging
import traceback
@@ -32,7 +33,15 @@ def is_pointer_tag(xml_obj):
actual_attr = set(xml_obj.attrib.keys())
return len(xml_obj) == 0 and actual_attr == expected_attr
def get_metadata_from_xml(xml_object, remove=True):
meta = xml_object.find('meta')
if meta is None:
return ''
dmdata = meta.text
log.debug('meta for %s loaded: %s' % (xml_object,dmdata))
if remove:
xml_object.remove(meta)
return dmdata
_AttrMapBase = namedtuple('_AttrMap', 'from_xml to_xml')
@@ -71,6 +80,7 @@ class XmlDescriptor(XModuleDescriptor):
metadata_attributes = ('format', 'graceperiod', 'showanswer', 'rerandomize',
'start', 'due', 'graded', 'display_name', 'url_name', 'hide_from_toc',
'ispublic', # if True, then course is listed for all users; see
'xqa_key', # for xqaa server access
# VS[compat] Remove once unused.
'name', 'slug')
@@ -180,8 +190,11 @@ class XmlDescriptor(XModuleDescriptor):
definition_xml = cls.load_file(filepath, system.resources_fs, location)
definition_metadata = get_metadata_from_xml(definition_xml)
cls.clean_metadata_from_xml(definition_xml)
definition = cls.definition_from_xml(definition_xml, system)
if definition_metadata:
definition['definition_metadata'] = definition_metadata
# TODO (ichuang): remove this after migration
# for Fall 2012 LMS migration: keep filename (and unmangled filename)
@@ -236,9 +249,9 @@ class XmlDescriptor(XModuleDescriptor):
filepath = cls._format_filepath(xml_object.tag, url_name)
definition_xml = cls.load_file(filepath, system.resources_fs, location)
else:
definition_xml = xml_object
definition_xml = xml_object # this is just a pointer, not the real definition content
definition = cls.load_definition(definition_xml, system, location)
definition = cls.load_definition(definition_xml, system, location) # note this removes metadata
# VS[compat] -- make Ike's github preview links work in both old and
# new file layouts
if is_pointer_tag(xml_object):
@@ -246,6 +259,17 @@ class XmlDescriptor(XModuleDescriptor):
definition['filename'] = [filepath, filepath]
metadata = cls.load_metadata(definition_xml)
# move definition metadata into dict
dmdata = definition.get('definition_metadata','')
if dmdata:
metadata['definition_metadata_raw'] = dmdata
try:
metadata.update(json.loads(dmdata))
except Exception as err:
log.debug('Error %s in loading metadata %s' % (err,dmdata))
metadata['definition_metadata_err'] = str(err)
return cls(
system,
definition,