Example #1
0
 def check(self):
     return (is_ast_like(
         self.tree,
         ast.Module(
             body=[ast.Assign(targets=[ast.Name(id='your_name')])]))
             and isinstance(self.console.locals.get('your_name'), str))
Example #2
0
    def visit_Assign(self, node):
        assert (len(node.targets) == 1)
        self.generic_visit(node)

        if isinstance(node.targets[0], ast.Tuple):
            targets = node.targets[0].elts

            # Create
            stmts = []

            holder = self.parse_stmt('__tmp_tuple = 0')
            holder.value = node.value

            stmts.append(holder)

            def tuple_indexed(i):
                indexing = self.parse_stmt('__tmp_tuple[0]')
                indexing.value.slice.value = self.parse_expr("{}".format(i))
                return indexing.value

            for i, target in enumerate(targets):
                is_local = isinstance(target, ast.Name)
                if is_local and self.is_creation(target.id):
                    var_name = target.id
                    target.ctx = ast.Store()
                    # Create
                    init = ast.Attribute(value=ast.Name(id='ti',
                                                        ctx=ast.Load()),
                                         attr='expr_init',
                                         ctx=ast.Load())
                    rhs = ast.Call(
                        func=init,
                        args=[tuple_indexed(i)],
                        keywords=[],
                    )
                    self.create_variable(var_name)
                    stmts.append(ast.Assign(targets=[target], value=rhs))
                else:
                    # Assign
                    target.ctx = ast.Load()
                    func = ast.Attribute(value=target,
                                         attr='assign',
                                         ctx=ast.Load())
                    call = ast.Call(func=func,
                                    args=[tuple_indexed(i)],
                                    keywords=[])
                    stmts.append(ast.Expr(value=call))

            for stmt in stmts:
                ast.copy_location(stmt, node)
            stmts.append(self.parse_stmt('del __tmp_tuple'))
            return self.make_single_statement(stmts)
        else:
            is_local = isinstance(node.targets[0], ast.Name)
            if is_local and self.is_creation(node.targets[0].id):
                var_name = node.targets[0].id
                # Create
                init = ast.Attribute(value=ast.Name(id='ti', ctx=ast.Load()),
                                     attr='expr_init',
                                     ctx=ast.Load())
                rhs = ast.Call(
                    func=init,
                    args=[node.value],
                    keywords=[],
                )
                self.create_variable(var_name)
                return ast.copy_location(
                    ast.Assign(targets=node.targets, value=rhs), node)
            else:
                # Assign
                node.targets[0].ctx = ast.Load()
                func = ast.Attribute(value=node.targets[0],
                                     attr='assign',
                                     ctx=ast.Load())
                call = ast.Call(func=func, args=[node.value], keywords=[])
                return ast.copy_location(ast.Expr(value=call), node)
Example #3
0
def _transform_statement(vars_already_initilized, statement):

    transformed_statement = None
    if isinstance(statement, ast.Assign):
        if isinstance(statement.value, ast.Call):
            args = []
            function_name = ast.Str(s=statement.value.func.id)
            args.append(function_name)
            for arg in statement.value.args:
                vars_already_initilized, transformed_arg = _transform_statement(
                    vars_already_initilized, arg)
                args.append(transformed_arg)
            args = ast.List(elts=args, ctx=ast.Load())
            transformed_statement = _trace_function_call(
                statement.targets[0], args)
        else:
            for target in statement.targets:
                #TODO:
                #Need soemthing to make sure multiple assignemnts
                #get traced to the right things. Ex. x, y = (1, 2)
                #if it's already defined - set it to new value.
                if target.id in vars_already_initilized:
                    vars_already_initilized, rhs = _transform_statement(
                        vars_already_initilized, statement.value)
                    transformed_statement = _trace_set(target, rhs)
                else:
                    #not defined yet, so trace it to a let.
                    vars_already_initilized, rhs = _transform_statement(
                        vars_already_initilized, statement.value)
                    transformed_statement = _trace_let(target, rhs)
                    vars_already_initilized[target.id] = 1

    elif isinstance(statement, ast.FunctionDef):
        args = [arg.arg for arg in statement.args.args]

        #insert statements into function body
        statement.body = _transform_statements(statement.body, {})

        #create function body trace and insert in begining of function body.
        function_trace = _trace_function_body(args)
        statement.body.insert(0, function_trace)

        #create assignment for each arg and insert after function body trace call
        arg_assignments = _trace_args(args)
        for arg in arg_assignments:
            statement.body.insert(1, arg)

        transformed_statement = statement

    elif isinstance(statement, ast.Return):
        vars_already_initilized, return_expr = _transform_statement(
            vars_already_initilized, statement.value)
        transformed_statement = _trace_break(return_expr)

    elif isinstance(statement, ast.If):
        #only supports single conditions for now
        if isinstance(statement.test, ast.NameConstant):
            vars_already_initilized, conditional = _transform_statement(
                vars_already_initilized, statement.test)
        else:
            vars_already_initilized, test_lhs = _transform_statement(
                vars_already_initilized, statement.test.left)
            op = _convert_operator_to_string(statement.test.ops[0])
            vars_already_initilized, test_rhs = _transform_statement(
                vars_already_initilized, statement.test.comparators[0])
            conditional = _exp_binop(op, test_lhs, test_rhs)

        name = 'test'
        while name in vars_already_initilized:
            name = name + '0'

        vars_already_initilized[name] = 1

        transformed_statement = [
            ast.Assign(targets=[ast.Name(id=name)], value=conditional)
        ]

        statement.body = _transform_statements(statement.body,
                                               vars_already_initilized, False)
        statement.body.insert(0, _trace_if_true(ast.Name(id=name)))

        if statement.orelse:
            statement.orelse = _transform_statements(statement.orelse,
                                                     vars_already_initilized,
                                                     False)
            statement.orelse.insert(0, _trace_if_false(ast.Name(id=name)))

        transformed_statement.append(statement)

    elif isinstance(statement, ast.BinOp):

        vars_already_initilized, lhs = _transform_statement(
            vars_already_initilized, statement.left)
        op = _convert_operator_to_string(statement.op)
        vars_already_initilized, rhs = _transform_statement(
            vars_already_initilized, statement.right)

        transformed_statement = _exp_binop(op, lhs, rhs)

    elif isinstance(statement, ast.UnaryOp):

        op = _convert_operator_to_string(statement.op)
        vars_already_initilized, rhs = _transform_statement(
            vars_already_initilized, statement.operand)

        transformed_statement = _exp_unary_op(op, rhs)

    elif isinstance(statement, ast.Name):
        transformed_statement = _exp_identifier(statement)

    elif isinstance(statement, ast.Num):
        transformed_statement = _exp_num(statement)

    elif isinstance(statement, ast.NameConstant) and statement.value is None:
        transformed_statement = _exp_none()

    elif isinstance(statement,
                    ast.NameConstant) and statement.value in [True, False]:
        transformed_statement = _exp_bool(statement)

    return vars_already_initilized, transformed_statement
def _make_for_loops_while(parent_node, names_in_use):
    """Converts for loops into while loops.
    Creates an index variable and a call to the len() function as a test
    condition for the while loop.
    All for loop iterators must be indexable.
    DOES NOT SUPPOT NONINDEXABLE ITERATORS.
    Parameters:
        parent_node: ast node
    Returns:
        parent node with updates"""

    # Get every index of for loop objects in the body of parent node.
    # Could be done cleaner with a numpy .where, but we'd have to import numpy
    # pretty much just for that.
    try:
        indxs_for_loops = []
        for indx in range(len(parent_node.body)):
            current = parent_node.body[indx]
            if isinstance(current, ast.For):
                indxs_for_loops.append(indx)
            if hasattr(current, "body"):
                is_module = isinstance(current, ast.Module)
                is_func_def = isinstance(current, ast.FunctionDef)
                if not is_func_def and not is_module:
                    current, names_in_use = _make_for_loops_while(
                        current, names_in_use)

    except AttributeError:
        # node has no body. No for loops in it.
        return parent_node, names_in_use

    num_lines_inserted = 0

    for for_loop_index in indxs_for_loops:
        for_loop_index = for_loop_index + num_lines_inserted
        for_loop = parent_node.body[for_loop_index]

        # Make loop incrementor variable.
        name_incrementor_variable = _new_name('loop_index', names_in_use)
        names_in_use[name_incrementor_variable] = 1

        # Make a call to built in len() function with the iterator
        # provided in the for loop.
        len_builtin_function = ast.Name(id='len', ctx=ast.Load)
        len_function_call = ast.Call(func=len_builtin_function,
                                     args=[for_loop.iter],
                                     keywords=[])

        # Test for while loop.
        left = ast.Name(id=name_incrementor_variable, ctx=ast.Load)
        compare_op = ast.Compare(left=left,
                                 ops=[ast.Lt()],
                                 comparators=[len_function_call])

        # Assign current value of loop to for loop target.
        index = ast.Index(ast.Name(id=name_incrementor_variable, ctx=ast.Load))
        value = ast.Subscript(for_loop.iter, index)
        target = [for_loop.target]
        assign_to_for_loop_target = ast.Assign(target, value)

        # Increment index variable.
        name = ast.Name(id=name_incrementor_variable)
        add_1_to_index_variable = ast.AugAssign(name, ast.Add(), ast.Num(1))

        # Construct while loop.
        while_loop = [assign_to_for_loop_target] + \
            for_loop.body + [add_1_to_index_variable]
        while_loop = ast.While(test=compare_op, body=while_loop, orelse=[])

        # Replace for with while loop.
        parent_node.body[for_loop_index] = while_loop

        # Insert loop incrementor variable before while loop and set to 0.
        inc_name = ast.Name(id=name_incrementor_variable, ctx=ast.Store)
        inc_0 = ast.Assign([inc_name], ast.Num(0))
        parent_node.body.insert(for_loop_index, inc_0)

        # Not the total lines inserted, only the lines inserted into the
        # parent's body. (so not the lines inside the loop)
        num_lines_inserted += 1

    return parent_node, names_in_use
Example #5
0
 def assign(self, expr: ast.expr) -> ast.Name:
     """Give *expr* a name."""
     name = self.variable()
     self.statements.append(ast.Assign([ast.Name(name, ast.Store())], expr))
     return ast.Name(name, ast.Load())
