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
bcdc11c3
Commit
bcdc11c3
authored
Apr 05, 2013
by
Ned Batchelder
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Hint functions are now run in the sandbox.
parent
ed13f0a0
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
68 additions
and
14 deletions
+68
-14
common/lib/capa/capa/responsetypes.py
+34
-8
common/lib/capa/capa/tests/response_xml_factory.py
+12
-2
common/lib/capa/capa/tests/test_responsetypes.py
+16
-0
common/lib/codejail/codejail/safe_exec.py
+6
-4
No files found.
common/lib/capa/capa/responsetypes.py
View file @
bcdc11c3
...
...
@@ -22,6 +22,7 @@ import random
import
re
import
requests
import
subprocess
import
textwrap
import
traceback
import
xml.sax.saxutils
as
saxutils
...
...
@@ -30,7 +31,7 @@ from shapely.geometry import Point, MultiPoint
# specific library imports
from
calc
import
evaluator
,
UndefinedVariable
from
.
correctmap
import
CorrectM
ap
from
.
import
correctm
ap
from
datetime
import
datetime
from
.util
import
*
from
lxml
import
etree
...
...
@@ -42,6 +43,10 @@ import safe_exec
log
=
logging
.
getLogger
(
__name__
)
CorrectMap
=
correctmap
.
CorrectMap
CORRECTMAP_PY
=
None
#-----------------------------------------------------------------------------
# Exceptions
...
...
@@ -253,20 +258,41 @@ class LoncapaResponse(object):
# We may extend this in the future to add another argument which provides a
# callback procedure to a social hint generation system.
if
not
hintfn
in
self
.
context
:
msg
=
'missing specified hint function
%
s in script context'
%
hintfn
msg
+=
"
\n
See XML source line
%
s"
%
getattr
(
self
.
xml
,
'sourceline'
,
'<unavailable>'
)
raise
LoncapaProblemError
(
msg
)
global
CORRECTMAP_PY
if
CORRECTMAP_PY
is
None
:
# We need the CorrectMap code for hint functions. No, this is not great.
CORRECTMAP_PY
=
inspect
.
getsource
(
correctmap
)
code
=
(
CORRECTMAP_PY
+
"
\n
"
+
self
.
context
[
'script_code'
]
+
"
\n
"
+
textwrap
.
dedent
(
"""
new_cmap = CorrectMap()
new_cmap.set_dict(new_cmap_dict)
old_cmap = CorrectMap()
old_cmap.set_dict(old_cmap_dict)
{hintfn}(answer_ids, student_answers, new_cmap, old_cmap)
new_cmap_dict.update(new_cmap.get_dict())
old_cmap_dict.update(old_cmap.get_dict())
"""
)
.
format
(
hintfn
=
hintfn
)
)
globals_dict
=
{
'answer_ids'
:
self
.
answer_ids
,
'student_answers'
:
student_answers
,
'new_cmap_dict'
:
new_cmap
.
get_dict
(),
'old_cmap_dict'
:
old_cmap
.
get_dict
(),
}
try
:
self
.
context
[
hintfn
](
self
.
answer_ids
,
student_answers
,
new_cmap
,
old_cmap
)
safe_exec
.
safe_exec
(
code
,
globals_dict
)
except
Exception
as
err
:
msg
=
'Error
%
s in evaluating hint function
%
s'
%
(
err
,
hintfn
)
msg
+=
"
\n
See XML source line
%
s"
%
getattr
(
self
.
xml
,
'sourceline'
,
'<unavailable>'
)
raise
ResponseError
(
msg
)
new_cmap
.
set_dict
(
globals_dict
[
'new_cmap_dict'
])
return
# hint specified by conditions and text dependent on conditions (a-la Loncapa design)
...
...
common/lib/capa/capa/tests/response_xml_factory.py
View file @
bcdc11c3
...
...
@@ -667,12 +667,16 @@ class StringResponseXMLFactory(ResponseXMLFactory):
Where *hint_prompt* is the string for which we show the hint,
*hint_name* is an internal identifier for the hint,
and *hint_text* is the text we show for the hint.
*hintfn*: The name of a function in the script to use for hints.
"""
# Retrieve the **kwargs
answer
=
kwargs
.
get
(
"answer"
,
None
)
case_sensitive
=
kwargs
.
get
(
"case_sensitive"
,
True
)
hint_list
=
kwargs
.
get
(
'hints'
,
None
)
assert
(
answer
)
hint_fn
=
kwargs
.
get
(
'hintfn'
,
None
)
assert
answer
# Create the <stringresponse> element
response_element
=
etree
.
Element
(
"stringresponse"
)
...
...
@@ -684,8 +688,10 @@ class StringResponseXMLFactory(ResponseXMLFactory):
response_element
.
set
(
"type"
,
"cs"
if
case_sensitive
else
"ci"
)
# Add the hints if specified
if
hint_list
:
if
hint_list
or
hint_fn
:
hintgroup_element
=
etree
.
SubElement
(
response_element
,
"hintgroup"
)
if
hint_list
:
assert
not
hint_fn
for
(
hint_prompt
,
hint_name
,
hint_text
)
in
hint_list
:
stringhint_element
=
etree
.
SubElement
(
hintgroup_element
,
"stringhint"
)
stringhint_element
.
set
(
"answer"
,
str
(
hint_prompt
))
...
...
@@ -697,6 +703,10 @@ class StringResponseXMLFactory(ResponseXMLFactory):
hint_text_element
=
etree
.
SubElement
(
hintpart_element
,
"text"
)
hint_text_element
.
text
=
str
(
hint_text
)
if
hint_fn
:
assert
not
hint_list
hintgroup_element
.
set
(
"hintfn"
,
hint_fn
)
return
response_element
def
create_input_element
(
self
,
**
kwargs
):
...
...
common/lib/capa/capa/tests/test_responsetypes.py
View file @
bcdc11c3
...
...
@@ -552,6 +552,22 @@ class StringResponseTest(ResponseTest):
correct_map
=
problem
.
grade_answers
(
input_dict
)
self
.
assertEquals
(
correct_map
.
get_hint
(
'1_2_1'
),
""
)
def
test_computed_hints
(
self
):
problem
=
self
.
build_problem
(
answer
=
"Michigan"
,
hintfn
=
"gimme_a_hint"
,
script
=
textwrap
.
dedent
(
"""
def gimme_a_hint(answer_ids, student_answers, new_cmap, old_cmap):
aid = answer_ids[0]
answer = student_answers[aid]
new_cmap.set_hint_and_mode(aid, answer+"??", "always")
"""
)
)
input_dict
=
{
'1_2_1'
:
'Hello'
}
correct_map
=
problem
.
grade_answers
(
input_dict
)
self
.
assertEquals
(
correct_map
.
get_hint
(
'1_2_1'
),
"Hello??"
)
class
CodeResponseTest
(
ResponseTest
):
from
response_xml_factory
import
CodeResponseXMLFactory
...
...
common/lib/codejail/codejail/safe_exec.py
View file @
bcdc11c3
"""Safe execution of untrusted Python code."""
import
json
import
logging
import
os.path
import
shutil
import
sys
...
...
@@ -9,6 +10,8 @@ import textwrap
from
codejail
import
jailpy
from
codejail.util
import
temp_directory
,
change_directory
log
=
logging
.
getLogger
(
__name__
)
def
safe_exec
(
code
,
globals_dict
,
files
=
None
,
python_path
=
None
):
"""Execute code as "exec" does, but safely.
...
...
@@ -78,10 +81,9 @@ def safe_exec(code, globals_dict, files=None, python_path=None):
# Turn this on to see what's being executed.
if
0
:
print
"--{:-<40}"
.
format
(
" jailed "
)
print
jailed_code
print
"--{:-<40}"
.
format
(
" exec "
)
print
code
log
.
debug
(
"Jailed code:
%
s"
,
jailed_code
)
log
.
debug
(
"Exec:
%
s"
,
code
)
log
.
debug
(
"Stdin:
%
s"
,
stdin
)
res
=
jailpy
.
jailpy
(
jailed_code
,
stdin
=
stdin
,
files
=
files
)
if
res
.
status
!=
0
:
...
...
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