chtypes 2.0.0.dev10__tar.gz → 2.0.0.dev12__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 (109) hide show
  1. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/CHANGELOG.md +18 -0
  2. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/PKG-INFO +4 -4
  3. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/README.md +3 -3
  4. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/pyproject.toml +1 -1
  5. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/__init__.py +24 -3
  6. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_abi2/_decls.py +26 -2
  7. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_abi2/_errmap.py +1 -1
  8. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_abi2/_vocab.py +92 -4
  9. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_decode.py +51 -4
  10. chtypes-2.0.0.dev12/src/chtypes/_input.py +376 -0
  11. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ocifetch/_ensure.py +70 -16
  12. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/errors.py +3 -0
  13. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/library.py +101 -15
  14. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/results.py +63 -9
  15. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/abi2/test_public_library.py +129 -5
  16. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/abi2/test_reader_rules.py +1 -1
  17. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/api/test_decode.py +209 -18
  18. chtypes-2.0.0.dev12/tests/api/test_input.py +238 -0
  19. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/goldens_v1/data/stub-goldens.json +2 -2
  20. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/goldens_v1/test_runner.py +5 -0
  21. chtypes-2.0.0.dev12/tests/ocifetch/test_preseed_scan.py +161 -0
  22. chtypes-2.0.0.dev12/tests/ocifetch/test_revocation_statement.py +240 -0
  23. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/uv.lock +1 -1
  24. chtypes-2.0.0.dev10/src/chtypes/_input.py +0 -185
  25. chtypes-2.0.0.dev10/tests/api/test_input.py +0 -104
  26. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/.gitignore +0 -0
  27. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/LICENSE +0 -0
  28. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/__main__.py +0 -0
  29. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_abi2/__init__.py +0 -0
  30. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_abi2/_errors.py +0 -0
  31. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_abi2/_loader.py +0 -0
  32. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_advisory.py +0 -0
  33. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_codes.py +0 -0
  34. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ed25519.py +0 -0
  35. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_guard.py +0 -0
  36. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ocifetch/__init__.py +0 -0
  37. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ocifetch/_channel.py +0 -0
  38. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ocifetch/_constants.py +0 -0
  39. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ocifetch/_dsse.py +0 -0
  40. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ocifetch/_errors.py +0 -0
  41. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ocifetch/_faults.py +0 -0
  42. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ocifetch/_goldens.py +0 -0
  43. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ocifetch/_hold.py +0 -0
  44. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ocifetch/_http.py +0 -0
  45. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ocifetch/_layout.py +0 -0
  46. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ocifetch/_lock.py +0 -0
  47. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ocifetch/_oci.py +0 -0
  48. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ocifetch/_prune.py +0 -0
  49. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ocifetch/_referrers.py +0 -0
  50. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ocifetch/_resolve.py +0 -0
  51. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ocifetch/_retired.py +0 -0
  52. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ocifetch/_revocation.py +0 -0
  53. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_ocifetch/_unpack.py +0 -0
  54. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/_setup.py +0 -0
  55. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/py.typed +0 -0
  56. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/src/chtypes/registry.py +0 -0
  57. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/abi2/__init__.py +0 -0
  58. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/abi2/_stub_tree.py +0 -0
  59. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/abi2/conftest.py +0 -0
  60. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/abi2/test_conformance.py +0 -0
  61. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/abi2/test_dev_fingerprint.py +0 -0
  62. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/abi2/test_goldens_runner_stub.py +0 -0
  63. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/abi2/test_loader.py +0 -0
  64. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/abi2/test_public_open.py +0 -0
  65. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/abi2/test_public_registry.py +0 -0
  66. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/abi2/test_public_server.py +0 -0
  67. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/abi2/test_public_setup_cases.py +0 -0
  68. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/abi2/test_registry_fetch.py +0 -0
  69. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/abi2/test_registry_flight.py +0 -0
  70. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/api/__init__.py +0 -0
  71. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/api/test_trusted_keys.py +0 -0
  72. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/api/test_vocab.py +0 -0
  73. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/cli/__init__.py +0 -0
  74. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/cli/conftest.py +0 -0
  75. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/cli/test_devchannel.py +0 -0
  76. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/cli/test_main.py +0 -0
  77. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/cli/test_resolve_prune.py +0 -0
  78. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/cli/test_revocation_cli.py +0 -0
  79. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/conftest.py +0 -0
  80. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/goldens_v1/__init__.py +0 -0
  81. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/__init__.py +0 -0
  82. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/_bundle_support.py +0 -0
  83. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/_registry_support.py +0 -0
  84. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/_sign_support.py +0 -0
  85. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/conftest.py +0 -0
  86. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/test_cache_roots.py +0 -0
  87. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/test_cache_strict.py +0 -0
  88. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/test_conformance.py +0 -0
  89. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/test_devchannel.py +0 -0
  90. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/test_dsse.py +0 -0
  91. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/test_ensure.py +0 -0
  92. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/test_goldens.py +0 -0
  93. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/test_http.py +0 -0
  94. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/test_layout.py +0 -0
  95. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/test_lock.py +0 -0
  96. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/test_oci.py +0 -0
  97. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/test_prodv2_smoke.py +0 -0
  98. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/test_prodv2channel.py +0 -0
  99. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/test_retired.py +0 -0
  100. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/test_revocation.py +0 -0
  101. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/test_seam_gate.py +0 -0
  102. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/ocifetch/test_unpack.py +0 -0
  103. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/test_abi_identity.py +0 -0
  104. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/test_cache_roots_api.py +0 -0
  105. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/test_devchannel_registry.py +0 -0
  106. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/test_ed25519.py +0 -0
  107. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/test_examples_tour.py +0 -0
  108. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/test_fetch_options.py +0 -0
  109. {chtypes-2.0.0.dev10 → chtypes-2.0.0.dev12}/tests/test_support_v2_gen.py +0 -0
