예제 #1
0
 def visit_Module(self, node):
     new_node = self.generic_visit(node)
     line_numbers = set()
     new_body = []
     try_body = new_node.body
     if try_body:
         while try_body and self._is_module_header(try_body[0]):
             # noinspection PyUnresolvedReferences
             new_body.append(try_body.pop(0))
         find_line_numbers(new_node, line_numbers)
     if line_numbers:
         first_line_number = min(line_numbers)
         last_line_number = max(line_numbers)
         handler_body = [self._create_context_call('exception'),
                         Raise()]
         handler = ExceptHandler(body=handler_body,
                                 lineno=last_line_number)
         new_body.append(Try(body=try_body,
                             handlers=[handler],
                             orelse=[],
                             finalbody=[]))
         new_node.body = new_body
         self._set_statement_line_numbers(try_body, first_line_number)
         self._set_statement_line_numbers(handler_body, last_line_number)
     return new_node
예제 #2
0
파일: ast.py 프로젝트: barry-scott/xonsh
    def insert_with_block_check(self, node):
        """Modifies a with statement node in-place to add an initial check
        for whether or not the block should be executed. If the block is
        not executed it will raise a XonshBlockError containing the required
        information.
        """
        nwith = self._nwith  # the nesting level of the current with-statement
        lineno = get_lineno(node)
        col = get_col(node, 0)
        # Add or discover target names
        targets = set()
        i = 0  # index of unassigned items

        def make_next_target():
            nonlocal i
            targ = '__xonsh_with_target_{}_{}__'.format(nwith, i)
            n = Name(id=targ, ctx=Store(), lineno=lineno, col_offset=col)
            targets.add(targ)
            i += 1
            return n
        for item in node.items:
            if item.optional_vars is None:
                if has_elts(item.context_expr):
                    targs = [make_next_target() for _ in item.context_expr.elts]
                    optvars = Tuple(elts=targs, ctx=Store(), lineno=lineno,
                                    col_offset=col)
                else:
                    optvars = make_next_target()
                item.optional_vars = optvars
            else:
                targets.update(gather_names(item.optional_vars))
        # Ok, now that targets have been found / created, make the actual check
        # to see if we are in a non-executing block. This is equivalent to
        # writing the following condition:
        #
        #     if getattr(targ0, '__xonsh_block__', False) or \
        #        getattr(targ1, '__xonsh_block__', False) or ...:
        #         raise XonshBlockError(lines, globals(), locals())
        tests = [_getblockattr(t, lineno, col) for t in sorted(targets)]
        if len(tests) == 1:
            test = tests[0]
        else:
            test = BoolOp(op=Or(), values=tests, lineno=lineno, col_offset=col)
        ldx, udx = self._find_with_block_line_idx(node)
        lines = [Str(s=s, lineno=lineno, col_offset=col)
                 for s in self.lines[ldx:udx]]
        check = If(test=test, body=[
            Raise(exc=xonsh_call('XonshBlockError',
                                 args=[List(elts=lines, ctx=Load(),
                                            lineno=lineno, col_offset=col),
                                       xonsh_call('globals', args=[],
                                                  lineno=lineno, col=col),
                                       xonsh_call('locals', args=[],
                                                  lineno=lineno, col=col)],
                                 lineno=lineno, col=col),
                  cause=None, lineno=lineno, col_offset=col)],
                orelse=[], lineno=lineno, col_offset=col)
        node.body.insert(0, check)
