weftcodec 1.2.0__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.
@@ -0,0 +1,257 @@
1
+ Metadata-Version: 2.4
2
+ Name: weftcodec
3
+ Version: 1.2.0
4
+ Summary: Independent Python reader for Weft WFT1 frames and canonical WCB, with a PyTorch-facing dataset over a WeftFS mount
5
+ Author: WeftFS contributors
6
+ License: Apache-2.0
7
+ Project-URL: Source, https://github.com/infinityabundance/WeftFS
8
+ Keywords: weft,weftfs,codec,wft1,wcb,blake3,pytorch
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: Apache Software License
12
+ Classifier: Operating System :: POSIX :: Linux
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: System :: Filesystems
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+ Requires-Dist: blake3>=0.3.1
22
+ Requires-Dist: zstandard>=0.22
23
+ Provides-Extra: torch
24
+ Requires-Dist: torch; extra == "torch"
25
+ Provides-Extra: orbax
26
+ Requires-Dist: jax[cpu]>=0.4; extra == "orbax"
27
+ Requires-Dist: orbax-checkpoint>=0.5; extra == "orbax"
28
+
29
+ # weftcodec (Python)
30
+
31
+ An independent Python implementation of the WeftCodec v1 **reader**: WFT1 frame
32
+ parsing, canonical WCB decode/encode, domain-separated BLAKE3 content roots, and
33
+ a PyTorch-facing dataset over a mounted WeftFS directory.
34
+
35
+ There are **no Rust or Go extension modules**. This is a third implementation,
36
+ written from the normative specification and tested against Rust-generated
37
+ conformance vectors.
38
+
39
+ ## Install
40
+
41
+ ```sh
42
+ pip install dist/weftcodec-1.2.0-py3-none-any.whl
43
+ # with the optional dataset extra
44
+ pip install "dist/weftcodec-1.2.0-py3-none-any.whl[torch]"
45
+ # with the optional JAX/Orbax adapter extra
46
+ pip install "dist/weftcodec-1.2.0-py3-none-any.whl[orbax]"
47
+ ```
48
+
49
+ Dependencies: `blake3`, `zstandard`. `torch`, `jax`, and `orbax-checkpoint`
50
+ are optional and are only imported by their adapter modules.
51
+
52
+ > **PyPI publication requires an API token we do not have.** The wheel is built
53
+ > in the Docker court and attached to the GitHub release; it is not published to
54
+ > PyPI.
55
+
56
+ ## Usage
57
+
58
+ ```sh
59
+ python -m weftcodec verify FRAME # validate structure + hashes
60
+ python -m weftcodec decode FRAME OUT # exact plaintext bytes
61
+ python -m weftcodec inspect FRAME # metadata as JSON
62
+ python -m weftcodec verify FRAME --deps DEPS_DIR # REFERENCE/DELTA/DICTIONARY
63
+ ```
64
+
65
+ Exit codes: `0` success, `1` codec or I/O failure, `2` usage error.
66
+
67
+ ```python
68
+ from weftcodec import parse, content_root, verify_frame
69
+ from weftcodec.dependency import DirectoryResolver
70
+ from weftcodec.modes import decode_bytes
71
+
72
+ resolver = DirectoryResolver("deps") # files named by lowercase hex
73
+ frame_bytes = open("frame.wft1", "rb").read()
74
+ frame = parse(frame_bytes)
75
+ plaintext = decode_bytes(frame_bytes, resolver)
76
+ assert content_root(plaintext) == frame.header.content_hash
77
+
78
+ result = verify_frame("frame.wft1", resolver)
79
+ print(result.ok, result.mode, result.content_hash, result.computed_content_hash)
80
+ ```
81
+
82
+ ### WCB
83
+
84
+ ```python
85
+ from weftcodec import wcb
86
+
87
+ value = wcb.decode(bytes.fromhex("08030501610301050162050374776f05016300"))
88
+ assert wcb.encode(value) == bytes.fromhex("08030501610301050162050374776f05016300")
89
+ ```
90
+
91
+ Python/WCB mapping: `None`→null, `bool`, `U64`, `I64`, `str`, `bytes`,
92
+ `list`/`tuple`, `dict` (text keys), `Timestamp`. Map keys are sorted by their
93
+ full encoded bytes; duplicates are rejected.
94
+
95
+ ### PyTorch dataset
96
+
97
+ ```python
98
+ from weftcodec.torch import WeftMapDataset
99
+
100
+ dataset = WeftMapDataset("/mnt/weft/dataset")
101
+ path, raw = dataset[0] # (relative path, bytes)
102
+
103
+ import torch
104
+ tensors = WeftMapDataset("/mnt/weft/dataset", dtype=torch.uint8)
105
+ path, tensor = tensors[0] # torch.frombuffer view
106
+ ```
107
+
108
+ Entries are sorted by POSIX-relative path, so ordering is deterministic across
109
+ processes.
110
+
111
+ ### PyTorch Distributed Checkpoint adapter
112
+
113
+ `weftcodec.dcp` implements the shape of
114
+ `torch.distributed.checkpoint.StorageWriter` / `StorageReader` over a WeftFS
115
+ store. The training process does not need a FUSE mount: every durable byte goes
116
+ through the Rust `weftfs` CLI (`checkpoint write` / `checkpoint restore`).
117
+
118
+ ```python
119
+ import torch
120
+ import torch.distributed.checkpoint as dcp
121
+ from weftcodec.dcp import WeftStorageWriter, WeftStorageReader, init_store
122
+
123
+ init_store("/data/weft-store")
124
+
125
+ model = MyModel()
126
+ dcp.save(
127
+ model.state_dict(),
128
+ storage_writer=WeftStorageWriter(
129
+ "run-0001", # single WeftFS checkpoint name
130
+ store_root="/data/weft-store",
131
+ topology=8, # store every tensor split 8 ways on axis 0
132
+ shard_strategy="zstd", # exact; tensor-sharded is the mode-10 option
133
+ ),
134
+ no_dist=True,
135
+ )
136
+
137
+ fresh = MyModel()
138
+ dcp.load(
139
+ fresh.state_dict(),
140
+ storage_reader=WeftStorageReader("run-0001", store_root="/data/weft-store"),
141
+ no_dist=True,
142
+ )
143
+ ```
144
+
145
+ Async save (the encode/store work runs on a `ThreadPoolExecutor` worker, with a
146
+ hard per-tensor staging bound; tensors are still copied through host memory):
147
+
148
+ ```python
149
+ from weftcodec.dcp import save_checkpoint_async
150
+
151
+ handle = save_checkpoint_async(
152
+ model.state_dict(),
153
+ checkpoint_id="run-0002",
154
+ store_root="/data/weft-store",
155
+ topology=8,
156
+ staging_bytes=256 * 1024 * 1024, # 256 MiB bound on one resolved tensor copy
157
+ )
158
+ metadata = handle.result() # raises the save error on this thread
159
+ ```
160
+
161
+ Every checkpoint is a canonical `weft.checkpoint.v1` manifest plus mode-10 or
162
+ exact codec shards; the DCP metadata is canonical WCB at
163
+ `/checkpoints/<name>/dcp.metadata`. The adapter verifies each tensor's BLAKE3
164
+ content root against the Rust manifest before/after every transfer. Verify with:
165
+
166
+ ```sh
167
+ weftfs --store /data/weft-store checkpoint verify --name run-0001 --json
168
+ weftfs --store /data/weft-store verify --full --json
169
+ ```
170
+
171
+ A checkpoint written by the Rust CLI alone (plain safetensors tensor names) is
172
+ readable too: the adapter synthesises DCP metadata from the manifest and reports
173
+ `reader.metadata_source == "manifest"`. Supported tensor dtypes are exactly the
174
+ WEFT-TENSOR v1 set (`f16`, `bf16`, `f32`, `f64`, `i8`, `u8`, `i16`, `i32`,
175
+ `i64`); everything else is rejected, never coerced. ShardedTensor, DTensor and
176
+ custom `planner_data` are not persisted. See `docs/PYTORCH-DCP.md` for the full
177
+ contract and non-claims.
178
+
179
+ ### JAX / Orbax adapter
180
+
181
+ `weftcodec.orbax` is an Orbax `AsyncCheckpointHandler` that stores a JAX PyTree
182
+ as one canonical `weft.checkpoint.v1` checkpoint through the same Rust CLI and
183
+ the same adapter plumbing as the DCP path. Each flattened leaf is recorded in a
184
+ canonical WCB `weft.orbax.v1` record with its path, dtype, shape, BLAKE3 content
185
+ root and logical root; the Orbax directory only carries a small canonical
186
+ locator pointing at the store.
187
+
188
+ ```python
189
+ import jax
190
+ from weftcodec.orbax import WeftOrbaxHandler, WeftSaveArgs, WeftRestoreArgs
191
+
192
+ handler = WeftOrbaxHandler(staging_bytes=256 * 1024 * 1024)
193
+ target = jax.tree_util.tree_map(
194
+ lambda a: jax.ShapeDtypeStruct(a.shape, a.dtype, sharding=a.sharding), params
195
+ )
196
+ # Drive it with orbax.checkpoint.Checkpointer, AsyncCheckpointer, or
197
+ # CheckpointManager:
198
+ # save(directory, args=WeftSaveArgs(
199
+ # item=params, store_root="/data/weft-store", checkpoint_id="run-0001"))
200
+ # restore(directory, args=WeftRestoreArgs(item=target))
201
+ ```
202
+
203
+ Supported leaf dtypes are the same exact WEFT-TENSOR v1 set. A target PyTree
204
+ with a missing, extra, differently typed, or differently shaped leaf fails
205
+ closed; different JAX sharding topologies are accepted because the stored
206
+ logical tensor is topology independent. `staging_bytes` bounds the staging
207
+ container and the restored bytes. See `docs/JAX-ORBAX.md` for the full contract,
208
+ measured comparison against Orbax's own OCDBT checkpoint, and non-claims (CPU
209
+ only, single process, no TPU/GPU, no multi-host JAX).
210
+
211
+ ## Supported modes
212
+
213
+ | Mode | Value | Python reader |
214
+ |---|---:|---|
215
+ | `RAW` | 0 | implemented |
216
+ | `ZSTD` | 1 | implemented (`zstandard`) |
217
+ | `REFERENCE` | 2 | implemented |
218
+ | `DELTA` | 3 | implemented |
219
+ | `DICTIONARY` | 4 | implemented (raw-content zstd dictionary) |
220
+ | `STRUCTURED` | 5 | implemented (canonical WCB validation) |
221
+ | `TENSOR` | 6 | implemented (descriptor validation) |
222
+ | `TOKEN_SEQUENCE` | 7 | implemented (descriptor + varint payload) |
223
+ | `QUANTIZED_TENSOR` | 8 | implemented (descriptor validation) |
224
+ | `FLOAT_TENSOR` | 9 | implemented (all five dtypes, `huffman-canonical-v1` exponent plane) |
225
+ | `TENSOR_SHARDED` | 10 | implemented (q4_0/q8_0 shards, plane verification, shard-set root) |
226
+ | `WEIGHT_DELTA` | 11 | implemented (base resolution, modular word subtraction, `delta_root`) |
227
+ | `KV_CACHE` | 12 | implemented (one page per frame, byte-plane decode) |
228
+ | `ACTIVATION_STREAM` | 13 | implemented (one chunk per frame, `digest_root`, stream root) |
229
+ | `SEMANTIC_DELTA` | 14 | implemented (policy verification against the resolved base) |
230
+ | `TENSOR_TILED` | 15 | implemented (per-tile roots and whole-tensor logical root) |
231
+ | `SPARSE_DELTA` | 16 | implemented (`zero-run-v1`, `delta_root`) |
232
+
233
+ Every allocated mode 0–18 is implemented. There is no approximate or lossy
234
+ decode path. Reserved mode values 17–127 and experimental values 128–255 are
235
+ rejected by `weftcodec.frame` with `UnsupportedMode`.
236
+
237
+ The reader is deliberately a decoder, not a WEFT-TENSOR container reader: it
238
+ does not claim WeftQL selectors, Context Roots, capability envelopes,
239
+ `weft.checkpoint.v1` manifests, WFA1 archives, or `weft.tensor.layout.v1` /
240
+ `weft.tensor.shard.v1` records. `TENSOR_TILED` supports full decode; the
241
+ region reader is not implemented in Python.
242
+
243
+ ## Tests
244
+
245
+ ```sh
246
+ pytest -q
247
+ ```
248
+
249
+ The suite consumes `../WeftCodec/conformance/v1/**` (Rust-generated vectors) and
250
+ runs the Rust CLI for cross-language encode/decode checks when
251
+ `/work/.docker-cache/target-rust/release/weftcodec` is available. The PyTorch test
252
+ uses `pytest.importorskip("torch")`.
253
+
254
+ `test_ai_modes.py` decodes every valid AI-mode vector to its recorded bytes and
255
+ recomputes every recorded root; `test_random_differential.py` generates at least
256
+ 2,000 frames per mode 9–16 from a deterministic PRNG and compares the Python
257
+ reader against the Rust CLI on every frame, plus 1,600 body mutants.
@@ -0,0 +1,24 @@
1
+ weftcodec/__init__.py,sha256=pkcW0yS2JTZo5xqW1MYzb46n36PJDGKv8mE2m3NpdyY,1689
2
+ weftcodec/__main__.py,sha256=mzx10AUUv_v_CRVT_rZYwihgTQuhWFpjc3neblSFbTM,123
3
+ weftcodec/ai_modes.py,sha256=J5flGXVySMe9woYg1U1nWeVcgqoMd95YDKc3_ZAFJVw,118711
4
+ weftcodec/cli.py,sha256=vmVXoGRqsVA_LPaxj4rlfhcIC7bnl4DDGuA2A9WAlbw,8074
5
+ weftcodec/crc32c.py,sha256=XlXKr39OzLzBuERM27r8i9ldqA1T0C1jlInVBu3SDek,735
6
+ weftcodec/dcp.py,sha256=ee4SHPFk4B_y3kgQGoz9auCUH7ibsWDfDtItiazSxEU,75950
7
+ weftcodec/dependency.py,sha256=5vpnDJN2krq_YAc1pJWkhYr80nlbdvA1qYPHW8tnjS8,8441
8
+ weftcodec/errors.py,sha256=Fd4uzlkTFjr6e8IKOcAH4GDmLyBY00_xLFD-epmyWeU,2608
9
+ weftcodec/frame.py,sha256=mKkF0IL4XnX128tEae-lFG2MSkxkZ4ESfBct1jRDOp4,15535
10
+ weftcodec/hashing.py,sha256=kgvV1ZGXbmepIaEcau3Djp3KZ6J-ykwHQ0mvUov8PDA,1859
11
+ weftcodec/huffman.py,sha256=ChTmtRi_DfmJ8_cvFvQYRCTwpXax-NPtfQqCru2DQ1c,7356
12
+ weftcodec/identity.py,sha256=d679KgOzMI5MKVkDvdR_K1q3LNOktXTihLeKupj8bVs,4015
13
+ weftcodec/limits.py,sha256=NBZC_Qo4w-dsefxwNMRQ49gomMePKTWUv5ca1Bgt6_g,2232
14
+ weftcodec/modes.py,sha256=2pn9OJFiUrWnkfJI6qzvyGrg9nrKAybDPC6anuP908A,25017
15
+ weftcodec/orbax.py,sha256=m3af69jU-mLx0Eny-vShwIL4wRsBD0ows3F_lipKBBs,61818
16
+ weftcodec/service.py,sha256=zzUdyXgfGZ7GtR2BntCUiEpwoXzXYAnaAtnW7Hi6tzY,31611
17
+ weftcodec/torch.py,sha256=PZIJQBNRgo8xbagcGxI5MSjD6iYhQQeqPKjJ5KTsMDA,3211
18
+ weftcodec/varint.py,sha256=6srhBLYJZEGGAWsDiW7fyUVL9p5FBwR_wiS9oCAes2E,2504
19
+ weftcodec/wcb.py,sha256=HBjh_gbO2eBZWthCqU8f4z57kG3nlBhj8Zq4LcXdIuw,10861
20
+ weftcodec-1.2.0.dist-info/METADATA,sha256=1GmGSeLMiZD87izNVBOTAnwAfetg2HNiXjoWJMhEQwM,10304
21
+ weftcodec-1.2.0.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
22
+ weftcodec-1.2.0.dist-info/entry_points.txt,sha256=IsOuP8jWz37d7NvWT9r9ACBpGPtvYsj8F9WTY1-kgMg,52
23
+ weftcodec-1.2.0.dist-info/top_level.txt,sha256=HO5-vBHWV3GGFKc540HJ5FFH_e-HVSTdMDgK1DGSua4,10
24
+ weftcodec-1.2.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.2.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ weftcodec-py = weftcodec.cli:main
@@ -0,0 +1 @@
1
+ weftcodec