API reference
This page is a compact reference for Pyccolo’s public API. The narrative pages under Concepts are the best way to learn the library; this appendix is for looking things up.
Everything documented here is importable from the top-level pyccolo package
(conventionally imported as pyc).
Tracers
Registering handlers
- pyccolo.register_handler(event: TraceEvent | Type[AST] | Tuple[TraceEvent | Type[AST], ...], when: Callable[[...], bool] | Predicate | None = None, reentrant: bool = False, static: bool = False, use_raw_node_id: bool = False, guard: Callable[[AST], str] | None = None, exempt_from_guards: bool = False)[source]
- pyccolo.register_raw_handler(event: TraceEvent | Type[AST] | Tuple[TraceEvent | Type[AST], ...], **kwargs)[source]
Every member of TraceEvent is also re-exported as
a module-level decorator, so @pyc.before_stmt is sugar for
register_handler(pyc.before_stmt) and accepts the same keyword arguments
(when=, reentrant=, …).
Running instrumented code
- pyccolo.eval(code: str | expr | Expression, *args, **kwargs) Any[source]
- pyccolo.instrumented(tracers: List[BaseTracer], mutate: bool = False) Callable[[Callable[[...], Any]], Callable[[...], Any]][source]
- pyccolo.tracer() BaseTracer[source]
- pyccolo.instance() BaseTracer[source]
Tracing contexts
Source-to-source
- pyccolo.transform(code: str, tracers: List[BaseTracer] | None = None, positions: None = None, pure: bool = False) str[source]
- pyccolo.transform(code: str, tracers: List[BaseTracer] | None, positions: List[Tuple[int, int]], pure: bool = False) Tuple[str, List[Position]]
- pyccolo.transform(code: str, *, positions: List[Tuple[int, int]], pure: bool = False) Tuple[str, List[Position]]
- pyccolo.untransform(tree: AST, tracers: List[BaseTracer] | None = None, positions: None = None, pure: bool = False) str[source]
- pyccolo.untransform(tree: AST, tracers: List[BaseTracer] | None, positions: List[Tuple[int, int]], pure: bool = False) Tuple[str, List[Position]]
- pyccolo.untransform(tree: AST, *, positions: List[Tuple[int, int]], pure: bool = False) Tuple[str, List[Position]]
- pyccolo.is_pure_transform() bool[source]
True while a
pure=Truetransform/untransform is running on this thread / async context. CooperatingCustomRewrite.rewrite/ paired-delimiteremitcallbacks must not mutate execution-relevant state (e.g. process-global registries the runtime later reads) when this is set – the transformed code is being inspected, not executed.
Predicates
- class pyccolo.Predicate(condition: Callable[[AST], bool], use_raw_node_id: Literal[False], static: bool = True)[source]
- class pyccolo.Predicate(condition: Callable[[int], bool], use_raw_node_id: Literal[True], static: bool = False)
- class pyccolo.Predicate(condition: Callable[[...], bool], use_raw_node_id: bool = False, static: bool = False)
Syntax augmentation
- class pyccolo.AugmentationSpec(aug_type, token, replacement, close_token, close_replacement, name_pattern, body_func_wrapper, custom)[source]
- aug_type: AugmentationType
Alias for field number 0
- custom: CustomRewrite | None
Alias for field number 7
- class pyccolo.AugmentationType(*values)[source]
- prefix = 'prefix'
- suffix = 'suffix'
- dot_prefix = 'dot_prefix'
- dot_suffix = 'dot_suffix'
- binop = 'binop'
- boolop = 'boolop'
- call = 'call'
- subscript = 'subscript'
- custom = 'custom'
- class pyccolo.CustomRewrite[source]
Drives a
AugmentationType.customspec. A cooperating tracer that needs a context-sensitive surface rewrite (one the static token/paired passes can’t express – e.g. a token whose meaning depends on the preceding token, or a per-occurrence choice between two lowerings) implements these three methods so the rewrite participates in pyccolo’s position-remapping anduntransformmachinery uniformly, instead of bolting on a parallel resugaring path.Subclassing is optional (the methods are duck-typed); it just documents intent.
- rewrite(code: str, register: Callable[[int, int], None]) Tuple[str, List[Tuple[int, int, int]]][source]
Forward-rewrite
code->(new_code, edits).editsare(start, end, new_len)triples incode’s input absolute offsets – sorted ascending and disjoint, the same shapereplace_tokens_and_get_augmented_positions()builds – so the caller can remap trackedpositionsthrough them withremap_through_edits(). For each rewritten occurrence whose resulting AST node should be reverse-handled byuntransform, callregister(line, col)with the 1-indexed line / 0-indexed col of the node’s anchor in ``new_code`` (the locationrange_for()will re-derive on the parsed node).
- range_for(node: AST) Range | None[source]
Anchor
Rangeof a rewrittennode(mirrors the built-in_get_<aug_type>_range_forhelpers), orNoneifnodeis not one this rewrite produced. Used both to bind the registered position forward and to locate the node duringuntransform.
- reverse(node: AST, spec: AugmentationSpec, aug_range: Range, code: str, line_starts: List[int]) Tuple[int, int, str] | None[source]
Reverse (resugar) splice
(start, end, new_text)on validcode, orNoneto leavenodeuntouched. A single whole-span edit suffices; the caller applies edits right-to-left.
State
Return-value sentinels
Handlers use these sentinels to express intents that a bare return cannot
(see The model: events and handlers):
pyccolo.Null— override the instrumented value withNone(as opposed to “no override”, which is what returningNonemeans).pyccolo.Skip— stop running further handlers for the current event on this tracer.pyccolo.SkipAll— abort the entire tracer stack for the current event.pyccolo.Pass— an explicit “do nothing / no override” marker.
The event taxonomy
All events are members of pyccolo.trace_events.TraceEvent, each
re-exported as pyc.<name>. The complete list (100+ events) is defined in
pyccolo/trace_events.py.
Grouped by what they instrument:
Statements:
before_stmt,after_stmt,after_module_stmt,after_expr_stmt.Names & assignments:
load_name,after_assign_rhs,before_augassign_rhs/after_augassign_rhs.Attributes:
before_attribute_load/after_attribute_load,before_attribute_store,before_attribute_del.Subscripts:
before_subscript_load/after_subscript_load,before_subscript_store,before_subscript_del,_load_saved_slice.Literals:
after_int,after_float,after_complex,after_string,after_bytes,after_list_literal,after_dict_literal,after_set_literal,after_tuple_literal,ellipsis.Operators:
before_binop/after_binop,before_unaryop/after_unaryop,before_boolop/after_boolop,before_compare/after_compare, and the*_argvariants.Comprehensions & calls: the comprehension events,
before_call/after_call, and the argument events.Control flow: the loop events (
before_for_loop_body,after_for_loop_iter,after_while_loop_iter, …),after_if_test,after_while_test.Functions:
before_function_body,after_function_execution,before_lambda/after_lambda_body.Imports & module lifecycle:
before_import,init_module,exit_module.``sys``-level events (see Compatibility with sys.settrace):
call,line,return_,exception,opcode.