chtypes 2.0.0.dev4__py3-none-any.whl → 2.0.0.dev6__py3-none-any.whl

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.
chtypes/__init__.py CHANGED
@@ -48,6 +48,7 @@ from importlib.metadata import version as _package_version
48
48
 
49
49
  from ._abi2._vocab import (
50
50
  EXPORT_NONE,
51
+ DeclinedLayer,
51
52
  DeclinedTier,
52
53
  DefaultKind,
53
54
  DiscoverQueryParam,
@@ -156,6 +157,7 @@ __all__ = [
156
157
  "ChtypesError",
157
158
  "Column",
158
159
  "Computed",
160
+ "DeclinedLayer",
159
161
  "DeclinedSetting",
160
162
  "DeclinedTier",
161
163
  "DefaultKind",
chtypes/_abi2/_decls.py CHANGED
@@ -1,4 +1,4 @@
1
- # GENERATED by scripts/abi-v1/gen.py --major 2 from spec/abi-v2/abi.json (CHS_ABI_FINGERPRINT sha256:28c7445ce6b5c6d0ae33177fd60eb7b3b5654a966c842b8d812aea622824dc72) — 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:d60a681ea0e249ab9e2c83b50640ad9cef040261ddf61805106c93e2c68774e4) — 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:28c7445ce6b5c6d0ae33177fd60eb7b3b5654a966c842b8d812aea622824dc72"
22
+ CHS_ABI_FINGERPRINT = "sha256:d60a681ea0e249ab9e2c83b50640ad9cef040261ddf61805106c93e2c68774e4"
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
chtypes/_abi2/_errmap.py CHANGED
@@ -1,4 +1,4 @@
1
- # GENERATED by scripts/abi-v1/gen.py --major 2 from spec/abi-v2/abi.json (CHS_ABI_FINGERPRINT sha256:28c7445ce6b5c6d0ae33177fd60eb7b3b5654a966c842b8d812aea622824dc72) — 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:d60a681ea0e249ab9e2c83b50640ad9cef040261ddf61805106c93e2c68774e4) — 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
chtypes/_abi2/_vocab.py CHANGED
@@ -1,8 +1,8 @@
1
- # GENERATED by scripts/abi-v1/gen.py --major 2 from spec/abi-v2/abi.json (CHS_ABI_FINGERPRINT sha256:28c7445ce6b5c6d0ae33177fd60eb7b3b5654a966c842b8d812aea622824dc72) — 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:d60a681ea0e249ab9e2c83b50640ad9cef040261ddf61805106c93e2c68774e4) — 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
- `Verdict`, `DefaultKind`, `MergeReason`, `DeclinedTier`, `Reason`, `Source`,
5
- `DiscoverQueryParam`) with the facts the description attaches to each value
4
+ `Verdict`, `DefaultKind`, `MergeReason`, `DeclinedTier`, `DeclinedLayer`, `Reason`,
5
+ `Source`, `DiscoverQueryParam`) with the facts the description attaches to each value
6
6
  (`Format.ch_name`, `Reason` lossy, `Source` is_stored, `Verdict.answered`), and the
7
7
  `DocFlags` groups. No other file in this package keeps a copy of any of it.
8
8
 
@@ -250,7 +250,7 @@ class MergeReason(StrEnum):
250
250
 
251
251
 
252
252
  class DeclinedTier(StrEnum):
253
- """The WHERE-settings tier of a setting a server profile sets and this build's
253
+ """The WHERE-settings tier of a setting a settings layer sets and this build's
254
254
  filters do not honor in a WHERE, as a `DeclinedSetting` reports it."""
255
255
 
256
256
  PREDICATE = "predicate"
@@ -274,6 +274,31 @@ class DeclinedTier(StrEnum):
274
274
  return cls(text)
275
275
 
276
276
 
277
+ class DeclinedLayer(StrEnum):
278
+ """The settings layer a `DeclinedSetting` comes from, the highest one that sets
279
+ the name: `defaults`, `server` or `schema`, lowest first."""
280
+
281
+ DEFAULTS = "defaults"
282
+ SERVER = "server"
283
+ SCHEMA = "schema"
284
+
285
+ @classmethod
286
+ def _missing_(cls, value: object) -> DeclinedLayer | None:
287
+ return _unknown_str(cls, value)
288
+
289
+ @property
290
+ def known(self) -> bool:
291
+ """Whether the description lists this value: False for exactly the unknown(n)
292
+ member an unlisted value reads as (rule r3)."""
293
+ return type(self)._value2member_map_.get(self._value_) is self
294
+
295
+ @classmethod
296
+ def of(cls, text: str) -> DeclinedLayer:
297
+ """Map a document's spelling. One the description does not list is kept as
298
+ this vocabulary's unknown(n) member, carrying it (rule r3)."""
299
+ return cls(text)
300
+
301
+
277
302
  class DiscoverQueryParam(StrEnum):
