Conversation
Restore Windows wheels and fix the issues found reviewing the release.
Windows builds
- setup.py fed GCC/Clang flags ("-O2", "-march=native") to MSVC, which only
emits D9002/LNK4044 "unknown option" diagnostics, so every Windows wheel we
ever shipped was built unoptimised. Use /O2 on Windows and split LINK_FLAGS.
- Drop the VS2019 Build Tools download. windows-latest already ships VS2022
(MSVC 14.3x), which is the minimum for CPython 3.13+ extensions; installing
the older VC 14.0/14.1 toolsets alongside it is the most likely cause of the
3.13 breakage in 0.0.219 that eventually cost us the whole job in 0.0.233.
- Verify wheels contain both native extensions and are tagged win_amd64,
rather than trusting a build that "succeeded".
- Cover Windows in the regression suite so this fails in CI, not at release.
Release workflow
- Replace ~100 lines of per-artifact staging with one pattern: dist-* download.
The duplication is why macOS cp314t went missing from 0.0.243 unnoticed.
- Remove the free-threaded (3.14t) builds.
- Remove the dead raspberrypi cibuildwheel job. It last produced an aarch64
wheel in February 2024 and carried its own independent PyPI publish step.
- Remove the Rust toolchain steps and setuptools_rust; there is no Rust here.
nbytes
- DataFrame(rows=..., schema=...) reported 0 bytes forever: _nbytes was seeded
to 0 unconditionally, and the len()==0 guard was dropped in 0.0.144.
- Polling nbytes() while appending was quadratic (32k rows took 25s; 128k
extrapolates to ~7 minutes) and 0.0.243's fix instead paid a full msgpack
serialisation on every append. Track a watermark so nbytes() sizes only the
rows appended since the last call: append does no serialisation and repeated
polling stays linear. 32k rows: 25.050s -> 0.043s.
- Row.nbytes() no longer enforces MAXIMUM_RECORD_SIZE. Sizing a frame must not
fail because one row is too big to serialise; as_bytes still refuses.
JSON output
- "remove orjson" (0.0.233) swapped orjson.dumps for json.dumps in both
Row.as_json and the JSONB write path, silently adding ", "/": " padding to
bytes we store. Restore compact separators in both.
- Use simdjson for loads only; its dumps delegates to stdlib without separator
control, so writes through it would reintroduce the padding.
sdist
- The sdist shipped without requirements.txt, so setup.py fell back to
egg-info/requires.txt, whose [simdjson] extras section is not a valid
requirement specifier. pip install from sdist failed outright on any platform
without a wheel. Add MANIFEST.in and stop parsing extras sections.
Other
- Cache the PyArrow type map instead of rebuilding it per column per call;
2.7x faster schema conversion, ~17% off .arrow() for small wide frames.
Output verified identical across all 52 type/nullable/precision cases.
- Guard optional integration imports with pytest.importorskip. opteryx and
polars have no Windows or 3.14 wheels and these only back optional tests.
- Add 3.14 to the regression matrix; we ship 3.14 wheels but never tested them.
- Remove varchar_array.pyx (not built, not imported) and the disabled macOS
workflow.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Restore Windows wheels, and fix what turned up on the way
Windows wheels stopped at
0.0.230. This restores them and fixes the issues found reviewing the release path.Why Windows builds stopped
PyPI and git together tell the story:
c1d0937dropped cp313 from the Windows matrix.0.0.230on PyPI confirms it:win_amd64for cp39/310/311/312, no cp313. Never fixed, just excluded.9ed6ec0/96d3854added 3.14/3.14t and set the Windows matrix back to['3.9'…'3.13','3.14','3.14t'], re-including the known-broken 3.13. Sinceuploadhadneeds: build-windows, that job failing blocked the whole publish.98ed6f0(0.0.233) deleted the Windows job — and that same day carries seven version bumps (0.0.233→0.0.239).The underlying build bug:
setup.pyfed["-O2", "-march=native"]to MSVC, which only emitsD9002/LNK4044"unknown option" diagnostics — every Windows wheel we ever shipped was built unoptimised. Combined with downloading VS2019 Build Tools (incl. VC 14.0/14.1) onto a runner that already has VS2022, that's the most likely cp313 breakage: CPython 3.13+ extensions need MSVC 14.3x.Changes
Windows — MSVC
/O2and splitLINK_FLAGS; VS2019 download deleted; wheels verified to contain both native extensions and carry thewin_amd64tag; Windows added to the regression suite so this fails in CI, not at release.Release workflow — ~100 lines of per-artifact staging replaced with one
pattern: dist-*download (that duplication is why macOS cp314t went missing from 0.0.243 unnoticed); free-threaded 3.14t removed; the deadraspberrypijob removed (last aarch64 wheel: Feb 2024, and it carried its own independent PyPI publish); Rust toolchain andsetuptools_rustremoved — there is no Rust here.nbytes()— two bugs, one fix:DataFrame(rows=..., schema=...)reported 0 bytes forever; thelen()==0guard was dropped in0.0.144(2024).nbytes()while appending was quadratic.0.0.243's fix instead paid a full msgpack serialise on every append. Now a watermark sizes only rows appended since the last call — no serialisation inappend, linear polling.4× rows → 16× time. 128k extrapolates to ~7 minutes; it is now 0.225s.
Row.nbytes()also no longer enforcesMAXIMUM_RECORD_SIZE— sizing a frame must not fail because one row is too big to serialise (arrow()handles it fine).as_bytesstill refuses. Verifiednbytes() == len(as_bytes)exactly for normal rows.JSON output —
133e940("remove orjson") swappedorjson.dumps→json.dumpsin bothRow.as_jsonand the JSONB write path, silently adding", "/": "padding to bytes we store. Compact separators restored in both. simdjson is now used forloadsonly — itsdumpsdelegates to stdlib without separator control and would reintroduce the padding.sdist was unbuildable — it shipped without
requirements.txt, sosetup.pyfell back toegg-info/requires.txt, whose[simdjson]extras section is not a valid requirement specifier:pip install orsofailed outright on any platform without a wheel. AddedMANIFEST.in; fallback no longer parses extras sections. Verified end-to-end in a clean venv.Other — PyArrow type map cached instead of rebuilt per column per call (2.7× faster schema conversion, ~17% off
.arrow()for small wide frames; output verified identical across all 52 type/nullable/precision cases). Optional integration imports guarded withpytest.importorskip(opteryx and polars have no Windows or 3.14 wheels). 3.14 added to the regression matrix — we ship 3.14 wheels but never tested them.varchar_array.pyxremoved (not built, not imported) and the disabled macOS workflow deleted.Testing
421 passed, 2 skipped.Not addressed
rugoalready uses the free hostedubuntu-24.04-armrunner; that would slot in as a normal matrix entry.Trueis accepted for an INTEGER column (stored asTrue, not1) sinceisinstance(True, int);{"d": 2}is rejected for a DOUBLE column. Both pre-existing.workflow_dispatch+ Test PyPI dry-run, Trusted Publishing (OIDC) instead ofPYPI_API_TOKEN, and cibuildwheel to replace the hand-rolled docker/build.sh/auditwheel matrix.