コード例 #1
0
def test_print_stmt__simple_prints():
    glb = {'_print_': PrintCollector, '_getattr_': None}

    code, errors = compile_restricted_exec(ALLOWED_PRINT_STATEMENT)[:2]
    assert code is not None
    assert errors == ()
    exec(code, glb)
    assert glb['_print']() == 'Hello World!\n'

    code, errors = compile_restricted_exec(
        ALLOWED_PRINT_STATEMENT_WITH_NO_NL)[:2]
    assert code is not None
    assert errors == ()
    exec(code, glb)
    assert glb['_print']() == 'Hello World!'

    code, errors = compile_restricted_exec(ALLOWED_MULTI_PRINT_STATEMENT)[:2]
    assert code is not None
    assert errors == ()
    exec(code, glb)
    assert glb['_print']() == 'Hello World! Hello Earth!\n'

    code, errors = compile_restricted_exec(ALLOWED_PRINT_TUPLE)[:2]
    assert code is not None
    assert errors == ()
    exec(code, glb)
    assert glb['_print']() == "Hello World!\n"

    code, errors = compile_restricted_exec(ALLOWED_PRINT_MULTI_TUPLE)[:2]
    assert code is not None
    assert errors == ()
    exec(code, glb)
    assert glb['_print']() == "('Hello World!', 'Hello Earth!')\n"
コード例 #2
0
def test_print_stmt__simple_prints():
    glb = {'_print_': PrintCollector, '_getattr_': None}

    code, errors = compile_restricted_exec(ALLOWED_PRINT_STATEMENT)[:2]
    assert code is not None
    assert errors == ()
    exec(code, glb)
    assert glb['_print']() == 'Hello World!\n'

    code, errors = compile_restricted_exec(
        ALLOWED_PRINT_STATEMENT_WITH_NO_NL)[:2]
    assert code is not None
    assert errors == ()
    exec(code, glb)
    assert glb['_print']() == 'Hello World!'

    code, errors = compile_restricted_exec(ALLOWED_MULTI_PRINT_STATEMENT)[:2]
    assert code is not None
    assert errors == ()
    exec(code, glb)
    assert glb['_print']() == 'Hello World! Hello Earth!\n'

    code, errors = compile_restricted_exec(ALLOWED_PRINT_TUPLE)[:2]
    assert code is not None
    assert errors == ()
    exec(code, glb)
    assert glb['_print']() == "Hello World!\n"

    code, errors = compile_restricted_exec(ALLOWED_PRINT_MULTI_TUPLE)[:2]
    assert code is not None
    assert errors == ()
    exec(code, glb)
    assert glb['_print']() == "('Hello World!', 'Hello Earth!')\n"
コード例 #3
0
def test_RestrictingNodeTransformer__visit_Lambda__6():
    """It prevents arguments starting with `_` in nested tuple unpacking."""
    result = compile_restricted_exec("lambda (a, (c, (_bad, c))): None")
    # RestrictedPython.compile.compile_restricted_exec on Python 2 renders
    # the error message twice. This is necessary as otherwise *_bad and
    # **_bad would be allowed.
    assert lambda_err_msg in result.errors
コード例 #4
0
def test_RestrictingNodeTransformer__visit_FunctionDef__6():
    """It prevents function arguments starting with `_` in tuples."""
    result = compile_restricted_exec("def foo(a, (c, (_bad, c))): pass")
    # RestrictedPython.compile.compile_restricted_exec on Python 2 renders
    # the error message twice. This is necessary as otherwise *_bad and
    # **_bad would be allowed.
    assert functiondef_err_msg in result.errors
