unstd 3.1.0__cp313-cp313-win_amd64.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.
Files changed (81) hide show
  1. unstd/__init__.py +86 -0
  2. unstd/_extra.py +28 -0
  3. unstd/audio/README.md +86 -0
  4. unstd/audio/__init__.py +22 -0
  5. unstd/audio/wavx.py +535 -0
  6. unstd/clone/README.md +91 -0
  7. unstd/clone/__init__.py +27 -0
  8. unstd/clone/structural.py +312 -0
  9. unstd/compress/README.md +45 -0
  10. unstd/compress/__init__.py +5 -0
  11. unstd/compress/_backend.py +64 -0
  12. unstd/compress/_inflate.py +127 -0
  13. unstd/compress/gzipx.py +222 -0
  14. unstd/containers/README.md +78 -0
  15. unstd/containers/__init__.py +34 -0
  16. unstd/containers/persistent.py +50 -0
  17. unstd/containers/sorted.py +53 -0
  18. unstd/crypto/README.md +102 -0
  19. unstd/crypto/__init__.py +20 -0
  20. unstd/crypto/_blake3.py +19 -0
  21. unstd/crypto/digest.py +138 -0
  22. unstd/crypto/tls.py +81 -0
  23. unstd/crypto/token.py +149 -0
  24. unstd/fs/README.md +62 -0
  25. unstd/fs/__init__.py +279 -0
  26. unstd/ids/README.md +38 -0
  27. unstd/ids/__init__.py +17 -0
  28. unstd/ids/uid.py +165 -0
  29. unstd/iters/README.md +63 -0
  30. unstd/iters/__init__.py +59 -0
  31. unstd/iters/consecutive.py +122 -0
  32. unstd/iters/distinct.py +76 -0
  33. unstd/iters/reshape.py +52 -0
  34. unstd/iters/select.py +134 -0
  35. unstd/model/README.md +74 -0
  36. unstd/model/__init__.py +31 -0
  37. unstd/model/base.py +74 -0
  38. unstd/model/settings.py +47 -0
  39. unstd/pack/README.md +104 -0
  40. unstd/pack/__init__.py +15 -0
  41. unstd/pack/binpack.py +203 -0
  42. unstd/proc/README.md +58 -0
  43. unstd/proc/__init__.py +258 -0
  44. unstd/py.typed +0 -0
  45. unstd/rand/README.md +75 -0
  46. unstd/rand/__init__.py +64 -0
  47. unstd/rand/crypto.py +48 -0
  48. unstd/rand/draw.py +148 -0
  49. unstd/rex/README.md +89 -0
  50. unstd/rex/__init__.py +363 -0
  51. unstd/rex/_faithful.py +321 -0
  52. unstd/serde/README.md +318 -0
  53. unstd/serde/__init__.py +24 -0
  54. unstd/serde/_json_common.py +16 -0
  55. unstd/serde/_json_decode_native.h +411 -0
  56. unstd/serde/_json_encode.py +199 -0
  57. unstd/serde/_json_encode_native.h +119 -0
  58. unstd/serde/_json_lines_native.h +99 -0
  59. unstd/serde/_json_native.c +676 -0
  60. unstd/serde/_json_native.cp313-win_amd64.pyd +0 -0
  61. unstd/serde/_json_native.pyi +16 -0
  62. unstd/serde/b64.py +272 -0
  63. unstd/serde/jsonx.py +411 -0
  64. unstd/serde/ndjson.py +336 -0
  65. unstd/serde/structs.py +144 -0
  66. unstd/text/README.md +93 -0
  67. unstd/text/__init__.py +13 -0
  68. unstd/text/fuzz.py +413 -0
  69. unstd/time/README.md +69 -0
  70. unstd/time/__init__.py +15 -0
  71. unstd/time/timeutil.py +292 -0
  72. unstd/time/zoned.py +133 -0
  73. unstd/toml/README.md +75 -0
  74. unstd/toml/__init__.py +129 -0
  75. unstd/yaml/README.md +48 -0
  76. unstd/yaml/__init__.py +182 -0
  77. unstd-3.1.0.dist-info/METADATA +152 -0
  78. unstd-3.1.0.dist-info/RECORD +81 -0
  79. unstd-3.1.0.dist-info/WHEEL +4 -0
  80. unstd-3.1.0.dist-info/licenses/LICENSE +202 -0
  81. unstd-3.1.0.dist-info/licenses/NOTICE +17 -0
unstd/__init__.py ADDED
@@ -0,0 +1,86 @@
1
+ """unstd — the unstandardized library.
2
+
3
+ Best-in-class native codecs behind small, **stdlib-faithful** surfaces: migrate a
4
+ call site by swapping the import, not the call. The base install is pure stdlib —
5
+ depending on ``unstd`` costs zero third-party closure — and each accelerated
6
+ backend rides an optional extra with a guarded stdlib fallback, so a lightweight
7
+ consumer never inherits a heavy dependency graph.
8
+
9
+ Module groups (grown incrementally from the stdlib census) — each named for the
10
+ stdlib surface it stands in for, and each either degrading to that surface or
11
+ failing loud where no faithful substitute exists:
12
+
13
+ - ``serde`` (``json`` / ``base64``) — ``jsonx`` (orjson/msgspec) · ``b64`` (pybase64) ·
14
+ ``ndjson`` (newline-delimited, rides ``jsonx``) · ``structs`` (msgspec, no
15
+ stdlib equivalent). Behind the ``serde`` extra; the rest fall back to stdlib.
16
+ - ``ids`` (``uuid``) — ``uid``: UUIDv7 minting and v5 derivation, falling back to
17
+ a stdlib generator. Behind the ``ids`` extra.
18
+ - ``crypto`` (``hashlib`` / ``hmac`` / ``ssl``) — BLAKE3 digests (content
19
+ hashes and short ids included), key derivation, keyed MACs and the bearer
20
+ envelope, constant-time compare, and a verifying TLS client policy. No
21
+ fallback: ``hashlib`` ships BLAKE2, which is a different algorithm, not a
22
+ slower one.
23
+ - ``time`` — ``timeutil`` (clocks, RFC-3339 formatting, ISO parsing, instant
24
+ arithmetic — pure stdlib; its protobuf ``Timestamp`` bridge is behind the
25
+ ``proto`` extra) · ``zoned`` (DST-correct wall-clock time over ``whenever``,
26
+ behind the ``time`` extra).
27
+ - ``model`` — the strict Pydantic wire-shape spine: ``StrictModel`` ·
28
+ ``FrozenModel`` · ``StrictSettings``. Behind the ``model`` extra (pydantic has
29
+ no stdlib equivalent, so there is no fallback).
30
+ - ``rex`` (``re``) — irregex linear-time matching, falls back to ``re``; the
31
+ flag and type vocabulary is re-exported verbatim.
32
+ - ``containers`` (``collections``) — always-sorted collections and a persistent
33
+ HAMT ``Map``. No faithful fallback (an ``O(n)`` stand-in would be a silent
34
+ lie), so the placeholders raise on construction.
35
+ - ``rand`` (``random``) — numpy PCG64 bulk draws; security-sensitive draws stay
36
+ on ``secrets`` regardless of the extra.
37
+ - ``pack`` (``struct``) — numpy bulk pack/unpack.
38
+ - ``clone`` (``copy``) — an exact-type structural deep clone, pure stdlib.
39
+ - ``text`` (``difflib``) — rapidfuzz similarity and fuzzy matching.
40
+ - ``audio`` (``wave``) — soundfile read/write plus a streaming writer.
41
+ - ``toml`` (``tomllib``) — reading is stdlib; writing needs tomlkit.
42
+ - ``yaml`` — safe YAML 1.2 and comment-preserving edits; requires the ``yaml`` extra.
43
+ - ``compress`` (``gzip``) — zlib-ng codecs behind ``gzipx``; the ``compress``
44
+ extra accelerates compression and inflation, with a stdlib fallback.
45
+ - ``proc`` (``subprocess``) · ``fs`` (``os``) · ``iters`` (``itertools``) —
46
+ pure stdlib, no extra, always present in the base install.
47
+
48
+ Import the module, not its members::
49
+
50
+ from unstd.serde import jsonx, b64, structs, ndjson
51
+ from unstd.ids import uid
52
+ from unstd.crypto import digest, token
53
+ from unstd.time import timeutil, zoned
54
+ from unstd.model import StrictModel, FrozenModel, StrictSettings
55
+ """
56
+
57
+ from __future__ import annotations
58
+
59
+
60
+ __version__: str
61
+
62
+ # A reload should refresh a version cached by a previous attribute access.
63
+ globals().pop("__version__", None)
64
+
65
+
66
+ def __getattr__(name: str) -> str:
67
+ """Resolve and cache the installed version only when it is requested."""
68
+ if name != "__version__":
69
+ msg = f"module {__name__!r} has no attribute {name!r}"
70
+ raise AttributeError(msg)
71
+
72
+ # Metadata discovery imports a large stdlib closure and scans distributions.
73
+ # Submodule consumers (including native codecs) do not need to pay that cost.
74
+ from importlib.metadata import PackageNotFoundError, version
75
+
76
+ try:
77
+ resolved = version("unstd")
78
+ except PackageNotFoundError: # source tree that was never installed
79
+ resolved = "0.0.0.dev0"
80
+ globals()[name] = resolved
81
+ return resolved
82
+
83
+
84
+ def __dir__() -> list[str]:
85
+ """Include the lazy version attribute without resolving install metadata."""
86
+ return sorted({*globals(), "__version__"})
unstd/_extra.py ADDED
@@ -0,0 +1,28 @@
1
+ """The deferred-raise placeholder every capability without a stdlib fallback binds.
2
+
3
+ Where a backend has no faithful substitute (a sorted container, a persistent
4
+ trie, a TOML writer), its public name still has to exist so the module imports
5
+ cleanly on a base install. :func:`missing` is that name: calling it raises an
6
+ ``ImportError`` naming the extra that fixes it, so a consumer that never touches
7
+ the capability pays nothing, and one that does gets a one-line fix.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from typing import TYPE_CHECKING, Never
13
+
14
+
15
+ if TYPE_CHECKING:
16
+ from collections.abc import Callable
17
+
18
+
19
+ def missing(qualname: str, extra: str) -> Callable[..., Never]:
20
+ """A stand-in for ``unstd.<qualname>`` that raises naming the ``extra`` it needs."""
21
+ msg = f"unstd.{qualname} requires the {extra!r} extra — install with: pip install 'unstd[{extra}]'"
22
+
23
+ def _raise(*_args: object, **_kwargs: object) -> Never:
24
+ raise ImportError(msg)
25
+
26
+ _raise.__name__ = _raise.__qualname__ = qualname.rpartition(".")[2]
27
+ _raise.__doc__ = f"Unavailable — {msg}."
28
+ return _raise
unstd/audio/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # `unstd.audio`
2
+
3
+ Part of [`unstd`](../README.md). A stdlib-`wave`-faithful **replacement**
4
+ that hands back sample _arrays_ instead of raw frame bytes — the shape a voice
5
+ path (TTS/STT) actually wants. The stdlib `wave` module only exposes packed
6
+ PCM byte strings; every call site then re-rolls the same `struct`/`array`
7
+ unpacking. `unstd.audio` folds that decode into the reader and the encode into the
8
+ writer.
9
+
10
+ ## Modules
11
+
12
+ | File | Role |
13
+ | --------- | ----------------------------------------------------------------------------------------------------------------- |
14
+ | `wavx.py` | `read`/`write` (whole-file) · `blocks`/`Writer` (streaming) · `wrap_pcm` — numpy-native WAV samples ↔ file. |
15
+
16
+ ```python
17
+ from unstd.audio import wavx
18
+
19
+ samples, sr = wavx.read("in.wav") # float32 in [-1, 1], sr = Hz
20
+ wavx.write("out.wav", samples, sr) # PCM_16 by default
21
+ ints, sr = wavx.read("in.wav", dtype="int16") # raw signed 16-bit
22
+
23
+ # streaming — for a live TTS/STT pipeline, not a file already fully in memory:
24
+ with wavx.Writer("out.wav", sr, channels=1) as w:
25
+ for chunk in synth_chunks:
26
+ w.write(chunk)
27
+ for block in wavx.blocks("in.wav", blocksize=4096):
28
+ play(block)
29
+
30
+ wavx.wrap_pcm(raw_pcm_bytes, sr, channels=1, width=2) # header only, no decode
31
+ ```
32
+
33
+ Mono is 1-D `(frames,)`; multichannel is 2-D `(frames, channels)` — the shape
34
+ libsndfile/`soundfile` use. Float samples written are clamped to `[-1, 1]` then
35
+ quantized; integer samples are written as-is.
36
+
37
+ ## Backend
38
+
39
+ The `audio` extra (`pip install 'unstd[audio]'`) provides `soundfile==…` +
40
+ `numpy==2.5.0`, so reads/writes ride **libsndfile** and samples are
41
+ `numpy.ndarray`. Without it there are two guarded stdlib fallbacks:
42
+
43
+ | Path | When | Samples | Read widths | Write subtypes |
44
+ | ----------------------- | ---------------------------- | ------------------- | ----------- | ----------------- |
45
+ | `soundfile` + `numpy` | `audio` extra installed | `ndarray` | libsndfile | libsndfile |
46
+ | stdlib `wave` + `numpy` | numpy present, no soundfile | `ndarray` | 8/16/32-bit | `PCM_16`/`PCM_32` |
47
+ | stdlib `wave` + `array` | no numpy (pure-stdlib floor) | `list`/`list[list]` | 16-bit | `PCM_16` |
48
+
49
+ The pure-stdlib floor deliberately trades ergonomics for zero dependencies:
50
+ 16-bit PCM only, Python lists, no vectorization. Wider widths / other subtypes
51
+ raise a clear error pointing at the `audio` extra rather than silently degrading.
52
+
53
+ **Fixed-point scaling is identical on every path** so a file written by one reads
54
+ back consistently on another: a _w_-bit sample ↔ float via `± 2**(w-1)`, so
55
+ `float32 → PCM16 → float32` round-trips lossless to within one quantization step
56
+ (`1/32768`).
57
+
58
+ ## Streaming — `Writer` / `blocks`
59
+
60
+ `read`/`write` buffer the whole file; a live pipeline (streaming TTS
61
+ synthesis, STT playback) wants frames as they arrive instead. `Writer` is a
62
+ context manager — `channels`/`subtype` are fixed up front (a stream has no
63
+ complete array to infer them from), and each `.write(chunk)` call appends one
64
+ chunk; `blocks(path, blocksize)` is the read-side generator, `blocksize`
65
+ frames at a time. Fast path: `soundfile`'s own `SoundFile`/`blocks` streaming
66
+ API. Fallback: stdlib `wave`'s `writeframesraw`/chunked `readframes`, which
67
+ requires the write target be **seekable** (a real file path, or a file object
68
+ opened on one) so `close()` can patch the RIFF/`data` sizes — a genuinely
69
+ non-seekable sink (a raw socket) needs the `audio` extra.
70
+
71
+ ## `wrap_pcm` — a header, nothing else
72
+
73
+ Some PCM never becomes samples: bytes straight off a wire (a codec's output, a
74
+ socket frame, a transcription upload) just need a RIFF/WAVE container around
75
+ them. `wrap_pcm(raw, samplerate, channels=1, width=2)` does exactly that — no
76
+ scale, no clamp, no requantize — where routing the same bytes through
77
+ `write` would decode to an array and re-quantize back, paying two
78
+ conversions and a quantization step to reproduce its own input.
79
+
80
+ ## Prior art
81
+
82
+ - **[`soundfile`](https://github.com/bastibe/python-soundfile)** (Bastian
83
+ Bechtold) — Python bindings over **[libsndfile](https://libsndfile.github.io/libsndfile/)**
84
+ (Erik de Castro Lopo), the fast path this module wraps.
85
+ - The stdlib [`wave`](https://docs.python.org/3/library/wave.html) module — the
86
+ raw-frame surface `unstd.audio` replaces, and the fallback codec.
@@ -0,0 +1,22 @@
1
+ """Audio I/O — numpy-native WAV read/write for voice paths.
2
+
3
+ A stdlib-``wave``-faithful *replacement* that hands back sample **arrays** instead
4
+ of raw frame bytes. The stdlib ``wave`` module only exposes packed PCM byte
5
+ strings; every TTS/STT call site then re-rolls the same ``struct``/``array``
6
+ unpacking. ``unstd.audio`` folds that decode into the reader and the encode into
7
+ the writer, so the surface is samples-in / samples-out.
8
+
9
+ Backend & fallback: the ``audio`` extra provides ``soundfile``
10
+ (libsndfile bindings) + ``numpy``. When present, reads/writes ride libsndfile and
11
+ samples are ``numpy`` arrays. Without the extra (a base ``unstd`` install) the
12
+ module falls back to the stdlib ``wave`` module plus manual PCM↔numpy conversion,
13
+ or — when ``numpy`` is also absent — the stdlib ``array`` module (reduced
14
+ ergonomics: 16-bit PCM only, Python ``list`` samples). The public surface works
15
+ everywhere; only the codec and the sample container differ.
16
+
17
+ Import the module, not its members::
18
+
19
+ from unstd.audio import wavx
20
+ """
21
+
22
+ from __future__ import annotations