Skip to content

Commit

Permalink
Merge branch 'master' into import_underscore_modul
Browse files Browse the repository at this point in the history
  • Loading branch information
loechel committed May 17, 2018
2 parents cf083b4 + 1b8b4c6 commit 780eeed
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 12 deletions.
3 changes: 3 additions & 0 deletions docs/CHANGES.rst
Expand Up @@ -25,6 +25,9 @@ Changes

- Imports like `from _a import b` or `from a._b import x` are now forbidden.

- Bring test coverage to 100 %.



4.0b3 (2018-04-12)
------------------
Expand Down
2 changes: 2 additions & 0 deletions setup.cfg
Expand Up @@ -53,6 +53,8 @@ omit =

[coverage:report]
precision = 2
show_missing = True
sort = Name

[coverage:html]
directory = _build/coverage
37 changes: 26 additions & 11 deletions src/RestrictedPython/transformer.py
Expand Up @@ -313,8 +313,11 @@ def gen_unpack_wrapper(self, node, target, ctx='store'):
ctx = ast.Store()
elif ctx == 'param':
ctx = ast.Param()
else:
raise Exception('Unsupported context type.')
else: # pragma: no cover
# Only store and param are defined ctx.
raise NotImplementedError(
'Unsupported context type: "{name}".'.format(name=type(ctx)),
)

# This node is used to catch the tuple in a tmp variable.
tmp_target = ast.Name(tmp_name, ctx)
Expand Down Expand Up @@ -380,8 +383,9 @@ def transform_slice(self, slice_):
dims.elts.append(self.transform_slice(item))
return dims

else:
raise Exception("Unknown slice type: {0}".format(slice_))
else: # pragma: no cover
# Index, Slice and ExtSlice are only defined Slice types.
raise NotImplementedError("Unknown slice type: {0}".format(slice_))

def check_name(self, node, name, allow_magic_methods=False):
"""Check names if they are allowed.
Expand Down Expand Up @@ -897,8 +901,10 @@ def visit_Attribute(self, node):
node.value = new_value
return node

else:
return self.node_contents_visit(node)
else: # pragma: no cover
# Impossible Case only ctx Load, Store and Del are defined in ast.
raise NotImplementedError(
"Unknown ctx type: {0}".format(type(node.ctx)))

# Subscripting

Expand Down Expand Up @@ -942,8 +948,10 @@ def visit_Subscript(self, node):
node.value = new_value
return node

else:
return node
else: # pragma: no cover
# Impossible Case only ctx Load, Store and Del are defined in ast.
raise NotImplementedError(
"Unknown ctx type: {0}".format(type(node.ctx)))

def visit_Index(self, node):
"""
Expand Down Expand Up @@ -1088,8 +1096,14 @@ def visit_AugAssign(self, node):

copy_locations(new_node, node)
return new_node

return node
else: # pragma: no cover
# Impossible Case - Only Node Types:
# * Name
# * Attribute
# * Subscript
# defined, those are checked before.
raise NotImplementedError(
"Unknown target type: {0}".format(type(node.target)))

def visit_Print(self, node):
"""Checks and mutates a print statement.
Expand Down Expand Up @@ -1297,6 +1311,7 @@ def visit_Lambda(self, node):
node = self.node_contents_visit(node)

if IS_PY3:
# Implicit Tuple unpacking is not anymore avaliable in Python3
return node

# Check for tuple parameters which need _getiter_ protection
Expand Down Expand Up @@ -1397,7 +1412,7 @@ def visit_Module(self, node):

# Inject the print collector after 'from __future__ import ....'
position = 0
for position, child in enumerate(node.body):
for position, child in enumerate(node.body): # pragma: no branch
if not isinstance(child, ast.ImportFrom):
break

Expand Down
27 changes: 27 additions & 0 deletions tests/test_Guards.py
@@ -1,6 +1,7 @@
from RestrictedPython._compat import IS_PY2
from RestrictedPython.Guards import guarded_unpack_sequence
from RestrictedPython.Guards import safe_builtins
from RestrictedPython.Guards import safer_getattr
from tests import e_eval
from tests import e_exec

Expand Down Expand Up @@ -187,3 +188,29 @@ def test_Guards__safer_getattr__2(e_exec):
assert 'Using format() on a unicode is not safe.' == str(err.value)
else:
assert 'Using format() on a str is not safe.' == str(err.value)


SAFER_GETATTR_ALLOWED = """\
class A:
def __init__(self, value):
self.value = value
a = A(2)
result = getattr(a, 'value')
"""


@pytest.mark.parametrize(*e_exec)
def test_Guards__safer_getattr__3(e_exec):
"""It allows to use `safer_getattr`."""
restricted_globals = dict(
__builtins__=safe_builtins,
__name__=None,
__metaclass__=type,
_write_=lambda x: x,
getattr=safer_getattr,
result=None,
)
e_exec(SAFER_GETATTR_ALLOWED, restricted_globals)
assert restricted_globals['result'] == 2
56 changes: 56 additions & 0 deletions tests/transformer/test_lambda.py
@@ -1,5 +1,6 @@
from RestrictedPython._compat import IS_PY2
from RestrictedPython._compat import IS_PY3
from RestrictedPython.Eval import default_guarded_getiter
from RestrictedPython.Guards import guarded_unpack_sequence
from tests import c_exec
from tests import e_exec
Expand Down Expand Up @@ -117,3 +118,58 @@ def test_RestrictingNodeTransformer__visit_Lambda__9(
assert 2 == _getiter_.call_count
_getiter_.assert_any_call((1, (2, 3)))
_getiter_.assert_any_call((2, 3))


LAMBDA_FUNC_1 = """
g = lambda x: x ** 2
"""


@pytest.mark.parametrize(*e_exec)
def test_RestrictingNodeTransformer__visit_Lambda__10(e_exec):
"""Simple lambda functions are allowed."""
restricted_globals = dict(
g=None,
)
e_exec(LAMBDA_FUNC_1, restricted_globals)
assert 4 == restricted_globals['g'](2)


LAMBDA_FUNC_2 = """
g = lambda (x, y) : (x ** 2, x + y)
"""


@pytest.mark.skipif(
IS_PY3,
reason="tuple parameter unpacking is gone in python 3")
@pytest.mark.parametrize(*e_exec)
def test_RestrictingNodeTransformer__visit_Lambda__11(e_exec):
"""Lambda functions with tuple unpacking are allowed."""
restricted_globals = dict(
g=None,
_unpack_sequence_=guarded_unpack_sequence,
_getiter_=default_guarded_getiter,
)
e_exec(LAMBDA_FUNC_2, restricted_globals)
assert (9, 5) == restricted_globals['g']((3, 2))


LAMBDA_FUNC_3 = """
g = lambda (x, y), z : (x ** y, x + z)
"""


@pytest.mark.skipif(
IS_PY3,
reason="tuple parameter unpacking is gone in python 3")
@pytest.mark.parametrize(*e_exec)
def test_RestrictingNodeTransformer__visit_Lambda__12(e_exec):
"""Lambda functions with tuple unpacking and simple params are allowed."""
restricted_globals = dict(
g=None,
_unpack_sequence_=guarded_unpack_sequence,
_getiter_=default_guarded_getiter,
)
e_exec(LAMBDA_FUNC_3, restricted_globals)
assert (64, 6) == restricted_globals['g']((4, 3), 2)
2 changes: 1 addition & 1 deletion tox.ini
Expand Up @@ -64,7 +64,7 @@ commands =
coverage combine
coverage html
coverage xml
coverage report
coverage report --fail-under=100.0

[testenv:isort-apply]
basepython = python2.7
Expand Down

0 comments on commit 780eeed

Please sign in to comment.