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