Skip to content

oai-statsig-python-core: Add version 0.29.0 - #2142

Merged
luhenry merged 2 commits into
mainfrom
oai-statsig-python-core
Sep 21, 2026
Merged

luhenry merged 2 commits into
mainfrom
oai-statsig-python-core

Conversation

@luhenry

@luhenry luhenry commented Sep 20, 2026 •

Copy link
Copy Markdown
Member

Compiles statsig-pyo3, the PyO3 binding for statsig's feature-flagging and experimentation server core, into a single cp310-abi3 wheel. Upstream publishes no riscv64 wheel.

Mirrors upstream's build.yml and this repo's build-statsig-python-core.yml, which builds the same crate. This is a separate distribution on its own version line — 0.29.0 shipped ten days before statsig-python-core 0.22.0 — with its crates renamed (statsig-rust becomes oai-statsig-rust).

Differs from upstream

  • Builds from the PyPI sdist — every public tag and branch stops at 0.23.0, so this release's tree is unpublished.
  • Two CARGO_PROFILE_RELEASE_* vars reproduce the python-release profile that keeps symbols in upstream's wheels.

Matrix: one cp310-abi3 wheel — pyo3/abi3-py310 covers every non-free-threaded CPython >= 3.10, and upstream ships no free-threaded wheel.

Testing

  • same as upstream

Note that cibuildwheel builds and tests this wheel under CPython 3.10, the floor of its abi3 range, which is older than anything upstream tests on. That is what surfaced patch 0003 below.

License: Wheel ships the project's ISC licence text, which upstream's wheels omit on every platform.

Patches

  • 0001-tests-wait-for-background-specs-syncs-instead-of-ass.patch — To upstream. Six polling tests ask for a specs_sync_interval_ms of 1, which StatsigOptions now rejects; reproduces off riscv64, against upstream's own published x86_64 wheel.
  • 0002-tests-give-fork_runner.py-a-timeout-a-slow-machine-c.patch — To upstream. 50 SDK initialisations overrun the ten-second subprocess budget; riscv64-only.
  • 0003-fix-read-code.co_qualname-only-where-it-exists-CPyth.patch — To upstream. _find_exposure_callsite reads frame.f_code.co_qualname, which CPython only has from 3.11, while the package declares requires-python >= 3.10 and ships one cp310-abi3 wheel. The error boundary swallows the AttributeError, so callsite logging silently returns "unknown" on 3.10 and the two test_exposure_logging.py callsite tests fail. Falls back to co_name. Not riscv64-specific and not in the Rust crate — the walk is pure Python in py_src/.

Validation

229 passed on riscv64 (cp310, the abi3 floor), no reruns, publish dry-run clean.

Reproduced off riscv64 against upstream's own published oai_statsig_python_core-0.29.0-cp310-abi3-manylinux_2_17_x86_64 wheel: the two callsite tests fail on x86_64 under CPython 3.10 with the identical assertion and stdout warning, and pass under 3.11. An earlier rehearsal of this port ran cp312 and reported 229 passed — cp312 has co_qualname, so it could not have seen this.

oai-statsig-python-core is a second PyPI distribution of statsig-pyo3, the
PyO3/maturin binding for statsig's feature-flagging and experimentation server
core. It runs on its own version line -- 0.29.0 was published on 2026-08-04,
ten days before statsig-python-core 0.22.0 -- and renames the Rust crates it
builds (statsig-rust becomes oai-statsig-rust), so it is a separate package
rather than an alias of the statsig-python-core this repo already serves.