コード例 #5
0
def test_with_stmt_multi_ctx_unpack_sequence(mocker):
    result = compile_restricted_exec(WITH_STMT_MULTI_CTX_WITH_UNPACK_SEQUENCE)
    assert result.errors == ()

    @contextlib.contextmanager
    def ctx1():
        yield (1, (2, 3))

    @contextlib.contextmanager
    def ctx2():
        yield (4, 5), (6, 7)

    _getiter_ = mocker.stub()
    _getiter_.side_effect = lambda ob: ob

    glb = {
        '_getiter_': _getiter_,
        '_unpack_sequence_': guarded_unpack_sequence
    }

    exec(result.code, glb)

    ret = glb['call'](ctx1, ctx2)

    assert ret == (1, 2, 3, 4, 5, 6, 7)
    _getiter_.assert_has_calls([
        mocker.call((1, (2, 3))),
        mocker.call((2, 3)),
        mocker.call(((4, 5), (6, 7))),
        mocker.call((4, 5)),
        mocker.call((6, 7))
    ])
コード例 #6
0
def run_test(program: str, *input_policies) -> bool:
    lcls = {
        f'dp{index}': get_dummy_pair(policy, index)
        for index, policy in enumerate(input_policies)
    }
    lcls.update(gen_module_namespace())
    lcls['ret'] = ret
    lcls['edit'] = edit
    lcls['double'] = double
    lcls['Collection'] = Collection
    lcls['display'] = display
    lcls['test'] = gen_dummy_fn('test')
    lcls['filter'] = gen_dummy_fn('filter')
    lcls['view'] = gen_dummy_fn('view')
    glbls = {'__builtins__': safe_builtins}

    while True:
        try:
            compile_results = compile_restricted_exec(program)
            if compile_results.errors:
                raise Exception(compile_results.errors)
            else:
                exec(compile_results.code, glbls, lcls)

                return True

        except:
            print(traceback.format_exc())
            return False
コード例 #7
0
def test_RestrictingNodeTransformer__visit_Name__3():
    """It denies a function name starting in `_`."""
    result = compile_restricted_exec(
        BAD_NAME_OVERRIDE_OVERRIDE_GUARD_WITH_FUNCTION)
    assert result.errors == (
        'Line 2: "_getattr" is an invalid variable name because it '
        'starts with "_"', )
コード例 #8
0
def test_RestrictingNodeTransformer__visit_Lambda__6():
    """It prevents arguments starting with `_` in nested tuple unpacking."""
    result = compile_restricted_exec("lambda (a, (c, (_bad, c))): None")
    # RestrictedPython.compile.compile_restricted_exec on Python 2 renders
    # the error message twice. This is necessary as otherwise *_bad and
    # **_bad would be allowed.
    assert lambda_err_msg in result.errors
コード例 #9
0
def test_RestrictingNodeTransformer__visit_Lambda__2():
    """It prevents keyword arguments starting with `_`."""
    result = compile_restricted_exec("lambda _bad=1: None")
    # RestrictedPython.compile.compile_restricted_exec on Python 2 renders
    # the error message twice. This is necessary as otherwise *_bad and **_bad
    # would be allowed.
    assert lambda_err_msg in result.errors
コード例 #10
0
def test_print_stmt_conditional_print():
    code, errors = compile_restricted_exec(CONDITIONAL_PRINT)[:2]
    glb = {'_print_': PrintCollector, '_getattr_': None}
    exec(code, glb)

    assert glb['func'](True) == '1\n'
    assert glb['func'](False) == ''
コード例 #11
0
def test_print_stmt_no_new_scope():
    code, errors = compile_restricted_exec(NO_PRINT_SCOPES)[:2]
    glb = {'_print_': PrintCollector, '_getattr_': None}
    exec(code, glb)

    ret = glb['class_scope']()
    assert ret == 'a\n'
コード例 #12
0
ファイル: core.py プロジェクト: ancile-project/PyPrivacy
def execute(users_secrets, program, app_id=None, app_module=None):
    json_output = dict()
    # object to interact with the program
    result = Result()

    glbls = {
        '__builtins__': safe_builtins,
        '_getitem_': default_guarded_getitem
    }

    lcls = assemble_locals(result=result,
                           users_secrets=users_secrets,
                           app_id=app_id,
                           debug=True)
    try:
        c_program = compile_restricted_exec(program)
        exec(c_program, glbls, lcls)

    except:
        print(traceback.format_exc())
        json_output = {'result': 'error', 'traceback': traceback.format_exc()}
        return json_output

    json_output['stored_items'] = result._stored_keys
    json_output['encrypted_data'] = result._encrypted_data
    json_output['data'] = result._dp_pair_data
    json_output['result'] = 'ok'
    return json_output
