Esempio n. 1
0
def simplify_list_comp(
    comp: t.Union[ast.ListComp, ast.GeneratorExp, ast.SetComp, ast.DictComp],
    new_stmts: t.List[ast.stmt],
    init: ast.expr,
    appender_attr: str,
) -> ast.Name:
    rewriter = NameRewriter()
    for gen in comp.generators:
        rewriter.visit(gen.target)

    res_load, res_store = gensym()
    res_stmts: t.List[ast.stmt] = []
    if isinstance(comp, ast.DictComp):
        rewriter.visit(comp.key)
        rewriter.visit(comp.value)
        key = SimplifyExpr(res_stmts).visit(comp.key)
        value = SimplifyExpr(res_stmts).visit(comp.value)
        res_stmts.append(
            ast.Assign(targets=[
                ast.Subscript(value=c.deepcopy(res_load),
                              slice=ast.Index(value=key),
                              ctx=ast.Store())
            ],
                       value=value))
    else:
        rewriter.visit(comp.elt)
        comp.elt = SimplifyExpr(res_stmts).visit(comp.elt)
        res_stmts.append(
            ast.Expr(value=ast.Call(
                func=ast.Attribute(value=c.deepcopy(res_load),
                                   attr=appender_attr,
                                   ctx=ast.Load()),
                args=[comp.elt],
                keywords=[],
            )))

    for gen in reversed(comp.generators):
        new_loop: t.Union[ast.For, ast.AsyncFor]
        if hasattr(gen, 'is_async') and gen.is_async:  # type: ignore
            new_loop = ast.AsyncFor(target=gen.target, orelse=[])
        else:
            new_loop = ast.For(target=gen.target, orelse=[])

        body: t.List[ast.stmt] = []
        new_loop.iter = SimplifyExpr(body).visit(gen.iter)

        for cond in reversed(gen.ifs):
            res_stmts = [ast.If(test=cond, body=res_stmts, orelse=[])]

        new_loop.body = res_stmts

        body.append(new_loop)
        res_stmts = body

    new_stmts.append(ast.Assign(
        targets=[res_store],
        value=init,
    ))
    new_stmts.extend(res_stmts)
    return res_load
Esempio n. 2
0
 def p_async_for_stmt(self, p):
     ''' async_for_stmt : ASYNC for_stmt '''
     async_for = ast.AsyncFor()
     for_node = p[2]
     for attr in tuple(for_node._fields) + ('lineno', 'col_offset'):
         setattr(async_for, attr, getattr(for_node, attr))
     p[0] = async_for
Esempio n. 3
0
 def visit_AsyncFor(self, node):
     new_node = ast.AsyncFor(
         self._visit(node.target),
         self._visit(node.iter),
         self._visit(node.body),
         self._visit(node.orelse),
         None,  # type_comment
     )
     return ast.copy_location(new_node, node)
Esempio n. 4
0
 def visit_AsyncFor(self, node):
     new_body = self.if_exists(node.body, self.visit_list)
     new_orelse = self.if_exists(node.orelse, self.visit_list)
     new_target = self.visit(node.target)
     new_iter = self.visit(node.iter)
     return_list = self.new_stmts + [
         ast.copy_location(
             ast.AsyncFor(new_target, new_iter, new_body, new_orelse), node)
     ]
     self.new_stmts.clear()
     return return_list
    def visit_AsyncFor(self, node: AsyncFor, *args, **kwargs) -> C.AsyncFor:
        target = self.visit(node.target, *args, **kwargs)
        iter = self.visit(node.iter, *args, **kwargs)
        body = self.visit(node.body, *args, **kwargs)
        orelse = self.visit(node.orelse, *args, **kwargs)
        type_comment = self.visit(node.type_comment, *args, **kwargs)

        return C.AsyncFor(
            target=target,
            iter=iter,
            body=body,
            orelse=orelse,
            type_comment=type_comment,
        )
