motorcortex-python 1.0.0rc1__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.
- motorcortex/__init__.py +314 -0
- motorcortex/_connection_state.py +58 -0
- motorcortex/_request_builders.py +157 -0
- motorcortex/_request_utils.py +314 -0
- motorcortex/_subscribe_dispatch.py +90 -0
- motorcortex/exceptions.py +65 -0
- motorcortex/init_threads.py +103 -0
- motorcortex/message_types.py +387 -0
- motorcortex/motorcortex_hash.json +166 -0
- motorcortex/motorcortex_pb2.py +105 -0
- motorcortex/motorcortex_pb2.pyi +1961 -0
- motorcortex/nng_url.py +49 -0
- motorcortex/parameter_tree.py +86 -0
- motorcortex/py.typed +0 -0
- motorcortex/reply.py +108 -0
- motorcortex/request.py +668 -0
- motorcortex/session.py +194 -0
- motorcortex/setup_logger.py +10 -0
- motorcortex/state_callback_handler.py +92 -0
- motorcortex/subscribe.py +400 -0
- motorcortex/subscription.py +414 -0
- motorcortex/timespec.py +173 -0
- motorcortex/version.py +1 -0
- motorcortex_python-1.0.0rc1.dist-info/LICENSE +22 -0
- motorcortex_python-1.0.0rc1.dist-info/METADATA +171 -0
- motorcortex_python-1.0.0rc1.dist-info/RECORD +28 -0
- motorcortex_python-1.0.0rc1.dist-info/WHEEL +5 -0
- motorcortex_python-1.0.0rc1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: motorcortex-python
|
|
3
|
+
Version: 1.0.0rc1
|
|
4
|
+
Summary: Python bindings for Motorcortex Engine
|
|
5
|
+
Home-page: https://www.motorcortex.io
|
|
6
|
+
Author: Alexey Zakharov
|
|
7
|
+
Author-email: alexey.zakharov@vectioneer.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Classifier: Topic :: System :: Distributed Computing
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: pynng<2,>=0.9.0
|
|
24
|
+
Requires-Dist: protobuf>=3.20
|
|
25
|
+
|
|
26
|
+
# motorcortex-python
|
|
27
|
+
|
|
28
|
+
[](https://git.vectioneer.com/pub/motorcortex-python/-/commits/master)
|
|
29
|
+
[](https://git.vectioneer.com/pub/motorcortex-python/-/commits/master)
|
|
30
|
+
[](https://pypi.org/project/motorcortex-python/)
|
|
31
|
+
[](https://pypi.org/project/motorcortex-python/)
|
|
32
|
+
[](LICENSE)
|
|
33
|
+
|
|
34
|
+
Python bindings for the [Motorcortex](https://www.motorcortex.io) real-time control engine. Connect to a Motorcortex server, read and write parameters, and stream live telemetry over a single TLS-secured websocket.
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install motorcortex-python
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Requires Python ≥ 3.10. Runtime dependencies (`pynng`, `protobuf`) are installed automatically.
|
|
43
|
+
|
|
44
|
+
## Quick start
|
|
45
|
+
|
|
46
|
+
Recommended — `Session` context manager (close is automatic, even on exceptions):
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
import motorcortex
|
|
50
|
+
|
|
51
|
+
with motorcortex.Session(
|
|
52
|
+
"wss://192.168.2.100",
|
|
53
|
+
certificate="mcx.cert.crt",
|
|
54
|
+
login="admin", password="admin",
|
|
55
|
+
timeout_ms=1000,
|
|
56
|
+
) as s:
|
|
57
|
+
# Read a single parameter
|
|
58
|
+
reply = s.req.getParameter("root/Control/dummyDouble").get()
|
|
59
|
+
print(reply.value)
|
|
60
|
+
|
|
61
|
+
# Write a parameter
|
|
62
|
+
s.req.setParameter("root/Control/dummyDouble", 3.14).get()
|
|
63
|
+
|
|
64
|
+
# Subscribe to a streamed update (every 10th cycle)
|
|
65
|
+
subscription = s.sub.subscribe(
|
|
66
|
+
["root/Control/dummyDouble"], "myGroup", frq_divider=10,
|
|
67
|
+
)
|
|
68
|
+
subscription.get()
|
|
69
|
+
subscription.notify(lambda result: print(result[0].value))
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Explicit-objects form — the original API, still supported:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
types = motorcortex.MessageTypes()
|
|
76
|
+
tree = motorcortex.ParameterTree()
|
|
77
|
+
|
|
78
|
+
req, sub = motorcortex.connect(
|
|
79
|
+
"wss://192.168.2.100", types, tree,
|
|
80
|
+
certificate="mcx.cert.crt",
|
|
81
|
+
login="admin", password="admin",
|
|
82
|
+
)
|
|
83
|
+
try:
|
|
84
|
+
reply = req.getParameter("root/Control/dummyDouble").get()
|
|
85
|
+
print(reply.value)
|
|
86
|
+
finally:
|
|
87
|
+
sub.close()
|
|
88
|
+
req.close()
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The URL grammar accepts IPv4, hostnames, and IPv6 literals both with and without explicit ports — e.g. `wss://host`, `wss://host:5568:5567`, `wss://[::1]`, `wss://[fe80::1]:5568:5567`.
|
|
92
|
+
|
|
93
|
+
## Documentation
|
|
94
|
+
|
|
95
|
+
- **[API reference — `docs/_index.md`](docs/_index.md)** — flat, method-by-method reference for every public class and function. Regenerated from the docstrings via `pydoc-markdown`.
|
|
96
|
+
- **[`ARCHITECTURE.md`](ARCHITECTURE.md)** — internals tour: module layout, connection lifecycle, subscribe frame format, parameter-tree cache, threading model, error contract, type conventions.
|
|
97
|
+
- **[`examples/README.md`](examples/README.md)** — runnable scripts (`quickstart.py`, `error_handling.py`) that demonstrate the canonical usage patterns.
|
|
98
|
+
- **[`CHANGELOG.md`](CHANGELOG.md)** — version history.
|
|
99
|
+
|
|
100
|
+
## Repository layout
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
motorcortex/ Python package
|
|
104
|
+
test/
|
|
105
|
+
unit/ Offline unit tests (no server)
|
|
106
|
+
integration/ Live tests against the vendored test_server
|
|
107
|
+
server/ Vendored C++ test_server (CMake project)
|
|
108
|
+
docs/ pydoc-markdown + stub generation scripts
|
|
109
|
+
benchmark/ Throughput scripts (not part of the test suite)
|
|
110
|
+
sandbox/ Ad-hoc repro scripts
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Testing
|
|
114
|
+
|
|
115
|
+
Unit tests run offline and require only the package itself:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
pip install -e .
|
|
119
|
+
pip install "coverage[toml]>=7.4"
|
|
120
|
+
python -m unittest discover -s test/unit -t .
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Integration tests spawn the vendored `test_server`. Build it once, then run the suite:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
cmake -S test/server -B test/server/build -DCMAKE_BUILD_TYPE=Release
|
|
127
|
+
cmake --build test/server/build
|
|
128
|
+
|
|
129
|
+
python -m unittest discover -s test/integration -t .
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Coverage (line + branch). `pyproject.toml` sets `parallel = true`, so each
|
|
133
|
+
`coverage run` writes a per-process data shard; use `coverage combine` to
|
|
134
|
+
merge them before `coverage report`:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
coverage erase
|
|
138
|
+
coverage run -m unittest discover -s test/unit -t .
|
|
139
|
+
coverage run -m unittest discover -s test/integration -t .
|
|
140
|
+
coverage combine
|
|
141
|
+
coverage report
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
See [`test/README.md`](test/README.md) for the full testing walkthrough.
|
|
145
|
+
|
|
146
|
+
## Regenerating the API reference
|
|
147
|
+
|
|
148
|
+
[`docs/_index.md`](docs/_index.md) is committed and should be refreshed
|
|
149
|
+
before each release so the rendered reference matches the code at
|
|
150
|
+
the tag. The regen is two commands — `pydoc-markdown` first, then
|
|
151
|
+
`format_api.sh` to wrap `>>>` examples as fenced Python blocks and
|
|
152
|
+
prepend the front matter:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
pip install pydoc-markdown
|
|
156
|
+
cd docs
|
|
157
|
+
pydoc-markdown pydoc-markdown.yml > _index.md
|
|
158
|
+
./format_api.sh
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The hook-based one-shot version was dropped — it races with the
|
|
162
|
+
shell redirect and silently loses output. See `docs/readme.md` and
|
|
163
|
+
the comment in `docs/pydoc-markdown.yml` for the full rationale.
|
|
164
|
+
|
|
165
|
+
## Release process
|
|
166
|
+
|
|
167
|
+
See [`PIPHOWTO.md`](PIPHOWTO.md) for PyPI release steps and [`CHANGELOG.md`](CHANGELOG.md) for version history.
|
|
168
|
+
|
|
169
|
+
## License
|
|
170
|
+
|
|
171
|
+
MIT — see [`LICENSE`](LICENSE).
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
motorcortex/__init__.py,sha256=wzoArp3S1h7iRcfGnRbvteR5x-HuVMwBwy7JGBnrsKQ,11965
|
|
2
|
+
motorcortex/_connection_state.py,sha256=0jos75PAyMsN3ew6HRoRDbLY-lGCzDit-SiUR7ZvnlA,2203
|
|
3
|
+
motorcortex/_request_builders.py,sha256=bMZAP1ko6jju1wXs5p6TCp4D93wbvSgpKRf3gvW9_Bg,5245
|
|
4
|
+
motorcortex/_request_utils.py,sha256=npW68Mr8YJk6jGek3CDIAZoFGFULQwaIRhlnNW0aDeA,12115
|
|
5
|
+
motorcortex/_subscribe_dispatch.py,sha256=mPXSqo44RgGryLZabj5xmBd7riW154kA8fnCEQ3Mjho,2942
|
|
6
|
+
motorcortex/exceptions.py,sha256=9xFscRC2yEO2AxesxJ15p6DimDVRIdOeCdj4gF0gahs,2239
|
|
7
|
+
motorcortex/init_threads.py,sha256=rT0VRhdwQfI0ziTi_jeEaLxTzCtkgVo71gmQIeQyuv8,3343
|
|
8
|
+
motorcortex/message_types.py,sha256=FA9jcrHS8lf_KxMi4qF5-bTDvZoGRoZ4paPS8oCF35k,15643
|
|
9
|
+
motorcortex/motorcortex_hash.json,sha256=727K4JXwdtqzkIPtlq7ROSVOKLEsy1za3D7IjlLqFpA,3572
|
|
10
|
+
motorcortex/motorcortex_pb2.py,sha256=bMRS3TcCJMbBGYqGKnmTiQZaTmpbiJv0iYU3EF8s29Q,12790
|
|
11
|
+
motorcortex/motorcortex_pb2.pyi,sha256=8mxofEtlFESwybu9eeo_i5iMw35eNqsmr2DjHU9pg1k,70451
|
|
12
|
+
motorcortex/nng_url.py,sha256=LXmeu_Z1Hn0_YkF4QqLN2SiEvG2_AvKlsYK1Cox_1RQ,1386
|
|
13
|
+
motorcortex/parameter_tree.py,sha256=i9nyo40okT8Y8WfPF2M9FZmCo59oXWuu3PXxmfexFtU,2696
|
|
14
|
+
motorcortex/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
+
motorcortex/reply.py,sha256=GMTaDQ_jeu32H5Zl4LA2Smw_PzNuho2cLuzY-1vvJQ0,3889
|
|
16
|
+
motorcortex/request.py,sha256=r16i1CZOl8qVvSrVNqMocdsOQCjiKw21XfKtN6PqMc0,26253
|
|
17
|
+
motorcortex/session.py,sha256=d5V3q5S5cATJ4Dm9W-lZo388o98ccX48B1fAjgQZ-5U,7038
|
|
18
|
+
motorcortex/setup_logger.py,sha256=ynWC2xMPC5lw_ubU1AL7lbuxm4VK2xqkLRNisAv_fZM,195
|
|
19
|
+
motorcortex/state_callback_handler.py,sha256=Vr9XZ5vN7-CKJdvbJlFkenwH6JfhuInkM1RQvRnlhPY,3069
|
|
20
|
+
motorcortex/subscribe.py,sha256=A0lFkkFTqEh8vSdGvr1JBq25gjo-xh4Ai_kcoW4aPIA,15715
|
|
21
|
+
motorcortex/subscription.py,sha256=n_7OKE_u-Sz0T49S54RuYXlJ2uzXPFzxeXIGg91lfLM,15406
|
|
22
|
+
motorcortex/timespec.py,sha256=bZ-CD2EY0ALoWmJyluThxkiqfVCiGZqPPHRlKSvq7Fs,4573
|
|
23
|
+
motorcortex/version.py,sha256=Zf80zUin_WQ77tGbDMBKvURmGcFKDgnESRwu7q6VXQk,25
|
|
24
|
+
motorcortex_python-1.0.0rc1.dist-info/LICENSE,sha256=m5IaPTxipQwDCpY_YUD927y5QnUzqKGLVUY8E2KxDMk,1165
|
|
25
|
+
motorcortex_python-1.0.0rc1.dist-info/METADATA,sha256=0ZhiD0dkeKZjWLEnncxOk2PRfLDx9t8Lbp8gbJabrW4,6144
|
|
26
|
+
motorcortex_python-1.0.0rc1.dist-info/WHEEL,sha256=hPN0AlP2dZM_3ZJZWP4WooepkmU9wzjGgCLCeFjkHLA,92
|
|
27
|
+
motorcortex_python-1.0.0rc1.dist-info/top_level.txt,sha256=2Glsldo3S13fGB0ub_vogd7y-RQYYNXDjnm-qESmjBY,12
|
|
28
|
+
motorcortex_python-1.0.0rc1.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
motorcortex
|