@@ -8,6 +8,15 @@ The four bindings in this repository are released together and give one answer,
8
8
 
9
9
  ### Added
10
10
 
11
+ - Tests: the shared revocation-statement table (`tests/fixtures/revocation-statement/cases.json`) runs against `verify_revocation` and `check_installed`: `superseded_by` must be a string (`""` = no fix), and the first verifying revocation in a listing wins. No behavior changed.
12
+ - `column_defaults` is covered by unit tests (ABI v2): the exact `insert_options` JSON for a UTF-8 value, a non-UTF-8 value (`value_b64`), an empty value (sent as `""`) and two entries in order, and the decode of a `default_override` cell (`Source.DEFAULT_OVERRIDE`, stored). The batches guide gains a usage section. No behavior changed.
13
+ - Docs: `docs/guides/batches.md` shows how a `column_defaults` value is read, in the body format's own field encoding (CSV quoting, TSV escapes, a JSON string or number), with a value that doesn't read refused at the call before any body byte.
14
+ - `CODE_DECLINED` (ABI v2, -2): the code a declined row, outcome or verdict carries, generated from the description and exported from `chtypes`, as `bindings-v1.md` section 3 promises.
15
+ - `CallError.reason` (ABI v2): the error's catalog id, read through `chs_error_reason` and passed through verbatim (ASCII, empty if none), on all four call classes.
16
+ - Spec batch 2, the options documents (ABI v2; moves the dev fingerprint): keyword-only `insertable_columns`, `column_defaults` (a sequence of `ColumnDefault`), `verdict_basis` (`VerdictBasis`: `INPUT`, `EXPORT`) and `defer_defaults` (`DeferDefaults`: `NONE`, `SERVER`) build `insert_options` for `Schema.row`, `Schema.rows`, `Schema.parse_block` and `Filter.rows`; `param_encoding` (`ParamEncoding`: `ESCAPED`, `RAW`) builds `filter_options` for `Schema.compile_filter`; `posture` (`Posture`: `CREATE`, `LOAD`) builds `schema_options` for `Library.compile_table`. `insert_options_extra`, `filter_options_extra` and `schema_options_extra` pass a member the binding has no name for through as JSON text, so the library, which refuses an unknown key (rule r1), is the only judge. A document with no member set is not sent. `Filter.rows` takes `columns` (`chs_filter_eval_body` takes the column list).
17
+ - Spec batch 2, a value that is not UTF-8 (ABI v2): a settings value, a query-parameter value, a `setup` default and a server profile's settings value is sent as `{"b64": ...}` (the content `json_object_byte_values`), where the binding used to refuse it, and `SchemaServer.settings` decodes the same form back (as `surrogateescape` text, the spelling the input side takes).
18
+ - Spec batch 2, the decline and refusal members (ABI v2): `RowResult`, `BatchResult` and `FilterResult` carry `reason` (the catalog id, present where the code is -2, `CHS_CODE_DECLINED`), `refused_at` (a `RefusalSite`: `CALL`, `BODY_READ`, `ROW`, `BODY_STEP`) and `refused_row`; `RowResult.verdict_reason`; `FilterRowError.reason`; `BatchResult.export_columns` and `BatchResult.export_declined_reason`.
19
+ - Spec batch 2, the schema description (ABI v2): `SchemaDescription.posture`, and `Column.default_support` (a `DefaultSupport`), `Column.default_support_reason` and `Column.reads`, reserved members a build reports when it implements them. `Source.DEFAULT_DEFERRED`, `Source.DEFAULT_OVERRIDE` (stored) and `DeclinedTier.SERVER_REFUSES` join the vocabularies.
11
20
  - A fetch-only call (#492): `Registry.fetch(request) -> Resolved` resolves, fetches, verifies and installs the build a request names into the cache, as `chtypes fetch` does, and opens nothing: no library is loaded and the process setup is untouched, so it needs no `setup`. It honors the registry's fetch options (offline, the cache, and under the production channel the bases, the trust and the lock), and a concurrent `fetch` and open of one request share one fetch. The `Resolved` names the installed version, build, digests and library path; errors are the fetch codes' classes.
12
21
  - `chtypes resolve <spelling> [--json]` (#493): what a line or version resolves to on every platform the registry offers, one `resolved <version> <platform> <build> <manifest>` line each, or with `--json` one JSON array of `{platform, version, build, manifest}` objects, each signed statement verified exactly as a fetch verifies it and no layer downloaded; `--offline` answers from the cache. The four CLIs print the same bytes, so one parser reads them (a CI cache key, for example).
13
22
  - `chtypes prune [--line <line>] [--keep <n>] [--dry-run]` (#494): removes the installed builds of each line and platform that at least n newer installed builds supersede (n defaults to 1), each with its record, its blobs and its `index.json` entry; `--dry-run` prints exactly what would go. It never removes a build a running process holds: a registry now holds every build it opens or fetches, with a shared `flock` on the entry's `verified.json` until the process exits, and prune removes an entry only after taking the exclusive lock without waiting, reporting it `in-use` otherwise. It never touches a system directory, nor, on the dev channel, another fingerprint's builds. The rules are `docs/guides/fetch-v1.md` sections 1 and 3, and the `resolve-build-*` and `prune-*` conformance cases hold all four bindings to them.
@@ -27,6 +36,11 @@ The four bindings in this repository are released together and give one answer,
27
36
 
28
37
  ### Changed
29
38
 
39
+ - **Breaking (vs the 2.0.0-dev releases):** the batch preview's default `doc_flags` is now 0 (the lean result): `Schema.rows` without `doc_flags=` returns no per-value documents. Pass `doc_flags=DocFlags.ALL` explicitly to get every column's per-value documents.
40
+ - **Breaking (ABI v2 dev): `BatchResult.spans` is a tuple of `Span | None`**, one entry per `rows` entry and index-aligned with it: `row_spans` carries `null` for a row the export did not carry (a skipped row, or a row a filter cut), which reads as `None`. It was the exported rows' spans only. Code that reads `span.off` from every entry raises `AttributeError` on a `None` entry: check each entry before reading it.
41
+ - **Breaking (ABI v2 dev): `AtMergeEntry.row` is `AtMergeEntry.part_row`**, the document's `part_row`.
42
+ - A document's `code` can be -2 (`CHS_CODE_DECLINED`) for a row, batch, filter result or verdict this build declined, and every decline names its `reason`.
43
+ - The refusal of a settings, query-parameter, default or server-settings value that is not valid UTF-8 is gone (it is the `{"b64": ...}` form now); a key that is not valid UTF-8, a macro and a server timezone are still refused, as a `UsageError` naming the input.
30
44
  - `chtypes list` and the tag listing name the published lines only (two-part, numeric order), as Go's always did; `chtypes resolve <line>` prints the exact version a line resolves to (#613).
31
45
  - **Breaking: the public surface the parity gate carried as exceptions is resolved, before the v2 lock (#499, #500).** A convenience exists in every binding or in none (`docs/reference/bindings-v1.md` §1, principle 2). Migration, old → new:
32
46
  - `chtypes.errors.internal` and `chtypes.errors.misuse` → private (#499): they were the binding's own construction helpers, never documented. Catch `InternalError` and `UsageError`, as before.
@@ -68,13 +82,17 @@ The four bindings in this repository are released together and give one answer,
68
82
  - **Enforcement gate lifted** for `26.8` on `darwin-arm64`.
69
83
  - **Enforcement gate lifted** for `26.9` on `darwin-arm64`.
70
84
  - `docs/limitations.md` is re-checked against artifact build `20261012.142240` (v2-dev.13), the library half measured on that build: functions that need a server, in a column expression, and a body the server may read serially or in parallel under a non-zero error budget are listed under "Declined by design"; the known divergence for a column expression that calls a function needing a server is retired, since that build declines those schemas (on 26.8 and 26.9 the `AI*` and `ai*` functions compile, as the page says); and the `lossy` raw-NUL TSV gap is marked fixed on that build and still present in the 1.0 libraries. `docs/guides/filters.md` gains a section on subcolumn filters and a JSON value typed by its batch.
85
+ - The ABI v2 spec now states the INSERT-time settings layering the library already uses, since artifact build `20261021.025722` (#632): at the INSERT, the schema's own settings (the compile profile) reach only the parse, minus a type gate, and every expression the INSERT evaluates and its limits (`max_partitions_per_insert_block` among them) run under the call's own settings, the server profile and the setup defaults only. A setting your INSERT session carries for those goes in the call's settings or the server profile (`docs/guides/settings.md`). No API change.
71
86
 
72
87
  ### Removed
73
88
 
89
+ - **Breaking (ABI v2 dev): `RowResult.unsupported_settings`**: the row document no longer carries `unsupported_settings`; the batch's and the filter result's lists stay.
74
90
  - `SchemaServer.filter_declined_settings` (a breaking change inside v2 dev, #588): the server member no longer carries the list. Read `SchemaDescription.filter_declined_settings`, whose `server`-layer entries are the profile's.
75
91
 
76
92
  ### Fixed
77
93
 
94
+ - An offline lookup no longer reads every cached blob once per pre-seeded entry (#690). For each `index.json` entry with no record, the lookup read every blob of the layout, layers included, to find its signature, so entries it could not install (a signature not present, or one no trusted key verifies) cost entries × cache bytes on every lookup: about 4.9 s for 27 such entries over 1.27 GB (`measured`, darwin-arm64). The signature referrers are now read once per lookup, and never a layer, because a blob larger than `limits.manifest_bytes` cannot be a manifest. Installed entries were already skipped. The build that is installed is verified exactly as before: its manifest against its descriptor, its whole layer against its digest, and its signature, platform, request and fingerprint. A unit test counts the blob reads of one lookup that installs nothing and holds them to at most two per blob and five per entry, with no layer read, at 2 and at 20 entries alike.
95
+ - Docs: `docs/guides/settings.md` names the ABI v2 admission time budget `chtypes_default_eval_cpu_nanos`, the evaluating thread's CPU time. Its examples used the 1.x name `chtypes_default_eval_wall_nanos`, which v2 refuses with `CHS_INVALID_ARGUMENT`.
78
96
  - A response body cut off part way (shorter than its Content-Length, a reset, a TLS close) is retried like a 5xx and, once the retry table is spent, is `CHTYPES_SOURCE_UNREACHABLE`; only an oversize body is `CHTYPES_ARTIFACT_CORRUPT`, and it is never retried (#641). Python took a body that ended before its Content-Length as the whole body and failed its digest check as corrupt without a retry; now a short body, or `http.client.IncompleteRead`, is retried and ends as unreachable. The rule is `docs/guides/fetch-v1.md` section 7, and the new `body-cut-off-then-ok` and `body-cut-off-exhausted` conformance cases hold every binding to it.
79
97
  - A chunked response body cut off before its terminating zero-length chunk is held to the same rule (#644): the new `body-cut-off-chunked-then-ok` and `body-cut-off-chunked-exhausted` conformance cases cut one on the layer blob GET, and this binding already retried it and ended as `CHTYPES_SOURCE_UNREACHABLE` once the retry table was spent. No behavior change; the case now holds it.
80
98
  - A settings or query-parameter key or value that is not valid UTF-8 is refused as a usage error; it was silently replaced with U+FFFD, so the library saw a different value. A string holding a lone surrogate (what `surrogateescape` makes of undecodable bytes) was sent as a `\udXXX` escape; the same inputs are refused now, for the per-call zone, the setup defaults and the server profile too. Valid UTF-8 serializes as before.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: chtypes
3
- Version: 2.0.0.dev10
3
+ Version: 2.0.0.dev12
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
@@ -43,7 +43,7 @@ uv add "chtypes>=2.0.0.dev0" # or: pip install "chtypes>=2.0.0.dev0"
43
43
 
44
44
  ```python
45
45
  import chtypes
46
- from chtypes import Format, Registry
46
+ from chtypes import DocFlags, Format, Registry
47
47
 
48
48
  chtypes.setup(timezone="UTC") # once, before the first open (optional)
49
49
  registry = Registry(autofetch=True)
@@ -51,7 +51,7 @@ library = registry.for_version("26.8") # a release line or an exact version
51
51
 
52
52
  ddl = b"CREATE TABLE t (x UInt8, ts DateTime DEFAULT now()) ENGINE = Memory"
53
53
  with library.compile_table(ddl) as schema:
54
- batch = schema.rows(Format.JSON_EACH_ROW, b'{"x":256}\n')
54
+ batch = schema.rows(Format.JSON_EACH_ROW, b'{"x":256}\n', doc_flags=DocFlags.ALL)
55
55
 
56
56
  row = batch.rows[0]
57
57
  print(batch.outcome) # accepted
@@ -96,7 +96,7 @@ A bad **row** is a verdict, not an exception: `outcome` becomes `Outcome.REJECTE
96
96
 
97
97
  **`ctypes` releases the GIL for the whole of a foreign call**, so calls on compiled handles run in parallel across threads. The package takes no lock around a call; it keeps a close guard per handle and one setup guard.
98
98
 
99
- **The INSERT column list is a keyword-only `columns`** on `schema.row`, `schema.rows` and `schema.parse_block`: `schema.row(Format.JSON_EACH_ROW, body, columns=["id", "e"])`. `None` or an empty sequence is the no-list shape; a list makes the data supply exactly those columns, with a listed `EPHEMERAL` value read and in scope for the DEFAULTs that reference it but never stored.
99
+ **The INSERT column list is a keyword-only `columns`** on `schema.row`, `schema.rows`, `schema.parse_block` and `filter.rows`: `schema.row(Format.JSON_EACH_ROW, body, columns=["id", "e"])`. `None` or an empty sequence is the no-list shape; a list makes the data supply exactly those columns, with a listed `EPHEMERAL` value read and in scope for the DEFAULTs that reference it but never stored.
100
100
 
101
101
  **Known gaps in 1.0** are listed, with workarounds, in [`docs/limitations.md`](https://github.com/wave-rf/chtypes/blob/main/docs/limitations.md#known-gaps-in-10).
102
102
 
@@ -24,7 +24,7 @@ uv add "chtypes>=2.0.0.dev0" # or: pip install "chtypes>=2.0.0.dev0"
24
24
 
25
25
  ```python
26
26
  import chtypes
27
- from chtypes import Format, Registry
27
+ from chtypes import DocFlags, Format, Registry
28
28
 
29
29
  chtypes.setup(timezone="UTC") # once, before the first open (optional)
30
30
  registry = Registry(autofetch=True)
@@ -32,7 +32,7 @@ library = registry.for_version("26.8") # a release line or an exact version
32
32
 
33
33
  ddl = b"CREATE TABLE t (x UInt8, ts DateTime DEFAULT now()) ENGINE = Memory"
34
34
  with library.compile_table(ddl) as schema:
35
- batch = schema.rows(Format.JSON_EACH_ROW, b'{"x":256}\n')
35
+ batch = schema.rows(Format.JSON_EACH_ROW, b'{"x":256}\n', doc_flags=DocFlags.ALL)
36
36
 
37
37
  row = batch.rows[0]
38
38
  print(batch.outcome) # accepted
@@ -77,7 +77,7 @@ A bad **row** is a verdict, not an exception: `outcome` becomes `Outcome.REJECTE
77
77
 
78
78
  **`ctypes` releases the GIL for the whole of a foreign call**, so calls on compiled handles run in parallel across threads. The package takes no lock around a call; it keeps a close guard per handle and one setup guard.
79
79
 
80
- **The INSERT column list is a keyword-only `columns`** on `schema.row`, `schema.rows` and `schema.parse_block`: `schema.row(Format.JSON_EACH_ROW, body, columns=["id", "e"])`. `None` or an empty sequence is the no-list shape; a list makes the data supply exactly those columns, with a listed `EPHEMERAL` value read and in scope for the DEFAULTs that reference it but never stored.
80
+ **The INSERT column list is a keyword-only `columns`** on `schema.row`, `schema.rows`, `schema.parse_block` and `filter.rows`: `schema.row(Format.JSON_EACH_ROW, body, columns=["id", "e"])`. `None` or an empty sequence is the no-list shape; a list makes the data supply exactly those columns, with a listed `EPHEMERAL` value read and in scope for the DEFAULTs that reference it but never stored.
81
81
 
82
82
  **Known gaps in 1.0** are listed, with workarounds, in [`docs/limitations.md`](https://github.com/wave-rf/chtypes/blob/main/docs/limitations.md#known-gaps-in-10).
83
83
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "chtypes"
3
- version = "2.0.0.dev10"
3
+ version = "2.0.0.dev12"
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"
@@ -13,14 +13,15 @@ C ABI. Nothing here reimplements a coercion rule, which is why the answers are
13
13
  exact by construction rather than approximately right.
14
14
 
15
15
  import chtypes
16
- from chtypes import Format, Registry
16
+ from chtypes import DocFlags, Format, Registry
17
17
 
18
18
  chtypes.setup(timezone="UTC") # once, before the first open
19
19
  registry = Registry(autofetch=True)
20
20
  library = registry.for_version("26.8") # a release line or an exact version
21
21
  ddl = b"CREATE TABLE t (ts DateTime, seq UInt8) ENGINE = Memory"
22
22
  with library.compile_table(ddl) as schema:
23
- batch = schema.rows(Format.JSON_EACH_ROW, b'{"ts":"2026-01-15 10:30:00","seq":256}\\n')
23
+ body = b'{"ts":"2026-01-15 10:30:00","seq":256}\\n'
24
+ batch = schema.rows(Format.JSON_EACH_ROW, body, doc_flags=DocFlags.ALL)
24
25
 
25
26
  batch.outcome # Outcome.ACCEPTED: the insert would succeed
26
27
  batch.transformed # the changes ClickHouse makes and reports as success
@@ -47,22 +48,34 @@ from importlib.metadata import PackageNotFoundError as _PackageNotFound
47
48
  from importlib.metadata import version as _package_version
48
49
 
49
50
  from ._abi2._vocab import (
51
+ CODE_DECLINED,
50
52
  EXPORT_NONE,
51
53
  DeclinedLayer,
52
54
  DeclinedTier,
53
55
  DefaultKind,
56
+ DefaultSupport,
54
57
  DiscoverQueryParam,
55
58
  DocFlags,
56
59
  FilterOutcome,
57
60
  Format,
58
61
  MergeReason,
59
62
  Outcome,
63
+ Posture,
60
64
  Reason,
65
+ RefusalSite,
61
66
  Source,
62
67
  Status,
63
68
  Verdict,
64
69
  )
65
- from ._input import BytesIn, ServerProfile, Settings
70
+ from ._input import (
71
+ BytesIn,
72
+ ColumnDefault,
73
+ DeferDefaults,
74
+ ParamEncoding,
75
+ ServerProfile,
76
+ Settings,
77
+ VerdictBasis,
78
+ )
66
79
  from ._setup import setup
67
80
  from .errors import (
68
81
  CODE_ARTIFACT_CORRUPT,
@@ -143,6 +156,7 @@ __all__ = [
143
156
  "CODE_SOURCE_RETIRED",
144
157
  "CODE_SOURCE_UNAUTHORIZED",
145
158
  "CODE_SOURCE_UNREACHABLE",
159
+ "CODE_DECLINED",
146
160
  "EXPORT_NONE",
147
161
  "Advisory",
148
162
  "ArtifactCorruptError",
@@ -163,11 +177,14 @@ __all__ = [
163
177
  "Capabilities",
164
178
  "ChtypesError",
165
179
  "Column",
180
+ "ColumnDefault",
166
181
  "Computed",
167
182
  "DeclinedLayer",
168
183
  "DeclinedSetting",
169
184
  "DeclinedTier",
185
+ "DeferDefaults",
170
186
  "DefaultKind",
187
+ "DefaultSupport",
171
188
  "DiscoverQueryParam",
172
189
  "DiscoveredColumn",
173
190
  "Discovery",
@@ -187,8 +204,11 @@ __all__ = [
187
204
  "Library",
188
205
  "MergeReason",
189
206
  "Outcome",
207
+ "ParamEncoding",
208
+ "Posture",
190
209
  "Reason",
191
210
  "Registry",
211
+ "RefusalSite",
192
212
  "Resolved",
193
213
  "Revocation",
194
214
  "RowResult",
@@ -213,6 +233,7 @@ __all__ = [
213
233
  "UsageError",
214
234
  "Value",
215
235
  "Verdict",
236
+ "VerdictBasis",
216
237
  "cache_root",
217
238
  "open_unverified",
218
239
  "search_dirs",
@@ -1,4 +1,4 @@
1
- # GENERATED by scripts/abi-v1/gen.py --major 2 from spec/abi-v2/abi.json (CHS_ABI_FINGERPRINT sha256:d60a681ea0e249ab9e2c83b50640ad9cef040261ddf61805106c93e2c68774e4) — DO NOT EDIT # noqa: E501
1
+ # GENERATED by scripts/abi-v1/gen.py --major 2 from spec/abi-v2/abi.json (CHS_ABI_FINGERPRINT sha256:d53239933966e15a3c363e631a94fbba1231d84c4300337115d3ae5377bb41c2) — DO NOT EDIT # noqa: E501
2
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
4
  dispatcher the conformance suite drives from tests/fixtures/abi-v2/cases.json.
@@ -19,7 +19,7 @@ from dataclasses import dataclass, field
19
19
  from . import _errmap
20
20
 
21
21
  CHS_ABI_VERSION = 2
22
- CHS_ABI_FINGERPRINT = "sha256:d60a681ea0e249ab9e2c83b50640ad9cef040261ddf61805106c93e2c68774e4"
22
+ CHS_ABI_FINGERPRINT = "sha256:d53239933966e15a3c363e631a94fbba1231d84c4300337115d3ae5377bb41c2"
23
23
 
24
24
  # The description's stability: "unstable" while this generation is being
25
25
  # designed, so CHS_ABI_FINGERPRINT moves with every change, and "locked" after
@@ -87,6 +87,7 @@ ALL_SYMBOLS: tuple[str, ...] = (
87
87
  "chs_error_column",
88
88
  "chs_error_free",
89
89
  "chs_error_message",
90
+ "chs_error_reason",
90
91
  "chs_error_status",
91
92
  "chs_filter_create",
92
93
  "chs_filter_eval_block",
@@ -248,6 +249,7 @@ _add("chs_error_ch_code", "scalar", "int32", _P("error", "handle", "chs_error"))
248
249
  _add("chs_error_ch_name", "handle", "chs_buf", _P("error", "handle", "chs_error"))
249
250
  _add("chs_error_message", "handle", "chs_buf", _P("error", "handle", "chs_error"))
250
251
  _add("chs_error_column", "handle", "chs_buf", _P("error", "handle", "chs_error"))
252
+ _add("chs_error_reason", "handle", "chs_buf", _P("error", "handle", "chs_error"))
251
253
  _add("chs_error_free", "void", None, _P("error", "handle", "chs_error", nullable=True))
252
254
  _add(
253
255
  "chs_live_handles",
@@ -371,6 +373,7 @@ _add(
371
373
  _P("body", "bytes_in", None),
372
374
  _P("settings", "bytes_in", None),
373
375
  _P("columns", "bytes_in", None),
376
+ _P("options", "bytes_in", None),
374
377
  _P("out", "out_handle", "chs_buf"),
375
378
  _P("err", "out_error", "chs_error", nullable=True),
376
379
  )
@@ -386,6 +389,7 @@ _add(
386
389
  _P("filter", "handle", "chs_filter", nullable=True),
387
390
  _P("export_format", "scalar", "int32"),
388
391
  _P("doc_flags", "scalar", "uint32"),
392
+ _P("options", "bytes_in", None),
389
393
  _P("out", "out_handle", "chs_buf"),
390
394
  _P("out_export", "out_handle", "chs_buf", nullable=True),
391
395
  _P("err", "out_error", "chs_error", nullable=True),
@@ -398,6 +402,7 @@ _add(
398
402
  _P("expr", "bytes_in", None),
399
403
  _P("query_params", "bytes_in", None),
400
404
  _P("settings", "bytes_in", None),
405
+ _P("options", "bytes_in", None),
401
406
  _P("out", "out_handle", "chs_filter"),
402
407
  _P("err", "out_error", "chs_error", nullable=True),
403
408
  )
@@ -410,6 +415,8 @@ _add(
410
415
  _P("format", "enum", "chs_format"),
411
416
  _P("body", "bytes_in", None),
412
417
  _P("settings", "bytes_in", None),
418
+ _P("columns", "bytes_in", None),
419
+ _P("options", "bytes_in", None),
413
420
  _P("out", "out_handle", "chs_buf"),
414
421
  _P("err", "out_error", "chs_error", nullable=True),
415
422
  )
@@ -422,6 +429,7 @@ _add(
422
429
  _P("body", "bytes_in", None),
423
430
  _P("settings", "bytes_in", None),
424
431
  _P("columns", "bytes_in", None),
432
+ _P("options", "bytes_in", None),
425
433
  _P("out", "out_handle", "chs_block"),
426
434
  _P("err", "out_error", "chs_error", nullable=True),
427
435
  )
@@ -563,6 +571,7 @@ class Api:
563
571
  info.ch_name.decode("ascii", "replace") if info else "",
564
572
  message,
565
573
  info.column if info else b"",
574
+ reason=info.reason.decode("ascii", "replace") if info else "",
566
575
  )
567
576
 
568
577
  def live_handles(self) -> bytes:
@@ -801,6 +810,7 @@ class Api:
801
810
  body: bytes | None,
802
811
  settings: bytes | None,
803
812
  columns: bytes | None,
813
+ options: bytes | None,
804
814
  ) -> bytes:
805
815
  """The generated call wrapper for chs_preview_row (thread class shared).
806
816
 
@@ -813,6 +823,7 @@ class Api:
813
823
  *_bytes_in(body),
814
824
  *_bytes_in(settings),
815
825
  *_bytes_in(columns),
826
+ *_bytes_in(options),
816
827
  ctypes.byref(out),
817
828
  ctypes.byref(err),
818
829
  )
@@ -829,6 +840,7 @@ class Api:
829
840
  filter: FilterHandle | None,
830
841
  export_format: int,
831
842
  doc_flags: int,
843
+ options: bytes | None,
832
844
  ) -> tuple[bytes, bytes | None]:
833
845
  """The generated call wrapper for chs_preview_batch (thread class shared).
834
846
 
@@ -845,6 +857,7 @@ class Api:
845
857
  None if filter is None else filter.value,
846
858
  int(export_format),
847
859
  int(doc_flags),
860
+ *_bytes_in(options),
848
861
  ctypes.byref(out),
849
862
  ctypes.byref(out_export),
850
863
  ctypes.byref(err),
@@ -861,6 +874,7 @@ class Api:
861
874
  expr: bytes | None,
862
875
  query_params: bytes | None,
863
876
  settings: bytes | None,
877
+ options: bytes | None,
864
878
  ) -> FilterHandle:
865
879
  """The generated call wrapper for chs_filter_create (thread class shared).
866
880
 
@@ -872,6 +886,7 @@ class Api:
872
886
  *_bytes_in(expr),
873
887
  *_bytes_in(query_params),
874
888
  *_bytes_in(settings),
889
+ *_bytes_in(options),
875
890
  ctypes.byref(out),
876
891
  ctypes.byref(err),
877
892
  )
@@ -884,6 +899,8 @@ class Api:
884
899
  format: int,
885
900
  body: bytes | None,
886
901
  settings: bytes | None,
902
+ columns: bytes | None,
903
+ options: bytes | None,
887
904
  ) -> bytes:
888
905
  """The generated call wrapper for chs_filter_eval_body (thread class shared).
889
906
 
@@ -895,6 +912,8 @@ class Api:
895
912
  int(format),
896
913
  *_bytes_in(body),
897
914
  *_bytes_in(settings),
915
+ *_bytes_in(columns),
916
+ *_bytes_in(options),
898
917
  ctypes.byref(out),
899
918
  ctypes.byref(err),
900
919
  )
@@ -908,6 +927,7 @@ class Api:
908
927
  body: bytes | None,
909
928
  settings: bytes | None,
910
929
  columns: bytes | None,
930
+ options: bytes | None,
911
931
  ) -> BlockHandle:
912
932
  """The generated call wrapper for chs_block_create (thread class shared).
913
933
 
@@ -920,6 +940,7 @@ class Api:
920
940
  *_bytes_in(body),
921
941
  *_bytes_in(settings),
922
942
  *_bytes_in(columns),
943
+ *_bytes_in(options),
923
944
  ctypes.byref(out),
924
945
  ctypes.byref(err),
925
946
  )
@@ -1007,6 +1028,7 @@ class ErrorInfo:
1007
1028
  ch_name: bytes
1008
1029
  message: bytes
1009
1030
  column: bytes
1031
+ reason: bytes = b""
1010
1032
 
1011
1033
 
1012
1034
  @dataclass
@@ -1068,6 +1090,7 @@ def _decode_error(api: Api, err_ptr: int) -> ErrorInfo:
1068
1090
  ch_name = _read_buf(api, api._raw["chs_error_ch_name"](err_ptr))
1069
1091
  message = _read_buf(api, api._raw["chs_error_message"](err_ptr))
1070
1092
  column = _read_buf(api, api._raw["chs_error_column"](err_ptr))
1093
+ reason = _read_buf(api, api._raw["chs_error_reason"](err_ptr))
1071
1094
  api._raw["chs_error_free"](err_ptr)
1072
1095
  return ErrorInfo(
1073
1096
  status=STATUS_BY_VALUE.get(status_val, f"UNKNOWN:{status_val}"),
@@ -1075,6 +1098,7 @@ def _decode_error(api: Api, err_ptr: int) -> ErrorInfo:
1075
1098
  ch_name=ch_name,
1076
1099
  message=message,
1077
1100
  column=column,
1101
+ reason=reason,
1078
1102
  )
1079
1103
 
1080
1104
 
@@ -1,4 +1,4 @@
1
- # GENERATED by scripts/abi-v1/gen.py --major 2 from spec/abi-v2/abi.json (CHS_ABI_FINGERPRINT sha256:d60a681ea0e249ab9e2c83b50640ad9cef040261ddf61805106c93e2c68774e4) — DO NOT EDIT # noqa: E501
1
+ # GENERATED by scripts/abi-v1/gen.py --major 2 from spec/abi-v2/abi.json (CHS_ABI_FINGERPRINT sha256:d53239933966e15a3c363e631a94fbba1231d84c4300337115d3ae5377bb41c2) — DO NOT EDIT # noqa: E501
2
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
4
  python/src/chtypes/_abi2/_errors.py). Only the MAPPING is generated: the
@@ -1,4 +1,4 @@
1
- # GENERATED by scripts/abi-v1/gen.py --major 2 from spec/abi-v2/abi.json (CHS_ABI_FINGERPRINT sha256:d60a681ea0e249ab9e2c83b50640ad9cef040261ddf61805106c93e2c68774e4) — DO NOT EDIT # noqa: E501
1
+ # GENERATED by scripts/abi-v1/gen.py --major 2 from spec/abi-v2/abi.json (CHS_ABI_FINGERPRINT sha256:d53239933966e15a3c363e631a94fbba1231d84c4300337115d3ae5377bb41c2) — DO NOT EDIT # noqa: E501
2
2
  """The Python binding's generated vocabularies, from spec/abi-v2/abi.json: the C
3
3
  enums (`Format`, `Status`), the document vocabularies (`Outcome`, `FilterOutcome`,
4
4
  `Verdict`, `DefaultKind`, `MergeReason`, `DeclinedTier`, `DeclinedLayer`, `Reason`,
@@ -256,6 +256,7 @@ class DeclinedTier(StrEnum):
256
256
  PREDICATE = "predicate"
257
257
  PREDICATE_UNFLIPPED = "predicate-unflipped"
258
258
  RESULT_CONTENT = "result-content"
259
+ SERVER_REFUSES = "server-refuses"
259
260
 
260
261
  @classmethod
261
262
  def _missing_(cls, value: object) -> DeclinedTier | None:
@@ -299,6 +300,83 @@ class DeclinedLayer(StrEnum):
299
300
  return cls(text)
300
301
 
301
302
 
303
+ class Posture(StrEnum):
304
+ """How a schema's statement was compiled: `create`, as a server's CREATE TABLE,
305
+ or `load`, as a server loads the stored definition of a table it holds."""
306
+
307
+ CREATE = "create"
308
+ LOAD = "load"
309
+
310
+ @classmethod
311
+ def _missing_(cls, value: object) -> Posture | None:
312
+ return _unknown_str(cls, value)
313
+
314
+ @property
315
+ def known(self) -> bool:
316
+ """Whether the description lists this value: False for exactly the unknown(n)
317
+ member an unlisted value reads as (rule r3)."""
318
+ return type(self)._value2member_map_.get(self._value_) is self
319
+
320
+ @classmethod
321
+ def of(cls, text: str) -> Posture:
322
+ """Map a document's spelling. One the description does not list is kept as
323
+ this vocabulary's unknown(n) member, carrying it (rule r3)."""
324
+ return cls(text)
325
+
326
+
327
+ class RefusalSite(StrEnum):
328
+ """Where a batch or filter document's refusal sits: `call` (the call, its settings or its
329
+ column list), `body_read` (the body outside any row: a header, the framing), `row` (one
330
+ row, `refused_row`) or `body_step` (a whole-body step)."""
331
+
332
+ CALL = "call"
333
+ BODY_READ = "body_read"
334
+ ROW = "row"
335
+ BODY_STEP = "body_step"
336
+
337
+ @classmethod
338
+ def _missing_(cls, value: object) -> RefusalSite | None:
339
+ return _unknown_str(cls, value)
340
+
341
+ @property
342
+ def known(self) -> bool:
343
+ """Whether the description lists this value: False for exactly the unknown(n)
344
+ member an unlisted value reads as (rule r3)."""
345
+ return type(self)._value2member_map_.get(self._value_) is self
346
+
347
+ @classmethod
348
+ def of(cls, text: str) -> RefusalSite:
349
+ """Map a document's spelling. One the description does not list is kept as
350
+ this vocabulary's unknown(n) member, carrying it (rule r3)."""
351
+ return cls(text)
352
+
353
+
354
+ class DefaultSupport(StrEnum):
355
+ """What this build does with a column's DEFAULT, as `schema_description` reports it per
356
+ column: `computed`, `generated`, `deferred` or `declined` (with a reason)."""
357
+
358
+ COMPUTED = "computed"
359
+ GENERATED = "generated"
360
+ DEFERRED = "deferred"
361
+ DECLINED = "declined"
362
+
363
+ @classmethod
364
+ def _missing_(cls, value: object) -> DefaultSupport | None:
365
+ return _unknown_str(cls, value)
366
+
367
+ @property
368
+ def known(self) -> bool:
369
+ """Whether the description lists this value: False for exactly the unknown(n)
370
+ member an unlisted value reads as (rule r3)."""
371
+ return type(self)._value2member_map_.get(self._value_) is self
372
+
373
+ @classmethod
374
+ def of(cls, text: str) -> DefaultSupport:
375
+ """Map a document's spelling. One the description does not list is kept as
376
+ this vocabulary's unknown(n) member, carrying it (rule r3)."""
377
+ return cls(text)
378
+
379
+
302
380
  class DiscoverQueryParam(StrEnum):
303
381
  """A query parameter of the SQL `discover_query` returns, which the caller binds
304
382
  when it runs the query."""
@@ -409,6 +487,8 @@ class Source:
409
487
  DEFAULT_EXPR_UNSUPPORTED: Final = "default_expr_unsupported"
410
488
  DEFAULT_VOLATILE_UNRESOLVED: Final = "default_volatile_unresolved"
411
489
  DEFAULT_PENDING: Final = "default_pending"
490
+ DEFAULT_DEFERRED: Final = "default_deferred"
491
+ DEFAULT_OVERRIDE: Final = "default_override"
412
492
 
413
493
  @staticmethod
414
494
  def known(source: str) -> bool:
@@ -417,9 +497,8 @@ class Source:
417
497
 
418
498
  @staticmethod
419
499
  def is_stored(source: str) -> bool:
420
- """The description's `is_stored` fact for `source`. The description does not yet
421
- say what an unknown(n) source reports (rule r3, "Facts without a fallback");
422
- until it does, an unlisted source is not stored."""
500
+ """The description's `is_stored` fact for `source`; an unknown(n) source
501
+ reports its fallback's (`skipped`), as rule r3 says."""
423
502
  return _SOURCE_IS_STORED.get(source, False)
424
503
 
425
504
 
@@ -435,6 +514,8 @@ _SOURCE_IS_STORED: Final[dict[str, bool]] = {
435
514
  "default_expr_unsupported": False,
436
515
  "default_volatile_unresolved": False,
437
516
  "default_pending": False,
517
+ "default_deferred": False,
518
+ "default_override": True,
438
519
  }
439
520
 
440
521
 
@@ -450,6 +531,10 @@ class DocFlags(IntFlag):
450
531
  # `chs_preview_batch`'s `export_format` for no export (`CHS_EXPORT_NONE`).
451
532
  EXPORT_NONE: Final = -1
452
533
 
534
+ # The code a declined row, outcome or verdict carries (`CHS_CODE_DECLINED`), outside
535
+ # ClickHouse's code table.
536
+ CODE_DECLINED: Final = -2
537
+
453
538
  # Every enum the description defines, by its own name, and the Python type that
454
539
  # spells it: rule r3's tests reach every one from here, so a new enum is covered
455
540
  # without a hand-kept list.
@@ -463,10 +548,13 @@ DESCRIBED_VOCABULARIES: Final[dict[str, type]] = {
463
548
  "batch_outcome": Outcome,
464
549
  "filter_outcome": FilterOutcome,
465
550
  "filter_verdict": Verdict,
551
+ "refusal_site": RefusalSite,
466
552
  "discover_query_param": DiscoverQueryParam,
467
553
  "default_kind": DefaultKind,
554
+ "default_support": DefaultSupport,
468
555
  "declined_tier": DeclinedTier,
469
556
  "declined_layer": DeclinedLayer,
557
+ "posture": Posture,
470
558
  }
471
559
 
472
560