Esempio n. 6
0
def explode_list_comp(
    comp: t.Union[ast.ListComp, ast.GeneratorExp, ast.SetComp],
    new_stmts: t.List[ast.stmt],
    init: ast.expr,
    appender_attr: str,
) -> ast.expr:
    res_load, res_store = gensym()
    res_stmts: t.List[ast.stmt] = [
        ast.Expr(
            value=ast.Call(
                func=ast.Attribute(
                    value=c.deepcopy(res_load),
                    attr=appender_attr,
                    ctx=ast.Load()
                ),
                args=[comp.elt]
            )
        )
    ]

    for gen in reversed(comp.generators):
        new_loop: t.Union[ast.For, ast.AsyncFor]
        if gen.is_async:
            new_loop = ast.AsyncFor(target=gen.target)
        else:
            new_loop = ast.For(target=gen.target)

        body: t.List[ast.stmt] = []
        new_loop.iter = explode_expr(gen.iter, body)

        for cond in reversed(gen.ifs):
            res_stmts = [ast.If(cond, res_stmts)]

        new_loop.body = res_stmts

        body.append(new_loop)
        res_stmts = body

    new_stmts.append(ast.Assign(
        targets=[res_store],
        value=init,
    ))
    new_stmts.extend(res_stmts)
    return res_load
Esempio n. 7
0
import pytest

from astvalidate.validators.contextual import ContextualASTValidator