コード例 #13
0
def test_print_stmt__with_printed_no_print():
    code, errors, warnings = compile_restricted_exec(WARN_PRINTED_NO_PRINT)[:3]

    assert code is not None
    assert errors == ()
    assert warnings == [
        "Line 2: Doesn't print, but reads 'printed' variable."]
コード例 #14
0
def execute(hass, filename, source, data):
    """Execute a script."""
    from RestrictedPython import compile_restricted_exec
    from RestrictedPython.Guards import safe_builtins, full_write_guard

    compiled = compile_restricted_exec(source, filename=filename)

    if compiled.errors:
        _LOGGER.error('Error loading script %s: %s', filename,
                      ', '.join(compiled.errors))
        return

    if compiled.warnings:
        _LOGGER.warning('Warning loading script %s: %s', filename,
                        ', '.join(compiled.warnings))

    restricted_globals = {
        '__builtins__': safe_builtins,
        '_print_': StubPrinter,
        '_getattr_': getattr,
        '_write_': full_write_guard,
    }
    local = {
        'hass': hass,
        'data': data,
        'logger': logging.getLogger('{}.{}'.format(__name__, filename))
    }

    try:
        _LOGGER.info('Executing %s: %s', filename, data)
        # pylint: disable=exec-used
        exec(compiled.code, restricted_globals, local)
    except Exception as err:  # pylint: disable=broad-except
        _LOGGER.exception('Error executing script %s: %s', filename, err)
コード例 #15
0
def test_with_stmt_multi_ctx_unpack_sequence(mocker):
    result = compile_restricted_exec(WITH_STMT_MULTI_CTX_WITH_UNPACK_SEQUENCE)
    assert result.errors == ()

    @contextlib.contextmanager
    def ctx1():
        yield (1, (2, 3))

    @contextlib.contextmanager
    def ctx2():
        yield (4, 5), (6, 7)

    _getiter_ = mocker.stub()
    _getiter_.side_effect = lambda ob: ob

    glb = {
        '_getiter_': _getiter_,
        '_unpack_sequence_': guarded_unpack_sequence
    }

    exec(result.code, glb)

    ret = glb['call'](ctx1, ctx2)

    assert ret == (1, 2, 3, 4, 5, 6, 7)
    _getiter_.assert_has_calls([
        mocker.call((1, (2, 3))),
        mocker.call((2, 3)),
        mocker.call(((4, 5), (6, 7))),
        mocker.call((4, 5)),
        mocker.call((6, 7))
    ])
コード例 #16
0
def test_print_stmt__with_printed_no_print_nested():
    code, errors, warnings = compile_restricted_exec(
        WARN_PRINTED_NO_PRINT_NESTED)[:3]

    assert code is not None
    assert errors == ()
    assert warnings == ["Line 3: Doesn't print, but reads 'printed' variable."]
コード例 #17
0
def test_call_py2_builtins():
    """It should not be allowed to access global __builtins__ in Python2."""
    result = compile_restricted_exec('__builtins__["getattr"]')
    assert result.code is None
    assert result.errors == (
        'Line 1: "__builtins__" is an invalid variable name because it starts with "_"',
    )  # NOQA: E501
コード例 #18
0
def test_call_breakpoint():
    """The Python3.7+ builtin function breakpoint should not
    be used and is forbidden in RestrictedPython.
    """
    result = compile_restricted_exec('breakpoint()')
    assert result.errors == ('Line 1: "breakpoint" is a reserved name.',)
    assert result.code is None
