chtypes 2.0.0.dev11__py3-none-any.whl → 2.0.0.dev13__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 +3 -2
- chtypes/_ocifetch/_ensure.py +106 -19
- chtypes/_ocifetch/_oci.py +41 -0
- chtypes/library.py +9 -3
- {chtypes-2.0.0.dev11.dist-info → chtypes-2.0.0.dev13.dist-info}/METADATA +3 -3
- {chtypes-2.0.0.dev11.dist-info → chtypes-2.0.0.dev13.dist-info}/RECORD +9 -9
- {chtypes-2.0.0.dev11.dist-info → chtypes-2.0.0.dev13.dist-info}/WHEEL +1 -1
- {chtypes-2.0.0.dev11.dist-info → chtypes-2.0.0.dev13.dist-info}/entry_points.txt +0 -0
- {chtypes-2.0.0.dev11.dist-info → chtypes-2.0.0.dev13.dist-info}/licenses/LICENSE +0 -0
chtypes/__init__.py
CHANGED
|
@@ -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
|
-
|
|
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
|
chtypes/_ocifetch/_ensure.py
CHANGED
|
@@ -75,6 +75,7 @@ from chtypes._ocifetch._layout import (
|
|
|
75
75
|
from chtypes._ocifetch._lock import Lock, LockPin, load_lock, new_lock, save_lock
|
|
76
76
|
from chtypes._ocifetch._oci import (
|
|
77
77
|
Descriptor,
|
|
78
|
+
copy_blob_verified,
|
|
78
79
|
fetch_blob_bytes,
|
|
79
80
|
fetch_blob_to_path,
|
|
80
81
|
fetch_manifest_by_digest,
|
|
@@ -86,6 +87,8 @@ from chtypes._ocifetch._oci import (
|
|
|
86
87
|
resolve_platform_manifest,
|
|
87
88
|
spelling_components,
|
|
88
89
|
validate_spelling,
|
|
90
|
+
verify_body_matches_digest,
|
|
91
|
+
verify_json_descriptor,
|
|
89
92
|
version_within_request,
|
|
90
93
|
)
|
|
91
94
|
from chtypes._ocifetch._referrers import ReferrerListing, discover_referrers, read_listing
|
|
@@ -1296,6 +1299,48 @@ def _ensure(
|
|
|
1296
1299
|
raise _translate_transport_error(e) from e
|
|
1297
1300
|
|
|
1298
1301
|
|
|
1302
|
+
def _local_bundle_referrers(
|
|
1303
|
+
blobs_dir: Path, skip: Collection[str], known: dict[str, bytes] | None = None
|
|
1304
|
+
) -> dict[str, list[tuple[str, dict]]]:
|
|
1305
|
+
"""Each subject manifest digest's signature referrer manifests among
|
|
1306
|
+
`blobs_dir`'s blobs, as (blob name, parsed manifest), in listing order.
|
|
1307
|
+
A referrer need not be listed in `index.json`, so every blob that could
|
|
1308
|
+
be one is read, once per lookup rather than once per entry. A blob named
|
|
1309
|
+
in `skip` (the caller's candidate layers) and a blob larger than
|
|
1310
|
+
`limits.manifest_bytes`, which cannot be a manifest, are never read, so
|
|
1311
|
+
no layer is read here, and a blob in `known` (bytes the caller already
|
|
1312
|
+
read, by name) is not read again (public issue #690)."""
|
|
1313
|
+
out: dict[str, list[tuple[str, dict]]] = {}
|
|
1314
|
+
try:
|
|
1315
|
+
blob_paths = list(blobs_dir.iterdir())
|
|
1316
|
+
except OSError:
|
|
1317
|
+
return out
|
|
1318
|
+
for blob_path in blob_paths:
|
|
1319
|
+
if blob_path.name in skip:
|
|
1320
|
+
continue
|
|
1321
|
+
try:
|
|
1322
|
+
body = known.get(blob_path.name) if known is not None else None
|
|
1323
|
+
if body is None:
|
|
1324
|
+
if blob_path.stat().st_size > C.MANIFEST_MAX_BYTES:
|
|
1325
|
+
continue
|
|
1326
|
+
body = blob_path.read_bytes()
|
|
1327
|
+
doc = json.loads(body)
|
|
1328
|
+
except (ValueError, OSError, UnicodeDecodeError):
|
|
1329
|
+
continue
|
|
1330
|
+
if not isinstance(doc, dict) or doc.get("mediaType") != C.MEDIA_TYPE_MANIFEST:
|
|
1331
|
+
continue
|
|
1332
|
+
subject = doc.get("subject") or {}
|
|
1333
|
+
subject_digest = subject.get("digest") if isinstance(subject, dict) else None
|
|
1334
|
+
if not isinstance(subject_digest, str):
|
|
1335
|
+
continue
|
|
1336
|
+
# A signature referrer only: a revocation of the manifest carries the same
|
|
1337
|
+
# bundle media type, and is not the signature of the artifact.
|
|
1338
|
+
if doc.get("artifactType") != C.MEDIA_TYPE_BUNDLE:
|
|
1339
|
+
continue
|
|
1340
|
+
out.setdefault(subject_digest, []).append((blob_path.name, doc))
|
|
1341
|
+
return out
|
|
1342
|
+
|
|
1343
|
+
|
|
1299
1344
|
def _verify_and_install_from_local_blobs(
|
|
1300
1345
|
*,
|
|
1301
1346
|
source_root: Path,
|
|
@@ -1303,6 +1348,8 @@ def _verify_and_install_from_local_blobs(
|
|
|
1303
1348
|
cache_write_root: Path,
|
|
1304
1349
|
trusted_keys: tuple[TrustedKey, ...],
|
|
1305
1350
|
visible_only: bool = False,
|
|
1351
|
+
referrers: dict[str, list[tuple[str, dict]]] | None = None,
|
|
1352
|
+
manifest_size: int | None = None,
|
|
1306
1353
|
) -> VerifiedRecord | None:
|
|
1307
1354
|
"""docs/guides/fetch-v1.md §1/§6: "A pre-seeded layout has entries in
|
|
1308
1355
|
`index.json` with no corresponding `unpacked/` directory yet; the first
|
|
@@ -1314,7 +1361,14 @@ def _verify_and_install_from_local_blobs(
|
|
|
1314
1361
|
`source_root/blobs/sha256/*`, never the network. Returns `None` — never
|
|
1315
1362
|
raises — for a missing, unreadable or untrusted entry, the same
|
|
1316
1363
|
tolerant shape `_find_verified_signature` uses for a network referrer:
|
|
1317
|
-
a bad pre-seed is "nothing usable here," not a crash.
|
|
1364
|
+
a bad pre-seed is "nothing usable here," not a crash.
|
|
1365
|
+
|
|
1366
|
+
The manifest blob is checked against `manifest_digest` (and against
|
|
1367
|
+
`manifest_size`, the index descriptor's size, when the caller has one)
|
|
1368
|
+
before it is parsed, and the layer blob against the manifest's layer
|
|
1369
|
+
descriptor (size and sha256) before it is decompressed: the same
|
|
1370
|
+
checks a download gets (§7.3), so no byte the signature does not cover
|
|
1371
|
+
reaches the install."""
|
|
1318
1372
|
blobs_dir = source_root / "blobs" / "sha256"
|
|
1319
1373
|
if not blobs_dir.is_dir():
|
|
1320
1374
|
return None
|
|
@@ -1323,28 +1377,25 @@ def _verify_and_install_from_local_blobs(
|
|
|
1323
1377
|
if not manifest_path.is_file():
|
|
1324
1378
|
return None
|
|
1325
1379
|
try:
|
|
1326
|
-
|
|
1380
|
+
manifest_bytes = manifest_path.read_bytes()
|
|
1381
|
+
verify_body_matches_digest(manifest_bytes, manifest_digest, what="pre-seeded manifest")
|
|
1382
|
+
if manifest_size is not None:
|
|
1383
|
+
verify_json_descriptor(
|
|
1384
|
+
manifest_bytes,
|
|
1385
|
+
Descriptor(media_type="", digest=manifest_digest, size=manifest_size),
|
|
1386
|
+
what="pre-seeded manifest",
|
|
1387
|
+
)
|
|
1388
|
+
manifest_doc = json.loads(manifest_bytes)
|
|
1327
1389
|
layer_desc = manifest_layer_descriptor(manifest_doc)
|
|
1328
1390
|
except (ValueError, OSError, FetchError):
|
|
1329
1391
|
return None
|
|
1330
1392
|
|
|
1393
|
+
if referrers is None:
|
|
1394
|
+
referrers = _local_bundle_referrers(blobs_dir, {parse_digest(layer_desc.digest)})
|
|
1331
1395
|
verified = None
|
|
1332
1396
|
bundle_digest = None
|
|
1333
1397
|
bundle_manifest_digest = None
|
|
1334
|
-
for
|
|
1335
|
-
try:
|
|
1336
|
-
doc = json.loads(blob_path.read_bytes())
|
|
1337
|
-
except (ValueError, OSError, UnicodeDecodeError):
|
|
1338
|
-
continue
|
|
1339
|
-
if not isinstance(doc, dict) or doc.get("mediaType") != C.MEDIA_TYPE_MANIFEST:
|
|
1340
|
-
continue
|
|
1341
|
-
subject = doc.get("subject") or {}
|
|
1342
|
-
if subject.get("digest") != manifest_digest:
|
|
1343
|
-
continue
|
|
1344
|
-
# A signature referrer only: a revocation of the manifest carries the same
|
|
1345
|
-
# bundle media type, and is not the signature of the artifact.
|
|
1346
|
-
if doc.get("artifactType") != C.MEDIA_TYPE_BUNDLE:
|
|
1347
|
-
continue
|
|
1398
|
+
for referrer_name, doc in referrers.get(manifest_digest, ()):
|
|
1348
1399
|
try:
|
|
1349
1400
|
referrer_layer = manifest_single_layer(doc, expected_media_type=C.MEDIA_TYPE_BUNDLE)
|
|
1350
1401
|
bundle_bytes = (blobs_dir / parse_digest(referrer_layer.digest)).read_bytes()
|
|
@@ -1354,7 +1405,7 @@ def _verify_and_install_from_local_blobs(
|
|
|
1354
1405
|
if candidate is not None:
|
|
1355
1406
|
verified = candidate
|
|
1356
1407
|
bundle_digest = referrer_layer.digest
|
|
1357
|
-
bundle_manifest_digest = "sha256:" +
|
|
1408
|
+
bundle_manifest_digest = "sha256:" + referrer_name
|
|
1358
1409
|
break
|
|
1359
1410
|
if verified is None:
|
|
1360
1411
|
return None
|
|
@@ -1383,9 +1434,18 @@ def _verify_and_install_from_local_blobs(
|
|
|
1383
1434
|
scratch = _scratch_root(cache_write_root)
|
|
1384
1435
|
tmp_dir = tempfile.mkdtemp(dir=str(scratch))
|
|
1385
1436
|
try:
|
|
1437
|
+
# Size and sha256 against the layer descriptor BEFORE decompressing
|
|
1438
|
+
# (§7.3), on a copy in scratch, which is then the file unpacked.
|
|
1439
|
+
verified_layer = os.path.join(tmp_dir, "layer")
|
|
1440
|
+
copy_blob_verified(
|
|
1441
|
+
str(layer_path),
|
|
1442
|
+
layer_desc,
|
|
1443
|
+
verified_layer,
|
|
1444
|
+
what=f"pre-seeded layer {layer_desc.digest}",
|
|
1445
|
+
)
|
|
1386
1446
|
unpacked_dir = os.path.join(tmp_dir, "unpacked")
|
|
1387
1447
|
unpack_tar_zst(
|
|
1388
|
-
|
|
1448
|
+
verified_layer,
|
|
1389
1449
|
unpacked_dir,
|
|
1390
1450
|
library_name=predicate["library"],
|
|
1391
1451
|
library_sha256=predicate["library_sha256"],
|
|
@@ -1422,7 +1482,9 @@ def _verify_preseeded_entries(roots: Sequence[Path], trusted_keys: tuple[Trusted
|
|
|
1422
1482
|
anywhere yet, and verifies+unpacks it from that root's OWN local blobs,
|
|
1423
1483
|
writing the result into `roots[0]` (the writable cache) regardless of
|
|
1424
1484
|
which root — including a read-only system directory — the blobs came
|
|
1425
|
-
from.
|
|
1485
|
+
from. An entry that already has a record is passed over without reading
|
|
1486
|
+
a blob, and each root's signature referrers are read once, never by
|
|
1487
|
+
reading a candidate's layer (public issue #690)."""
|
|
1426
1488
|
cache_write_root = roots[0]
|
|
1427
1489
|
already_verified = {record.manifest for _dir, record in list_verified_records(roots)}
|
|
1428
1490
|
for root in roots:
|
|
@@ -1431,16 +1493,41 @@ def _verify_preseeded_entries(roots: Sequence[Path], trusted_keys: tuple[Trusted
|
|
|
1431
1493
|
index_doc = json.loads(index_path.read_text(encoding="utf-8"))
|
|
1432
1494
|
except (OSError, ValueError):
|
|
1433
1495
|
continue
|
|
1496
|
+
blobs_dir = root / "blobs" / "sha256"
|
|
1497
|
+
candidates: list[str] = []
|
|
1498
|
+
candidate_layers: set[str] = set()
|
|
1499
|
+
manifests_read: dict[str, bytes] = {}
|
|
1500
|
+
sizes: dict[str, int] = {}
|
|
1434
1501
|
for m in index_doc.get("manifests") or []:
|
|
1435
1502
|
digest = m.get("digest")
|
|
1436
1503
|
if not digest or digest in already_verified:
|
|
1437
1504
|
continue
|
|
1505
|
+
candidates.append(digest)
|
|
1506
|
+
size = m.get("size")
|
|
1507
|
+
if isinstance(size, int) and not isinstance(size, bool):
|
|
1508
|
+
sizes[digest] = size
|
|
1509
|
+
try:
|
|
1510
|
+
manifest_hex = parse_digest(digest)
|
|
1511
|
+
manifest_bytes = (blobs_dir / manifest_hex).read_bytes()
|
|
1512
|
+
manifests_read[manifest_hex] = manifest_bytes
|
|
1513
|
+
layer = manifest_layer_descriptor(json.loads(manifest_bytes))
|
|
1514
|
+
candidate_layers.add(parse_digest(layer.digest))
|
|
1515
|
+
except (ValueError, OSError, FetchError):
|
|
1516
|
+
continue
|
|
1517
|
+
if not candidates:
|
|
1518
|
+
continue
|
|
1519
|
+
referrers = _local_bundle_referrers(blobs_dir, candidate_layers, manifests_read)
|
|
1520
|
+
for digest in candidates:
|
|
1521
|
+
if digest in already_verified:
|
|
1522
|
+
continue
|
|
1438
1523
|
record = _verify_and_install_from_local_blobs(
|
|
1439
1524
|
source_root=root,
|
|
1440
1525
|
manifest_digest=digest,
|
|
1441
1526
|
cache_write_root=cache_write_root,
|
|
1442
1527
|
trusted_keys=trusted_keys,
|
|
1443
1528
|
visible_only=True,
|
|
1529
|
+
referrers=referrers,
|
|
1530
|
+
manifest_size=sizes.get(digest),
|
|
1444
1531
|
)
|
|
1445
1532
|
if record is not None:
|
|
1446
1533
|
already_verified.add(digest)
|
chtypes/_ocifetch/_oci.py
CHANGED
|
@@ -26,6 +26,7 @@ from chtypes._ocifetch._http import (
|
|
|
26
26
|
|
|
27
27
|
__all__ = [
|
|
28
28
|
"Descriptor",
|
|
29
|
+
"copy_blob_verified",
|
|
29
30
|
"fetch_blob_bytes",
|
|
30
31
|
"fetch_blob_to_path",
|
|
31
32
|
"fetch_manifest_by_digest",
|
|
@@ -143,6 +144,46 @@ def verify_body_matches_digest(body: bytes, digest: str, *, what: str) -> None:
|
|
|
143
144
|
)
|
|
144
145
|
|
|
145
146
|
|
|
147
|
+
def copy_blob_verified(src_path: str, descriptor: Descriptor, dest_path: str, *, what: str) -> None:
|
|
148
|
+
"""Copy a LOCAL blob file (a pre-seeded layout's `blobs/sha256/<hex>`)
|
|
149
|
+
to `dest_path`, streaming, and check the copy's size and sha256 against
|
|
150
|
+
`descriptor` BEFORE the caller does anything else with it — the local
|
|
151
|
+
counterpart of `fetch_blob_to_path`, with the same §7.3 rule ("check
|
|
152
|
+
size and sha256 before decompressing"). The caller unpacks the copy it
|
|
153
|
+
verified, never the source file, so the bytes checked are the bytes
|
|
154
|
+
used. Reads at most `descriptor.size + 1` bytes; removes `dest_path` on
|
|
155
|
+
any failure."""
|
|
156
|
+
expected = parse_digest(descriptor.digest)
|
|
157
|
+
hasher = hashlib.sha256()
|
|
158
|
+
size = 0
|
|
159
|
+
try:
|
|
160
|
+
with open(src_path, "rb") as src, open(dest_path, "wb") as dst:
|
|
161
|
+
while size <= descriptor.size:
|
|
162
|
+
chunk = src.read(min(1 << 20, descriptor.size + 1 - size))
|
|
163
|
+
if not chunk:
|
|
164
|
+
break
|
|
165
|
+
hasher.update(chunk)
|
|
166
|
+
dst.write(chunk)
|
|
167
|
+
size += len(chunk)
|
|
168
|
+
if size > descriptor.size:
|
|
169
|
+
raise ArtifactCorruptError(
|
|
170
|
+
f"{what}: larger than the descriptor's size {descriptor.size}"
|
|
171
|
+
)
|
|
172
|
+
if size != descriptor.size:
|
|
173
|
+
raise ArtifactCorruptError(
|
|
174
|
+
f"{what}: size {size} disagreed with the descriptor's {descriptor.size}"
|
|
175
|
+
)
|
|
176
|
+
actual = hasher.hexdigest()
|
|
177
|
+
if actual != expected:
|
|
178
|
+
raise ArtifactCorruptError(f"{what}: sha256 {actual} disagreed with {expected}")
|
|
179
|
+
except BaseException:
|
|
180
|
+
try:
|
|
181
|
+
os.unlink(dest_path)
|
|
182
|
+
except OSError:
|
|
183
|
+
pass
|
|
184
|
+
raise
|
|
185
|
+
|
|
186
|
+
|
|
146
187
|
def resolve_platform_manifest(index_doc: dict, platform_key: str) -> Descriptor:
|
|
147
188
|
"""Pick the one manifest descriptor in an OCI image index matching
|
|
148
189
|
`platform_key` (e.g. "linux-arm64"), refusing a duplicate or absent
|
chtypes/library.py
CHANGED
|
@@ -54,6 +54,8 @@ __all__ = ["Block", "Filter", "Library", "Schema", "Server", "open_unverified"]
|
|
|
54
54
|
# One image per file, process-wide: keyed on the realpath's device and inode, so
|
|
55
55
|
# two registries, two spellings or a hardlink of one artifact share one image
|
|
56
56
|
# and one Library. Guarded by the setup lock, which an open holds throughout.
|
|
57
|
+
# The batch preview's default `doc_flags`: 0, the lean result (no per-value documents).
|
|
58
|
+
_LEAN_DOC_FLAGS = DocFlags(0)
|
|
57
59
|
_IMAGES: dict[tuple[int, int], Library] = {}
|
|
58
60
|
|
|
59
61
|
|
|
@@ -212,7 +214,8 @@ class Filter(_Handle):
|
|
|
212
214
|
insert_options_extra: Mapping[str, str] | None = None,
|
|
213
215
|
) -> FilterResult:
|
|
214
216
|
"""Evaluate over a body. `settings` and `session_timezone` are the body's
|
|
215
|
-
|
|
217
|
+
INSERT settings: they govern its parse and the expressions the INSERT
|
|
218
|
+
evaluates, never the WHERE, whose zone was fixed when the filter compiled.
|
|
216
219
|
`columns` is the INSERT column list and the keywords after it the
|
|
217
220
|
`insert_options` members, as for `Schema.rows`."""
|
|
218
221
|
payload = body_bytes(body)
|
|
@@ -304,11 +307,14 @@ class Schema(_Handle):
|
|
|
304
307
|
insert_options_extra: Mapping[str, str] | None = None,
|
|
305
308
|
row_filter: Filter | None = None,
|
|
306
309
|
export: Format | int | None = None,
|
|
307
|
-
doc_flags: DocFlags =
|
|
310
|
+
doc_flags: DocFlags = _LEAN_DOC_FLAGS,
|
|
308
311
|
) -> BatchResult:
|
|
309
312
|
"""A whole body. `export` asks for the accepted rows serialized in that
|
|
310
313
|
format (`payload`, and `spans`); to insert a body whose rows carry a
|
|
311
|
-
`default_generated` column, insert `payload`, never the original input.
|
|
314
|
+
`default_generated` column, insert `payload`, never the original input.
|
|
315
|
+
|
|
316
|
+
`doc_flags` chooses the document groups; absent means 0, the lean result
|
|
317
|
+
(no per-value documents). Pass `DocFlags.ALL` for every group."""
|
|
312
318
|
payload = body_bytes(body)
|
|
313
319
|
settings_bytes = settings_json(settings, session_timezone)
|
|
314
320
|
columns_bytes = columns_json(columns)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: chtypes
|
|
3
|
-
Version: 2.0.0.
|
|
3
|
+
Version: 2.0.0.dev13
|
|
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
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
chtypes/__init__.py,sha256=
|
|
1
|
+
chtypes/__init__.py,sha256=8bwCCMfg7k233x9tK6Eg8lITeC8EDwSS5M8VCkxbuPY,6736
|
|
2
2
|
chtypes/__main__.py,sha256=6qal_3mJBVfNc9LNHsSB0d9Sfurxix6QbNWG5TEa4L4,19392
|
|
3
3
|
chtypes/_advisory.py,sha256=wTRNdwqLiOGsFKZQ7CYZHsfIhDrKc_arpaxEYZCUxV4,1212
|
|
4
4
|
chtypes/_codes.py,sha256=mRhjP-7fOU6j15le7r1jHwLJkiClMIIIEtfOkriR7uE,1301
|
|
@@ -8,7 +8,7 @@ chtypes/_guard.py,sha256=kVgvxRWu7H-eba3hTqPBmpqjxOCWdQGwiFAHvSnl1OU,1996
|
|
|
8
8
|
chtypes/_input.py,sha256=ZAUEs3r26_CsFiIvaXV9P-F_C9jlRRzMNKgG--G4HnQ,15157
|
|
9
9
|
chtypes/_setup.py,sha256=7mXvPxLCHS9h1FRWNr5uKfCUg-Gk8VjmC-5KNW5HogI,6125
|
|
10
10
|
chtypes/errors.py,sha256=-sCgdySXZn5HRL8Vkwbj9gSvhj0nvCCjwt3mFn6gKIc,10511
|
|
11
|
-
chtypes/library.py,sha256=
|
|
11
|
+
chtypes/library.py,sha256=MYlk7ksWiq3OP2nJ4YoqRhP2rqLc_xdRktdNQAnwjm0,22290
|
|
12
12
|
chtypes/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
13
|
chtypes/registry.py,sha256=CQHnHr9T-2LyqRsYl5wdWKIVWCOiX9Vx4BLcZL2yCB0,23702
|
|
14
14
|
chtypes/results.py,sha256=1HUdvhrjeEl9Fm1GOJUXVREtc7HN31s2yrQbm5_ZeKQ,15397
|
|
@@ -22,7 +22,7 @@ chtypes/_ocifetch/__init__.py,sha256=Nwmn1_JqkRSy-1q8182RT5m4HJfbdJgr54it7_TKvBg
|
|
|
22
22
|
chtypes/_ocifetch/_channel.py,sha256=1MuIj5O8N1d8OdTN4Rx4zf3kc2Nh1hjx4o5BIE6JgmA,20484
|
|
23
23
|
chtypes/_ocifetch/_constants.py,sha256=Gk-h6UkPg5dvNlhkr8z-UY4Y866unUPOSpE8ZwJvoJw,6287
|
|
24
24
|
chtypes/_ocifetch/_dsse.py,sha256=nYkjmRefmVTonH1KUADNNUl0J9sh2C3fg-0WEyURjcc,9838
|
|
25
|
-
chtypes/_ocifetch/_ensure.py,sha256=
|
|
25
|
+
chtypes/_ocifetch/_ensure.py,sha256=0v-tGzC4P0oLtADN-YBHzAMWaqOc2bYincxwUAhWtyg,81190
|
|
26
26
|
chtypes/_ocifetch/_errors.py,sha256=SE0zcTUr1fSvSH7HiLGjAInYvD_im8_SyeZNf-VKzXI,7594
|
|
27
27
|
chtypes/_ocifetch/_faults.py,sha256=HpoB9tJW7aLRiJdCFnspzkwhpFATZ6f6hGi49Mbfnhs,7609
|
|
28
28
|
chtypes/_ocifetch/_goldens.py,sha256=8MicgeJSRd4WZkaEsdujRnOa7twQvbT-wfSMPZaD-ms,4191
|
|
@@ -30,15 +30,15 @@ chtypes/_ocifetch/_hold.py,sha256=AmXKLFWdPEmZ5fuxKbTKbzYn-Gue9AyMfYTquQ0qvOs,48
|
|
|
30
30
|
chtypes/_ocifetch/_http.py,sha256=3D8WZXAObw-IiZqLSh9GEys2EKOEE2i9CVfUqjLh3E0,29013
|
|
31
31
|
chtypes/_ocifetch/_layout.py,sha256=ezEoVrsSMhvDhQ4U04hsGdu1-_ISZQ4V6zg4gGIChTQ,21300
|
|
32
32
|
chtypes/_ocifetch/_lock.py,sha256=14_uex9qXdOht-5FSrSvFvd99-gB7DmI3bDuxXs4YU8,5530
|
|
33
|
-
chtypes/_ocifetch/_oci.py,sha256=
|
|
33
|
+
chtypes/_ocifetch/_oci.py,sha256=Xc0JEShGemdTlu2LviOBFSMTcjwCu9uP6jdG0qlKO80,15677
|
|
34
34
|
chtypes/_ocifetch/_prune.py,sha256=gPToHNkOOVjCWA-lowJHnGpguqOFXklUOQs7PAGfhBQ,10203
|
|
35
35
|
chtypes/_ocifetch/_referrers.py,sha256=SQ8BMVzzA1085azzfAA0Nw3GrHPjeu98smasKyS609A,10530
|
|
36
36
|
chtypes/_ocifetch/_resolve.py,sha256=Qv8xFUdOR-Kb_JqmUeDiQ4_Xv2ETuNFpmoDckMp7eV8,11239
|
|
37
37
|
chtypes/_ocifetch/_retired.py,sha256=mqnI9RA7UK0A5RthCeLlBeVAu5SHbtwKFwxsSZk5e6A,7018
|
|
38
38
|
chtypes/_ocifetch/_revocation.py,sha256=DdKRjFp1eFAxVD7DZHK1bj3_sWVLlaEkVEVx6JyV2Zs,23710
|
|
39
39
|
chtypes/_ocifetch/_unpack.py,sha256=Cn4-up63KL63L8pnkS5zwJ6VbbHPSigpCnmOdcHJ4RI,5609
|
|
40
|
-
chtypes-2.0.0.
|
|
41
|
-
chtypes-2.0.0.
|
|
42
|
-
chtypes-2.0.0.
|
|
43
|
-
chtypes-2.0.0.
|
|
44
|
-
chtypes-2.0.0.
|
|
40
|
+
chtypes-2.0.0.dev13.dist-info/METADATA,sha256=W3xyv6dfQ9wI53cfWtQWioHnctgRuShzOSDZC5H3Jv4,11365
|
|
41
|
+
chtypes-2.0.0.dev13.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
|
|
42
|
+
chtypes-2.0.0.dev13.dist-info/entry_points.txt,sha256=TdNcluWBR0VOt5mVFROsp-NiVPAdR3EHo0UsHlMC0r0,50
|
|
43
|
+
chtypes-2.0.0.dev13.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
44
|
+
chtypes-2.0.0.dev13.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|