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 == {}
示例#14
0
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')
    ])
示例#15
0
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
示例#26
0
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')
示例#28
0
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
示例#32
0
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)
示例#33
0
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()
示例#34
0
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
示例#35
0
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)
示例#37
0
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()
示例#38
0
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
示例#39
0
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()
示例#40
0
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)
示例#41
0
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))])
示例#42
0
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))
示例#43
0
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'
示例#44
0
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))])
示例#45
0
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)
示例#47
0
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')
    ])
示例#48
0
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)
示例#49
0
def test_RestrictingNodeTransformer__visit_Assert__1():
    """It allows assert statements."""
    restricted_exec('assert 1')
示例#50
0
def test_RestrictingNodeTransformer__visit_Name__2_5():
    """It allows `_` as variable name."""
    glb = restricted_exec('_ = 2411')
    assert glb['_'] == 2411
示例#51
0
def test_Global():
    glb = {'a': None}
    restricted_exec(GLOBAL_EXAMPLE, glb)
    assert glb['a'] == 11
示例#52
0
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')
示例#53
0
def test_RestrictingNodeTransformer__visit_Break__1():
    """It allows `break` statements."""
    glb = restricted_exec(BREAK)
    assert glb['a'] == 8
示例#54
0
def test_RestrictingNodeTransformer__visit_Continue__1():
    """It allows `continue` statements."""
    glb = restricted_exec(CONTINUE)
    assert glb['a'] == 15
示例#55
0
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)
示例#56
0
def test_RestrictingNodeTransformer__visit_While__1():
    """It allows `while` statements."""
    glb = restricted_exec(WHILE)
    assert glb['a'] == 8