Example #6
0
 def do_with_case(self, ctx_id, ctx_node, node, orelse):
     if not isinstance(node.context_expr, ast.Name):
         return node
     if orelse is not None and node.context_expr.id == "_":
         raise SyntaxError(
             "any type identifier _ must be at the end of with-statement list"
         )
     # append the last match when it doesn't exist
     if orelse is None and node.context_expr.id != "_":
         orelse = [
             ast.Raise(type=ast.Call(func=ast.Name(id="SyntaxError",
                                                   ctx=ast.Load()),
                                     args=[ast.Str("match nothing!")],
                                     keywords=[],
                                     starargs=None,
                                     kwargs=None),
                       inst=None,
                       tback=None)
         ]
     body = []
     for stmt in node.body:
         if self.check_match_begin(stmt):
             body.append(self.visit_With(stmt))
         else:
             body.append(stmt)
     # convert to if-statement
     if node.optional_vars is not None:
         if isinstance(node.optional_vars, ast.Tuple):
             total = len(node.optional_vars.elts)
         elif isinstance(node.optional_vars, ast.Name):
             total = 1
         else:
             raise SyntaxError(
                 "variable capture list must be variable (for only one variable) or tuple (for many variables)"
             )
         assert isinstance(ctx_node, ast.Call)
         ctx_var = ctx_node.args[0].id
         import_stmt = ast.ImportFrom(module="pymatch",
                                      names=[ast.alias("unpack", None)],
                                      level=0)
         unpack_stmt = ast.Assign(targets=[node.optional_vars],
                                  value=ast.Call(
                                      func=ast.Name(id="unpack",
                                                    ctx=ast.Load()),
                                      args=[
                                          ast.Name(id=ctx_var,
                                                   ctx=ast.Load()),
                                          ast.Num(total)
                                      ],
                                      keywords=[],
                                      starargs=None,
                                      kwargs=None))
         body = [import_stmt, unpack_stmt] + body
     if node.context_expr.id == "_":
         return body
     else:
         return ast.If(test=ast.Call(
             func=ast.Name(id="issubclass", ctx=ast.Load()),
             args=[ast.Name(id=ctx_id, ctx=ast.Load()), node.context_expr],
             keywords=[],
             starargs=None,
             kwargs=None),
                       body=body,
                       orelse=deepcopy(orelse))
Example #7
0
def gen_store(name, value):
    return ast.Assign(targets=[
        ast.Subscript(value=ast_attr("self.vars"), slice=ast.Str(name))
    ],
                      value=value)
Example #8
0
 def assign(self, val, name=''):
     """
 Assign an element to the variable (variable = val)
 If the parameter name is provided, then assign to an attribute (variable.name = val)
 """
     return ast.Assign([self.store(name=name)], val)
Example #9
0
                code = line
            else:
                code += "\n" + line

        variables = []
        if code:
            parsed = ast.parse(code)
            for i, node in enumerate(parsed.body):
                # do this auto variable only for pure expressions
                # which is not a function call
                if isinstance(node, ast.Expr) and not isinstance(
                        node.value, ast.Call):
                    name = "res%s" % var_counter
                    var_counter += 1
                    new_node = (ast.Assign(
                        targets=[ast.Name(id=name, ctx=ast.Store())],
                        value=node.value))
                    parsed.body[i] = ast.fix_missing_locations(new_node)
                    variables.append(name)

            eval(compile(parsed, "<string>", "exec"))
            for var in variables:
                val = locals()[var]
                from pprint import pprint
                if "DataFrame" in type(val).__name__ or val is not None:
                    pprint(val)

            if mpl: flush_figures(request)
    except Py4JNetworkError:
        # since it's using local connection, network error
        # means java process is already dead
Example #10
0
def find_if(body, parent, args, reach):
    try:
        for field in body._fields:
            find_if(getattr(body, field), parent, args, reach)

    except AttributeError:
        if isinstance(body, list):
            ind = 0

            while ind in range(len(body)):
                line = body[ind]

                if isinstance(line, ast.Return):
                    reach = False

                elif isinstance(line, ast.If) or isinstance(line, ast.While):
                    node = branch_dist(line.test, args)
                    new_branch = branch(parent, line.lineno, reach)

                    # Assign branch distance to temporary variable
                    body.insert(
                        ind,
                        ast.Assign(targets=[ast.Name(id=args.temp_name)],
                                   value=node))

                    # Print branch_id, op_type, branch distance in order
                    body.insert(
                        ind + 1,
                        ast.Expr(value=ast.Call(
                            func=ast.Attribute(value=ast.Name(
                                id=args.file_name),
                                               attr='write'),
                            args=[
                                ast.Call(func=ast.Attribute(
                                    value=ast.Str(s='{} {}\n'), attr='format'),
                                         args=[
                                             ast.Num(n=new_branch.ind),
                                             ast.Name(id=args.temp_name)
                                         ],
                                         keywords=[],
                                         starargs=None,
                                         kwargs=None)
                            ],
                            keywords=[],
                            starargs=None,
                            kwargs=None)))

                    line.test = ast.Compare(left=ast.Name(id=args.temp_name),
                                            ops=[ast.LtE()],
                                            comparators=[ast.Num(n=0)])

                    if isinstance(line, ast.While):
                        line.body.append(body[ind])
                        line.body.append(body[ind + 1])

                    find_if(line.body, new_branch.ind, args, reach)
                    find_if(line.orelse, -new_branch.ind, args, reach)

                    ind += 2

                else:
                    find_if(line, parent, args, reach)

                ind += 1
Example #11
0
def init_assign(prop):
    return ast.Assign(
        targets=[ast.Attribute(value=ast.Name(id="self"), attr=prop)],
        value=ast.Name(id=prop))
def parse_annotation_mutable_layers(code, lineno, nas_mode):
    """Parse the string of mutable layers in annotation.
    Return a list of AST Expr nodes
    code: annotation string (excluding '@')
    nas_mode: the mode of NAS
    """
    module = ast.parse(code)
    assert type(module) is ast.Module, 'internal error #1'
    assert len(
        module.body
    ) == 1, 'Annotation mutable_layers contains more than one expression'
    assert type(module.body[0]) is ast.Expr, 'Annotation is not expression'
    call = module.body[0].value
    nodes = []
    mutable_id = 'mutable_block_' + str(lineno)
    mutable_layer_cnt = 0
    for arg in call.args:
        fields = {
            'layer_choice': False,
            'fixed_inputs': False,
            'optional_inputs': False,
            'optional_input_size': False,
            'layer_output': False
        }
        for k, value in zip(arg.keys, arg.values):
            if k.id == 'layer_choice':
                assert not fields[
                    'layer_choice'], 'Duplicated field: layer_choice'
                assert type(
                    value
                ) is ast.List, 'Value of layer_choice should be a list'
                call_funcs_keys = []
                call_funcs_values = []
                call_kwargs_values = []
                for call in value.elts:
                    assert type(
                        call
                    ) is ast.Call, 'Element in layer_choice should be function call'
                    call_name = astor.to_source(call).strip()
                    call_funcs_keys.append(ast_Str(s=call_name))
                    call_funcs_values.append(call.func)
                    assert not call.args, 'Number of args without keyword should be zero'
                    kw_args = []
                    kw_values = []
                    for kw in call.keywords:
                        kw_args.append(ast_Str(s=kw.arg))
                        kw_values.append(kw.value)
                    call_kwargs_values.append(
                        ast.Dict(keys=kw_args, values=kw_values))
                call_funcs = ast.Dict(keys=call_funcs_keys,
                                      values=call_funcs_values)
                call_kwargs = ast.Dict(keys=call_funcs_keys,
                                       values=call_kwargs_values)
                fields['layer_choice'] = True
            elif k.id == 'fixed_inputs':
                assert not fields[
                    'fixed_inputs'], 'Duplicated field: fixed_inputs'
                assert type(
                    value
                ) is ast.List, 'Value of fixed_inputs should be a list'
                fixed_inputs = value
                fields['fixed_inputs'] = True
            elif k.id == 'optional_inputs':
                assert not fields[
                    'optional_inputs'], 'Duplicated field: optional_inputs'
                assert type(
                    value
                ) is ast.List, 'Value of optional_inputs should be a list'
                var_names = [
                    ast_Str(s=astor.to_source(var).strip())
                    for var in value.elts
                ]
                optional_inputs = ast.Dict(keys=var_names, values=value.elts)
                fields['optional_inputs'] = True
            elif k.id == 'optional_input_size':
                assert not fields[
                    'optional_input_size'], 'Duplicated field: optional_input_size'
                assert type(value) is ast_Num or type(value) is ast.List, \
                    'Value of optional_input_size should be a number or list'
                optional_input_size = value
                fields['optional_input_size'] = True
            elif k.id == 'layer_output':
                assert not fields[
                    'layer_output'], 'Duplicated field: layer_output'
                assert type(
                    value
                ) is ast.Name, 'Value of layer_output should be ast.Name type'
                layer_output = value
                fields['layer_output'] = True
            else:
                raise AssertionError('Unexpected field in mutable layer')
        # make call for this mutable layer
        assert fields['layer_choice'], 'layer_choice must exist'
        assert fields['layer_output'], 'layer_output must exist'
        mutable_layer_id = 'mutable_layer_' + str(mutable_layer_cnt)
        mutable_layer_cnt += 1
        target_call_attr = ast.Attribute(value=ast.Name(id='nni',
                                                        ctx=ast.Load()),
                                         attr='mutable_layer',
                                         ctx=ast.Load())
        target_call_args = [
            ast_Str(s=mutable_id),
            ast_Str(s=mutable_layer_id), call_funcs, call_kwargs
        ]
        if fields['fixed_inputs']:
            target_call_args.append(fixed_inputs)
        else:
            target_call_args.append(ast.List(elts=[]))
        if fields['optional_inputs']:
            target_call_args.append(optional_inputs)
            assert fields[
                'optional_input_size'], 'optional_input_size must exist when optional_inputs exists'
            target_call_args.append(optional_input_size)
        else:
            target_call_args.append(ast.Dict(keys=[], values=[]))
            target_call_args.append(ast_Num(n=0))
        target_call_args.append(ast_Str(s=nas_mode))
        if nas_mode in ['enas_mode', 'oneshot_mode', 'darts_mode']:
            target_call_args.append(ast.Name(id='tensorflow'))
        target_call = ast.Call(func=target_call_attr,
                               args=target_call_args,
                               keywords=[])
        node = ast.Assign(targets=[layer_output], value=target_call)
        nodes.append(node)
    return nodes
