chtypes 1.1.0__tar.gz → 2.0.0.dev0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/PKG-INFO +6 -2
  2. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/README.md +5 -1
  3. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/pyproject.toml +1 -1
  4. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/__init__.py +9 -1
  5. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/__main__.py +20 -0
  6. {chtypes-1.1.0/src/chtypes/_abi1 → chtypes-2.0.0.dev0/src/chtypes/_abi2}/__init__.py +5 -3
  7. {chtypes-1.1.0/src/chtypes/_abi1 → chtypes-2.0.0.dev0/src/chtypes/_abi2}/_decls.py +15 -9
  8. {chtypes-1.1.0/src/chtypes/_abi1 → chtypes-2.0.0.dev0/src/chtypes/_abi2}/_errmap.py +3 -3
  9. {chtypes-1.1.0/src/chtypes/_abi1 → chtypes-2.0.0.dev0/src/chtypes/_abi2}/_loader.py +24 -7
  10. chtypes-2.0.0.dev0/src/chtypes/_abi2/_vocab.py +416 -0
  11. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/_decode.py +13 -15
  12. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/_ocifetch/__init__.py +6 -0
  13. chtypes-2.0.0.dev0/src/chtypes/_ocifetch/_channel.py +325 -0
  14. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/_ocifetch/_ensure.py +36 -9
  15. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/_ocifetch/_layout.py +25 -14
  16. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/_ocifetch/_lock.py +5 -3
  17. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/errors.py +1 -1
  18. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/library.py +2 -2
  19. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/registry.py +31 -4
  20. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/results.py +1 -1
  21. {chtypes-1.1.0/tests/abi1 → chtypes-2.0.0.dev0/tests/abi2}/__init__.py +1 -1
  22. {chtypes-1.1.0/tests/abi1 → chtypes-2.0.0.dev0/tests/abi2}/conftest.py +28 -11
  23. {chtypes-1.1.0/tests/abi1 → chtypes-2.0.0.dev0/tests/abi2}/test_conformance.py +6 -6
  24. chtypes-2.0.0.dev0/tests/abi2/test_dev_fingerprint.py +59 -0
  25. {chtypes-1.1.0/tests/abi1 → chtypes-2.0.0.dev0/tests/abi2}/test_goldens_runner_stub.py +22 -7
  26. {chtypes-1.1.0/tests/abi1 → chtypes-2.0.0.dev0/tests/abi2}/test_loader.py +3 -3
  27. {chtypes-1.1.0/tests/abi1 → chtypes-2.0.0.dev0/tests/abi2}/test_public_library.py +9 -4
  28. {chtypes-1.1.0/tests/abi1 → chtypes-2.0.0.dev0/tests/abi2}/test_public_open.py +1 -1
  29. {chtypes-1.1.0/tests/abi1 → chtypes-2.0.0.dev0/tests/abi2}/test_public_registry.py +16 -1
  30. {chtypes-1.1.0/tests/abi1 → chtypes-2.0.0.dev0/tests/abi2}/test_public_setup_cases.py +3 -3
  31. chtypes-2.0.0.dev0/tests/abi2/test_reader_rules.py +243 -0
  32. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/api/test_decode.py +37 -13
  33. chtypes-2.0.0.dev0/tests/api/test_vocab.py +124 -0
  34. chtypes-2.0.0.dev0/tests/cli/conftest.py +26 -0
  35. chtypes-2.0.0.dev0/tests/cli/test_devchannel.py +126 -0
  36. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/cli/test_main.py +4 -2
  37. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/conftest.py +1 -1
  38. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/goldens_v1/test_runner.py +25 -5
  39. chtypes-2.0.0.dev0/tests/ocifetch/conftest.py +28 -0
  40. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/ocifetch/test_conformance.py +12 -0
  41. chtypes-2.0.0.dev0/tests/ocifetch/test_devchannel.py +268 -0
  42. chtypes-2.0.0.dev0/tests/ocifetch/test_seam_gate.py +57 -0
  43. chtypes-2.0.0.dev0/tests/test_abi_identity.py +24 -0
  44. chtypes-2.0.0.dev0/tests/test_devchannel_registry.py +98 -0
  45. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/test_fetch_options.py +9 -4
  46. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/uv.lock +1 -1
  47. chtypes-1.1.0/src/chtypes/_abi1/_vocab.py +0 -254
  48. chtypes-1.1.0/tests/api/test_vocab.py +0 -90
  49. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/.gitignore +0 -0
  50. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/CHANGELOG.md +0 -0
  51. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/LICENSE +0 -0
  52. {chtypes-1.1.0/src/chtypes/_abi1 → chtypes-2.0.0.dev0/src/chtypes/_abi2}/_errors.py +0 -0
  53. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/_ed25519.py +0 -0
  54. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/_guard.py +0 -0
  55. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/_input.py +0 -0
  56. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/_ocifetch/_constants.py +0 -0
  57. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/_ocifetch/_dsse.py +0 -0
  58. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/_ocifetch/_errors.py +0 -0
  59. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/_ocifetch/_faults.py +0 -0
  60. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/_ocifetch/_goldens.py +0 -0
  61. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/_ocifetch/_http.py +0 -0
  62. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/_ocifetch/_oci.py +0 -0
  63. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/_ocifetch/_referrers.py +0 -0
  64. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/_ocifetch/_unpack.py +0 -0
  65. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/_setup.py +0 -0
  66. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/src/chtypes/py.typed +0 -0
  67. {chtypes-1.1.0/tests/abi1 → chtypes-2.0.0.dev0/tests/abi2}/_stub_tree.py +0 -0
  68. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/api/__init__.py +0 -0
  69. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/api/test_input.py +0 -0
  70. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/cli/__init__.py +0 -0
  71. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/goldens_v1/__init__.py +0 -0
  72. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/goldens_v1/data/stub-goldens.json +0 -0
  73. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/ocifetch/__init__.py +0 -0
  74. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/ocifetch/_bundle_support.py +0 -0
  75. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/ocifetch/_registry_support.py +0 -0
  76. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/ocifetch/_sign_support.py +0 -0
  77. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/ocifetch/test_cache_roots.py +0 -0
  78. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/ocifetch/test_cache_strict.py +0 -0
  79. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/ocifetch/test_dsse.py +0 -0
  80. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/ocifetch/test_ensure.py +0 -0
  81. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/ocifetch/test_goldens.py +0 -0
  82. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/ocifetch/test_http.py +0 -0
  83. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/ocifetch/test_layout.py +0 -0
  84. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/ocifetch/test_lock.py +0 -0
  85. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/ocifetch/test_oci.py +0 -0
  86. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/ocifetch/test_unpack.py +0 -0
  87. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/test_ed25519.py +0 -0
  88. {chtypes-1.1.0 → chtypes-2.0.0.dev0}/tests/test_examples_tour.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: chtypes
