Skip to main content

chtypes — Python SDK

If this row were inserted into this table on this ClickHouse version, what would happen? chtypes answers with ClickHouse's own code: the real C++ type machinery, vendored per release into a native library behind the frozen chs_* C ABI and reached here through stdlib ctypes. Nothing semantic is reimplemented, so "what does ClickHouse do with 256 into a UInt8?" is answered by ClickHouse rather than by a model of it. One peer binding among {go, python, ts, rust} — no language is privileged, and all four give one answer.

Pure Python: zero dependencies, no build step, no compiler.

Install

Two things: this package, and at least one artifact — the per-version native library it dlopens at runtime.

uv add chtypes            # or: pip install chtypes
python -m chtypes fetch 25.8

The fetch lands in ~/.cache/chtypes/artifacts/<os>-<arch>/25.8/ — the per-user cache every chtypes binding reads by default — after checking an ed25519 signature over the release and the sha256 of every byte. $CHTYPES_REGISTRY overrides it. The ed25519 verifier is pure stdlib too.

Quickstart

from chtypes import Format, Registry

registry = Registry()                   # walks the search path
library = registry.for_version("25.8")  # a line or an exact patch; never a nearest match

with library.compile_ddl("x UInt8, ts DateTime DEFAULT now()") as schema:
    batch = schema.rows(Format.JSON_EACH_ROW, b'{"x":256}\n')

row = batch.rows[0]
print(batch.outcome)              # accepted
print(row.value("x").text)        # 0             — what would actually be stored
print(row.transformed[0].reason)  # overflow_wrap — which is the product
print(row.substituted)            # ts: send it explicitly, or preview != stored

The row is accepted and 256 is silently stored as 0. That report — transformed — is the one derived answer in the system and the reason it exists.

ts was substituted rather than stored: send every substituted column as an explicit value in the real INSERT, or the server re-evaluates now() at its own instant and your preview is not what landed. Pin the instant in tests with settings={"chtypes_now_epoch_nanos": "1700000000000000000"}.

Three outcomes, and conflating any two is a bug

A bad row is a verdict, not an exception: outcome becomes Outcome.REJECTED with ClickHouse's own code. Exceptions are for schema-level answers and for the machinery.

  • SchemaError — the server itself would refuse this, and .code is a real ClickHouse code.
  • UnsupportedError — this build declines to answer, and a real server might well have accepted. Fall back to the server; never tell a user they are wrong on the strength of a decline.
  • UnsupportedError is a peer of SchemaError, not a subclass. except SchemaError never catches a decline. Handle the two arms explicitly, or catch ChtypesError for both.

Documentation

Quickstart the same program in all four languages
Python API reference every symbol, the C entry point under it, what it returns and what it raises
Artifacts getting one, where it lands, verifying and pinning it
Batches always rows, and the two bad-row policies
Transformations the silent-change report, and the DEFAULTs you must echo back
Settings · Discovery the four channels; asking a real server what profile to validate under
Filters · Multi-version boolean expressions over rows; several ClickHouse versions in one process
Support matrix · Limitations what works where; what chtypes declines to answer

Three things specific to this binding

A settings value must never be a float. encode_settings stringifies an int exactly and raises TypeError on a float: a 19-digit chtypes_now_epoch_nanos does not survive an IEEE double, and as a JSON number the setting would be silently ignored.

substituted is on RowResult, not on BatchResult. Reach it through batch.rows[i].substituted. BatchResult does carry a batch-level transformed, which folds in the storage layer's own verdicts.

ctypes releases the GIL for the whole duration of a foreign call, so the GIL is not the exclusion. The package uses a writer-preferring readers-writer lock per loaded image plus one plain lock per Schema; set_default_settings and close take it exclusively, as the ABI requires. Measured under contention: 27,770 batch reads across 8 threads against 566 concurrent settings swaps, every answer byte-identical to the uncontended one.

Tests

uv run pytest -q. Tests that need an artifact skip loudly by name without a registry on the search path, and a suite that ran nothing fails. The fetch suite runs offline against the miniature releases in tests/fixtures/fetch/ through file:// sources and the test key.

License

Apache 2.0. The artifacts this package loads are Elastic License 2.0 — a separate license, shipped inside each artifact release.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

chtypes-0.1.2.tar.gz (120.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

chtypes-0.1.2-py3-none-any.whl (90.2 kB view details)

Uploaded Python 3

File details

Details for the file chtypes-0.1.2.tar.gz.

File metadata

  • Download URL: chtypes-0.1.2.tar.gz
  • Upload date:
  • Size: 120.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for chtypes-0.1.2.tar.gz
Algorithm Hash digest
SHA256 8baf9a327d9724e39fbdfe6648de4a048178d0d7023f8affec033635b72aba8a
MD5 7a0be680a1ff6b7f280825eed80bea4a
BLAKE2b-256 fc291c348fa30bd6f180454dfb4c1db2c16be4e715a1f19269802bca6216c4e0

See more details on using hashes here.

Provenance

The following attestation bundles were made for chtypes-0.1.2.tar.gz:

Publisher: release-python.yml on Wave-RF/chtypes

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file chtypes-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: chtypes-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 90.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for chtypes-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 8cf7df6233978ff61b3a29277687ea902b406d98217a1280ae771a47d575e156
MD5 e00d13928d8e70d4dbda981d0cacf95b
BLAKE2b-256 894da72b36815ce159d0e7d47d1f4585a63d0ffb5b719fa6714bec7c25d937a7

See more details on using hashes here.

Provenance

The following attestation bundles were made for chtypes-0.1.2-py3-none-any.whl:

Publisher: release-python.yml on Wave-RF/chtypes

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page