Skip to content

Design

Every load-bearing decision in redef traces to a measurement or a field failure. This page states the decisions and their evidence in short form; the research notes carry the full versions.

Decorator-scoped and hookless. Import hooks and source codecs earn a vacuous pass from static checkers, because the file's surface is valid Python that is never what runs, and a process-wide hook taxes every import whether or not it uses the mechanism (measured at 4× to 5× cold for the most complete Python macro expander, on modules with no macros at all). A decorator touches only what it decorates, announces itself at the definition site, and leaves the file meaning what it says to every tool.

The envelope is fixed; the edges are the product. Source recovery works in 10 of 18 execution contexts on CPython 3.14, and no library changes that. What a library chooses is the behaviour at the other eight: redef converts every silent misbehaviour (wrong function rewritten, closure failing three calls later, OSError with no context) into a named error with the remedy when one exists.

Repairs are defaults, never options. The audited deployers each implement a subset of the repairs; the library's reason to exist is the conjunction. There is no configuration to reintroduce the gaps.

Refusals are API. Lambdas, wrapped functions, closures at recompile time, and stale sources raise typed errors. A refusal you can catch and explain beats a heuristic that is right most of the time.

Verification is on by default, by a pre-registered rule. The stale-body detector shipped opt-in until its first field trial ran clean; the trial's first run failed, fixed two real defects, and the post-fix state satisfied the rule. The sequence is documented rather than smoothed over; see Verification.

No cache, by measurement. The whole pipeline costs tens to hundreds of microseconds per decorated function, once per process. A bytecode cache would buy almost nothing and would import the cache-correctness problem (version tags, invalidation, foreign builds) that the research measured in deployed expanders.

Innermost, and honest about detectability. The rewrite must sit closest to def. A wrapper below it means the recovered source no longer describes the received object. __wrapped__ is detected and refused; an unadvertised wrapper is undetectable from the inside, and the docs say so rather than pretending otherwise.

Two authorities are checked against each other. A function's source and its code object agree only under assumptions (same compiler, same flags, same text). redef checks the agreement rather than assuming it, and the check's two field-found failure modes (module-level __future__ flags, caches from same-magic sibling builds) are now part of the design: flags are inherited, and the comparator grades structure separately from bytes.

What it deliberately is not. Not a macro system: no call-site syntax, no quasiquotes, no multi-phase compilation (mcpyrate does that, behind an import hook, and is the right tool for it). Not a whole-module rewriter: typeguard and pytest own that pattern. Not a bytecode tool: version-pinned opcode knowledge is a different project. One function, from its source, correctly.