def test_RestrictingNodeTransformer__test_ternary_if( mocker): src = 'x.y = y.a if y.z else y.b' _getattr_ = mocker.stub() _getattr_.side_effect = lambda ob, key: ob[key] _write_ = mocker.stub() _write_.side_effect = lambda ob: ob glb = { '_getattr_': _getattr_, '_write_': _write_, 'x': mocker.stub(), 'y': {'a': 'a', 'b': 'b'}, } glb['y']['z'] = True restricted_exec(src, glb) assert glb['x'].y == 'a' _write_.assert_called_once_with(glb['x']) _getattr_.assert_has_calls([ mocker.call(glb['y'], 'z'), mocker.call(glb['y'], 'a')]) _write_.reset_mock() _getattr_.reset_mock() glb['y']['z'] = False restricted_exec(src, glb) assert glb['x'].y == 'b' _write_.assert_called_once_with(glb['x']) _getattr_.assert_has_calls([ mocker.call(glb['y'], 'z'), mocker.call(glb['y'], 'b')])
def test_Guards__write_wrapper__2(): """It wraps setattr and it works when guarded_setattr is implemented.""" class ObjWithGuardedSetattr: my_attr = None def __guarded_setattr__(self, key, value): setattr(self, key, value) set_attribute_using_guarded_setattr_code = ''' myobj_with_guarded_setattr = ObjWithGuardedSetattr() setattr(myobj_with_guarded_setattr, 'my_attr', 'bar') ''' restricted_globals = dict( __builtins__=safe_builtins, ObjWithGuardedSetattr=ObjWithGuardedSetattr, myobj_with_guarded_setattr=None, __name__='restricted_module', __metaclass__=type, _write_=_write_, _getattr_=getattr,) restricted_exec( set_attribute_using_guarded_setattr_code, restricted_globals) assert restricted_globals['myobj_with_guarded_setattr'].my_attr == 'bar'
def test_RestrictingNodeTransformer__visit_Lambda__10(): """Simple lambda functions are allowed.""" restricted_globals = dict( g=None, ) restricted_exec(LAMBDA_FUNC_1, restricted_globals) assert 4 == restricted_globals['g'](2)
def test_RestrictingNodeTransformer__visit_FunctionDef__8( mocker): _getiter_ = mocker.stub() _getiter_.side_effect = lambda it: it glb = { '_getiter_': _getiter_, '_unpack_sequence_': guarded_unpack_sequence } restricted_exec('def simple((a, b)): return a, b', glb) val = (1, 2) ret = glb['simple'](val) assert ret == val _getiter_.assert_called_once_with(val) _getiter_.reset_mock() restricted_exec(NESTED_SEQ_UNPACK, glb) val = (1, 2, (3, (4, 5))) ret = glb['nested'](val) assert ret == (1, 2, 3, 4, 5) assert 3 == _getiter_.call_count _getiter_.assert_any_call(val) _getiter_.assert_any_call(val[2]) _getiter_.assert_any_call(val[2][1]) _getiter_.reset_mock() ret = glb['nested_with_order']((1, 2), (3, 4)) assert ret == (1, 2, 3, 4) _getiter_.assert_has_calls([ mocker.call((1, 2)), mocker.call((3, 4))]) _getiter_.reset_mock()
def test_Guards__guarded_setattr__1(): """It allows use setattr and delattr when _guarded_writes is True. """ class MyObjectD: value = None _guarded_writes = 1 setattr_code = ''' my_object_d = MyObjectD() setattr(my_object_d, 'value', 9999)''' delattr_code = "delattr(my_object_d, 'value')" restricted_globals = dict( __builtins__=safe_builtins, MyObjectD=MyObjectD, my_object_d=None, __name__='restricted_module', __metaclass__=type, _write_=_write_, _getattr_=getattr,) restricted_exec(setattr_code, restricted_globals) assert 9999 == restricted_globals['my_object_d'].value restricted_exec(delattr_code, restricted_globals) assert None is restricted_globals['my_object_d'].value
def test_with_stmt_subscript(mocker): _write_ = mocker.stub() _write_.side_effect = lambda ob: ob glb = {'_write_': _write_} restricted_exec(WITH_STMT_SUBSCRIPT, glb) # Test single_key ctx = mocker.MagicMock() ctx.__enter__.return_value = ctx x = {} glb['single_key'](ctx, x) assert x['key'] == ctx _write_.assert_called_once_with(x) _write_.reset_mock() # Test slice_key ctx = mocker.MagicMock() ctx.__enter__.return_value = (1, 2) x = [0, 0, 0, 0, 0, 0] glb['slice_key'](ctx, x) assert x == [0, 0, 1, 2, 0, 0, 0] _write_.assert_called_once_with(x)
def test_read_slice_subscript_with_step(mocker): value = None _getitem_ = mocker.stub() _getitem_.side_effect = lambda ob, index: (ob, index) glb = {'_getitem_': _getitem_} restricted_exec(SLICE_SUBSCRIPT_WITH_STEP, glb) assert (value, slice(1, 2, 3)) == glb['slice_subscript_with_step'](value)
def test_read_simple_subscript(mocker): value = None _getitem_ = mocker.stub() _getitem_.side_effect = lambda ob, index: (ob, index) glb = {'_getitem_': _getitem_} restricted_exec(SIMPLE_SUBSCRIPTS, glb) assert (value, 'b') == glb['simple_subscript'](value)
def test_read_slice_subscript_no_lower_bound(mocker): value = None _getitem_ = mocker.stub() _getitem_.side_effect = lambda ob, index: (ob, index) glb = {'_getitem_': _getitem_} restricted_exec(SLICE_SUBSCRIPT_NO_LOWER_BOUND, glb) assert (value, slice(None, 1, None)) == glb['slice_subscript_no_lower_bound'](value) # NOQA: E501
def test_tuple_subscript(mocker): value = None _getitem_ = mocker.stub() _getitem_.side_effect = lambda ob, index: (ob, index) glb = {'_getitem_': _getitem_} restricted_exec(TUPLE_SUBSCRIPTS, glb) assert (value, (1, 2)) == glb['tuple_subscript'](value)
def test_RestrictingNodeTransformer__guard_iter__1(mocker): it = (1, 2, 3) _getiter_ = mocker.stub() _getiter_.side_effect = lambda x: x glb = {'_getiter_': _getiter_} restricted_exec(ITERATORS, glb) ret = glb['for_loop'](it) assert 6 == ret _getiter_.assert_called_once_with(it) _getiter_.reset_mock() ret = glb['nested_for_loop']((1, 2), (3, 4)) assert 20 == ret _getiter_.assert_has_calls([ mocker.call((1, 2)), mocker.call((3, 4)) ]) _getiter_.reset_mock() ret = glb['dict_comp'](it) assert {1: 2, 2: 4, 3: 6} == ret _getiter_.assert_called_once_with(it) _getiter_.reset_mock() ret = glb['list_comp'](it) assert [2, 4, 6] == ret _getiter_.assert_called_once_with(it) _getiter_.reset_mock() ret = glb['nested_list_comp']((1, 2), (3, 4)) assert [5, 6] == ret _getiter_.assert_has_calls([ mocker.call((1, 2)), mocker.call((3, 4)) ]) _getiter_.reset_mock() ret = glb['set_comp'](it) assert {2, 4, 6} == ret _getiter_.assert_called_once_with(it) _getiter_.reset_mock() ret = glb['generator'](it) assert isinstance(ret, types.GeneratorType) assert list(ret) == [2, 4, 6] _getiter_.assert_called_once_with(it) _getiter_.reset_mock() ret = glb['nested_generator']((0, 1, 2), (1, 2)) assert isinstance(ret, types.GeneratorType) assert list(ret) == [2, 3, 3, 4] _getiter_.assert_has_calls([ mocker.call((0, 1, 2)), mocker.call((1, 2)), mocker.call((1, 2))]) _getiter_.reset_mock()
def test_RestrictingNodeTransformer__visit_Lambda__12(): """Lambda functions with tuple unpacking and simple params are allowed.""" restricted_globals = dict( g=None, _unpack_sequence_=guarded_unpack_sequence, _getiter_=default_guarded_getiter, ) restricted_exec(LAMBDA_FUNC_3, restricted_globals) assert (64, 6) == restricted_globals['g']((4, 3), 2)
def test_del_subscripts( mocker): value = {'b': None} _write_ = mocker.stub() _write_.side_effect = lambda ob: ob glb = {'_write_': _write_} restricted_exec(DEL_SUBSCRIPT, glb) glb['del_subscript'](value) assert value == {}
def test_RestrictingNodeTransformer__visit_Try__2( mocker): """It allows try-except-else statements.""" trace = mocker.stub() restricted_exec(TRY_EXCEPT_ELSE)['try_except_else'](trace) trace.assert_has_calls([ mocker.call('try'), mocker.call('else') ])
def test_RestrictingNodeTransformer__visit_TryFinally__1( mocker): """It allows try-finally statements.""" trace = mocker.stub() restricted_exec(TRY_FINALLY)['try_finally'](trace) trace.assert_has_calls([ mocker.call('try'), mocker.call('finally') ])
def test_write_subscripts( mocker): value = {'b': None} _write_ = mocker.stub() _write_.side_effect = lambda ob: ob glb = {'_write_': _write_} restricted_exec(WRITE_SUBSCRIPTS, glb) glb['assign_subscript'](value) assert value['b'] == 1
def test_RestrictingNodeTransformer__visit_Attribute__3(mocker): """It transforms the attribute access to `_getattr_`.""" glb = { '_getattr_': mocker.stub(), 'a': [], 'b': 'b' } restricted_exec(TRANSFORM_ATTRIBUTE_ACCESS, glb) glb['func']() glb['_getattr_'].assert_called_once_with([], 'b')
def test_Guards__safer_getattr__3(): """It allows to use `safer_getattr`.""" restricted_globals = dict( __builtins__=safe_builtins, __name__=None, __metaclass__=type, _write_=_write_, getattr=safer_getattr, result=None, ) restricted_exec(SAFER_GETATTR_ALLOWED, restricted_globals) assert restricted_globals['result'] == 2
def test_Guards__safer_getattr__1(): """It prevents using the format method of a string. format() is considered harmful: http://lucumr.pocoo.org/2016/12/29/careful-with-str-format/ """ glb = { '__builtins__': safe_builtins, } with pytest.raises(NotImplementedError) as err: restricted_exec(STRING_DOT_FORMAT_DENIED, glb) assert 'Using format() on a str is not safe.' == str(err.value)
def test_RestrictingNodeTransformer__visit_ClassDef__6(): """It allows to define an ``__init__`` method.""" restricted_globals = dict( t=None, _write_=lambda x: x, __metaclass__=type, __name__='constructor_test', ) restricted_exec(CONSTRUCTOR_TEST, restricted_globals) t = restricted_globals['t'] assert t.input == 42
def test_RestrictingNodeTransformer__visit_Attribute__5( mocker): """It transforms writing to an attribute to `_write_`.""" glb = { '_write_': mocker.stub(), 'a': mocker.stub(), } glb['_write_'].return_value = glb['a'] restricted_exec("a.b = 'it works'", glb) glb['_write_'].assert_called_once_with(glb['a']) assert glb['a'].b == 'it works'
def test_os_import(): """It does not allow to import anything by default. The `__import__` function is not provided as it is not safe. """ # Caution: This test is broken on PyPy until the following issue is fixed: # https://bitbucket.org/pypy/pypy/issues/2653 # PyPy currently ignores the restriction of the `__builtins__`. glb = {'__builtins__': safe_builtins} with pytest.raises(ImportError) as err: restricted_exec(OS_IMPORT_EXAMPLE, glb) assert '__import__ not found' == str(err.value)
def test_RestrictingNodeTransformer__visit_ClassDef__5(): """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) restricted_exec(DECORATED_CLASS, restricted_globals) comb = restricted_globals['comb'] assert comb.class_att == 2342 assert comb.base_att == 42 assert comb.wrap_att == 23
def test_RestrictingNodeTransformer__visit_Call__2(mocker): _apply_ = mocker.stub() _apply_.side_effect = lambda func, *args, **kwargs: func(*args, **kwargs) glb = { '_apply_': _apply_, 'foo': lambda *args, **kwargs: (args, kwargs) } restricted_exec(FUNCTIONC_CALLS, glb) ret = glb['positional_args']() assert ((1, 2), {}) == ret assert _apply_.called is False _apply_.reset_mock() ret = glb['star_args']() ref = ((3, 4), {}) assert ref == ret _apply_.assert_called_once_with(glb['foo'], *ref[0]) _apply_.reset_mock() ret = glb['positional_and_star_args']() ref = ((1, 2, 3, 4), {}) assert ref == ret _apply_.assert_called_once_with(glb['foo'], *ref[0]) _apply_.reset_mock() ret = glb['kw_args']() ref = ((), {'x': 5, 'y': 6}) assert ref == ret _apply_.assert_called_once_with(glb['foo'], **ref[1]) _apply_.reset_mock() ret = glb['star_and_kw']() ref = ((3, 4), {'x': 5, 'y': 6}) assert ref == ret _apply_.assert_called_once_with(glb['foo'], *ref[0], **ref[1]) _apply_.reset_mock() ret = glb['positional_and_star_and_kw_args']() ref = ((1, 3, 4), {'x': 5, 'y': 6}) assert ref == ret _apply_.assert_called_once_with(glb['foo'], *ref[0], **ref[1]) _apply_.reset_mock() ret = glb['positional_and_star_and_keyword_and_kw_args']() ref = ((1, 2, 3, 4), {'x': 5, 'y': 6, 'r': 9}) assert ref == ret _apply_.assert_called_once_with(glb['foo'], *ref[0], **ref[1]) _apply_.reset_mock()
def test_RestrictingNodeTransformer__visit_ClassDef__7(): """It allows to define an ``__eq__`` method.""" restricted_globals = dict( result1=None, result2=None, _getattr_=getattr, _write_=lambda x: x, __metaclass__=type, __name__='compare_test', ) restricted_exec(COMPARE_TEST, restricted_globals) assert restricted_globals['result1'] is True assert restricted_globals['result2'] is False
def test_RestrictingNodeTransformer__visit_ClassDef__7(): """It allows to define an ``__eq__`` method.""" restricted_globals = dict( result1=None, result2=None, _getattr_=getattr, _write_=lambda x: x, __metaclass__=type, __name__='compare_test', ) restricted_exec(COMPARE_TEST, restricted_globals) assert restricted_globals['result1'] is True assert restricted_globals['result2'] is False
def test_RestrictingNodeTransformer__visit_Attribute__5_5( mocker): """It transforms deleting of an attribute to `_write_`.""" glb = { '_write_': mocker.stub(), 'a': mocker.stub(), } glb['a'].b = 'it exists' glb['_write_'].return_value = glb['a'] restricted_exec("del a.b", glb) glb['_write_'].assert_called_once_with(glb['a']) assert not hasattr(glb['a'], 'b')
def test_RestrictingNodeTransformer__visit_ClassDef__8(): """It allows to define a ``__contains__`` method.""" restricted_globals = dict( result1=None, result2=None, _getattr_=getattr, _write_=lambda x: x, __metaclass__=type, __name__='container_test', object=object, ) restricted_exec(CONTAINER_TEST, restricted_globals) assert restricted_globals['result1'] is True assert restricted_globals['result2'] is True
def test_RestrictingNodeTransformer__visit_Attribute__8( 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) } restricted_exec('lambda_default = lambda x=b.b: x', glb) _getattr_.assert_has_calls([mocker.call(glb['b'], 'b')]) assert glb['lambda_default']() == 2
def test_RestrictingNodeTransformer__visit_Attribute__7( mocker): """It transforms attribute access in function default kw to `_write_`.""" _getattr_ = mocker.Mock() _getattr_.side_effect = getattr glb = { '_getattr_': _getattr_, 'a': mocker.Mock(a=1), } restricted_exec(TRANSFORM_ATTRIBUTE_ACCESS_FUNCTION_DEFAULT, glb) _getattr_.assert_has_calls([mocker.call(glb['a'], 'a')]) assert glb['func_default']() == 1
def test_RestrictingNodeTransformer__visit_ClassDef__8(): """It allows to define a ``__contains__`` method.""" restricted_globals = dict( result1=None, result2=None, _getattr_=getattr, _write_=lambda x: x, __metaclass__=type, __name__='container_test', object=object, ) restricted_exec(CONTAINER_TEST, restricted_globals) assert restricted_globals['result1'] is True assert restricted_globals['result2'] is True
def test_Guards__safer_getattr__2(): """It prevents using the format method of a unicode. format() is considered harmful: http://lucumr.pocoo.org/2016/12/29/careful-with-str-format/ """ glb = { '__builtins__': safe_builtins, } with pytest.raises(NotImplementedError) as err: restricted_exec(UNICODE_DOT_FORMAT_DENIED, glb) if IS_PY2: 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)
def test_RestrictingNodeTransformer__visit_Call__2(mocker): _apply_ = mocker.stub() _apply_.side_effect = lambda func, *args, **kwargs: func(*args, **kwargs) glb = {'_apply_': _apply_, 'foo': lambda *args, **kwargs: (args, kwargs)} restricted_exec(FUNCTIONC_CALLS, glb) ret = glb['positional_args']() assert ((1, 2), {}) == ret assert _apply_.called is False _apply_.reset_mock() ret = glb['star_args']() ref = ((3, 4), {}) assert ref == ret _apply_.assert_called_once_with(glb['foo'], *ref[0]) _apply_.reset_mock() ret = glb['positional_and_star_args']() ref = ((1, 2, 3, 4), {}) assert ref == ret _apply_.assert_called_once_with(glb['foo'], *ref[0]) _apply_.reset_mock() ret = glb['kw_args']() ref = ((), {'x': 5, 'y': 6}) assert ref == ret _apply_.assert_called_once_with(glb['foo'], **ref[1]) _apply_.reset_mock() ret = glb['star_and_kw']() ref = ((3, 4), {'x': 5, 'y': 6}) assert ref == ret _apply_.assert_called_once_with(glb['foo'], *ref[0], **ref[1]) _apply_.reset_mock() ret = glb['positional_and_star_and_kw_args']() ref = ((1, 3, 4), {'x': 5, 'y': 6}) assert ref == ret _apply_.assert_called_once_with(glb['foo'], *ref[0], **ref[1]) _apply_.reset_mock() ret = glb['positional_and_star_and_keyword_and_kw_args']() ref = ((1, 2, 3, 4), {'x': 5, 'y': 6, 'r': 9}) assert ref == ret _apply_.assert_called_once_with(glb['foo'], *ref[0], **ref[1]) _apply_.reset_mock()
def test_RestrictingNodeTransformer__visit_ClassDef__3(): """It applies the global __metaclass__ to all generated classes if present. """ def _metaclass(name, bases, dict): ob = type(name, bases, dict) ob.foo = 2411 return ob restricted_globals = dict(__metaclass__=_metaclass, __name__='implicit_metaclass', b=None, _getattr_=getattr) restricted_exec(IMPLICIT_METACLASS, restricted_globals) assert restricted_globals['b'] == 2411
def test_RestrictingNodeTransformer__visit_ClassDef__5(): """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) restricted_exec(DECORATED_CLASS, restricted_globals) comb = restricted_globals['comb'] assert comb.class_att == 2342 assert comb.base_att == 42 assert comb.wrap_att == 23
def test_with_stmt_attribute_access(mocker): _getattr_ = mocker.stub() _getattr_.side_effect = getattr _write_ = mocker.stub() _write_.side_effect = lambda ob: ob glb = {'_getattr_': _getattr_, '_write_': _write_} restricted_exec(WITH_STMT_ATTRIBUTE_ACCESS, glb) # Test simple ctx = mocker.MagicMock(y=1) ctx.__enter__.return_value = ctx glb['simple'](ctx) assert ctx.z == 2 _write_.assert_called_once_with(ctx) _getattr_.assert_called_once_with(ctx, 'y') _write_.reset_mock() _getattr_.reset_mock() # Test assign_attr x = mocker.Mock() glb['assign_attr'](ctx, x) assert x.z == 1 assert x.y == ctx _write_.assert_has_calls([ mocker.call(x), mocker.call(x) ]) _write_.reset_mock() # Test load_attr ctx = mocker.MagicMock() ctx.__enter__.return_value = ctx w = mocker.Mock(ctx=ctx) glb['load_attr'](w) assert w.ctx.z == 1 _getattr_.assert_called_once_with(w, 'ctx') _write_.assert_called_once_with(w.ctx)
def test_RestrictingNodeTransformer__visit_AugAssign__1( mocker): """It allows augmented assign for variables.""" _inplacevar_ = mocker.stub() _inplacevar_.side_effect = lambda op, val, expr: val + expr glb = { '_inplacevar_': _inplacevar_, 'a': 1, 'x': 1, 'z': 0 } restricted_exec("a += x + z", glb) assert glb['a'] == 2 _inplacevar_.assert_called_once_with('+=', 1, 1) _inplacevar_.reset_mock()
def test_Guards__guarded_unpack_sequence__1(mocker): """If the sequence is shorter then expected the interpreter will raise 'ValueError: need more than X value to unpack' anyway => No childs are unpacked => nothing to protect.""" src = "one, two, three = (1, 2)" _getiter_ = mocker.stub() _getiter_.side_effect = lambda it: it glb = { '_getiter_': _getiter_, '_unpack_sequence_': guarded_unpack_sequence, } with pytest.raises(ValueError) as excinfo: restricted_exec(src, glb) assert 'values to unpack' in str(excinfo.value) assert _getiter_.call_count == 1
def test_RestrictingNodeTransformer__guard_iter__2(mocker): it = ((1, 2), (3, 4), (5, 6)) call_ref = [ mocker.call(it), mocker.call(it[0]), mocker.call(it[1]), mocker.call(it[2]) ] _getiter_ = mocker.stub() _getiter_.side_effect = lambda x: x glb = { '_getiter_': _getiter_, '_iter_unpack_sequence_': guarded_iter_unpack_sequence } restricted_exec(ITERATORS_WITH_UNPACK_SEQUENCE, glb) ret = glb['for_loop'](it) assert ret == 21 _getiter_.assert_has_calls(call_ref) _getiter_.reset_mock() ret = glb['dict_comp'](it) assert ret == {1: 3, 3: 7, 5: 11} _getiter_.assert_has_calls(call_ref) _getiter_.reset_mock() ret = glb['list_comp'](it) assert ret == [3, 7, 11] _getiter_.assert_has_calls(call_ref) _getiter_.reset_mock() ret = glb['set_comp'](it) assert ret == {3, 7, 11} _getiter_.assert_has_calls(call_ref) _getiter_.reset_mock() ret = list(glb['generator'](it)) assert ret == [3, 7, 11] _getiter_.assert_has_calls(call_ref) _getiter_.reset_mock()
def test_with_stmt_attribute_access(mocker): _getattr_ = mocker.stub() _getattr_.side_effect = getattr _write_ = mocker.stub() _write_.side_effect = lambda ob: ob glb = {'_getattr_': _getattr_, '_write_': _write_} restricted_exec(WITH_STMT_ATTRIBUTE_ACCESS, glb) # Test simple ctx = mocker.MagicMock(y=1) ctx.__enter__.return_value = ctx glb['simple'](ctx) assert ctx.z == 2 _write_.assert_called_once_with(ctx) _getattr_.assert_called_once_with(ctx, 'y') _write_.reset_mock() _getattr_.reset_mock() # Test assign_attr x = mocker.Mock() glb['assign_attr'](ctx, x) assert x.z == 1 assert x.y == ctx _write_.assert_has_calls([mocker.call(x), mocker.call(x)]) _write_.reset_mock() # Test load_attr ctx = mocker.MagicMock() ctx.__enter__.return_value = ctx w = mocker.Mock(ctx=ctx) glb['load_attr'](w) assert w.ctx.z == 1 _getattr_.assert_called_once_with(w, 'ctx') _write_.assert_called_once_with(w.ctx)
def test_with_stmt_unpack_sequence(mocker): @contextlib.contextmanager def ctx(): yield (1, (2, 3)) _getiter_ = mocker.stub() _getiter_.side_effect = lambda ob: ob glb = { '_getiter_': _getiter_, '_unpack_sequence_': guarded_unpack_sequence } restricted_exec(WITH_STMT_WITH_UNPACK_SEQUENCE, glb) ret = glb['call'](ctx) assert ret == (1, 2, 3) _getiter_.assert_has_calls([mocker.call((1, (2, 3))), mocker.call((2, 3))])
def test_RestrictingNodeTransformer__visit_Lambda__9(mocker): _getiter_ = mocker.stub() _getiter_.side_effect = lambda it: it glb = { '_getiter_': _getiter_, '_unpack_sequence_': guarded_unpack_sequence, '_getattr_': getattr, 'sum': sum, } src = "m = lambda (a, (b, c)), *ag, **kw: a+b+c+sum(ag)+sum(kw.values())" restricted_exec(src, glb) ret = glb['m']((1, (2, 3)), 4, 5, 6, g=7, e=8) assert ret == 36 assert 2 == _getiter_.call_count _getiter_.assert_any_call((1, (2, 3))) _getiter_.assert_any_call((2, 3))
def test_Guards__safe_builtins__2(): """It allows to define new classes by allowing `__build_class__`. """ class_can_be_defined_code = ''' class MyClass: value = None def display(self): return str(self.value) ob1 = MyClass() ob1.value = 2411 result = ob1.display()''' restricted_globals = dict(result=None, __name__='restricted_module', __metaclass__=type, _write_=_write_, _getattr_=getattr) restricted_exec(class_can_be_defined_code, restricted_globals) assert restricted_globals['result'] == '2411'
def test_RestrictingNodeTransformer__visit_Assign__2( mocker): src = "a, *d, (c, *e), x = (1, 2, 3, (4, 3, 4), 5)" _getiter_ = mocker.stub() _getiter_.side_effect = lambda it: it glb = { '_getiter_': _getiter_, '_unpack_sequence_': guarded_unpack_sequence } restricted_exec(src, glb) assert glb['a'] == 1 assert glb['d'] == [2, 3] assert glb['c'] == 4 assert glb['e'] == [3, 4] assert glb['x'] == 5 _getiter_.assert_has_calls([ mocker.call((1, 2, 3, (4, 3, 4), 5)), mocker.call((4, 3, 4))])
def test_RestrictingNodeTransformer__visit_Assign__1(mocker): src = "orig = (a, (x, z)) = (c, d) = g" _getiter_ = mocker.stub() _getiter_.side_effect = lambda it: it glb = { '_getiter_': _getiter_, '_unpack_sequence_': guarded_unpack_sequence, 'g': (1, (2, 3)), } restricted_exec(src, glb) assert glb['a'] == 1 assert glb['x'] == 2 assert glb['z'] == 3 assert glb['c'] == 1 assert glb['d'] == (2, 3) assert glb['orig'] == (1, (2, 3)) assert _getiter_.call_count == 3 _getiter_.assert_any_call((1, (2, 3))) _getiter_.assert_any_call((2, 3)) _getiter_.reset_mock()
def test_dict_comprehension_with_attrs(mocker): _getattr_ = mocker.Mock() _getattr_.side_effect = getattr _getiter_ = mocker.Mock() _getiter_.side_effect = lambda ob: ob glb = {'_getattr_': _getattr_, '_getiter_': _getiter_} restricted_exec(DICT_COMPREHENSION_WITH_ATTRS, glb) z = [mocker.Mock(k=0, v='a'), mocker.Mock(k=1, v='b')] seq = mocker.Mock(z=z) ret = glb['call'](seq) assert ret == {1: 'b'} _getiter_.assert_called_once_with(z) calls = [mocker.call(seq, 'z')] # Note: Order changed in PEP 572, starting with Python 3.8. if IS_PY38_OR_GREATER: calls.extend([ mocker.call(z[0], 'k'), mocker.call(z[1], 'k'), mocker.call(z[1], 'k'), mocker.call(z[1], 'v'), ]) else: calls.extend([ mocker.call(z[0], 'k'), mocker.call(z[1], 'k'), mocker.call(z[1], 'v'), mocker.call(z[1], 'k'), ]) _getattr_.assert_has_calls(calls)
def test_dict_comprehension_with_attrs(mocker): _getattr_ = mocker.Mock() _getattr_.side_effect = getattr _getiter_ = mocker.Mock() _getiter_.side_effect = lambda ob: ob glb = {'_getattr_': _getattr_, '_getiter_': _getiter_} restricted_exec(DICT_COMPREHENSION_WITH_ATTRS, glb) z = [mocker.Mock(k=0, v='a'), mocker.Mock(k=1, v='b')] seq = mocker.Mock(z=z) ret = glb['call'](seq) assert ret == {1: 'b'} _getiter_.assert_called_once_with(z) _getattr_.assert_has_calls([ mocker.call(seq, 'z'), mocker.call(z[0], 'k'), mocker.call(z[1], 'k'), mocker.call(z[1], 'v'), mocker.call(z[1], 'k') ])
def test_Guards__write_wrapper__1(): """It wraps the value attribute when it is not marked with _guarded_writes.""" class ObjWithoutGuardedWrites: my_attr = None setattr_without_guarded_writes_code = ''' my_ob = ObjWithoutGuardedWrites() setattr(my_ob, 'my_attr', 'bar')''' restricted_globals = dict( __builtins__=safe_builtins, ObjWithoutGuardedWrites=ObjWithoutGuardedWrites, my_attr=None, __name__='restricted_module', __metaclass__=type, _write_=_write_, _getattr_=getattr, ) with pytest.raises(TypeError) as excinfo: restricted_exec(setattr_without_guarded_writes_code, restricted_globals) assert 'attribute-less object (assign or del)' in str(excinfo.value)
def test_RestrictingNodeTransformer__visit_Assert__1(): """It allows assert statements.""" restricted_exec('assert 1')
def test_RestrictingNodeTransformer__visit_Name__2_5(): """It allows `_` as variable name.""" glb = restricted_exec('_ = 2411') assert glb['_'] == 2411
def test_Global(): glb = {'a': None} restricted_exec(GLOBAL_EXAMPLE, glb) assert glb['a'] == 11
def test_RestrictingNodeTransformer__visit_Attribute__3(mocker): """It transforms the attribute access to `_getattr_`.""" glb = {'_getattr_': mocker.stub(), 'a': [], 'b': 'b'} restricted_exec(TRANSFORM_ATTRIBUTE_ACCESS, glb) glb['func']() glb['_getattr_'].assert_called_once_with([], 'b')
def test_RestrictingNodeTransformer__visit_Break__1(): """It allows `break` statements.""" glb = restricted_exec(BREAK) assert glb['a'] == 8
def test_RestrictingNodeTransformer__visit_Continue__1(): """It allows `continue` statements.""" glb = restricted_exec(CONTINUE) assert glb['a'] == 15
def test_RestrictingNodeTransformer__visit_Lambda__10(): """Simple lambda functions are allowed.""" restricted_globals = dict(g=None, ) restricted_exec(LAMBDA_FUNC_1, restricted_globals) assert 4 == restricted_globals['g'](2)
def test_RestrictingNodeTransformer__visit_While__1(): """It allows `while` statements.""" glb = restricted_exec(WHILE) assert glb['a'] == 8