Metadata-Version: 2.4
Name: cpython-extensions
Version: 1.3.2
Summary: CPython 3.13 switch/live dispatch, specialization, function inlining, and validated goto extensions
Author: Mch Stephen
License-Expression: GPL-3.0-only
Project-URL: Homepage, https://github.com/Karvp/cpython-extensions
Project-URL: Repository, https://github.com/Karvp/cpython-extensions
Project-URL: Issues, https://github.com/Karvp/cpython-extensions/issues
Project-URL: Documentation, https://github.com/Karvp/cpython-extensions/blob/main/docs/COMPREHENSIVE_GUIDE.md
Classifier: Development Status :: 5 - Production/Stable
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Intended Audience :: Developers
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX
Classifier: Operating System :: MacOS
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: <3.14,>=3.13
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: bytecode<0.18,>=0.17
Provides-Extra: test
Requires-Dist: pytest<10,>=8; extra == "test"
Requires-Dist: coverage[toml]<8,>=7.6; extra == "test"
Provides-Extra: build
Requires-Dist: build<2,>=1.2; extra == "build"
Requires-Dist: twine<7,>=5; extra == "build"
Requires-Dist: trove-classifiers>=2026.6.1.19; extra == "build"
Provides-Extra: dev
Requires-Dist: pytest<10,>=8; extra == "dev"
Requires-Dist: coverage[toml]<8,>=7.6; extra == "dev"
Requires-Dist: build<2,>=1.2; extra == "dev"
Requires-Dist: twine<7,>=5; extra == "dev"
Requires-Dist: trove-classifiers>=2026.6.1.19; extra == "dev"
Dynamic: license-file

# cpython-extensions

**Production-oriented CPython 3.13 extensions for switch dispatch, guarded specialization/partial evaluation, bytecode-level function inlining, and validated local goto.**

