pycyphal2 2.0.0.dev4__tar.gz → 2.0.0.dev5__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.
- {pycyphal2-2.0.0.dev4/src/pycyphal2.egg-info → pycyphal2-2.0.0.dev5}/PKG-INFO +1 -1
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2/__init__.py +1 -1
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2/_node.py +3 -1
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5/src/pycyphal2.egg-info}/PKG-INFO +1 -1
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/tests/test_integration.py +2 -2
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/tests/test_topic.py +37 -10
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/LICENSE +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/README.md +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/pyproject.toml +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/setup.cfg +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2/_api.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2/_hash.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2/_header.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2/_publisher.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2/_subscriber.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2/_transport.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2/can/__init__.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2/can/_interface.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2/can/_media_slcan.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2/can/_reassembly.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2/can/_transport.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2/can/_wire.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2/can/pythoncan.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2/can/socketcan.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2/can/webserial.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2/py.typed +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2/udp.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2.egg-info/SOURCES.txt +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2.egg-info/dependency_links.txt +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2.egg-info/requires.txt +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/src/pycyphal2.egg-info/top_level.txt +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/tests/test_gossip.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/tests/test_hash.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/tests/test_header.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/tests/test_monitor.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/tests/test_names.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/tests/test_parity.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/tests/test_parity_coverage.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/tests/test_pubsub.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/tests/test_reliable.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/tests/test_reorder.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/tests/test_rpc.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/tests/test_scout.py +0 -0
- {pycyphal2-2.0.0.dev4 → pycyphal2-2.0.0.dev5}/tests/test_udp.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pycyphal2
|
|
3
|
-
Version: 2.0.0.
|
|
3
|
+
Version: 2.0.0.dev5
|
|
4
4
|
Summary: Pure-Python implementation of Cyphal -- a simple and robust real-time publish/subscribe stack that runs anywhere.
|
|
5
5
|
Author-email: Pavel Kirienko and OpenCyphal team <pavel@opencyphal.org>
|
|
6
6
|
License: MIT
|
|
@@ -155,7 +155,7 @@ from ._transport import SubjectWriter as SubjectWriter
|
|
|
155
155
|
from ._transport import Transport as Transport
|
|
156
156
|
from ._transport import TransportArrival as TransportArrival
|
|
157
157
|
|
|
158
|
-
__version__ = "2.0.0.
|
|
158
|
+
__version__ = "2.0.0.dev5"
|
|
159
159
|
|
|
160
160
|
# pdoc needs __all__ to display re-exported members.
|
|
161
161
|
__all__ = [
|
|
@@ -246,7 +246,9 @@ def compute_subject_id(topic_hash: int, evictions: int, modulus: int) -> int:
|
|
|
246
246
|
"""Compute the subject-ID for a topic given its hash, evictions, and subject-ID modulus."""
|
|
247
247
|
if evictions >= EVICTIONS_PINNED_MIN:
|
|
248
248
|
return 0xFFFFFFFF - evictions
|
|
249
|
-
|
|
249
|
+
h = topic_hash % modulus
|
|
250
|
+
e = evictions % modulus
|
|
251
|
+
return SUBJECT_ID_PINNED_MAX + 1 + ((h + ((e * e) % modulus)) % modulus)
|
|
250
252
|
|
|
251
253
|
|
|
252
254
|
# =====================================================================================================================
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pycyphal2
|
|
3
|
-
Version: 2.0.0.
|
|
3
|
+
Version: 2.0.0.dev5
|
|
4
4
|
Summary: Pure-Python implementation of Cyphal -- a simple and robust real-time publish/subscribe stack that runs anywhere.
|
|
5
5
|
Author-email: Pavel Kirienko and OpenCyphal team <pavel@opencyphal.org>
|
|
6
6
|
License: MIT
|
|
@@ -270,12 +270,12 @@ async def test_subject_id_computation():
|
|
|
270
270
|
"""Verify subject-ID computation matches the reference formula."""
|
|
271
271
|
modulus = 8378431 # 23bit
|
|
272
272
|
|
|
273
|
-
# Non-pinned: 0x2000 + ((hash + evictions^2) % modulus)
|
|
273
|
+
# Non-pinned: 0x2000 + (((hash % modulus) + ((evictions % modulus)^2 % modulus)) % modulus)
|
|
274
274
|
sid = compute_subject_id(0xDEADBEEF, 0, modulus)
|
|
275
275
|
assert sid == 0x2000 + (0xDEADBEEF % modulus)
|
|
276
276
|
|
|
277
277
|
sid = compute_subject_id(0xDEADBEEF, 3, modulus)
|
|
278
|
-
assert sid == 0x2000 + ((0xDEADBEEF +
|
|
278
|
+
assert sid == 0x2000 + (((0xDEADBEEF % modulus) + ((3 % modulus) ** 2 % modulus)) % modulus)
|
|
279
279
|
|
|
280
280
|
# Pinned: UINT32_MAX - evictions
|
|
281
281
|
sid = compute_subject_id(0xDEADBEEF, EVICTIONS_PINNED_MIN, modulus)
|
|
@@ -40,21 +40,40 @@ def test_compute_subject_id_pinned_boundary():
|
|
|
40
40
|
|
|
41
41
|
def test_compute_subject_id_non_pinned_zero_evictions():
|
|
42
42
|
"""Non-pinned with zero evictions: offset + hash % modulus."""
|
|
43
|
-
topic_hash
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
for topic_hash in (0, 1, rapidhash("my/topic"), (1 << 64) - 1):
|
|
44
|
+
sid = compute_subject_id(topic_hash, 0, DEFAULT_MODULUS)
|
|
45
|
+
expected = SUBJECT_ID_PINNED_MAX + 1 + (topic_hash % DEFAULT_MODULUS)
|
|
46
|
+
assert sid == expected
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
def test_compute_subject_id_non_pinned_with_evictions():
|
|
50
|
-
"""Non-pinned formula: offset + (hash + evictions^2) % modulus."""
|
|
50
|
+
"""Non-pinned formula: offset + ((hash % modulus) + ((evictions % modulus)^2 % modulus)) % modulus."""
|
|
51
51
|
topic_hash = rapidhash("some/topic")
|
|
52
52
|
for ev in (1, 2, 5, 100):
|
|
53
53
|
sid = compute_subject_id(topic_hash, ev, DEFAULT_MODULUS)
|
|
54
|
-
expected =
|
|
54
|
+
expected = (
|
|
55
|
+
SUBJECT_ID_PINNED_MAX
|
|
56
|
+
+ 1
|
|
57
|
+
+ (
|
|
58
|
+
((topic_hash % DEFAULT_MODULUS) + (((ev % DEFAULT_MODULUS) * (ev % DEFAULT_MODULUS)) % DEFAULT_MODULUS))
|
|
59
|
+
% DEFAULT_MODULUS
|
|
60
|
+
)
|
|
61
|
+
)
|
|
55
62
|
assert sid == expected
|
|
56
63
|
|
|
57
64
|
|
|
65
|
+
def test_compute_subject_id_non_pinned_does_not_wrap_uint64_sum():
|
|
66
|
+
topic_hash = (1 << 64) - 1
|
|
67
|
+
evictions = EVICTIONS_PINNED_MIN - 1
|
|
68
|
+
sid = compute_subject_id(topic_hash, evictions, DEFAULT_MODULUS)
|
|
69
|
+
uint64_wrapping = (
|
|
70
|
+
SUBJECT_ID_PINNED_MAX + 1 + (((topic_hash + (evictions * evictions)) & ((1 << 64) - 1)) % DEFAULT_MODULUS)
|
|
71
|
+
)
|
|
72
|
+
assert sid == 49564
|
|
73
|
+
assert uint64_wrapping == 74897
|
|
74
|
+
assert sid != uint64_wrapping
|
|
75
|
+
|
|
76
|
+
|
|
58
77
|
def test_compute_subject_id_evictions_changes_sid():
|
|
59
78
|
"""Different eviction counts should generally produce different subject-IDs."""
|
|
60
79
|
topic_hash = rapidhash("test/evictions")
|
|
@@ -70,7 +89,14 @@ def test_compute_subject_id_just_below_pinned():
|
|
|
70
89
|
ev = EVICTIONS_PINNED_MIN - 1
|
|
71
90
|
topic_hash = 12345
|
|
72
91
|
sid = compute_subject_id(topic_hash, ev, DEFAULT_MODULUS)
|
|
73
|
-
expected =
|
|
92
|
+
expected = (
|
|
93
|
+
SUBJECT_ID_PINNED_MAX
|
|
94
|
+
+ 1
|
|
95
|
+
+ (
|
|
96
|
+
((topic_hash % DEFAULT_MODULUS) + (((ev % DEFAULT_MODULUS) * (ev % DEFAULT_MODULUS)) % DEFAULT_MODULUS))
|
|
97
|
+
% DEFAULT_MODULUS
|
|
98
|
+
)
|
|
99
|
+
)
|
|
74
100
|
assert sid == expected
|
|
75
101
|
|
|
76
102
|
|
|
@@ -361,9 +387,10 @@ async def test_gossip_unknown_collision_we_lose():
|
|
|
361
387
|
# produces the same subject-ID and a very high lage.
|
|
362
388
|
remote_lage = 50 # Very old.
|
|
363
389
|
# Build a fake hash that produces the same SID as our topic.
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
390
|
+
target_remainder = (
|
|
391
|
+
(topic.hash % DEFAULT_MODULUS)
|
|
392
|
+
+ (((old_evictions % DEFAULT_MODULUS) * (old_evictions % DEFAULT_MODULUS)) % DEFAULT_MODULUS)
|
|
393
|
+
) % DEFAULT_MODULUS
|
|
367
394
|
# Pick remote_hash such that remote_hash % modulus == target_remainder AND remote_hash != topic.hash.
|
|
368
395
|
remote_hash = target_remainder + DEFAULT_MODULUS # Different from topic.hash but same modular result.
|
|
369
396
|
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|