Example #13
0
def execute_code_block(compiler, block, example_globals,
                       script_vars, gallery_conf):
    """Executes the code block of the example file"""
    if example_globals is None:  # testing shortcut
        example_globals = script_vars['fake_main'].__dict__
    blabel, bcontent, lineno = block
    # If example is not suitable to run, skip executing its blocks
    if not script_vars['execute_script'] or blabel == 'text':
        return ''

    cwd = os.getcwd()
    # Redirect output to stdout and
    orig_stdout, orig_stderr = sys.stdout, sys.stderr
    src_file = script_vars['src_file']

    # First cd in the original example dir, so that any file
    # created by the example get created in this directory

    captured_std = StringIO()
    os.chdir(os.path.dirname(src_file))

    sys_path = copy.deepcopy(sys.path)
    sys.path.append(os.getcwd())
    sys.stdout = sys.stderr = LoggingTee(captured_std, logger, src_file)

    try:
        dont_inherit = 1
        if sys.version_info >= (3, 8):
            ast_Module = partial(ast.Module, type_ignores=[])
        else:
            ast_Module = ast.Module
        code_ast = ast_Module([bcontent])
        code_ast = compile(bcontent, src_file, 'exec',
                           ast.PyCF_ONLY_AST | compiler.flags, dont_inherit)
        ast.increment_lineno(code_ast, lineno - 1)
        # capture output if last line is expression
        is_last_expr = False
        if len(code_ast.body) and isinstance(code_ast.body[-1], ast.Expr):
            is_last_expr = True
            last_val = code_ast.body.pop().value
            # exec body minus last expression
            _, mem_body = _memory_usage(
                _exec_once(
                    compiler(code_ast, src_file, 'exec'),
                    script_vars['fake_main']),
                gallery_conf)
            # exec last expression, made into assignment
            body = [ast.Assign(
                targets=[ast.Name(id='___', ctx=ast.Store())], value=last_val)]
            last_val_ast = ast_Module(body=body)
            ast.fix_missing_locations(last_val_ast)
            _, mem_last = _memory_usage(
                _exec_once(
                    compiler(last_val_ast, src_file, 'exec'),
                    script_vars['fake_main']),
                gallery_conf)
            # capture the assigned variable
            ___ = example_globals['___']
            mem_max = max(mem_body, mem_last)
        else:
            _, mem_max = _memory_usage(
                _exec_once(
                    compiler(code_ast, src_file, 'exec'),
                    script_vars['fake_main']),
                gallery_conf)
        script_vars['memory_delta'].append(mem_max)
    except Exception:
        sys.stdout.flush()
        sys.stderr.flush()
        sys.stdout, sys.stderr = orig_stdout, orig_stderr
        except_rst = handle_exception(sys.exc_info(), src_file, script_vars,
                                      gallery_conf)
        code_output = u"\n{0}\n\n\n\n".format(except_rst)
        # still call this even though we won't use the images so that
        # figures are closed
        save_figures(block, script_vars, gallery_conf)
    else:
        sys.stdout.flush()
        sys.stderr.flush()
        sys.stdout, orig_stderr = orig_stdout, orig_stderr
        sys.path = sys_path
        os.chdir(cwd)

        last_repr = None
        repr_meth = None
        if is_last_expr:
            if gallery_conf['ignore_repr_types']:
                ignore_repr = re.search(
                    gallery_conf['ignore_repr_types'], str(type(___))
                )
            else:
                ignore_repr = False
            if gallery_conf['capture_repr'] != () and not ignore_repr:
                for meth in gallery_conf['capture_repr']:
                    try:
                        last_repr = getattr(___, meth)()
                        # for case when last statement is print()
                        if last_repr is None or last_repr == 'None':
                            repr_meth = None
                        else:
                            repr_meth = meth
                    except Exception:
                        pass
                    else:
                        if isinstance(last_repr, str):
                            break
        captured_std = captured_std.getvalue().expandtabs()
        # normal string output
        if repr_meth in ['__repr__', '__str__'] and last_repr:
            captured_std = u"{0}\n{1}".format(captured_std, last_repr)
        if captured_std and not captured_std.isspace():
            captured_std = CODE_OUTPUT.format(indent(captured_std, u' ' * 4))
        else:
            captured_std = ''
        images_rst = save_figures(block, script_vars, gallery_conf)
        # give html output its own header
        if repr_meth == '_repr_html_':
            captured_html = html_header.format(indent(last_repr, u' ' * 8))
        else:
            captured_html = ''
        code_output = u"\n{0}\n\n{1}\n{2}\n\n".format(
            images_rst, captured_std, captured_html)

    finally:
        os.chdir(cwd)
        sys.path = sys_path
        sys.stdout, sys.stderr = orig_stdout, orig_stderr

    return code_output
Example #14
0
    def visit_With(self, node):
        node = self.generic_visit(node)

        # Build equivalent code with try catch finally.
        # PEP-0343 provides the equivalent code for us.

        statements = []

        # mgr = node.expr
        mgr_id = self.id_factory("mgr")
        s = mk_assign(mgr_id, node.context_expr)
        statements.append(s)

        # exit = type(msg).__exit__
        exit_id = self.id_factory("exit")
        s = mk_assign(exit_id,
                      mk_attr(mk_call('type', [mk_name(mgr_id)]), "__exit__"))
        statements.append(s)

        # value = type(msg).__enter__(mgr)
        value_id = self.id_factory("value")
        s = mk_assign(
            value_id,
            mk_call_expr(
                mk_attr(mk_call('type', [mk_name(mgr_id)]), "__enter__"),
                [mk_name(mgr_id)]))
        statements.append(s)

        # exc = True
        exc_id = self.id_factory("exc")
        s = mk_assign(exc_id, mk_name("True"))
        statements.append(s)

        # try:
        tryfinally_body = []
        tryfinally_finalbody = []
        s = ast.TryFinally(body=tryfinally_body,
                           finalbody=tryfinally_finalbody)
        statements.append(s)

        #     try:
        tryexcept_body = []
        tryexcept_except = []
        expt_handler = ast.ExceptHandler(type=None,
                                         name=None,
                                         body=tryexcept_except)
        s = ast.TryExcept(body=tryexcept_body,
                          handlers=[expt_handler],
                          orelse=[])
        tryfinally_body.append(s)

        #         node.optional_vars = value
        if node.optional_vars:
            s = ast.Assign(targets=[node.optional_vars],
                           value=mk_name(value_id))
            tryexcept_body.append(s)

        #         body
        tryexcept_body.extend(node.body)

        #     except:

        #         exc = False
        s = mk_assign(exc_id, mk_name("False"))
        tryexcept_except.append(s)

        #         sys.exc_info()
        sys_exc_info = mk_call_expr(mk_attr(mk_name('sys'), "exc_info"), [])
        #         exit(mgr, *sys.exc_info())
        exit_call = mk_call(exit_id, [mk_name(mgr_id)], vararg=sys_exc_info)
        #         not exit(mgr, *sys.exc_info())
        test = ast.UnaryOp(op=ast.Not(), operand=exit_call)

        #        if not exit(mgr, *sys.exc_info()):
        #            raise
        s = ast.If(test=test,
                   body=[ast.Raise(type=None, inst=None, tback=None)],
                   orelse=[])
        tryexcept_except.append(s)

        # finally:

        #     if exc:
        #       exit(mgr, None, None, None)
        exit_call = mk_call(exit_id, [
            mk_name(mgr_id),
            mk_name("None"),
            mk_name("None"),
            mk_name("None")
        ])
        s = ast.If(test=mk_name(exc_id),
                   body=[ast.Expr(value=exit_call)],
                   orelse=[])
        tryfinally_finalbody.append(s)

        return statements
Example #15
0
    def visit_For(self, node):
        # CASE: for x in xs: ...

        # TODO: this is c/p from while, maybe try to abstract the common
        # parts.

        if node.orelse:
            raise MyiaSyntaxError("For loops may not have an else: clause.")

        assert self.dest
        wsym = self.global_gen(self.dest, WTEST)
        wbsym = self.global_gen(self.dest, WLOOP)

        augm_body = node.body + [ast.Assign()]

        # We visit the body once to get the free variables
        testp = self.sub_parser(dry=True)
        testp.return_error = 'Cannot return in while loops.'
        testp.body_wrapper(node.body)
        in_vars = testp.free_variables
        in_vars.update(testp.local_assignments)  # type: ignore
        in_vars = list(in_vars)  # type: ignore
        out_vars = list(testp.local_assignments)

        # We visit once more, this time adding the free vars as parameters
        p = self.sub_parser(dest=wbsym)
        in_iter = p.new_variable('~it~')
        in_list = p.new_variable('~li~')
        loopvar = p.new_variable(node.target)
        in_syms = [in_iter, in_list] + [p.new_variable(v) for v in in_vars]

        # Have to execute this before the body in order to get the right
        # symbols, otherwise they will be shadowed. If I recall correctly,
        # that's why we need to revisit instead of just using testp.
        initial_values = [p.vtrack[v] for v in out_vars]
        test = Apply(inst_builtin.less, in_iter,
                     Apply(inst_builtin.len, in_list))
        body = p.body_wrapper(node.body)

        loop_args = in_syms
        loop_body = body(
            Apply(wsym, Apply(inst_builtin.add, in_iter, Value(1)), in_list,
                  *[p.vtrack[v] for v in in_vars]))
        loop_ass = Apply(inst_builtin.index, in_list, in_iter)
        loop_body = Let(((loopvar, loop_ass), ), loop_body)
        with About(loop_body.find_location(), 'parse'):
            loop_fn = self.reg_lambda(wbsym, loop_args, loop_body)
        outer_body = Apply(
            Apply(
                inst_builtin.switch,
                test,
                Closure(loop_fn, in_syms),
                # Closure on identity is a trick to create a thunk
                # that returns a pre-defined value (we need this
                # parameter to be a function with no arguments in
                # order to match the signature of the other branch).
                Closure(inst_builtin.identity, (Tuple(initial_values), ))))

        self.reg_lambda(wsym, in_syms, outer_body)

        # We immediately apply our shiny new function to start
        # the loop rolling.
        listvar = self.gen('~li~')
        val = Apply(wsym, Value(0), listvar,
                    *[self.visit_variable(v) for v in in_vars])

        # We get back the variables the while loop sets.
        listass = _Assign(listvar, self.visit(node.iter))
        return Begin([listass, self.multi_assign(out_vars, val)])
