Commit ff5773c0 by ichuang

Merge pull request #348 from MITx/kimth/lms-coderesponse

merging this now because the it looks ok, and it fixes some bugs introduced by the last xserver merge, which are preventing the LMS from running in the current version of master.
parents 24f85bf2 18a7f587
......@@ -29,7 +29,6 @@ import xqueue_interface
log = logging.getLogger('mitx.' + __name__)
qinterface = xqueue_interface.XqueueInterface()
#-----------------------------------------------------------------------------
# Exceptions
......@@ -811,7 +810,7 @@ class CodeResponse(LoncapaResponse):
def setup_response(self):
xml = self.xml
self.queue_name = xml.get('queuename', self.system.xqueue_default_queuename)
self.queue_name = xml.get('queuename', self.system.xqueue['default_queuename'])
answer = xml.find('answer')
if answer is not None:
......@@ -859,10 +858,11 @@ class CodeResponse(LoncapaResponse):
# Prepare xqueue request
#------------------------------------------------------------
qinterface = self.system.xqueue['interface']
# Generate header
queuekey = xqueue_interface.make_hashkey(self.system.seed)
xheader = xqueue_interface.make_xheader(lms_callback_url=self.system.xqueue_callback_url,
queuekey = xqueue_interface.make_hashkey(str(self.system.seed)+self.answer_id)
xheader = xqueue_interface.make_xheader(lms_callback_url=self.system.xqueue['callback_url'],
lms_key=queuekey,
queue_name=self.queue_name)
......@@ -891,7 +891,7 @@ class CodeResponse(LoncapaResponse):
msg='Unable to deliver your submission to grader. (Reason: %s.) Please try again later.' % msg)
else:
# Non-null CorrectMap['queuekey'] indicates that the problem has been queued
cmap.set(self.answer_id, queuekey=queuekey, msg='Submitted to grader')
cmap.set(self.answer_id, queuekey=queuekey, msg='Submitted to grader. (Queue length: %s)' % msg)
return cmap
......
......@@ -39,6 +39,7 @@
lineWrapping: true,
indentUnit: "${tabsize}",
tabSize: "${tabsize}",
indentWithTabs: true,
smartIndent: false
});
});
......@@ -48,7 +49,7 @@
border: 1px solid black;
font-size: 14px;
line-height: 18px;
resize: vertical;
resize: both;
}
</style>
</section>
......@@ -47,7 +47,12 @@ def parse_xreply(xreply):
'content': Message from xqueue (string)
}
'''
xreply = json.loads(xreply)
try:
xreply = json.loads(xreply)
except ValueError, err:
log.error(err)
return (1, 'unexpected reply from server')
return_code = xreply['return_code']
content = xreply['content']
return (return_code, content)
......@@ -61,7 +66,7 @@ class XqueueInterface:
def __init__(self, url=XQUEUE_URL, auth=XQUEUE_LMS_AUTH):
self.url = url
self.auth = auth
self.s = requests.session()
self.session = requests.session()
self._login()
def send_to_queue(self, header, body, file_to_upload=None):
......@@ -86,29 +91,32 @@ class XqueueInterface:
return (error, msg)
def _login(self):
try:
r = self.s.post(self.url+'/xqueue/login/', data={ 'username': self.auth['username'],
'password': self.auth['password'] })
except requests.exceptions.ConnectionError, err:
log.error(err)
return (1, 'cannot connect to server')
payload = { 'username': self.auth['username'],
'password': self.auth['password'] }
return self._http_post(self.url+'/xqueue/login/', payload)
return parse_xreply(r.text)
def _send_to_queue(self, header, body, file_to_upload=None):
payload = {'xqueue_header': header,
'xqueue_body' : body}
files = None
if file_to_upload is not None:
files = { file_to_upload.name: file_to_upload }
return self._http_post(self.url+'/xqueue/submit/', payload, files)
def _http_post(self, url, data, files=None):
try:
r = self.s.post(self.url+'/xqueue/submit/', data=payload, files=files)
r = self.session.post(url, data=data, files=files)
except requests.exceptions.ConnectionError, err:
log.error(err)
return (1, 'cannot connect to server')
return (1, 'cannot connect to server')
if r.status_code not in [200]:
return (1, 'unexpected HTTP status code [%d]' % r.status_code)
return parse_xreply(r.text)
qinterface = XqueueInterface()
......@@ -12,6 +12,7 @@ class @Problem
bind: =>
MathJax.Hub.Queue ["Typeset", MathJax.Hub]
window.update_schematics()
@inputs = @$("[id^=input_#{@element_id.replace(/problem_/, '')}_]")
@$('section.action input:button').click @refreshAnswers
@$('section.action input.check').click @check_fd
#@$('section.action input.check').click @check
......@@ -66,8 +67,8 @@ class @Problem
return
fd = new FormData()
@$("[id^=input_#{@element_id.replace(/problem_/, '')}_]").each (index, element) ->
@inputs.each (index, element) ->
if element.type is 'file'
if element.files[0] instanceof File
fd.append(element.id, element.files[0])
......@@ -155,4 +156,4 @@ class @Problem
element.schematic.update_value()
@$(".CodeMirror").each (index, element) ->
element.CodeMirror.save() if element.CodeMirror.save
@answers = @$("[id^=input_#{@element_id.replace(/problem_/, '')}_]").serialize()
@answers = @inputs.serialize()
......@@ -643,8 +643,7 @@ class ModuleSystem(object):
user=None,
filestore=None,
debug=False,
xqueue_callback_url=None,
xqueue_default_queuename="null",
xqueue = None,
is_staff=False):
'''
Create a closure around the system environment.
......@@ -668,6 +667,9 @@ class ModuleSystem(object):
filestore - A filestore ojbect. Defaults to an instance of OSFS based
at settings.DATA_DIR.
xqueue - Dict containing XqueueInterface object, as well as parameters
for the specific StudentModule
replace_urls - TEMPORARY - A function like static_replace.replace_urls
that capa_module can use to fix up the static urls in
ajax results.
......@@ -676,8 +678,7 @@ class ModuleSystem(object):
TODO (vshnayder): this will need to change once we have real user roles.
'''
self.ajax_url = ajax_url
self.xqueue_callback_url = xqueue_callback_url
self.xqueue_default_queuename = xqueue_default_queuename
self.xqueue = xqueue
self.track_function = track_function
self.filestore = filestore
self.get_module = get_module
......
......@@ -8,6 +8,7 @@ from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.models import User
from xmodule.modulestore.django import modulestore
from capa.xqueue_interface import qinterface
from mitxmako.shortcuts import render_to_string
from models import StudentModule, StudentModuleCache
from static_replace import replace_urls
......@@ -157,6 +158,10 @@ def get_module(user, request, location, student_module_cache, position=None):
# TODO: Queuename should be derived from 'course_settings.json' of each course
xqueue_default_queuename = descriptor.location.org + '-' + descriptor.location.course
xqueue = { 'interface': qinterface,
'callback_url': xqueue_callback_url,
'default_queuename': xqueue_default_queuename.replace(' ','_') }
def _get_module(location):
(module, _, _, _) = get_module(user, request, location,
student_module_cache, position)
......@@ -168,8 +173,7 @@ def get_module(user, request, location, student_module_cache, position=None):
system = ModuleSystem(track_function=make_track_function(request),
render_template=render_to_string,
ajax_url=ajax_url,
xqueue_callback_url=xqueue_callback_url,
xqueue_default_queuename=xqueue_default_queuename.replace(' ','_'),
xqueue=xqueue,
# TODO (cpennington): Figure out how to share info between systems
filestore=descriptor.system.resources_fs,
get_module=_get_module,
......@@ -222,6 +226,9 @@ def get_module(user, request, location, student_module_cache, position=None):
@csrf_exempt
def xqueue_callback(request, userid, id, dispatch):
'''
Entry point for graded results from the queueing system.
'''
# Parse xqueue response
get = request.POST.copy()
try:
......
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