コード例 #19
0
def test_print_stmt_conditional_print():
    code, errors = compile_restricted_exec(CONDITIONAL_PRINT)[:2]
    glb = {'_print_': PrintCollector, '_getattr_': None}
    exec(code, glb)

    assert glb['func'](True) == '1\n'
    assert glb['func'](False) == ''
コード例 #20
0
def test_RestrictingNodeTransformer__visit_Lambda__2():
    """It prevents keyword arguments starting with `_`."""
    result = compile_restricted_exec("lambda _bad=1: None")
    # RestrictedPython.compile.compile_restricted_exec on Python 2 renders
    # the error message twice. This is necessary as otherwise *_bad and **_bad
    # would be allowed.
    assert lambda_err_msg in result.errors
コード例 #21
0
def test_print_stmt_no_new_scope():
    code, errors = compile_restricted_exec(NO_PRINT_SCOPES)[:2]
    glb = {'_print_': PrintCollector, '_getattr_': None}
    exec(code, glb)

    ret = glb['class_scope']()
    assert ret == 'a\n'
コード例 #22
0
def test_async_yield_from():
    """`yield from` statement should be allowed."""
    result = compile_restricted_exec(ASYNC_YIELD_FORM_EXAMPLE)
    assert result.errors == (
        'Line 4: AsyncFunctionDef statements are not allowed.',
    )
    assert result.code is None
コード例 #23
0
def execute(hass, filename, source, data=None):
    """Execute Python source."""

    compiled = compile_restricted_exec(source, filename=filename)

    if compiled.errors:
        _LOGGER.error("Error loading script %s: %s", filename,
                      ", ".join(compiled.errors))
        return

    if compiled.warnings:
        _LOGGER.warning("Warning loading script %s: %s", filename,
                        ", ".join(compiled.warnings))

    def protected_getattr(obj, name, default=None):
        """Restricted method to get attributes."""
        if name.startswith("async_"):
            raise ScriptError("Not allowed to access async methods")
        if (obj is hass and name not in ALLOWED_HASS
                or obj is hass.bus and name not in ALLOWED_EVENTBUS
                or obj is hass.states and name not in ALLOWED_STATEMACHINE
                or obj is hass.services and name not in ALLOWED_SERVICEREGISTRY
                or obj is dt_util and name not in ALLOWED_DT_UTIL
                or obj is datetime and name not in ALLOWED_DATETIME
                or isinstance(obj, TimeWrapper) and name not in ALLOWED_TIME):
            raise ScriptError(
                f"Not allowed to access {obj.__class__.__name__}.{name}")

        return getattr(obj, name, default)

    builtins = safe_builtins.copy()
    builtins.update(utility_builtins)
    builtins["datetime"] = datetime
    builtins["sorted"] = sorted
    builtins["time"] = TimeWrapper()
    builtins["dt_util"] = dt_util
    logger = logging.getLogger(f"{__name__}.{filename}")
    restricted_globals = {
        "__builtins__": builtins,
        "_print_": StubPrinter,
        "_getattr_": protected_getattr,
        "_write_": full_write_guard,
        "_getiter_": iter,
        "_getitem_": default_guarded_getitem,
        "_iter_unpack_sequence_": guarded_iter_unpack_sequence,
        "_unpack_sequence_": guarded_unpack_sequence,
        "hass": hass,
        "data": data or {},
        "logger": logger,
    }

    try:
        _LOGGER.info("Executing %s: %s", filename, data)
        # pylint: disable=exec-used
        exec(compiled.code, restricted_globals)
    except ScriptError as err:
        logger.error("Error executing script: %s", err)
    except Exception as err:  # pylint: disable=broad-except
        logger.exception("Error executing script: %s", err)
コード例 #24
0
def test_RestrictingNodeTransformer__visit_Call__1():
    """It compiles a function call successfully and returns the used name."""
    result = compile_restricted_exec('a = max([1, 2, 3])')
    assert result.errors == ()
    loc = {}
    exec(result.code, {}, loc)
    assert loc['a'] == 3
    assert result.used_names == {'max': True}