Example #16
0
    def _bind_arguments(self, f_ast, call_expr, new_stmts):
        args_def = f_ast.args

        # Scope a variable name as unique to the function, and update any references
        # to it in the function
        def unique_and_rename(name):
            unique_name = f'{name}{SEP}{f_ast.name}'
            renamer = Rename(name, unique_name)
            for stmt in f_ast.body:
                renamer.visit(stmt)
            return unique_name

        args = call_expr.args[:]

        # Rename all variables declared in the function that aren't arguments
        assgn_finder = FindAssignments()
        assgn_finder.visit(f_ast)
        arg_names = set([arg.arg for arg in args_def.args])
        for name in assgn_finder.names:
            if name not in arg_names:
                unique_and_rename(name)

        # If function is called with f(*args)
        if len(call_expr.args) > 0 and \
           isinstance(call_expr.args[-1], ast.Starred):
            star_arg = call_expr.args.pop().value

            # Get the length of the star_arg runtime list
            star_arg_obj = eval(a2s(star_arg), self.globls, self.globls)

            # Generate an indexing expression for each element of the list
            call_star_args = [
                ast.Subscript(value=star_arg,
                              slice=ast.Index(value=ast.Num(i)))
                for i in range(len(star_arg_obj))
            ]
        else:
            star_arg = None

        # If function is called with f(**kwargs)
        star_kwarg = [arg for arg in call_expr.keywords if arg.arg is None]
        star_kwarg = star_kwarg[0].value if len(star_kwarg) > 0 else None
        if star_kwarg is not None:
            star_kwarg_dict = eval(a2s(star_kwarg), self.globls, self.globls)
            call_star_kwarg = {
                key: ast.Subscript(value=star_kwarg,
                                   slice=ast.Index(value=ast.Str(key)))
                for key in star_kwarg_dict.keys()
            }

        # Function's anonymous arguments, e.g. f(1, 2) becomes [1, 2]
        call_anon_args = call_expr.args[:]

        # Function's keyword arguments, e.g. f(x=1, y=2) becomes {'x': 1, 'y': 2}
        call_kwargs = {
            arg.arg: arg.value
            for arg in call_expr.keywords if arg.arg is not None
        }

        # Match up defaults with variable names.
        #
        # Python convention is that if function has N arguments and K < N defaults, then
        # the defaults correspond to arguments N - K .. N.
        nodefault = len(args_def.args) - len(args_def.defaults)
        anon_defaults = {
            arg.arg: default
            for arg, default in zip(args_def.args[nodefault:],
                                    args_def.defaults)
        }

        # All keyword-only arguments must have defaults.
        #
        # kwonlyargs occur if a function definition has args AFTER a *args, e.g.
        # the var "y" in `def foo(x, *args, y=1)`
        kw_defaults = {
            arg.arg: default
            for arg, default in zip(args_def.kwonlyargs, args_def.kw_defaults)
        }

        # For each non-keyword-only argument, match it up with the corresponding
        # syntax from the call expression
        for arg in args_def.args:
            k = arg.arg

            # First, match with anonymous arguments
            if len(call_anon_args) > 0:
                v = call_anon_args.pop(0)

            # Then use *args if it exists
            elif star_arg is not None and len(call_star_args) > 0:
                v = call_star_args.pop(0)

            # Then use keyword arguments
            elif k in call_kwargs:
                v = call_kwargs.pop(k)

            # Then use **kwargs if it exists
            elif star_kwarg is not None and k in call_star_kwarg:
                v = call_star_kwarg.pop(k)

            # Otherwise use the default value
            else:
                v = anon_defaults.pop(k)

            # Add a binding from function argument to call argument
            uniq_k = unique_and_rename(k)
            stmt = ast.Assign(targets=[make_name(uniq_k)], value=v)
            new_stmts.append(stmt)

        # Perform equivalent procedure as above, but for keyword-only arguments
        for arg in args_def.kwonlyargs:
            k = arg.arg

            if k in call_kwargs:
                v = call_kwargs.pop(k)
            elif star_kwarg is not None and k in call_star_kwarg:
                v = call_star_kwarg.pop(k)
            else:
                v = kw_defaults.pop(k)

            uniq_k = unique_and_rename(k)
            stmt = ast.Assign(targets=[make_name(uniq_k)], value=v)
            new_stmts.append(stmt)

        # If function definition uses *args, then assign it to the remaining anonymous
        # arguments from the call_expr
        if args_def.vararg is not None:
            k = unique_and_rename(args_def.vararg.arg)
            v = call_anon_args[:]
            if star_arg is not None:
                v += call_star_args
            new_stmts.append(
                ast.Assign(targets=[make_name(k)], value=ast.List(elts=v)))

        # Similarly for **kwargs in the function definition
        if args_def.kwarg is not None:
            k = unique_and_rename(args_def.kwarg.arg)
            items = call_kwargs.items()
            if star_kwarg is not None:
                items = itertools.chain(items, call_star_kwarg.items())
            kwkeys, kwvalues = unzip(items)
            new_stmts.append(
                ast.Assign(targets=[make_name(k)],
                           value=ast.Dict([ast.Str(s) for s in kwkeys],
                                          kwvalues)))
Example #17
0
def new_assignment(name, value):
    name = ast.Name(id=name)
    value = new_constant(value)

    return ast.Assign(targets=[name], value=value)
Example #18
0
 def assgn(value):
     return ast.Assign(targets=[make_name(ret_var)], value=value)
Example #19
0
    def build(self) -> typing.Optional[ast.ClassDef]:
        base_class: typing.Union[ast.Attribute, ast.Name]

        # Create the base class
        if not self.resource.base or self.resource.base.name == "object":
            base_class = ast.Attribute(value=ast.Name(id="marshmallow"),
                                       attr="Schema")
        else:
            if self.resource.base.name in FIELD_TYPES:
                return None
            base_class = ast.Name(id=self.resource.base.name + "Schema")

            if self.resource.package_name != self.resource.base.package_name:
                self.generator.import_resource(
                    self.resource.package_name,
                    self.resource.base.package_name,
                    self.resource.base.name + "Schema",
                )

        # Define the base class
        class_node = ast.ClassDef(
            name=self.resource.name + "Schema",
            bases=[base_class],
            keywords=[],
            decorator_list=[],
            body=[],
        )

        doc_string = (
            f"Marshmallow schema for :class:`commercetools.types.{self.resource.name}`."
        )
        class_node.body.append(
            ast.Expr(value=ast.Str(s=doc_string, kind=None)))

        # Add the field definitions
        for prop in self.resource.properties:
            node = self._create_schema_property(prop)
            if node:
                class_node.body.append(node)

        # Add the Meta class
        class_node.body.append(
            ast.ClassDef(
                name="Meta",
                bases=[],
                keywords=[],
                body=[
                    ast.Assign(
                        targets=[ast.Name(id="unknown")],
                        value=ast.Name(id="marshmallow.EXCLUDE"),
                    )
                ],
                decorator_list=[],
            ))

        # Create the post_load() method
        post_load_node = self._create_marshmallow_hook("post_load")
        if self.contains_regex_field:
            post_load_node.body.append(
                self._create_regex_call("_regex", "postprocess"))
        post_load_node.body.append(
            ast.Return(value=ast.Call(
                func=ast.Name(id=f"types.{self.resource.name}"),
                args=[],
                keywords=[ast.keyword(arg=None, value=ast.Name(id="data"))],
            )))
        class_node.body.append(post_load_node)

        # Create the pre_load() method
        if self.contains_regex_field:
            node = self._create_marshmallow_hook("pre_load")
            node.body.append(self._create_regex_call("_regex", "preprocess"))
            node.body.append(ast.Return(value=ast.Name(id="data")))
            class_node.body.append(node)

            node = self._create_marshmallow_hook("pre_dump")
            node.body.append(self._create_regex_call("_regex", "preprocess"))
            node.body.append(ast.Return(value=ast.Name(id="data")))
            class_node.body.append(node)

            node = self._create_marshmallow_hook("post_dump")
            node.body.append(self._create_regex_call("_regex", "postprocess"))
            node.body.append(ast.Return(value=ast.Name(id="data")))
            class_node.body.append(node)

        d_field = self.resource.get_discriminator_field()
        if d_field:
            post_load_node.body.insert(
                0,
                ast.Delete(targets=[
                    ast.Subscript(
                        value=ast.Name(id="data"),
                        slice=ast.Index(value=ast.Str(s=d_field.attribute_name,
                                                      kind=None)),
                    )
                ]),
            )
        return class_node
Example #20
0
def compile_to_logpdf(graph: GraphicalModel, namespace: Dict) -> Artifact:
    """Compile a graphical model into a log-probability density function.

    Example
    -------

    Let us consider a simple linear regression example:

        >>> @mcx.model
        ... def linear_regression(x, lmbda=1.):
        ...     scale <~ Exponential(lmbda)
        ...     coeff <~ Normal(0, 1)
        ...     y = np.dot(x, coeff)
        ...     predictions <~ Normal(y, scale)
        ...     return predictions

    MCX parses this definition into a graphical model. This function compiles
    the graph in a python function that returns the values of the
    log-probability density function:

        >>> def linear_regression_logpdf(x, scale, coeffs, predictions, lmbda=1.):
        ...     logpdf = 0
        ...     logpdf += Exponential(lmbda).logpdf(scale)
        ...     logpdf += Normal(0, 1).logpdf(coeff)
        ...     y = np.dot(x, coeff)
        ...     logpdf += Normal(y, coeff).logpdf(predictions)
        ...     return logpdf

    The logpdf is then partially applied on the dataset {(x, prediction)} for
    inference.

    Of course it would impact the core


    Parameters
    ----------
    model:
        A probabilistic graphical model.
    namespace:
        The names contained in the model definition's global scope.

    Returns
    -------
    logpdf:
        A function that returns the log probability of a model at one point the
        parameter space.
    var_names:
        The name of the random variables arguments of the logpdf function, in
        the order in which they appear.
    logpdf_source:
        A string containing the source code of the logpdf. Useful for inspection
        by the user.
    """
    fn_name = graph.name + "_logpdf"

    #
    # ARGUMENTS
    #

    kwarg_nodes = [
        node[1]["content"] for node in graph.nodes(data=True)
        if isinstance(node[1]["content"], Argument)
        and node[1]["content"].default_value is not None
    ]

    # The (keyword) arguments of the model definition and random variables
    # are passed as arguments to the logpdf.
    model_kwargs = [kwarg.to_logpdf_iadd() for kwarg in kwarg_nodes]
    model_arguments = [
        node[1]["content"].to_logpdf_iadd() for node in graph.nodes(data=True)
        if isinstance(node[1]["content"], Argument)
        and node[1]["content"].default_value is None
    ]
    random_variables = [
        ast.arg(arg=node[1]["content"].name, annotation=None)
        for node in graph.nodes(data=True)
        if isinstance(node[1]["content"], RandVar)
    ]

    logpdf_arguments = random_variables + model_arguments + model_kwargs

    # We propagate the kwargs' default values
    defaults = [kwarg.default_value for kwarg in kwarg_nodes]

    #
    # FUNCTION BODY
    # To write the function body, we traverse the graph in topological order
    # while incrementing the value of the logpdf.
    #

    body: List[Union[ast.Assign, ast.Constant, ast.Num, ast.Return]] = []
    body.append(
        ast.Assign(
            targets=[ast.Name(id="logpdf", ctx=ast.Store())],
            value=ast.Constant(value=0),
        ))
    ordered_nodes = [
        graph.nodes[node]["content"] for node in nx.topological_sort(graph)
        if not isinstance(graph.nodes[node]["content"], Argument)
    ]
    for node in ordered_nodes:
        body.append(node.to_logpdf_iadd())

    returned = ast.Return(value=ast.Name(id="logpdf", ctx=ast.Load()))
    body.append(returned)

    logpdf_ast = ast.Module(
        body=[
            ast.FunctionDef(
                name=fn_name,
                args=ast.arguments(
                    args=logpdf_arguments,
                    vararg=None,
                    kwarg=None,
                    posonlyargs=[],
                    kwonlyargs=[],
                    defaults=defaults,
                    kw_defaults=[],
                ),
                body=body,
                decorator_list=[],
            )
        ],
        type_ignores=[],
    )
    logpdf_ast = ast.fix_missing_locations(logpdf_ast)
    logpdf = compile(logpdf_ast, filename="<ast>", mode="exec")
    exec(logpdf, namespace)
    fn = namespace[fn_name]

    argument_names = [arg.arg for arg in logpdf_arguments]

    return Artifact(fn, argument_names, fn_name,
                    astor.code_gen.to_source(logpdf_ast))
