Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
codejail
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
codejail
Commits
ff96a50c
Commit
ff96a50c
authored
Mar 28, 2013
by
Ned Batchelder
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor to move assumed_imports into capa, so that code_jail is more pure.
parent
ef328415
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
3 additions
and
134 deletions
+3
-134
codejail/lazymod.py
+0
-42
codejail/safe_exec.py
+3
-34
codejail/tests/test_lazymod.py
+0
-26
codejail/tests/test_safe_exec.py
+0
-13
codejail/util.py
+0
-19
No files found.
codejail/lazymod.py
deleted
100644 → 0
View file @
ef328415
"""A module proxy for delayed importing of modules.
From http://barnesc.blogspot.com/2006/06/automatic-python-imports-with-autoimp.html,
in the public domain.
"""
import
sys
class
LazyModule
(
object
):
"""A lazy module proxy."""
def
__init__
(
self
,
modname
):
self
.
__dict__
[
'__name__'
]
=
modname
self
.
_set_mod
(
None
)
def
_set_mod
(
self
,
mod
):
if
mod
is
not
None
:
self
.
__dict__
=
mod
.
__dict__
self
.
__dict__
[
'_lazymod_mod'
]
=
mod
def
_load_mod
(
self
):
__import__
(
self
.
__name__
)
self
.
_set_mod
(
sys
.
modules
[
self
.
__name__
])
def
__getattr__
(
self
,
name
):
if
self
.
__dict__
[
'_lazymod_mod'
]
is
None
:
self
.
_load_mod
()
mod
=
self
.
__dict__
[
'_lazymod_mod'
]
if
hasattr
(
mod
,
name
):
return
getattr
(
mod
,
name
)
else
:
try
:
subname
=
'
%
s.
%
s'
%
(
self
.
__name__
,
name
)
__import__
(
subname
)
submod
=
getattr
(
mod
,
name
)
except
ImportError
:
raise
AttributeError
(
"'module' object has no attribute
%
r"
%
name
)
self
.
__dict__
[
name
]
=
LazyModule
(
subname
,
submod
)
return
self
.
__dict__
[
name
]
codejail/safe_exec.py
View file @
ff96a50c
...
@@ -6,40 +6,17 @@ import shutil
...
@@ -6,40 +6,17 @@ import shutil
import
sys
import
sys
import
textwrap
import
textwrap
import
lazymod
import
jailpy
import
jailpy
from
util
import
temp_directory
,
change_directory
,
TempDirectory
from
util
import
temp_directory
,
change_directory
# We'll need the code from lazymod.py for use in jailpy, so read it now.
def
safe_exec
(
code
,
globals_dict
,
files
=
None
,
python_path
=
None
):
lazymod_py_file
=
lazymod
.
__file__
if
lazymod_py_file
.
endswith
(
"c"
):
lazymod_py_file
=
lazymod_py_file
[:
-
1
]
lazymod_py
=
open
(
lazymod_py_file
)
.
read
()
def
names_and_modules
(
assumed_imports
):
"""Get uniform names and modules from assumed_imports."""
for
modname
in
assumed_imports
:
if
isinstance
(
modname
,
tuple
):
yield
modname
else
:
yield
modname
,
modname
def
safe_exec
(
code
,
globals_dict
,
assumed_imports
=
None
,
files
=
None
,
python_path
=
None
):
"""Execute code as "exec" does, but safely.
"""Execute code as "exec" does, but safely.
`code` is a string of Python code. `globals_dict` is used as the globals
`code` is a string of Python code. `globals_dict` is used as the globals
during execution. Modifications the code makes to `globals_dict` are
during execution. Modifications the code makes to `globals_dict` are
reflected in the dictionary on return.
reflected in the dictionary on return.
`assumed_imports` is a list of modules to make available as implicit
imports for the code. Entries are either a name, "mod", which makes
"import mod" part of the code, or a pair, ("f", "fooey"), which makes
"import fooey as f" part of the code. The module name can be dotted.
Returns None. Changes made by `code` are visible in `globals_dict`.
Returns None. Changes made by `code` are visible in `globals_dict`.
"""
"""
...
@@ -72,11 +49,6 @@ def safe_exec(code, globals_dict, assumed_imports=None, files=None, python_path=
...
@@ -72,11 +49,6 @@ def safe_exec(code, globals_dict, assumed_imports=None, files=None, python_path=
the_code
.
append
(
"sys.path.append(
%
r)
\n
"
%
pybase
)
the_code
.
append
(
"sys.path.append(
%
r)
\n
"
%
pybase
)
files
.
append
(
pydir
)
files
.
append
(
pydir
)
if
assumed_imports
:
the_code
.
append
(
lazymod_py
)
for
name
,
modname
in
names_and_modules
(
assumed_imports
):
the_code
.
append
(
"g_dict['{}'] = LazyModule('{}')
\n
"
.
format
(
name
,
modname
))
the_code
.
append
(
textwrap
.
dedent
(
the_code
.
append
(
textwrap
.
dedent
(
# Execute the sandboxed code.
# Execute the sandboxed code.
"""
"""
...
@@ -140,7 +112,7 @@ def json_safe(d):
...
@@ -140,7 +112,7 @@ def json_safe(d):
return
json
.
loads
(
json
.
dumps
(
jd
))
return
json
.
loads
(
json
.
dumps
(
jd
))
def
not_safe_exec
(
code
,
globals_dict
,
assumed_imports
=
None
,
files
=
None
,
python_path
=
None
):
def
not_safe_exec
(
code
,
globals_dict
,
files
=
None
,
python_path
=
None
):
"""Another implementation of `safe_exec`, but not safe.
"""Another implementation of `safe_exec`, but not safe.
This can be swapped in for debugging problems in sandboxed Python code.
This can be swapped in for debugging problems in sandboxed Python code.
...
@@ -151,9 +123,6 @@ def not_safe_exec(code, globals_dict, assumed_imports=None, files=None, python_p
...
@@ -151,9 +123,6 @@ def not_safe_exec(code, globals_dict, assumed_imports=None, files=None, python_p
"""
"""
g_dict
=
json_safe
(
globals_dict
)
g_dict
=
json_safe
(
globals_dict
)
for
name
,
modname
in
names_and_modules
(
assumed_imports
or
()):
g_dict
[
name
]
=
lazymod
.
LazyModule
(
modname
)
with
temp_directory
(
delete_when_done
=
True
)
as
tmpdir
:
with
temp_directory
(
delete_when_done
=
True
)
as
tmpdir
:
with
change_directory
(
tmpdir
):
with
change_directory
(
tmpdir
):
# Copy the files here.
# Copy the files here.
...
...
codejail/tests/test_lazymod.py
deleted
100644 → 0
View file @
ef328415
"""Test lazymod.py"""
import
sys
import
unittest
from
codejail.lazymod
import
LazyModule
from
codejail.util
import
ModuleIsolation
class
TestLazyMod
(
unittest
.
TestCase
):
def
setUp
(
self
):
# Each test will remove modules that it imported.
self
.
addCleanup
(
ModuleIsolation
()
.
clean_up
)
def
test_simple
(
self
):
# Import some stdlib module that has not been imported before
self
.
assertNotIn
(
"colorsys"
,
sys
.
modules
)
colorsys
=
LazyModule
(
"colorsys"
)
hsv
=
colorsys
.
rgb_to_hsv
(
.
3
,
.
4
,
.
2
)
self
.
assertEqual
(
hsv
[
0
],
0.25
)
def
test_dotted
(
self
):
self
.
assertNotIn
(
"email.utils"
,
sys
.
modules
)
email_utils
=
LazyModule
(
"email.utils"
)
self
.
assertEqual
(
email_utils
.
quote
(
'"hi"'
),
r'\"hi\"'
)
codejail/tests/test_safe_exec.py
View file @
ff96a50c
...
@@ -14,19 +14,6 @@ class SafeExecTests(object):
...
@@ -14,19 +14,6 @@ class SafeExecTests(object):
self
.
safe_exec
(
"a = 17"
,
g
)
self
.
safe_exec
(
"a = 17"
,
g
)
self
.
assertEqual
(
g
[
'a'
],
17
)
self
.
assertEqual
(
g
[
'a'
],
17
)
def
test_assumed_imports
(
self
):
g
=
{}
# Using string without importing it is bad.
with
self
.
assertRaises
(
Exception
):
self
.
safe_exec
(
"a = string.ascii_lowercase[0]"
,
g
)
# Using string with an assumed import is fine.
self
.
safe_exec
(
"a = string.ascii_lowercase[0]"
,
g
,
assumed_imports
=
[
"string"
])
self
.
assertEqual
(
g
[
'a'
],
'a'
)
# Can also import with a shorthand.
self
.
safe_exec
(
"a = op.join('x', 'y')"
,
g
,
assumed_imports
=
[(
"op"
,
"os.path"
)])
self
.
assertEqual
(
g
[
'a'
][
0
],
'x'
)
self
.
assertEqual
(
g
[
'a'
][
-
1
],
'y'
)
def
test_files_are_copied
(
self
):
def
test_files_are_copied
(
self
):
g
=
{}
g
=
{}
self
.
safe_exec
(
self
.
safe_exec
(
...
...
codejail/util.py
View file @
ff96a50c
...
@@ -32,25 +32,6 @@ def temp_directory(delete_when_done=True):
...
@@ -32,25 +32,6 @@ def temp_directory(delete_when_done=True):
tmp
.
clean_up
()
tmp
.
clean_up
()
class
ModuleIsolation
(
object
):
"""
Manage changes to sys.modules so that we can roll back imported modules.
Create this object, it will snapshot the currently imported modules. When
you call `clean_up()`, it will delete any module imported since its creation.
"""
def
__init__
(
self
):
# Save all the names of all the imported modules.
self
.
mods
=
set
(
sys
.
modules
)
def
clean_up
(
self
):
# Get a list of modules that didn't exist when we were created
new_mods
=
[
m
for
m
in
sys
.
modules
if
m
not
in
self
.
mods
]
# and delete them all so another import will run code for real again.
for
m
in
new_mods
:
del
sys
.
modules
[
m
]
class
ChangeDirectory
(
object
):
class
ChangeDirectory
(
object
):
def
__init__
(
self
,
new_dir
):
def
__init__
(
self
,
new_dir
):
self
.
old_dir
=
os
.
getcwd
()
self
.
old_dir
=
os
.
getcwd
()
...
...
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