@pytest.mark.parametrize(
    "node, message",
    [
        (ast.Return(), "inside of a function"),
        (
            ast.AsyncFunctionDef(body=[ast.Yield(), ast.Return(1)]),
            "can't be part of async gen",
        ),
        (ast.Continue(), "inside of a loop"),
        (ast.Break(), "inside of a loop"),
        (ast.AsyncFor(), "inside of a coroutine"),
        (
            ast.Try(handlers=[
                ast.ExceptHandler(type=None),
                ast.ExceptHandler(type=1),
            ]),
            "must be placed last",
        ),
        (
            ast.Module([1, 2, ast.ImportFrom("__future__")]),
            "must occur at the top",
        ),
        (
            ast.Module(
                [ast.ImportFrom("__future__", names=[ast.alias(name="lol")])]),
            "'lol' is not defined",
Esempio n. 8
0
def AsyncFor(draw, statements) -> ast.AsyncFor:
    target = draw(Name(ast.Store))
    iter = draw(expression())
    body = draw(lists(statements, min_size=1, max_size=3))
    orelse = draw(lists(statements, min_size=1, max_size=3))
    return ast.AsyncFor(target, iter, body, orelse)
Esempio n. 9
0
def _translate_all_expression_to_a_module(
        generator_exp: ast.GeneratorExp, generated_function_name: str,
        name_to_value: Mapping[str, Any]) -> ast.Module:
    """
    Generate the AST of the module to trace an all quantifier on an generator expression.

    :param generator_exp: generator expression to be translated
    :param generated_function_name: UUID of the tracing function to be used in the code
    :param name_to_value:
        mapping of all resolved values to the variable names
        (passed as arguments to the function so that the generation can access them)
    :return: translation to a module
    """
    assert generated_function_name not in name_to_value
    assert not hasattr(builtins, generated_function_name)

    # Collect all the names involved in the generation
    relevant_names = _collect_stored_names(
        generator.target for generator in generator_exp.generators)

    assert generated_function_name not in relevant_names

    # Work backwards, from the most-inner block outwards

    result_id = 'icontract_tracing_all_result_{}'.format(uuid.uuid4().hex)
    result_assignment = ast.Assign(
        targets=[ast.Name(id=result_id, ctx=ast.Store())],
        value=generator_exp.elt)

    exceptional_return = ast.Return(
        ast.Tuple(elts=[
            ast.Name(id=result_id, ctx=ast.Load()),
            ast.Tuple(elts=[
                ast.Tuple(elts=[
                    ast.Constant(value=relevant_name, kind=None),
                    ast.Name(id=relevant_name, ctx=ast.Load())
                ],
                          ctx=ast.Load()) for relevant_name in relevant_names
            ],
                      ctx=ast.Load())
        ],
                  ctx=ast.Load()))

    # While happy return shall not be executed, we add it here for robustness in case
    # future refactorings forget to check for that edge case.
    happy_return = ast.Return(
        ast.Tuple(elts=[
            ast.Name(id=result_id, ctx=ast.Load()),
            ast.Constant(value=None, kind=None)
        ],
                  ctx=ast.Load()))

    critical_if: If = ast.If(test=ast.Name(id=result_id, ctx=ast.Load()),
                             body=[ast.Pass()],
                             orelse=[exceptional_return])

    # Previous inner block to be added as body to the next outer block
    block = None  # type: Optional[List[ast.stmt]]
    for i, comprehension in enumerate(reversed(generator_exp.generators)):
        if i == 0:
            # This is the inner-most comprehension.
            block = [result_assignment, critical_if]
        assert block is not None

        for condition in reversed(comprehension.ifs):
            block = [ast.If(test=condition, body=block, orelse=[])]

        if not comprehension.is_async:
            block = [
                ast.For(target=comprehension.target,
                        iter=comprehension.iter,
                        body=block,
                        orelse=[])
            ]
        else:
            block = [
                ast.AsyncFor(target=comprehension.target,
                             iter=comprehension.iter,
                             body=block,
                             orelse=[])
            ]

    assert block is not None

    block.append(happy_return)

    # Now we are ready to generate the function.

    is_async = any(comprehension.is_async
                   for comprehension in generator_exp.generators)

    args = [
        ast.arg(arg=name, annotation=None)
        for name in sorted(name_to_value.keys())
    ]

    if sys.version_info < (3, 5):
        raise NotImplementedError(
            "Python versions below 3.5 not supported, got: {}".format(
                sys.version_info))

    if not is_async:
        if sys.version_info < (3, 8):
            func_def_node = ast.FunctionDef(
                name=generated_function_name,
                args=ast.arguments(args=args,
                                   kwonlyargs=[],
                                   kw_defaults=[],
                                   defaults=[],
                                   vararg=None,
                                   kwarg=None),
                decorator_list=[],
                body=block
            )  # type: Union[ast.FunctionDef, ast.AsyncFunctionDef]

            module_node = ast.Module(body=[func_def_node])
        else:
            func_def_node = ast.FunctionDef(name=generated_function_name,
                                            args=ast.arguments(args=args,
                                                               posonlyargs=[],
                                                               kwonlyargs=[],
                                                               kw_defaults=[],
                                                               defaults=[],
                                                               vararg=None,
                                                               kwarg=None),
                                            decorator_list=[],
                                            body=block)

            module_node = ast.Module(body=[func_def_node], type_ignores=[])
    else:
        if sys.version_info < (3, 8):
            async_func_def_node = ast.AsyncFunctionDef(
                name=generated_function_name,
                args=ast.arguments(args=args,
                                   kwonlyargs=[],
                                   kw_defaults=[],
                                   defaults=[],
                                   vararg=None,
                                   kwarg=None),
                decorator_list=[],
                body=block)

            module_node = ast.Module(body=[async_func_def_node])
        else:
            async_func_def_node = ast.AsyncFunctionDef(
                name=generated_function_name,
                args=ast.arguments(args=args,
                                   posonlyargs=[],
                                   kwonlyargs=[],
                                   kw_defaults=[],
                                   defaults=[],
                                   vararg=None,
                                   kwarg=None),
                decorator_list=[],
                body=block)

            module_node = ast.Module(body=[async_func_def_node],
                                     type_ignores=[])

    ast.fix_missing_locations(module_node)

    return module_node
Esempio n. 10
0
def generate_async_for(max_depth=None):
    target = generate_variable_or_tuple()
    iter = generate_expression(max_depth=max_depth)
    body = generate_block(max_depth=max_depth)
    orelse = random.choice([generate_block(max_depth=max_depth), []])
    return ast.AsyncFor(target, iter, body, orelse)