Example #21
0
    def gen_unpack_wrapper(self, node, target, ctx='store'):
        """Helper function to protect tuple unpacks.

        node: used to copy the locations for the new nodes.
        target: is the tuple which must be protected.
        ctx: Defines the context of the returned temporary node.

        It returns a tuple with two element.

        Element 1: Is a temporary name node which must be used to
                   replace the target.
                   The context (store, param) is defined
                   by the 'ctx' parameter..

        Element 2: Is a try .. finally where the body performs the
                   protected tuple unpack of the temporary variable
                   into the original target.
        """

        # Generate a tmp name to replace the tuple with.
        tmp_name = self.gen_tmp_name()

        # Generates an expressions which protects the unpack.
        # converter looks like 'wrapper(tmp_name)'.
        # 'wrapper' takes care to protect sequence unpacking with _getiter_.
        converter = self.protect_unpack_sequence(
            target, ast.Name(tmp_name, ast.Load()))

        # Assign the expression to the original names.
        # Cleanup the temporary variable.
        # Generates:
        # try:
        #     # converter is 'wrapper(tmp_name)'
        #     arg = converter
        # finally:
        #     del tmp_arg
        try_body = [ast.Assign(targets=[target], value=converter)]
        finalbody = [self.gen_del_stmt(tmp_name)]

        if IS_PY2:
            cleanup = ast.TryFinally(body=try_body, finalbody=finalbody)
        else:
            cleanup = ast.Try(body=try_body,
                              finalbody=finalbody,
                              handlers=[],
                              orelse=[])

        if ctx == 'store':
            ctx = ast.Store()
        elif ctx == 'param':
            ctx = ast.Param()
        else:  # pragma: no cover
            # Only store and param are defined ctx.
            raise NotImplementedError(
                'Unsupported context type: "{name}".'.format(name=type(ctx)), )

        # This node is used to catch the tuple in a tmp variable.
        tmp_target = ast.Name(tmp_name, ctx)

        copy_locations(tmp_target, node)
        copy_locations(cleanup, node)

        return (tmp_target, cleanup)
Example #22
0
def find_pyparams_assignments_nodes(
    node: ast.Module,
    assigment_op_name: str = PyParam.__name__
) -> List[Union[ast.AnnAssign, ast.Assign]]:
    """Scans the AST Module i.e. an AST representation of the python file and
    return all AnnAssign nodes.
    Note that AnnAssign appears when pyparam is defined with typing annotation e.g.

    variable_a: int = PyParam(value=512) # is a AnnAssign node
    variable_a = PyParam(value=512) # is a Assign node

    Args:
        node: a root node of the AST tree, this node should be a AST representation
            of the python file
        assigment_op_name: a name of the assignment function e.g. PyParam.__name__

    Returns:
        nodes: a list of AnnAssign or Assign found in the Module

    """

    supported_nodes = [ast.AnnAssign, ast.Assign]

    pyparams_nodes = []
    for element in node.body:
        if element.__dict__.get("body", None) is not None:
            pyparams_nodes += find_pyparams_assignments_nodes(
                element, assigment_op_name=assigment_op_name)

        # dealing with function definition arguments
        if isinstance(element, ast.FunctionDef):

            defaults = element.args.defaults
            num_defaults = len(defaults)
            args = element.args.args[-num_defaults:]
            arg_nodes = []
            for arg, default in zip(args, defaults):
                arg_nodes.append(
                    ast.Assign(targets=[ast.Name(arg.arg, None)],
                               value=default))

            body_element = ast.Module(arg_nodes)
            pyparams_nodes += find_pyparams_assignments_nodes(
                body_element, assigment_op_name=assigment_op_name)

        # must be AnnAssign
        if any([isinstance(element, sn) for sn in supported_nodes]):
            # value must be Call
            if isinstance(element.value, ast.Call):
                # func must be named
                if isinstance(element.value.func, ast.Name):
                    func_id = element.value.func.id
                    # the name of the function must be e.g. "PyParam"
                    if func_id == assigment_op_name:
                        pyparams_nodes += [element]
                    else:
                        # loop over the arguments of some Func(**kwargs) declaration
                        # note only named keywords are supported
                        kwarg_nodes = []
                        for keyword in element.value.keywords:
                            kwarg_nodes.append(
                                ast.Assign(
                                    targets=[ast.Name(keyword.arg, None)],
                                    value=keyword.value))

                        body_element = ast.Module(kwarg_nodes)
                        pyparams_nodes += find_pyparams_assignments_nodes(
                            body_element, assigment_op_name=assigment_op_name)

    return pyparams_nodes
Example #23
0
def t_add_dead_code(the_ast, uid=1, all_sites=False):
    """
	Statement of the form if False:\n <HOLE> = 1 is added to the target program. 
	all_sites=False: The insertion location (either beginning, or end) is chosen at random.
	all_sites=True: The statement is inserted at all possible locations.
	"""
    def insert_holes(the_ast, hole_id, site_map):

        if 'body' not in the_ast.__dict__ or len(the_ast.body) == 0:
            return False, the_ast, hole_id, site_map
        new_body = []
        for node in the_ast.body:
            site_map["if false : @R_{}@ = 1".format(hole_id)] = [
                "", 'transforms.AddDeadCode'
            ]
            new_body += [
                ast.If(test=ast.Name(id="False", ctx=ast.Load()),
                       body=[
                           ast.Assign(targets=[
                               ast.Name(id="REPLACEME" + str(hole_id),
                                        ctx=ast.Store())
                           ],
                                      value=ast.Num(n=1))
                       ],
                       orelse=[]), node
            ]
            hole_id += 1
        site_map["if false : @R_{}@ = 1".format(hole_id)] = [
            "", 'transforms.AddDeadCode'
        ]
        new_body.append(
            ast.If(test=ast.Name(id="False", ctx=ast.Load()),
                   body=[
                       ast.Assign(targets=[
                           ast.Name(id="REPLACEME" + str(hole_id),
                                    ctx=ast.Store())
                       ],
                                  value=ast.Num(n=1))
                   ],
                   orelse=[]))
        hole_id += 1
        the_ast.body = new_body

        for i in range(len(the_ast.body[1:])):
            if i % 2 == 0:
                node = the_ast.body[i + 1]
                _, _, hole_id, site_map = insert_holes(node, hole_id, site_map)
        return True, the_ast, hole_id, site_map

    if len(the_ast.body) == 0 or not isinstance(the_ast.body[0],
                                                ast.FunctionDef):
        return False, the_ast, uid - 1, {}

    if all_sites:
        changed, the_ast_body, hole_id, site_map = insert_holes(
            the_ast.body[0], uid, {})
        the_ast.body[0] = the_ast_body
        return changed, the_ast, hole_id - 1, site_map

    else:
        site_map = {}
        if bool(random.getrandbits(1)):
            the_ast.body[0].body.insert(
                0,
                ast.If(test=ast.Name(id="False", ctx=ast.Load()),
                       body=[
                           ast.Assign(targets=[
                               ast.Name(id="REPLACEME" + str(uid),
                                        ctx=ast.Store())
                           ],
                                      value=ast.Num(n=1))
                       ],
                       orelse=[]))
            site_map['@R_{}@'.format(uid)] = ["", 'transforms.AddDeadCode']
        else:
            the_ast.body[0].body.append(
                ast.If(test=ast.Name(id="False", ctx=ast.Load()),
                       body=[
                           ast.Assign(targets=[
                               ast.Name(id="REPLACEME" + str(uid),
                                        ctx=ast.Store())
                           ],
                                      value=ast.Num(n=1))
                       ],
                       orelse=[]))
            site_map['@R_{}@'.format(uid)] = ["", 'transforms.AddDeadCode']

        return True, the_ast, uid, site_map
