aether-dsc 0.2.0__tar.gz → 0.2.2__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.
- aether_dsc-0.2.2/NOTICE +8 -0
- {aether_dsc-0.2.0/aether_dsc.egg-info → aether_dsc-0.2.2}/PKG-INFO +5 -1
- {aether_dsc-0.2.0 → aether_dsc-0.2.2}/README.md +4 -0
- {aether_dsc-0.2.0 → aether_dsc-0.2.2}/aether_dsc/__init__.py +14 -2
- aether_dsc-0.2.2/aether_dsc/_payload/c19a2ae533cbef09f605b99cce9c58d42fa00928b99327a361023a3f8f3cc7d1.bin +0 -0
- {aether_dsc-0.2.0 → aether_dsc-0.2.2}/aether_dsc/payload_headers_host.txt +1 -0
- {aether_dsc-0.2.0 → aether_dsc-0.2.2/aether_dsc.egg-info}/PKG-INFO +5 -1
- {aether_dsc-0.2.0 → aether_dsc-0.2.2}/aether_dsc.egg-info/SOURCES.txt +3 -2
- {aether_dsc-0.2.0 → aether_dsc-0.2.2}/pyproject.toml +4 -1
- aether_dsc-0.2.2/tests/test_ft_payload.py +109 -0
- aether_dsc-0.2.0/NOTICE +0 -2
- aether_dsc-0.2.0/aether_dsc/_payload/a9c89146169d59183c41dba2a050a420a5f3dd40729154ae547b61a2239c38b8.bin +0 -0
- {aether_dsc-0.2.0 → aether_dsc-0.2.2}/LICENSE +0 -0
- {aether_dsc-0.2.0 → aether_dsc-0.2.2}/aether_dsc/_core.py +0 -0
- {aether_dsc-0.2.0 → aether_dsc-0.2.2}/aether_dsc/_rtc_check.py +0 -0
- {aether_dsc-0.2.0 → aether_dsc-0.2.2}/aether_dsc/_seal_impl.py +0 -0
- {aether_dsc-0.2.0 → aether_dsc-0.2.2}/aether_dsc/payload_headers.txt +0 -0
- {aether_dsc-0.2.0 → aether_dsc-0.2.2}/aether_dsc/seal.py +0 -0
- {aether_dsc-0.2.0 → aether_dsc-0.2.2}/aether_dsc.egg-info/dependency_links.txt +0 -0
- {aether_dsc-0.2.0 → aether_dsc-0.2.2}/aether_dsc.egg-info/requires.txt +0 -0
- {aether_dsc-0.2.0 → aether_dsc-0.2.2}/aether_dsc.egg-info/top_level.txt +0 -0
- {aether_dsc-0.2.0 → aether_dsc-0.2.2}/setup.cfg +0 -0
- {aether_dsc-0.2.0 → aether_dsc-0.2.2}/tests/test_aether_dsc.py +0 -0
aether_dsc-0.2.2/NOTICE
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
aether
|
|
2
|
+
Copyright 2026 Alessandro Masat
|
|
3
|
+
|
|
4
|
+
The table-driven exp and log in aether/backend/cpu/simd/math/PacketExpLog.h
|
|
5
|
+
follow the algorithms of ARM optimized-routines
|
|
6
|
+
(https://github.com/ARM-software/optimized-routines, math/exp.c and math/log.c),
|
|
7
|
+
Copyright (c) Arm Limited, MIT OR Apache-2.0 WITH LLVM-exception. The lookup
|
|
8
|
+
tables in PacketExpLogTables.h were regenerated for aether.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aether-dsc
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: aether-dsc — the sealed AETHER header payload: opaque, digest-named, no readable source in the wheel
|
|
5
5
|
Author: Alessandro Masat
|
|
6
6
|
License: Apache-2.0
|
|
@@ -58,3 +58,7 @@ refused, never shipped silently broken.
|
|
|
58
58
|
The blob is a zlib-compressed tar — not obfuscation against a determined
|
|
59
59
|
reader, just enough that `strings`/`cat` on the wheel does not hand back
|
|
60
60
|
readable C++ source.
|
|
61
|
+
|
|
62
|
+
## Threading
|
|
63
|
+
|
|
64
|
+
Free-threaded CPython (3.13t/3.14t) is supported: the compiled modules declare GIL-free operation and the GIL stays disabled after import. Any number of threads may call module-level functions, build, compile, plan and cache concurrently. Distinct objects may be used from distinct threads without synchronisation. One stateful object (a stream, capture, launcher, graph, composer, plan, pipeline, active set, host kernel or arg block) shared by several threads is memory-safe — its calls serialise and a consumed object raises — but the ORDER of those calls is the caller's responsibility, exactly as for a NumPy array or a CuPy stream. CUDA adds two rules of its own: a stream capture is begun, filled and ended by one thread, and while any capture is open no thread may synchronise the whole device (stream-level synchronisation is fine). GPU routes are supported on free-threaded 3.14; on 3.13t the CPU route runs.
|
|
@@ -39,3 +39,7 @@ refused, never shipped silently broken.
|
|
|
39
39
|
The blob is a zlib-compressed tar — not obfuscation against a determined
|
|
40
40
|
reader, just enough that `strings`/`cat` on the wheel does not hand back
|
|
41
41
|
readable C++ source.
|
|
42
|
+
|
|
43
|
+
## Threading
|
|
44
|
+
|
|
45
|
+
Free-threaded CPython (3.13t/3.14t) is supported: the compiled modules declare GIL-free operation and the GIL stays disabled after import. Any number of threads may call module-level functions, build, compile, plan and cache concurrently. Distinct objects may be used from distinct threads without synchronisation. One stateful object (a stream, capture, launcher, graph, composer, plan, pipeline, active set, host kernel or arg block) shared by several threads is memory-safe — its calls serialise and a consumed object raises — but the ORDER of those calls is the caller's responsibility, exactly as for a NumPy array or a CuPy stream. CUDA adds two rules of its own: a stream capture is begun, filled and ended by one thread, and while any capture is open no thread may synchronise the whole device (stream-level synchronisation is fine). GPU routes are supported on free-threaded 3.14; on 3.13t the CPU route runs.
|
|
@@ -31,6 +31,8 @@ goes through :func:`seal`; see :mod:`aether_dsc.seal`'s module docstring.
|
|
|
31
31
|
"""
|
|
32
32
|
from __future__ import annotations
|
|
33
33
|
|
|
34
|
+
import threading
|
|
35
|
+
|
|
34
36
|
from ._core import Payload, PAYLOAD_DIR, _unpack, digest_of
|
|
35
37
|
# Imported from `_seal_impl`, deliberately NOT from `.seal`:
|
|
36
38
|
# `aether_dsc/seal.py` is `python -m aether_dsc.seal`'s CLI file, and
|
|
@@ -48,9 +50,10 @@ __all__ = ["Payload", "seal", "payload", "version", "PAYLOAD_DIR"]
|
|
|
48
50
|
#: `constexpr version()`), because a sealed payload speaks for exactly one
|
|
49
51
|
#: aether checkout and a version skew between the two would silently claim
|
|
50
52
|
#: otherwise.
|
|
51
|
-
version = "0.2.
|
|
53
|
+
version = "0.2.2"
|
|
52
54
|
|
|
53
55
|
_PAYLOAD_CACHE: Payload | None = None
|
|
56
|
+
_PAYLOAD_LOCK = threading.Lock()
|
|
54
57
|
|
|
55
58
|
|
|
56
59
|
def payload() -> Payload:
|
|
@@ -66,6 +69,14 @@ def payload() -> Payload:
|
|
|
66
69
|
`$HAWK_AETHER_INCLUDE`: a caller that wants "seal if there is no
|
|
67
70
|
blob" asks for it explicitly, `payload()` never guesses.
|
|
68
71
|
"""
|
|
72
|
+
cached = _PAYLOAD_CACHE
|
|
73
|
+
if cached is not None:
|
|
74
|
+
return cached
|
|
75
|
+
with _PAYLOAD_LOCK:
|
|
76
|
+
return _payload_locked()
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _payload_locked() -> Payload:
|
|
69
80
|
global _PAYLOAD_CACHE
|
|
70
81
|
if _PAYLOAD_CACHE is not None:
|
|
71
82
|
return _PAYLOAD_CACHE
|
|
@@ -96,4 +107,5 @@ def _reset_payload_cache() -> None:
|
|
|
96
107
|
freshly written blob in a test's tmp `_payload/` dir) is picked up
|
|
97
108
|
without restarting the process."""
|
|
98
109
|
global _PAYLOAD_CACHE
|
|
99
|
-
|
|
110
|
+
with _PAYLOAD_LOCK:
|
|
111
|
+
_PAYLOAD_CACHE = None
|
|
Binary file
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
# ever observed.
|
|
25
25
|
aether/backend/cpu/simd/math/PacketArcTrig.h
|
|
26
26
|
aether/backend/cpu/simd/math/PacketExpLog.h
|
|
27
|
+
aether/backend/cpu/simd/math/PacketExpLogTables.h
|
|
27
28
|
aether/backend/cpu/simd/math/PacketHyperbolic.h
|
|
28
29
|
aether/backend/cpu/simd/math/PacketMathCore.h
|
|
29
30
|
aether/backend/cpu/simd/math/PacketMisc.h
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aether-dsc
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: aether-dsc — the sealed AETHER header payload: opaque, digest-named, no readable source in the wheel
|
|
5
5
|
Author: Alessandro Masat
|
|
6
6
|
License: Apache-2.0
|
|
@@ -58,3 +58,7 @@ refused, never shipped silently broken.
|
|
|
58
58
|
The blob is a zlib-compressed tar — not obfuscation against a determined
|
|
59
59
|
reader, just enough that `strings`/`cat` on the wheel does not hand back
|
|
60
60
|
readable C++ source.
|
|
61
|
+
|
|
62
|
+
## Threading
|
|
63
|
+
|
|
64
|
+
Free-threaded CPython (3.13t/3.14t) is supported: the compiled modules declare GIL-free operation and the GIL stays disabled after import. Any number of threads may call module-level functions, build, compile, plan and cache concurrently. Distinct objects may be used from distinct threads without synchronisation. One stateful object (a stream, capture, launcher, graph, composer, plan, pipeline, active set, host kernel or arg block) shared by several threads is memory-safe — its calls serialise and a consumed object raises — but the ORDER of those calls is the caller's responsibility, exactly as for a NumPy array or a CuPy stream. CUDA adds two rules of its own: a stream capture is begun, filled and ended by one thread, and while any capture is open no thread may synchronise the whole device (stream-level synchronisation is fine). GPU routes are supported on free-threaded 3.14; on 3.13t the CPU route runs.
|
|
@@ -14,5 +14,6 @@ aether_dsc.egg-info/SOURCES.txt
|
|
|
14
14
|
aether_dsc.egg-info/dependency_links.txt
|
|
15
15
|
aether_dsc.egg-info/requires.txt
|
|
16
16
|
aether_dsc.egg-info/top_level.txt
|
|
17
|
-
aether_dsc/_payload/
|
|
18
|
-
tests/test_aether_dsc.py
|
|
17
|
+
aether_dsc/_payload/c19a2ae533cbef09f605b99cce9c58d42fa00928b99327a361023a3f8f3cc7d1.bin
|
|
18
|
+
tests/test_aether_dsc.py
|
|
19
|
+
tests/test_ft_payload.py
|
|
@@ -14,7 +14,7 @@ name = "aether-dsc"
|
|
|
14
14
|
# aether-dsc ships a SEALED payload of that exact checkout, so a version skew
|
|
15
15
|
# between the two would silently claim a payload speaks for a different
|
|
16
16
|
# aether than it does.
|
|
17
|
-
version = "0.2.
|
|
17
|
+
version = "0.2.2"
|
|
18
18
|
description = "aether-dsc — the sealed AETHER header payload: opaque, digest-named, no readable source in the wheel"
|
|
19
19
|
readme = "README.md"
|
|
20
20
|
requires-python = ">=3.9"
|
|
@@ -67,6 +67,9 @@ aether_dsc = ["py.typed", "_payload/*.bin", "payload_headers.txt",
|
|
|
67
67
|
|
|
68
68
|
[tool.pytest.ini_options]
|
|
69
69
|
testpaths = ["tests"]
|
|
70
|
+
markers = [
|
|
71
|
+
"ft: free-threading rows (raptor.conformance.freethreading) -- skip on a GIL build; select with -m ft on 3.13t/3.14t.",
|
|
72
|
+
]
|
|
70
73
|
# Makes `import aether_dsc` work against the checked-out tree without an
|
|
71
74
|
# install — this repo root, prepended to sys.path before collection (mirrors
|
|
72
75
|
# raptor's/hawk's own pyproject convention).
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Copyright 2026 Alessandro Masat
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
"""Free-threading rows for aether-dsc (FT-1 and FT-3: one ``Payload`` identity).
|
|
5
|
+
|
|
6
|
+
On a GIL build the rows SKIP with a reason; the name manifest keeps "skipped"
|
|
7
|
+
from degrading into "silently not collected".
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import sys
|
|
13
|
+
import threading
|
|
14
|
+
import time
|
|
15
|
+
|
|
16
|
+
import pytest
|
|
17
|
+
|
|
18
|
+
import aether_dsc
|
|
19
|
+
from raptor.conformance import freethreading as ft
|
|
20
|
+
from raptor.conformance.freethreading import declare_ft_row, register_ft_row
|
|
21
|
+
|
|
22
|
+
pytestmark = pytest.mark.ft
|
|
23
|
+
|
|
24
|
+
declare_ft_row(
|
|
25
|
+
"FT-1-GIL-FREE-AETHER-DSC", "aether-dsc",
|
|
26
|
+
"importing aether_dsc leaves the GIL off")
|
|
27
|
+
declare_ft_row(
|
|
28
|
+
"FT-3-PAYLOAD-IDENTITY", "aether-dsc",
|
|
29
|
+
"16 threads on a cold payload() cache get one Payload object")
|
|
30
|
+
|
|
31
|
+
EXPECTED_TESTS = frozenset(
|
|
32
|
+
{
|
|
33
|
+
"test_manifest_all_tests_collected",
|
|
34
|
+
"test_rows_declared_and_collected",
|
|
35
|
+
"test_gil_free_import",
|
|
36
|
+
"test_payload_cold_cache_single_identity",
|
|
37
|
+
"test_payload_cold_cache_single_identity_slow_unpack",
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
THREADS = 16
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _cold_race(rounds: int) -> None:
|
|
45
|
+
for _ in range(rounds):
|
|
46
|
+
aether_dsc._reset_payload_cache()
|
|
47
|
+
barrier = threading.Barrier(THREADS)
|
|
48
|
+
got: list[object] = []
|
|
49
|
+
errors: list[BaseException] = []
|
|
50
|
+
|
|
51
|
+
def work() -> None:
|
|
52
|
+
try:
|
|
53
|
+
barrier.wait()
|
|
54
|
+
got.append(aether_dsc.payload())
|
|
55
|
+
except BaseException as exc: # noqa: BLE001 - checked below
|
|
56
|
+
errors.append(exc)
|
|
57
|
+
|
|
58
|
+
pool = [threading.Thread(target=work) for _ in range(THREADS)]
|
|
59
|
+
for t in pool:
|
|
60
|
+
t.start()
|
|
61
|
+
for t in pool:
|
|
62
|
+
t.join()
|
|
63
|
+
assert not errors, errors
|
|
64
|
+
assert len(got) == THREADS
|
|
65
|
+
assert len({id(p) for p in got}) == 1, "payload() returned distinct objects"
|
|
66
|
+
assert all(p is got[0] for p in got)
|
|
67
|
+
assert aether_dsc.payload() is got[0]
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_manifest_all_tests_collected(request):
|
|
71
|
+
here = {
|
|
72
|
+
i.name for i in request.session.items if i.module is sys.modules[__name__]
|
|
73
|
+
}
|
|
74
|
+
assert EXPECTED_TESTS <= here, sorted(EXPECTED_TESTS - here)
|
|
75
|
+
assert {n for n in here if "[" not in n} <= EXPECTED_TESTS
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def test_rows_declared_and_collected():
|
|
79
|
+
ft.assert_ft_rows_complete("aether-dsc")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@register_ft_row("FT-1-GIL-FREE-AETHER-DSC")
|
|
83
|
+
def test_gil_free_import():
|
|
84
|
+
ft.require_free_threaded()
|
|
85
|
+
ft.assert_gil_free("aether_dsc")
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@register_ft_row("FT-3-PAYLOAD-IDENTITY")
|
|
89
|
+
def test_payload_cold_cache_single_identity():
|
|
90
|
+
try:
|
|
91
|
+
_cold_race(50)
|
|
92
|
+
finally:
|
|
93
|
+
aether_dsc._reset_payload_cache()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def test_payload_cold_cache_single_identity_slow_unpack(monkeypatch):
|
|
97
|
+
# Widen the check-then-set window: a slow unpack makes an unlocked
|
|
98
|
+
# cold-cache race certain on every interpreter, GIL or not.
|
|
99
|
+
real = aether_dsc._unpack
|
|
100
|
+
|
|
101
|
+
def slow(data):
|
|
102
|
+
time.sleep(0.02)
|
|
103
|
+
return real(data)
|
|
104
|
+
|
|
105
|
+
monkeypatch.setattr(aether_dsc, "_unpack", slow)
|
|
106
|
+
try:
|
|
107
|
+
_cold_race(3)
|
|
108
|
+
finally:
|
|
109
|
+
aether_dsc._reset_payload_cache()
|
aether_dsc-0.2.0/NOTICE
DELETED
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|