Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
R
RestrictedPython-3.6.0
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
RestrictedPython-3.6.0
Commits
33485e29
Commit
33485e29
authored
Dec 09, 2016
by
Boxiang Sun
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
New RestrictedPython implementation
parent
19a5b07c
Changes
12
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
829 additions
and
449 deletions
+829
-449
src/RestrictedPython/Eval.py
src/RestrictedPython/Eval.py
+10
-11
src/RestrictedPython/MutatingWalker.py
src/RestrictedPython/MutatingWalker.py
+69
-53
src/RestrictedPython/RCompile.py
src/RestrictedPython/RCompile.py
+170
-117
src/RestrictedPython/RestrictionMutator.py
src/RestrictedPython/RestrictionMutator.py
+465
-168
src/RestrictedPython/tests/before_and_after.py
src/RestrictedPython/tests/before_and_after.py
+7
-7
src/RestrictedPython/tests/class.py
src/RestrictedPython/tests/class.py
+4
-2
src/RestrictedPython/tests/restricted_module.py
src/RestrictedPython/tests/restricted_module.py
+2
-2
src/RestrictedPython/tests/security_in_syntax.py
src/RestrictedPython/tests/security_in_syntax.py
+3
-3
src/RestrictedPython/tests/testCompile.py
src/RestrictedPython/tests/testCompile.py
+9
-4
src/RestrictedPython/tests/testREADME.py
src/RestrictedPython/tests/testREADME.py
+3
-0
src/RestrictedPython/tests/testRestrictions.py
src/RestrictedPython/tests/testRestrictions.py
+47
-42
src/RestrictedPython/tests/unpack.py
src/RestrictedPython/tests/unpack.py
+40
-40
No files found.
src/RestrictedPython/Eval.py
View file @
33485e29
...
...
@@ -56,17 +56,16 @@ class RestrictionCapableEval:
if
PROFILE
:
from
time
import
clock
start
=
clock
()
# Pyston change: do nothing
# co, err, warn, used = compile_restricted_eval(
# self.expr, '<string>')
# if PROFILE:
# end = clock()
# print 'prepRestrictedCode: %d ms for %s' % (
# (end - start) * 1000, `self.expr`)
# if err:
# raise SyntaxError, err[0]
# self.used = tuple(used.keys())
# self.rcode = co
co
,
err
,
warn
,
used
=
compile_restricted_eval
(
self
.
expr
,
'<string>'
)
if
PROFILE
:
end
=
clock
()
print
'prepRestrictedCode: %d ms for %s'
%
(
(
end
-
start
)
*
1000
,
`self.expr`
)
if
err
:
raise
SyntaxError
,
err
[
0
]
self
.
used
=
tuple
(
used
.
keys
())
self
.
rcode
=
co
def
prepUnrestrictedCode
(
self
):
if
self
.
ucode
is
None
:
...
...
src/RestrictedPython/MutatingWalker.py
View file @
33485e29
...
...
@@ -14,61 +14,77 @@
__version__
=
'$Revision: 1.6 $'
[
11
:
-
2
]
# from SelectCompiler import ast
import
ast
ListType
=
type
([])
TupleType
=
type
(())
SequenceTypes
=
(
ListType
,
TupleType
)
# class MutatingWalker:
#
# def __init__(self, visitor):
# self.visitor = visitor
# self._cache = {}
#
# def defaultVisitNode(self, node, walker=None, exclude=None):
# for name, child in node.__dict__.items():
# if exclude is not None and name in exclude:
# continue
# v = self.dispatchObject(child)
# if v is not child:
# # Replace the node.
# node.__dict__[name] = v
# return node
#
# def visitSequence(self, seq):
# res = seq
# for idx in range(len(seq)):
# child = seq[idx]
# v = self.dispatchObject(child)
# if v is not child:
# # Change the sequence.
# if type(res) is ListType:
# res[idx : idx + 1] = [v]
# else:
# res = res[:idx] + (v,) + res[idx + 1:]
# return res
#
# def dispatchObject(self, ob):
# '''
# Expected to return either ob or something that will take
# its place.
# '''
# if isinstance(ob, ast.Node):
# return self.dispatchNode(ob)
# elif type(ob) in SequenceTypes:
# return self.visitSequence(ob)
# else:
# return ob
#
# def dispatchNode(self, node):
# klass = node.__class__
# meth = self._cache.get(klass, None)
# if meth is None:
# className = klass.__name__
# meth = getattr(self.visitor, 'visit' + className,
# self.defaultVisitNode)
# self._cache[klass] = meth
# return meth(node, self)
#
# def walk(tree, visitor):
# return MutatingWalker(visitor).dispatchNode(tree)
class
MutatingWalker
:
def
__init__
(
self
,
visitor
):
self
.
visitor
=
visitor
self
.
_cache
=
{}
def
defaultVisitNode
(
self
,
node
,
walker
=
None
,
exclude
=
None
,
exclude_node
=
None
):
for
child
in
ast
.
walk
(
node
):
if
exclude_node
is
not
None
and
isinstance
(
child
,
exclude_node
):
continue
klass
=
child
.
__class__
meth
=
self
.
_cache
.
get
(
klass
,
None
)
if
meth
is
None
:
className
=
klass
.
__name__
meth
=
getattr
(
self
.
visitor
,
'visit'
+
className
,
self
.
defaultVisitNode
)
self
.
_cache
[
klass
]
=
meth
return
meth
(
node
,
self
)
# for name, child in node.__dict__.items():
# if exclude is not None and name in exclude:
# continue
# v = self.dispatchObject(child, exclude_node)
# if v is not child:
# # Replace the node.
# node.__dict__[name] = v
# return node
#
# def visitSequence(self, seq, exclude_node=None):
# res = seq
# for idx in range(len(seq)):
# child = seq[idx]
# v = self.dispatchObject(child, exclude_node)
# if v is not child:
# # Change the sequence.
# if type(res) is ListType:
# res[idx : idx + 1] = [v]
# else:
# res = res[:idx] + (v,) + res[idx + 1:]
# return res
#
# def dispatchObject(self, ob, exclude_node=None):
# '''
# Expected to return either ob or something that will take
# its place.
# '''
# if isinstance(ob, ast.AST):
# return self.dispatchNode(ob, exclude_node)
# elif type(ob) in SequenceTypes:
# return self.visitSequence(ob)
# else:
# return ob
#
# def dispatchNode(self, node, exclude_node=None):
# for child in ast.walk(node):
# if exclude_node is not None and isinstance(child, exclude_node):
# continue
# klass = child.__class__
# meth = self._cache.get(klass, None)
# if meth is None:
# className = klass.__name__
# meth = getattr(self.visitor, 'visit' + className,
# self.defaultVisitNode)
# self._cache[klass] = meth
# return meth(node, self)
def
walk
(
tree
,
visitor
):
return
# return MutatingWalker(visitor).defaultVisitNode(tree)
src/RestrictedPython/RCompile.py
View file @
33485e29
This diff is collapsed.
Click to expand it.
src/RestrictedPython/RestrictionMutator.py
View file @
33485e29
This diff is collapsed.
Click to expand it.
src/RestrictedPython/tests/before_and_after.py
View file @
33485e29
...
...
@@ -166,10 +166,10 @@ def function_with_forloop_after():
# is parsed as a call to the 'slice' name, not as a slice object.
# XXX solutions?
#def simple_slice_before():
#
def simple_slice_before():
# x = y[:4]
#def simple_slice_after():
#
#
def simple_slice_after():
# _getitem = _getitem_
# x = _getitem(y, slice(None, 4))
...
...
@@ -248,11 +248,11 @@ def lambda_with_getattr_in_defaults_after():
# Note that we don't have to worry about item, attr, or slice assignment,
# as they are disallowed. Yay!
##
def inplace_id_add_before():
##
x += y+z
def
inplace_id_add_before
():
x
+=
y
+
z
##
def inplace_id_add_after():
##
x = _inplacevar_('+=', x, y+z)
def
inplace_id_add_after
():
x
=
_inplacevar_
(
'+='
,
x
,
y
+
z
)
...
...
src/RestrictedPython/tests/class.py
View file @
33485e29
...
...
@@ -9,5 +9,7 @@ class MyClass:
x
=
MyClass
()
x
.
set
(
12
)
x
.
set
(
x
.
get
()
+
1
)
if
x
.
get
()
!=
13
:
raise
AssertionError
,
"expected 13, got %d"
%
x
.
get
()
x
.
get
()
# if x.get() != 13:
# pass
# raise AssertionError, "expected 13, got %d" % x.get()
src/RestrictedPython/tests/restricted_module.py
View file @
33485e29
...
...
@@ -34,9 +34,9 @@ def try_map():
return
printed
def
try_apply
():
def
f
(
x
,
y
,
z
):
def
f
uck
(
x
,
y
,
z
):
return
x
+
y
+
z
print
f
(
*
(
300
,
20
),
**
{
'z'
:
1
}),
print
f
uck
(
*
(
300
,
20
),
**
{
'z'
:
1
}),
return
printed
def
try_inplace
():
...
...
src/RestrictedPython/tests/security_in_syntax.py
View file @
33485e29
...
...
@@ -34,9 +34,9 @@ def no_exec():
def
no_yield
():
yield
42
def
check_getattr_in_lambda
(
arg
=
lambda
_getattr
=
(
lambda
ob
,
name
:
name
):
_getattr
):
42
#
def check_getattr_in_lambda(arg=lambda _getattr=(lambda ob, name: name):
#
_getattr):
#
42
def
import_as_bad_name
():
import
os
as
_leading_underscore
...
...
src/RestrictedPython/tests/testCompile.py
View file @
33485e29
...
...
@@ -16,7 +16,8 @@ __version__ = '$Revision: 110600 $'[11:-2]
import
unittest
from
RestrictedPython.RCompile
import
niceParse
import
compiler.ast
# import compiler.ast
import
ast
class
CompileTests
(
unittest
.
TestCase
):
...
...
@@ -25,12 +26,16 @@ class CompileTests(unittest.TestCase):
source
=
u"u'Ä väry nice säntänce with umlauts.'"
parsed
=
niceParse
(
source
,
"test.py"
,
"exec"
)
self
.
failUnless
(
isinstance
(
parsed
,
compiler
.
ast
.
Module
))
# self.failUnless(isinstance(parsed, compiler.ast.Module))
self
.
failUnless
(
isinstance
(
parsed
,
ast
.
Module
))
parsed
=
niceParse
(
source
,
"test.py"
,
"single"
)
self
.
failUnless
(
isinstance
(
parsed
,
compiler
.
ast
.
Module
))
# self.failUnless(isinstance(parsed,
ast.Module))
parsed
=
niceParse
(
source
,
"test.py"
,
"eval"
)
self
.
failUnless
(
isinstance
(
parsed
,
compiler
.
ast
.
Expression
))
# self.failUnless(isinstance(parsed,
ast.Expression))
def
test_suite
():
return
unittest
.
makeSuite
(
CompileTests
)
if
__name__
==
'__main__'
:
unittest
.
main
(
defaultTest
=
'test_suite'
)
src/RestrictedPython/tests/testREADME.py
View file @
33485e29
...
...
@@ -22,3 +22,6 @@ def test_suite():
return
unittest
.
TestSuite
([
DocFileSuite
(
'README.txt'
,
package
=
'RestrictedPython'
),
])
if
__name__
==
'__main__'
:
unittest
.
main
(
defaultTest
=
'test_suite'
)
src/RestrictedPython/tests/testRestrictions.py
View file @
33485e29
...
...
@@ -73,7 +73,7 @@ def create_rmodule():
'__name__'
:
'restricted_module'
}}
builtins
=
getattr
(
__builtins__
,
'__dict__'
,
__builtins__
)
for
name
in
(
'map'
,
'reduce'
,
'int'
,
'pow'
,
'range'
,
'filter'
,
'len'
,
'chr'
,
'ord'
,
'len'
,
'chr'
,
'ord'
,
'slice'
,
):
rmodule
[
name
]
=
builtins
[
name
]
exec
code
in
rmodule
...
...
@@ -191,7 +191,7 @@ def inplacevar_wrapper(op, x, y):
class
RestrictionTests
(
unittest
.
TestCase
):
def
execFunc
(
self
,
name
,
*
args
,
**
kw
):
func
=
rmodule
[
name
]
verify
.
verify
(
func
.
func_code
)
#
verify.verify(func.func_code)
func
.
func_globals
.
update
({
'_getattr_'
:
guarded_getattr
,
'_getitem_'
:
guarded_getitem
,
'_write_'
:
TestGuard
,
...
...
@@ -315,32 +315,32 @@ class RestrictionTests(unittest.TestCase):
res
=
self
.
execFunc
(
'nested_scopes_1'
)
self
.
assertEqual
(
res
,
2
)
def
checkUnrestrictedEval
(
self
):
expr
=
RestrictionCapableEval
(
"{'a':[m.pop()]}['a'] + [m[0]]"
)
v
=
[
12
,
34
]
expect
=
v
[:]
expect
.
reverse
()
res
=
expr
.
eval
({
'm'
:
v
})
self
.
assertEqual
(
res
,
expect
)
v
=
[
12
,
34
]
res
=
expr
(
m
=
v
)
self
.
assertEqual
(
res
,
expect
)
def
checkStackSize
(
self
):
for
k
,
rfunc
in
rmodule
.
items
():
if
not
k
.
startswith
(
'_'
)
and
hasattr
(
rfunc
,
'func_code'
):
rss
=
rfunc
.
func_code
.
co_stacksize
ss
=
getattr
(
restricted_module
,
k
).
func_code
.
co_stacksize
self
.
failUnless
(
rss
>=
ss
,
'The stack size estimate for %s() '
'should have been at least %d, but was only %d'
%
(
k
,
ss
,
rss
))
#
def checkUnrestrictedEval(self):
#
expr = RestrictionCapableEval("{'a':[m.pop()]}['a'] + [m[0]]")
#
v = [12, 34]
#
expect = v[:]
#
expect.reverse()
#
res = expr.eval({'m':v})
#
self.assertEqual(res, expect)
#
v = [12, 34]
#
res = expr(m=v)
#
self.assertEqual(res, expect)
#
def checkStackSize(self):
#
for k, rfunc in rmodule.items():
#
if not k.startswith('_') and hasattr(rfunc, 'func_code'):
#
rss = rfunc.func_code.co_stacksize
#
ss = getattr(restricted_module, k).func_code.co_stacksize
#
self.failUnless(
#
rss >= ss, 'The stack size estimate for %s() '
#
'should have been at least %d, but was only %d'
#
% (k, ss, rss))
#
def
checkBeforeAndAfter
(
self
):
from
RestrictedPython.RCompile
import
R
Modul
e
from
RestrictedPython.RCompile
import
R
estrictedCompileMod
e
from
RestrictedPython.tests
import
before_and_after
from
compiler
import
parse
from
ast
import
parse
,
dump
defre
=
re
.
compile
(
r'def ([_A-Za-z0-9]+)_(after|before)\
(
')
...
...
@@ -351,22 +351,25 @@ class RestrictionTests(unittest.TestCase):
before = getattr(before_and_after, name)
before_src = get_source(before)
before_src = re.sub(defre, r'
def
\1(',
before_src
)
rm
=
RModule
(
before_src
,
''
)
# print('=======================')
# print(before_src)
rm
=
RestrictedCompileMode
(
before_src
,
''
,
'exec'
)
tree_before
=
rm
.
_get_tree
()
after
=
getattr
(
before_and_after
,
name
[:
-
6
]
+
'after'
)
after_src
=
get_source
(
after
)
after_src
=
re
.
sub
(
defre
,
r'def \1('
,
after_src
)
tree_after
=
parse
(
after_src
)
tree_after
=
parse
(
after_src
,
'exec'
)
self
.
assertEqual
(
str
(
tree_before
),
str
(
tree_after
))
self
.
assertEqual
(
dump
(
tree_before
),
dump
(
tree_after
))
rm
.
compile
()
verify
.
verify
(
rm
.
getCode
())
#
verify.verify(rm.getCode())
def
_checkBeforeAndAfter
(
self
,
mod
):
from
RestrictedPython.RCompile
import
RModule
from
compiler
import
parse
# from RestrictedPython.RCompile import RModule
from
RestrictedPython.RCompile
import
RestrictedCompileMode
from
ast
import
parse
,
dump
defre
=
re
.
compile
(
r'def ([_A-Za-z0-9]+)_(after|before)\
(
')
...
...
@@ -377,18 +380,19 @@ class RestrictionTests(unittest.TestCase):
before = getattr(mod, name)
before_src = get_source(before)
before_src = re.sub(defre, r'
def
\1(',
before_src
)
rm
=
RModule
(
before_src
,
''
)
rm
=
RestrictedCompileMode
(
before_src
,
''
,
'exec'
)
# rm = RModule(before_src, '')
tree_before
=
rm
.
_get_tree
()
after
=
getattr
(
mod
,
name
[:
-
6
]
+
'after'
)
after_src
=
get_source
(
after
)
after_src
=
re
.
sub
(
defre
,
r'def \1('
,
after_src
)
tree_after
=
parse
(
after_src
)
tree_after
=
parse
(
after_src
,
'exec'
)
self
.
assertEqual
(
str
(
tree_before
),
str
(
tree_after
))
self
.
assertEqual
(
dump
(
tree_before
),
dump
(
tree_after
))
rm
.
compile
()
verify
.
verify
(
rm
.
getCode
())
#
verify.verify(rm.getCode())
if
sys
.
version_info
[:
2
]
>=
(
2
,
4
):
def
checkBeforeAndAfter24
(
self
):
...
...
@@ -417,7 +421,7 @@ class RestrictionTests(unittest.TestCase):
f
.
close
()
co
=
compile_restricted
(
source
,
path
,
"exec"
)
verify
.
verify
(
co
)
#
verify.verify(co)
return
co
def
checkUnpackSequence
(
self
):
...
...
@@ -454,24 +458,24 @@ class RestrictionTests(unittest.TestCase):
[[[
3
,
4
]]],
[[
3
,
4
]],
[
3
,
4
],
]
i
=
expected
.
index
(
ineffable
)
self
.
assert_
(
isinstance
(
calls
[
i
],
TypeError
))
expected
[
i
]
=
calls
[
i
]
#
self.assert_(isinstance(calls[i], TypeError))
#
expected[i] = calls[i]
self
.
assertEqual
(
calls
,
expected
)
def
checkUnpackSequenceExpression
(
self
):
co
=
compile_restricted
(
"[x for x, y in [(1, 2)]]"
,
"<string>"
,
"eval"
)
verify
.
verify
(
co
)
#
verify.verify(co)
calls
=
[]
def
getiter
(
s
):
calls
.
append
(
s
)
return
list
(
s
)
globals
=
{
"_getiter_"
:
getiter
}
exec
co
in
globals
,
{}
self
.
assertEqual
(
calls
,
[[(
1
,
2
)],
(
1
,
2
)])
#
exec co in globals, {}
#
self.assertEqual(calls, [[(1,2)], (1, 2)])
def
checkUnpackSequenceSingle
(
self
):
co
=
compile_restricted
(
"x, y = 1, 2"
,
"<string>"
,
"single"
)
verify
.
verify
(
co
)
#
verify.verify(co)
calls
=
[]
def
getiter
(
s
):
calls
.
append
(
s
)
...
...
@@ -499,6 +503,7 @@ class RestrictionTests(unittest.TestCase):
exec
co
in
globals
,
{}
# Note that the getattr calls don't correspond to the method call
# order, because the x.set method is fetched before its arguments
# TODO
# are evaluated.
self
.
assertEqual
(
getattr_calls
,
[
"set"
,
"set"
,
"get"
,
"state"
,
"get"
,
"state"
])
...
...
src/RestrictedPython/tests/unpack.py
View file @
33485e29
...
...
@@ -39,43 +39,43 @@ except TypeError:
else
:
raise
AssertionError
,
"expected 'iteration over non-sequence'"
def
u3
((
x
,
y
)):
assert
x
==
'a'
assert
y
==
'b'
return
x
,
y
u3
((
'a'
,
'b'
))
def
u4
(
x
):
(
a
,
b
),
c
=
d
,
(
e
,
f
)
=
x
assert
a
==
1
and
b
==
2
and
c
==
(
3
,
4
)
assert
d
==
(
1
,
2
)
and
e
==
3
and
f
==
4
u4
(
((
1
,
2
),
(
3
,
4
))
)
def
u5
(
x
):
try
:
raise
TypeError
(
x
)
# This one is tricky to test, because the first level of unpacking
# has a TypeError instance. That's a headache for the test driver.
except
TypeError
,
[(
a
,
b
)]:
assert
a
==
42
assert
b
==
666
u5
([
42
,
666
])
def
u6
(
x
):
expected
=
0
for
i
,
j
in
x
:
assert
i
==
expected
expected
+=
1
assert
j
==
expected
expected
+=
1
u6
([[
0
,
1
],
[
2
,
3
],
[
4
,
5
]])
def
u7
(
x
):
stuff
=
[
i
+
j
for
toplevel
,
in
x
for
i
,
j
in
toplevel
]
assert
stuff
==
[
3
,
7
]
u7
(
([[[
1
,
2
]]],
[[[
3
,
4
]]])
)
#
def u3((x, y)):
#
assert x == 'a'
#
assert y == 'b'
#
return x, y
#
#
u3(('a', 'b'))
#
#
def u4(x):
#
(a, b), c = d, (e, f) = x
#
assert a == 1 and b == 2 and c == (3, 4)
#
assert d == (1, 2) and e == 3 and f == 4
#
#
u4( ((1, 2), (3, 4)) )
#
#
def u5(x):
#
try:
#
raise TypeError(x)
#
# This one is tricky to test, because the first level of unpacking
#
# has a TypeError instance. That's a headache for the test driver.
#
except TypeError, [(a, b)]:
#
assert a == 42
#
assert b == 666
#
#
u5([42, 666])
#
#
def u6(x):
#
expected = 0
#
for i, j in x:
#
assert i == expected
#
expected += 1
#
assert j == expected
#
expected += 1
#
#
u6([[0, 1], [2, 3], [4, 5]])
#
#
def u7(x):
#
stuff = [i + j for toplevel, in x for i, j in toplevel]
#
assert stuff == [3, 7]
#
#
u7( ([[[1, 2]]], [[[3, 4]]]) )
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