Website: https://post-py.org/
This repository is postpyc, the POST Python Compiler — the reference implementation of the POST Python standard (Performance Optimized Statically Typed Python) — together with the standard's specification.
The goal is to define a clear, portable subset of Python that can be compiled ahead of time to native code, in the spirit of tools like Numba, Cython, Codon, Pythran, taichi-lang, and related compiled Python variants. A POST Python source file is still valid Python, but the language subset, type vocabulary, array ABI, and vectorized kernel model are specified so multiple compiler implementations can target the same standard.
The current specification is a draft. See docs/spec.md. Distribution policy for compiled packages (source-only PyPI, split native packages for conda/pixi/nix) lives in docs/distribution.md.
This repository contains:
- A draft language specification for POST Python 0.2.
- A structural checker for the compilable Python subset.
- A typed frontend that lowers Python AST into a small IR.
- A C99 backend that emits native shared-library code.
- A
postyptype vocabulary for scalar dtypes, arrays, shapes, layouts, dataframes, and series. - Numba-shaped
@vectorizeand@guvectorizedecorators for NumPy-compatible ufunc-style kernels. - Tests for checker behavior, compiler lowering, array layout/ABI behavior, and vectorized decorators.
A companion library, ppspecial,
reimplements scipy.special in pure POST Python and serves as the standard's
flagship real-world consumer. It is the first of a family of pp* packages
rebuilding SciPy one subpackage at a time — the project's primary proving
ground. See postscipy-roadmap.md for the package map,
sequencing, and the compiler-capability matrix that work feeds.
POST Python is not production-ready. It is a reference implementation and design vehicle for the standard.
POST Python code uses ordinary Python syntax with explicit type annotations:
from postpyc import vectorize from postyp import Float64 from postpyc.math import exp @vectorize def gaussian(x: Float64, mu: Float64, sigma: Float64) -> Float64: z: Float64 = (x - mu) / sigma return exp(-0.5 * z * z) / (sigma * 2.5066282746310002)
Generalized vectorized kernels use Numba-style @guvectorize with output
parameters:
from postpyc import guvectorize from postyp import Array, Float64 @guvectorize([], "(n),(n)->()") def dot(a: Array[Float64], b: Array[Float64], out: Array[Float64]) -> None: result: Float64 = 0.0 for i in range(len(a)): result += a[i] * b[i] out[0] = result
docs/spec.md Draft language specification
postyp-dist/postyp.py Type vocabulary (published separately as `postyp`)
postpyc/checker.py Structural subset checker
postpyc/compiler/ AST frontend, IR, and C backend
postpyc/ufunc.py @vectorize and @guvectorize runtime wrappers
postpyc/build.py POST Python to C99 to shared-library build helper
postpyc/math.py Typed scalar math wrappers
examples/ Example POST Python source files
tests/ Reference test suite
POST Python ships as a regular Python package and can be installed with either
pip or pixi. Both paths install two importable units:
the postpyc package and the postyp type module.
A working C compiler (cc, clang, or gcc) is required to compile POST
Python sources to native code. The pixi environment installs one for you;
under pip you need a system compiler.
python -m pip install postpyc
The distribution is named postpyc (postpython and postpy on PyPI
belong to unrelated projects, and PyPI's name-similarity rule blocks
post-py). The import name matches: import postpyc. The type vocabulary
is published separately as postyp
and installed automatically as a dependency.
From a local checkout:
python -m pip install ./postyp-dist .For development — including pytest, numpy, and narwhals — install the
dev extra in editable mode:
python -m pip install -e ".[dev]"Run the test suite:
pytest
pyproject.toml contains a [tool.pixi] workspace. Pixi resolves
conda-forge dependencies (Python, NumPy, narwhals, a C compiler) and installs
POST Python itself as an editable PyPI package, so any source changes are
picked up immediately.
pixi install # default environment pixi install -e dev # development environment with pytest etc.
Run a defined task:
pixi run -e dev test # pytest tests/ pixi run -e dev check FILE.py # postpyc check on a source file pixi run -e dev build-example # python examples/build_shared_lib.py
Or drop into a shell with the environment activated:
pixi shell -e dev
After installing (or with pixi shell -e dev active), build one of the
examples to a native shared library:
python examples/build_shared_lib.py
Or call the build helper directly:
from postpyc.build import build_file lib_path = build_file("examples/gaussian.py") print(lib_path)
- Python syntax, static subset: POST Python files remain
.pyfiles, but unsupported dynamic constructs are rejected by the checker or compiler. - Typed native values: scalar types such as
Float64,Int64, andBoolare fixed-width native dtypes. - Array ABI: arrays carry shape, byte-stride, layout, and offset metadata so C-order, Fortran-order, and strided views can be represented portably.
- Numba-shaped vectorization:
@vectorizedefines scalar elementwise kernels;@guvectorizedefines kernels over core dimensions with explicit output arrays. - Modular standard: conformance is organized into profiles such as POST Core, POST Array, POST DataFrame, POST Ufunc ABI, CPython Extension, and Accelerator Extension.
- Interpreter compatibility: decorators provide interpreted-mode behavior so examples can be run under CPython while the compiler path matures.
The implementation is intentionally small and incomplete. Some features described in the specification are not lowered yet and should produce explicit unsupported-feature diagnostics rather than being silently accepted. The reference compiler currently emits C99 and shared libraries; broader executable, extension-module, dataframe, and accelerator support are still design and implementation work.
This project is useful as both a language design artifact and a testbed for compiler behavior. Good contributions include:
- Tightening the specification.
- Adding conformance tests.
- Improving diagnostics for unsupported-but-valid POST Python features.
- Expanding array layout and ABI coverage.
- Building out examples that stress native-code lowering.
- Comparing behavior against existing compiled Python tools.
The most important rule for the reference implementation is simple: reject unsupported semantics clearly rather than accepting code and changing behavior.