3
- Version: 1.1.0
3
+ Version: 2.0.0.dev0
4
4
  Summary: Python binding for the chtypes artifacts: ClickHouse's own type system, per version, behind the frozen chs_* C ABI
5
5
  Project-URL: Homepage, https://github.com/wave-rf/chtypes
6
6
  Project-URL: Repository, https://github.com/wave-rf/chtypes
@@ -19,6 +19,8 @@ Description-Content-Type: text/markdown
19
19
 
20
20
  # chtypes — Python SDK
21
21
 
22
+ > **2.0.0-dev: UNSTABLE, staging only, not for production.** This is the ABI v2 development binding (public issue #511). It speaks ABI v2's unstable description, pins its dev fingerprint and refuses a library with any other ("update your dev SDK"). It fetches only from the staging dev channel (`https://registry-staging.wavehouse.dev/chtypes/v2-dev`) and trusts only the staging key; `CHTYPES_ARTIFACTS_URL`, `CHTYPES_TRUSTED_KEYS` and `CHTYPES_ALLOW_UNSIGNED`, and the `bases`, `trusted_keys` and `allow_unsigned` fetch options, are ignored, each with one warning; `--lock`, `--frozen` and `--update`, and the `frozen`, `lock_path`, `lock_write` and `update` options, are refused, because a dev build is replaceable and a superseded one expires after 14 days. Its cache is `${XDG_CACHE_HOME:-~/.cache}/chtypes/v2-dev`, or `<CHTYPES_CACHE>/v2-dev` under an explicit cache, which no 1.x SDK reads. Every vocabulary keeps a value it does not list as its `unknown(n)` member (`Outcome("x")`, whose `known` is `False`) instead of failing the document. The rules are r1 to r6 of [`docs/reference/abi-v2.md`](../docs/reference/abi-v2.md). For production, use the 1.x package: `pip install "chtypes<2"`.
23
+
22
24
  **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.
23
25
 
24
26
  Pure ctypes: no compiler, no build step. The only dependency is a zstd decompressor for the artifact layer, which is the standard library's own from Python 3.14 and the `backports.zstd` package before that.
@@ -28,9 +30,11 @@ Pure ctypes: no compiler, no build step. The only dependency is a zstd decompres
28
30
  Two things: this package, and at least one **artifact** — the per-version native library it `dlopen`s at runtime. The registry fetches the artifact on first use when autofetch is on (`Registry(autofetch=True)` or `CHTYPES_AUTOFETCH=1`), after verifying its signature and every byte against the signed statement; with autofetch off it answers only from what is already installed.
29
31
 
30
32
  ```sh
31
- uv add chtypes # or: pip install chtypes
33
+ uv add "chtypes>=2.0.0.dev0" # or: pip install "chtypes>=2.0.0.dev0"
32
34
  ```
33
35
 
36
+ `uv add chtypes` and `pip install chtypes` never select a pre-release on their own: the specifier names a dev version, which is what allows one.
37
+
34
38
  ## Quickstart
35
39
 
36
40
  ```python
@@ -1,5 +1,7 @@
1
1
  # chtypes — Python SDK
2
2
 
3
+ > **2.0.0-dev: UNSTABLE, staging only, not for production.** This is the ABI v2 development binding (public issue #511). It speaks ABI v2's unstable description, pins its dev fingerprint and refuses a library with any other ("update your dev SDK"). It fetches only from the staging dev channel (`https://registry-staging.wavehouse.dev/chtypes/v2-dev`) and trusts only the staging key; `CHTYPES_ARTIFACTS_URL`, `CHTYPES_TRUSTED_KEYS` and `CHTYPES_ALLOW_UNSIGNED`, and the `bases`, `trusted_keys` and `allow_unsigned` fetch options, are ignored, each with one warning; `--lock`, `--frozen` and `--update`, and the `frozen`, `lock_path`, `lock_write` and `update` options, are refused, because a dev build is replaceable and a superseded one expires after 14 days. Its cache is `${XDG_CACHE_HOME:-~/.cache}/chtypes/v2-dev`, or `<CHTYPES_CACHE>/v2-dev` under an explicit cache, which no 1.x SDK reads. Every vocabulary keeps a value it does not list as its `unknown(n)` member (`Outcome("x")`, whose `known` is `False`) instead of failing the document. The rules are r1 to r6 of [`docs/reference/abi-v2.md`](../docs/reference/abi-v2.md). For production, use the 1.x package: `pip install "chtypes<2"`.
4
+
3
5
  **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.
4
6
 
5
7
  Pure ctypes: no compiler, no build step. The only dependency is a zstd decompressor for the artifact layer, which is the standard library's own from Python 3.14 and the `backports.zstd` package before that.
@@ -9,9 +11,11 @@ Pure ctypes: no compiler, no build step. The only dependency is a zstd decompres
9
11
  Two things: this package, and at least one **artifact** — the per-version native library it `dlopen`s at runtime. The registry fetches the artifact on first use when autofetch is on (`Registry(autofetch=True)` or `CHTYPES_AUTOFETCH=1`), after verifying its signature and every byte against the signed statement; with autofetch off it answers only from what is already installed.
10
12
 
11
13
  ```sh
12
- uv add chtypes # or: pip install chtypes
14
+ uv add "chtypes>=2.0.0.dev0" # or: pip install "chtypes>=2.0.0.dev0"
13
15
  ```
14
16
 
17
+ `uv add chtypes` and `pip install chtypes` never select a pre-release on their own: the specifier names a dev version, which is what allows one.
18
+
15
19
  ## Quickstart
16
20
 
17
21
  ```python
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "chtypes"
3
- version = "1.1.0"
3
+ version = "2.0.0.dev0"
4
4
  description = "Python binding for the chtypes artifacts: ClickHouse's own type system, per version, behind the frozen chs_* C ABI"
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -1,5 +1,11 @@
1
1
  """chtypes: ClickHouse's own type system, per version, from Python.
2
2
 
3
+ 2.0.0-dev: UNSTABLE, staging only, not for production. This pre-release speaks
4
+ the ABI v2 dev description (spec/abi-v2/docs.md): it fetches only from the
5
+ staging dev channel and trusts only its key, refuses locks and frozen fetches,
6
+ caches under its own `v2-dev` root, and refuses a library built from any other
7
+ dev fingerprint (rules r5 and r6).
8
+
3
9
  One question, exactly: *if this row were inserted into this ClickHouse table on
4
10
  this ClickHouse version, what would happen?* The answer comes from ClickHouse's
5
11
  real C++ machinery, vendored per release into a shared library behind the frozen
@@ -40,9 +46,10 @@ from __future__ import annotations
40
46
  from importlib.metadata import PackageNotFoundError as _PackageNotFound
41
47
  from importlib.metadata import version as _package_version
42
48
 
43
- from ._abi1._vocab import (
49
+ from ._abi2._vocab import (
44
50
  EXPORT_NONE,
45
51
  DefaultKind,
52
+ DiscoverQueryParam,
46
53
  DocFlags,
47
54
  FilterOutcome,
48
55
  Format,
@@ -140,6 +147,7 @@ __all__ = [
140
147
  "Column",
141
148
  "Computed",
142
149
  "DefaultKind",
150
+ "DiscoverQueryParam",
143
151
  "DiscoveredColumn",
144
152
  "Discovery",
145
153
  "EngineCell",
@@ -12,6 +12,15 @@ A spelling is `26.8`, `26.8.15` or `26.8.15.10`. Exit statuses come from the
12
12
  as `ERROR_EXIT_CODES`); a usage error exits 2 and success exits 0. Progress and
13
13
  diagnostics go to stderr; `fetch` prints one installed library path per line on
14
14
  stdout.
15
+
16
+ 2.0.0-dev: UNSTABLE, staging only, not for production. This CLI speaks the ABI
17
+ v2 dev channel (spec/abi-v2/docs.md, rules r5 and r6): it fetches only from
18
+ https://registry-staging.wavehouse.dev/chtypes/v2-dev and trusts only the
19
+ staging key; CHTYPES_ARTIFACTS_URL, CHTYPES_TRUSTED_KEYS and
20
+ CHTYPES_ALLOW_UNSIGNED are ignored, each with one warning; --lock, --frozen and
21
+ --update are refused before any network call; its default cache is
22
+ ${XDG_CACHE_HOME:-~/.cache}/chtypes/v2-dev, and an explicit one (--cache,
23
+ CHTYPES_CACHE) is used through its v2-dev subroot.
15
24
  """
16
25
 
17
26
  from __future__ import annotations
@@ -24,6 +33,7 @@ from collections.abc import Sequence
24
33
 
25
34
  from . import __version__ as chtypes_version
26
35
  from . import _ocifetch as fetch_layer
36
+ from ._ocifetch import _channel
27
37
  from ._ocifetch import _constants as C
28
38
  from ._ocifetch._ensure import _translate_transport_error, detect_host_platform, missing_notes
29
39
  from ._ocifetch._errors import ArtifactCorruptError, ArtifactMissingError, FetchError
@@ -67,6 +77,12 @@ def build_parser() -> argparse.ArgumentParser:
67
77
  parser = _Parser(
68
78
  prog="chtypes",
69
79
  description="Fetch, verify and locate chtypes artifacts (docs/guides/fetch-v1.md).",
80
+ epilog=(
81
+ "2.0.0-dev: UNSTABLE, staging only, not for production. Fetches only from the staging "
82
+ "dev channel and trusts only its key; --lock, --frozen and --update are refused; "
83
+ "CHTYPES_ARTIFACTS_URL, CHTYPES_TRUSTED_KEYS and CHTYPES_ALLOW_UNSIGNED are ignored "
84
+ "(spec/abi-v2/docs.md, rule r6)."
85
+ ),
70
86
  )
71
87
  parser.add_argument("--version", action="version", version=f"chtypes {_display_version()}")
72
88
  sub = parser.add_subparsers(dest="command", metavar="<command>")
@@ -196,6 +212,10 @@ def _published_tags(options) -> list[str]:
196
212
 
197
213
 
198
214
  def _cmd_fetch(args: argparse.Namespace) -> int:
215
+ # A dev SDK pins nothing: the refusal comes before anything else, the
216
+ # network above all (rule r6).
217
+ if (args.lock or args.frozen or args.update) and not _channel.active().pinnable:
218
+ raise ValueError(f"chtypes: {_channel.PINNING_REFUSED}")
199
219
  if args.all and args.spellings:
200
220
  raise ValueError("chtypes: give spellings or --all, not both")
201
221
  if not args.all and not args.spellings and not args.update:
@@ -1,4 +1,4 @@
1
- """The ABI v1 loader and generated declaration layer (plan
1
+ """The ABI v2 loader and generated declaration layer (plan
2
2
  PLAN-sdk-v1-ffi-2026-10-01.md), private to this binding. Not part of `chtypes`'s
3
3
  public surface: the public API (`chtypes.library`, `chtypes.registry`) is built
4
4
  over it, and re-exports the vocabularies and errors it defines.
@@ -7,11 +7,13 @@ over it, and re-exports the vocabularies and errors it defines.
7
7
  handle classes, the typed call wrappers on `Api`, and the test-only
8
8
  `invoke_by_name()` dispatcher.
9
9
  - `_vocab`: GENERATED -- `Format`, `Status`, `Outcome`, `Verdict`, `Reason`,
10
- `Source`, `DefaultKind`, `DocFlags` and the facts the description attaches.
10
+ `Source`, `DefaultKind`, `DiscoverQueryParam`, `DocFlags` and the facts the
11
+ description attaches, each vocabulary with its unknown(n) member (rule r3).
11
12
  - `_errors`: the public `chtypes.errors` classes, re-exported under the names
12
13
  `_errmap` uses.
13
14
  - `_errmap`: GENERATED -- the sdk.json status/reason -> `_errors` class maps.
14
- - `_loader`: hand-written -- `open()`/`open_unverified()`, the loader steps.
15
+ - `_loader`: hand-written -- `open()`/`open_unverified()`, the loader steps,
16
+ and rule r6's exact refusal of another fingerprint.
15
17
  """
16
18
 
17
19
  from __future__ import annotations
@@ -1,9 +1,9 @@
1
- # GENERATED by scripts/abi-v1/gen.py from spec/abi-v1/abi.json (CHS_ABI_FINGERPRINT sha256:856e5cb7543db291b4db716662bf6e487b2258973b959bbf5d58b4bd46d73285) — DO NOT EDIT # noqa: E501
2
- """The Python binding's generated ABI v1 layer: ctypes signatures, the handle
1
+ # GENERATED by scripts/abi-v1/gen.py --major 2 from spec/abi-v2/abi.json (CHS_ABI_FINGERPRINT sha256:8ec0c6941f000aa07bfb9fbfef20205d3ee0a588833856bd12270ba42912bfb3) — DO NOT EDIT # noqa: E501
2
+ """The Python binding's generated ABI v2 layer: ctypes signatures, the handle
3
3
  classes, the two-phase resolve functions and invoke_by_name(), the test-only
4
- dispatcher the conformance suite drives from tests/fixtures/abi-v1/cases.json.
4
+ dispatcher the conformance suite drives from tests/fixtures/abi-v2/cases.json.
5
5
  See scripts/abi-v1/emit/python.py's module docstring for the design this file
6
- implements and why. This is the ONLY python/src/chtypes/_abi1 file that reads
6
+ implements and why. This is the ONLY python/src/chtypes/_abi2 file that reads
7
7
  a chs_* attribute (scripts/abi-v1/check-no-hand-decls.py exempts it by its
8
8
  banner, above); every other file in this package calls the non-chs_-prefixed
9
9
  names this module exposes instead.
@@ -18,8 +18,14 @@ from dataclasses import dataclass, field
18
18
 
19
19
  from . import _errmap
20
20
 
21
- CHS_ABI_VERSION = 1
22
- CHS_ABI_FINGERPRINT = "sha256:856e5cb7543db291b4db716662bf6e487b2258973b959bbf5d58b4bd46d73285"
21
+ CHS_ABI_VERSION = 2
22
+ CHS_ABI_FINGERPRINT = "sha256:8ec0c6941f000aa07bfb9fbfef20205d3ee0a588833856bd12270ba42912bfb3"
23
+
24
+ # The description's stability: "unstable" while this generation is being
25
+ # designed, so CHS_ABI_FINGERPRINT moves with every change, and "locked" after
26
+ # (spec/abi-v2/docs.md, rule r6). A dev SDK refuses any other fingerprint with
27
+ # the dev message (_loader.py).
28
+ CHS_ABI_STABILITY = "unstable"
23
29
 
24
30
  # sdk.json's loader.cross_check: (build_info field, predicate field, how to
25
31
  # compare), read by _loader.py's step 5 without it ever touching sdk.json
@@ -516,7 +522,7 @@ class Api:
516
522
  cls = _errmap.call_error_class(name)
517
523
  message = info.message if info else b""
518
524
  if name not in STATUS_BY_NAME:
519
- message = f"status {status} is outside the closed chs_status set".encode() + (
525
+ message = f"call status unknown({status}) is outside the closed set".encode() + (
520
526
  b": " + message if message else b""
521
527
  )
522
528
  raise cls(
@@ -927,7 +933,7 @@ def resolve_all(lib: ctypes.CDLL) -> Api:
927
933
  time step 6 runs, step 3 has already proven it exists). The first symbol
928
934
  ctypes cannot dlsym raises MissingSymbol(name); _loader.py's step 6 turns
929
935
  that into "missing_symbol:<name>", matching every missing-<sym> stub
930
- variant (tests/fixtures/abi-v1/cases.json), chs_build_info and
936
+ variant (tests/fixtures/abi-v2/cases.json), chs_build_info and
931
937
  chs_clickhouse_version included -- loader step 4 needs chs_build_info
932
938
  already resolved, which is exactly why this sweep must run before it."""
933
939
  raw: dict = {}
@@ -1028,7 +1034,7 @@ def invoke_by_name(api: Api, name: str, args: Iterable[object] = ()) -> InvokeRe
1028
1034
  (or None, where nullable) for handle. Output parameters are never
1029
1035
  supplied by the caller: this dispatcher allocates them, and decodes them
1030
1036
  into the returned InvokeResult. Test-only: every chs_ spelling below is
1031
- why this file, alone in python/src/chtypes/_abi1, carries the generated
1037
+ why this file, alone in python/src/chtypes/_abi2, carries the generated
1032
1038
  banner check-no-hand-decls.py exempts."""
1033
1039
  spec = FUNCTIONS[name]
1034
1040
  fn = api._raw[name]
@@ -1,7 +1,7 @@
1
- # GENERATED by scripts/abi-v1/gen.py from spec/abi-v1/abi.json (CHS_ABI_FINGERPRINT sha256:856e5cb7543db291b4db716662bf6e487b2258973b959bbf5d58b4bd46d73285) — DO NOT EDIT # noqa: E501
2
- """spec/abi-v1/sdk.json's error-mapping tables, as references to the
1
+ # GENERATED by scripts/abi-v1/gen.py --major 2 from spec/abi-v2/abi.json (CHS_ABI_FINGERPRINT sha256:8ec0c6941f000aa07bfb9fbfef20205d3ee0a588833856bd12270ba42912bfb3) — DO NOT EDIT # noqa: E501
2
+ """spec/abi-v2/sdk.json's error-mapping tables, as references to the
3
3
  public classes (python/src/chtypes/errors.py, re-exported by
4
- python/src/chtypes/_abi1/_errors.py). Only the MAPPING is generated: the
4
+ python/src/chtypes/_abi2/_errors.py). Only the MAPPING is generated: the
5
5
  classes themselves are stable across a regeneration (plan section 3.4), so a
6
6
  status renumbering or a new loader refusal reason changes this file, never
7
7
  the classes.
@@ -1,4 +1,4 @@
1
- """The ABI v1 loader, Python half (plan PLAN-sdk-v1-ffi section 3.2/3.3).
1
+ """The ABI v2 loader, Python half (plan PLAN-sdk-v1-ffi section 3.2/3.3).
2
2
 
3
3
  Decoupled from the fetch PRs on purpose (plan section 3.1): `open()` takes a
4
4
  small, loader-owned `predicate` mapping rather than the fetch module's
@@ -8,13 +8,13 @@ wired up; `predicate` is passed through exactly as that seam promises.
8
8
 
9
9
  Every `chs_*` spelling in this module is forbidden by
10
10
  scripts/abi-v1/check-no-hand-decls.py (it is not a generated file), so this
11
- calls ONLY python/src/chtypes/_abi1/_decls.py's non-`chs_`-prefixed surface:
11
+ calls ONLY python/src/chtypes/_abi2/_decls.py's non-`chs_`-prefixed surface:
12
12
  `resolve_abi_version()`, `resolve_all()`, and the `Api` object they return.
13
13
 
14
14
  Steps 1-6 run in the order plan section 3.2 gives (with step 6's full
15
15
  resolve-all sweep run right after step 3, BEFORE step 4's
16
16
  `chs_build_info()` call -- step 4 needs that symbol already resolved, and
17
- `tests/fixtures/abi-v1/cases.json`'s `missing-chs_build_info` and
17
+ `tests/fixtures/abi-v2/cases.json`'s `missing-chs_build_info` and
18
18
  `missing-chs_clickhouse_version` stub variants both expect the step 6
19
19
  `missing_symbol:<name>` reason, not a step 4 one, which is only possible if
20
20
  the full symbol sweep happens before chs_build_info is ever called). Step 7
@@ -54,6 +54,25 @@ def _refuse(reason: str, path: str, want: object = None, got: object = None) ->
54
54
  raise cls(reason=reason, path=path, want=want, got=got)
55
55
 
56
56
 
57
+ def dev_fingerprint_message(sdk: str, library: str) -> str:
58
+ """Rule r6's exact refusal of a library whose fingerprint is not this dev
59
+ SDK's (spec/abi-v2/docs.md): `sdk` is the SDK's own fingerprint and
60
+ `library` the library's, both full "sha256:" spellings."""
61
+ return f"this SDK speaks dev fingerprint {sdk}; the library has {library} — update your dev SDK"
62
+
63
+
64
+ def _refuse_fingerprint(path: str, got: object) -> None:
65
+ """Loader step 4's fingerprint refusal: CHTYPES_ARTIFACT_INCOMPATIBLE.
66
+ While this generation's description is unstable (a 2.0.0-dev SDK), its
67
+ message is exactly rule r6's; after the lock it is the ordinary refusal."""
68
+ want = _decls.CHS_ABI_FINGERPRINT
69
+ cls = _errmap.loader_error_class("fingerprint")
70
+ if _decls.CHS_ABI_STABILITY == "unstable":
71
+ message = dev_fingerprint_message(want, str(got))
72
+ raise cls(message, reason="fingerprint", path=path, want=want, got=got)
73
+ raise cls(reason="fingerprint", path=path, want=want, got=got)
74
+
75
+
57
76
  def _glibc_version() -> tuple[int, int] | None:
58
77
  """Resolve `gnu_get_libc_version` dynamically from the running process:
59
78
  `ctypes.CDLL(None)` is the process image's own global symbols (glibc's,
@@ -193,9 +212,7 @@ def _open(
193
212
  info = _parse_build_info(raw, path)
194
213
 
195
214
  if info["abi_fingerprint"] != _decls.CHS_ABI_FINGERPRINT:
196
- _refuse(
197
- "fingerprint", path, want=_decls.CHS_ABI_FINGERPRINT, got=info.get("abi_fingerprint")
198
- )
215
+ _refuse_fingerprint(path, info.get("abi_fingerprint"))
199
216
 
200
217
  if not skip_step5:
201
218
  _cross_check(info, predicate, path)
@@ -231,7 +248,7 @@ def open(
231
248
  timezone: bytes = b"",
232
249
  defaults: bytes = b"",
233
250
  ) -> LoadResult:
234
- """Load and verify a v1 artifact at `path` against its (already verified
251
+ """Load and verify an ABI v2 artifact at `path` against its (already verified
235
252
  elsewhere) signed `predicate`, then set the image zone (`timezone`, empty
236
253
  = UTC) and the default settings (`defaults`, a JSON object of string
237
254
  values, empty for none): step 7. Raises an artifact error naming the exact