Example #24
0
    def _compile_directive_call_assets(self, el, options):
        """ This special 't-call' tag can be used in order to aggregate/minify javascript and css assets"""
        if len(el):
            raise SyntaxError("t-call-assets cannot contain children nodes")

        # nodes = self._get_asset(xmlid, options, css=css, js=js, debug=values.get('debug'), async=async, values=values)
        #
        # for index, (tagName, t_attrs, content) in enumerate(nodes):
        #     if index:
        #         append('\n        ')
        #     append('<')
        #     append(tagName)
        #
        #     self._post_processing_att(tagName, t_attrs, options)
        #     for name, value in t_attrs.items():
        #         if value or isinstance(value, string_types)):
        #             append(u' ')
        #             append(name)
        #             append(u'="')
        #             append(escape(pycompat.to_text((value)))
        #             append(u'"')
        #
        #     if not content and tagName in self._void_elements:
        #         append('/>')
        #     else:
        #         append('>')
        #         if content:
        #           append(content)
        #         append('</')
        #         append(tagName)
        #         append('>')
        #
        space = el.getprevious() is not None and el.getprevious(
        ).tail or el.getparent().text
        sep = u'\n' + space.rsplit('\n').pop()
        return [
            ast.Assign(
                targets=[ast.Name(id='nodes', ctx=ast.Store())],
                value=ast.Call(
                    func=ast.Attribute(value=ast.Name(id='self',
                                                      ctx=ast.Load()),
                                       attr='_get_asset_nodes',
                                       ctx=ast.Load()),
                    args=[
                        ast.Str(el.get('t-call-assets')),
                        ast.Name(id='options', ctx=ast.Load()),
                    ],
                    keywords=[
                        ast.keyword('css',
                                    self._get_attr_bool(el.get('t-css',
                                                               True))),
                        ast.keyword('js',
                                    self._get_attr_bool(el.get('t-js', True))),
                        ast.keyword(
                            'debug',
                            ast.Call(func=ast.Attribute(value=ast.Name(
                                id='values', ctx=ast.Load()),
                                                        attr='get',
                                                        ctx=ast.Load()),
                                     args=[ast.Str('debug')],
                                     keywords=[],
                                     starargs=None,
                                     kwargs=None)),
                        ast.keyword(
                            'async',
                            self._get_attr_bool(el.get('async', False))),
                        ast.keyword('values',
                                    ast.Name(id='values', ctx=ast.Load())),
                    ],
                    starargs=None,
                    kwargs=None)),
            ast.For(
                target=ast.Tuple(elts=[
                    ast.Name(id='index', ctx=ast.Store()),
                    ast.Tuple(elts=[
                        ast.Name(id='tagName', ctx=ast.Store()),
                        ast.Name(id='t_attrs', ctx=ast.Store()),
                        ast.Name(id='content', ctx=ast.Store())
                    ],
                              ctx=ast.Store())
                ],
                                 ctx=ast.Store()),
                iter=ast.Call(func=ast.Name(id='enumerate', ctx=ast.Load()),
                              args=[ast.Name(id='nodes', ctx=ast.Load())],
                              keywords=[],
                              starargs=None,
                              kwargs=None),
                body=[
                    ast.If(test=ast.Name(id='index', ctx=ast.Load()),
                           body=[self._append(ast.Str(sep))],
                           orelse=[]),
                    self._append(ast.Str(u'<')),
                    self._append(ast.Name(id='tagName', ctx=ast.Load())),
                ] + self._append_attributes() + [
                    ast.If(test=ast.BoolOp(
                        op=ast.And(),
                        values=[
                            ast.UnaryOp(ast.Not(),
                                        ast.Name(id='content', ctx=ast.Load()),
                                        lineno=0,
                                        col_offset=0),
                            ast.Compare(
                                left=ast.Name(id='tagName', ctx=ast.Load()),
                                ops=[ast.In()],
                                comparators=[
                                    ast.Attribute(value=ast.Name(
                                        id='self', ctx=ast.Load()),
                                                  attr='_void_elements',
                                                  ctx=ast.Load())
                                ]),
                        ]),
                           body=[self._append(ast.Str(u'/>'))],
                           orelse=[
                               self._append(ast.Str(u'>')),
                               ast.If(test=ast.Name(id='content',
                                                    ctx=ast.Load()),
                                      body=[
                                          self._append(
                                              ast.Name(id='content',
                                                       ctx=ast.Load()))
                                      ],
                                      orelse=[]),
                               self._append(ast.Str(u'</')),
                               self._append(
                                   ast.Name(id='tagName', ctx=ast.Load())),
                               self._append(ast.Str(u'>')),
                           ])
                ],
                orelse=[])
        ]
Example #25
0
    def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]:
        """Return the AST statements to replace the ast.Assert instance.

        This rewrites the test of an assertion to provide
        intermediate values and replace it with an if statement which
        raises an assertion error with a detailed explanation in case
        the expression is false.
        """
        if isinstance(assert_.test, ast.Tuple) and len(assert_.test.elts) >= 1:
            from _pytest.warning_types import PytestAssertRewriteWarning
            import warnings

            # TODO: This assert should not be needed.
            assert self.module_path is not None
            warnings.warn_explicit(
                PytestAssertRewriteWarning(
                    "assertion is always true, perhaps remove parentheses?"
                ),
                category=None,
                filename=os.fspath(self.module_path),
                lineno=assert_.lineno,
            )

        self.statements = []  # type: List[ast.stmt]
        self.variables = []  # type: List[str]
        self.variable_counter = itertools.count()

        if self.enable_assertion_pass_hook:
            self.format_variables = []  # type: List[str]

        self.stack = []  # type: List[Dict[str, ast.expr]]
        self.expl_stmts = []  # type: List[ast.stmt]
        self.push_format_context()
        # Rewrite assert into a bunch of statements.
        top_condition, explanation = self.visit(assert_.test)

        negation = ast.UnaryOp(ast.Not(), top_condition)

        if self.enable_assertion_pass_hook:  # Experimental pytest_assertion_pass hook
            msg = self.pop_format_context(ast.Str(explanation))

            # Failed
            if assert_.msg:
                assertmsg = self.helper("_format_assertmsg", assert_.msg)
                gluestr = "\n>assert "
            else:
                assertmsg = ast.Str("")
                gluestr = "assert "
            err_explanation = ast.BinOp(ast.Str(gluestr), ast.Add(), msg)
            err_msg = ast.BinOp(assertmsg, ast.Add(), err_explanation)
            err_name = ast.Name("AssertionError", ast.Load())
            fmt = self.helper("_format_explanation", err_msg)
            exc = ast.Call(err_name, [fmt], [])
            raise_ = ast.Raise(exc, None)
            statements_fail = []
            statements_fail.extend(self.expl_stmts)
            statements_fail.append(raise_)

            # Passed
            fmt_pass = self.helper("_format_explanation", msg)
            orig = self._assert_expr_to_lineno()[assert_.lineno]
            hook_call_pass = ast.Expr(
                self.helper(
                    "_call_assertion_pass",
                    ast.Num(assert_.lineno),
                    ast.Str(orig),
                    fmt_pass,
                )
            )
            # If any hooks implement assert_pass hook
            hook_impl_test = ast.If(
                self.helper("_check_if_assertion_pass_impl"),
                self.expl_stmts + [hook_call_pass],
                [],
            )
            statements_pass = [hook_impl_test]

            # Test for assertion condition
            main_test = ast.If(negation, statements_fail, statements_pass)
            self.statements.append(main_test)
            if self.format_variables:
                variables = [
                    ast.Name(name, ast.Store()) for name in self.format_variables
                ]
                clear_format = ast.Assign(variables, ast.NameConstant(None))
                self.statements.append(clear_format)

        else:  # Original assertion rewriting
            # Create failure message.
            body = self.expl_stmts
            self.statements.append(ast.If(negation, body, []))
            if assert_.msg:
                assertmsg = self.helper("_format_assertmsg", assert_.msg)
                explanation = "\n>assert " + explanation
            else:
                assertmsg = ast.Str("")
                explanation = "assert " + explanation
            template = ast.BinOp(assertmsg, ast.Add(), ast.Str(explanation))
            msg = self.pop_format_context(template)
            fmt = self.helper("_format_explanation", msg)
            err_name = ast.Name("AssertionError", ast.Load())
            exc = ast.Call(err_name, [fmt], [])
            raise_ = ast.Raise(exc, None)

            body.append(raise_)

        # Clear temporary variables by setting them to None.
        if self.variables:
            variables = [ast.Name(name, ast.Store()) for name in self.variables]
            clear = ast.Assign(variables, ast.NameConstant(None))
            self.statements.append(clear)
        # Fix line numbers.
        for stmt in self.statements:
            set_location(stmt, assert_.lineno, assert_.col_offset)
        return self.statements
Example #26
0
def eval_annassign(env, node):
    if node.value is None:
        return
    val_ = ast.Assign(targets=[node.target], value=node.value)
    return eval_assign(env, val_)
Example #27
0
    def visit_Assign(self, node):
        """Look for 'LOG = logging.getLogger'

        This handles the simple case:
          name = [logging_module].getLogger(...)

          - or -

          name = [i18n_name](...)

        And some much more comple ones:
          name = [i18n_name](...) % X

          - or -

          self.name = [i18n_name](...) % X

        """
        attr_node_types = (ast.Name, ast.Attribute)

        if (len(node.targets) != 1
                or not isinstance(node.targets[0], attr_node_types)):
            # say no to: "x, y = ..."
            return super(CheckForLoggingIssues, self).generic_visit(node)

        target_name = self._find_name(node.targets[0])

        if (isinstance(node.value, ast.BinOp) and
                isinstance(node.value.op, ast.Mod)):
            if (isinstance(node.value.left, ast.Call) and
                    isinstance(node.value.left.func, ast.Name) and
                    node.value.left.func.id in self.i18n_names):
                # NOTE(dstanek): this is done to match cases like:
                # `msg = _('something %s') % x`
                node = ast.Assign(value=node.value.left)

        if not isinstance(node.value, ast.Call):
            # node.value must be a call to getLogger
            self.assignments.pop(target_name, None)
            return super(CheckForLoggingIssues, self).generic_visit(node)

        # is this a call to an i18n function?
        if (isinstance(node.value.func, ast.Name)
                and node.value.func.id in self.i18n_names):
            self.assignments[target_name] = node.value.func.id
            return super(CheckForLoggingIssues, self).generic_visit(node)

        if (not isinstance(node.value.func, ast.Attribute)
                or not isinstance(node.value.func.value, attr_node_types)):
            # function must be an attribute on an object like
            # logging.getLogger
            return super(CheckForLoggingIssues, self).generic_visit(node)

        object_name = self._find_name(node.value.func.value)
        func_name = node.value.func.attr

        if (object_name in self.logger_module_names
                and func_name == 'getLogger'):
            self.logger_names.append(target_name)

        return super(CheckForLoggingIssues, self).generic_visit(node)
