Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
6de2fa5e
Commit
6de2fa5e
authored
Aug 02, 2012
by
kimth
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
LMS interface to xqueue in separate file
parent
c7084e52
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
83 additions
and
44 deletions
+83
-44
common/lib/capa/capa/responsetypes.py
+32
-44
lms/djangoapps/courseware/xqueue_interface.py
+51
-0
No files found.
common/lib/capa/capa/responsetypes.py
View file @
6de2fa5e
...
...
@@ -24,6 +24,7 @@ import abc
# specific library imports
from
calc
import
evaluator
,
UndefinedVariable
from
correctmap
import
CorrectMap
from
courseware
import
xqueue_interface
from
util
import
*
from
lxml
import
etree
from
lxml.html.soupparser
import
fromstring
as
fromstring_bs
# uses Beautiful Soup!!! FIXME?
...
...
@@ -798,10 +799,10 @@ class SymbolicResponse(CustomResponse):
class
CodeResponse
(
LoncapaResponse
):
'''
Grade student code using an external server, called 'xqueue'
In contrast to ExternalResponse, CodeResponse has following behavior:
1) Goes through a queueing system
2) Does not do external request for 'get_answers'
Grade student code using an external
queueing
server, called 'xqueue'
External requests are only submitted for student submission grading
(i.e. and not for getting reference answers)
'''
response_tag
=
'coderesponse'
...
...
@@ -857,9 +858,33 @@ class CodeResponse(LoncapaResponse):
self
.
context
.
update
({
'submission'
:
submission
})
extra_payload
=
{
'edX_student_response'
:
submission
}
r
,
queuekey
=
self
.
_send_to_queue
(
extra_payload
)
# TODO: Perform checks on the xqueue response
# Prepare xqueue request
#------------------------------------------------------------
# Queuekey generation
h
=
hashlib
.
md5
()
h
.
update
(
str
(
self
.
system
.
seed
))
h
.
update
(
str
(
time
.
time
()))
queuekey
=
h
.
hexdigest
()
# Non-null CorrectMap['queuekey'] indicates that the problem has been submitted
# Generate header
xheader
=
xqueue_interface
.
make_xheader
(
lms_callback_url
=
self
.
system
.
xqueue_callback_url
,
lms_key
=
queuekey
,
queue_name
=
self
.
queue_name
)
# Generate body
# NOTE: Currently specialized to 6.00x's pyxservers, which follows the ExternalResponse interface
contents
=
{
'xml'
:
etree
.
tostring
(
self
.
xml
,
pretty_print
=
True
),
'edX_cmd'
:
'get_score'
,
'edX_tests'
:
self
.
tests
,
'processor'
:
self
.
code
,
'edX_student_response'
:
submission
}
# Submit request
xqueue_interface
.
send_to_queue
(
header
=
xheader
,
body
=
json
.
dumps
(
contents
))
# Non-null CorrectMap['queuekey'] indicates that the problem has been queued
cmap
=
CorrectMap
()
cmap
.
set
(
self
.
answer_id
,
queuekey
=
queuekey
,
msg
=
'Submitted to queue'
)
...
...
@@ -883,7 +908,7 @@ class CodeResponse(LoncapaResponse):
self
.
context
[
'correct'
][
0
]
=
admap
[
ad
]
# Replace 'oldcmap' with new grading results if queuekey matches.
# If queuekey does not match, we keep waiting for the score_msg
that will match
# If queuekey does not match, we keep waiting for the score_msg
whose key actually matchs
if
oldcmap
.
is_right_queuekey
(
self
.
answer_id
,
queuekey
):
msg
=
rxml
.
find
(
'message'
)
.
text
.
replace
(
' '
,
' '
)
oldcmap
.
set
(
self
.
answer_id
,
correctness
=
self
.
context
[
'correct'
][
0
],
msg
=
msg
,
queuekey
=
None
)
# Queuekey is consumed
...
...
@@ -892,8 +917,6 @@ class CodeResponse(LoncapaResponse):
return
oldcmap
# CodeResponse differentiates from ExternalResponse in the behavior of 'get_answers'. CodeResponse.get_answers
# does NOT require a queue submission, and the answer is computed (extracted from problem XML) locally.
def
get_answers
(
self
):
anshtml
=
'<font color="blue"><span class="code-answer"><br/><pre>
%
s</pre><br/></span></font>'
%
self
.
answer
return
{
self
.
answer_id
:
anshtml
}
...
...
@@ -901,41 +924,6 @@ class CodeResponse(LoncapaResponse):
def
get_initial_display
(
self
):
return
{
self
.
answer_id
:
self
.
initial_display
}
# CodeResponse._send_to_queue implements the same interface as defined for ExternalResponse's 'get_score'
def
_send_to_queue
(
self
,
extra_payload
):
# Prepare payload
xmlstr
=
etree
.
tostring
(
self
.
xml
,
pretty_print
=
True
)
header
=
{
'lms_callback_url'
:
self
.
system
.
xqueue_callback_url
,
'queue_name'
:
self
.
queue_name
,
}
# Queuekey generation
h
=
hashlib
.
md5
()
h
.
update
(
str
(
self
.
system
.
seed
))
h
.
update
(
str
(
time
.
time
()))
queuekey
=
h
.
hexdigest
()
header
.
update
({
'lms_key'
:
queuekey
})
body
=
{
'xml'
:
xmlstr
,
'edX_cmd'
:
'get_score'
,
'edX_tests'
:
self
.
tests
,
'processor'
:
self
.
code
,
}
body
.
update
(
extra_payload
)
payload
=
{
'xqueue_header'
:
json
.
dumps
(
header
),
'xqueue_body'
:
json
.
dumps
(
body
),
}
# Contact queue server
try
:
r
=
requests
.
post
(
self
.
url
,
data
=
payload
)
except
Exception
as
err
:
msg
=
"Error in CodeResponse
%
s: cannot connect to queue server url=
%
s"
%
(
err
,
self
.
url
)
log
.
error
(
msg
)
raise
Exception
(
msg
)
return
r
,
queuekey
#-----------------------------------------------------------------------------
...
...
lms/djangoapps/courseware/xqueue_interface.py
0 → 100644
View file @
6de2fa5e
#
# LMS Interface to external queueing system (xqueue)
#
import
json
import
requests
# TODO: Collection of parameters to be hooked into rest of edX system
XQUEUE_SUBMIT_URL
=
'http://xqueue.edx.org/xqueue/submit/'
def
upload_files_to_s3
():
print
' THK: xqueue_interface.upload_files_to_s3'
def
make_xheader
(
lms_callback_url
,
lms_key
,
queue_name
):
'''
Generate header for delivery and reply of queue request.
Xqueue header is a JSON-serialized dict:
{ 'lms_callback_url': url to which xqueue will return the request (string),
'lms_key': secret key used by LMS to protect its state (string),
'queue_name': designate a specific queue within xqueue server, e.g. 'MITx-6.00x' (string)
}
'''
return
json
.
dumps
({
'lms_callback_url'
:
lms_callback_url
,
'lms_key'
:
lms_key
,
'queue_name'
:
queue_name
})
def
send_to_queue
(
header
,
body
,
xqueue_url
=
None
):
'''
Submit a request to xqueue.
header: JSON-serialized dict in the format described in 'xqueue_interface.make_xheader'
body: Serialized data for the receipient behind the queueing service. The operation of
xqueue is agnostic to the contents of 'body'
'''
if
xqueue_url
is
None
:
xqueue_url
=
XQUEUE_SUBMIT_URL
# Contact queue server
payload
=
{
'xqueue_header'
:
header
,
'xqueue_body'
:
body
}
try
:
r
=
requests
.
post
(
xqueue_url
,
data
=
payload
)
except
Exception
as
err
:
msg
=
'Error in xqueue_interface.send_to_queue
%
s: Cannot connect to server url=
%
s'
%
(
err
,
xqueue_url
)
raise
Exception
(
msg
)
#print r.text
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment