diff --git a/.github/dependabot.yml b/.github/dependabot.yml index dacc9274..ee6bf5ef 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -35,14 +35,9 @@ updates: - "minor" - "patch" - # ordvec-python's only runtime dep is numpy, and its floor is a DELIBERATE - # broad/legacy-compatibility choice: ordvec is dep-light + abi3-py39, and - # rust-numpy 0.27 supports numpy 1.x AND 2.x at runtime, so we keep numpy - # >=1.20 (usable on Python 3.9 + numpy 1.x legacy stacks). Raising the floor to - # 2.x would drop those users (numpy 2.1+ also dropped Python 3.9) for zero gain - # — ordvec's speed is its Rust kernels; numpy is just the zero-copy array - # container. So `ignore` numpy to stop Dependabot re-proposing the floor bump. - # maturin (build dep) updates and security advisories still flow. + # ordvec-python's only runtime dep is numpy (floor >=2.0, matching abi3-py310 / + # Python >=3.10); maturin is the build dep. Group minor+patch into one PR; + # majors stay separate for manual review. - package-ecosystem: "pip" directory: "/ordvec-python" schedule: @@ -55,9 +50,6 @@ updates: update-types: - "minor" - "patch" - ignore: - # Hold the broad numpy floor (see above); do not auto-raise it. - - dependency-name: "numpy" # fuzz/ is a workspace-EXCLUDED standalone crate (own Cargo.lock), nightly-only # cargo-fuzz tooling. Dev-only surface, low priority — group all, tight PR limit. diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 4d79e04f..fedeb159 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -61,7 +61,7 @@ jobs: # release-python.yml builds one wheel per platform; this matrix makes # sure every one of those targets is *behaviourally* tested (build → # install → pytest), not merely compiled. abi3 means a single wheel - # covers all CPython 3.9+, so the python axis only needs its 3.9↔3.13 + # covers all CPython 3.10+, so the python axis only needs its 3.10↔3.13 # floor/ceiling checked once (linux/x86_64); the other targets exercise # the native code on 3.13. The aarch64 runners (ubuntu-24.04-arm, # macos-latest) are what exercise the NEON kernels through the bindings. @@ -73,7 +73,7 @@ jobs: # x86_64 code is covered by the linux-x86_64 legs (logic) + macos-arm64 # (Mach-O), so the lost test coverage is marginal. include: - - { os: ubuntu-latest, python: "3.9" } # linux x86_64 — abi3 floor + - { os: ubuntu-latest, python: "3.10" } # linux x86_64 — abi3 floor - { os: ubuntu-latest, python: "3.13" } # linux x86_64 — abi3 ceiling - { os: ubuntu-24.04-arm, python: "3.13" } # linux aarch64 — NEON - { os: macos-latest, python: "3.13" } # macOS arm64 — NEON diff --git a/.github/workflows/release-python.yml b/.github/workflows/release-python.yml index d29f289f..5671d6ef 100644 --- a/.github/workflows/release-python.yml +++ b/.github/workflows/release-python.yml @@ -1,6 +1,6 @@ # Publishes the `ordvec` Python bindings (distributed as the `ordvec` wheel) to -# PyPI via Trusted Publishing (OIDC). abi3-py39 => one wheel per platform covers -# CPython 3.9+, so the matrix varies by platform/arch only. +# PyPI via Trusted Publishing (OIDC). abi3-py310 => one wheel per platform covers +# CPython 3.10+, so the matrix varies by platform/arch only. # # maturin runs with working-directory: ordvec-python (matching python.yml) so the # binding's own pyproject.toml/Cargo.toml are the unambiguous build context. @@ -47,7 +47,7 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - name: Build abi3 wheel (covers CPython 3.9+) + - name: Build abi3 wheel (covers CPython 3.10+) uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0 with: working-directory: ordvec-python diff --git a/CHANGELOG.md b/CHANGELOG.md index 102c8f09..be58468d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -_No unreleased changes yet._ +### Changed + +- **Python bindings (`ordvec-python`):** raised the floor to **Python 3.10** and + **numpy 2.0**; the abi3 wheel target moves to `abi3-py310`. Python 3.9 reached + end-of-life (October 2025) and pytest's CVE-2025-71176 fix dropped 3.9 support. + +### Security + +- Remediated **GHSA-6w46-j5rx-g56g** / CVE-2025-71176 (pytest vulnerable tmpdir + handling) by moving the dev/test toolchain to pytest 9.0.3 on Python ≥3.10. ## [0.2.0] - 2026-05-22 diff --git a/ordvec-python/Cargo.toml b/ordvec-python/Cargo.toml index f70faa3f..c2f9a0be 100644 --- a/ordvec-python/Cargo.toml +++ b/ordvec-python/Cargo.toml @@ -18,5 +18,5 @@ crate-type = ["cdylib"] # Alias the core crate as `ordvec_core` so binding code is unambiguous and never # mixes `ordvec::` with the Python-facing `ordvec` package name. ordvec_core = { package = "ordvec", path = ".." } -pyo3 = { version = "0.27.0", features = ["extension-module", "abi3-py39"] } +pyo3 = { version = "0.27.0", features = ["extension-module", "abi3-py310"] } numpy = "0.27.0" diff --git a/ordvec-python/README.md b/ordvec-python/README.md index 4c1f7f2c..6cbfdd38 100644 --- a/ordvec-python/README.md +++ b/ordvec-python/README.md @@ -30,7 +30,7 @@ scores, ids = q.search_asymmetric(np.random.randn(8, 1024).astype(np.float32), k pip install ordvec ``` -Wheels target CPython 3.9+ (abi3). Building from source needs a Rust toolchain +Wheels target CPython 3.10+ (abi3). Building from source needs a Rust toolchain (MSRV 1.89) and [maturin](https://www.maturin.rs/). ## Provenance & license diff --git a/ordvec-python/pyproject.toml b/ordvec-python/pyproject.toml index b5a08ffc..defc182e 100644 --- a/ordvec-python/pyproject.toml +++ b/ordvec-python/pyproject.toml @@ -7,7 +7,7 @@ name = "ordvec" version = "0.2.0" description = "Training-free ordinal & sign quantization for compressed vector retrieval" readme = "README.md" -requires-python = ">=3.9" +requires-python = ">=3.10" license = { text = "MIT OR Apache-2.0" } authors = [ { name = "Nelson Spence" }, @@ -32,7 +32,6 @@ classifiers = [ "Operating System :: MacOS", "Operating System :: Microsoft :: Windows", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", @@ -43,7 +42,7 @@ classifiers = [ ] dependencies = [ - "numpy>=1.20", + "numpy>=2.2", ] [project.urls] diff --git a/ordvec-python/requirements-dev.txt b/ordvec-python/requirements-dev.txt index 227bd840..1ac8850d 100644 --- a/ordvec-python/requirements-dev.txt +++ b/ordvec-python/requirements-dev.txt @@ -1,10 +1,11 @@ # Hash-pinned dev/test deps for ordvec-python CI (pytest, numpy, maturin + # transitive closure). Generated by: uv pip compile --universal --generate-hashes -# --python-version 3.9. Installed via `pip install --require-hashes -r` so the -# OpenSSF Scorecard Pinned-Dependencies check is satisfied. Maintained by Dependabot. +# --python-version 3.10. Installed via `pip install --require-hashes -r +# ordvec-python/requirements-dev.txt` so the OpenSSF Scorecard +# Pinned-Dependencies check is satisfied. Maintained by Dependabot. # This file was autogenerated by uv via the following command: -# uv pip compile /tmp/dev.in --universal --generate-hashes --python-version 3.9 -o /tmp/dev-req.txt +# uv pip compile /tmp/dev.in --universal --generate-hashes --python-version 3.10 -o ordvec-python/requirements-dev.txt colorama==0.4.6 ; sys_platform == 'win32' \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 @@ -13,11 +14,7 @@ exceptiongroup==1.3.1 ; python_full_version < '3.11' \ --hash=sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219 \ --hash=sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598 # via pytest -iniconfig==2.1.0 ; python_full_version < '3.10' \ - --hash=sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7 \ - --hash=sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760 - # via pytest -iniconfig==2.3.0 ; python_full_version >= '3.10' \ +iniconfig==2.3.0 \ --hash=sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730 \ --hash=sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12 # via pytest @@ -37,54 +34,7 @@ maturin==1.13.3 \ --hash=sha256:c00ea6428dea17bf616fe93770837634454b28c2de1a876e42ef8036c616079a \ --hash=sha256:def4a435ea9d2ee93b18ba579dc8c9cf898889a66f312cd379b5e374ec3e3ad6 # via -r /tmp/dev.in -numpy==2.0.2 ; python_full_version < '3.10' \ - --hash=sha256:0123ffdaa88fa4ab64835dcbde75dcdf89c453c922f18dced6e27c90d1d0ec5a \ - --hash=sha256:11a76c372d1d37437857280aa142086476136a8c0f373b2e648ab2c8f18fb195 \ - --hash=sha256:13e689d772146140a252c3a28501da66dfecd77490b498b168b501835041f951 \ - --hash=sha256:1e795a8be3ddbac43274f18588329c72939870a16cae810c2b73461c40718ab1 \ - --hash=sha256:26df23238872200f63518dd2aa984cfca675d82469535dc7162dc2ee52d9dd5c \ - --hash=sha256:286cd40ce2b7d652a6f22efdfc6d1edf879440e53e76a75955bc0c826c7e64dc \ - --hash=sha256:2b2955fa6f11907cf7a70dab0d0755159bca87755e831e47932367fc8f2f2d0b \ - --hash=sha256:2da5960c3cf0df7eafefd806d4e612c5e19358de82cb3c343631188991566ccd \ - --hash=sha256:312950fdd060354350ed123c0e25a71327d3711584beaef30cdaa93320c392d4 \ - --hash=sha256:423e89b23490805d2a5a96fe40ec507407b8ee786d66f7328be214f9679df6dd \ - --hash=sha256:496f71341824ed9f3d2fd36cf3ac57ae2e0165c143b55c3a035ee219413f3318 \ - --hash=sha256:49ca4decb342d66018b01932139c0961a8f9ddc7589611158cb3c27cbcf76448 \ - --hash=sha256:51129a29dbe56f9ca83438b706e2e69a39892b5eda6cedcb6b0c9fdc9b0d3ece \ - --hash=sha256:5fec9451a7789926bcf7c2b8d187292c9f93ea30284802a0ab3f5be8ab36865d \ - --hash=sha256:671bec6496f83202ed2d3c8fdc486a8fc86942f2e69ff0e986140339a63bcbe5 \ - --hash=sha256:7f0a0c6f12e07fa94133c8a67404322845220c06a9e80e85999afe727f7438b8 \ - --hash=sha256:807ec44583fd708a21d4a11d94aedf2f4f3c3719035c76a2bbe1fe8e217bdc57 \ - --hash=sha256:883c987dee1880e2a864ab0dc9892292582510604156762362d9326444636e78 \ - --hash=sha256:8c5713284ce4e282544c68d1c3b2c7161d38c256d2eefc93c1d683cf47683e66 \ - --hash=sha256:8cafab480740e22f8d833acefed5cc87ce276f4ece12fdaa2e8903db2f82897a \ - --hash=sha256:8df823f570d9adf0978347d1f926b2a867d5608f434a7cff7f7908c6570dcf5e \ - --hash=sha256:9059e10581ce4093f735ed23f3b9d283b9d517ff46009ddd485f1747eb22653c \ - --hash=sha256:905d16e0c60200656500c95b6b8dca5d109e23cb24abc701d41c02d74c6b3afa \ - --hash=sha256:9189427407d88ff25ecf8f12469d4d39d35bee1db5d39fc5c168c6f088a6956d \ - --hash=sha256:96a55f64139912d61de9137f11bf39a55ec8faec288c75a54f93dfd39f7eb40c \ - --hash=sha256:97032a27bd9d8988b9a97a8c4d2c9f2c15a81f61e2f21404d7e8ef00cb5be729 \ - --hash=sha256:984d96121c9f9616cd33fbd0618b7f08e0cfc9600a7ee1d6fd9b239186d19d97 \ - --hash=sha256:9a92ae5c14811e390f3767053ff54eaee3bf84576d99a2456391401323f4ec2c \ - --hash=sha256:9ea91dfb7c3d1c56a0e55657c0afb38cf1eeae4544c208dc465c3c9f3a7c09f9 \ - --hash=sha256:a15f476a45e6e5a3a79d8a14e62161d27ad897381fecfa4a09ed5322f2085669 \ - --hash=sha256:a392a68bd329eafac5817e5aefeb39038c48b671afd242710b451e76090e81f4 \ - --hash=sha256:a3f4ab0caa7f053f6797fcd4e1e25caee367db3112ef2b6ef82d749530768c73 \ - --hash=sha256:a46288ec55ebbd58947d31d72be2c63cbf839f0a63b49cb755022310792a3385 \ - --hash=sha256:a61ec659f68ae254e4d237816e33171497e978140353c0c2038d46e63282d0c8 \ - --hash=sha256:a842d573724391493a97a62ebbb8e731f8a5dcc5d285dfc99141ca15a3302d0c \ - --hash=sha256:becfae3ddd30736fe1889a37f1f580e245ba79a5855bff5f2a29cb3ccc22dd7b \ - --hash=sha256:c05e238064fc0610c840d1cf6a13bf63d7e391717d247f1bf0318172e759e692 \ - --hash=sha256:c1c9307701fec8f3f7a1e6711f9089c06e6284b3afbbcd259f7791282d660a15 \ - --hash=sha256:c7b0be4ef08607dd04da4092faee0b86607f111d5ae68036f16cc787e250a131 \ - --hash=sha256:cfd41e13fdc257aa5778496b8caa5e856dc4896d4ccf01841daee1d96465467a \ - --hash=sha256:d731a1c6116ba289c1e9ee714b08a8ff882944d4ad631fd411106a30f083c326 \ - --hash=sha256:df55d490dea7934f330006d0f81e8551ba6010a5bf035a249ef61a94f21c500b \ - --hash=sha256:ec9852fb39354b5a45a80bdab5ac02dd02b15f44b3804e9f00c556bf24b4bded \ - --hash=sha256:f15975dfec0cf2239224d80e32c3170b1d168335eaedee69da84fbe9f1f9cd04 \ - --hash=sha256:f26b258c385842546006213344c50655ff1555a9338e2e5e02a0756dc3e803dd - # via -r /tmp/dev.in -numpy==2.2.6 ; python_full_version == '3.10.*' \ +numpy==2.2.6 ; python_full_version < '3.11' \ --hash=sha256:038613e9fb8c72b0a41f025a7e4c3f0b7a1b5d768ece4796b674c8f3fe13efff \ --hash=sha256:0678000bb9ac1475cd454c6b8c799206af8107e310843532b04d49649c717a47 \ --hash=sha256:0811bb762109d9708cca4d0b13c4f67146e3c3b7cf8d34018c722adb2d957c84 \ @@ -227,11 +177,7 @@ pygments==2.20.0 \ --hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \ --hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 # via pytest -pytest==8.4.2 ; python_full_version < '3.10' \ - --hash=sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01 \ - --hash=sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79 - # via -r /tmp/dev.in -pytest==9.0.3 ; python_full_version >= '3.10' \ +pytest==9.0.3 \ --hash=sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9 \ --hash=sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c # via -r /tmp/dev.in