pyomq 0.2.0__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.
Files changed (152) hide show
  1. pyomq-0.2.0/Cargo.toml +45 -0
  2. pyomq-0.2.0/PKG-INFO +136 -0
  3. pyomq-0.2.0/README.md +105 -0
  4. pyomq-0.2.0/bindings/pyomq/.gitignore +1 -0
  5. pyomq-0.2.0/bindings/pyomq/CHANGELOG.md +15 -0
  6. pyomq-0.2.0/bindings/pyomq/Cargo.lock +1913 -0
  7. pyomq-0.2.0/bindings/pyomq/Cargo.toml +39 -0
  8. pyomq-0.2.0/bindings/pyomq/README.md +105 -0
  9. pyomq-0.2.0/bindings/pyomq/scripts/update_perf.py +296 -0
  10. pyomq-0.2.0/bindings/pyomq/src/constants.rs +131 -0
  11. pyomq-0.2.0/bindings/pyomq/src/context.rs +117 -0
  12. pyomq-0.2.0/bindings/pyomq/src/conversions.rs +73 -0
  13. pyomq-0.2.0/bindings/pyomq/src/dispatch.rs +51 -0
  14. pyomq-0.2.0/bindings/pyomq/src/error.rs +69 -0
  15. pyomq-0.2.0/bindings/pyomq/src/lib.rs +93 -0
  16. pyomq-0.2.0/bindings/pyomq/src/options.rs +373 -0
  17. pyomq-0.2.0/bindings/pyomq/src/runtime.rs +402 -0
  18. pyomq-0.2.0/bindings/pyomq/src/socket.rs +556 -0
  19. pyomq-0.2.0/bindings/pyomq/src/socket_async.rs +300 -0
  20. pyomq-0.2.0/bindings/pyomq/tests/conftest.py +49 -0
  21. pyomq-0.2.0/bindings/pyomq/tests/test_async.py +114 -0
  22. pyomq-0.2.0/bindings/pyomq/tests/test_async_compat.py +83 -0
  23. pyomq-0.2.0/bindings/pyomq/tests/test_async_interop.py +88 -0
  24. pyomq-0.2.0/bindings/pyomq/tests/test_basic.py +88 -0
  25. pyomq-0.2.0/bindings/pyomq/tests/test_compat.py +427 -0
  26. pyomq-0.2.0/bindings/pyomq/tests/test_exceptions.py +149 -0
  27. pyomq-0.2.0/bindings/pyomq/tests/test_interop.py +257 -0
  28. pyomq-0.2.0/bindings/pyomq/tests/test_options.py +145 -0
  29. pyomq-0.2.0/bindings/pyomq/tests/test_perf.py +124 -0
  30. pyomq-0.2.0/bindings/pyomq/tests/test_poller.py +177 -0
  31. pyomq-0.2.0/bindings/pyomq/tests/test_pubsub.py +50 -0
  32. pyomq-0.2.0/bindings/pyomq/tests/test_reqrep.py +42 -0
  33. pyomq-0.2.0/bindings/pyomq/tests/test_socket_types.py +262 -0
  34. pyomq-0.2.0/blume/Cargo.toml +24 -0
  35. pyomq-0.2.0/blume/README.md +48 -0
  36. pyomq-0.2.0/blume/benches/throughput.rs +277 -0
  37. pyomq-0.2.0/blume/src/error.rs +72 -0
  38. pyomq-0.2.0/blume/src/lib.rs +9 -0
  39. pyomq-0.2.0/blume/src/receiver.rs +113 -0
  40. pyomq-0.2.0/blume/src/sender.rs +60 -0
  41. pyomq-0.2.0/blume/src/shared.rs +145 -0
  42. pyomq-0.2.0/blume/tests/basic.rs +84 -0
  43. pyomq-0.2.0/blume/tests/batch.rs +80 -0
  44. pyomq-0.2.0/blume/tests/bounded.rs +60 -0
  45. pyomq-0.2.0/blume/tests/disconnect.rs +59 -0
  46. pyomq-0.2.0/blume/tests/mpsc.rs +125 -0
  47. pyomq-0.2.0/omq-compio/CHANGELOG.md +201 -0
  48. pyomq-0.2.0/omq-compio/Cargo.toml +82 -0
  49. pyomq-0.2.0/omq-compio/benches/common/mod.rs +349 -0
  50. pyomq-0.2.0/omq-compio/benches/compression.rs +351 -0
  51. pyomq-0.2.0/omq-compio/benches/latency.rs +155 -0
  52. pyomq-0.2.0/omq-compio/benches/multithread_push_pull.rs +161 -0
  53. pyomq-0.2.0/omq-compio/benches/pair.rs +165 -0
  54. pyomq-0.2.0/omq-compio/benches/pub_sub.rs +220 -0
  55. pyomq-0.2.0/omq-compio/benches/push_pull.rs +302 -0
  56. pyomq-0.2.0/omq-compio/benches/req_rep.rs +79 -0
  57. pyomq-0.2.0/omq-compio/benches/router_dealer.rs +191 -0
  58. pyomq-0.2.0/omq-compio/examples/profile_tcp.rs +90 -0
  59. pyomq-0.2.0/omq-compio/src/bin/bench_peer.rs +114 -0
  60. pyomq-0.2.0/omq-compio/src/lib.rs +47 -0
  61. pyomq-0.2.0/omq-compio/src/monitor.rs +114 -0
  62. pyomq-0.2.0/omq-compio/src/runtime.rs +105 -0
  63. pyomq-0.2.0/omq-compio/src/socket/dial.rs +422 -0
  64. pyomq-0.2.0/omq-compio/src/socket/handle.rs +1472 -0
  65. pyomq-0.2.0/omq-compio/src/socket/inner.rs +1164 -0
  66. pyomq-0.2.0/omq-compio/src/socket/install.rs +358 -0
  67. pyomq-0.2.0/omq-compio/src/socket/mod.rs +86 -0
  68. pyomq-0.2.0/omq-compio/src/socket/send.rs +830 -0
  69. pyomq-0.2.0/omq-compio/src/transport/driver.rs +992 -0
  70. pyomq-0.2.0/omq-compio/src/transport/inproc.rs +218 -0
  71. pyomq-0.2.0/omq-compio/src/transport/ipc.rs +104 -0
  72. pyomq-0.2.0/omq-compio/src/transport/mod.rs +9 -0
  73. pyomq-0.2.0/omq-compio/src/transport/peer_io.rs +313 -0
  74. pyomq-0.2.0/omq-compio/src/transport/tcp.rs +57 -0
  75. pyomq-0.2.0/omq-compio/src/transport/udp.rs +115 -0
  76. pyomq-0.2.0/omq-compio/tests/blake3zmq.rs +142 -0
  77. pyomq-0.2.0/omq-compio/tests/broker.rs +202 -0
  78. pyomq-0.2.0/omq-compio/tests/conflate.rs +123 -0
  79. pyomq-0.2.0/omq-compio/tests/connection_errors.rs +120 -0
  80. pyomq-0.2.0/omq-compio/tests/coverage_matrix.rs +355 -0
  81. pyomq-0.2.0/omq-compio/tests/curve.rs +192 -0
  82. pyomq-0.2.0/omq-compio/tests/double_close.rs +87 -0
  83. pyomq-0.2.0/omq-compio/tests/draft_types.rs +167 -0
  84. pyomq-0.2.0/omq-compio/tests/fuzz_parsers.rs +469 -0
  85. pyomq-0.2.0/omq-compio/tests/fuzz_socket_actions.rs +227 -0
  86. pyomq-0.2.0/omq-compio/tests/handshake_timeout.rs +73 -0
  87. pyomq-0.2.0/omq-compio/tests/heartbeat.rs +152 -0
  88. pyomq-0.2.0/omq-compio/tests/inproc_subside.rs +108 -0
  89. pyomq-0.2.0/omq-compio/tests/interop_pyzmq_curve.rs +336 -0
  90. pyomq-0.2.0/omq-compio/tests/interop_ruby.rs +461 -0
  91. pyomq-0.2.0/omq-compio/tests/ipc_basic.rs +85 -0
  92. pyomq-0.2.0/omq-compio/tests/ipv6.rs +128 -0
  93. pyomq-0.2.0/omq-compio/tests/large_messages.rs +260 -0
  94. pyomq-0.2.0/omq-compio/tests/linger.rs +182 -0
  95. pyomq-0.2.0/omq-compio/tests/lz4_tcp.rs +88 -0
  96. pyomq-0.2.0/omq-compio/tests/mixed_transports.rs +142 -0
  97. pyomq-0.2.0/omq-compio/tests/monitor.rs +84 -0
  98. pyomq-0.2.0/omq-compio/tests/multi_peer.rs +142 -0
  99. pyomq-0.2.0/omq-compio/tests/options_polish.rs +283 -0
  100. pyomq-0.2.0/omq-compio/tests/priority.rs +223 -0
  101. pyomq-0.2.0/omq-compio/tests/pub_sub.rs +175 -0
  102. pyomq-0.2.0/omq-compio/tests/push_pull.rs +284 -0
  103. pyomq-0.2.0/omq-compio/tests/radio_dish.rs +128 -0
  104. pyomq-0.2.0/omq-compio/tests/reconnect.rs +225 -0
  105. pyomq-0.2.0/omq-compio/tests/reconnect_all_types.rs +203 -0
  106. pyomq-0.2.0/omq-compio/tests/recv_direct.rs +181 -0
  107. pyomq-0.2.0/omq-compio/tests/req_rep.rs +300 -0
  108. pyomq-0.2.0/omq-compio/tests/router_dealer.rs +151 -0
  109. pyomq-0.2.0/omq-compio/tests/tcp_basic.rs +84 -0
  110. pyomq-0.2.0/omq-compio/tests/udp.rs +137 -0
  111. pyomq-0.2.0/omq-compio/tests/unbind_disconnect.rs +75 -0
  112. pyomq-0.2.0/omq-compio/tests/xpub_xsub.rs +258 -0
  113. pyomq-0.2.0/omq-compio/tests/zstd_tcp.rs +239 -0
  114. pyomq-0.2.0/omq-proto/CHANGELOG.md +103 -0
  115. pyomq-0.2.0/omq-proto/Cargo.toml +57 -0
  116. pyomq-0.2.0/omq-proto/benches/mechanism_frame.rs +151 -0
  117. pyomq-0.2.0/omq-proto/src/backoff.rs +92 -0
  118. pyomq-0.2.0/omq-proto/src/connect_opts.rs +59 -0
  119. pyomq-0.2.0/omq-proto/src/endpoint.rs +337 -0
  120. pyomq-0.2.0/omq-proto/src/error.rs +48 -0
  121. pyomq-0.2.0/omq-proto/src/lib.rs +38 -0
  122. pyomq-0.2.0/omq-proto/src/message.rs +1045 -0
  123. pyomq-0.2.0/omq-proto/src/monitor.rs +157 -0
  124. pyomq-0.2.0/omq-proto/src/options.rs +749 -0
  125. pyomq-0.2.0/omq-proto/src/proto/chunked_buf.rs +381 -0
  126. pyomq-0.2.0/omq-proto/src/proto/command.rs +479 -0
  127. pyomq-0.2.0/omq-proto/src/proto/connection.rs +1105 -0
  128. pyomq-0.2.0/omq-proto/src/proto/frame.rs +504 -0
  129. pyomq-0.2.0/omq-proto/src/proto/greeting.rs +327 -0
  130. pyomq-0.2.0/omq-proto/src/proto/mechanism/blake3zmq/cookie.rs +175 -0
  131. pyomq-0.2.0/omq-proto/src/proto/mechanism/blake3zmq/crypto.rs +216 -0
  132. pyomq-0.2.0/omq-proto/src/proto/mechanism/blake3zmq/handshake.rs +881 -0
  133. pyomq-0.2.0/omq-proto/src/proto/mechanism/blake3zmq/mod.rs +357 -0
  134. pyomq-0.2.0/omq-proto/src/proto/mechanism/blake3zmq/transform.rs +195 -0
  135. pyomq-0.2.0/omq-proto/src/proto/mechanism/blake3zmq/wire.rs +105 -0
  136. pyomq-0.2.0/omq-proto/src/proto/mechanism/curve.rs +808 -0
  137. pyomq-0.2.0/omq-proto/src/proto/mechanism/curve_keys.rs +183 -0
  138. pyomq-0.2.0/omq-proto/src/proto/mechanism/mod.rs +414 -0
  139. pyomq-0.2.0/omq-proto/src/proto/mod.rs +237 -0
  140. pyomq-0.2.0/omq-proto/src/proto/transform/common.rs +85 -0
  141. pyomq-0.2.0/omq-proto/src/proto/transform/lz4.rs +618 -0
  142. pyomq-0.2.0/omq-proto/src/proto/transform/mod.rs +164 -0
  143. pyomq-0.2.0/omq-proto/src/proto/transform/zstd.rs +695 -0
  144. pyomq-0.2.0/omq-proto/src/proto/z85.rs +177 -0
  145. pyomq-0.2.0/omq-proto/src/subscription.rs +141 -0
  146. pyomq-0.2.0/omq-proto/src/type_state.rs +246 -0
  147. pyomq-0.2.0/omq-proto/tests/connection.rs +551 -0
  148. pyomq-0.2.0/omq-proto/tests/endpoint.rs +220 -0
  149. pyomq-0.2.0/pyproject.toml +59 -0
  150. pyomq-0.2.0/python/pyomq/__init__.py +453 -0
  151. pyomq-0.2.0/python/pyomq/asyncio.py +206 -0
  152. pyomq-0.2.0/python/pyomq/error.py +47 -0