コード例 #25
0
def test_RestrictingNodeTransformer__visit_ClassDef__4():
    """It does not allow to pass a metaclass to class definitions."""

    result = compile_restricted_exec(EXPLICIT_METACLASS)

    assert result.errors == (
        'Line 2: The keyword argument "metaclass" is not allowed.',)
    assert result.code is None
コード例 #26
0
def test_import_py3_builtins():
    """It should not be allowed to access global builtins in Python3."""
    result = compile_restricted_exec(BUILTINS_EXAMPLE)
    assert result.code is None
    assert result.errors == (
        'Line 2: "builtins" is a reserved name.',
        'Line 4: "builtins" is a reserved name.'
    )
コード例 #27
0
def test_import_py2_as_builtins():
    """It should not be allowed to access global __builtins__ in Python2."""
    result = compile_restricted_exec(__BUILTINS_EXAMPLE)
    assert result.code is None
    assert result.errors == (
        'Line 2: "__builtins__" is an invalid variable name because it starts with "_"',  # NOQA: E501
        'Line 4: "__builtins__" is an invalid variable name because it starts with "_"'  # NOQA: E501
    )
コード例 #28
0
def test_RestrictingNodeTransformer__visit_ClassDef__4():
    """It does not allow to pass a metaclass to class definitions."""

    result = compile_restricted_exec(EXPLICIT_METACLASS)

    assert result.errors == (
        'Line 2: The keyword argument "metaclass" is not allowed.', )
    assert result.code is None
コード例 #29
0
def test_print_stmt__with_print_no_printed():
    code, errors, warnings = compile_restricted_exec(WARN_PRINT_NO_PRINTED)[:3]

    assert code is not None
    assert errors == ()
    assert warnings == [
        "Line 2: Prints, but never reads 'printed' variable."
    ]
コード例 #30
0
def test_print_stmt__nested_print_collector(mocker):
    code, errors = compile_restricted_exec(INJECT_PRINT_COLLECTOR_NESTED)[:2]

    glb = {"_print_": PrintCollector, '_getattr_': None}
    exec(code, glb)

    ret = glb['main']()
    assert ret == 'inner\nf1\nf2main\n'
コード例 #31
0
def test_RestrictingNodeTransformer__visit_Call__1():
    """It compiles a function call successfully and returns the used name."""
    result = compile_restricted_exec('a = max([1, 2, 3])')
    assert result.errors == ()
    loc = {}
    exec(result.code, {}, loc)
    assert loc['a'] == 3
    assert result.used_names == {'max': True}
コード例 #32
0
def test_iterate_over_dict_items_safe():
    glb = safe_globals.copy()
    glb['_getiter_'] = default_guarded_getiter
    glb['_iter_unpack_sequence_'] = guarded_iter_unpack_sequence
    result = compile_restricted_exec(ITERATE_OVER_DICT_ITEMS)
    assert result.code is not None
    assert result.errors == ()
    exec(result.code, glb, None)
コード例 #33
0
def test_iterate_over_dict_items_safe():
    glb = safe_globals.copy()
    glb['_getiter_'] = default_guarded_getiter
    glb['_iter_unpack_sequence_'] = guarded_iter_unpack_sequence
    result = compile_restricted_exec(ITERATE_OVER_DICT_ITEMS)
    assert result.code is not None
    assert result.errors == ()
    exec(result.code, glb, None)
コード例 #34
0
def test_iterate_over_dict_items_plain():
    glb = {}
    result = compile_restricted_exec(ITERATE_OVER_DICT_ITEMS)
    assert result.code is not None
    assert result.errors == ()
    with pytest.raises(NameError) as excinfo:
        exec(result.code, glb, None)
    assert "name '_iter_unpack_sequence_' is not defined" in str(excinfo.value)
コード例 #35
0
def test_compile__compile_restricted_exec__4():
    """It does not return code on a SyntaxError."""
    result = compile_restricted_exec('asdf|')
    assert result.code is None
    assert result.warnings == []
    assert result.used_names == {}
    assert result.errors == (
        "Line 1: SyntaxError: invalid syntax at statement: 'asdf|'", )