Every public tag and branch of statsig-io/statsig-server-core stops at 0.23.0
(164 tags, 68 releases/* branches, main's workspace version), so 0.24.0 onwards
are cut from a tree that is not published. The PyPI sdist is therefore the only
published form of this release and is the upstream tree the build consumes; it
is self-contained, carrying the Cargo workspace, Cargo.lock, the Python sources
and both test trees the suite needs.

The build otherwise mirrors build-statsig-python-core.yml, which compiles the
same crate: one cp310-abi3 wheel covers every non-free-threaded CPython >= 3.10,
protoc comes from Rocky 10's CRB repo for statsig-grpc's build script, and the
Rust toolchain is installed in-container. Two deviations are specific to this
distribution:

  - CARGO_PROFILE_RELEASE_{DEBUG,STRIP} reproduce the `python-release` profile
    this tree adds on top of `release` (debug = 1, strip = "none"), which is why
    upstream's published wheels ship a 39 MB unstripped extension with symbols
    their production profiles can resolve. Expressing it through the cargo
    profile env vars rather than `--profile python-release` keeps the name out of
    MATURIN_PEP517_ARGS, which would otherwise be inherited by every unrelated
    maturin sdist built in the same container.
  - The sdist carries no licence file, so maturin's default glob beside
    pyproject.toml finds nothing and upstream's wheels ship no licence text on
    any platform despite declaring ISC. The build stages the project's ISC
    licence so ours does, and the test command asserts it landed.

The two patches fix tests that fail on upstream's own published x86_64 wheel,
verified by running the suite against it: StatsigOptions now rejects a
specs_sync_interval_ms below 1000 and falls back to the default, which breaks
six polling tests in test_data_store.py that still ask for 1, and
fork_runner.py's 50 SDK initialisations need more than ten seconds on a riscv64
runner. Both carry forward the equivalent patches this repo already ships for
statsig-python-core 0.22.0 and 0.23.0.

cargo metadata --filter-platform riscv64gc-unknown-linux-gnu resolves all 335
crates, and the native ones are pinned to the same versions the 0.23.0 riscv64
build already compiled: ring 0.17.14, zstd-sys 2.0.13+zstd.1.5.6, prost 0.13.4
and tonic 0.12.3.
@github-actions

github-actions Bot commented Sep 20, 2026 •

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-09-21 08:04 UTC

luhenry added a commit that referenced this pull request Sep 20, 2026
… cannot run

The cp310-abi3 build's test step failed on `co_qualname`: two
test_exposure_logging.py tests asserted the automatic exposure-callsite
metadata and got "unknown", each preceded by "Statsig SDK Error (Python
Bindings): _find_exposure_callsite 'code' object has no attribute
'co_qualname'". 227 passed, 2 failed, and --reruns 3 did not move them.

Nothing to do with riscv64, and nothing to do with the Rust core: the callsite
walk is pure Python in py_src/statsig_python_core/statsig.py, and it reads
`frame.f_code.co_qualname`, an attribute CPython only grew in 3.11. This
package declares requires-python >= 3.10 and ships a single pyo3/abi3-py310
wheel, so 3.10 is in its support range -- and it is exactly the interpreter
cibuildwheel builds and tests `only: cp310-manylinux_riscv64` with, the floor
of the abi3 range. ErrorBoundary.wrap swallows the AttributeError into that
warning and returns None, so _get_exposure_callsite_metadata takes its
"unknown" branch and callsite logging is silently dead on 3.10 everywhere.

Reproduced off riscv64 to prove the point: against upstream's own published
oai_statsig_python_core-0.29.0-cp310-abi3-manylinux_2_17_x86_64 wheel on
x86_64, both tests fail under CPython 3.10 with the identical assertion and
warning, and all 21 tests in the file pass under 3.11. The earlier rehearsal
that reported 229 passed ran on cp312, which has the attribute, so it could
never have seen this.

Patch 0003 falls back to `co_name`, which every supported version has, rather
than skipping the tests: the tests are asserting a real product behaviour that
should work on 3.10. For a module-level function the two names are identical,
and for a method `co_name` only loses the class prefix -- still far better than
"unknown". With all three patches applied the full suite is 229 passed under
CPython 3.10 on x86_64, matching the count the riscv64 job reached.
luhenry added a commit that referenced this pull request Sep 21, 2026
queue: oai-statsig-python-core 0.29.0 - CI green after the co_qualname fix,
PR #2142 still draft.

An abi3 wheel is built and tested under the floor of its abi3 range, which is
routinely older than anything upstream tests on, so the project's own Python
code can use an API that interpreter does not have. oai-statsig-python-core
0.29.0 reads code.co_qualname (CPython 3.11+) while declaring requires-python
>= 3.10 and shipping one cp310-abi3 wheel; it reproduces on x86_64 under 3.10
against upstream's own published wheel, and the cp312 rehearsal that preceded
the port could not have seen it.

Gotcha 96 is the mirror image of this (a wheel compiled on a newer interpreter
breaking on older ones); 469 needs no compiler at all, which is why the write-up
leads with "not the Rust crate, not riscv64" and with grepping the sdist for the
attribute before theorising about the binding layer.
@luhenry
luhenry marked this pull request as ready for review September 21, 2026 07:31
@luhenry
luhenry merged commit dcd7b73 into main Sep 21, 2026
9 checks passed
@luhenry
luhenry deleted the oai-statsig-python-core branch September 21, 2026 07:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant