chtypes 2.0.0.dev4__tar.gz → 2.0.0.dev6__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.
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/CHANGELOG.md +36 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/PKG-INFO +1 -1
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/pyproject.toml +1 -1
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/__init__.py +2 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_abi2/_decls.py +2 -2
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_abi2/_errmap.py +1 -1
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_abi2/_vocab.py +30 -4
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_decode.py +7 -4
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_ocifetch/_channel.py +57 -3
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_ocifetch/_constants.py +7 -1
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_ocifetch/_ensure.py +29 -2
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/registry.py +83 -22
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/results.py +30 -16
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/abi2/test_public_server.py +67 -25
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/abi2/test_public_setup_cases.py +11 -9
- chtypes-2.0.0.dev6/tests/abi2/test_registry_flight.py +189 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/ocifetch/test_conformance.py +90 -26
- chtypes-2.0.0.dev6/tests/ocifetch/test_prodv2_smoke.py +63 -0
- chtypes-2.0.0.dev6/tests/ocifetch/test_prodv2channel.py +70 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/uv.lock +1 -1
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/.gitignore +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/LICENSE +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/README.md +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/__main__.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_abi2/__init__.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_abi2/_errors.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_abi2/_loader.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_ed25519.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_guard.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_input.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_ocifetch/__init__.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_ocifetch/_dsse.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_ocifetch/_errors.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_ocifetch/_faults.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_ocifetch/_goldens.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_ocifetch/_http.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_ocifetch/_layout.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_ocifetch/_lock.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_ocifetch/_oci.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_ocifetch/_referrers.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_ocifetch/_retired.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_ocifetch/_unpack.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/_setup.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/errors.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/library.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/src/chtypes/py.typed +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/abi2/__init__.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/abi2/_stub_tree.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/abi2/conftest.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/abi2/test_conformance.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/abi2/test_dev_fingerprint.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/abi2/test_goldens_runner_stub.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/abi2/test_loader.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/abi2/test_public_library.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/abi2/test_public_open.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/abi2/test_public_registry.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/abi2/test_reader_rules.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/api/__init__.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/api/test_decode.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/api/test_input.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/api/test_vocab.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/cli/__init__.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/cli/conftest.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/cli/test_devchannel.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/cli/test_main.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/conftest.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/goldens_v1/__init__.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/goldens_v1/data/stub-goldens.json +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/goldens_v1/test_runner.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/ocifetch/__init__.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/ocifetch/_bundle_support.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/ocifetch/_registry_support.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/ocifetch/_sign_support.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/ocifetch/conftest.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/ocifetch/test_cache_roots.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/ocifetch/test_cache_strict.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/ocifetch/test_devchannel.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/ocifetch/test_dsse.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/ocifetch/test_ensure.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/ocifetch/test_goldens.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/ocifetch/test_http.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/ocifetch/test_layout.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/ocifetch/test_lock.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/ocifetch/test_oci.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/ocifetch/test_retired.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/ocifetch/test_seam_gate.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/ocifetch/test_unpack.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/test_abi_identity.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/test_cache_roots_api.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/test_devchannel_registry.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/test_ed25519.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/test_examples_tour.py +0 -0
- {chtypes-2.0.0.dev4 → chtypes-2.0.0.dev6}/tests/test_fetch_options.py +0 -0
|
@@ -8,16 +8,52 @@ The four bindings in this repository are released together and give one answer,
|
|
|
8
8
|
|
|
9
9
|
### Added
|
|
10
10
|
|
|
11
|
+
- Every settings layer's filter-declined settings, in one list (ABI v2; moves the dev fingerprint; #588): `SchemaDescription.filter_declined_settings`, a tuple of `DeclinedSetting`, decoded from `schema_description`'s new required top-level `filter_declined_settings`, over every layer known at schema compile (`setup`'s defaults as the compile captured them, the server profile, and the schema's own settings). `DeclinedSetting` gains `layer`, the highest layer that sets the name, from the new `DeclinedLayer` vocabulary (`DEFAULTS`, `SERVER`, `SCHEMA`, and its unknown(n)). One entry per name, ordered by layer and then by name bytes, as the library writes it; the binding sorts nothing.
|
|
12
|
+
- `Schema.describe` raises the library's `CHS_REJECTED` with ch_code 306 (TOO_DEEP_RECURSION), a `SchemaError`, for a deep input the server's stack check refuses (ABI v2: `chs_schema_describe` now lists `CHS_REJECTED`).
|
|
11
13
|
- The server's filter-declined settings (ABI v2; moves the dev fingerprint): `SchemaServer.filter_declined_settings`, a tuple of `DeclinedSetting` (`name`, `tier`), decoded from `schema_description`'s new required `server.filter_declined_settings`, with the new `DeclinedTier` vocabulary (`PREDICATE`, `PREDICATE_UNFLIPPED`, `RESULT_CONTENT`, and its unknown(n)). `compile_filter` on a schema whose server lists any is the library's `CHS_DECLINED`, an `UnsupportedError` carrying its message; a filter's own settings other than `session_timezone` are no longer declined at compile, and a declined one is named at evaluation instead.
|
|
12
14
|
- The v2 spec states that a filter verdict counts only when the evaluation's outcome is `ok`: over a body a server would not accept, every verdict is `d`.
|
|
13
15
|
- The v2 spec publishes the WHERE-affecting settings lists (`spec/abi-v2/where-settings/`) with the consumer rule.
|
|
14
16
|
- The v2 spec publishes the filter decline-reasons catalog (`spec/abi-v2/declines/`).
|
|
17
|
+
- The v2 spec's decline catalog has 49 entries, and it publishes the settings values a server refuses outright (`spec/abi-v2/where-settings/documented-pathological.tsv`).
|
|
18
|
+
- The v2 spec's decline catalog follows the producer's batch 11: its `server-profile-setting` entry now covers every settings layer the schema compiles under (the id is unchanged), the evaluation-time setting entries name only the filter's own settings, and its `stack-depth` entry lists `chs_schema_describe`.
|
|
15
19
|
- A `410 Gone` is a retired repository, and permanent (#571). Any request the fetch layer makes (a tag, an alias, a digest, a blob, `tags/list`, the referrers API or its fallback tag, after a redirect too) that answers `410` is now the new code `CHTYPES_SOURCE_RETIRED` (exit status 10), never retried and never sent to the next base, nor from the dev channel's alias to its tag. It was `CHTYPES_SOURCE_UNREACHABLE` (exit 3) with the registry's message dropped, and Go, Python and Rust moved on to the next base, so a mirror's 404 could hide the retirement. The error names the URL that answered and carries the registry's own message, with control and bidirectional-formatting characters removed and cut to 256 code points: Go `CodeSourceRetired` (`errors.Is(err, ErrSourceRetired)`), Python and TypeScript `SourceRetiredError`, Rust `Error::SourceRetired`. The rule is `docs/guides/fetch-v1.md` section 2, "A retired repository", and the `retired-410-*` and `list-tags-retired-410` conformance cases and one shared message table (`tests/fixtures/retired-message/cases.json`) hold all four bindings to it.
|
|
16
20
|
- A 2.0.0-dev SDK prefers the newest build of its own fingerprint (#511). A version request resolves `<tag>--fp-<fingerprint>` first, the alias the staging dev registry serves beside every dev tag, with the binding's own generated ABI fingerprint, and the tag itself only when every base answers the alias 404; any other failure of the alias request is that failure, with no fallback, and an alias whose index lacks the platform is `CHTYPES_ARTIFACT_UNPUBLISHED`. The dev channel's cache lookups (the installed-build lookup a registry open makes first, the offline answer, and the monotonic rule of a fetch) now see only records whose signed `abi_fingerprint` is the SDK's own, so a newer build of another fingerprint, installed by another dev SDK in the shared cache, is never returned or kept over this one's own, and is never removed or rewritten. So a dev build of a newer fingerprint no longer strands an older dev SDK until its consumers upgrade. Trust is unchanged (the signed predicate and the load checks decide), a listing never shows an alias, nothing records one, `list` and `where` are unchanged, and there is no option: both steps are the dev channel's alone, and the v1 contract and every production channel never take them. The rule is `docs/guides/fetch-v1.md` section 3, and the `dev-alias-*`, `resolve-installed-dev-alias-*` and `list-tags-dev-alias` conformance cases hold all four bindings to it.
|
|
17
21
|
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- `compile_filter` is the library's `CHS_DECLINED`, `UnsupportedError`, on a schema whose `filter_declined_settings` is not empty from any layer, and its message names each setting and its layer (ABI v2, #588). A declined setting from the defaults or the schema's own settings now fails the compile, where it was named at evaluation before; a filter's own settings and an evaluation's are still named at evaluation.
|
|
25
|
+
- **Enforcement gate lifted** for `26.3` on `linux-amd64`.
|
|
26
|
+
- **Enforcement gate lifted** for `26.7` on `linux-amd64`.
|
|
27
|
+
- **Enforcement gate lifted** for `26.8` on `linux-amd64`.
|
|
28
|
+
- **Enforcement gate lifted** for `26.9` on `linux-amd64`.
|
|
29
|
+
- **Enforcement gate lifted** for `26.3` on `linux-arm64`.
|
|
30
|
+
- **Enforcement gate lifted** for `26.7` on `linux-arm64`.
|
|
31
|
+
- **Enforcement gate lifted** for `26.8` on `linux-arm64`.
|
|
32
|
+
- **Enforcement gate lifted** for `26.9` on `linux-arm64`.
|
|
33
|
+
- **Enforcement gate lifted** for `26.7` on `darwin-arm64`.
|
|
34
|
+
- **Enforcement gate lifted** for `26.8` on `darwin-arm64`.
|
|
35
|
+
- **Enforcement gate lifted** for `26.9` on `darwin-arm64`.
|
|
36
|
+
- **Enforcement gate restored** for `26.3` on `linux-amd64`.
|
|
37
|
+
- **Enforcement gate restored** for `26.3` on `linux-arm64`.
|
|
38
|
+
- **Enforcement gate restored** for `26.7` on `linux-amd64`.
|
|
39
|
+
- **Enforcement gate restored** for `26.7` on `linux-arm64`.
|
|
40
|
+
- **Enforcement gate restored** for `26.8` on `linux-amd64`.
|
|
41
|
+
- **Enforcement gate restored** for `26.8` on `linux-arm64`.
|
|
42
|
+
- **Enforcement gate restored** for `26.9` on `linux-amd64`.
|
|
43
|
+
- **Enforcement gate restored** for `26.9` on `linux-arm64`.
|
|
44
|
+
- **Enforcement gate restored** for `26.7` on `darwin-arm64`.
|
|
45
|
+
- **Enforcement gate restored** for `26.8` on `darwin-arm64`.
|
|
46
|
+
- **Enforcement gate restored** for `26.9` on `darwin-arm64`.
|
|
47
|
+
|
|
48
|
+
### Removed
|
|
49
|
+
|
|
50
|
+
- `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.
|
|
51
|
+
|
|
18
52
|
### Fixed
|
|
19
53
|
|
|
54
|
+
- A 2.0.0-dev SDK whose own-fingerprint alias has expired, with a cached build of that fingerprint for the request, now says so in the `CHTYPES_ARTIFACT_UNPUBLISHED` message of `fetch` (#581): `; a cached build for this fingerprint (build <id>) is still usable by open; upgrade the SDK to get newer builds` is appended. The code, the exit status (4) and the cache are unchanged, and all four bindings give the same message (`fp-ahead-cached-own-fp`).
|
|
20
55
|
- A 2.0.0-dev SDK whose fingerprint no published build carries yet now fails closed with a precise message (#578). When every base answers its own alias 404 and the tag names a build signed for another fingerprint, `fetch` is `CHTYPES_ARTIFACT_UNPUBLISHED` (exit status 4): `no published build for this SDK's fingerprint <own fp>; newest published on this channel is <fp> (build <id>)`. It used to install that build, or report it already installed, and the lookup at open then answered `CHTYPES_ARTIFACT_MISSING` with advice to run `fetch`: a loop with no pointer to the cause. Nothing is downloaded or installed and the cache is unchanged. An alias that answers, a tag at the SDK's own fingerprint and the v1 contract are unchanged. All four bindings run the same fetch conformance cases, `fp-ahead-*`, and the rule is `docs/guides/fetch-v1.md` section 3.
|
|
56
|
+
- Opening a line no longer waits for another line's fetch: the registry never holds its lock across network I/O, and concurrent opens of one request share one fetch (#491).
|
|
21
57
|
|
|
22
58
|
## [1.1.0] — 2026-10-06
|
|
23
59
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: chtypes
|
|
3
|
-
Version: 2.0.0.
|
|
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
|
|
@@ -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",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# GENERATED by scripts/abi-v1/gen.py --major 2 from spec/abi-v2/abi.json (CHS_ABI_FINGERPRINT sha256:
|
|
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:
|
|
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
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# GENERATED by scripts/abi-v1/gen.py --major 2 from spec/abi-v2/abi.json (CHS_ABI_FINGERPRINT sha256:
|
|
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
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# GENERATED by scripts/abi-v1/gen.py --major 2 from spec/abi-v2/abi.json (CHS_ABI_FINGERPRINT sha256:
|
|
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`, `
|
|
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
|
|
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
|
|
|
@@ -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,
|
|
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
|
-
|
|
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:
|
|
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(
|
|
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(
|
|
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
|
|
|
@@ -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
|
-
|
|
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
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
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:
|
|
@@ -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
|
|
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
|
|
256
|
-
in a WHERE: an entry of the
|
|
257
|
-
`name` is bytes (from `name` or
|
|
258
|
-
line's WHERE-settings list gives
|
|
259
|
-
|
|
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,
|
|
297
|
-
`server` is None exactly when it was
|
|
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)
|