Production-oriented CPython 3.13 language-extension utilities for fast switch dispatch, bytecode-level function inlining, and validated local goto.
The distribution is named cpython-extensions; the import package is python_extensions. The project deliberately targets CPython internals and currently supports CPython 3.13.x (>=3.13,<3.14).
python -m pip install cpython-extensionsfrom python_extensions import (
case,
enable_goto,
enable_switch,
inline_calls,
inline_function,
switch,
)
goto .nameandlabel .nameare compile-time pseudo-statements recognized inside@enable_gotofunctions; they are not runtime objects that need to be imported.
| Capability | What it provides | Production-oriented default |
|---|---|---|
| Switch | Hash-table-style multi-way dispatch, typed key identity, guarded cases, and fallthrough | mode="auto" |
| Inline | Bytecode-level call inlining, profitability checks, shared regions, data-flow optimization | policy="speed", binding="frozen" |
| Goto | Explicit local jumps with exception-region and CFG validation | mode="strict" |
| Verification | Post-transform bytecode/control-flow verification and reports | Keep enabled |
The package favors general Python semantics, explicit opt-ins, and fail-closed transformation over benchmark-specific shortcuts.
Python intentionally keeps its language small and structured, but some performance-sensitive or generated-code workloads benefit from lower-level control. cpython-extensions explores three bounded extensions while keeping the transformation pipeline observable and verifiable:
- Switch — efficient multi-route dispatch without manually maintaining a dictionary of lambdas or a long
if/elifladder. - Inline — clone selected function bodies into callers, with profitability analysis and guarded binding when targets may change.
- Goto — local control-flow jumps for state machines, generated parsers, and carefully audited low-level code.
This is not a replacement Python implementation and does not claim portability to PyPy or other interpreters. It is intentionally CPython-specific.
from python_extensions import case, enable_switch, switch
@enable_switch
def classify(command: str) -> int:
with switch(command):
if case("read", "peek"):
return 1
if case("write"):
return 2
if case():
return 0Use exact runtime type as part of case identity when Python's ordinary equality aliases are undesirable:
@enable_switch(case_key_mode="typed")
def exact(value):
with switch(value):
if case(1):
return "int"
if case(1.0):
return "float"
if case(True):
return "bool"
if case():
return "other"from python_extensions import inline_calls, inline_function
@inline_function(register_only=True)
def affine(x: int, scale: int = 4) -> int:
return x * scale + 3
@inline_calls(policy="speed")
def hot_path(x: int) -> int:
return affine(x)The default binding="frozen" is the highest-optimization mode and assumes the target remains intentionally stable after transformation. Use guarded binding when a callee may be rebound or mutated:
@inline_calls(policy="always", binding="guarded")
def plugin_sensitive(x):
return affine(x)Guarded mode validates the callable state used by the cloned body and falls back to the ordinary call if that state no longer matches.
from python_extensions import enable_goto
@enable_goto
def countdown(n: int) -> int:
total = 0
label .loop
if n <= 0:
goto .done
total += n
n -= 1
goto .loop
label .done
return totalStrict mode is the production default and rejects jumps that cross unsafe control-flow or exception-region boundaries.
The source-level goto .name / label .name notation is inspired in part by Entrian's “goto for Python”. cpython-extensions uses an independent CPython 3.13 lowering pipeline with strict CFG/exception-region validation and post-transform bytecode verification; it does not reuse Entrian's implementation.
from python_extensions import optimize_extensions
@optimize_extensions(
switch=True,
inline={"policy": "speed"},
goto=True,
)
def execute(...):
...Inspect rather than blindly trust transformed functions:
from python_extensions import explain_extensions, verify_code
print(explain_extensions(execute))
verify_code(execute.__code__)| Area | Recommended default | Choose another mode when... |
|---|---|---|
| Switch | mode="auto" |
You have explicitly accepted the contract of a live/self-modifying backend |
| Case identity | case_key_mode="python" |
Exact runtime types such as 1, 1.0, and True must remain distinct |
| Inline binding | binding="frozen" |
Use guarded for hot reload, plugins, monkey-patching, replaceable methods, or mutable defaults |
| Inline policy | policy="speed" |
Use always for controlled experiments or code-size/latency tradeoffs you have measured |
| Goto | mode="strict" |
unsafe is reserved for carefully audited low-level experiments |
| Verification | enabled | Do not bypass verifier failures in production |
python -m pip install cpython-extensionsgit clone https://github.com/Karvp/cpython-extensions.git
cd cpython-extensions
python -m venv .venvWindows PowerShell:
.venv\Scripts\Activate.ps1
python -m pip install -U pip
python -m pip install -e ".[dev]"
python -m pytestPOSIX shells:
source .venv/bin/activate
python -m pip install -U pip
python -m pip install -e ".[dev]"
python -m pytestpython -m compileall -q src tests tools benchmarks/scripts
python -m pytest
python -m coverage run --branch -m pytest
python -m coverage report
python tools/check_repo.pyLong-running stress tests are intentionally separated from ordinary pull-request feedback. See .github/workflows/stress.yml.
Version 1.1.0 is the current supported release line. It is a performance-evidence, verification, and documentation milestone over 1.0.4: the production transformation contracts are preserved, while the optimized paths are covered by stronger scaling benchmarks and structural regression tests.
The 1.1.0 tree has been exercised on CPython 3.13.5 with the package regression suite, CPython dev-mode checks, bytecode/control-flow verification, multi-million-operation stress and differential harnesses, reproducible wheel/sdist builds, and exact-artifact smoke tests.
Release evidence:
The project does not currently claim independent certification for free-threaded CPython (3.13t) or for CPython 3.14+.
For direct literal routes, the portable compiler can lower the switch to a bound table lookup. Route data grows with the number of cases, but the executable hot path remains bounded instead of expanding into an N-way comparison chain. The 1.1.0 scaling harness compares equivalent generated routers implemented as if/elif, match, a hand-written bound dict.get, and @enable_switch(mode="portable").
Every successful route is validated before timing. Hits are distributed uniformly over every route in forward and reverse order; misses are checked for correctness but excluded from timing so the linear baselines represent average successful-hit depth rather than a deliberately worst-case miss. The committed 1.1.0 run used CPython 3.13.5 on Linux x86-64 and timeit.repeat with 7 repeats and 50 warm-up batches. It targets 100,000 successful dispatches per sample through 256 routes; for larger generated routers the harness scales work with route count while retaining at least 50,000 dispatches per sample.
| Integer cases | if/elif |
match |
bound dict.get |
switch |
vs if/elif |
vs match |
|---|---|---|---|---|---|---|
| 2 | 45.71 ns | 47.19 ns | 51.34 ns | 49.84 ns | 0.92× | 0.95× |
| 4 | 53.28 ns | 59.93 ns | 46.65 ns | 46.10 ns | 1.16× | 1.30× |
| 8 | 72.51 ns | 82.42 ns | 43.76 ns | 44.65 ns | 1.62× | 1.85× |
| 16 | 125.43 ns | 133.69 ns | 45.72 ns | 43.35 ns | 2.89× | 3.08× |
| 32 | 237.92 ns | 242.18 ns | 44.41 ns | 43.07 ns | 5.52× | 5.62× |
| 64 | 451.40 ns | 484.48 ns | 46.17 ns | 45.42 ns | 9.94× | 10.67× |
| 128 | 842.59 ns | 899.73 ns | 44.20 ns | 44.04 ns | 19.13× | 20.43× |
| 256 | 1,741.36 ns | 1,718.07 ns | 44.61 ns | 44.69 ns | 38.96× | 38.44× |
| 512 | 3,444.44 ns | 3,378.72 ns | 45.86 ns | 48.29 ns | 71.33× | 69.97× |
| 1,024 | 7,222.90 ns | 7,181.39 ns | 44.98 ns | 50.54 ns | 142.90× | 142.08× |
The scaling behavior is the important result. The switch stays near a dictionary lookup while the linear branch forms grow with route count. At 64 integer routes it is 9.94× faster than if/elif; at 256 routes 38.96×; at 512 routes 71.33×; and at 1,024 routes 142.90×. String routing shows the same large-route advantage: the 1,024-route string case records 83.86× versus if/elif on this run.
The bounded-code regression explains why the curve does not become linear: the specialized direct-value function remains 74 bytes of executable bytecode at 1,024 routes, while the generated if/elif reaches 17,420 bytes and match reaches 19,466 bytes. The table payload still consumes memory proportional to route count; the bounded claim applies to the executable dispatch path, not total storage.
The crossover is also part of the evidence. At two routes, native branching is faster. Around 4–8 routes the table-backed path reaches parity and then begins to pull away. Use switch for the semantics and maintainability you need, and treat the scaling advantage as strongest for larger static route sets that qualify for the portable specialization.
Reproduce the matrix:
python benchmarks/scripts/benchmark_switch_scaling_v110.py \
--target-dispatches 100000 --repeat 7 --warmup-batches 50 \
--json benchmarks/results/BENCHMARK_SWITCH_SCALING_V110.jsonRaw evidence: benchmarks/results/BENCHMARK_SWITCH_SCALING_V110.json.
The companion harness keeps the comparisons specific to the feature being measured. Frozen inlining is compared with an ordinary call to the same helper. Strict goto is compared with an explicit state-machine loop, with a naturally structured reference measured separately so the cost of label/jump lowering remains visible.
| Scenario | Plain Python | With extension | Relative result |
|---|---|---|---|
| Small frozen affine helper | 58.31 ns/call | 43.52 ns/call | 1.34× faster |
Three-state explicit FSM (n=32) |
4,005.89 ns/call | 1,620.34 ns/call | 2.47× faster |
| Naturally structured reference for the same work | 1,602.91 ns/call | 1,620.34 ns/call (goto) |
1.1% slower than structured reference |
The goto result should be read narrowly. goto is not a replacement for code that is already naturally expressed as a loop. It is useful when the source genuinely is a state machine, generated control-flow graph, or cleanup-oriented low-level routine; in that setting strict lowering can remove repeated state-variable dispatch while preserving explicit label/jump structure and verifier checks.
Reproduce these measurements:
python benchmarks/scripts/benchmark_extension_benefits_v110.py \
--json benchmarks/results/BENCHMARK_EXTENSION_BENEFITS_V110.jsonRaw evidence: benchmarks/results/BENCHMARK_EXTENSION_BENEFITS_V110.json.
These are microbenchmarks, not universal performance guarantees. CPU, operating system, CPython patch release, adaptive specialization state, key type, hit distribution, route-body shape, and surrounding application work can all change the result. The repository therefore keeps timing evidence separate from semantic qualification, validates results before timing, commits raw JSON, and uses structural tests to guard the mechanism behind the large-switch scaling result.
The broader 1.1.0 baseline is available through benchmarks/scripts/benchmark_readme_baseline_v110.py and its committed JSON result. Historical benchmark evidence remains under benchmarks/results/ and is not rewritten when a new release is cut.
See benchmarks/README.md for reproduction and evidence-retention guidance.
- Comprehensive guide — complete API, performance choices, guarded/frozen semantics, composition, troubleshooting, and deployment guidance.
- Architecture — transformation pipeline, invariants, and subsystem responsibilities.
- Compatibility — interpreter/runtime support boundary and unsupported environments.
- Release process — reproducible build, artifact verification, and tag/release workflow.
- Release notes — release summary, including 1.1.0.
- Changelog — public release changes.
- Contributing — development expectations and test requirements.
- Security policy — how to report verifier, crash, or unsafe-boundary issues.
Canonical repository: Karvp/cpython-extensions. Recommended repository settings and topics are tracked in .github/REPOSITORY_METADATA.md. The recommended GitHub description is:
Production-oriented CPython 3.13 bytecode extensions for switch dispatch, function inlining, and validated goto.
Contributions are welcome when they preserve general Python semantics and avoid benchmark- or fixture-specific shortcuts. Please run the normal development gates before opening a pull request and include focused regression coverage for observable behavior changes.
See CONTRIBUTING.md.
Low-level bytecode transformation can amplify interpreter/runtime assumptions. Crashes, verifier bypasses, incorrect exception-region handling, or unsafe boundary crossings should be treated as security-relevant until triaged.
See SECURITY.md.
This project is licensed under the Mozilla Public License 2.0 (MPL-2.0). See LICENSE.
MPL-2.0 is a file-level copyleft license: modifications to MPL-covered source files remain under MPL-2.0 when distributed, while the license permits those files to be combined with a larger work under different terms, subject to the license conditions.