Skip to content

v0.9.0 - HyperCast 0.9.0's culture sweep in every column, free-threaded Python, and Blazor fixes

Choose a tag to compare

@buvinghausen buvinghausen released this 21 Oct 05:44
· 79 commits to master since this release
v0.9.0

HyperTabular 0.9.0 is built on HyperCast 0.9.0, its culture-fidelity sweep: everything a culture declares about a number now reaches every plan column, because the core casts every cell through HyperCast's doors. Also free-threaded Python, and the Blazor WebAssembly fixes from the same consumer feedback HyperCast answered, in the same shape. Nothing a binding's caller writes changes; one ABI layout does. The full list, with a bullet per binding, is in CHANGELOG.md.

Install

Language Package
Rust cargo add hypertabular
C# (.NET 11) dotnet add package HyperTabular
Java (JDK 25) implementation("io.github.skunkwerkx:hypertabular:0.9.0")
Go go get github.com/SkunkWerkx/HyperTabular/go@v0.9.0
Swift .package(url: "https://github.com/SkunkWerkx/HyperTabular", from: "0.9.0")
Python (3.11+) pip install hypertabular
Ruby (3.3+) gem install hypertabular
PHP (8.2+) composer require skunkwerkx/hypertabular

Highlights

  • A plan column's format carries everything HyperCast 0.9.0's NumFormat declares. The numeric doors of a plan column read the currency amount's own separators, further spellings of the minus and plus signs and the percent symbol, native digits beside ASCII, separators of one or two characters, and the TRAILING_SIGN lenience. Each binding's Column takes HyperCast's own NumFormat, which now takes the whole declaration: NumFormat.From(CultureInfo) in C#, from(Locale) in Java, and the rest. One rule throughout, HyperCast's: the ASCII or English default is always read and a declared symbol is read beside it, so no cell that parsed in 0.8.0 reads differently.
  • Python: free-threaded CPython, with the GIL off. Each platform gets three wheels where it had one: cp311-abi3 for CPython 3.11+ with the GIL as before, cp314-cp314t for free-threaded 3.14, and cp315-abi3.abi3t, PEP 803's stable ABI for 3.15+ with or without the GIL. The module declares it needs no GIL, so a free-threaded interpreter keeps it off after import hypertabular, and readers on different threads run in parallel. A Batch and a Workbook can be shared by any number of threads. A reader or a sheet is read by one thread at a time; a second thread calling into one meanwhile gets RuntimeError, never a race on its buffers. PyPI gets 25 wheels per release where it got 9.
  • C#: Blazor WebAssembly. A publish without the wasm-tools workload used to skip linking the native core and ship a runtime with no hypertabular_* symbols, with nothing louder than the SDK's own warning. The package's targets now fail the build with HYPERTABULAR002; an app that keeps a managed fallback sets HyperTabularRequireWasmWorkload to false. The browser-wasm archive is at runtimes/browser-wasm/nativeassets/net11.0/, the path the forge stages, and the targets live in build/net11.0/ with buildTransitive/ importing them, so a project that reaches the package through a class library gets the same wiring.
  • The format crosses the C ABI as HyperCast 0.9.0 lays it out. ColumnSpec is 104 bytes where it was 44: ordinal, door and parameter, then RawNumFormat, a size word followed by the 92-byte NumFormat in place. All zeros is still the invariant notation. Every binding restates the layout where it builds a spec and writes the format through HyperCast's own bridge (ToRaw, Raw, writeFormat, packed, rawFormat), so no bridge lays a byte of it out itself. The corpus replays are byte-identical in all eight languages.
  • Every README example was compiled and run against this release's build, the root README's C# and Rust ones included.

Upgrading from 0.8

  • HyperCast 0.9.0 is the floor in every package: hypercast = "0.9.0" for the crate, hypercast>=0.9.0,<0.10 on PyPI, HyperCast 0.9.0 on NuGet, hypercast 0.9.0 on Maven Central, ~> 0.9.0 for the gem, ^0.9.0 on Packagist, from: "0.9.0" for the Swift package and v0.9.0 for the Go module. The types this crate re-exports from HyperCast (Decimal, NumFormat, Fault, the temporal types) are HyperCast 0.9's.
  • Rust: NumFormat's separators are Symbol<8> where they were char, so build a format with NumFormat::new and its with_* methods rather than a struct literal. Symbol and NativeDigits are re-exported beside CurrencySymbol. The crate's python-values dependency is built on PyO3 0.30.
  • Direct C ABI callers: ColumnSpec is 104 bytes. Rebuild against the 0.9.0 header; a 44-byte spec is a contract violation, not a cell fault.
  • Python from source: a build from a checkout needs maturin 1.15 or newer. Wheels need nothing.
  • C#: nothing to change. A Blazor WebAssembly publish without wasm-tools now stops with HYPERTABULAR002 instead of shipping a runtime that cannot read.
  • Java, Go, Swift, Ruby, PHP: nothing to change beyond the HyperCast floor.

Verifying

Every artifact is built in CI and attested, the browser-wasm archive inside the NuGet package included: the one gap 0.8.0's notes reported is closed, and the NuGet pack now refuses any native without provenance.

gh attestation verify <file> --repo SkunkWerkx/HyperTabular