From fb8963744f58a0e64138f175b53b58570a536099 Mon Sep 17 00:00:00 2001 From: Alexander Loechel Date: Mon, 18 Sep 2017 22:11:26 +0200 Subject: [PATCH 1/3] add flake8 plugins flake8-isort and flake8-strict --- tox.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tox.ini b/tox.ini index 49521cd..690f8a5 100644 --- a/tox.ini +++ b/tox.ini @@ -100,6 +100,8 @@ deps = # Useful flake8 plugins that are Python and Plone specific: flake8-debugger flake8-todo + flake8-isort + flake8_strict isort commands = From 3d3b267b3790b7a091d3718fc85308d28b1336fd Mon Sep 17 00:00:00 2001 From: Alexander Loechel Date: Mon, 18 Sep 2017 22:43:07 +0200 Subject: [PATCH 2/3] apply flake8 fixes to tests --- setup.py | 88 +++++++++----------- tests/test_Guards.py | 12 ++- tests/test_compile.py | 36 +++++--- tests/test_compile_restricted_function.py | 18 ++-- tests/test_print_function.py | 28 +++++-- tests/test_print_stmt.py | 42 +++++++--- tests/transformer/test_assign.py | 11 +-- tests/transformer/test_async.py | 12 ++- tests/transformer/test_attribute.py | 28 +++---- tests/transformer/test_augassign.py | 17 ++-- tests/transformer/test_call.py | 4 +- tests/transformer/test_classdef.py | 17 +++- tests/transformer/test_conditional.py | 14 ++-- tests/transformer/test_dict_comprehension.py | 2 +- tests/transformer/test_functiondef.py | 41 +++++---- tests/transformer/test_generic.py | 6 +- tests/transformer/test_iterator.py | 11 +-- tests/transformer/test_lambda.py | 5 +- tests/transformer/test_subscript.py | 35 ++++---- tests/transformer/test_try.py | 36 ++++---- tests/transformer/test_with_stmt.py | 11 +-- 21 files changed, 261 insertions(+), 213 deletions(-) diff --git a/setup.py b/setup.py index 06cb2a2..1efb196 100644 --- a/setup.py +++ b/setup.py @@ -29,52 +29,42 @@ def read(*rnames): ] -setup(name='RestrictedPython', - version='4.0b3.dev0', - url='http://pypi.python.org/pypi/RestrictedPython', - license='ZPL 2.1', - description='RestrictedPython is a defined subset of the Python ' - 'language which allows to provide a program input into ' - 'a trusted environment.', - long_description=(read('README.rst') + '\n' + - read('docs', 'CHANGES.rst')), - classifiers=[ - 'License :: OSI Approved :: Zope Public License', - 'Programming Language :: Python', - 'Operating System :: OS Independent', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: Implementation :: CPython', - 'Topic :: Security', - ], - keywords='restricted execution security untrusted code', - author='Zope Foundation and Contributors', - author_email='zope-dev@zope.org', - packages=find_packages('src'), - package_dir={'': 'src'}, - install_requires=[ - 'setuptools', - - ], - setup_requires=[ - 'pytest-runner', - ], - tests_require=tests_require, - extras_require={ - 'docs': [ - 'Sphinx', - ], - 'test': tests_require, - 'release': [ - 'zest.releaser', - ], - 'develop': [ - 'pdbpp', - 'isort', - ], - }, - include_package_data=True, - zip_safe=False, - ) +setup( + name='RestrictedPython', + version='4.0b3.dev0', + url='http://pypi.python.org/pypi/RestrictedPython', + license='ZPL 2.1', + description='RestrictedPython is a defined subset of the Python ' + 'language which allows to provide a program input into ' + 'a trusted environment.', + long_description=(read('README.rst') + '\n' + + read('docs', 'CHANGES.rst')), + classifiers=[ + 'License :: OSI Approved :: Zope Public License', + 'Programming Language :: Python', + 'Operating System :: OS Independent', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: Implementation :: CPython', + 'Topic :: Security', + ], + keywords='restricted execution security untrusted code', + author='Zope Foundation and Contributors', + author_email='zope-dev@zope.org', + packages=find_packages('src'), + package_dir={'': 'src'}, + install_requires=[ + 'setuptools', + ], + setup_requires=[ + 'pytest-runner', + ], + tests_require=tests_require, + extras_require={ + 'test': tests_require, + }, + include_package_data=True, + zip_safe=False, +) diff --git a/tests/test_Guards.py b/tests/test_Guards.py index 0155668..7732fec 100644 --- a/tests/test_Guards.py +++ b/tests/test_Guards.py @@ -35,7 +35,8 @@ def display(self): __name__='restricted_module', __metaclass__=type, _write_=lambda x: x, - _getattr_=getattr) + _getattr_=getattr, + ) e_exec(class_can_be_defined_code, restricted_globals) assert restricted_globals['result'] == '2411' @@ -62,7 +63,8 @@ class MyObjectD: __name__='restricted_module', __metaclass__=type, _write_=lambda x: x, - _getattr_=getattr,) + _getattr_=getattr, + ) e_exec(setattr_code, restricted_globals) assert 9999 == restricted_globals['my_object_d'].value @@ -89,7 +91,8 @@ class ObjWithoutGuardedWrites: __name__='restricted_module', __metaclass__=type, _write_=lambda x: x, - _getattr_=getattr,) + _getattr_=getattr, + ) with pytest.raises(TypeError) as excinfo: e_exec(setattr_without_guarded_writes_code, restricted_globals) @@ -118,7 +121,8 @@ def __guarded_setattr__(self, key, value): __name__='restricted_module', __metaclass__=type, _write_=lambda x: x, - _getattr_=getattr,) + _getattr_=getattr, + ) e_exec(set_attribute_using_guarded_setattr_code, restricted_globals) assert restricted_globals['myobj_with_guarded_setattr'].my_attr == 'bar' diff --git a/tests/test_compile.py b/tests/test_compile.py index d27bc13..b6283d5 100644 --- a/tests/test_compile.py +++ b/tests/test_compile.py @@ -64,7 +64,8 @@ def test_compile__compile_restricted_exec__3(c_exec): result = c_exec('_a = 42\n_b = 43') errors = ( 'Line 1: "_a" is an invalid variable name because it starts with "_"', - 'Line 2: "_b" is an invalid variable name because it starts with "_"') + 'Line 2: "_b" is an invalid variable name because it starts with "_"', + ) assert result.errors == errors assert result.warnings == [] assert result.used_names == {} @@ -79,7 +80,8 @@ def test_compile__compile_restricted_exec__4(c_exec): assert result.warnings == [] assert result.used_names == {} assert result.errors == ( - 'Line 1: SyntaxError: invalid syntax in on statement: asdf|',) + 'Line 1: SyntaxError: invalid syntax in on statement: asdf|', + ) @pytest.mark.parametrize(*c_exec) @@ -91,10 +93,12 @@ def test_compile__compile_restricted_exec__5(c_exec): assert result.used_names == {} if IS_PY2: assert result.errors == ( - 'compile() expected string without null bytes',) + 'compile() expected string without null bytes', + ) else: assert result.errors == ( - 'source code string cannot contain null bytes',) + 'source code string cannot contain null bytes', + ) EXEC_STATEMENT = """\ @@ -110,9 +114,10 @@ def no_exec(): def test_compile__compile_restricted_exec__10(c_exec): """It is a SyntaxError to use the `exec` statement. (Python 3 only)""" result = c_exec(EXEC_STATEMENT) - assert ( + assert result.errors == ( "Line 2: SyntaxError: Missing parentheses in call to 'exec' in on " - "statement: exec 'q = 1'",) == result.errors + "statement: exec 'q = 1'", + ) FUNCTION_DEF = """\ @@ -129,7 +134,8 @@ def test_compile__compile_restricted_eval__1(c_eval): """ result = c_eval(FUNCTION_DEF) assert result.errors == ( - 'Line 1: SyntaxError: invalid syntax in on statement: def a():',) + 'Line 1: SyntaxError: invalid syntax in on statement: def a():', + ) @pytest.mark.parametrize(*e_eval) @@ -143,7 +149,12 @@ def test_compile__compile_restricted_eval__used_names(c_eval): result = c_eval("a + b + func(x)") assert result.errors == () assert result.warnings == [] - assert result.used_names == {'a': True, 'b': True, 'x': True, 'func': True} + assert result.used_names == { + 'a': True, + 'b': True, + 'x': True, + 'func': True, + } @pytest.mark.parametrize(*c_single) @@ -165,7 +176,8 @@ def a(): @pytest.mark.skipif( IS_PY3, reason="Print statement is gone in Python 3." - "Test Deprecation Warming in Python 2") + "Test Deprecation Warning in Python 2" +) def test_compile_restricted(): """This test checks compile_restricted itself if that emit Python warnings. For actual tests for print statement see: test_print_stmt.py @@ -190,6 +202,8 @@ def a(): def test_compile_restricted_eval(): """This test checks compile_restricted itself if that raise Python errors. """ - with pytest.raises(SyntaxError, - message="Line 3: Eval calls are not allowed."): + with pytest.raises( + SyntaxError, + message="Line 3: Eval calls are not allowed.", + ): compile_restricted(EVAL_EXAMPLE, '', 'exec') diff --git a/tests/test_compile_restricted_function.py b/tests/test_compile_restricted_function.py index ca51aba..85950c7 100644 --- a/tests/test_compile_restricted_function.py +++ b/tests/test_compile_restricted_function.py @@ -21,7 +21,7 @@ def test_compile_restricted_function(c_function): body, name, filename='', - globalize=global_symbols + globalize=global_symbols, ) assert result.code is not None @@ -30,7 +30,7 @@ def test_compile_restricted_function(c_function): safe_globals = { '__name__': 'script', '_getattr_': getattr, - '_print_': PrintCollector + '_print_': PrintCollector, } safe_globals.update(safe_builtins) safe_locals = {} @@ -55,7 +55,7 @@ def test_compile_restricted_function_func_wrapped(c_function): body, name, filename='', - globalize=global_symbols + globalize=global_symbols, ) assert result.code is not None @@ -89,7 +89,7 @@ def test_compile_restricted_function_with_arguments(c_function): body, name, filename='', - globalize=global_symbols + globalize=global_symbols, ) assert result.code is not None @@ -98,7 +98,7 @@ def test_compile_restricted_function_with_arguments(c_function): safe_globals = { '__name__': 'script', '_getattr_': getattr, - '_print_': PrintCollector + '_print_': PrintCollector, } safe_globals.update(safe_builtins) safe_locals = {} @@ -123,7 +123,7 @@ def test_compile_restricted_function_can_access_global_variables(c_function): body, name, filename='', - globalize=global_symbols + globalize=global_symbols, ) assert result.code is not None @@ -133,7 +133,7 @@ def test_compile_restricted_function_can_access_global_variables(c_function): '__name__': 'script', '_getattr_': getattr, 'input': 'Hello World!', - '_print_': PrintCollector + '_print_': PrintCollector, } safe_globals.update(safe_builtins) safe_locals = {} @@ -155,7 +155,7 @@ def test_compile_restricted_function_pretends_the_code_is_executed_in_a_global_s body, name, filename='', - globalize=global_symbols + globalize=global_symbols, ) assert result.code is not None @@ -186,7 +186,7 @@ def test_compile_restricted_function_allows_invalid_python_identifiers_as_functi body, name, filename='', - globalize=global_symbols + globalize=global_symbols, ) assert result.code is not None diff --git a/tests/test_print_function.py b/tests/test_print_function.py index d29fa18..793403b 100644 --- a/tests/test_print_function.py +++ b/tests/test_print_function.py @@ -45,7 +45,10 @@ def test_print_function__simple_prints(): - glb = {'_print_': PrintCollector, '_getattr_': None} + glb = { + '_print_': PrintCollector, + '_getattr_': None, + } code, errors = compiler(ALLOWED_PRINT_FUNCTION)[:2] assert errors == () @@ -104,7 +107,7 @@ def test_print_function_with_star_args(mocker): glb = { '_print_': PrintCollector, '_getattr_': None, - "_apply_": _apply_ + "_apply_": _apply_, } code, errors = compiler(ALLOWED_PRINT_FUNCTION_WITH_STAR_ARGS)[:2] @@ -130,7 +133,7 @@ def test_print_function_with_kw_args(mocker): glb = { '_print_': PrintCollector, '_getattr_': None, - "_apply_": _apply_ + "_apply_": _apply_, } code, errors = compiler(ALLOWED_PRINT_FUNCTION_WITH_KWARGS)[:2] @@ -145,7 +148,8 @@ def test_print_function_with_kw_args(mocker): 3, end='!', file=None, - sep='-') + sep='-', + ) PROTECT_WRITE_ON_FILE = """ @@ -163,7 +167,7 @@ def test_print_function__protect_file(mocker): glb = { '_print_': PrintCollector, '_getattr_': _getattr_, - 'stream': stream + 'stream': stream, } code, errors = compiler(PROTECT_WRITE_ON_FILE)[:2] @@ -177,7 +181,7 @@ def test_print_function__protect_file(mocker): mocker.call('a'), mocker.call(' '), mocker.call('b'), - mocker.call('\n') + mocker.call('\n'), ]) @@ -306,7 +310,7 @@ def test_print_function_no_new_scope(): '_print_': PrintCollector, '__metaclass__': type, '_getattr_': None, - '_getiter_': lambda ob: ob + '_getiter_': lambda ob: ob, } exec(code, glb) @@ -334,7 +338,10 @@ def do_stuff(func): def test_print_function_pass_print_function(): code, errors = compiler(PASS_PRINT_FUNCTION)[:2] - glb = {'_print_': PrintCollector, '_getattr_': None} + glb = { + '_print_': PrintCollector, + '_getattr_': None, + } exec(code, glb) ret = glb['main']() @@ -352,7 +359,10 @@ def func(cond): def test_print_function_conditional_print(): code, errors = compiler(CONDITIONAL_PRINT)[:2] - glb = {'_print_': PrintCollector, '_getattr_': None} + glb = { + '_print_': PrintCollector, + '_getattr_': None, + } exec(code, glb) assert glb['func'](True) == '1\n' diff --git a/tests/test_print_stmt.py b/tests/test_print_stmt.py index 2c7362d..d3a0bd4 100644 --- a/tests/test_print_stmt.py +++ b/tests/test_print_stmt.py @@ -7,7 +7,8 @@ pytestmark = pytest.mark.skipif( IS_PY3, - reason="print statement no longer exists in Python 3") + reason="print statement no longer exists in Python 3", +) ALLOWED_PRINT_STATEMENT = """ @@ -35,7 +36,10 @@ @pytest.mark.parametrize(*c_exec) def test_print_stmt__simple_prints(c_exec): - glb = {'_print_': PrintCollector, '_getattr_': None} + glb = { + '_print_': PrintCollector, + '_getattr_': None, + } code, errors = c_exec(ALLOWED_PRINT_STATEMENT)[:2] assert code is not None @@ -75,7 +79,10 @@ def test_print_stmt__fail_with_none_target(c_exec, mocker): assert code is not None assert errors == () - glb = {'_getattr_': getattr, '_print_': PrintCollector} + glb = { + '_getattr_': getattr, + '_print_': PrintCollector, + } with pytest.raises(AttributeError) as excinfo: exec(code, glb) @@ -95,7 +102,10 @@ def test_print_stmt__protect_chevron_print(c_exec, mocker): _getattr_ = mocker.stub() _getattr_.side_effect = getattr - glb = {'_getattr_': _getattr_, '_print_': PrintCollector} + glb = { + '_getattr_': _getattr_, + '_print_': PrintCollector, + } exec(code, glb) @@ -105,7 +115,7 @@ def test_print_stmt__protect_chevron_print(c_exec, mocker): stream.write.assert_has_calls([ mocker.call('Hello World!'), - mocker.call('\n') + mocker.call('\n'), ]) _getattr_.assert_called_once_with(stream, 'write') @@ -136,7 +146,10 @@ def main(): def test_print_stmt__nested_print_collector(c_exec, mocker): code, errors = c_exec(INJECT_PRINT_COLLECTOR_NESTED)[:2] - glb = {"_print_": PrintCollector, '_getattr_': None} + glb = { + "_print_": PrintCollector, + '_getattr_': None, + } exec(code, glb) ret = glb['main']() @@ -156,7 +169,8 @@ def test_print_stmt__with_printed_no_print(c_exec): assert code is not None assert errors == () assert warnings == [ - "Line 2: Doesn't print, but reads 'printed' variable."] + "Line 2: Doesn't print, but reads 'printed' variable.", + ] WARN_PRINTED_NO_PRINT_NESTED = """ @@ -175,7 +189,7 @@ def test_print_stmt__with_printed_no_print_nested(c_exec): assert errors == () assert warnings == [ "Line 2: Print statement is deprecated and not avaliable anymore in Python 3.", # NOQA: E501 - "Line 3: Doesn't print, but reads 'printed' variable." + "Line 3: Doesn't print, but reads 'printed' variable.", ] @@ -193,7 +207,7 @@ def test_print_stmt__with_print_no_printed(c_exec): assert errors == () assert warnings == [ "Line 3: Print statement is deprecated and not avaliable anymore in Python 3.", # NOQA: E501 - "Line 2: Prints, but never reads 'printed' variable." + "Line 2: Prints, but never reads 'printed' variable.", ] @@ -234,7 +248,10 @@ class A: @pytest.mark.parametrize(*c_exec) def test_print_stmt_no_new_scope(c_exec): code, errors = c_exec(NO_PRINT_SCOPES)[:2] - glb = {'_print_': PrintCollector, '_getattr_': None} + glb = { + '_print_': PrintCollector, + '_getattr_': None, + } exec(code, glb) ret = glb['class_scope']() @@ -252,7 +269,10 @@ def func(cond): @pytest.mark.parametrize(*c_exec) def test_print_stmt_conditional_print(c_exec): code, errors = c_exec(CONDITIONAL_PRINT)[:2] - glb = {'_print_': PrintCollector, '_getattr_': None} + glb = { + '_print_': PrintCollector, + '_getattr_': None, + } exec(code, glb) assert glb['func'](True) == '1\n' diff --git a/tests/transformer/test_assign.py b/tests/transformer/test_assign.py index d7d4314..46cd581 100644 --- a/tests/transformer/test_assign.py +++ b/tests/transformer/test_assign.py @@ -33,10 +33,10 @@ def test_RestrictingNodeTransformer__visit_Assign__1(e_exec, mocker): @pytest.mark.skipif( IS_PY2, - reason="starred assignments are python3 only") + reason="starred assignments are python3 only", +) @pytest.mark.parametrize(*e_exec) -def test_RestrictingNodeTransformer__visit_Assign__2( - e_exec, mocker): +def test_RestrictingNodeTransformer__visit_Assign__2(e_exec, mocker): src = "a, *d, (c, *e), x = (1, 2, 3, (4, 3, 4), 5)" _getiter_ = mocker.stub() @@ -44,7 +44,7 @@ def test_RestrictingNodeTransformer__visit_Assign__2( glb = { '_getiter_': _getiter_, - '_unpack_sequence_': guarded_unpack_sequence + '_unpack_sequence_': guarded_unpack_sequence, } e_exec(src, glb) @@ -56,4 +56,5 @@ def test_RestrictingNodeTransformer__visit_Assign__2( _getiter_.assert_has_calls([ mocker.call((1, 2, 3, (4, 3, 4), 5)), - mocker.call((4, 3, 4))]) + mocker.call((4, 3, 4)), + ]) diff --git a/tests/transformer/test_async.py b/tests/transformer/test_async.py index f09a738..b1cccdc 100644 --- a/tests/transformer/test_async.py +++ b/tests/transformer/test_async.py @@ -8,7 +8,8 @@ pytestmark = pytest.mark.skipif( not IS_PY35_OR_GREATER, - reason="async statement was first introduced in Python 3.5") + reason="async statement was first introduced in Python 3.5", +) # Example from https://docs.python.org/3/library/asyncio-task.html @@ -70,7 +71,8 @@ async def display_date(loop): def test_await(c_exec): result = compile_restricted_exec( AWAIT_EXAMPLE, - policy=RestrictingAsyncNodeTransformer) + policy=RestrictingAsyncNodeTransformer, + ) assert result.errors == ('Line 11: Await statements are not allowed.',) assert result.code is None @@ -87,7 +89,8 @@ async def square_series(con, to): def test_async_with(c_exec): result = compile_restricted_exec( ASYNC_WITH_EXAMPLE, - policy=RestrictingAsyncNodeTransformer) + policy=RestrictingAsyncNodeTransformer, + ) assert result.errors == ('Line 3: AsyncWith statements are not allowed.',) assert result.code is None @@ -104,6 +107,7 @@ async def read_rows(rows): def test_async_for(c_exec): result = compile_restricted_exec( ASYNC_FOR_EXAMPLE, - policy=RestrictingAsyncNodeTransformer) + policy=RestrictingAsyncNodeTransformer, + ) assert result.errors == ('Line 3: AsyncFor statements are not allowed.',) assert result.code is None diff --git a/tests/transformer/test_attribute.py b/tests/transformer/test_attribute.py index 3159fff..879ccd2 100644 --- a/tests/transformer/test_attribute.py +++ b/tests/transformer/test_attribute.py @@ -17,7 +17,8 @@ def test_RestrictingNodeTransformer__visit_Attribute__1(c_exec): result = c_exec(BAD_ATTR_UNDERSCORE) assert result.errors == ( 'Line 3: "_some_attr" is an invalid attribute name because it ' - 'starts with "_".',) + 'starts with "_".', + ) BAD_ATTR_ROLES = """\ @@ -33,7 +34,8 @@ def test_RestrictingNodeTransformer__visit_Attribute__2(c_exec): result = c_exec(BAD_ATTR_ROLES) assert result.errors == ( 'Line 3: "abc__roles__" is an invalid attribute name because it ' - 'ends with "__roles__".',) + 'ends with "__roles__".', + ) TRANSFORM_ATTRIBUTE_ACCESS = """\ @@ -43,13 +45,12 @@ def func(): @pytest.mark.parametrize(*e_exec) -def test_RestrictingNodeTransformer__visit_Attribute__3( - e_exec, mocker): +def test_RestrictingNodeTransformer__visit_Attribute__3(e_exec, mocker): """It transforms the attribute access to `_getattr_`.""" glb = { '_getattr_': mocker.stub(), 'a': [], - 'b': 'b' + 'b': 'b', } e_exec(TRANSFORM_ATTRIBUTE_ACCESS, glb) glb['func']() @@ -71,8 +72,7 @@ def test_RestrictingNodeTransformer__visit_Attribute__4(c_exec): @pytest.mark.parametrize(*e_exec) -def test_RestrictingNodeTransformer__visit_Attribute__5( - e_exec, mocker): +def test_RestrictingNodeTransformer__visit_Attribute__5(e_exec, mocker): """It transforms writing to an attribute to `_write_`.""" glb = { '_write_': mocker.stub(), @@ -87,8 +87,7 @@ def test_RestrictingNodeTransformer__visit_Attribute__5( @pytest.mark.parametrize(*e_exec) -def test_RestrictingNodeTransformer__visit_Attribute__5_5( - e_exec, mocker): +def test_RestrictingNodeTransformer__visit_Attribute__5_5(e_exec, mocker): """It transforms deleting of an attribute to `_write_`.""" glb = { '_write_': mocker.stub(), @@ -117,7 +116,8 @@ def test_RestrictingNodeTransformer__visit_Attribute__6(c_exec): result = c_exec(DISALLOW_TRACEBACK_ACCESS) assert result.errors == ( 'Line 5: "__traceback__" is an invalid attribute name because ' - 'it starts with "_".',) + 'it starts with "_".', + ) TRANSFORM_ATTRIBUTE_ACCESS_FUNCTION_DEFAULT = """ @@ -127,8 +127,7 @@ def func_default(x=a.a): @pytest.mark.parametrize(*e_exec) -def test_RestrictingNodeTransformer__visit_Attribute__7( - e_exec, mocker): +def test_RestrictingNodeTransformer__visit_Attribute__7(e_exec, mocker): """It transforms attribute access in function default kw to `_write_`.""" _getattr_ = mocker.Mock() _getattr_.side_effect = getattr @@ -145,15 +144,14 @@ def test_RestrictingNodeTransformer__visit_Attribute__7( @pytest.mark.parametrize(*e_exec) -def test_RestrictingNodeTransformer__visit_Attribute__8( - e_exec, mocker): +def test_RestrictingNodeTransformer__visit_Attribute__8(e_exec, mocker): """It transforms attribute access in lamda default kw to `_write_`.""" _getattr_ = mocker.Mock() _getattr_.side_effect = getattr glb = { '_getattr_': _getattr_, - 'b': mocker.Mock(b=2) + 'b': mocker.Mock(b=2), } e_exec('lambda_default = lambda x=b.b: x', glb) diff --git a/tests/transformer/test_augassign.py b/tests/transformer/test_augassign.py index 43b5dcc..94f1e11 100644 --- a/tests/transformer/test_augassign.py +++ b/tests/transformer/test_augassign.py @@ -5,8 +5,7 @@ @pytest.mark.parametrize(*e_exec) -def test_RestrictingNodeTransformer__visit_AugAssign__1( - e_exec, mocker): +def test_RestrictingNodeTransformer__visit_AugAssign__1(e_exec, mocker): """It allows augmented assign for variables.""" _inplacevar_ = mocker.stub() _inplacevar_.side_effect = lambda op, val, expr: val + expr @@ -15,7 +14,7 @@ def test_RestrictingNodeTransformer__visit_AugAssign__1( '_inplacevar_': _inplacevar_, 'a': 1, 'x': 1, - 'z': 0 + 'z': 0, } e_exec("a += x + z", glb) @@ -29,7 +28,8 @@ def test_RestrictingNodeTransformer__visit_AugAssign__2(c_exec): """It forbids augmented assign of attributes.""" result = c_exec("a.a += 1") assert result.errors == ( - 'Line 1: Augmented assignment of attributes is not allowed.',) + 'Line 1: Augmented assignment of attributes is not allowed.', + ) @pytest.mark.parametrize(*c_exec) @@ -38,7 +38,8 @@ def test_RestrictingNodeTransformer__visit_AugAssign__3(c_exec): result = c_exec("a[a] += 1") assert result.errors == ( 'Line 1: Augmented assignment of object items and slices is not ' - 'allowed.',) + 'allowed.', + ) @pytest.mark.parametrize(*c_exec) @@ -47,7 +48,8 @@ def test_RestrictingNodeTransformer__visit_AugAssign__4(c_exec): result = c_exec("a[x:y] += 1") assert result.errors == ( 'Line 1: Augmented assignment of object items and slices is not ' - 'allowed.',) + 'allowed.', + ) @pytest.mark.parametrize(*c_exec) @@ -56,4 +58,5 @@ def test_RestrictingNodeTransformer__visit_AugAssign__5(c_exec): result = c_exec("a[x:y:z] += 1") assert result.errors == ( 'Line 1: Augmented assignment of object items and slices is not ' - 'allowed.',) + 'allowed.', + ) diff --git a/tests/transformer/test_call.py b/tests/transformer/test_call.py index 4ab5677..42a70ce 100644 --- a/tests/transformer/test_call.py +++ b/tests/transformer/test_call.py @@ -12,7 +12,7 @@ def test_RestrictingNodeTransformer__visit_Call__1(c_exec): loc = {} exec(result.code, {}, loc) assert loc['a'] == 3 - assert result.used_names == {'max': True} + assert result.used_names == {'max': True, } # def f(a, b, c): pass @@ -57,7 +57,7 @@ def test_RestrictingNodeTransformer__visit_Call__2(e_exec, mocker): glb = { '_apply_': _apply_, - 'foo': lambda *args, **kwargs: (args, kwargs) + 'foo': lambda *args, **kwargs: (args, kwargs), } e_exec(FUNCTIONC_CALLS, glb) diff --git a/tests/transformer/test_classdef.py b/tests/transformer/test_classdef.py index 1a3e0a4..f65a4f5 100644 --- a/tests/transformer/test_classdef.py +++ b/tests/transformer/test_classdef.py @@ -32,7 +32,8 @@ def test_RestrictingNodeTransformer__visit_ClassDef__2(c_exec): result = c_exec(BAD_CLASS) assert result.errors == ( 'Line 1: "_bad" is an invalid variable name ' - 'because it starts with "_"',) + 'because it starts with "_"', + ) IMPLICIT_METACLASS = ''' @@ -53,7 +54,10 @@ def _metaclass(name, bases, dict): return ob restricted_globals = dict( - __metaclass__=_metaclass, b=None, _getattr_=getattr) + __metaclass__=_metaclass, + b=None, + _getattr_=getattr, + ) e_exec(IMPLICIT_METACLASS, restricted_globals) @@ -99,8 +103,13 @@ def test_RestrictingNodeTransformer__visit_ClassDef__5(e_exec): """It preserves base classes and decorators for classes.""" restricted_globals = dict( - comb=None, _getattr_=getattr, _write_=lambda x: x, __metaclass__=type, - __name__='restricted_module', __builtins__=safe_builtins) + comb=None, + _getattr_=getattr, + _write_=lambda x: x, + __metaclass__=type, + __name__='restricted_module', + __builtins__=safe_builtins, + ) e_exec(DECORATED_CLASS, restricted_globals) diff --git a/tests/transformer/test_conditional.py b/tests/transformer/test_conditional.py index d3c05d5..925dec6 100644 --- a/tests/transformer/test_conditional.py +++ b/tests/transformer/test_conditional.py @@ -4,8 +4,7 @@ @pytest.mark.parametrize(*e_exec) -def test_RestrictingNodeTransformer__test_ternary_if( - e_exec, mocker): +def test_RestrictingNodeTransformer__test_ternary_if(e_exec, mocker): src = 'x.y = y.a if y.z else y.b' _getattr_ = mocker.stub() _getattr_.side_effect = lambda ob, key: ob[key] @@ -16,7 +15,10 @@ def test_RestrictingNodeTransformer__test_ternary_if( '_getattr_': _getattr_, '_write_': _write_, 'x': mocker.stub(), - 'y': {'a': 'a', 'b': 'b'}, + 'y': { + 'a': 'a', + 'b': 'b', + }, } glb['y']['z'] = True @@ -26,7 +28,8 @@ def test_RestrictingNodeTransformer__test_ternary_if( _write_.assert_called_once_with(glb['x']) _getattr_.assert_has_calls([ mocker.call(glb['y'], 'z'), - mocker.call(glb['y'], 'a')]) + mocker.call(glb['y'], 'a'), + ]) _write_.reset_mock() _getattr_.reset_mock() @@ -38,4 +41,5 @@ def test_RestrictingNodeTransformer__test_ternary_if( _write_.assert_called_once_with(glb['x']) _getattr_.assert_has_calls([ mocker.call(glb['y'], 'z'), - mocker.call(glb['y'], 'b')]) + mocker.call(glb['y'], 'b'), + ]) diff --git a/tests/transformer/test_dict_comprehension.py b/tests/transformer/test_dict_comprehension.py index f0ea9d6..f839397 100644 --- a/tests/transformer/test_dict_comprehension.py +++ b/tests/transformer/test_dict_comprehension.py @@ -32,5 +32,5 @@ def test_dict_comprehension_with_attrs(e_exec, mocker): mocker.call(z[0], 'k'), mocker.call(z[1], 'k'), mocker.call(z[1], 'v'), - mocker.call(z[1], 'k') + mocker.call(z[1], 'k'), ]) diff --git a/tests/transformer/test_functiondef.py b/tests/transformer/test_functiondef.py index 7f5b0c2..92d772c 100644 --- a/tests/transformer/test_functiondef.py +++ b/tests/transformer/test_functiondef.py @@ -12,8 +12,7 @@ @pytest.mark.parametrize(*c_exec) -def test_RestrictingNodeTransformer__visit_FunctionDef__1( - c_exec): +def test_RestrictingNodeTransformer__visit_FunctionDef__1(c_exec): """It prevents function arguments starting with `_`.""" result = c_exec("def foo(_bad): pass") # RestrictedPython.compile.compile_restricted_exec on Python 2 renders @@ -23,8 +22,7 @@ def test_RestrictingNodeTransformer__visit_FunctionDef__1( @pytest.mark.parametrize(*c_exec) -def test_RestrictingNodeTransformer__visit_FunctionDef__2( - c_exec): +def test_RestrictingNodeTransformer__visit_FunctionDef__2(c_exec): """It prevents function keyword arguments starting with `_`.""" result = c_exec("def foo(_bad=1): pass") # RestrictedPython.compile.compile_restricted_exec on Python 2 renders @@ -34,16 +32,14 @@ def test_RestrictingNodeTransformer__visit_FunctionDef__2( @pytest.mark.parametrize(*c_exec) -def test_RestrictingNodeTransformer__visit_FunctionDef__3( - c_exec): +def test_RestrictingNodeTransformer__visit_FunctionDef__3(c_exec): """It prevents function * arguments starting with `_`.""" result = c_exec("def foo(*_bad): pass") assert result.errors == (functiondef_err_msg,) @pytest.mark.parametrize(*c_exec) -def test_RestrictingNodeTransformer__visit_FunctionDef__4( - c_exec): +def test_RestrictingNodeTransformer__visit_FunctionDef__4(c_exec): """It prevents function ** arguments starting with `_`.""" result = c_exec("def foo(**_bad): pass") assert result.errors == (functiondef_err_msg,) @@ -51,10 +47,10 @@ def test_RestrictingNodeTransformer__visit_FunctionDef__4( @pytest.mark.skipif( IS_PY3, - reason="tuple parameter unpacking is gone in Python 3") + reason="tuple parameter unpacking is gone in Python 3", +) @pytest.mark.parametrize(*c_exec) -def test_RestrictingNodeTransformer__visit_FunctionDef__5( - c_exec): +def test_RestrictingNodeTransformer__visit_FunctionDef__5(c_exec): """It prevents function arguments starting with `_` in tuples.""" result = c_exec("def foo((a, _bad)): pass") # RestrictedPython.compile.compile_restricted_exec on Python 2 renders @@ -65,10 +61,10 @@ def test_RestrictingNodeTransformer__visit_FunctionDef__5( @pytest.mark.skipif( IS_PY3, - reason="tuple parameter unpacking is gone in Python 3") + reason="tuple parameter unpacking is gone in Python 3", +) @pytest.mark.parametrize(*c_exec) -def test_RestrictingNodeTransformer__visit_FunctionDef__6( - c_exec): +def test_RestrictingNodeTransformer__visit_FunctionDef__6(c_exec): """It prevents function arguments starting with `_` in tuples.""" result = c_exec("def foo(a, (c, (_bad, c))): pass") # RestrictedPython.compile.compile_restricted_exec on Python 2 renders @@ -79,10 +75,10 @@ def test_RestrictingNodeTransformer__visit_FunctionDef__6( @pytest.mark.skipif( IS_PY2, - reason="There is no single `*` argument in Python 2") + reason="There is no single `*` argument in Python 2", +) @pytest.mark.parametrize(*c_exec) -def test_RestrictingNodeTransformer__visit_FunctionDef__7( - c_exec): +def test_RestrictingNodeTransformer__visit_FunctionDef__7(c_exec): """It prevents `_` function arguments together with a single `*`.""" result = c_exec("def foo(good, *, _bad): pass") assert result.errors == (functiondef_err_msg,) @@ -99,16 +95,16 @@ def nested_with_order((a, b), (c, d)): @pytest.mark.skipif( IS_PY3, - reason="tuple parameter unpacking is gone in python 3") + reason="tuple parameter unpacking is gone in python 3", +) @pytest.mark.parametrize(*e_exec) -def test_RestrictingNodeTransformer__visit_FunctionDef__8( - e_exec, mocker): +def test_RestrictingNodeTransformer__visit_FunctionDef__8(e_exec, mocker): _getiter_ = mocker.stub() _getiter_.side_effect = lambda it: it glb = { '_getiter_': _getiter_, - '_unpack_sequence_': guarded_unpack_sequence + '_unpack_sequence_': guarded_unpack_sequence, } e_exec('def simple((a, b)): return a, b', glb) @@ -134,5 +130,6 @@ def test_RestrictingNodeTransformer__visit_FunctionDef__8( assert ret == (1, 2, 3, 4) _getiter_.assert_has_calls([ mocker.call((1, 2)), - mocker.call((3, 4))]) + mocker.call((3, 4)), + ]) _getiter_.reset_mock() diff --git a/tests/transformer/test_generic.py b/tests/transformer/test_generic.py index 8ca41ce..169a89f 100644 --- a/tests/transformer/test_generic.py +++ b/tests/transformer/test_generic.py @@ -11,6 +11,8 @@ class MyFancyNode(ast.AST): transformer = RestrictingNodeTransformer() transformer.visit(MyFancyNode()) assert transformer.errors == [ - 'Line None: MyFancyNode statements are not allowed.'] + 'Line None: MyFancyNode statements are not allowed.', + ] assert transformer.warnings == [ - 'Line None: MyFancyNode statement is not known to RestrictedPython'] + 'Line None: MyFancyNode statement is not known to RestrictedPython', + ] diff --git a/tests/transformer/test_iterator.py b/tests/transformer/test_iterator.py index 73ffd28..4d833d2 100644 --- a/tests/transformer/test_iterator.py +++ b/tests/transformer/test_iterator.py @@ -57,7 +57,7 @@ def test_RestrictingNodeTransformer__guard_iter__1(e_exec, mocker): assert 20 == ret _getiter_.assert_has_calls([ mocker.call((1, 2)), - mocker.call((3, 4)) + mocker.call((3, 4)), ]) _getiter_.reset_mock() @@ -75,7 +75,7 @@ def test_RestrictingNodeTransformer__guard_iter__1(e_exec, mocker): assert [5, 6] == ret _getiter_.assert_has_calls([ mocker.call((1, 2)), - mocker.call((3, 4)) + mocker.call((3, 4)), ]) _getiter_.reset_mock() @@ -96,7 +96,8 @@ def test_RestrictingNodeTransformer__guard_iter__1(e_exec, mocker): _getiter_.assert_has_calls([ mocker.call((0, 1, 2)), mocker.call((1, 2)), - mocker.call((1, 2))]) + mocker.call((1, 2)), + ]) _getiter_.reset_mock() @@ -129,7 +130,7 @@ def test_RestrictingNodeTransformer__guard_iter__2(e_exec, mocker): mocker.call(it), mocker.call(it[0]), mocker.call(it[1]), - mocker.call(it[2]) + mocker.call(it[2]), ] _getiter_ = mocker.stub() @@ -137,7 +138,7 @@ def test_RestrictingNodeTransformer__guard_iter__2(e_exec, mocker): glb = { '_getiter_': _getiter_, - '_iter_unpack_sequence_': guarded_iter_unpack_sequence + '_iter_unpack_sequence_': guarded_iter_unpack_sequence, } e_exec(ITERATORS_WITH_UNPACK_SEQUENCE, glb) diff --git a/tests/transformer/test_lambda.py b/tests/transformer/test_lambda.py index c882ad4..f731f76 100644 --- a/tests/transformer/test_lambda.py +++ b/tests/transformer/test_lambda.py @@ -99,14 +99,13 @@ def test_RestrictingNodeTransformer__visit_Lambda__8(c_exec): IS_PY3, reason="tuple parameter unpacking is gone in python 3") @pytest.mark.parametrize(*e_exec) -def test_RestrictingNodeTransformer__visit_Lambda__9( - e_exec, mocker): +def test_RestrictingNodeTransformer__visit_Lambda__9(e_exec, mocker): _getiter_ = mocker.stub() _getiter_.side_effect = lambda it: it glb = { '_getiter_': _getiter_, '_unpack_sequence_': guarded_unpack_sequence, - '_getattr_': lambda ob, val: getattr(ob, val) + '_getattr_': lambda ob, val: getattr(ob, val), } src = "m = lambda (a, (b, c)), *ag, **kw: a+b+c+sum(ag)+sum(kw.values())" diff --git a/tests/transformer/test_subscript.py b/tests/transformer/test_subscript.py index 6a74fc1..727c0da 100644 --- a/tests/transformer/test_subscript.py +++ b/tests/transformer/test_subscript.py @@ -14,7 +14,7 @@ def test_read_simple_subscript(e_exec, mocker): value = None _getitem_ = mocker.stub() _getitem_.side_effect = lambda ob, index: (ob, index) - glb = {'_getitem_': _getitem_} + glb = {'_getitem_': _getitem_, } e_exec(SIMPLE_SUBSCRIPTS, glb) assert (value, 'b') == glb['simple_subscript'](value) @@ -31,7 +31,7 @@ def test_tuple_subscript(e_exec, mocker): value = None _getitem_ = mocker.stub() _getitem_.side_effect = lambda ob, index: (ob, index) - glb = {'_getitem_': _getitem_} + glb = {'_getitem_': _getitem_, } e_exec(TUPLE_SUBSCRIPTS, glb) assert (value, (1, 2)) == glb['tuple_subscript'](value) @@ -48,7 +48,7 @@ def test_read_slice_subscript_no_upper_bound(e_exec, mocker): value = None _getitem_ = mocker.stub() _getitem_.side_effect = lambda ob, index: (ob, index) - glb = {'_getitem_': _getitem_} + glb = {'_getitem_': _getitem_, } e_exec(SLICE_SUBSCRIPT_NO_UPPER_BOUND, glb) assert (value, slice(1, None, None)) == glb['slice_subscript_no_upper_bound'](value) # NOQA: E501 @@ -65,7 +65,7 @@ def test_read_slice_subscript_no_lower_bound(e_exec, mocker): value = None _getitem_ = mocker.stub() _getitem_.side_effect = lambda ob, index: (ob, index) - glb = {'_getitem_': _getitem_} + glb = {'_getitem_': _getitem_, } e_exec(SLICE_SUBSCRIPT_NO_LOWER_BOUND, glb) assert (value, slice(None, 1, None)) == glb['slice_subscript_no_lower_bound'](value) # NOQA: E501 @@ -82,7 +82,7 @@ def test_read_slice_subscript_no_step(e_exec, mocker): value = None _getitem_ = mocker.stub() _getitem_.side_effect = lambda ob, index: (ob, index) - glb = {'_getitem_': _getitem_} + glb = {'_getitem_': _getitem_, } e_exec(SLICE_SUBSCRIPT_NO_STEP, glb) assert (value, slice(1, 2, None)) == glb['slice_subscript_no_step'](value) @@ -99,7 +99,7 @@ def test_read_slice_subscript_with_step(e_exec, mocker): value = None _getitem_ = mocker.stub() _getitem_.side_effect = lambda ob, index: (ob, index) - glb = {'_getitem_': _getitem_} + glb = {'_getitem_': _getitem_, } e_exec(SLICE_SUBSCRIPT_WITH_STEP, glb) assert (value, slice(1, 2, 3)) == glb['slice_subscript_with_step'](value) @@ -117,7 +117,7 @@ def test_read_extended_slice_subscript(e_exec, mocker): value = None _getitem_ = mocker.stub() _getitem_.side_effect = lambda ob, index: (ob, index) - glb = {'_getitem_': _getitem_} + glb = {'_getitem_': _getitem_, } e_exec(EXTENDED_SLICE_SUBSCRIPT, glb) ret = glb['extended_slice_subscript'](value) ref = ( @@ -127,10 +127,9 @@ def test_read_extended_slice_subscript(e_exec, mocker): slice(None, 1, None), slice(1, None, None), slice(1, 2, None), - slice(1, 2, 3) - ) + slice(1, 2, 3), + ), ) - assert ref == ret @@ -141,14 +140,12 @@ def assign_subscript(a): @pytest.mark.parametrize(*e_exec) -def test_write_subscripts( - e_exec, mocker): - value = {'b': None} +def test_write_subscripts(e_exec, mocker): + value = {'b': None, } _write_ = mocker.stub() _write_.side_effect = lambda ob: ob - glb = {'_write_': _write_} + glb = {'_write_': _write_, } e_exec(WRITE_SUBSCRIPTS, glb) - glb['assign_subscript'](value) assert value['b'] == 1 @@ -160,13 +157,11 @@ def del_subscript(a): @pytest.mark.parametrize(*e_exec) -def test_del_subscripts( - e_exec, mocker): - value = {'b': None} +def test_del_subscripts(e_exec, mocker): + value = {'b': None, } _write_ = mocker.stub() _write_.side_effect = lambda ob: ob - glb = {'_write_': _write_} + glb = {'_write_': _write_, } e_exec(DEL_SUBSCRIPT, glb) glb['del_subscript'](value) - assert value == {} diff --git a/tests/transformer/test_try.py b/tests/transformer/test_try.py index 181173b..4153d08 100644 --- a/tests/transformer/test_try.py +++ b/tests/transformer/test_try.py @@ -17,15 +17,14 @@ def try_except(m): @pytest.mark.parametrize(*e_exec) -def test_RestrictingNodeTransformer__visit_Try__1( - e_exec, mocker): +def test_RestrictingNodeTransformer__visit_Try__1(e_exec, mocker): """It allows try-except statements.""" trace = mocker.stub() e_exec(TRY_EXCEPT)['try_except'](trace) trace.assert_has_calls([ mocker.call('try'), - mocker.call('except') + mocker.call('except'), ]) @@ -41,15 +40,14 @@ def try_except_else(m): @pytest.mark.parametrize(*e_exec) -def test_RestrictingNodeTransformer__visit_Try__2( - e_exec, mocker): +def test_RestrictingNodeTransformer__visit_Try__2(e_exec, mocker): """It allows try-except-else statements.""" trace = mocker.stub() e_exec(TRY_EXCEPT_ELSE)['try_except_else'](trace) trace.assert_has_calls([ mocker.call('try'), - mocker.call('else') + mocker.call('else'), ]) @@ -65,15 +63,14 @@ def try_finally(m): @pytest.mark.parametrize(*e_exec) -def test_RestrictingNodeTransformer__visit_TryFinally__1( - e_exec, mocker): +def test_RestrictingNodeTransformer__visit_TryFinally__1(e_exec, mocker): """It allows try-finally statements.""" trace = mocker.stub() e_exec(TRY_FINALLY)['try_finally'](trace) trace.assert_has_calls([ mocker.call('try'), - mocker.call('finally') + mocker.call('finally'), ]) @@ -90,8 +87,7 @@ def try_except_finally(m): @pytest.mark.parametrize(*e_exec) -def test_RestrictingNodeTransformer__visit_TryFinally__2( - e_exec, mocker): +def test_RestrictingNodeTransformer__visit_TryFinally__2(e_exec, mocker): """It allows try-except-finally statements.""" trace = mocker.stub() e_exec(TRY_EXCEPT_FINALLY)['try_except_finally'](trace) @@ -99,7 +95,7 @@ def test_RestrictingNodeTransformer__visit_TryFinally__2( trace.assert_has_calls([ mocker.call('try'), mocker.call('except'), - mocker.call('finally') + mocker.call('finally'), ]) @@ -117,8 +113,7 @@ def try_except_else_finally(m): @pytest.mark.parametrize(*e_exec) -def test_RestrictingNodeTransformer__visit_TryFinally__3( - e_exec, mocker): +def test_RestrictingNodeTransformer__visit_TryFinally__3(e_exec, mocker): """It allows try-except-else-finally statements.""" trace = mocker.stub() e_exec(TRY_EXCEPT_ELSE_FINALLY)['try_except_else_finally'](trace) @@ -126,7 +121,7 @@ def test_RestrictingNodeTransformer__visit_TryFinally__3( trace.assert_has_calls([ mocker.call('try'), mocker.call('else'), - mocker.call('finally') + mocker.call('finally'), ]) @@ -143,14 +138,13 @@ def tuple_unpack(err): IS_PY3, reason="tuple unpacking on exceptions is gone in python3") @pytest.mark.parametrize(*e_exec) -def test_RestrictingNodeTransformer__visit_ExceptHandler__1( - e_exec, mocker): +def test_RestrictingNodeTransformer__visit_ExceptHandler__1(e_exec, mocker): _getiter_ = mocker.stub() _getiter_.side_effect = lambda it: it glb = { '_getiter_': _getiter_, - '_unpack_sequence_': guarded_unpack_sequence + '_unpack_sequence_': guarded_unpack_sequence, } e_exec(EXCEPT_WITH_TUPLE_UNPACK, glb) @@ -160,7 +154,8 @@ def test_RestrictingNodeTransformer__visit_ExceptHandler__1( _getiter_.assert_has_calls([ mocker.call(err), - mocker.call((2, 3))]) + mocker.call((2, 3)), + ]) BAD_TRY_EXCEPT = """ @@ -181,4 +176,5 @@ def test_RestrictingNodeTransformer__visit_ExceptHandler__2( result = c_exec(BAD_TRY_EXCEPT) assert result.errors == ( 'Line 5: "_leading_underscore" is an invalid variable name because ' - 'it starts with "_"',) + 'it starts with "_"', + ) diff --git a/tests/transformer/test_with_stmt.py b/tests/transformer/test_with_stmt.py index 9543ce5..b1a14ad 100644 --- a/tests/transformer/test_with_stmt.py +++ b/tests/transformer/test_with_stmt.py @@ -24,7 +24,7 @@ def ctx(): glb = { '_getiter_': _getiter_, - '_unpack_sequence_': guarded_unpack_sequence + '_unpack_sequence_': guarded_unpack_sequence, } e_exec(WITH_STMT_WITH_UNPACK_SEQUENCE, glb) @@ -34,7 +34,8 @@ def ctx(): assert ret == (1, 2, 3) _getiter_.assert_has_calls([ mocker.call((1, (2, 3))), - mocker.call((2, 3))]) + mocker.call((2, 3)), + ]) WITH_STMT_MULTI_CTX_WITH_UNPACK_SEQUENCE = """ @@ -62,7 +63,7 @@ def ctx2(): glb = { '_getiter_': _getiter_, - '_unpack_sequence_': guarded_unpack_sequence + '_unpack_sequence_': guarded_unpack_sequence, } exec(result.code, glb) @@ -75,7 +76,7 @@ def ctx2(): mocker.call((2, 3)), mocker.call(((4, 5), (6, 7))), mocker.call((4, 5)), - mocker.call((6, 7)) + mocker.call((6, 7)), ]) @@ -127,7 +128,7 @@ def test_with_stmt_attribute_access(e_exec, mocker): assert x.y == ctx _write_.assert_has_calls([ mocker.call(x), - mocker.call(x) + mocker.call(x), ]) _write_.reset_mock() From 676daadc1169318807bf050ba3b4a1fa4c23002b Mon Sep 17 00:00:00 2001 From: Alexander Loechel Date: Mon, 18 Sep 2017 22:49:09 +0200 Subject: [PATCH 3/3] apply flake8 fixes for better readability. --- src/RestrictedPython/Eval.py | 5 +- src/RestrictedPython/Guards.py | 17 ++-- src/RestrictedPython/compile.py | 147 +++++++++++++++++----------- src/RestrictedPython/transformer.py | 133 +++++++++++++++++-------- 4 files changed, 194 insertions(+), 108 deletions(-) diff --git a/src/RestrictedPython/Eval.py b/src/RestrictedPython/Eval.py index 836ea5e..fd992e1 100644 --- a/src/RestrictedPython/Eval.py +++ b/src/RestrictedPython/Eval.py @@ -76,7 +76,8 @@ def prepUnrestrictedCode(self): self.expr, '', 'eval', - ast.PyCF_ONLY_AST) + ast.PyCF_ONLY_AST, + ) co = compile(exp_node, '', 'eval') @@ -99,7 +100,7 @@ def eval(self, mapping): global_scope = { '_getattr_': default_guarded_getattr, - '_getitem_': default_guarded_getitem + '_getitem_': default_guarded_getitem, } global_scope.update(self.globals) diff --git a/src/RestrictedPython/Guards.py b/src/RestrictedPython/Guards.py index 7d25f3e..1efa349 100644 --- a/src/RestrictedPython/Guards.py +++ b/src/RestrictedPython/Guards.py @@ -54,7 +54,7 @@ 'slice', 'str', 'tuple', - 'zip' + 'zip', ] _safe_exceptions = [ @@ -207,19 +207,23 @@ def __init__(self, ob): __setitem__ = _handler( '__guarded_setitem__', - 'object does not support item or slice assignment') + 'object does not support item or slice assignment', + ) __delitem__ = _handler( '__guarded_delitem__', - 'object does not support item or slice assignment') + 'object does not support item or slice assignment', + ) __setattr__ = _handler( '__guarded_setattr__', - 'attribute-less object (assign or del)') + 'attribute-less object (assign or del)', + ) __delattr__ = _handler( '__guarded_delattr__', - 'attribute-less object (assign or del)') + 'attribute-less object (assign or del)', + ) return Wrapper @@ -265,7 +269,8 @@ def safer_getattr(object, name, getattr=getattr): """ if isinstance(object, _compat.basestring) and name == 'format': raise NotImplementedError( - 'Using format() on a %s is not safe.' % object.__class__.__name__) + 'Using format() on a %s is not safe.' % object.__class__.__name__, + ) return getattr(object, name) diff --git a/src/RestrictedPython/compile.py b/src/RestrictedPython/compile.py index 1cc55a8..9ef8acc 100644 --- a/src/RestrictedPython/compile.py +++ b/src/RestrictedPython/compile.py @@ -7,34 +7,45 @@ CompileResult = namedtuple( - 'CompileResult', 'code, errors, warnings, used_names') + 'CompileResult', + 'code, errors, warnings, used_names', +) syntax_error_template = ( - 'Line {lineno}: {type}: {msg} in on statement: {statement}') + 'Line {lineno}: {type}: {msg} in on statement: {statement}' +) def _compile_restricted_mode( - source, - filename='', - mode="exec", - flags=0, - dont_inherit=False, - policy=RestrictingNodeTransformer): + source, + filename='', + mode="exec", + flags=0, + dont_inherit=False, + policy=RestrictingNodeTransformer, +): byte_code = None errors = [] warnings = [] used_names = {} if policy is None: # Unrestricted Source Checks - byte_code = compile(source, filename, mode=mode, flags=flags, - dont_inherit=dont_inherit) + byte_code = compile( + source, + filename, + mode=mode, + flags=flags, + dont_inherit=dont_inherit, + ) elif issubclass(policy, RestrictingNodeTransformer): c_ast = None allowed_source_types = [str, ast.Module] if IS_PY2: allowed_source_types.append(unicode) # NOQA: F821,E501 # PY2 only statement, in Python 2 only module if not issubclass(type(source), tuple(allowed_source_types)): - raise TypeError('Not allowed source type: ' - '"{0.__class__.__name__}".'.format(source)) + raise TypeError( + 'Not allowed source type: ' + '"{0.__class__.__name__}".'.format(source), + ) c_ast = None # workaround for pypy issue https://bitbucket.org/pypy/pypy/issues/2552 if isinstance(source, ast.Module): @@ -45,30 +56,36 @@ def _compile_restricted_mode( except (TypeError, ValueError) as e: errors.append(str(e)) except SyntaxError as v: - errors.append(syntax_error_template.format( - lineno=v.lineno, - type=v.__class__.__name__, - msg=v.msg, - statement=v.text.strip() - )) + errors.append( + syntax_error_template.format( + lineno=v.lineno, + type=v.__class__.__name__, + msg=v.msg, + statement=v.text.strip(), + ), + ) if c_ast: policy(errors, warnings, used_names).visit(c_ast) if not errors: - byte_code = compile(c_ast, filename, mode=mode # , - # flags=flags, - # dont_inherit=dont_inherit - ) + byte_code = compile( + c_ast, + filename, + mode=mode, + # flags=flags, + # dont_inherit=dont_inherit + ) else: raise TypeError('Unallowed policy provided for RestrictedPython') return CompileResult(byte_code, tuple(errors), warnings, used_names) def compile_restricted_exec( - source, - filename='', - flags=0, - dont_inherit=False, - policy=RestrictingNodeTransformer): + source, + filename='', + flags=0, + dont_inherit=False, + policy=RestrictingNodeTransformer, +): """Compile restricted for the mode `exec`.""" return _compile_restricted_mode( source, @@ -76,15 +93,17 @@ def compile_restricted_exec( mode='exec', flags=flags, dont_inherit=dont_inherit, - policy=policy) + policy=policy, + ) def compile_restricted_eval( - source, - filename='', - flags=0, - dont_inherit=False, - policy=RestrictingNodeTransformer): + source, + filename='', + flags=0, + dont_inherit=False, + policy=RestrictingNodeTransformer, +): """Compile restricted for the mode `eval`.""" return _compile_restricted_mode( source, @@ -92,15 +111,17 @@ def compile_restricted_eval( mode='eval', flags=flags, dont_inherit=dont_inherit, - policy=policy) + policy=policy, + ) def compile_restricted_single( - source, - filename='', - flags=0, - dont_inherit=False, - policy=RestrictingNodeTransformer): + source, + filename='', + flags=0, + dont_inherit=False, + policy=RestrictingNodeTransformer, +): """Compile restricted for the mode `single`.""" return _compile_restricted_mode( source, @@ -108,18 +129,20 @@ def compile_restricted_single( mode='single', flags=flags, dont_inherit=dont_inherit, - policy=policy) + policy=policy, + ) def compile_restricted_function( - p, # parameters - body, - name, - filename='', - globalize=None, # List of globals (e.g. ['here', 'context', ...]) - flags=0, - dont_inherit=False, - policy=RestrictingNodeTransformer): + p, # parameters + body, + name, + filename='', + globalize=None, # List of globals (e.g. ['here', 'context', ...]) + flags=0, + dont_inherit=False, + policy=RestrictingNodeTransformer, +): """Compile a restricted code object for a function. The globalize argument, if specified, is a list of variable names to be @@ -165,8 +188,11 @@ def compile_restricted_function( # We don't want the user to need to understand this. if globalize: body_ast.body.insert(0, ast.Global(globalize)) - wrapper_ast = ast.parse('def masked_function_name(%s): pass' % p, - '', 'exec') + wrapper_ast = ast.parse( + 'def masked_function_name(%s): pass' % p, + '', + 'exec', + ) # In case the name you chose for your generated function is not a # valid python identifier we set it after the fact function_ast = wrapper_ast.body[0] @@ -182,18 +208,20 @@ def compile_restricted_function( mode='exec', flags=flags, dont_inherit=dont_inherit, - policy=policy) + policy=policy, + ) return result def compile_restricted( - source, - filename='', - mode='exec', - flags=0, - dont_inherit=False, - policy=RestrictingNodeTransformer): + source, + filename='', + mode='exec', + flags=0, + dont_inherit=False, + policy=RestrictingNodeTransformer, +): """Replacement for the built-in compile() function. policy ... `ast.NodeTransformer` class defining the restrictions. @@ -206,13 +234,14 @@ def compile_restricted( mode=mode, flags=flags, dont_inherit=dont_inherit, - policy=policy) + policy=policy, + ) else: raise TypeError('unknown mode %s', mode) for warning in result.warnings: warnings.warn( warning, - SyntaxWarning + SyntaxWarning, ) if result.errors: raise SyntaxError(result.errors) diff --git a/src/RestrictedPython/transformer.py b/src/RestrictedPython/transformer.py index abdeed3..7a41e3a 100644 --- a/src/RestrictedPython/transformer.py +++ b/src/RestrictedPython/transformer.py @@ -46,7 +46,7 @@ ast.BitOr: '|=', ast.BitXor: '^=', ast.BitAnd: '&=', - ast.FloorDiv: '//=' + ast.FloorDiv: '//=', } if IS_PY35_OR_GREATER: @@ -115,13 +115,15 @@ def error(self, node, info): """Record a security error discovered during transformation.""" lineno = getattr(node, 'lineno', None) self.errors.append( - 'Line {lineno}: {info}'.format(lineno=lineno, info=info)) + 'Line {lineno}: {info}'.format(lineno=lineno, info=info), + ) def warn(self, node, info): """Record a security error discovered during transformation.""" lineno = getattr(node, 'lineno', None) self.warnings.append( - 'Line {lineno}: {info}'.format(lineno=lineno, info=info)) + 'Line {lineno}: {info}'.format(lineno=lineno, info=info), + ) def guard_iter(self, node): """ @@ -143,12 +145,14 @@ def guard_iter(self, node): new_iter = ast.Call( func=ast.Name('_iter_unpack_sequence_', ast.Load()), args=[node.iter, spec, ast.Name('_getiter_', ast.Load())], - keywords=[]) + keywords=[], + ) else: new_iter = ast.Call( func=ast.Name("_getiter_", ast.Load()), args=[node.iter], - keywords=[]) + keywords=[], + ) copy_locations(new_iter, node.iter) node.iter = new_iter @@ -241,7 +245,8 @@ def protect_unpack_sequence(self, target, value): return ast.Call( func=ast.Name('_unpack_sequence_', ast.Load()), args=[value, spec, ast.Name('_getiter_', ast.Load())], - keywords=[]) + keywords=[], + ) def gen_unpack_wrapper(self, node, target, ctx='store'): """Helper function to protect tuple unpacks. @@ -270,7 +275,8 @@ def gen_unpack_wrapper(self, node, target, ctx='store'): # 'wrapper' takes care to protect sequence unpacking with _getiter_. converter = self.protect_unpack_sequence( target, - ast.Name(tmp_name, ast.Load())) + ast.Name(tmp_name, ast.Load()), + ) # Assign the expression to the original names. # Cleanup the temporary variable. @@ -284,10 +290,17 @@ def gen_unpack_wrapper(self, node, target, ctx='store'): finalbody = [self.gen_del_stmt(tmp_name)] if IS_PY2: - cleanup = ast.TryFinally(body=try_body, finalbody=finalbody) + cleanup = ast.TryFinally( + body=try_body, + finalbody=finalbody, + ) else: cleanup = ast.Try( - body=try_body, finalbody=finalbody, handlers=[], orelse=[]) + body=try_body, + finalbody=finalbody, + handlers=[], + orelse=[], + ) if ctx == 'store': ctx = ast.Store() @@ -313,8 +326,13 @@ def gen_none_node(self): def gen_lambda(self, args, body): return ast.Lambda( args=ast.arguments( - args=args, vararg=None, kwarg=None, defaults=[]), - body=body) + args=args, + vararg=None, + kwarg=None, + defaults=[], + ), + body=body, + ) def gen_del_stmt(self, name_to_del): return ast.Delete(targets=[ast.Name(name_to_del, ast.Del())]) @@ -352,7 +370,8 @@ def transform_slice(self, slice_): return ast.Call( func=ast.Name('slice', ast.Load()), args=args, - keywords=[]) + keywords=[], + ) elif isinstance(slice_, ast.ExtSlice): dims = ast.Tuple([], ast.Load()) @@ -371,11 +390,15 @@ def check_name(self, node, name): self.error( node, '"{name}" is an invalid variable name because it ' - 'starts with "_"'.format(name=name)) + 'starts with "_"'.format(name=name), + ) elif name.endswith('__roles__'): - self.error(node, '"%s" is an invalid variable name because ' - 'it ends with "__roles__".' % name) + self.error( + node, + '"%s" is an invalid variable name because ' + 'it ends with "__roles__".' % name, + ) elif name == "printed": self.error(node, '"printed" is a reserved name.') @@ -446,7 +469,9 @@ def inject_print_collector(self, node, position=0): value=ast.Call( func=ast.Name("_print_", ast.Load()), args=[ast.Name("_getattr_", ast.Load())], - keywords=[])) + keywords=[], + ), + ) if isinstance(node, ast.Module): _print.lineno = position @@ -472,7 +497,8 @@ def gen_attr_check(self, node, attr_name): call_getattr = ast.Call( func=ast.Name('_getattr_', ast.Load()), args=[node, ast.Str(attr_name)], - keywords=[]) + keywords=[], + ) return ast.BoolOp(op=ast.And(), values=[call_getattr, node]) @@ -489,14 +515,15 @@ def generic_visit(self, node): self.warn( node, '{0.__class__.__name__}' - ' statement is not known to RestrictedPython'.format(node) + ' statement is not known to RestrictedPython'.format(node), ) self.not_allowed(node) def not_allowed(self, node): self.error( node, - '{0.__class__.__name__} statements are not allowed.'.format(node)) + '{0.__class__.__name__} statements are not allowed.'.format(node), + ) def node_contents_visit(self, node): """Visit the contents of a node.""" @@ -564,7 +591,8 @@ def visit_Name(self, node): new_node = ast.Call( func=ast.Name("_print", ast.Load()), args=[], - keywords=[]) + keywords=[], + ) copy_locations(new_node, node) return new_node @@ -574,7 +602,8 @@ def visit_Name(self, node): new_node = ast.Attribute( value=ast.Name('_print', ast.Load()), attr="_call_print", - ctx=ast.Load()) + ctx=ast.Load(), + ) copy_locations(new_node, node) return new_node @@ -837,20 +866,23 @@ def visit_Attribute(self, node): self.error( node, '"{name}" is an invalid attribute name because it starts ' - 'with "_".'.format(name=node.attr)) + 'with "_".'.format(name=node.attr), + ) if node.attr.endswith('__roles__'): self.error( node, '"{name}" is an invalid attribute name because it ends ' - 'with "__roles__".'.format(name=node.attr)) + 'with "__roles__".'.format(name=node.attr), + ) if isinstance(node.ctx, ast.Load): node = self.node_contents_visit(node) new_node = ast.Call( func=ast.Name('_getattr_', ast.Load()), args=[node.value, ast.Str(node.attr)], - keywords=[]) + keywords=[], + ) copy_locations(new_node, node) return new_node @@ -860,7 +892,8 @@ def visit_Attribute(self, node): new_value = ast.Call( func=ast.Name('_write_', ast.Load()), args=[node.value], - keywords=[]) + keywords=[], + ) copy_locations(new_value, node.value) node.value = new_value @@ -896,7 +929,8 @@ def visit_Subscript(self, node): new_node = ast.Call( func=ast.Name('_getitem_', ast.Load()), args=[node.value, self.transform_slice(node.slice)], - keywords=[]) + keywords=[], + ) copy_locations(new_node, node) return new_node @@ -905,7 +939,8 @@ def visit_Subscript(self, node): new_value = ast.Call( func=ast.Name('_write_', ast.Load()), args=[node.value], - keywords=[]) + keywords=[], + ) copy_locations(new_value, node) node.value = new_value @@ -1004,7 +1039,8 @@ def visit_Assign(self, node): if isinstance(target, ast.Tuple): wrapper = ast.Assign( targets=[target], - value=self.protect_unpack_sequence(target, node.value)) + value=self.protect_unpack_sequence(target, node.value), + ) new_nodes.append(wrapper) else: new_node = ast.Assign(targets=[target], value=node.value) @@ -1033,14 +1069,16 @@ def visit_AugAssign(self, node): if isinstance(node.target, ast.Attribute): self.error( node, - "Augmented assignment of attributes is not allowed.") + "Augmented assignment of attributes is not allowed.", + ) return node elif isinstance(node.target, ast.Subscript): self.error( node, "Augmented assignment of object items " - "and slices is not allowed.") + "and slices is not allowed.", + ) return node elif isinstance(node.target, ast.Name): @@ -1051,9 +1089,11 @@ def visit_AugAssign(self, node): args=[ ast.Str(IOPERATOR_TO_STR[type(node.op)]), ast.Name(node.target.id, ast.Load()), - node.value + node.value, ], - keywords=[])) + keywords=[], + ), + ) copy_locations(new_node, node) return new_node @@ -1077,9 +1117,11 @@ def visit_Print(self, node): """ self.print_info.print_used = True - self.warn(node, - "Print statement is deprecated and " - "not avaliable anymore in Python 3.") + self.warn( + node, + "Print statement is deprecated and " + "not avaliable anymore in Python 3.", + ) node = self.node_contents_visit(node) if node.dest is None: @@ -1217,7 +1259,8 @@ def visit_With(self, node): if isinstance(item.optional_vars, ast.Tuple): tmp_target, unpack = self.gen_unpack_wrapper( node, - item.optional_vars) + item.optional_vars, + ) item.optional_vars = tmp_target node.body.insert(0, unpack) @@ -1248,7 +1291,10 @@ def visit_FunctionDef(self, node): for index, arg in enumerate(list(node.args.args)): if isinstance(arg, ast.Tuple): tmp_target, unpack = self.gen_unpack_wrapper( - node, arg, 'param') + node, + arg, + 'param', + ) # Replace the tuple with a single (temporary) parameter. node.args.args[index] = tmp_target @@ -1282,7 +1328,8 @@ def visit_Lambda(self, node): tmp_name = self.gen_tmp_name() converter = self.protect_unpack_sequence( arg, - ast.Name(tmp_name, ast.Load())) + ast.Name(tmp_name, ast.Load()), + ) outer_params.append(ast.Name(tmp_name, ast.Param())) inner_args.append(converter) @@ -1349,11 +1396,15 @@ def visit_ClassDef(self, node): else: if any(keyword.arg == 'metaclass' for keyword in node.keywords): self.error( - node, 'The keyword argument "metaclass" is not allowed.') - CLASS_DEF = textwrap.dedent('''\ + node, + 'The keyword argument "metaclass" is not allowed.', + ) + CLASS_DEF = textwrap.dedent( + '''\ class {0.name}(metaclass=__metaclass__): pass - '''.format(node)) + '''.format(node), + ) new_class_node = ast.parse(CLASS_DEF).body[0] new_class_node.body = node.body new_class_node.bases = node.bases