コード例 #36
0
def test_iterate_over_dict_items_plain():
    glb = {}
    result = compile_restricted_exec(ITERATE_OVER_DICT_ITEMS)
    assert result.code is not None
    assert result.errors == ()
    with pytest.raises(NameError) as excinfo:
        exec(result.code, glb, None)
    assert "name '_iter_unpack_sequence_' is not defined" in str(excinfo.value)
コード例 #37
0
def test_print_stmt__nested_print_collector(mocker):
    code, errors = compile_restricted_exec(INJECT_PRINT_COLLECTOR_NESTED)[:2]

    glb = {"_print_": PrintCollector, '_getattr_': None}
    exec(code, glb)

    ret = glb['main']()
    assert ret == 'inner\nf1\nf2main\n'
コード例 #38
0
def test_transform():
    """It compiles a function call successfully and returns the used name."""

    result = compile_restricted_exec('a = f"{max([1, 2, 3])}"')
    assert result.errors == ()
    loc = {}
    exec(result.code, {}, loc)
    assert loc['a'] == '3'
    assert result.used_names == {'max': True}
コード例 #39
0
def test_compile__compile_restricted_exec__2():
    """It compiles without restrictions if there is no policy."""
    result = compile_restricted_exec('_a = 42', policy=None)
    assert result.errors == ()
    assert result.warnings == []
    assert result.used_names == {}
    glob = {}
    exec(result.code, glob)
    assert glob['_a'] == 42
コード例 #40
0
def execute(hass, filename, source, data=None):
    """Execute Python source."""
    from RestrictedPython import compile_restricted_exec
    from RestrictedPython.Guards import safe_builtins, full_write_guard, \
        guarded_iter_unpack_sequence, guarded_unpack_sequence
    from RestrictedPython.Utilities import utility_builtins
    from RestrictedPython.Eval import default_guarded_getitem

    compiled = compile_restricted_exec(source, filename=filename)

    if compiled.errors:
        _LOGGER.error('Error loading script %s: %s', filename,
                      ', '.join(compiled.errors))
        return

    if compiled.warnings:
        _LOGGER.warning('Warning loading script %s: %s', filename,
                        ', '.join(compiled.warnings))

    def protected_getattr(obj, name, default=None):
        """Restricted method to get attributes."""
        # pylint: disable=too-many-boolean-expressions
        if name.startswith('async_'):
            raise ScriptError('Not allowed to access async methods')
        elif (obj is hass and name not in ALLOWED_HASS
              or obj is hass.bus and name not in ALLOWED_EVENTBUS
              or obj is hass.states and name not in ALLOWED_STATEMACHINE
              or obj is hass.services and name not in ALLOWED_SERVICEREGISTRY):
            raise ScriptError('Not allowed to access {}.{}'.format(
                obj.__class__.__name__, name))

        return getattr(obj, name, default)

    builtins = safe_builtins.copy()
    builtins.update(utility_builtins)
    builtins['datetime'] = datetime
    restricted_globals = {
        '__builtins__': builtins,
        '_print_': StubPrinter,
        '_getattr_': protected_getattr,
        '_write_': full_write_guard,
        '_getiter_': iter,
        '_getitem_': default_guarded_getitem,
        '_iter_unpack_sequence_': guarded_iter_unpack_sequence,
        '_unpack_sequence_': guarded_unpack_sequence,
    }
    logger = logging.getLogger('{}.{}'.format(__name__, filename))
    local = {'hass': hass, 'data': data or {}, 'logger': logger}

    try:
        _LOGGER.info('Executing %s: %s', filename, data)
        # pylint: disable=exec-used
        exec(compiled.code, restricted_globals, local)
    except ScriptError as err:
        logger.error('Error executing script: %s', err)
    except Exception as err:  # pylint: disable=broad-except
        logger.exception('Error executing script: %s', err)
