Latest Results
Ship prebuilt abi3 R-tree wheels so users don't need a C compiler (#57)
* prototype: ship prebuilt abi3 rtree modules, keep witty as fallback
* drop Python 3.10; abi3 build is now unconditional
* switch build backend to setuptools; merge _specs into _codegen
* ci: drop 3.10, test the built wheel instead of an editable install
* ci: build release wheels with cibuildwheel; prebuild LineRTree too
* ci: update macOS runner version to 15 for compatibility
* ci: pick the right linux wheel via --find-links instead of a glob
* always prebuild both tree classes; drop the PREBUILT_LINE_TREES flag
* address review: setup.py __main__ guard, C-core depends, stronger compiler probe, README
- guard setup() so cythonize's worker processes don't re-run the build
- declare rtree.c/h + config.h as Extension depends, so edits to the vendored
C core actually rebuild the prebuilt modules instead of silently going stale
- probe with #include <Python.h> (via get_python_inc) so a box with cc but no
dev headers is caught before the real build, and guard the distutils import
- package-data patterns needed a src/ prefix to match the vendored C at all
- rewrite README's Cross-Platform Support section; it still told users they
needed a compiler
- reword comments that implied witty/Cheetah were optional: they remain
install-time deps, they're just never invoked on the prebuilt path
* PEP 639 license, lazy metadata builds, env-flag parsing; restore eager __init__
- license = "MIT" + license-files, drop the deprecated classifier
- skip rendering/cythonizing 32 variants for metadata-only commands, matched on
recognized command names so 'sdist bdist_wheel' still builds
- SPATIAL_GRAPH_NO_PREBUILT=0 disabled prebuilding, since any non-empty string
is truthy; both readers now share env_flag() so they cannot diverge
- the lazy __init__ broke the API docs: griffe inspects __dict__, so the seven
deferred names vanished (527 -> 414 documented symbols). Import witty and
Cheetah lazily inside _graph.graph_base instead, which keeps the 35ms import
and restores full docs
* rename env_flag to env_enabled
* review: stop setup.py importing the package at module scope
Two follow-ups from review.
setup.py imported `spatial_graph._rtree._naming` at module scope (after
inserting src/ on sys.path), which pulled the whole package -- and with
the eager __init__, the graph half too -- into every setuptools command.
A single module-scope third-party import anywhere in the package would
then break the entire build system, `sdist` and `egg_info` included,
with a traceback pointing at the package rather than at setup.py.
Verified: adding `import witty` to graph_base.py made `build --sdist`
fail at get_requires_for_build_sdist.
The import now happens only where the package is genuinely needed, via
`_src_on_path()`: in `prebuilt_extensions()`, and in `should_prebuild()`
after the `metadata_only()` early return. Metadata-only commands no
longer import the package at all -- `spatial_graph` stays out of
sys.modules -- while `env_enabled` remains shared with the runtime, so
the build and the lookup still cannot read the same variable
differently.
tests/test_prebuilt.py was the one consumer not converted to
`env_enabled`, so SPATIAL_GRAPH_REQUIRE_PREBUILT=0 would skip
prebuilding at build time yet still assert it at test time.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* correct three inaccurate claims; mirror build_ext's include dirs in the probe
- can_compile()'s comment justified get_python_inc with a venv/sysconfig
mechanism that does not exist; replaced with the real reason, and the probe
now also passes the platform-specific include dir as build_ext does, since
that is where pyconfig.h can live and a false negative there silently emits
a pure-Python wheel
- _naming.py claimed installs may have neither Cheetah nor witty; both are
unconditional dependencies, and it contradicted _codegen.py
- README implied LineRTree is prebuilt for int64/uint64 items; its items are
node pairs, so the prebuilt set is int64[2]/uint64[2]
* assert no runtime compilation directly, instead of simulating a witty-less install
Blocking witty.compile_cython states the actual property -- prebuilt variants
must not invoke the compiler -- in the environment users really get, since
witty is an unconditional dependency and will always be installed. The old CI
step instead simulated its absence, which can never happen, and needed
--no-deps/--no-index gymnastics plus a second install to undo them.
The check now lives in the test suite, so it runs on every OS and Python in
the test matrix rather than only in one Linux job, and it covers all 32
variants. test-abi3-wheel keeps its remaining job: proving one cp311 wheel we
actually publish runs on 3.11-3.14.
* simplify the wheel install; harden the deploy job before its first run
Installing by package name would have resolved spatial-graph from PyPI: our
version is a dev release and resolvers exclude pre-releases by default, so
'uv pip install --find-links wheelhouse spatial-graph' silently installs the
last real release (verified: it picked 0.0.7). Naming the manylinux wheel is
both simpler than pinning the parsed version and immune to that.
deploy has never executed, and only ever will on a tag. Give it a checkout
rather than assume action-gh-release works without one, and name build-wheels
in needs instead of relying on test-abi3-wheel to pull it in.
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Ship prebuilt abi3 R-tree wheels so users don't need a C compiler (#57)
* prototype: ship prebuilt abi3 rtree modules, keep witty as fallback
* drop Python 3.10; abi3 build is now unconditional
* switch build backend to setuptools; merge _specs into _codegen
* ci: drop 3.10, test the built wheel instead of an editable install
* ci: build release wheels with cibuildwheel; prebuild LineRTree too
* ci: update macOS runner version to 15 for compatibility
* ci: pick the right linux wheel via --find-links instead of a glob
* always prebuild both tree classes; drop the PREBUILT_LINE_TREES flag
* address review: setup.py __main__ guard, C-core depends, stronger compiler probe, README
- guard setup() so cythonize's worker processes don't re-run the build
- declare rtree.c/h + config.h as Extension depends, so edits to the vendored
C core actually rebuild the prebuilt modules instead of silently going stale
- probe with #include <Python.h> (via get_python_inc) so a box with cc but no
dev headers is caught before the real build, and guard the distutils import
- package-data patterns needed a src/ prefix to match the vendored C at all
- rewrite README's Cross-Platform Support section; it still told users they
needed a compiler
- reword comments that implied witty/Cheetah were optional: they remain
install-time deps, they're just never invoked on the prebuilt path
* PEP 639 license, lazy metadata builds, env-flag parsing; restore eager __init__
- license = "MIT" + license-files, drop the deprecated classifier
- skip rendering/cythonizing 32 variants for metadata-only commands, matched on
recognized command names so 'sdist bdist_wheel' still builds
- SPATIAL_GRAPH_NO_PREBUILT=0 disabled prebuilding, since any non-empty string
is truthy; both readers now share env_flag() so they cannot diverge
- the lazy __init__ broke the API docs: griffe inspects __dict__, so the seven
deferred names vanished (527 -> 414 documented symbols). Import witty and
Cheetah lazily inside _graph.graph_base instead, which keeps the 35ms import
and restores full docs
* rename env_flag to env_enabled
* review: stop setup.py importing the package at module scope
Two follow-ups from review.
setup.py imported `spatial_graph._rtree._naming` at module scope (after
inserting src/ on sys.path), which pulled the whole package -- and with
the eager __init__, the graph half too -- into every setuptools command.
A single module-scope third-party import anywhere in the package would
then break the entire build system, `sdist` and `egg_info` included,
with a traceback pointing at the package rather than at setup.py.
Verified: adding `import witty` to graph_base.py made `build --sdist`
fail at get_requires_for_build_sdist.
The import now happens only where the package is genuinely needed, via
`_src_on_path()`: in `prebuilt_extensions()`, and in `should_prebuild()`
after the `metadata_only()` early return. Metadata-only commands no
longer import the package at all -- `spatial_graph` stays out of
sys.modules -- while `env_enabled` remains shared with the runtime, so
the build and the lookup still cannot read the same variable
differently.
tests/test_prebuilt.py was the one consumer not converted to
`env_enabled`, so SPATIAL_GRAPH_REQUIRE_PREBUILT=0 would skip
prebuilding at build time yet still assert it at test time.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* correct three inaccurate claims; mirror build_ext's include dirs in the probe
- can_compile()'s comment justified get_python_inc with a venv/sysconfig
mechanism that does not exist; replaced with the real reason, and the probe
now also passes the platform-specific include dir as build_ext does, since
that is where pyconfig.h can live and a false negative there silently emits
a pure-Python wheel
- _naming.py claimed installs may have neither Cheetah nor witty; both are
unconditional dependencies, and it contradicted _codegen.py
- README implied LineRTree is prebuilt for int64/uint64 items; its items are
node pairs, so the prebuilt set is int64[2]/uint64[2]
* assert no runtime compilation directly, instead of simulating a witty-less install
Blocking witty.compile_cython states the actual property -- prebuilt variants
must not invoke the compiler -- in the environment users really get, since
witty is an unconditional dependency and will always be installed. The old CI
step instead simulated its absence, which can never happen, and needed
--no-deps/--no-index gymnastics plus a second install to undo them.
The check now lives in the test suite, so it runs on every OS and Python in
the test matrix rather than only in one Linux job, and it covers all 32
variants. test-abi3-wheel keeps its remaining job: proving one cp311 wheel we
actually publish runs on 3.11-3.14.
* simplify the wheel install; harden the deploy job before its first run
Installing by package name would have resolved spatial-graph from PyPI: our
version is a dev release and resolvers exclude pre-releases by default, so
'uv pip install --find-links wheelhouse spatial-graph' silently installs the
last real release (verified: it picked 0.0.7). Naming the manylinux wheel is
both simpler than pinning the parsed version and immune to that.
deploy has never executed, and only ever will on a tag. Give it a checkout
rather than assume action-gh-release works without one, and name build-wheels
in needs instead of relying on test-abi3-wheel to pull it in.
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Latest Branches
+30%
tlambert03:prebuilt-abi3-proto 0%
pre-commit-ci-update-config 0%
© 2026 CodSpeed Technology