Example #28
0
    def visit_Assign(self, node):
        assert (len(node.targets) == 1)
        self.generic_visit(node)

        decorated = isinstance(node.value, ast.Call) and isinstance(
            node.value.func, ast.Attribute) and isinstance(node.value.func.value, ast.Name) \
                    and node.value.func.value.id == 'ti'

        is_static_assign = False

        if decorated:
            attr = node.value.func
            if attr.attr == 'static':
                is_static_assign = True
            else:
                pass  # eg. x = ti.cast(xx) will reach here, but they're not decorators, so no raising errors here

        if is_static_assign:
            return node

        if isinstance(node.targets[0], ast.Tuple):
            targets = node.targets[0].elts

            # Create
            stmts = []

            holder = self.parse_stmt('__tmp_tuple = ti.expr_init_list(0, '
                                     f'{len(targets)})')
            holder.value.args[0] = node.value

            stmts.append(holder)

            def tuple_indexed(i):
                indexing = self.parse_stmt('__tmp_tuple[0]')
                indexing.value.slice.value = self.parse_expr("{}".format(i))
                return indexing.value

            for i, target in enumerate(targets):
                is_local = isinstance(target, ast.Name)
                if is_local and self.is_creation(target.id):
                    var_name = target.id
                    target.ctx = ast.Store()
                    # Create
                    init = ast.Attribute(value=ast.Name(id='ti',
                                                        ctx=ast.Load()),
                                         attr='expr_init',
                                         ctx=ast.Load())
                    rhs = ast.Call(
                        func=init,
                        args=[tuple_indexed(i)],
                        keywords=[],
                    )
                    self.create_variable(var_name)
                    stmts.append(ast.Assign(targets=[target], value=rhs))
                else:
                    # Assign
                    target.ctx = ast.Load()
                    func = ast.Attribute(value=target,
                                         attr='assign',
                                         ctx=ast.Load())
                    call = ast.Call(func=func,
                                    args=[tuple_indexed(i)],
                                    keywords=[])
                    stmts.append(ast.Expr(value=call))

            for stmt in stmts:
                ast.copy_location(stmt, node)
            stmts.append(self.parse_stmt('del __tmp_tuple'))
            return self.make_single_statement(stmts)
        else:
            is_local = isinstance(node.targets[0], ast.Name)
            if is_local and self.is_creation(node.targets[0].id):
                var_name = node.targets[0].id
                # Create
                init = ast.Attribute(value=ast.Name(id='ti', ctx=ast.Load()),
                                     attr='expr_init',
                                     ctx=ast.Load())
                rhs = ast.Call(
                    func=init,
                    args=[node.value],
                    keywords=[],
                )
                self.create_variable(var_name)
                return ast.copy_location(
                    ast.Assign(targets=node.targets, value=rhs), node)
            else:
                # Assign
                node.targets[0].ctx = ast.Load()
                func = ast.Attribute(value=node.targets[0],
                                     attr='assign',
                                     ctx=ast.Load())
                call = ast.Call(func=func, args=[node.value], keywords=[])
                return ast.copy_location(ast.Expr(value=call), node)
Example #29
0
def makeRegressor(model: Xgboost,
                  useSigmoids: bool = False,
                  useNumPy: bool = False) -> ast.Module:
    """Converts a regression XGBoost decision tree model into a python module of if-else trees"""
    #code:typing.List[ast.stmt]=[]
    code = []
    numpyModuleName = "numpy"
    if useSigmoids:
        code.extend(
            generateFermiSplitFunction(
                sigmoidSplitFuncName,
                tanhModuleName=(numpyModuleName if useNumPy else "math")))

    if useNumPy:
        code.append(
            ast.ImportFrom(module=numpyModuleName,
                           names=[ast.alias(name=numpySumName, asname=None)],
                           level=0))

    features = int(model.param.num_feature)
    trees = int(model.gbm_.param.num_trees)
    groups = int(model.gbm_.param.num_output_group)
    if groups == 0:
        groups = 1

    treesInAGroup = trees // groups

    groupFunctions = []
    groupFunctionsNames = []
    elts = []
    for j in range(groups):
        group = []
        for i in range(treesInAGroup):
            t = model.gbm_.trees[j * treesInAGroup + i]
            name = "g" + str(j) + "_t" + str(i)
            code.extend(treesToFuncs(t, name, useSigmoids))
            group.append(ast.Name(id=name))
        elts.append(ast.Tuple(elts=group))
        groupFuncName = "g" + str(j)
        groupFunctionsNames.append(ast.Name(groupFuncName))
        groupFunctions.append(
            makeGroup(groupFuncName, model.param.base_score,
                      useNumPy=useNumPy))

    code.extend(groupFunctions)
    code.append(
        ast.Assign(targets=[treesAccumulator],
                   value=ast.Dict(keys=groupFunctionsNames, values=elts)))

    code.append(
        wrapWithFunc([
            ast.Expr(value=astStr(s=genModelSummary(model))),
            ast.Assert(test=ast.Compare(left=ast.Call(
                func=lenFunc, args=[vector], keywords=[]),
                                        ops=[ast.Eq()],
                                        comparators=[astNum(n=features)]),
                       msg=ast.BinOp(left=ast.BinOp(
                           left=astStr(s="This model requires exactly " +
                                       str(features) + " feature, but "),
                           op=ast.Add(),
                           right=ast.Call(func=strFunc,
                                          args=[
                                              ast.Call(func=lenFunc,
                                                       args=[vector],
                                                       keywords=[])
                                          ],
                                          keywords=[])),
                                     op=ast.Add(),
                                     right=astStr(s=" were given"))),
            ast.Assign(
                targets=[res],
                value=ast.ListComp(
                    elt=ast.Call(func=groupTemp, args=[vector], keywords=[]),
                    generators=[
                        ast.comprehension(
                            target=groupTemp, iter=treesAccumulator, ifs=[])
                    ])),
            ast.Return(value=res)
        ], regressorFunctionName))

    return ast.Module(body=code)
