Source-to-source API

When you want the rewritten source — for a linter, formatter, or source map — rather than a running program, use these module-level functions. They operate against the active tracer stack (or the tracers you pass explicitly). See Source-to-source transforms for the how-to.

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.parse(code: str, mode: str = 'exec', instrument: bool = True) Module | Expression[source]

Both transform and untransform accept positions=[(line, col), ...] and return the remapped positions alongside the rewritten source, for source-map-style tooling.

Pure (analysis-only) transforms

Passing pure=True marks a transform whose result will never be executed — purely for analysis. Cooperating rewrites can consult is_pure_transform() to avoid touching execution-relevant state. It is thread- and async-safe (backed by a ContextVar).

pyccolo.is_pure_transform() bool[source]

True while a pure=True transform/untransform is running on this thread / async context. Cooperating CustomRewrite.rewrite / paired-delimiter emit callbacks 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.

with OptionalChainer:
    assert pyc.transform("y = a?.b?.c") == "y = a.b.c"
    tree = pyc.parse("y = a?.b?.c", instrument=False)
    assert pyc.untransform(tree) == "y = a?.b?.c"
    assert pyc.transform("y = a?.b", pure=True) == "y = a.b"

Sandbox filenames

Instrumented code run through exec() / eval() is compiled under a synthetic filename so it can be recognized in frames and tracebacks:

pyccolo.SANDBOX_FNAME

The filename assigned to sandboxed exec/eval code.

pyccolo.SANDBOX_FNAME_PREFIX

The prefix shared by all sandbox filenames — test frame.f_code.co_filename against it to detect sandboxed frames.

pyccolo.TRACEBACK_VISIBLE_SANDBOX_FILES

The registry of sandbox files whose frames should remain visible in tracebacks (see mark_traceback_visible()).