[![Python](https://img.shields.io/badge/Python-3.13-3776AB?logo=python&logoColor=white)](https://www.python.org/)
[![Implementation](https://img.shields.io/badge/implementation-CPython-306998)](https://www.python.org/)
[![License](https://img.shields.io/badge/license-GPL--3.0--only-blue)](LICENSE)
[![Typing](https://img.shields.io/badge/typing-py.typed-informational)](src/python_extensions/py.typed)

The distribution is **`cpython-extensions`** and the primary import package is **`python_extensions`**. The project deliberately targets CPython internals and currently supports **CPython 3.13.x** (`>=3.13,<3.14`).

```bash
python -m pip install cpython-extensions
```

```python
from python_extensions import (
    case,
    enable_goto,
    enable_switch,
    hotpath,
    inline_calls,
    inline_function,
    optimize_extensions,
    partial,
    runtime_diagnostics,
    specialize,
    switch,
)
```

> `goto .name` and `label .name` are compile-time pseudo-statements recognized inside `@enable_goto` functions; they are not runtime objects that need to be imported.

## At a glance

| Capability | What it provides | Production-oriented default |
|---|---|---|
| **Switch** | Hash/table-backed multi-way dispatch, typed key identity, guarded cases, fallthrough, and optional live self-modifying dispatch | `mode="auto"` (portable) |
| **Partial** | Freeze selected parameters into a real transformed function and eliminate provably dead work | explicit `partial(...)` |
| **Specialize** | Guarded exact-type/constant variants with guaranteed generic fallback | explicit `@specialize(...)` |
| **Hotpath** | Bounded adaptive discovery and promotion of profitable argument shapes | `policy="speed", backend="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"` |
| **Runtime qualification** | Bounded package-owned CPython/runtime self-tests at import plus opt-in exhaustive diagnostics | automatic |
| **Verification** | Post-transform bytecode/control-flow verification and transformation reports | Keep enabled |

The package favors **general Python semantics, explicit opt-ins, bounded adaptive state, and fail-closed transformation** over benchmark-specific shortcuts.

## Why cpython-extensions?

Python intentionally keeps its language and execution model structured. Some hot interpreters, parsers, generated state machines, numeric kernels, and stable internal helpers nevertheless benefit from lower-level control. `cpython-extensions` provides a set of CPython-specific transformations while keeping the selected plan inspectable and independently verifiable.

- **Switch** — efficient multi-route dispatch without a manually maintained handler dictionary or long `if/elif` ladder.
- **Partial / specialize / hotpath** — expose constants and exact runtime types to the bytecode optimizer while retaining explicit guards or generic fallback where required.
- **Inline** — clone eligible helper bodies into callers, with profitability analysis and guarded binding for replaceable targets.
- **Goto** — local control-flow jumps for generated state machines and carefully audited low-level code.

This is not a replacement Python implementation and does not claim portability to PyPy or other interpreters.

## Quick start

### Switch dispatch

```python
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 0
```

Use exact runtime type as part of case identity when Python's ordinary equality aliases are undesirable:

```python
@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"
```

The default `mode="auto"` is deliberately portable and never mutates executable bytecode unless you explicitly supply `live_threshold`. In 1.3.0 that threshold opt-in is plan-aware: direct-value, expression-template, and statement-template portable plans veto live mutation even above the threshold because their compact lowering is already the preferred architecture. Live dispatch remains a CPython-3.13-only optimization for hot, repeated in-frame routing:

```python
@enable_switch(mode="fast", live_engine="auto")
def run_vm(opcodes):
    acc = 0
    for opcode in opcodes:
        with switch(opcode):
            if case(0):
                acc += 1
            if case(1):
                acc ^= 7
            # ... many heterogeneous opcode bodies ...
    return acc
```

`live_engine="auto"` uses the optional fused C dispatcher when its runtime self-test succeeds and otherwise falls back to the historical ctypes gate. `live_engine="native"` requires the C accelerator; `live_engine="ctypes"` is mainly useful for diagnostics and reproducible comparisons.

**Do not assume live is universally faster.** The extensive 1.2.0 qualification shows strong gains for large dense integer VM/parser loops, while portable statement-template/direct-value lowering remains preferable for ordinary HTTP/RPC routing and trivial cases. See [Live switch architecture and performance](docs/LIVE_SWITCH.md).

### Partial evaluation

```python
from python_extensions import partial

def parse(data, mode="safe"):
    if mode == "fast":
        return fast_parse(data)
    return checked_parse(data)

fast_parse_only = partial(parse, mode="fast")
```

`partial()` produces a transformed Python function whose frozen parameters are removed from the effective call signature. Safe constant propagation and dead-branch elimination are applied without changing observable local-variable behavior.

### Guarded specialization

```python
from python_extensions import specialize

@specialize(constants={"mode": "fast"}, types={"value": int})
def convert(value, mode="safe"):
    if type(value) is int and mode == "fast":
        return value + 1
    return slow_convert(value, mode)
```

The specialized variant is guarded. A guard miss executes the original generic function. Exact-type and constant guards are used only where their matching semantics are safe.

### Adaptive hot paths

```python
from python_extensions import hotpath

@hotpath(threshold=64, max_variants=1, policy="speed")
def decode(value, mode):
    if mode == "binary":
        return decode_binary(value)
    return decode_text(value)
```

`hotpath()` observes only a bounded number of shapes for a bounded profiling budget. On eligible ordinary functions, `backend="auto"` prefers CPython 3.13 `sys.monitoring` during warm-up and can install a verified in-frame dispatcher after promotion. It falls back to a wrapper where that contract is not suitable. See [Specialization and partial evaluation](docs/SPECIALIZATION.md).

### Function inlining

```python
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 intentionally remains stable after transformation. Use guarded binding when a callee may be rebound or mutated:

```python
@inline_calls(policy="always", binding="guarded")
def plugin_sensitive(x):
    return affine(x)
```

### Validated goto

```python
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 total
```

Strict mode is the production default and rejects jumps that cross unsafe control-flow or exception-region boundaries.

The source-level notation is inspired in part by [Entrian's “goto for Python”](https://entrian.com/goto/). `cpython-extensions` uses an independent CPython 3.13 lowering pipeline with strict CFG/exception-region validation and post-transform verification.

### Compose extensions

Composition uses one fixed order:

```text
switch -> partial -> inline -> goto -> specialize/hotpath
```

```python
from python_extensions import optimize_extensions

@optimize_extensions(
    switch=True,
    partial={"mode": "fast"},
    inline={"policy": "speed"},
    goto=True,
    specialize={"types": {"value": int}},
)
def execute(value, mode="safe"):
    ...
```

`specialize` and `hotpath` are alternative final layers and cannot both be enabled in the same pipeline.

Inspect transformed functions rather than blindly trusting them:

```python
from python_extensions import explain_extensions, verify_code

print(explain_extensions(execute))
verify_code(execute.__code__)
```

## Choosing the right mode

| Area | Recommended default | Choose another mode when... |
|---|---|---|
| Switch | `mode="auto"` | Use live modes only after accepting their CPython/runtime and concurrency contracts |
| Live engine | `live_engine="auto"` | Force `native` for certification or `ctypes` for fallback/diagnostic comparison |
| Case identity | `case_key_mode="python"` | Exact runtime types such as `1`, `1.0`, and `True` must remain distinct |
| Partial | explicit frozen bindings | You can prove the bound configuration is intentionally stable |
| Specialize | explicit constants/types | You know the valuable shape and need generic fallback |
| Hotpath | `policy="speed"`, bounded defaults | Runtime shape discovery is more useful than declaring variants manually |
| Inline binding | `binding="frozen"` | Use `guarded` for hot reload, plugins, monkey-patching, replaceable methods, or mutable defaults |
| Inline policy | `policy="speed"` | Use `always` only for controlled experiments or measured tradeoffs |
| Goto | `mode="strict"` | `unsafe` is reserved for carefully audited low-level experiments |
| Verification | enabled | Do not bypass verifier failures in production |

## Installation and native accelerator

### PyPI

```bash
python -m pip install cpython-extensions
```

When the build environment can compile the optional extension, the installed wheel contains `python_extensions._livegate`, the native live-switch accelerator. Source installations retain portable/ctypes functionality if that optional extension build is unavailable.
Tagged Linux releases are built on GitHub Actions as PyPI-compatible manylinux wheels via cibuildwheel; raw `linux_x86_64` setuptools wheels are never staged for publication.

Check availability:

```python
import importlib.util
print(importlib.util.find_spec("python_extensions._livegate") is not None)
```

The native accelerator is **not imported automatically on free-threaded CPython 3.13 builds** because this release does not certify live self-modifying dispatch for no-GIL execution. Portable switch mode remains the supported path there.

### Development checkout

```bash
git clone https://github.com/Karvp/cpython-extensions.git
cd cpython-extensions
python -m venv .venv
```

Windows PowerShell:

```powershell
.venv\Scripts\Activate.ps1
python -m pip install -U pip
python -m pip install -e ".[dev]"
python -m pytest
```

POSIX shells:

```bash
source .venv/bin/activate
python -m pip install -U pip
python -m pip install -e ".[dev]"
python -m pytest
```

## Runtime qualification and diagnostics

Version 1.3.0 performs bounded package-owned runtime qualification automatically during `import python_extensions`. The import-time probe verifies the CPython 3.13 wordcode/alignment contract, required opcodes, `CodeType.replace`, exception-table decoding, the shared CFG/stack verifier, portable switch execution, and goto runtime prerequisites. It never calls application functions.

Historically lazy or mutation-sensitive checks remain deferred so ordinary import stays bounded. Request the complete snapshot when diagnosing a deployment:

```python
from python_extensions import runtime_diagnostics

print(runtime_diagnostics())
print(runtime_diagnostics(full=True))
```

`full=True` additionally qualifies live-switch memory layout/native `_livegate` when supported and the bytecode-dependent inline/specialization subsystems. Results and failures are cached per process; returned dictionaries are detached copies. Free-threaded CPython reports live mode as unsupported rather than importing the native live accelerator. See [Runtime qualification](docs/RUNTIME_DIAGNOSTICS.md).

## Verification and development gates

```bash
python -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.py
```

Long-running stress tests are intentionally separated from ordinary pull-request feedback. See `.github/workflows/stress.yml` and the harnesses under `tests/`.

## Release quality

Version **1.3.2** is the current documented release line. It is a metadata-only corrective release over 1.3.0: runtime behavior, generated hot paths, V130 performance evidence, and the GPL-3.0-only licensing contract are unchanged. The intervening `v1.3.1` tag failed the release gate before any artifact was built or published because its source still declared 1.3.0. Historical 1.0.x–1.2.0 artifacts retain the licenses under which they were distributed.

The final 1.3.0 qualification on CPython 3.13.5 records **458/458 native-enabled tests**, the same **458/458** under CPython `-X dev`, debug allocation, and warnings-as-errors, plus the inherited **8,316,000-call** specialization adversarial and **1,239,100-call** live-switch compatibility harnesses.

Release evidence:

- [`benchmarks/results/BENCHMARK_PRIMARY_V130.md`](benchmarks/results/BENCHMARK_PRIMARY_V130.md) and [JSON](benchmarks/results/BENCHMARK_PRIMARY_V130.json) — **primary normal-Python-vs-extension benchmark**;
- [`benchmarks/results/BENCHMARK_SWITCH_SCALING_V110.json`](benchmarks/results/BENCHMARK_SWITCH_SCALING_V110.json) — retained portable-switch scaling against native Python dispatch forms;
- [`benchmarks/results/BENCHMARK_LIVE_EXTENSIVE_V122.md`](benchmarks/results/BENCHMARK_LIVE_EXTENSIVE_V122.md) and [JSON](benchmarks/results/BENCHMARK_LIVE_EXTENSIVE_V122.json) — portable/ctypes/native live mode comparison;
- [`benchmarks/results/BENCHMARK_OPTIMIZATION_V130.md`](benchmarks/results/BENCHMARK_OPTIMIZATION_V130.md) and [JSON](benchmarks/results/BENCHMARK_OPTIMIZATION_V130.json) — 1.2→1.3 transformation/profiling improvements;
- [`PYTHON_EXTENSIONS_1.3.0_CERTIFICATION.txt`](PYTHON_EXTENSIONS_1.3.0_CERTIFICATION.txt) and [`RELEASE_AUDIT_1.3.0.txt`](RELEASE_AUDIT_1.3.0.txt).

The `v110`/`v121`/`v122`/`v130` suffixes in benchmark and regression filenames are **engineering evidence identifiers**, not package versions.

## Performance overview

Performance documentation follows one order deliberately: **first compare normal Python with extension support; only then compare extension modes/backends; finally examine release-to-release implementation overhead**. This prevents an impressive backend-vs-backend result from being mistaken for the benefit of adopting the extension itself.

### 1. Normal Python vs extension support — primary benchmark

The V130 primary benchmark now leads with an intended scaling workload: a **1,024-way source-level router**. Each implementation returns identical values for every one of the 1,024 routes and for a miss before timing begins. Measurements are aggregated across **three fresh CPython 3.13.5 processes** using the same deterministic, uniformly distributed successful-hit traffic.

| 1,024-way router | `if/elif` | `match` | `dict.get` control | Extension switch | vs `if/elif` | vs `match` |
|---|---:|---:|---:|---:|---:|---:|
| Integer keys | 7624.5 ns | 8137.7 ns | **51.8 ns** | 57.0 ns | **133.7×** | **142.7×** |
| String keys | 4906.0 ns | 5180.2 ns | **61.8 ns** | 69.0 ns | **71.1×** | **75.1×** |

This is the main switch value proposition: the extension turns large declarative case-oriented source into **dictionary-class dispatch** instead of paying linear branch depth. The `dict.get` column is deliberately kept beside the headline result. The extension is only about 10–12% more expensive than the hand-built hash-table control on this host; the 70×–143× gains are specifically over native **linear source dispatch**, not over Python's dictionary primitive.

The transformed direct-value switch also keeps executable `co_code` bounded: the recorded 1,024-integer router is **74 B** of executable bytecode versus **17,420 B** for `if/elif` and **19,466 B** for `match` (the route table itself is separate object data, so these numbers are not total-memory claims).

Other extension families remain in the same primary suite:

| Scenario | Normal Python | With extension | Speedup | Control |
|---|---:|---:|---:|---:|
| Small frozen helper / inline | 59.9 ns | **46.1 ns** | **1.33×** | — |
| Three-state explicit FSM / goto | 4333.0 ns | **1652.4 ns** | **2.67×** | structured loop: 1772.0 ns |

Goto is benchmarked against the explicit/generated state-machine formulation it is designed to replace, while the naturally structured loop remains visible as a fairness control. On this sample strict goto is also slightly faster than that structured control, but the project does not generalize that result to algorithms that are naturally expressible as ordinary loops.

The retained 2–1,024-route scaling matrix remains useful for crossover context. Selected integer results:

| Routes | `if/elif` | `match` | `dict.get` | Extension | vs `if/elif` |
|---:|---:|---:|---:|---:|---:|
| 8 | 72.5 ns | 82.4 ns | 43.8 ns | **44.7 ns** | **1.62×** |
| 64 | 451.4 ns | 484.5 ns | 46.2 ns | **45.4 ns** | **9.94×** |
| 256 | 1741.4 ns | 1718.1 ns | **44.6 ns** | 44.7 ns | **38.96×** |
| 1,024 | 7222.9 ns | 7181.4 ns | **45.0 ns** | 50.5 ns | **142.90×** |

The primary benchmark therefore demonstrates the extension on a workload where its architecture matters, while the dictionary and structured-loop controls keep the claims scoped to the actual advantage.

### 2. Improvement between extension modes/backends

Only after establishing the normal-Python baseline should backend selection be considered. Portable and live switch solve different problems: portable mode can collapse direct/template shapes into compact table-backed code, while live mode keeps heterogeneous bodies inline and mutates a verified jump gate at runtime.

Selected real-backend CPython 3.13.5 results from the retained V122 workload matrix:

| Workload | Routes / traffic | Portable | Native live | Native vs portable |
|---|---|---:|---:|---:|
| Dense VM | 64 / random | 250.4 ns | **147.4 ns** | **1.70×** |
| Dense VM | 1,024 / skewed | 330.6 ns | **160.5 ns** | **2.06×** |
| Dense VM | 2,048 / random | 393.3 ns | **159.2 ns** | **2.47×** |
| Integer parser | 256 / skewed | 289.0 ns | **156.5 ns** | **1.85×** |
| State machine | 128 / random | 152.9 ns | **121.1 ns** | **1.26×** |
| HTTP string router | 64 / random | 230.7 ns | 230.0 ns | ~1.00× |
| Sparse protocol IDs | 256 / random | **237.1 ns** | 242.2 ns | 0.98× |
| Heavy server bodies | 256 / random | **406.3 ns** | 427.6 ns | 0.95× |
| Direct/minimal control | 256 / random | **49.7 ns** | 62.2 ns | 0.80× |

A separate **10,000,384-dispatch** 1,024-route VM sample recorded about **329.4 ns portable vs 169.0 ns native**, or **1.95×**. A 10-million-dispatch HTTP loop remained essentially tied (**228.9 ns portable vs 231.2 ns native**). For one router call per request at 64 string routes, the control measured about **135.9 ns portable**, **141.0 ns shared native**, and **246.2 ns thread-local native**.

So native live is a strong mode improvement for repeated in-frame VM/parser-style dispatch, but it is **not** the default answer for ordinary routing. See [Live switch architecture and performance](docs/LIVE_SWITCH.md).

### 3. 1.3.0 implementation improvements

The V130 optimization benchmark is a third-level comparison: it asks how 1.3 changed extension overhead relative to 1.2, not whether extensions beat normal Python.

On the certified host, median transformation construction improved by about **1.15× goto**, **1.13× switch-auto**, **1.24× inline**, **1.07× partial**, and **1.18× explicit specialize**. Monomorphic hotpath warm-up profiling improved from about **1216.7 ns/call to 628.3 ns/call (1.94×)**. Hotpath wrapper construction itself is effectively unchanged.

Automatic root-import qualification has a measured cost (**11.73 ms → 13.14 ms**, about 1.12×) because 1.3 validates bounded runtime assumptions before application transformations begin. Expensive lazy/mutation-sensitive probes remain deferred. Representative steady-state transformed `co_code` fingerprints are byte-identical to 1.2.0, so short-run steady-state timing movement is not advertised as a code-generation speedup.

### How to read the numbers

All measurements are evidence from specific certified hosts, not universal guarantees. CPU, OS, CPython patch/build, adaptive state, key type, traffic distribution, route-body shape, cache state, and surrounding work matter. Prefer this decision order:

1. benchmark **normal Python vs extension support** on the workload you actually care about;
2. if the extension helps, compare its relevant **modes/backends**;
3. use version-to-version optimization numbers only to understand transformation/profiling overhead changes.

See [benchmark methodology](benchmarks/README.md) for reproduction details and negative controls.

## Documentation

- **[Comprehensive guide](docs/COMPREHENSIVE_GUIDE.md)** — complete API, composition, deployment, and troubleshooting guidance.
- **[Runtime qualification](docs/RUNTIME_DIAGNOSTICS.md)** — automatic import-time checks, exhaustive diagnostics, caching, failure behavior, and deployment interpretation.
- **[Live switch architecture and performance](docs/LIVE_SWITCH.md)** — native/ctypes engines, concurrency contracts, benchmark interpretation, and workload selection.
- **[Specialization and partial evaluation](docs/SPECIALIZATION.md)** — `partial`, `specialize`, `hotpath`, guards, profiling bounds, and composition.
- **[Architecture](docs/ARCHITECTURE.md)** — transformation pipeline, invariants, and subsystem responsibilities.
- **[Compatibility](docs/COMPATIBILITY.md)** — interpreter/runtime/build support boundary.
- **[Release process](docs/RELEASING.md)** — reproducible build, artifact verification, and tag/release workflow.
- **[Release notes](docs/RELEASE_NOTES.md)** — release summaries.
- **[Benchmarks](benchmarks/README.md)** — benchmark reproduction and evidence-retention rules.
- **[Changelog](CHANGELOG.md)** — public release changes.
- **[Contributing](CONTRIBUTING.md)** — development expectations and test requirements.
- **[Security policy](SECURITY.md)** — reporting verifier, crash, unsafe-boundary, and native live-gate issues.

## Repository metadata

Canonical repository: **[Karvp/cpython-extensions](https://github.com/Karvp/cpython-extensions)**. Recommended repository settings and topics are tracked in [`.github/REPOSITORY_METADATA.md`](.github/REPOSITORY_METADATA.md).

Recommended GitHub description:

> CPython 3.13 extensions for fast switch/live dispatch, specialization, function inlining, and verified local goto.

## Contributing

Contributions are welcome when they preserve general Python semantics and avoid benchmark- or fixture-specific shortcuts. Performance changes must include correctness coverage and a workload-appropriate benchmark; a microbenchmark win is not sufficient if a broader certified workload regresses.

See [CONTRIBUTING.md](CONTRIBUTING.md).

## Security

Low-level bytecode transformation and explicit live self-modification amplify interpreter/runtime assumptions. Crashes, verifier bypasses, incorrect exception-region handling, unsafe gate writes, or unexpected no-GIL behavior should be treated as security-relevant until triaged.

See [SECURITY.md](SECURITY.md).

## License

The current source and the 1.3.2 release are licensed under the **GNU General Public License v3.0 only (`GPL-3.0-only`)**. See [LICENSE](LICENSE).

This is a strong-copyleft license. Distribution of covered or derivative works must comply with GPLv3's source and licensing obligations. Releases that were already distributed under MPL-2.0 retain those historical license grants; the 1.3.0 relicensing does not revoke them.