278
303
  """A query parameter of the SQL `discover_query` returns, which the caller binds
279
304
  when it runs the query."""
@@ -441,6 +466,7 @@ DESCRIBED_VOCABULARIES: Final[dict[str, type]] = {
441
466
  "discover_query_param": DiscoverQueryParam,
442
467
  "default_kind": DefaultKind,
443
468
  "declined_tier": DeclinedTier,
469
+ "declined_layer": DeclinedLayer,
444
470
  }
445
471
 
446
472
 
chtypes/_decode.py CHANGED
@@ -29,6 +29,7 @@ from collections.abc import Callable, Mapping
29
29
  from typing import Any
30
30
 
31
31
  from ._abi2._vocab import (
32
+ DeclinedLayer,
32
33
  DeclinedTier,
33
34
  DefaultKind,
34
35
  FilterOutcome,
@@ -504,10 +505,11 @@ def _string_map(obj: Mapping[str, Any], key: str, where: str) -> dict[str, str]
504
505
 
505
506
 
506
507
  def _declined_setting(obj: dict[str, Any], where: str) -> DeclinedSetting:
507
- # An unlisted tier is its unknown(n): kept, never a failure (rule r3).
508
+ # An unlisted tier or layer is its unknown(n): kept, never a failure (rule r3).
508
509
  return DeclinedSetting(
509
510
  name=_name(obj, "name", where),
510
511
  tier=DeclinedTier.of(_text(obj, "tier", where)),
512
+ layer=DeclinedLayer.of(_text(obj, "layer", where)),
511
513
  )
512
514
 
513
515
 
@@ -516,9 +518,6 @@ def _server(obj: dict[str, Any], where: str) -> SchemaServer:
516
518
  timezone=_text(obj, "timezone", where),
517
519
  settings=_string_map(obj, "settings", where) or {},
518
520
  macros=_string_map(obj, "macros", where),
519
- filter_declined_settings=_objects(
520
- obj, "filter_declined_settings", where, _declined_setting
521
- ),
522
521
  )
523
522
 
524
523
 
@@ -546,6 +545,10 @@ def decode_schema_description(raw: bytes) -> SchemaDescription:
546
545
  if replicated is None
547
546
  else _replicated(_obj(replicated, where, "replicated"), f"{where}.replicated")
548
547
  ),
548
+ # Over every layer known at schema compile, with or without a server.
549
+ filter_declined_settings=_objects(
550
+ obj, "filter_declined_settings", where, _declined_setting
551
+ ),
549
552
  )
550
553
 
551
554
 
@@ -79,6 +79,7 @@ __all__ = [
79
79
  "visible",
80
80
  "use_dev_channel_for_tests",
81
81
  "use_fetch_v1_for_tests",
82
+ "use_prod_v2_for_tests",
82
83
  ]
83
84
 
84
85
  # The dev channel's registry and key (spec/abi-v2/docs.md, rule r6).
@@ -165,6 +166,25 @@ FETCH_V1_CHANNEL: Final = Channel(
165
166
  pinnable=True,
166
167
  )
167
168
 
169
+ # The production generation-2 channel a 2.0.0 SDK speaks after the lock: the v1
170
+ # contract with v2 values, from the generated constants (docs/guides/fetch-v1.md,
171
+ # "Generation 2 after the lock"). It trusts the release key, honors every
172
+ # override and pin, and has no alias step. NOT the default: only
173
+ # use_prod_v2_for_tests selects it, until the lock change makes it active()'s
174
+ # fallback.
175
+ PROD_V2_CHANNEL: Final = Channel(
176
+ name=C.PROD_V2_NAME,
177
+ abi=C.PROD_V2_ABI_GENERATION,
178
+ record_schema=C.PROD_V2_RECORD_SCHEMA,
179
+ root_leaf=C.PROD_V2_CACHE_DIR,
180
+ subroot=C.PROD_V2_CACHE_DIR,
181
+ system_dirs=C.PROD_V2_SYSTEM_DIRS,
182
+ bases=C.PROD_V2_BASES,
183
+ keys=C.RELEASE_KEYS,
184
+ overridable=True,
185
+ pinnable=True,
186
+ )
187
+
168
188
  _lock = threading.Lock()
169
189
  _current: Channel | None = None
