pycyphal2 2.0.0.dev0__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.dev0/LICENSE +20 -0
- pycyphal2-2.0.0.dev0/PKG-INFO +58 -0
- pycyphal2-2.0.0.dev0/README.md +28 -0
- pycyphal2-2.0.0.dev0/pyproject.toml +120 -0
- pycyphal2-2.0.0.dev0/setup.cfg +4 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2/__init__.py +89 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2/_api.py +604 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2/_hash.py +204 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2/_header.py +349 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2/_node.py +1472 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2/_publisher.py +427 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2/_subscriber.py +430 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2/_transport.py +92 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2/can/__init__.py +43 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2/can/_interface.py +131 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2/can/_reassembly.py +158 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2/can/_transport.py +525 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2/can/_wire.py +376 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2/can/pythoncan.py +261 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2/can/socketcan.py +225 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2/py.typed +0 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2/udp.py +1000 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2.egg-info/PKG-INFO +58 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2.egg-info/SOURCES.txt +40 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2.egg-info/dependency_links.txt +1 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2.egg-info/requires.txt +6 -0
- pycyphal2-2.0.0.dev0/src/pycyphal2.egg-info/top_level.txt +1 -0
- pycyphal2-2.0.0.dev0/tests/test_gossip.py +440 -0
- pycyphal2-2.0.0.dev0/tests/test_hash.py +106 -0
- pycyphal2-2.0.0.dev0/tests/test_header.py +399 -0
- pycyphal2-2.0.0.dev0/tests/test_integration.py +369 -0
- pycyphal2-2.0.0.dev0/tests/test_monitor.py +232 -0
- pycyphal2-2.0.0.dev0/tests/test_names.py +559 -0
- pycyphal2-2.0.0.dev0/tests/test_parity.py +624 -0
- pycyphal2-2.0.0.dev0/tests/test_parity_coverage.py +917 -0
- pycyphal2-2.0.0.dev0/tests/test_pubsub.py +749 -0
- pycyphal2-2.0.0.dev0/tests/test_reliable.py +1152 -0
- pycyphal2-2.0.0.dev0/tests/test_reorder.py +289 -0
- pycyphal2-2.0.0.dev0/tests/test_rpc.py +321 -0
- pycyphal2-2.0.0.dev0/tests/test_scout.py +76 -0
- pycyphal2-2.0.0.dev0/tests/test_topic.py +463 -0
- pycyphal2-2.0.0.dev0/tests/test_udp.py +1189 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019 Pavel Kirienko and OpenCyphal team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
7
|
+
the Software without restriction, including without limitation the rights to
|
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
10
|
+
subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pycyphal2
|
|
3
|
+
Version: 2.0.0.dev0
|
|
4
|
+
Summary: Pure-Python implementation of Cyphal -- a simple and robust real-time publish/subscribe stack that runs anywhere.
|
|
5
|
+
Author-email: Pavel Kirienko and OpenCyphal team <pavel@opencyphal.org>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://opencyphal.org
|
|
8
|
+
Project-URL: Repository, https://github.com/OpenCyphal/pycyphal
|
|
9
|
+
Keywords: cyphal,opencyphal,uavcan,pub-sub,publish-subscribe,data-bus,ethernet,can-bus,vehicular,onboard-networking,avionics,communication-protocol,broker
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Topic :: Scientific/Engineering
|
|
12
|
+
Classifier: Topic :: Software Development :: Embedded Systems
|
|
13
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
14
|
+
Classifier: Topic :: Software Development :: Object Brokering
|
|
15
|
+
Classifier: Topic :: System :: Distributed Computing
|
|
16
|
+
Classifier: Topic :: System :: Networking
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Programming Language :: Python
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Operating System :: OS Independent
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Provides-Extra: udp
|
|
26
|
+
Requires-Dist: ifaddr~=0.2.0; extra == "udp"
|
|
27
|
+
Provides-Extra: pythoncan
|
|
28
|
+
Requires-Dist: python-can~=4.0; extra == "pythoncan"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
<div align="center">
|
|
32
|
+
|
|
33
|
+
<img src="https://opencyphal.org/favicon-192.png" width="60px">
|
|
34
|
+
|
|
35
|
+
<h1>Cyphal in Python</h1>
|
|
36
|
+
|
|
37
|
+
_pub/sub without steroids_
|
|
38
|
+
|
|
39
|
+
[](https://opencyphal.org/)
|
|
40
|
+
[](https://forum.opencyphal.org)
|
|
41
|
+
[](https://opencyphal.github.io/pycyphal)
|
|
42
|
+
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
-----
|
|
46
|
+
|
|
47
|
+
Python implementation of the [Cyphal](https://opencyphal.org) stack that runs on GNU/Linux, Windows, and macOS.
|
|
48
|
+
|
|
49
|
+
Install as follows.
|
|
50
|
+
Optional features inside the brackets can be removed if not needed; see `pyproject.toml` for the full list:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
pip install pycyphal2[udp,pythoncan]
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
📚 **Read the docs** at <https://opencyphal.github.io/pycyphal>.
|
|
57
|
+
|
|
58
|
+
💡 **Runnable examples** at `examples/`.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="https://opencyphal.org/favicon-192.png" width="60px">
|
|
4
|
+
|
|
5
|
+
<h1>Cyphal in Python</h1>
|
|
6
|
+
|
|
7
|
+
_pub/sub without steroids_
|
|
8
|
+
|
|
9
|
+
[](https://opencyphal.org/)
|
|
10
|
+
[](https://forum.opencyphal.org)
|
|
11
|
+
[](https://opencyphal.github.io/pycyphal)
|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
-----
|
|
16
|
+
|
|
17
|
+
Python implementation of the [Cyphal](https://opencyphal.org) stack that runs on GNU/Linux, Windows, and macOS.
|
|
18
|
+
|
|
19
|
+
Install as follows.
|
|
20
|
+
Optional features inside the brackets can be removed if not needed; see `pyproject.toml` for the full list:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
pip install pycyphal2[udp,pythoncan]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
📚 **Read the docs** at <https://opencyphal.github.io/pycyphal>.
|
|
27
|
+
|
|
28
|
+
💡 **Runnable examples** at `examples/`.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pycyphal2"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
requires-python = ">=3.11"
|
|
9
|
+
dependencies = [] # The core must be dependency-free by design. Transports may add dependencies.
|
|
10
|
+
authors = [
|
|
11
|
+
{ name = "Pavel Kirienko and OpenCyphal team", email = "pavel@opencyphal.org" },
|
|
12
|
+
]
|
|
13
|
+
description = "Pure-Python implementation of Cyphal -- a simple and robust real-time publish/subscribe stack that runs anywhere."
|
|
14
|
+
readme = { file = "README.md", content-type = "text/markdown" }
|
|
15
|
+
license = { text = "MIT" }
|
|
16
|
+
keywords = [
|
|
17
|
+
"cyphal",
|
|
18
|
+
"opencyphal",
|
|
19
|
+
"uavcan",
|
|
20
|
+
"pub-sub",
|
|
21
|
+
"publish-subscribe",
|
|
22
|
+
"data-bus",
|
|
23
|
+
"ethernet",
|
|
24
|
+
"can-bus",
|
|
25
|
+
"vehicular",
|
|
26
|
+
"onboard-networking",
|
|
27
|
+
"avionics",
|
|
28
|
+
"communication-protocol",
|
|
29
|
+
"broker",
|
|
30
|
+
]
|
|
31
|
+
classifiers = [
|
|
32
|
+
"Intended Audience :: Developers",
|
|
33
|
+
"Topic :: Scientific/Engineering",
|
|
34
|
+
"Topic :: Software Development :: Embedded Systems",
|
|
35
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
36
|
+
"Topic :: Software Development :: Object Brokering",
|
|
37
|
+
"Topic :: System :: Distributed Computing",
|
|
38
|
+
"Topic :: System :: Networking",
|
|
39
|
+
"License :: OSI Approved :: MIT License",
|
|
40
|
+
"Programming Language :: Python",
|
|
41
|
+
"Programming Language :: Python :: 3",
|
|
42
|
+
"Operating System :: OS Independent",
|
|
43
|
+
"Typing :: Typed",
|
|
44
|
+
]
|
|
45
|
+
[project.urls]
|
|
46
|
+
Homepage = "https://opencyphal.org"
|
|
47
|
+
Repository = "https://github.com/OpenCyphal/pycyphal"
|
|
48
|
+
|
|
49
|
+
[tool.setuptools.dynamic]
|
|
50
|
+
version = { attr = "pycyphal2.__version__" }
|
|
51
|
+
|
|
52
|
+
[project.optional-dependencies]
|
|
53
|
+
udp = ["ifaddr~=0.2.0"]
|
|
54
|
+
pythoncan = ["python-can~=4.0"]
|
|
55
|
+
|
|
56
|
+
[tool.setuptools.packages.find]
|
|
57
|
+
where = ["src"]
|
|
58
|
+
|
|
59
|
+
[tool.setuptools.package-data]
|
|
60
|
+
pycyphal2 = ["py.typed"]
|
|
61
|
+
|
|
62
|
+
[tool.mypy]
|
|
63
|
+
strict = true
|
|
64
|
+
mypy_path = "src"
|
|
65
|
+
warn_unused_ignores = false
|
|
66
|
+
implicit_reexport = false
|
|
67
|
+
|
|
68
|
+
[[tool.mypy.overrides]]
|
|
69
|
+
module = ["tests.*"]
|
|
70
|
+
disallow_untyped_defs = false
|
|
71
|
+
check_untyped_defs = true
|
|
72
|
+
|
|
73
|
+
[tool.coverage.run]
|
|
74
|
+
branch = true
|
|
75
|
+
source_pkgs = ["pycyphal2"]
|
|
76
|
+
|
|
77
|
+
[tool.coverage.report]
|
|
78
|
+
show_missing = true
|
|
79
|
+
exclude_lines = [
|
|
80
|
+
"pragma: no cover",
|
|
81
|
+
"if __name__ == .__main__.",
|
|
82
|
+
"if TYPE_CHECKING:",
|
|
83
|
+
"raise NotImplementedError",
|
|
84
|
+
"@(abc\\.)?abstractmethod",
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
[tool.coverage.html]
|
|
88
|
+
directory = "htmlcov"
|
|
89
|
+
|
|
90
|
+
[tool.pytest.ini_options]
|
|
91
|
+
asyncio_mode = "auto"
|
|
92
|
+
|
|
93
|
+
[tool.ruff]
|
|
94
|
+
line-length = 120
|
|
95
|
+
target-version = "py312"
|
|
96
|
+
preview = true
|
|
97
|
+
|
|
98
|
+
[tool.ruff.lint]
|
|
99
|
+
# Only the checks the project needs right now; others disabled to avoid false positives.
|
|
100
|
+
select = [
|
|
101
|
+
"F401", # unused imports
|
|
102
|
+
"F811", # redefinition of unused name
|
|
103
|
+
"F841", # local variable assigned but never used
|
|
104
|
+
"ARG001", # unused function argument
|
|
105
|
+
"ARG002", # unused method argument
|
|
106
|
+
"ARG005", # unused lambda argument
|
|
107
|
+
"PLR6301", # method could be a function or static method
|
|
108
|
+
"SLF001", # private member accessed from outside its class/module
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
[tool.ruff.lint.per-file-ignores]
|
|
112
|
+
# Tests may access internals for white-box testing; allow SLF001 there.
|
|
113
|
+
"tests/*" = ["SLF001", "ARG", "PLR6301"]
|
|
114
|
+
|
|
115
|
+
[tool.black]
|
|
116
|
+
line-length = 120
|
|
117
|
+
target-version = ['py312']
|
|
118
|
+
include = '''
|
|
119
|
+
((src|tests|examples)/.*\.pyi?$)
|
|
120
|
+
'''
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""
|
|
2
|
+
`Cyphal <https://opencyphal.org>`_ in Python —
|
|
3
|
+
decentralized real-time pub/sub with tunable reliability, service discovery, and zero configuration.
|
|
4
|
+
Works anywhere, `even baremetal MCUs <https://github.com/OpenCyphal-Garage/cy>`_.
|
|
5
|
+
|
|
6
|
+
Supports various transports such as Ethernet (UDP) and CAN FD with optional redundancy.
|
|
7
|
+
Set up a transport, make a node, publish and subscribe:
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
from pycyphal2 import Node, Instant
|
|
11
|
+
from pycyphal2.udp import UDPTransport
|
|
12
|
+
|
|
13
|
+
async def main():
|
|
14
|
+
node = Node.new(UDPTransport.new(), "my_node")
|
|
15
|
+
|
|
16
|
+
pub = node.advertise("sensor/temperature")
|
|
17
|
+
await pub(Instant.now() + 1.0, b"21.5")
|
|
18
|
+
|
|
19
|
+
sub = node.subscribe("sensor/temperature")
|
|
20
|
+
async for arrival in sub:
|
|
21
|
+
print(arrival.message)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
All public symbols live at the top level — just `import pycyphal2`.
|
|
25
|
+
Transport modules (`pycyphal2.udp`, `pycyphal2.can`) are imported separately
|
|
26
|
+
so that only the needed dependencies are pulled in.
|
|
27
|
+
|
|
28
|
+
The source repository contains a collection of runnable examples.
|
|
29
|
+
|
|
30
|
+
Environment variables control name remapping similar to ROS:
|
|
31
|
+
|
|
32
|
+
- `CYPHAL_NAMESPACE` — default namespace prepended to relative topic names.
|
|
33
|
+
- `CYPHAL_REMAP` — topic name remappings (`from=to` pairs, whitespace-separated).
|
|
34
|
+
|
|
35
|
+
Publication is best-effort by default. Pass ``reliable=True`` when publishing to retry delivery until
|
|
36
|
+
acknowledged by every known subscriber or until the deadline; if the remote side does not acknowledge in time,
|
|
37
|
+
:class:`DeliveryError` is raised.
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
await pub(Instant.now() + 1.0, b"payload", reliable=True)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Subscriptions normally yield messages as soon as they arrive. Set ``reordering_window`` [seconds] on
|
|
44
|
+
:meth:`Node.subscribe` to allow delaying out-of-order messages to reconstruct the original publication order.
|
|
45
|
+
This is useful for sensor feeds and state estimators.
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
sub = node.subscribe("sensor/temperature", reordering_window=0.1)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
RPC is layered directly on top of pub/sub. Use :meth:`Publisher.request` to publish a message that expects
|
|
52
|
+
responses, and use :attr:`Arrival.breadcrumb` on the subscriber side to send a unicast reply back to the requester.
|
|
53
|
+
One request may yield responses from multiple subscribers.
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
stream = await pub.request(Instant.now() + 1.0, 0.5, b"read")
|
|
57
|
+
async for response in stream:
|
|
58
|
+
print(response.message)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Streaming is just repeated replying on the same breadcrumb. The requester consumes such replies through
|
|
62
|
+
:class:`ResponseStream`; each responder numbers its own responses from zero upward.
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
await arrival.breadcrumb(Instant.now() + 1.0, b"chunk-1", reliable=True)
|
|
66
|
+
await arrival.breadcrumb(Instant.now() + 1.0, b"chunk-2", reliable=True)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Cyphal does not define a serialization format. Previous versions used to define the DSDL format but it has been
|
|
70
|
+
extracted into an independent project, and Cyphal was made serialization-agnostic in v1.1+.
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
from __future__ import annotations
|
|
74
|
+
|
|
75
|
+
from ._api import *
|
|
76
|
+
from ._transport import Transport as Transport
|
|
77
|
+
from ._transport import TransportArrival as TransportArrival
|
|
78
|
+
from ._transport import SubjectWriter as SubjectWriter
|
|
79
|
+
|
|
80
|
+
__version__ = "2.0.0.dev0"
|
|
81
|
+
|
|
82
|
+
# pdoc needs __all__ to display re-exported members.
|
|
83
|
+
__all__ = [
|
|
84
|
+
_k
|
|
85
|
+
for _k, _v in vars().items()
|
|
86
|
+
if not _k.startswith("_")
|
|
87
|
+
and _k not in {"annotations", "TYPE_CHECKING"}
|
|
88
|
+
and (getattr(_v, "__module__", None) or "").startswith(__name__)
|
|
89
|
+
]
|