Repository navigation
Add python 3.15, small fixes, update vendored packages - #2
Merged
Merged
Conversation
Bump the floor to Python 3.13. CI matrix, wheel build matrix, ruff target-version, classifiers, and the requires-python pin all drop the 3.11 / 3.12 cells. Also strip the now-dead `PY_VERSION_HEX < 0x030C0000` branch in src/slots.cc (the function had a fallback for borrowing tp_dict; everything we support has PyType_GetDict). The PEP 562 module-level `__getattr__` experiment from this branch is reverted — eager definitions remain in floatium/__init__.py, and the autopatch hook goes through floatium.install (not floatium._ext.install directly). `from __future__ import annotations` is dropped from __init__.py and _autopatch.py since 3.13+ supports PEP 604 unions natively at runtime; that saves an `import __future__` (~90 µs) on the autopatch hot path without needing PEP 562. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Python 3.15.0 final shipped 2026-10-09. cibuildwheel 4.3.1 carries cp315 / cp315t in its default catalog and needs no `enable` token for free-threaded 3.14+, so bump to it and add cp315-* cp315t-* to the build list. cibuildwheel 4.0 dropped the experimental cp313t builds together with the cpython-freethreading enable, so wheels.yml keeps one pinned cibuildwheel 3.4.1 step that builds only cp313t-*. ci.yml / cpython-suite.yml: 3.15 and 3.15t resolve to final releases on all three OSes now, so drop allow-prereleases and the 3.15t × windows exclusion. New test-all-backends job compiles every backend (FLOATIUM_*_BACKEND=all) so the non-default ones are exercised in CI. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- format(x, "r") returned repr(); stock float.__format__ raises
ValueError. Drop the 'r' branch from parse_simple_spec so the spec
falls through to the original and errors exactly like stock. The
parity test used to skip "r" instead of checking it; it now asserts
the same exception type and message.
- 3.15+ debug builds: install()/uninstall() left PyFloat_Type with
tp_version_tag == 0 until the next lookup, and init_static_type()
asserts a non-zero tag on static builtin types whenever a
subinterpreter is created. Re-assign a tag immediately via
PyUnstable_Type_AssignVersionTag() after invalidating.
- floatium.enabled(False) re-installed the build-default backends on
exit instead of the ones that were active.
- The parse hook now only forwards strings made of [0-9.eE+-] to the
backend, so parity no longer depends on how permissive a backend's
strtod is: libc strtod (the "stock" backend) accepted hex floats and
nan(...), and honoured LC_NUMERIC (float("1,5") == 1.5 under de_DE).
- Wuffs: integer-part digits beyond the 800-digit HPD cap did not
advance the decimal point, so "1" + 800 zeros + "e-800" parsed as 0.1.
Local one-line fix in the vendored header, re-applied by
tools/sync_wuffs.sh and documented in README.vendor; also present in
upstream Wuffs main.
- New tests/test_backends.py checks every compiled-in format and parse
backend against stock in-process (random bit patterns, subnormals,
long mantissas, 30+ specs).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
fmt 12.2.0 (1be298e): Dragonbox full cache is now on by default (FMT_USE_FULL_CACHE_DRAGONBOX=1 unless __OPTIMIZE_SIZE__), which is the shortest-repr path floatium uses for repr()/str(). No changes to the format_float / Dragon4 code reached by modes 2 and 3. fast_float v8.3.2 (42f2548): unrolled integer-digit scan, 4-digit SWAR on GCC as well as clang, skipped rounding-mode probe for long mantissas, compile-time format folding — all on the from_chars<double> hot path — plus compiler compatibility fixes. No correctness changes to the double path. Synced with tools/sync_fmt.sh and tools/sync_fast_float.sh; vendored files remain byte-identical to upstream. Ryu is already at upstream HEAD; the Wuffs float-parsing code is unchanged upstream since 2023. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… script
Re-measured on the same release CPython 3.14.3 after the fmt 12.2.0 /
fast_float v8.3.2 bump (bench_ns_per_op for the README table,
bench_backend_matrix for BENCHMARKS.md). repr() is ~7% faster across
corpora from fmt's Dragonbox full cache; f"{x:.4f}" and float(s) are
unchanged within noise (an A/B against the v8.2.5 headers on this
machine gave identical parse timings).
bench/bench_backend_matrix.py is the script that produces the
BENCHMARKS.md tables, so they are reproducible with
`FLOATIUM_AUTOPATCH=0 python -m bench.bench_backend_matrix` on an
all-backends build.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…st_float v8.3.2 Drop cp313t wheels: cibuildwheel 4.x no longer builds 3.13 free-threaded CPython, and carrying a pinned 3.x step for one identifier is not worth it. 3.13 (GIL) wheels, 3.14t and 3.15t stay; 3.13t users build from the sdist. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ndidate Vendors the C port of Żmij (vitaut/zmij a9d6363, MIT or BSL-1.0; zmij.c + zmij-c.h only) and adds a "zmij" format backend that serves every _Py_dg_dtoa mode from it: shortest via Żmij's verified algorithm, %e/%f precision via its correctly rounded scientific/fixed writers (bigint-backed above 18 digits). Unlike fmt_opt and ryu_opt this is one unmodified library plus one adapter, with no C++ anywhere — the shape a CPython proposal needs. The adapter (src/cpython_adapter/zmij_dtoa.c) is plain C11 against the exact _Py_dg_dtoa contract, using nothing from CPython but PyMem_*: it re-reads Żmij's printf-style text into digits + decpt and implements mode 3 with negative ndigits (round(x, -k)) with ties-to-even digit arithmetic on the exact integer part. Verified with 182k direct calls through ctypes against repr/format/round, plus tests/test_backends.py across 2800 values x 32 specs; suite passes on 3.14 and 3.15t debug. Also: CMAKE_C_STANDARD 11 (zmij.c uses static_assert), the all-backends CI job now runs on ubuntu/macos/windows so zmij.c is built with MSVC and Apple clang too, INTERNALS.md documents the zmij + wuffs pair as the CPython candidate, and README.vendor lists the three upstream requests for Żmij (asm -> __asm__ for -std=c11, a to-decimal C entry point, extern "C" guards). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…loatium backend) Oracles are int/int true division (correctly rounded by contract), Decimal quantize/round and brute-force shortest search, so they share no code with dtoa.c or the vendored libraries. ~1M checks per 40k-value run; stock dtoa.c and every floatium backend pass with zero mismatches, so this is the parity evidence for the CPython proposal rather than a bug finder. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…rse candidate Vendors kolemannix/ffc.h v26.09.01+1 (7e85c6d; Apache-2.0 / MIT / BSL-1.0 like fast_float) and adds an "ffc" parse backend: the same Clinger + Eisel-Lemire + bigint digit-comparison pipeline as the fast_float backend, but a single C99 header with no C++. Used by valkey and hiredis. Compiles under CPython's -std=c11 without warnings. The adapter (src/cpython_adapter/ffc_strtod.c) is plain C with the _Py_dg_strtod contract: no whitespace skipping, inf/nan left to _Py_parse_inf_or_nan, endptr and errno = ERANGE semantics. Chosen over Wuffs for the CPython proposal: Wuffs' parser is an extract of a transpiler-generated multi-codec file, rejects numbers with leading zeros (10,839 of 268k hard-case strings, 12 of 5.3M corpus lines, all of which float() must accept), and its HPD fallback is ~12x slower on 17-digit inputs. ffc.h matched fast_float and glibc bit for bit on all 5.3M published corpus lines and 268k exact-midpoint / long-mantissa cases, tracks fast_float within noise in BENCHMARKS.md, and passes tools/fuzz_float_oracle.py (1M checks) installed as zmij + ffc. INTERNALS.md now names zmij + ffc as the CPython candidate pair and explains the choice; BENCHMARKS.md gains the ffc column. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…andidate)
The shipped wheel is now the exact pure-C configuration proposed for
CPython: Żmij for every dtoa mode and ffc.h (C99 fast_float) for
parsing, so every user exercises the candidate code. fmt_opt /
fast_float / ryu_opt / wuffs stay available at build time and, in an
"all" build, at install time.
README benchmark table re-measured with the new defaults on the same
release CPython 3.14.3 (repr 1.5–5.4x, fixed 1.1–4.3x, parse 1–4.1x).
fmt_opt remains faster on f"{x:.4f}" for huge magnitudes (Ryu d2fixed);
the default favours what CPython can take over the last nanoseconds.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
PowerShell does not treat a trailing backslash as a line continuation, so the multi-line pip install ran '-C ...' as a separate command and the windows-latest all-backends job failed at install time. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ith MSVC The extract included <intrin.h> inside multiply_u64 and count_leading_zeroes_u64 for the MSVC branches; MSVC rejects a system header at block scope (C2598 and a cascade of errors in xmmintrin.h), which broke the new windows-latest all-backends CI job. Documented as local modification 8 and re-applied by tools/sync_wuffs.sh. Co-Authored-By: Claude Fable 5.1 <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.
No description provided.