コード例 #41
0
def execute(hass, filename, source, data=None):
    """Execute Python source."""
    from RestrictedPython import compile_restricted_exec
    from RestrictedPython.Guards import safe_builtins, full_write_guard
    from RestrictedPython.Utilities import utility_builtins
    from RestrictedPython.Eval import default_guarded_getitem

    compiled = compile_restricted_exec(source, filename=filename)

    if compiled.errors:
        _LOGGER.error('Error loading script %s: %s', filename,
                      ', '.join(compiled.errors))
        return

    if compiled.warnings:
        _LOGGER.warning('Warning loading script %s: %s', filename,
                        ', '.join(compiled.warnings))

    def protected_getattr(obj, name, default=None):
        """Restricted method to get attributes."""
        # pylint: disable=too-many-boolean-expressions
        if name.startswith('async_'):
            raise ScriptError('Not allowed to access async methods')
        elif (obj is hass and name not in ALLOWED_HASS or
              obj is hass.bus and name not in ALLOWED_EVENTBUS or
              obj is hass.states and name not in ALLOWED_STATEMACHINE or
              obj is hass.services and name not in ALLOWED_SERVICEREGISTRY):
            raise ScriptError('Not allowed to access {}.{}'.format(
                obj.__class__.__name__, name))

        return getattr(obj, name, default)

    builtins = safe_builtins.copy()
    builtins.update(utility_builtins)
    restricted_globals = {
        '__builtins__': builtins,
        '_print_': StubPrinter,
        '_getattr_': protected_getattr,
        '_write_': full_write_guard,
        '_getiter_': iter,
        '_getitem_': default_guarded_getitem
    }
    logger = logging.getLogger('{}.{}'.format(__name__, filename))
    local = {
        'hass': hass,
        'data': data or {},
        'logger': logger
    }

    try:
        _LOGGER.info('Executing %s: %s', filename, data)
        # pylint: disable=exec-used
        exec(compiled.code, restricted_globals, local)
    except ScriptError as err:
        logger.error('Error executing script: %s', err)
    except Exception as err:  # pylint: disable=broad-except
        logger.exception('Error executing script: %s', err)
コード例 #42
0
def test_visit_invalid_variable_name():
    """Accessing private attributes is forbidden.

    This is just a smoke test to validate that restricted exec is used
    in the run-time evaluation of f-strings.
    """
    result = compile_restricted_exec('f"{__init__}"')
    assert result.errors == (
        'Line 1: "__init__" is an invalid variable name because it starts with "_"',  # NOQA: E501
    )
コード例 #43
0
def test_f_string_self_documenting_expressions():
    """Checks if f-string self-documenting expressions is checked."""
    result = compile_restricted_exec(
        f_string_self_documenting_expressions_example,
    )
    assert result.errors == ()

    glb = {'_print_': PrintCollector, '_getattr_': None}
    exec(result.code, glb)
    assert glb['_print']() == "user='******' member_since=datetime.date(1975, 7, 31)\n"  # NOQA: E501
コード例 #44
0
def test_compile__compile_restricted_exec__1():
    """It returns a CompileResult on success."""
    result = compile_restricted_exec('a = 42')
    assert result.__class__ == CompileResult
    assert result.errors == ()
    assert result.warnings == []
    assert result.used_names == {}
    glob = {}
    exec(result.code, glob)
    assert glob['a'] == 42
コード例 #45
0
def test_yield():
    """`yield` statement should be allowed."""
    result = compile_restricted_exec(YIELD_EXAMPLE)
    assert result.errors == ()
    assert result.code is not None
    local = {}
    exec(result.code, {}, local)
    test_generator = local['test_generator']
    exec_result = list(test_generator())
    assert exec_result == [42]
コード例 #46
0
def test_RestrictingNodeTransformer__module_func_def_name_call():
    """It forbids definition and usage of magic methods as functions ...

    ... at module level.
    """
    result = compile_restricted_exec(BLACKLISTED_FUNC_NAMES_CALL_TEST)
    # assert result.errors == ('Line 1: ')
    assert result.errors == (
        'Line 2: "__init__" is an invalid variable name because it starts with "_"',  # NOQA: E501
        'Line 5: "__init__" is an invalid variable name because it starts with "_"',  # NOQA: E501
    )