Example #30
0
def from_phpast(node):
    if node is None:
        return py.Pass(**pos(node))

    if isinstance(node, str):
        return py.Str(node, **pos(node))

    if isinstance(node, (int, float)):
        return py.Num(node, **pos(node))

    if isinstance(node, php.Array):
        if node.nodes:
            if node.nodes[0].key is not None:
                keys = []
                values = []
                for elem in node.nodes:
                    keys.append(from_phpast(elem.key))
                    values.append(from_phpast(elem.value))
                return py.Dict(keys, values, **pos(node))
            else:
                return py.List([from_phpast(x.value) for x in node.nodes],
                               py.Load(**pos(node)), **pos(node))
        else:
            return py.List([], py.Load(**pos(node)), **pos(node))

    if isinstance(node, php.InlineHTML):
        args = [py.Str(node.data, **pos(node))]
        return py.Call(
            py.Name('inline_html', py.Load(**pos(node)), **pos(node)), args,
            [], None, None, **pos(node))

    if isinstance(node, php.Echo):
        return py.Call(py.Name('echo', py.Load(**pos(node)), **pos(node)),
                       list(map(from_phpast, node.nodes)), [], None, None,
                       **pos(node))

    if isinstance(node, php.Print):
        return py.Print(None, [from_phpast(node.node)], True, **pos(node))

    if isinstance(node, php.Exit):
        args = []
        if node.expr is not None:
            args.append(from_phpast(node.expr))
        return py.Raise(
            py.Call(py.Name('Exit', py.Load(**pos(node)), **pos(node)), args,
                    [], None, None, **pos(node)), None, None, **pos(node))

    if isinstance(node, php.Return):
        if node.node is None:
            return py.Return(None, **pos(node))
        else:
            return py.Return(from_phpast(node.node), **pos(node))

    if isinstance(node, php.Break):
        assert node.node is None, 'level on break not supported'
        return py.Break(**pos(node))

    if isinstance(node, php.Continue):
        assert node.node is None, 'level on continue not supported'
        return py.Continue(**pos(node))

    if isinstance(node, php.Silence):
        return from_phpast(node.expr)

    if isinstance(node, php.Block):
        return from_phpast(php.If(1, node, [], None, lineno=node.lineno))

    if isinstance(node, php.Unset):
        return py.Delete(list(map(from_phpast, node.nodes)), **pos(node))

    if isinstance(node, php.IsSet) and len(node.nodes) == 1:
        if isinstance(node.nodes[0], php.ArrayOffset):
            return py.Compare(from_phpast(node.nodes[0].expr),
                              [py.In(**pos(node))],
                              [from_phpast(node.nodes[0].node)], **pos(node))
        if isinstance(node.nodes[0], php.ObjectProperty):
            return py.Call(
                py.Name('hasattr', py.Load(**pos(node)), **pos(node)), [
                    from_phpast(node.nodes[0].node),
                    from_phpast(node.nodes[0].name)
                ], [], None, None, **pos(node))
        if isinstance(node.nodes[0], php.Variable):
            return py.Compare(py.Str(
                node.nodes[0].name[1:], **pos(node)), [py.In(**pos(node))], [
                    py.Call(py.Name('vars', py.Load(**pos(node)), **pos(node)),
                            [], [], None, None, **pos(node))
                ], **pos(node))
        return py.Compare(from_phpast(node.nodes[0]), [py.IsNot(**pos(node))],
                          [py.Name('None', py.Load(**pos(node)), **pos(node))],
                          **pos(node))

    if isinstance(node, php.Empty):
        return from_phpast(
            php.UnaryOp('!',
                        php.BinaryOp('&&',
                                     php.IsSet([node.expr],
                                               lineno=node.lineno),
                                     node.expr,
                                     lineno=node.lineno),
                        lineno=node.lineno))

    if isinstance(node, php.Assignment):
        if (isinstance(node.node, php.ArrayOffset) and node.node.expr is None):
            return py.Call(
                py.Attribute(from_phpast(node.node.node), 'append',
                             py.Load(**pos(node)), **pos(node)),
                [from_phpast(node.expr)], [], None, None, **pos(node))
        if (isinstance(node.node, php.ObjectProperty)
                and isinstance(node.node.name, php.BinaryOp)):
            return to_stmt(
                py.Call(py.Name('setattr', py.Load(**pos(node)), **pos(node)),
                        [
                            from_phpast(node.node.node),
                            from_phpast(node.node.name),
                            from_phpast(node.expr)
                        ], [], None, None, **pos(node)))
        return py.Assign([store(from_phpast(node.node))],
                         from_phpast(node.expr), **pos(node))

    if isinstance(node, php.ListAssignment):
        return py.Assign([
            py.Tuple(list(map(store, list(map(from_phpast, node.nodes)))),
                     py.Store(**pos(node)), **pos(node))
        ], from_phpast(node.expr), **pos(node))

    if isinstance(node, php.AssignOp):
        return from_phpast(
            php.Assignment(node.left,
                           php.BinaryOp(node.op[:-1],
                                        node.left,
                                        node.right,
                                        lineno=node.lineno),
                           False,
                           lineno=node.lineno))

    if isinstance(node, (php.PreIncDecOp, php.PostIncDecOp)):
        return from_phpast(
            php.Assignment(node.expr,
                           php.BinaryOp(node.op[0],
                                        node.expr,
                                        1,
                                        lineno=node.lineno),
                           False,
                           lineno=node.lineno))

    if isinstance(node, php.ArrayOffset):
        return py.Subscript(from_phpast(node.node),
                            py.Index(from_phpast(node.expr), **pos(node)),
                            py.Load(**pos(node)), **pos(node))

    if isinstance(node, php.ObjectProperty):
        if isinstance(node.name, (php.Variable, php.BinaryOp)):
            return py.Call(
                py.Name('getattr', py.Load(**pos(node)), **pos(node)),
                [from_phpast(node.node),
                 from_phpast(node.name)], [], None, None, **pos(node))
        return py.Attribute(from_phpast(node.node), node.name,
                            py.Load(**pos(node)), **pos(node))

    if isinstance(node, php.Constant):
        name = node.name
        if name.lower() == 'true': name = 'True'
        if name.lower() == 'false': name = 'False'
        if name.lower() == 'null': name = 'None'
        return py.Name(name, py.Load(**pos(node)), **pos(node))

    if isinstance(node, php.Variable):
        name = node.name[1:]
        if name == 'this': name = 'self'
        return py.Name(name, py.Load(**pos(node)), **pos(node))

    if isinstance(node, php.Global):
        return py.Global([var.name[1:] for var in node.nodes], **pos(node))

    if isinstance(node, php.Include):
        once = py.Name('True' if node.once else 'False', py.Load(**pos(node)),
                       **pos(node))
        return py.Call(py.Name('include', py.Load(**pos(node)), **pos(node)),
                       [from_phpast(node.expr), once], [], None, None,
                       **pos(node))

    if isinstance(node, php.Require):
        once = py.Name('True' if node.once else 'False', py.Load(**pos(node)),
                       **pos(node))
        return py.Call(py.Name('require', py.Load(**pos(node)), **pos(node)),
                       [from_phpast(node.expr), once], [], None, None,
                       **pos(node))

    if isinstance(node, php.UnaryOp):
        op = unary_ops.get(node.op)
        assert op is not None, "unknown unary operator: '%s'" % node.op
        op = op(**pos(node))
        return py.UnaryOp(op, from_phpast(node.expr), **pos(node))

    if isinstance(node, php.BinaryOp):
        if node.op == '.':
            pattern, pieces = build_format(node.left, node.right)
            if pieces:
                return py.BinOp(
                    py.Str(pattern, **pos(node)), py.Mod(**pos(node)),
                    py.Tuple(list(map(from_phpast, pieces)),
                             py.Load(**pos(node)), **pos(node)), **pos(node))
            else:
                return py.Str(pattern % (), **pos(node))
        if node.op in bool_ops:
            op = bool_ops[node.op](**pos(node))
            return py.BoolOp(op,
                             [from_phpast(node.left),
                              from_phpast(node.right)], **pos(node))
        if node.op in cmp_ops:
            op = cmp_ops[node.op](**pos(node))
            return py.Compare(from_phpast(node.left), [op],
                              [from_phpast(node.right)], **pos(node))
        op = binary_ops.get(node.op)
        if node.op == 'instanceof':
            return py.Call(
                func=py.Name(id='isinstance', ctx=py.Load(**pos(node))),
                args=[from_phpast(node.left),
                      from_phpast(node.right)],
                keywords=[],
                starargs=None,
                kwargs=None)
        assert op is not None, "unknown binary operator: '%s'" % node.op
        op = op(**pos(node))
        return py.BinOp(from_phpast(node.left), op, from_phpast(node.right),
                        **pos(node))

    if isinstance(node, php.TernaryOp):
        return py.IfExp(from_phpast(node.expr), from_phpast(node.iftrue),
                        from_phpast(node.iffalse), **pos(node))

    if isinstance(node, php.Cast):
        return py.Call(
            py.Name(casts.get(node.type, node.type), py.Load(**pos(node)),
                    **pos(node)), [from_phpast(node.expr)], [], None, None,
            **pos(node))

    if isinstance(node, php.If):
        orelse = []
        if node.else_:
            for else_ in map(from_phpast, deblock(node.else_.node)):
                orelse.append(to_stmt(else_))
        for elseif in reversed(node.elseifs):
            orelse = [
                py.If(
                    from_phpast(elseif.expr),
                    list(
                        map(to_stmt,
                            list(map(from_phpast, deblock(elseif.node))))),
                    orelse, **pos(node))
            ]
        return py.If(
            from_phpast(node.expr),
            list(map(to_stmt, list(map(from_phpast, deblock(node.node))))),
            orelse, **pos(node))

    if isinstance(node, php.For):
        assert node.test is None or len(node.test) == 1, \
            'only a single test is supported in for-loops'
        return from_phpast(
            php.Block((node.start or []) + [
                php.While(node.test[0] if node.test else 1,
                          php.Block(deblock(node.node) + (node.count or []),
                                    lineno=node.lineno),
                          lineno=node.lineno)
            ],
                      lineno=node.lineno))

    if isinstance(node, php.Foreach):
        if node.keyvar is None:
            target = py.Name(node.valvar.name[1:], py.Store(**pos(node)),
                             **pos(node))
        else:
            target = py.Tuple([
                py.Name(node.keyvar.name[1:], py.Store(**pos(node))),
                py.Name(node.valvar.name[1:], py.Store(**pos(node)))
            ], py.Store(**pos(node)), **pos(node))
        return py.For(
            target, from_phpast(node.expr),
            list(map(to_stmt, list(map(from_phpast, deblock(node.node))))), [],
            **pos(node))

    if isinstance(node, php.While):
        return py.While(
            from_phpast(node.expr),
            list(map(to_stmt, list(map(from_phpast, deblock(node.node))))), [],
            **pos(node))

    if isinstance(node, php.DoWhile):
        condition = php.If(php.UnaryOp('!', node.expr, lineno=node.lineno),
                           php.Break(None, lineno=node.lineno), [],
                           None,
                           lineno=node.lineno)
        return from_phpast(
            php.While(1,
                      php.Block(deblock(node.node) + [condition],
                                lineno=node.lineno),
                      lineno=node.lineno))

    if isinstance(node, php.Try):
        return py.TryExcept(
            list(map(to_stmt, list(map(from_phpast, node.nodes)))), [
                py.ExceptHandler(
                    py.Name(catch.class_, py.Load(**pos(node)), **pos(node)),
                    store(from_phpast(catch.var)),
                    list(map(to_stmt, list(map(from_phpast, catch.nodes)))),
                    **pos(node)) for catch in node.catches
            ], [], **pos(node))

    if isinstance(node, php.Throw):
        return py.Raise(from_phpast(node.node), None, None, **pos(node))

    if isinstance(node, php.Function):
        args = []
        defaults = []
        for param in node.params:
            args.append(
                py.Name(param.name[1:], py.Param(**pos(node)), **pos(node)))
            if param.default is not None:
                defaults.append(from_phpast(param.default))
        body = list(map(to_stmt, list(map(from_phpast, node.nodes))))
        if not body: body = [py.Pass(**pos(node))]
        return py.FunctionDef(node.name,
                              py.arguments(args, None, None, defaults), body,
                              [], **pos(node))

    if isinstance(node, php.Method):
        args = []
        defaults = []
        decorator_list = []
        if 'static' in node.modifiers:
            decorator_list.append(
                py.Name('classmethod', py.Load(**pos(node)), **pos(node)))
            args.append(py.Name('cls', py.Param(**pos(node)), **pos(node)))
        else:
            args.append(py.Name('self', py.Param(**pos(node)), **pos(node)))
        for param in node.params:
            args.append(
                py.Name(param.name[1:], py.Param(**pos(node)), **pos(node)))
            if param.default is not None:
                defaults.append(from_phpast(param.default))
        body = list(map(to_stmt, list(map(from_phpast, node.nodes))))
        if not body: body = [py.Pass(**pos(node))]
        return py.FunctionDef(node.name,
                              py.arguments(args, None, None, defaults), body,
                              decorator_list, **pos(node))

    if isinstance(node, php.Class):
        name = node.name
        bases = []
        extends = node.extends or 'object'
        bases.append(py.Name(extends, py.Load(**pos(node)), **pos(node)))
        body = list(map(to_stmt, list(map(from_phpast, node.nodes))))
        for stmt in body:
            if (isinstance(stmt, py.FunctionDef)
                    and stmt.name in (name, '__construct')):
                stmt.name = '__init__'
        if not body: body = [py.Pass(**pos(node))]
        return py.ClassDef(name, bases, body, [], **pos(node))

    if isinstance(node, (php.ClassConstants, php.ClassVariables)):
        assert len(node.nodes) == 1, \
            'only one class-level assignment supported per line'
        if isinstance(node.nodes[0], php.ClassConstant):
            name = php.Constant(node.nodes[0].name, lineno=node.lineno)
        else:
            name = php.Variable(node.nodes[0].name, lineno=node.lineno)
        initial = node.nodes[0].initial
        if initial is None:
            initial = php.Constant('None', lineno=node.lineno)
        return py.Assign([store(from_phpast(name))], from_phpast(initial),
                         **pos(node))

    if isinstance(node, (php.FunctionCall, php.New)):
        if isinstance(node.name, str):
            name = py.Name(node.name, py.Load(**pos(node)), **pos(node))
        else:
            name = py.Subscript(
                py.Call(py.Name('vars', py.Load(**pos(node)), **pos(node)), [],
                        [], None, None, **pos(node)),
                py.Index(from_phpast(node.name), **pos(node)),
                py.Load(**pos(node)), **pos(node))
        args, kwargs = build_args(node.params)
        return py.Call(name, args, kwargs, None, None, **pos(node))

    if isinstance(node, php.MethodCall):
        args, kwargs = build_args(node.params)
        return py.Call(
            py.Attribute(from_phpast(node.node), node.name,
                         py.Load(**pos(node)), **pos(node)), args, kwargs,
            None, None, **pos(node))

    if isinstance(node, php.StaticMethodCall):
        class_ = node.class_
        if class_ == 'self': class_ = 'cls'
        args, kwargs = build_args(node.params)
        return py.Call(
            py.Attribute(py.Name(class_, py.Load(**pos(node)),
                                 **pos(node)), node.name, py.Load(**pos(node)),
                         **pos(node)), args, kwargs, None, None, **pos(node))

    if isinstance(node, php.StaticProperty):
        class_ = node.node
        name = node.name
        if isinstance(name, php.Variable):
            name = name.name[1:]
        return py.Attribute(py.Name(class_, py.Load(**pos(node)), **pos(node)),
                            name, py.Load(**pos(node)), **pos(node))

    return py.Call(py.Name('XXX', py.Load(**pos(node)),
                           **pos(node)), [py.Str(str(node), **pos(node))], [],
                   None, None, **pos(node))