Summary
bjdata cannot be installed on PyPy via a normal pip install bjdata using PYBJDATA_NO_EXTENSION=1. The install fails while building the numpy build dependency from source — even though bjdata deliberately skips its C extension on PyPy and runs as pure Python there. numpy is pulled in unconditionally at build time and is, for the PyPy/pure-Python build, entirely unnecessary.
This is bjdata 0.6.6 (latest on PyPI).
What happens
On PyPy 3.11, pip install bjdata (building from the PyPI sdist, since no wheels are published) does:
Collecting bjdata
Downloading bjdata-0.6.6.tar.gz
Installing build dependencies ...
Using cached oldest_supported_numpy-...
Collecting numpy==1.23.2 (from oldest-supported-numpy)
Downloading numpy-1.23.2.tar.gz
Building wheel for numpy (pyproject.toml): ... error <-- fails here
ERROR: Failed to build 'bjdata' when installing build dependencies for bjdata
numpy==1.23.2 has no PyPy 3.11 wheel, so pip tries to compile that (old)
numpy from source under PyPy, which fails. The build never even reaches
bjdata's own setup.py.
Root cause
Two unconditional references to numpy force this, both of which are dead weight for the PyPy/pure-Python build:
-
pyproject.toml — numpy is an unconditional PEP 517 build requirement:
[build-system]
requires = ["setuptools>=40", "wheel", "oldest-supported-numpy"]
build-backend = "setuptools.build_meta"
Under build isolation, pip installs oldest-supported-numpy before running
setup.py. On PyPy that resolves to numpy==1.23.2 (no PyPy wheel) → source
build → failure. (oldest-supported-numpy is also deprecated upstream in
favor of building against the numpy 2.0 ABI.)
-
setup.py — numpy is imported at module top level:
from numpy import get_include as numpy_get_include # top of setup.py
...
BUILD_EXTENSIONS = (
"PYBJDATA_NO_EXTENSION" not in os.environ and python_implementation() != "PyPy"
)
...
ext_modules=([Extension("_bjdata", ..., include_dirs=[..., numpy_get_include()])]
if BUILD_EXTENSIONS else [])
BUILD_EXTENSIONS is always False on PyPy, so the _bjdata C extension
is never built and numpy_get_include() is never used there — yet the
top-level from numpy import get_include means setup.py cannot even be
imported without numpy present.
So on PyPy, bjdata is pure Python and needs no compiler and no numpy — but the packaging requires numpy at build time anyway, and the only numpy it can find (oldest-supported-numpy → 1.23.2) is unbuildable on PyPy.
Proposed fix (two small changes)
-
setup.py: make the numpy import lazy / conditional on actually building
the extension, e.g. import get_include only inside the if BUILD_EXTENSIONS
branch instead of at module top level. Then setup.py needs numpy only when
the C extension is actually compiled (CPython, extension enabled).
-
pyproject.toml: drop the deprecated oldest-supported-numpy and require
a modern numpy that ships PyPy wheels, ideally gated so it is only required
where the extension is built, e.g.:
[build-system]
requires = [
"setuptools>=40",
"wheel",
"numpy>=2.0.0; platform_python_implementation == 'CPython'",
]
build-backend = "setuptools.build_meta"
(numpy 2.x publishes PyPy 3.11 wheels, so even an unconditional numpy>=2.0.0 would already let the build succeed on PyPy.)
With either/both, pip install bjdata would succeed on PyPy as a pure-Python package, with no numpy build.
(Optionally: publishing binary wheels for bjdata would also help — currently PyPI has sdist only, so every install builds from source.)
Impact / where we hit this
Autobahn|Python provides a WAMP "ubjson" serializer and is migrating it from the unmaintained py-ubjson to the maintained bjdata (issue crossbario/autobahn-python#1849, PR #1855). We expose bjdata via an optional autobahn[serialization] extra. Our CI's PyPy 3.11 job fails to install it for exactly the reason above. Because the failure is in
bjdata's build dependencies (before setup.py runs), setting PYBJDATA_NO_EXTENSION=1 does not help.
As a workaround on our side we are restricting the bjdata dependency to CPython, which means the UBJSON serializer is unavailable on PyPy. We'd love to relax that once bjdata installs cleanly on PyPy.
Thanks for maintaining bjdata!
Summary
bjdatacannot be installed on PyPy via a normalpip install bjdatausingPYBJDATA_NO_EXTENSION=1. The install fails while building the numpy build dependency from source — even thoughbjdatadeliberately skips its C extension on PyPy and runs as pure Python there. numpy is pulled in unconditionally at build time and is, for the PyPy/pure-Python build, entirely unnecessary.This is
bjdata0.6.6 (latest on PyPI).What happens
On PyPy 3.11,
pip install bjdata(building from the PyPI sdist, since no wheels are published) does:numpy==1.23.2has no PyPy 3.11 wheel, so pip tries to compile that (old)numpy from source under PyPy, which fails. The build never even reaches
bjdata's ownsetup.py.Root cause
Two unconditional references to numpy force this, both of which are dead weight for the PyPy/pure-Python build:
pyproject.toml— numpy is an unconditional PEP 517 build requirement:Under build isolation, pip installs
oldest-supported-numpybefore runningsetup.py. On PyPy that resolves tonumpy==1.23.2(no PyPy wheel) → sourcebuild → failure. (
oldest-supported-numpyis also deprecated upstream infavor of building against the numpy 2.0 ABI.)
setup.py— numpy is imported at module top level:BUILD_EXTENSIONSis alwaysFalseon PyPy, so the_bjdataC extensionis never built and
numpy_get_include()is never used there — yet thetop-level
from numpy import get_includemeanssetup.pycannot even beimported without numpy present.
So on PyPy,
bjdatais pure Python and needs no compiler and no numpy — but the packaging requires numpy at build time anyway, and the only numpy it can find (oldest-supported-numpy→ 1.23.2) is unbuildable on PyPy.Proposed fix (two small changes)
setup.py: make the numpy import lazy / conditional on actually buildingthe extension, e.g. import
get_includeonly inside theif BUILD_EXTENSIONSbranch instead of at module top level. Then
setup.pyneeds numpy only whenthe C extension is actually compiled (CPython, extension enabled).
pyproject.toml: drop the deprecatedoldest-supported-numpyand requirea modern numpy that ships PyPy wheels, ideally gated so it is only required
where the extension is built, e.g.:
(numpy 2.x publishes PyPy 3.11 wheels, so even an unconditional
numpy>=2.0.0would already let the build succeed on PyPy.)With either/both,
pip install bjdatawould succeed on PyPy as a pure-Python package, with no numpy build.(Optionally: publishing binary wheels for
bjdatawould also help — currently PyPI has sdist only, so every install builds from source.)Impact / where we hit this
Autobahn|Python provides a WAMP "ubjson" serializer and is migrating it from the unmaintained
py-ubjsonto the maintainedbjdata(issue crossbario/autobahn-python#1849, PR #1855). We exposebjdatavia an optionalautobahn[serialization]extra. Our CI's PyPy 3.11 job fails to install it for exactly the reason above. Because the failure is inbjdata's build dependencies (beforesetup.pyruns), settingPYBJDATA_NO_EXTENSION=1does not help.As a workaround on our side we are restricting the
bjdatadependency to CPython, which means the UBJSON serializer is unavailable on PyPy. We'd love to relax that oncebjdatainstalls cleanly on PyPy.Thanks for maintaining
bjdata!