예제 #3
0
    def visit_FunctionDef(self, node):
        """ Instrument a function definition by creating a new report builder
        for this stack frame and putting it in a local variable. The local
        variable has the same name as the global variable so all calls can
        use the same CONTEXT_NAME symbol, but it means that I had to use this:
        x = globals()['x'].start_frame()
        Kind of ugly, but I think it was worth it to handle recursive calls.
        """
        if node.name == '__repr__':
            return node

        new_node = self.generic_visit(node)

        line_numbers = set()
        self._find_line_numbers(new_node, line_numbers)
        first_line_number = min(line_numbers)
        last_line_number = max(line_numbers)
        args = [Num(n=first_line_number),
                Num(n=last_line_number)]
        try_body = new_node.body
        globals_call = Call(func=Name(id='globals', ctx=Load()),
                            args=[],
                            keywords=[],
                            starargs=None,
                            kwargs=None)
        global_context = Subscript(value=globals_call,
                                   slice=Index(value=Str(s=CONTEXT_NAME)),
                                   ctx=Load())
        start_frame_call = Call(func=Attribute(value=global_context,
                                               attr='start_frame',
                                               ctx=Load()),
                                args=args,
                                keywords=[],
                                starargs=None,
                                kwargs=None)
        context_assign = Assign(targets=[Name(id=CONTEXT_NAME, ctx=Store())],
                                value=start_frame_call)
        new_node.body = [context_assign]

        # trace function parameter values
        for target in new_node.args.args:
            if isinstance(target, Name) and target.id == 'self':
                continue
            if arg and isinstance(target, arg) and target.arg == 'self':
                continue
            new_node.body.append(self._trace_assignment(target, node.lineno))

        handler_body = [self._create_context_call('exception'),
                        Raise()]
        new_node.body.append(
            TryExcept(body=try_body,
                      handlers=[ExceptHandler(body=handler_body)],
                      orelse=[],
                      finalbody=[]))
        self._set_statement_line_numbers(try_body, first_line_number)
        self._set_statement_line_numbers(handler_body, last_line_number)
        return new_node
예제 #4
0
    def visit_FunctionDef(self, node):
        """ Instrument a function definition by creating a new report builder
        for this stack frame and putting it in a local variable. The local
        variable has the same name as the global variable so all calls can
        use the same CONTEXT_NAME symbol, but it means that I had to use this:
        x = globals()['x'].start_frame()
        Kind of ugly, but I think it was worth it to handle recursive calls.
        """
        new_node = self.generic_visit(node)

        line_numbers = set()
        find_line_numbers(new_node, line_numbers)
        first_line_number = min(line_numbers)
        last_line_number = max(line_numbers)
        args = [Num(n=first_line_number), Num(n=last_line_number)]
        start_frame_keywords = []
        for decorator in new_node.decorator_list:
            if getattr(decorator, 'id', None) == 'traced':
                start_frame_keywords.append(
                    keyword(arg='is_decorated',
                            value=Name(id='True', ctx=Load())))
        try_body = new_node.body
        globals_call = Call(func=Name(id='globals', ctx=Load()),
                            args=[],
                            keywords=[],
                            starargs=None,
                            kwargs=None)
        global_context = Subscript(value=globals_call,
                                   slice=Index(value=Str(s=CONTEXT_NAME)),
                                   ctx=Load())
        start_frame_call = Call(func=Attribute(value=global_context,
                                               attr='start_frame',
                                               ctx=Load()),
                                args=args,
                                keywords=start_frame_keywords,
                                starargs=None,
                                kwargs=None)
        context_assign = Assign(targets=[Name(id=CONTEXT_NAME, ctx=Store())],
                                value=start_frame_call)
        new_node.body = [context_assign]
        if isinstance(try_body[0], Expr) and isinstance(
                try_body[0].value, Str):
            # Move docstring back to top of function.
            # noinspection PyUnresolvedReferences
            new_node.body.insert(0, try_body.pop(0))

        # trace function parameter values
        arg_nodes = []
        arg_nodes.extend(getattr(new_node.args, 'posonlyargs', []))
        arg_nodes.extend(new_node.args.args)
        arg_nodes.append(new_node.args.kwarg)
        arg_nodes.append(new_node.args.vararg)
        arg_nodes.extend(new_node.args.kwonlyargs)
        for target in arg_nodes:
            if target is None:
                continue
            if isinstance(target, Name) and target.id == 'self':
                continue
            if isinstance(target, arg) and target.arg == 'self':
                continue
            new_node.body.append(self._trace_assignment(target, node.lineno))

        if try_body:
            handler_body = [self._create_context_call('exception'), Raise()]
            new_node.body.append(
                Try(body=try_body,
                    handlers=[ExceptHandler(body=handler_body)],
                    orelse=[],
                    finalbody=[]))
            self._set_statement_line_numbers(try_body, first_line_number)
            self._set_statement_line_numbers(handler_body, last_line_number)
        return new_node