170
190
 
@@ -224,6 +244,14 @@ def use_fetch_v1_for_tests() -> Callable[[], None]:
224
244
  return _use(FETCH_V1_CHANNEL)
225
245
 
226
246
 
247
+ def use_prod_v2_for_tests() -> Callable[[], None]:
248
+ """Make this TEST run speak the production generation-2 channel
249
+ (`PROD_V2_CHANNEL`): the v1 contract with abi 2, schema-2 records and the
250
+ `v2` subroot. Returns the restore function; raises outside a test run."""
251
+ _test_only("use_prod_v2_for_tests")
252
+ return _use(PROD_V2_CHANNEL)
253
+
254
+
227
255
  def allow_overrides_for_tests() -> Callable[[], None]:
228
256
  """Make this TEST run's dev channel honor the base, trust and unsigned
229
257
  overrides, so a test can reach a fixture registry signed with the test key;
@@ -277,7 +305,11 @@ def visible(predicate: object, channel: Channel | None = None) -> bool:
277
305
 
278
306
 
279
307
  def ahead_of_registry(
280
- alias_absent: bool, predicate: object, channel: Channel | None = None
308
+ alias_absent: bool,
309
+ predicate: object,
310
+ channel: Channel | None = None,
311
+ *,
312
+ cached_own_build: Callable[[], str | None] | None = None,
281
313
  ) -> None:
282
314
  """The dev channel's answer for an SDK whose fingerprint no published build
