[package]
name = "s4-codec-py"
# v0.8.5 #82 C-2: inherit version from `[workspace.package]` so PyPI publishes
# under the workspace's actual semver (was hard-coded "0.1.0", which would
# have shipped a misleadingly-pre-release wheel for a v0.8.x workspace).
version.workspace = true
# Edition 2021 (not 2024) — PyO3 0.22's proc-macros generate code that
# trips edition-2024's `unsafe-op-in-unsafe-fn` hard-error. Upgrading to
# pyo3 0.23+ would let us go to 2024, but 0.22 is the latest stable line
# documented in the issue and the rest of the workspace's pin.
edition = "2021"
rust-version.workspace = true
license.workspace = true
authors.workspace = true
repository.workspace = true
homepage.workspace = true
documentation.workspace = true
readme = "README.md"
description = "Python (pyo3) bindings for s4-codec — in-process CPU compression (zstd + gzip) for ML / ETL pipelines. GPU codecs are not exposed in Python in v1.0; route GPU workloads through the s4 server gateway."

# NOTE: we deliberately do NOT inherit `[workspace.lints]` (which sets
# `unsafe_code = "deny"`) — the `pyo3` proc-macros expand to `unsafe`
# blocks (FFI into CPython is inherently unsafe), so denying unsafe code
# here would block compilation. The unsafe surface is confined to the
# pyo3-generated glue; our own code stays safe Rust.
[lints.rust]
unsafe_code = "allow"
# v0.8.5 #85: pyo3 0.22's `create_exception!` macro expands to
# `#[cfg(feature = "gil-refs")]` inside *our* crate (not pyo3's), so rustc's
# check-cfg lint complains it's not in OUR features list. The feature lives
# in pyo3's manifest; we just have to tell our own check-cfg about it.
# Removable once pyo3 0.23+ drops the gil-refs gate.
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(feature, values("gil-refs"))'] }

[lints.clippy]
# pyo3 0.22's `#[pymethods]` macro expands `PyResult` return types to
# include a `.into()` that's a no-op when the function already returns
# `PyResult<T>` directly. Filing this against pyo3 upstream isn't worth
# blocking the workspace's `-D warnings` clippy gate on.
useless_conversion = "allow"

[lib]
name = "s4_codec"
crate-type = ["cdylib"]

[features]
default = []
# Forward to s4-codec/nvcomp-gpu. Requires CUDA toolchain at build time and
# a CUDA-capable GPU at runtime. See README.md for details.
nvcomp-gpu = ["s4-codec-rs/nvcomp-gpu"]

[dependencies]
# `extension-module` tells PyO3 to *not* link libpython into the cdylib
# (the Python interpreter that loads the .so provides those symbols at
# runtime). This is what makes the cdylib build cleanly on a CI runner
# that has no Python development package installed — `cargo check` /
# `cargo build` produce a .so that's only meant to be loaded by Python,
# never executed standalone.
#
# `abi3-py39` opts into the CPython stable ABI ≥ 3.9, which means a single
# wheel works on any CPython 3.9..=latest *and* `cargo check` doesn't
# bind to the host's Python minor version (so a runner with bleeding-edge
# Python 3.14 doesn't trip PyO3 0.22's "newer than PyO3's maximum
# supported version" guard).
pyo3 = { version = "0.24", features = ["extension-module", "abi3-py39"] }
# Renamed import (`s4_codec_rs` instead of the crate's natural `s4_codec`)
# so the symbol doesn't collide with our own cdylib's library name
# (`s4_codec`, dictated by the Python module name).
s4-codec-rs = { package = "s4-codec", path = "../s4-codec", version = "1" }
bytes = { workspace = true }
tokio = { workspace = true }
# v1.1 s4fs: expose `crc32c(bytes) -> int` so the pure-Python fsspec
# reader (python/s4fs) can verify `passthrough` frame payloads (the only
# codec whose payload integrity isn't checked by a decompressor).
crc32c = { workspace = true }

[dev-dependencies]
# v0.8.5 #82: parse `CARGO_PKG_VERSION` in `tests/version_matches_workspace.rs`
# to assert the binding's version is a real workspace-inherited semver
# (>= 0.8.0), not the legacy hard-coded "0.1.0" (which CARGO_PKG_VERSION
# alone can't disambiguate from a deliberate pre-release).
semver = "1"
