This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Consider using release 1.1.0 instead.
Reason given by maintainers: 0.x is retired; use 1.0 or later (see https://github.com/Wave-RF/chtypes/issues/431)
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.codeis 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.UnsupportedErroris a peer ofSchemaError, not a subclass.except SchemaErrornever catches a decline. Handle the two arms explicitly, or catchChtypesErrorfor 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.
Metadata
Release files for chtypes 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| chtypes-0.2.0.tar.gz | 122.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| chtypes-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 212.7 kB
Release files / chtypes-0.2.0.tar.gz
| Download URL | chtypes-0.2.0.tar.gz |
|---|---|
| Size | 122.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f308e0a47c71390c264f55f7f96dce1a18da5595c7485318a189af7b4fe75c04
|
|
BLAKE2b-256 checksum How to use checksums |
f90231e5bc9dbf161867e8be1946de43733e996e931530ed812e5bc3a9a0124f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.
Transparency logRelease files / chtypes-0.2.0-py3-none-any.whl
| Download URL | chtypes-0.2.0-py3-none-any.whl |
|---|---|
| Size | 90.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
47a9dc74707b342ee13565b4b1bb409d088b7fa47dcd76e7b2ce7800a7452f04
|
|
BLAKE2b-256 checksum How to use checksums |
204c8d1eb033c4eb5b1dad8b2583d74840bf4c1bf34c77b95d3464896fd4ad37
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.
Transparency log