BaseTracer
Everything you build with Pyccolo is a subclass of BaseTracer. Thanks to
its metaclass, the class itself acts as the tracer for most purposes: it is a
singleton, it doubles as a context manager, and class-level calls are forwarded to
the instance.
Activation & singleton
A tracer class is a traitlets singleton. You rarely instantiate it yourself:
MyTracer.instance()— the singleton instance (alsopyc.instance()for the active tracer).with MyTracer:— activate for a dynamic scope (the class is a context manager). Equivalent towith MyTracer.instance().tracing_context():.MyTracer.enable()/MyTracer.disable()— activate/deactivate imperatively.
Context managers
Running & compiling code
See Why pyc.exec, and how scoping works for why code defined in the same file as the tracer must be run through these entry points.
- BaseTracer.exec(code: str | Module | stmt | Expression, global_env: dict | None = None, local_env: dict | None = None, *, instrument: bool = True, filename: str | None = None, num_extra_lookback_frames: int = 0) Dict[str, Any]
- BaseTracer.eval(code: str | expr | Expression, global_env: dict | None = None, local_env: dict | None = None, *, instrument: bool = True, filename: str | None = None, num_extra_lookback_frames: int = 0) Any
- BaseTracer.execute(*args, **kwargs)
- BaseTracer.parse(code: str, mode='exec', filename: str | None = None, tracers: List[BaseTracer] | None = None, instrument: bool = True) Module | Expression
- BaseTracer.transform(code: str, tracers: List[BaseTracer] | None = None, positions: List[Tuple[int, int]] | None = None, pure: bool = False) str | Tuple[str, List[Position]]
- BaseTracer.untransform(tree: AST, tracers: List[BaseTracer] | None = None, positions: List[Tuple[int, int]] | None = None, pure: bool = False) str | Tuple[str, List[Position]]
Re-entrant fragments
For instrumenting code from inside a handler without disturbing tracer state (used by macro-style tracers):
- BaseTracer.parse_fragment(code: str, filename: str | None = None, tracers: List[BaseTracer] | None = None) Module | Expression
Parse + instrument a code fragment from within an already active trace (e.g. inside an event handler) without disturbing the enclosing rewrite’s transient state. Returns the instrumented AST; the caller may edit it before running it with
exec_raw(..., instrument=False).Use this (rather than
parse/exec) when you need to compile a fragment mid-handler: it neither re-enters the tracing context (which would reset tracer state) nor clobbers an in-flight parse, so nested instrumented constructs in the fragment still dispatch to handlers.tracersscopes the instrumentation to a subset of the active stack; pass it when a foreign co-tracer should not weave its events into the fragment (e.g. it would not recognize the fragment’s synthetic nodes).
- BaseTracer.exec_fragment(code: str | Module, global_env: dict, local_env: dict, filename: str | None = None) dict
Parse, instrument, and run a code fragment from within an active trace, reusing the current tracing context.
local_envis mutated with whatever the fragment defines and returned. Seeparse_fragment().
Overridable hooks
Override these on your subclass to customize behavior. All have safe defaults.
- BaseTracer.should_propagate_handler_exception(evt: TraceEvent, exc: Exception) bool
Guards
Guards let you switch instrumentation off at runtime for a function or loop once you no longer need it — the key to amortizing overhead.
Augmentation helpers
Used when defining new syntax.
- classmethod BaseTracer.syntax_augmentation_specs() List[AugmentationSpec]
- classmethod BaseTracer.get_augmentations(node_id: AST | int) FrozenSet[AugmentationSpec]
- BaseTracer.make_ast_rewriter(path: str, module_id: int | None = None, tracers: List[BaseTracer] | None = None) AstRewriter
- BaseTracer.make_syntax_augmenter(ast_rewriter: AstRewriter | None) Callable[[CodeLines], CodeLines]
AST ancestry
Classmethods for asking where a node sits in the tree — handy inside when=
predicates and handlers.
State
- BaseTracer.make_stack()
- BaseTracer.reset()
NoopTracer
The default tracer used when the stack is empty: it patches nothing, enables no guards, and instruments no files.