pyomq-0.2.0/Cargo.toml ADDED
@@ -0,0 +1,45 @@
1
+ [workspace]
2
+ members = [
3
+ "blume",
4
+ "omq",
5
+ "omq-compio",
6
+ "omq-proto",
7
+ "omq-tokio",
8
+ ]
9
+ default-members = ["blume", "omq", "omq-compio", "omq-proto", "omq-tokio"]
10
+ # Bindings live in their own subtree. Each is its own build root - Python's
11
+ # maturin / Ruby's rake-compiler / etc. drive them - and they would otherwise
12
+ # pull foreign-language toolchains into `cargo build --workspace`.
13
+ exclude = ["bindings"]
14
+ resolver = "2"
15
+
16
+ [workspace.package]
17
+ edition = "2024"
18
+ rust-version = "1.93"
19
+ license = "ISC"
20
+ authors = ["Patrik Wenger <paddor@gmail.com>"]
21
+ repository = "https://github.com/paddor/omq.rs"
22
+ description = "Pure Rust OMQ/ZeroMQ: wire-compatible, feature-complete, high-performance."
23
+
24
+ [workspace.lints.rust]
25
+ missing_debug_implementations = "deny"
26
+ unsafe_op_in_unsafe_fn = "deny"
27
+ rust_2018_idioms = { level = "warn", priority = -1 }
28
+ unreachable_pub = "warn"
29
+
30
+ [workspace.lints.clippy]
31
+ all = { level = "warn", priority = -1 }
32
+ pedantic = { level = "warn", priority = -1 }
33
+ module_name_repetitions = "allow"
34
+ missing_errors_doc = "allow"
35
+ missing_panics_doc = "allow"
36
+ must_use_candidate = "allow"
37
+ cast_possible_truncation = "allow"
38
+ cast_sign_loss = "allow"
39
+ cast_precision_loss = "allow"
40
+
41
+ [profile.bench]
42
+ debug = "line-tables-only"
43
+
44
+ [profile.release]
45
+ debug = "line-tables-only"
pyomq-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,136 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyomq
3
+ Version: 0.2.0
4
+ Classifier: Development Status :: 3 - Alpha
5
+ Classifier: License :: OSI Approved :: ISC License (ISCL)
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: Programming Language :: Python :: 3.9
8
+ Classifier: Programming Language :: Python :: 3.10
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Rust
13
+ Classifier: Topic :: System :: Networking
14
+ Requires-Dist: pytest>=7 ; extra == 'test'
15
+ Requires-Dist: pytest-asyncio>=0.21 ; extra == 'test'
16
+ Requires-Dist: pyzmq>=25 ; extra == 'test'
17
+ Provides-Extra: all
18
+ Provides-Extra: blake3zmq
19
+ Provides-Extra: curve
20
+ Provides-Extra: lz4
21
+ Provides-Extra: test
22
+ Provides-Extra: zstd
23
+ Summary: Python binding for omq.rs (Rust libzmq port). Drop-in pyzmq replacement on the common path.
24
+ Keywords: zeromq,omq,messaging,pyzmq,zmq
25
+ Author-email: Patrik Wenger <paddor@gmail.com>
26
+ License: ISC
27
+ Requires-Python: >=3.9
28
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
29
+ Project-URL: Repository, https://github.com/paddor/omq.rs
30
+
31
+ # pyomq
32
+
33
+ Python binding for [omq.rs](https://github.com/paddor/omq.rs), a Rust libzmq
34
+ port. Drop-in pyzmq replacement on the common path.
35
+
36
+ ## Install
37
+
38
+ ```sh
39
+ uv pip install pyomq
40
+ # Optional extras (built into the wheel via cargo features):
41
+ uv pip install 'pyomq[curve]'
42
+ uv pip install 'pyomq[blake3zmq,lz4,zstd]'
43
+ uv pip install 'pyomq[test]' # adds pytest, pyzmq for the interop suite
44
+ ```
45
+
46
+ ## Usage
47
+
48
+ ```python
49
+ import pyomq as zmq # drop-in for `import zmq` from pyzmq
50
+
51
+ ctx = zmq.Context()
52
+ push = ctx.socket(zmq.PUSH)
53
+ push.connect("tcp://127.0.0.1:5555")
54
+ push.send(b"hello")
55
+ push.close()
56
+ ctx.term()
57
+ ```
58
+
59
+ For asynchronous code:
60
+
61
+ ```python
62
+ import pyomq.asyncio as zmq_async
63
+
64
+ ctx = zmq_async.Context()
65
+ sock = ctx.socket(pyomq.PUSH)
66
+ await sock.connect("tcp://127.0.0.1:5555")
67
+ await sock.send(b"hello")
68
+ await sock.close()
69
+ ```
70
+
71
+ ## Status
72
+
73
+ Sync and `asyncio` APIs both ship in this release. All 19 ZMTP socket types are wired:
74
+
75
+ - **Standard (RFC 28 + 47)**: PAIR, PUB, SUB, REQ, REP, DEALER, ROUTER, PULL, PUSH, XPUB, XSUB.
76
+ - **Draft**: SERVER, CLIENT (RFC 41), RADIO, DISH (RFC 48), GATHER, SCATTER (RFC 49), PEER, CHANNEL (RFC 51).
77
+
78
+ Transports: `tcp://`, `ipc://`, `inproc://`, and `udp://` (RADIO/DISH only).
79
+ Optional features built into the wheel: `curve`, `blake3zmq`, `lz4`, `zstd`.
80
+
81
+ DISH groups: use `socket.join(b"group")` / `socket.leave(b"group")` to manage
82
+ subscriptions; messages are sent as multipart `[group, body]`.
83
+
84
+ ## Backend
85
+
86
+ pyomq is built on `omq-compio` (single-threaded io_uring on Linux). The runtime
87
+ runs on a dedicated background thread; every Python call releases the GIL
88
+ across the runtime trip. This is the only backend pyomq supports — the
89
+ `omq-tokio` backend exists in the upstream Rust workspace for callers that need
90
+ a multi-thread tokio integration, but pyomq's per-call overhead is shaped
91
+ around compio's single-thread invariant.
92
+
93
+ ## Performance
94
+
95
+ Loopback PUSH/PULL throughput vs pyzmq, on a Linux 6.12 (Debian 13) VM on an
96
+ Intel Mac Mini 2018 (i7-8700B, 3.2 GHz), Rust 1.95.0, default features:
97
+
98
+ <!-- PERF:START -->
99
+ | Size | inproc pyomq | inproc pyzmq | ratio | tcp pyomq | tcp pyzmq | ratio |
100
+ |---------|-------------:|-------------:|----------:|----------:|----------:|----------:|
101
+ | 8 B | 1.30 M/s | 627 k/s | **2.08×** | 1.36 M/s | 565 k/s | **2.41×** |
102
+ | 32 B | 1.29 M/s | 620 k/s | **2.08×** | 1.36 M/s | 576 k/s | **2.37×** |
103
+ | 128 B | 1.31 M/s | 516 k/s | **2.54×** | 1.29 M/s | 496 k/s | **2.61×** |
104
+ | 512 B | 1.29 M/s | 480 k/s | **2.69×** | 1.21 M/s | 461 k/s | **2.62×** |
105
+ | 2 KiB | 1.17 M/s | 461 k/s | **2.54×** | 908 k/s | 342 k/s | **2.65×** |
106
+ | 8 KiB | 1.04 M/s | 368 k/s | **2.83×** | 349 k/s | 102 k/s | **3.41×** |
107
+ | 32 KiB | 622 k/s | 196 k/s | **3.17×** | 116 k/s | 46 k/s | **2.50×** |
108
+ | 128 KiB | 203 k/s | 70 k/s | **2.91×** | 32 k/s | 24 k/s | **1.32×** |
109
+ <!-- PERF:END -->
110
+
111
+ ### `zmq.proxy()` forwarding (128 B, TCP)
112
+
113
+ <!-- PROXY_PERF:START -->
114
+ | | pyomq | pyzmq | ratio |
115
+ |--------------------|----------:|----------:|----------:|
116
+ | PUSH/PULL msg/s | 963 k/s | 520 k/s | **1.85×** |
117
+ | REQ/REP rt/s | 8,764/s | 6,521/s | **1.34×** |
118
+ <!-- PROXY_PERF:END -->
119
+
120
+ pyomq's `proxy()` runs as a native Rust async loop on the compio thread — no
121
+ Python per-message overhead. pyzmq's `zmq.proxy()` calls libzmq's C-level
122
+ `zmq_proxy`. PUSH/PULL forwarding is throughput-bound and pyomq is ~1.9× faster.
123
+ REQ/REP is latency-bound (4 TCP hops per round-trip) so both are similar.
124
+
125
+ Run `scripts/update_perf.py` (after `maturin develop --release`) to re-measure and update the tables above.
126
+
127
+ ## Develop
128
+
129
+ ```sh
130
+ cd bindings/pyomq
131
+ uv venv && source .venv/bin/activate
132
+ uv pip install maturin pytest pyzmq
133
+ maturin develop --release
134
+ pytest -v
135
+ ```
136
+
pyomq-0.2.0/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # pyomq
2
+
3
+ Python binding for [omq.rs](https://github.com/paddor/omq.rs), a Rust libzmq
4
+ port. Drop-in pyzmq replacement on the common path.
5
+
6
+ ## Install
7
+
8
+ ```sh
9
+ uv pip install pyomq
10
+ # Optional extras (built into the wheel via cargo features):
11
+ uv pip install 'pyomq[curve]'
12
+ uv pip install 'pyomq[blake3zmq,lz4,zstd]'
13
+ uv pip install 'pyomq[test]' # adds pytest, pyzmq for the interop suite
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ```python
19
+ import pyomq as zmq # drop-in for `import zmq` from pyzmq
20
+
21
+ ctx = zmq.Context()
22
+ push = ctx.socket(zmq.PUSH)
23
+ push.connect("tcp://127.0.0.1:5555")
24
+ push.send(b"hello")
25
+ push.close()
26
+ ctx.term()
27
+ ```
28
+
29
+ For asynchronous code:
30
+
31
+ ```python
32
+ import pyomq.asyncio as zmq_async
33
+
34
+ ctx = zmq_async.Context()
35
+ sock = ctx.socket(pyomq.PUSH)
36
+ await sock.connect("tcp://127.0.0.1:5555")
37
+ await sock.send(b"hello")
38
+ await sock.close()
39
+ ```
40
+
41
+ ## Status
42
+
43
+ Sync and `asyncio` APIs both ship in this release. All 19 ZMTP socket types are wired:
44
+
45
+ - **Standard (RFC 28 + 47)**: PAIR, PUB, SUB, REQ, REP, DEALER, ROUTER, PULL, PUSH, XPUB, XSUB.
46
+ - **Draft**: SERVER, CLIENT (RFC 41), RADIO, DISH (RFC 48), GATHER, SCATTER (RFC 49), PEER, CHANNEL (RFC 51).
47
+
48
+ Transports: `tcp://`, `ipc://`, `inproc://`, and `udp://` (RADIO/DISH only).
49
+ Optional features built into the wheel: `curve`, `blake3zmq`, `lz4`, `zstd`.
50
+
51
+ DISH groups: use `socket.join(b"group")` / `socket.leave(b"group")` to manage
52
+ subscriptions; messages are sent as multipart `[group, body]`.
53
+
54
+ ## Backend
55
+
56
+ pyomq is built on `omq-compio` (single-threaded io_uring on Linux). The runtime
57
+ runs on a dedicated background thread; every Python call releases the GIL
58
+ across the runtime trip. This is the only backend pyomq supports — the
59
+ `omq-tokio` backend exists in the upstream Rust workspace for callers that need
60
+ a multi-thread tokio integration, but pyomq's per-call overhead is shaped
61
+ around compio's single-thread invariant.
62
+
63
+ ## Performance
64
+
65
+ Loopback PUSH/PULL throughput vs pyzmq, on a Linux 6.12 (Debian 13) VM on an
66
+ Intel Mac Mini 2018 (i7-8700B, 3.2 GHz), Rust 1.95.0, default features:
67
+
68
+ <!-- PERF:START -->
69
+ | Size | inproc pyomq | inproc pyzmq | ratio | tcp pyomq | tcp pyzmq | ratio |
70
+ |---------|-------------:|-------------:|----------:|----------:|----------:|----------:|
71
+ | 8 B | 1.30 M/s | 627 k/s | **2.08×** | 1.36 M/s | 565 k/s | **2.41×** |
72
+ | 32 B | 1.29 M/s | 620 k/s | **2.08×** | 1.36 M/s | 576 k/s | **2.37×** |
73
+ | 128 B | 1.31 M/s | 516 k/s | **2.54×** | 1.29 M/s | 496 k/s | **2.61×** |
74
+ | 512 B | 1.29 M/s | 480 k/s | **2.69×** | 1.21 M/s | 461 k/s | **2.62×** |
75
+ | 2 KiB | 1.17 M/s | 461 k/s | **2.54×** | 908 k/s | 342 k/s | **2.65×** |
76
+ | 8 KiB | 1.04 M/s | 368 k/s | **2.83×** | 349 k/s | 102 k/s | **3.41×** |
77
+ | 32 KiB | 622 k/s | 196 k/s | **3.17×** | 116 k/s | 46 k/s | **2.50×** |
78
+ | 128 KiB | 203 k/s | 70 k/s | **2.91×** | 32 k/s | 24 k/s | **1.32×** |
79
+ <!-- PERF:END -->
80
+
81
+ ### `zmq.proxy()` forwarding (128 B, TCP)
82
+
83
+ <!-- PROXY_PERF:START -->
84
+ | | pyomq | pyzmq | ratio |
85
+ |--------------------|----------:|----------:|----------:|
86
+ | PUSH/PULL msg/s | 963 k/s | 520 k/s | **1.85×** |
87
+ | REQ/REP rt/s | 8,764/s | 6,521/s | **1.34×** |
88
+ <!-- PROXY_PERF:END -->
89
+
90
+ pyomq's `proxy()` runs as a native Rust async loop on the compio thread — no
91
+ Python per-message overhead. pyzmq's `zmq.proxy()` calls libzmq's C-level
92
+ `zmq_proxy`. PUSH/PULL forwarding is throughput-bound and pyomq is ~1.9× faster.
93
+ REQ/REP is latency-bound (4 TCP hops per round-trip) so both are similar.
94
+
95
+ Run `scripts/update_perf.py` (after `maturin develop --release`) to re-measure and update the tables above.
96
+
97
+ ## Develop
98
+
99
+ ```sh
100
+ cd bindings/pyomq
101
+ uv venv && source .venv/bin/activate
102
+ uv pip install maturin pytest pyzmq
103
+ maturin develop --release
104
+ pytest -v
105
+ ```
@@ -0,0 +1 @@
1
+ /CLA*
@@ -0,0 +1,15 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.2.0](https://github.com/paddor/omq.rs/releases/tag/pyomq-v0.2.0) - 2026-05-04
11
+
12
+ ### Added
13
+
14
+ - First PyPI release. Python binding for omq-compio (compio/io_uring backend).
15
+ Linux x86_64 and aarch64 wheels; stable ABI covers Python 3.9+.