283
315
  carries yet (docs/guides/fetch-v1.md §3; public issue #578): when every base
@@ -287,11 +319,33 @@ def ahead_of_registry(
287
319
  build answers gets, naming both fingerprints. Nothing is installed and an
288
320
  install of that build is never reported, because the lookup this SDK opens
289
321
  through would refuse it. Returns in every other case: the alias answered,
290
- the tag's build is this SDK's own, or the contract has no own fingerprint."""
322
+ the tag's build is this SDK's own, or the contract has no own fingerprint.
323
+
324
+ The expired alias with a usable cache (public issue #581): `cached_own_build`
325
+ looks up, through the filter open uses, the cache's verified record of this
326
+ SDK's OWN fingerprint for the request, and returns its build id ("" for a
327
+ record that names none) or None for no record. When there is one the
328
+ message grows by `_cached_own_suffix`; the code does not change."""
291
329
  channel = channel or active()
292
330
  if not alias_absent or visible(predicate, channel):
293
331
  return
294
- raise ArtifactUnpublishedError(f"chtypes: {_ahead_message(channel.own_fingerprint, predicate)}")
332
+ message = _ahead_message(channel.own_fingerprint, predicate)
333
+ if cached_own_build is not None:
334
+ build = cached_own_build()
335
+ if build is not None:
336
+ message += _cached_own_suffix(build)
337
+ raise ArtifactUnpublishedError(f"chtypes: {message}")
338
+
339
+
340
+ def _cached_own_suffix(build: str) -> str:
341
+ """The clause appended when the cache holds an own-fingerprint build: "; a
342
+ cached build for this fingerprint (build <id>) is still usable by open;
343
+ upgrade the SDK to get newer builds", the parenthesis dropped when the
344
+ record names no build."""
345
+ suffix = "; a cached build for this fingerprint"
346
+ if build:
347
+ suffix += f" (build {build})"
348
+ return suffix + " is still usable by open; upgrade the SDK to get newer builds"
295
349
 
296
350
 
297
351
  def _ahead_message(own: str, predicate: object) -> str:
@@ -1,6 +1,6 @@
1
1
  # Code generated by scripts/fetch-v1/gen-constants.py from
2
2
  # spec/fetch-v1/constants.json. DO NOT EDIT.
3
- # Source sha256: 4554956faeb154fc324a6120b7b35976222c6bc8ecbce7fd0147502e3073611d
3
+ # Source sha256: 82afa8d6cba96c10b5945c6f7c1c8360a504cc8ac6231e74017cc6c20b908df6
4
4
  """The v1 fetch constants, generated: see docs/guides/fetch-v1.md."""
5
5
 
6
6
  from __future__ import annotations
@@ -101,6 +101,12 @@ RETIRED_MESSAGE_MAX_CODE_POINTS: Final[int] = 256
101
101
 
102
102
  CACHE_ROOT_TEMPLATE: Final[str] = "${XDG_CACHE_HOME:-$HOME/.cache}/chtypes/v1"
103
103
  SYSTEM_CACHE_DIRS: Final[tuple[str, ...]] = ("/usr/local/share/chtypes/v1", "/opt/chtypes/v1")
104
+ PROD_V2_NAME: Final[str] = "v2"
105
+ PROD_V2_ABI_GENERATION: Final[int] = 2
106
+ PROD_V2_RECORD_SCHEMA: Final[int] = 2
107
+ PROD_V2_CACHE_DIR: Final[str] = "v2"
108
+ PROD_V2_BASES: Final[tuple[str, ...]] = ("https://registry.wavehouse.dev/chtypes/v2",)
109
+ PROD_V2_SYSTEM_DIRS: Final[tuple[str, ...]] = ("/usr/local/share/chtypes/v2", "/opt/chtypes/v2")
104
110
  CACHE_UNPACKED_DIR: Final[str] = "unpacked/sha256"
105
111
  CACHE_VERIFIED_RECORD: Final[str] = "verified.json"
106
112
  CACHE_ANNOTATION_PREFIX: Final[str] = "dev.wavehouse.chtypes."
@@ -716,7 +716,11 @@ def _ensure_floating(
716
716
  # An install of another fingerprint's build, reached through the tag
717
717
  # because the registry has none at this SDK's own, is never reported
718
718
  # installed (public issue #578): refused before the cache is touched.
719
- _channel.ahead_of_registry(alias_absent, existing_record.predicate)
719
+ _channel.ahead_of_registry(
720
+ alias_absent,
721
+ existing_record.predicate,
722
+ cached_own_build=lambda: _cached_own_build(roots, platform_key, request.spelling),
723
+ )
720
724
  # A NEWER build within the request, installed beside it, is still the
721
725
  # answer ("monotonic-warning", docs/guides/fetch-v1.md §9).
722
726
  newer = _newer_installed(
@@ -812,7 +816,11 @@ def _ensure_floating(
812
816
  # own fingerprint answered 404 on every base, and the tag's build is
813
817
  # signed for another. Refused from the signed statement, before the
814
818
  # layer is requested, so nothing is downloaded or installed.
815
- _channel.ahead_of_registry(alias_absent, predicate)
819
+ _channel.ahead_of_registry(
820
+ alias_absent,
821
+ predicate,
822
+ cached_own_build=lambda: _cached_own_build(roots, platform_key, request.spelling),
823
+ )
816
824
  newer = _newer_installed(roots, platform_key, predicate, request.spelling)
817
825
  if newer is not None:
818
826
  newer_dir, newer_record, warning = newer
@@ -1235,6 +1243,25 @@ def with_notes(message: str, notes: Sequence[str]) -> str:
1235
1243
  return f"{message}. {' '.join(notes)}"
1236
1244
 
1237
1245
 
1246
+ def _cached_own_build(
1247
+ roots: Sequence[Path], platform_key: str, request_spelling: str
1248
+ ) -> str | None:
1249
+ """The build id of the newest cached record of this SDK's OWN fingerprint
1250
+ that answers the request (`resolve_installed`'s filter), "" when it names
1251
+ none, or None when the cache holds no such record (public issue #581)."""
1252
+ candidates = [
1253
+ record
1254
+ for _dir, record in list_verified_records(roots)
1255
+ if record.platform == platform_key
1256
+ and version_within_request(record.version, request_spelling)
1257
+ and _channel.visible(record.predicate)
1258
+ ]
1259
+ if not candidates:
1260
+ return None
1261
+ best = max(candidates, key=lambda r: (spelling_components(r.version), r.build))
1262
+ return best.build or ""
1263
+
1264
+
1238
1265
  def resolve_installed(request: Request, platform: str, options: Options) -> Resolved | None:
1239
1266
  """Cache-only: never touches the network (docs/guides/fetch-v1.md "The seam").
1240
1267
 
chtypes/registry.py CHANGED
@@ -15,13 +15,19 @@ The sequence of `for_version(request)`:
15
15
  Construction opens nothing. The binding orders and matches no versions itself:
16
16
  which installed build a floating request means, and the spelling rules, are the
17
17
  fetch layer's.
18
+
19
+ Opens of different requests never wait for each other's fetch (public issue
20
+ #491): the registry's lock guards its memo and the attempts in progress, and is
21
+ never held across steps 2 to 5. Concurrent opens of one request share one
22
+ attempt, and so one fetch, and each gets that attempt's `Library` or its error;
23
+ a failed attempt is never remembered, so the next open starts a new one.
18
24
  """
19
25
 
20
26
  from __future__ import annotations
21
27
 
22
28
  import os
23
29
  import threading
24
- from collections.abc import Sequence
30
+ from collections.abc import Callable, Sequence
25
31
  from dataclasses import dataclass
26
32
  from pathlib import Path
27
33
 
@@ -168,6 +174,19 @@ def _wrap(exc: FetchError) -> errors.ArtifactError:
168
174
  return wrapped
169
175
 
170
176
 
177
+ class _Flight:
178
+ """One attempt to open one request: the installed lookup, the fetch when
179
+ there is one, and the load. Every open of that request made while it is in
180
+ progress waits on it and gets its answer."""
181
+
182
+ __slots__ = ("done", "error", "library")
183
+
184
+ def __init__(self) -> None:
185
+ self.done = threading.Event()
186
+ self.library: Library | None = None
187
+ self.error: BaseException | None = None
188
+
189
+
171
190
  class Registry:
172
191
  """Opens versions. Safe across threads. `autofetch` defaults to
173
192
  `CHTYPES_AUTOFETCH`, and is off when that is unset.
@@ -175,6 +194,9 @@ class Registry:
175
194
  Construction opens nothing: only `for_version` and `preload` open an
176
195
  artifact. `preload` opens each listed request through the loader at
177
196
  construction, in list order, and never fetches, even with autofetch on.
197
+
198
+ An open never waits for another request's fetch, and concurrent opens of
199
+ one request share one fetch (public issue #491).
178
200
  """
179
201
 
180
202
  def __init__(
@@ -189,8 +211,14 @@ class Registry:
189
211
  env = os.environ.get(_fetch_constants.ENV_AUTOFETCH_NAME, "")
190
212
  autofetch = env.strip().lower() in _TRUTHY
191
213
  self._autofetch = autofetch
192
- self._lock = threading.RLock()
214
+ # Guards the memo and the attempts in progress, never a lookup, a fetch
215
+ # or a load.
216
+ self._lock = threading.Lock()
193
217
  self._memo: dict[str, Library] = {}
218
+ self._flights: dict[str, _Flight] = {}
219
+ # A test hook, None outside tests: called each time an open starts
220
+ # waiting on an attempt, its own or another open's.
221
+ self._on_wait: Callable[[str], None] | None = None
194
222
  if isinstance(preload, str):
195
223
  raise TypeError("preload must be a sequence of requests, not a single string")
196
224
  for request in preload:
@@ -221,30 +249,63 @@ class Registry:
221
249
  return tuple(seen)
222
250
 
223
251
  def _open(self, request: str, *, allow_fetch: bool) -> Library:
252
+ with self._lock:
253
+ hit = self._memo.get(request)
254
+ if hit is not None:
255
+ return hit
256
+ # A refused version spelling is the caller's own misuse, refused before
257
+ # anything is attempted, and unlocks nothing.
258
+ try:
259
+ fetch_request = Request(request)
260
+ except ValueError as exc:
261
+ raise errors.misuse(str(exc)) from None
262
+ # So is a pinning request on the dev channel (rule r6).
263
+ _refuse_pinning(self._fetch._to_options())
224
264
  with self._lock:
225
265
  hit = self._memo.get(request)
226
266
  if hit is not None:
227
267
  return hit
228
- # A refused version spelling is the caller's own misuse, refused
229
- # before anything is attempted, and unlocks nothing. An open that
230
- # attempted a load and failed unlocks the setup record while no
231
- # image has completed load step 7, whatever failed: the resolve,
232
- # the fetch, the signature or any load step (bindings-v1.md
233
- # section 6, rule 4).
234
- try:
235
- fetch_request = Request(request)
236
- except ValueError as exc:
237
- raise errors.misuse(str(exc)) from None
238
- # So is a pinning request on the dev channel (rule r6).
239
- _refuse_pinning(self._fetch._to_options())
240
- began = _setup.generation()
241
- try:
242
- library = self._resolve_and_open(request, fetch_request, allow_fetch)
243
- except Exception:
244
- _setup.open_failed(began)
245
- raise
246
- self._memo[request] = library
247
- return library
268
+ flight = self._flights.get(request)
269
+ lead = flight is None
270
+ if flight is None:
271
+ flight = self._flights[request] = _Flight()
272
+ on_wait = self._on_wait
273
+ if on_wait is not None:
274
+ on_wait(request)
275
+ if lead:
276
+ self._attempt(flight, request, fetch_request, allow_fetch)
277
+ else:
278
+ flight.done.wait()
279
+ if flight.error is not None:
280
+ raise flight.error
281
+ assert flight.library is not None
282
+ return flight.library
283
+
284
+ def _attempt(
285
+ self, flight: _Flight, request: str, fetch_request: Request, allow_fetch: bool
286
+ ) -> None:
287
+ """Run an attempt on the leading open's thread, with no lock held, then
288
+ release every open waiting on it. An attempt that tried a load and
289
+ failed unlocks the setup record while no image has completed load step
290
+ 7, whatever failed: the resolve, the fetch, the signature or any load
291
+ step (bindings-v1.md section 6, rule 4). It is never remembered."""
292
+ began = _setup.generation()
293
+ library: Library | None = None
294
+ error: BaseException | None = None
295
+ try:
296
+ library = self._resolve_and_open(request, fetch_request, allow_fetch)
297
+ except Exception as exc:
298
+ _setup.open_failed(began)
299
+ error = exc
300
+ except BaseException as exc:
301
+ error = exc
302
+ with self._lock:
303
+ del self._flights[request]
304
+ if error is None:
305
+ assert library is not None
306
+ self._memo[request] = library
307
+ flight.library, flight.error = library, error
308
+ flight.done.set()
248
309
 
249
310
  def _resolve_and_open(self, request: str, fetch_request: Request, allow_fetch: bool) -> Library:
250
311
  try:
chtypes/results.py CHANGED
@@ -14,7 +14,15 @@ from __future__ import annotations
14
14
  from collections.abc import Mapping
15
15
  from dataclasses import dataclass
16
16
 
17
- from ._abi2._vocab import DeclinedTier, DefaultKind, FilterOutcome, MergeReason, Outcome, Verdict
17
+ from ._abi2._vocab import (
18
+ DeclinedLayer,
19
+ DeclinedTier,
20
+ DefaultKind,
21
+ FilterOutcome,
22
+ MergeReason,
23
+ Outcome,
24
+ Verdict,
25
+ )
18
26
 
19
27
  __all__ = [
20
28
  "AtMergeEntry",
@@ -252,14 +260,17 @@ class Column:
252
260
 
253
261
  @dataclass(frozen=True, slots=True)
254
262
  class DeclinedSetting:
255
- """One setting a server's profile sets that this build's filters do not honor
256
- in a WHERE: an entry of the server's `filter_declined_settings` (ABI v2).
257
- `name` is bytes (from `name` or `name_b64`). `tier` is the tier this build
258
- line's WHERE-settings list gives it, a `DeclinedTier`; one the description
259
- does not list is its unknown(n) member (rule r3)."""
263
+ """One setting the schema compiles under that this build's filters do not
264
+ honor in a WHERE: an entry of the schema description's
265
+ `filter_declined_settings` (ABI v2). `name` is bytes (from `name` or
266
+ `name_b64`). `tier` is the tier this build line's WHERE-settings list gives
267
+ it, a `DeclinedTier`, and `layer` the settings layer it comes from, the
268
+ highest one that sets the name, a `DeclinedLayer`; a value the description
269
+ does not list is its vocabulary's unknown(n) member (rule r3)."""
260
270
 
261
271
  name: bytes
262
272
  tier: DeclinedTier
273
+ layer: DeclinedLayer
263
274
 
264
275
 
265
276
  @dataclass(frozen=True, slots=True)
@@ -269,17 +280,11 @@ class SchemaServer:
269
280
  data-derived. `timezone` is the zone the schema's types bind: the profile's,
270
281
  or else the image zone. `settings` is the profile's settings (`{}` when it
271
282
  gave none). `macros` is None exactly when the profile carried no macros
272
- (unknown), and a mapping, even an empty one, when it did (the complete set).
273
- `filter_declined_settings` is the settings the profile sets that this
274
- build's filters do not honor in a WHERE, in the profile's own order, empty
275
- when it lists none: a schema on a server that lists any is one
276
- `compile_filter` declines (`UnsupportedError`), and a consumer that streams
277
- rows refuses such a tenant (spec/abi-v2/where-settings/README.md)."""
283
+ (unknown), and a mapping, even an empty one, when it did (the complete set)."""
278
284
 
279
285
  timezone: str
280
286
  settings: Mapping[str, str]
281
287
  macros: Mapping[str, str] | None
282
- filter_declined_settings: tuple[DeclinedSetting, ...] = ()
283
288
 
284
289
 
285
290
  @dataclass(frozen=True, slots=True)
@@ -293,13 +298,22 @@ class SchemaReplicated:
293
298
 
294
299
  @dataclass(frozen=True, slots=True)
295
300
  class SchemaDescription:
296
- """A schema's columns, in declared order, and the server it was compiled on.
297
- `server` is None exactly when it was compiled without one; `replicated` is
298
- None when the document carries none."""
301
+ """A schema's columns, in declared order, the server it was compiled on, and
302
+ the settings its filters decline. `server` is None exactly when it was
303
+ compiled without one; `replicated` is None when the document carries none.
304
+ `filter_declined_settings` is the settings the schema compiles under that
305
+ this build's filters do not honor in a WHERE, over every layer known at
306
+ schema compile (the defaults `setup` set, the server profile and the
307
+ schema's own settings), empty when it lists none: one entry per name, at
308
+ the highest layer that sets it, ordered by layer and then by name bytes, as
309
+ the library wrote it. A schema that lists any is one `compile_filter`
310
+ declines (`UnsupportedError`), and a consumer that streams rows refuses
311
+ such a tenant (spec/abi-v2/where-settings/README.md)."""
299
312
 
300
313
  columns: tuple[Column, ...]
301
314
  server: SchemaServer | None = None
302
315
  replicated: SchemaReplicated | None = None
316
+ filter_declined_settings: tuple[DeclinedSetting, ...] = ()
303
317
 
304
318
 
305
319
  @dataclass(frozen=True, slots=True)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: chtypes
3
- Version: 2.0.0.dev4
3
+ Version: 2.0.0.dev6
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
@@ -1,6 +1,6 @@
1
- chtypes/__init__.py,sha256=9xXEUgqnxJmAjUbz8X3coym4UyM01HShX7Lrds751VM,6177
1
+ chtypes/__init__.py,sha256=SGE4VfnmW5NbOQSExtplVwFPhddBQHVJ38Yv-CUWJ0o,6217
2
2
  chtypes/__main__.py,sha256=XYGNTpTLXI1AUp7srvuNVv2SZAcfwLaXpoXRVInyhF4,14030
3
- chtypes/_decode.py,sha256=v5pdwphwAldVzgHg6saWsxqUFjMHqcMO-XOuDyuRVZg,22686
3
+ chtypes/_decode.py,sha256=owtRPXVPtNOGzQzgb37Rki7iceMoua_k_VWY38RkaIo,22852
4
4
  chtypes/_ed25519.py,sha256=uwaAKWvgoc936e1ZfgLrtR47W87WWCL541kFaqBXrB0,4141
5
5
  chtypes/_guard.py,sha256=zTtwprCS0XvGWY7GDozo-IP6GwjMAWl-o-AjShdCSVI,1985
6
6
  chtypes/_input.py,sha256=i4OUmgmHxx618g0DVFYy8LmHhggfBT03NyMxH3ptZBI,6020
@@ -8,19 +8,19 @@ chtypes/_setup.py,sha256=n84T0hFmXu_fdnXQIFhk3dMVL0_-yhfdRZsqCXTLzzg,6114
8
8
  chtypes/errors.py,sha256=7gDi9Ij8yptrr9E0LZyA2XkeaFFVyZoQMVQjQj6mn0s,9936
9
9
  chtypes/library.py,sha256=G6DJFiRuv8--JARxfiSNEqeFLkafaMs_n9nG-IwoC74,17878
10
10
  chtypes/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- chtypes/registry.py,sha256=Q3LR7wBs7Ggy_5xG_-0bZrTRgvRWJO5OJbD92ecUlt4,13786
12
- chtypes/results.py,sha256=OnxFUNyhlNeA2jwsMVAqYjKjmqguvKtWzrCwi7F6CFM,12123
11
+ chtypes/registry.py,sha256=ApkHjOx4jBxeKJCZ7aTsPDJCWFnSd6rDRLfXam4ddQg,16275
12
+ chtypes/results.py,sha256=gue7f4pqnpvXlSteYqhmqU1ZuAYCD7p4AgTiuYWpgYY,12591
13
13
  chtypes/_abi2/__init__.py,sha256=d3i7_iUDMFT1jg49vRQz1SMH6oseYZHUR0oPt6aSTiY,1042
14
- chtypes/_abi2/_decls.py,sha256=X88Ylb33Sw5iJjikVTfVzdgCfjGvKpn4F3mT0qAnD7I,38454
15
- chtypes/_abi2/_errmap.py,sha256=vNPgHFV742Px2aTyYqJez7I3qXRq80AOUcMqDvyPGFI,2886
14
+ chtypes/_abi2/_decls.py,sha256=tGj_gOkMsw9fv8lWBXHUMn6dfYqpkta_nq1BhT6p4Dk,38454
15
+ chtypes/_abi2/_errmap.py,sha256=BQ2Wgj8H3ukUQwCAKgUyAhs6xy5fDoYYLX1YZGdWEcA,2886
16
16
  chtypes/_abi2/_errors.py,sha256=wRE9M0oYtJz_9izQqpEBh5571M_1QzGWBoJ3pJTykWw,761
17
17
  chtypes/_abi2/_loader.py,sha256=VMWrbWMp9Uq3K-7a219lfqAmSmBlD2hcB6WDJgG8XG0,12514
18
- chtypes/_abi2/_vocab.py,sha256=rzbenqXqDoWZkvpjRw0UUBEkgWoOtE462QUGyCE3cTw,16516
18
+ chtypes/_abi2/_vocab.py,sha256=6Ly15gQ1Vf3SP8hDSWCg1jnwVEURCBWSj9LZgv23xfA,17442
19
19
  chtypes/_ocifetch/__init__.py,sha256=enfPOKkqP4kqAKqckBGWXN1OQsiYo9ngDP-wzG0zn2I,1484
20
- chtypes/_ocifetch/_channel.py,sha256=2L-sSetXv4iF0mpsIX4-iTAhNbu9eY1IsGnb4WTptwM,17980
21
- chtypes/_ocifetch/_constants.py,sha256=IZtAK3oxnCELZysvrzRozJkntxKSQllGjxod5No-Kco,5644
20
+ chtypes/_ocifetch/_channel.py,sha256=YEt6qlhr-AMFhSHefFvS5GQJ30-Qh4PAbGN6xnHZwxU,20217
21
+ chtypes/_ocifetch/_constants.py,sha256=Lt7hrSxFr5L2y87wsw33bbCekEwdq8wKn8N3i_r79o8,5974
22
22
  chtypes/_ocifetch/_dsse.py,sha256=0RaFJaG1jhXr1uPfuHxm7yAn6viNzYhfCRUf-sW5SvQ,9333
23
- chtypes/_ocifetch/_ensure.py,sha256=GtuYJJXhL0TbUypx94OPr3BhnkrQoHuWjZdPYrvpLgw,62597
23
+ chtypes/_ocifetch/_ensure.py,sha256=rI_xj0dccct7wMz0DwHoJTAB-yGVYFkLZ2Z0qRXuR30,63612
24
24
  chtypes/_ocifetch/_errors.py,sha256=TTYpwhvZ7MyD9Ssg5js8_YB8Fl30rYBPlENyAetqEbQ,7129
25
25
  chtypes/_ocifetch/_faults.py,sha256=HpoB9tJW7aLRiJdCFnspzkwhpFATZ6f6hGi49Mbfnhs,7609
26
26
  chtypes/_ocifetch/_goldens.py,sha256=8MicgeJSRd4WZkaEsdujRnOa7twQvbT-wfSMPZaD-ms,4191
@@ -31,8 +31,8 @@ chtypes/_ocifetch/_oci.py,sha256=UdA8QGTh1O27DBYRf5UxsevjgI52IecQlEf9IO6Y0A4,139
31
31
  chtypes/_ocifetch/_referrers.py,sha256=J2b4gN6vryz_IzYHxrd2Tp-tQO9Cz766rZtKgCVcKqA,6008
32
32
  chtypes/_ocifetch/_retired.py,sha256=MQ6nbWLJw50IZYY1VfM6AiCZ4BySK0GVkGVOtAXaq3Y,3060
33
33
  chtypes/_ocifetch/_unpack.py,sha256=Cn4-up63KL63L8pnkS5zwJ6VbbHPSigpCnmOdcHJ4RI,5609
34
- chtypes-2.0.0.dev4.dist-info/METADATA,sha256=xGAOsOpaNNPKh1cxhmBitwUrzSsCgiwBOqNltkBmWO0,11280
35
- chtypes-2.0.0.dev4.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
36
- chtypes-2.0.0.dev4.dist-info/entry_points.txt,sha256=TdNcluWBR0VOt5mVFROsp-NiVPAdR3EHo0UsHlMC0r0,50
37
- chtypes-2.0.0.dev4.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
38
- chtypes-2.0.0.dev4.dist-info/RECORD,,
34
+ chtypes-2.0.0.dev6.dist-info/METADATA,sha256=T0boAAXpcSjeW7OqcCM0WihNHOX7ZRGU4ePoQnAlL-I,11280
35
+ chtypes-2.0.0.dev6.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
36
+ chtypes-2.0.0.dev6.dist-info/entry_points.txt,sha256=TdNcluWBR0VOt5mVFROsp-NiVPAdR3EHo0UsHlMC0r0,50
37
+ chtypes-2.0.0.dev6.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
38
+ chtypes-2.0.0.dev6.dist-info/RECORD,,