コード例 #47
0
def test_safer_getattr__underscore_name():
    """It prevents accessing an attribute which starts with an underscore."""
    result = compile_restricted_exec(GETATTR_UNDERSCORE_NAME)
    assert result.errors == ()
    assert result.warnings == []
    glb = safe_globals.copy()
    glb['getattr'] = safer_getattr
    with pytest.raises(AttributeError) as err:
        exec(result.code, glb, {})
    assert (
        '"__class__" is an invalid attribute name because it starts with "_"'
        == str(err.value))
コード例 #48
0
def test_print_stmt__fail_with_none_target(mocker):
    code, errors = compile_restricted_exec('print >> None, "test"')[:2]

    assert code is not None
    assert errors == ()

    glb = {'_getattr_': getattr, '_print_': PrintCollector}

    with pytest.raises(AttributeError) as excinfo:
        exec(code, glb)

    assert "'NoneType' object has no attribute 'write'" in str(excinfo.value)
コード例 #49
0
def test_yield_from():
    """`yield from` statement should be allowed."""
    result = compile_restricted_exec(YIELD_FORM_EXAMPLE)
    assert result.errors == ()
    assert result.code is not None

    def my_external_generator():
        my_list = [1, 2, 3, 4, 5]
        for elem in my_list:
            yield(elem)

    local = {}
    exec(result.code, {}, local)
    reader_wapper = local['reader_wapper']
    exec_result = list(reader_wapper(my_external_generator()))
    assert exec_result == [1, 2, 3, 4, 5]
コード例 #50
0
def test_print_stmt__protect_chevron_print(mocker):
    code, errors = compile_restricted_exec(
        PROTECT_PRINT_STATEMENT_WITH_CHEVRON)[:2]

    _getattr_ = mocker.stub()
    _getattr_.side_effect = getattr
    glb = {'_getattr_': _getattr_, '_print_': PrintCollector}

    exec(code, glb)

    stream = mocker.stub()
    stream.write = mocker.stub()
    glb['print_into_stream'](stream)

    stream.write.assert_has_calls([
        mocker.call('Hello World!'),
        mocker.call('\n')
    ])

    _getattr_.assert_called_once_with(stream, 'write')
コード例 #51
0
def test_Nonlocal():
    result = compile_restricted_exec(NONLOCAL_EXAMPLE)
    assert result.errors == ('Line 5: Nonlocal statements are not allowed.',)
    assert result.code is None
コード例 #52
0
def test_RestrictingNodeTransformer__visit_Lambda__8():
    """It prevents arguments starting with `_` in weird lambdas."""
    result = compile_restricted_exec(BAD_ARG_IN_LAMBDA)
    # On Python 2 the first error message is contained twice:
    assert lambda_err_msg in result.errors
コード例 #53
0
def test_RestrictingNodeTransformer__visit_Lambda__7():
    """It prevents arguments starting with `_` together with a single `*`."""
    result = compile_restricted_exec("lambda good, *, _bad: None")
    assert result.errors == (lambda_err_msg,)
コード例 #54
0
def test_RestrictingNodeTransformer__visit_Lambda__4():
    """It prevents ** arguments starting with `_`."""
    result = compile_restricted_exec("lambda **_bad: None")
    assert result.errors == (lambda_err_msg,)
コード例 #55
0
def test_RestrictingNodeTransformer__visit_Attribute__2():
    """It is an error if a bad attribute name is used."""
    result = compile_restricted_exec(BAD_ATTR_ROLES)
    assert result.errors == (
        'Line 3: "abc__roles__" is an invalid attribute name because it '
        'ends with "__roles__".',)
コード例 #56
0
def test_RestrictingNodeTransformer__visit_Attribute__4():
    """It allows `_` as attribute name."""
    result = compile_restricted_exec(ALLOW_UNDERSCORE_ONLY)
    assert result.errors == ()