예제 #1
0
 def _get_replacement_args(self, args, keywords: bool):
     replacement_args = []
     for arg in args:
         is_starred = isinstance(arg, ast.Starred)
         is_kwstarred = keywords and arg.arg is None
         if keywords or is_starred:
             maybe_kwarg = getattr(arg, 'value')
         else:
             maybe_kwarg = arg
         with fast.location_of(maybe_kwarg):
             with self.attrsub_context(None):
                 visited_maybe_kwarg = self.visit(maybe_kwarg)
             with self.attrsub_context(None):
                 new_arg_value = cast(ast.expr, fast.Call(
                     func=self._emitter_ast(),
                     args=[TraceEvent.argument.to_ast(), self._get_copy_id_ast(maybe_kwarg)],
                     keywords=fast.kwargs(
                         ret=visited_maybe_kwarg,
                         is_starred=fast.NameConstant(is_starred),
                         is_kwstarred=fast.NameConstant(is_kwstarred)
                     ),
                 ))
         if keywords or is_starred:
             setattr(arg, 'value', new_arg_value)
         else:
             arg = new_arg_value
         replacement_args.append(arg)
     return replacement_args
예제 #2
0
 def visit_Dict(self, node: ast.Dict):
     traced_keys: List[Optional[ast.expr]] = []
     traced_values: List[ast.expr] = []
     for k, v in zip(node.keys, node.values):
         is_dict_unpack = (k is None)
         if is_dict_unpack:
             traced_keys.append(None)
         else:
             with fast.location_of(k):
                 traced_keys.append(fast.Call(
                     func=self._emitter_ast(),
                     args=[TraceEvent.dict_key.to_ast(), self._get_copy_id_ast(k)],
                     keywords=fast.kwargs(
                         ret=self.visit(k),
                         value_node_id=self._get_copy_id_ast(v),
                         dict_node_id=self._get_copy_id_ast(node),
                     )
                 ))
         with fast.location_of(v):
             if is_dict_unpack:
                 key_node_id_ast = fast.NameConstant(None)
             else:
                 key_node_id_ast = self._get_copy_id_ast(k)
             traced_values.append(fast.Call(
                 func=self._emitter_ast(),
                 args=[TraceEvent.dict_value.to_ast(), self._get_copy_id_ast(v)],
                 keywords=fast.kwargs(
                     ret=self.visit(v),
                     key_node_id=key_node_id_ast,
                     dict_node_id=self._get_copy_id_ast(node),
                 )
             ))
     node.keys = traced_keys
     node.values = traced_values
     return self.visit_literal(node, should_inner_visit=False)
예제 #3
0
 def visit_List_or_Tuple(self, node: Union[ast.List, ast.Tuple]):
     traced_elts: List[ast.expr] = []
     is_load = isinstance(getattr(node, 'ctx', ast.Load()), ast.Load)
     saw_starred = False
     for i, elt in enumerate(node.elts):
         if isinstance(elt, ast.Starred):
             # TODO: trace starred elts too
             saw_starred = True
             traced_elts.append(elt)
             continue
         elif not is_load:
             traced_elts.append(self.visit(elt))
             continue
         with fast.location_of(elt):
             traced_elts.append(fast.Call(
                 func=self._emitter_ast(),
                 args=[
                     TraceEvent.list_elt.to_ast() if isinstance(node, ast.List) else TraceEvent.tuple_elt.to_ast(),
                     self._get_copy_id_ast(elt),
                 ],
                 keywords=fast.kwargs(
                     ret=self.visit(elt),
                     index=fast.NameConstant(None) if saw_starred else fast.Num(i),
                     container_node_id=self._get_copy_id_ast(node),
                 )
             ))
     node.elts = traced_elts
     return self.visit_literal(node, should_inner_visit=False)
예제 #4
0
    def visit_Attribute_or_Subscript(
        self,
        node: Union[ast.Attribute, ast.Subscript],
        attr_or_sub: ast.expr,
        call_context: bool = False
    ):
        orig_node_id = id(node)
        with fast.location_of(node.value):
            extra_args: List[ast.keyword] = []
            if isinstance(node.value, ast.Name):
                extra_args = fast.kwargs(obj_name=fast.Str(node.value.id))

            with self.attrsub_context(node):
                node.value = fast.Call(
                    func=self._emitter_ast(),
                    args=[
                        TraceEvent.subscript.to_ast() if isinstance(node, ast.Subscript) else TraceEvent.attribute.to_ast(),
                        self._get_copy_id_ast(node.value)
                    ],
                    keywords=fast.kwargs(
                        ret=self.visit(node.value),
                        attr_or_subscript=attr_or_sub,
                        ctx=fast.Str(node.ctx.__class__.__name__),
                        call_context=fast.NameConstant(call_context),
                        top_level_node_id=self._get_copy_id_ast(self._top_level_node_for_symbol)
                    ) + extra_args
                )
        # end fast.location_of(node.value)

        return self._maybe_wrap_symbol_in_before_after_tracing(node, orig_node_id=orig_node_id)
예제 #5
0
    def _maybe_wrap_symbol_in_before_after_tracing(
        self, node, call_context=False, orig_node_id=None, begin_kwargs=None, end_kwargs=None
    ):
        if self._inside_attrsub_load_chain:
            return node
        orig_node = node
        orig_node_id = orig_node_id or id(orig_node)
        begin_kwargs = begin_kwargs or {}
        end_kwargs = end_kwargs or {}

        ctx = getattr(orig_node, 'ctx', ast.Load())
        is_load = isinstance(ctx, ast.Load)

        with fast.location_of(node):
            begin_kwargs['ret'] = self._get_copy_id_ast(orig_node_id)
            if is_load:
                end_ret = orig_node
            elif isinstance(orig_node, (ast.Attribute, ast.Subscript)):
                end_ret = orig_node.value
            else:
                raise TypeError('Unsupported node type for before / after symbol tracing: %s', type(orig_node))
            end_kwargs['ret'] = end_ret
            end_kwargs['ctx'] = fast.Str(ctx.__class__.__name__)
            end_kwargs['call_context'] = fast.NameConstant(call_context)
            node = fast.Call(
                func=self._emitter_ast(),
                args=[
                    TraceEvent.after_complex_symbol.to_ast(),
                    fast.Call(
                        # this will return the node id
                        func=self._emitter_ast(),
                        args=[TraceEvent.before_complex_symbol.to_ast(), self._get_copy_id_ast(orig_node_id)],
                        keywords=fast.kwargs(**begin_kwargs),
                    )
                ],
                keywords=fast.kwargs(**end_kwargs),
            )
            if not is_load:
                if isinstance(orig_node, ast.Attribute):
                    node = fast.Attribute(
                        value=node,
                        attr=orig_node.attr,
                    )
                elif isinstance(orig_node, ast.Subscript):
                    node = fast.Subscript(
                        value=node,
                        slice=orig_node.slice,
                    )
                else:
                    logger.error(
                        'Symbol tracing stores unsupported for node %s with type %s', orig_node, type(orig_node)
                    )
                    assert False
                node.ctx = ast.Store()
        # end location_of(node)
        return node