rsloop 0.1.2__tar.gz → 0.1.3__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 (43) hide show
  1. {rsloop-0.1.2 → rsloop-0.1.3}/.github/workflows/wheels.yml +10 -0
  2. {rsloop-0.1.2 → rsloop-0.1.3}/.gitignore +2 -1
  3. {rsloop-0.1.2 → rsloop-0.1.3}/Cargo.lock +4 -3
  4. {rsloop-0.1.2 → rsloop-0.1.3}/Cargo.toml +5 -2
  5. rsloop-0.1.3/PKG-INFO +303 -0
  6. rsloop-0.1.3/README.md +270 -0
  7. {rsloop-0.1.2 → rsloop-0.1.3}/benchmarks/compare_event_loops.py +32 -4
  8. {rsloop-0.1.2 → rsloop-0.1.3}/demo/fastapi_service.py +28 -4
  9. {rsloop-0.1.2 → rsloop-0.1.3}/examples/04_unix_and_accepted_socket.py +4 -0
  10. {rsloop-0.1.2 → rsloop-0.1.3}/examples/05_pipes_signals_subprocesses.py +38 -8
  11. {rsloop-0.1.2 → rsloop-0.1.3}/pyproject.toml +1 -1
  12. rsloop-0.1.3/scripts/build-wheels.sh +232 -0
  13. {rsloop-0.1.2 → rsloop-0.1.3}/src/callbacks.rs +3 -2
  14. rsloop-0.1.3/src/fd_ops.rs +231 -0
  15. {rsloop-0.1.2 → rsloop-0.1.3}/src/loop_core.rs +7 -6
  16. {rsloop-0.1.2 → rsloop-0.1.3}/src/process_transport.rs +43 -6
  17. {rsloop-0.1.2 → rsloop-0.1.3}/src/python_api.rs +176 -76
  18. {rsloop-0.1.2 → rsloop-0.1.3}/src/runtime.rs +15 -2
  19. {rsloop-0.1.2 → rsloop-0.1.3}/src/stream_transport.rs +341 -97
  20. rsloop-0.1.3/tests/test_run.py +165 -0
  21. {rsloop-0.1.2 → rsloop-0.1.3}/uv.lock +1 -1
  22. rsloop-0.1.2/PKG-INFO +0 -299
  23. rsloop-0.1.2/README.md +0 -266
  24. rsloop-0.1.2/scripts/build-wheels.sh +0 -128
  25. rsloop-0.1.2/src/fd_ops.rs +0 -109
  26. rsloop-0.1.2/tests/test_run.py +0 -25
  27. {rsloop-0.1.2 → rsloop-0.1.3}/LICENSE +0 -0
  28. {rsloop-0.1.2 → rsloop-0.1.3}/benchmarks/README.md +0 -0
  29. {rsloop-0.1.2 → rsloop-0.1.3}/build.rs +0 -0
  30. {rsloop-0.1.2 → rsloop-0.1.3}/demo/README.md +0 -0
  31. {rsloop-0.1.2 → rsloop-0.1.3}/examples/01_basics.py +0 -0
  32. {rsloop-0.1.2 → rsloop-0.1.3}/examples/02_fd_and_sockets.py +0 -0
  33. {rsloop-0.1.2 → rsloop-0.1.3}/examples/03_streams.py +0 -0
  34. {rsloop-0.1.2 → rsloop-0.1.3}/python/rsloop/__init__.py +0 -0
  35. {rsloop-0.1.2 → rsloop-0.1.3}/rsloop.png +0 -0
  36. {rsloop-0.1.2 → rsloop-0.1.3}/src/async_event.rs +0 -0
  37. {rsloop-0.1.2 → rsloop-0.1.3}/src/blocking.rs +0 -0
  38. {rsloop-0.1.2 → rsloop-0.1.3}/src/context.rs +0 -0
  39. {rsloop-0.1.2 → rsloop-0.1.3}/src/errors.rs +0 -0
  40. {rsloop-0.1.2 → rsloop-0.1.3}/src/fast_streams.rs +0 -0
  41. {rsloop-0.1.2 → rsloop-0.1.3}/src/lib.rs +0 -0
  42. {rsloop-0.1.2 → rsloop-0.1.3}/src/profiler.rs +0 -0
  43. {rsloop-0.1.2 → rsloop-0.1.3}/src/python_names.rs +0 -0
@@ -20,6 +20,13 @@ jobs:
20
20
  - os_name: linux
21
21
  runner: ubuntu-latest
22
22
  rust_target: x86_64-unknown-linux-gnu
23
+ - os_name: windows-amd64
24
+ runner: windows-latest
25
+ rust_target: x86_64-pc-windows-msvc
26
+ - os_name: windows-arm64
27
+ runner: windows-11-arm
28
+ rust_target: aarch64-pc-windows-msvc
29
+ python_versions: "3.11 3.12 3.13 3.14 3.14t"
23
30
  - os_name: macos-intel
24
31
  runner: macos-15-intel
25
32
  rust_target: x86_64-apple-darwin
@@ -50,6 +57,9 @@ jobs:
50
57
  uses: Swatinem/rust-cache@v2
51
58
 
52
59
  - name: Build wheels
60
+ shell: bash
61
+ env:
62
+ RSLOOP_PYTHON_VERSIONS: ${{ matrix.python_versions }}
53
63
  run: scripts/build-wheels.sh --out dist --target "${{ matrix.rust_target }}"
54
64
 
55
65
  - name: Upload wheel artifacts
@@ -5,8 +5,9 @@ dist/
5
5
  tmp/
6
6
 
7
7
  *.so
8
+ *.pyd
8
9
 
9
- python/uvloop_rust_impl/_loop
10
+ python/rsloop/_loop*
10
11
 
11
12
  benchmarks/profiles*
12
13
  benchmarks/compare_event_loops.results.json
@@ -943,7 +943,7 @@ dependencies = [
943
943
 
944
944
  [[package]]
945
945
  name = "rsloop"
946
- version = "0.1.1"
946
+ version = "0.1.3"
947
947
  dependencies = [
948
948
  "crossbeam-channel",
949
949
  "futures",
@@ -954,6 +954,7 @@ dependencies = [
954
954
  "pyo3-build-config",
955
955
  "signal-hook",
956
956
  "socket2",
957
+ "windows-sys",
957
958
  ]
958
959
 
959
960
  [[package]]
@@ -1043,9 +1044,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
1043
1044
 
1044
1045
  [[package]]
1045
1046
  name = "signal-hook"
1046
- version = "0.3.18"
1047
+ version = "0.4.3"
1047
1048
  source = "registry+https://github.com/rust-lang/crates.io-index"
1048
- checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2"
1049
+ checksum = "3b57709da74f9ff9f4a27dce9526eec25ca8407c45a7887243b031a58935fb8e"
1049
1050
  dependencies = [
1050
1051
  "libc",
1051
1052
  "signal-hook-registry",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "rsloop"
3
- version = "0.1.1"
3
+ version = "0.1.3"
4
4
  edition = "2021"
5
5
  description = "An event loop for asyncio written in Rust"
6
6
  license = "Apache-2.0"
@@ -24,9 +24,12 @@ libc = "0.2"
24
24
  pprof = { version = "0.15.0", default-features = false, features = ["flamegraph"], optional = true }
25
25
  pyo3 = { version = "0.28", features = ["extension-module"] }
26
26
  pyo3-async-runtimes = { version = "0.28", features = ["async-std-runtime"] }
27
- signal-hook = "0.3"
27
+ signal-hook = "0.4"
28
28
  socket2 = "0.6"
29
29
 
30
+ [target.'cfg(windows)'.dependencies]
31
+ windows-sys = { version = "0.61", features = ["Win32_Foundation", "Win32_Networking_WinSock", "Win32_System_Pipes", "Win32_System_Threading"] }
32
+
30
33
  [build-dependencies]
31
34
  pyo3-build-config = "0.28"
32
35
 
rsloop-0.1.3/PKG-INFO ADDED
@@ -0,0 +1,303 @@
1
+ Metadata-Version: 2.4
2
+ Name: rsloop
3
+ Version: 0.1.3
4
+ Classifier: Development Status :: 3 - Alpha
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: License :: OSI Approved :: Apache Software License
7
+ Classifier: Operating System :: MacOS
8
+ Classifier: Operating System :: POSIX :: Linux
9
+ Classifier: Programming Language :: Python
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3 :: Only
12
+ Classifier: Programming Language :: Python :: 3.8
13
+ Classifier: Programming Language :: Python :: 3.9
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: Programming Language :: Python :: 3.14
19
+ Classifier: Programming Language :: Rust
20
+ Classifier: Topic :: Software Development :: Libraries
21
+ Classifier: Topic :: System :: Networking
22
+ License-File: LICENSE
23
+ Summary: An event loop for asyncio written in Rust
24
+ Keywords: asyncio,event-loop,pyo3,python,rust
25
+ Home-Page: https://github.com/RustedBytes/rsloop
26
+ Author: RustedBytes
27
+ Requires-Python: >=3.8
28
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
29
+ Project-URL: Homepage, https://github.com/RustedBytes/rsloop
30
+ Project-URL: Issues, https://github.com/RustedBytes/rsloop/issues
31
+ Project-URL: Repository, https://github.com/RustedBytes/rsloop
32
+
33
+ <img src="./rsloop.png" alt="rsloop logo" align="center">
34
+
35
+ # An event loop for asyncio written in Rust
36
+
37
+ [![PyPI - Version](https://img.shields.io/pypi/v/rsloop)](https://pypi.org/project/rsloop/)
38
+ [![PyPI Downloads](https://static.pepy.tech/personalized-badge/rsloop?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads)](https://pepy.tech/projects/rsloop)
39
+
40
+ `rsloop` is a PyO3-based `asyncio` event loop implemented in Rust.
41
+
42
+ Each `rsloop.Loop` owns a dedicated Rust runtime thread for loop coordination
43
+ and I/O work. Python callbacks, tasks, and coroutines still run on the thread
44
+ that calls `run_forever()` or `run_until_complete()` (usually the main Python
45
+ thread).
46
+
47
+ The package exposes:
48
+
49
+ - a native extension module at `rsloop._loop`
50
+ - a Python wrapper in `python/rsloop/__init__.py`
51
+ - `rsloop.Loop`, `rsloop.new_event_loop()`, and `rsloop.run(...)`
52
+
53
+ Repository metadata currently targets Python `>=3.8`. The packaged project now
54
+ supports the core event-loop surface on Linux, macOS, and Windows, including
55
+ Windows pipe transports and subprocess workflows.
56
+
57
+ ## Install
58
+
59
+ From PyPI:
60
+
61
+ ```bash
62
+ pip install rsloop
63
+ ```
64
+
65
+ With `uv`:
66
+
67
+ ```bash
68
+ uv add rsloop
69
+ ```
70
+
71
+ ## Usage
72
+
73
+ Simple entry point:
74
+
75
+ ```python
76
+ import rsloop
77
+
78
+ async def main():
79
+ ...
80
+
81
+ rsloop.run(main())
82
+ ```
83
+
84
+ Manual loop creation also works:
85
+
86
+ ```python
87
+ import asyncio
88
+ import rsloop
89
+
90
+ loop = rsloop.new_event_loop()
91
+ asyncio.set_event_loop(loop)
92
+ try:
93
+ loop.run_until_complete(...)
94
+ finally:
95
+ asyncio.set_event_loop(None)
96
+ loop.close()
97
+ ```
98
+
99
+ Importing `rsloop` also patches `asyncio.set_event_loop()` so Python 3.8 can
100
+ accept an `rsloop.Loop` instance, matching the behavior exercised by
101
+ `tests/test_run.py`.
102
+
103
+ ## Verified Surface Area
104
+
105
+ The current codebase implements these user-facing areas.
106
+
107
+ Loop lifecycle and scheduling:
108
+
109
+ - `run_forever`, `run_until_complete`, `stop`, `close`
110
+ - `time`, `is_running`, `is_closed`
111
+ - `get_debug`, `set_debug`
112
+ - `call_soon`, `call_soon_threadsafe`, `call_later`, `call_at`
113
+ - returned `Handle` and `TimerHandle` objects with `cancel()` / `cancelled()`
114
+
115
+ Tasks, futures, and execution helpers:
116
+
117
+ - `create_future`, `create_task`
118
+ - `set_task_factory`, `get_task_factory`
119
+ - `set_exception_handler`, `get_exception_handler`,
120
+ `call_exception_handler`, `default_exception_handler`
121
+ - `set_default_executor`, `run_in_executor`
122
+ - `shutdown_asyncgens`, `shutdown_default_executor`
123
+ - callback execution under captured `contextvars.Context`
124
+ - `asyncio.get_running_loop()` support while running on `rsloop`
125
+ - `rsloop.run(...)` helper, with `asyncio.run(..., loop_factory=...)`
126
+ integration on Python 3.12+
127
+
128
+ I/O and networking:
129
+
130
+ - `add_reader`, `remove_reader`, `add_writer`, `remove_writer`
131
+ - `sock_recv`, `sock_recv_into`, `sock_sendall`, `sock_accept`, `sock_connect`
132
+ - `getaddrinfo`, `getnameinfo`
133
+ - `create_server`, `create_connection`
134
+ - `create_unix_server`, `create_unix_connection`
135
+ - `connect_accepted_socket`
136
+ - returned `Server` objects with `close()`, `is_serving()`, `get_loop()`,
137
+ and `sockets()`
138
+ - returned `StreamTransport` objects with `write()`, `writelines()`, `close()`,
139
+ `abort()`, `is_closing()`, `write_eof()`, `can_write_eof()`,
140
+ `get_extra_info()`, `get_protocol()`, `set_protocol()`,
141
+ `pause_reading()`, `resume_reading()`, `is_reading()`
142
+
143
+ Pipes, subprocesses, and signals:
144
+
145
+ - `connect_read_pipe`, `connect_write_pipe`
146
+ - `subprocess_exec`, `subprocess_shell`
147
+ - returned `ProcessTransport` and `ProcessPipeTransport` objects
148
+ - higher-level compatibility with `asyncio.create_subprocess_exec()` and
149
+ `asyncio.create_subprocess_shell()`
150
+ - Unix subprocess options including `cwd`, `env`, `executable`, `pass_fds`,
151
+ `start_new_session`, `process_group`, `user`, `group`, `extra_groups`,
152
+ `umask`, and `restore_signals`
153
+ - `add_signal_handler`, `remove_signal_handler`
154
+
155
+ Profiling:
156
+
157
+ - `profile(...)`, `profiler_running()`, `start_profiler()`, `stop_profiler()`
158
+
159
+ ## Fast Streams
160
+
161
+ Importing `rsloop` patches `asyncio.open_connection()` and
162
+ `asyncio.start_server()` by default.
163
+
164
+ That import-time behavior is controlled by `RSLOOP_USE_FAST_STREAMS` and can be
165
+ disabled with:
166
+
167
+ ```bash
168
+ export RSLOOP_USE_FAST_STREAMS=0
169
+ ```
170
+
171
+ The native fast-stream path is used only when:
172
+
173
+ - the running loop is an `rsloop.Loop`
174
+ - `ssl` is unset or `None`
175
+
176
+ Otherwise `rsloop` falls back to the stdlib `asyncio.streams` helpers.
177
+
178
+ The implementation lives in `src/fast_streams.rs` and is backed by the lower
179
+ level transport code in `src/stream_transport.rs`.
180
+
181
+ ## Current Limitations
182
+
183
+ These gaps are visible in the current implementation.
184
+
185
+ - TLS is not implemented.
186
+ - `start_tls()` is stubbed.
187
+ - `ssl=...` is rejected for `create_server`, `create_connection`,
188
+ `create_unix_server`, `create_unix_connection`, and
189
+ `connect_accepted_socket`.
190
+ - Stream transport flow control is partial:
191
+ `pause_reading()` and `resume_reading()` work, but
192
+ `get_write_buffer_size()` returns `0`,
193
+ `get_write_buffer_limits()` returns `(0, 0)`, and
194
+ `set_write_buffer_limits()` is a no-op.
195
+ - Several compatibility parameters are currently accepted only to preserve API
196
+ shape, not to provide full behavior:
197
+ `server_hostname`, `happy_eyeballs_delay`, `interleave`, `all_errors`,
198
+ `ssl_handshake_timeout`, `ssl_shutdown_timeout`, and
199
+ `shutdown_default_executor(timeout=...)`.
200
+ - Subprocess support is intentionally incomplete:
201
+ `preexec_fn` is unsupported, and text mode is rejected for
202
+ `asyncio.create_subprocess_exec()` /
203
+ `asyncio.create_subprocess_shell()` when using the stdlib subprocess stream
204
+ protocol.
205
+ - Low-level subprocess transport APIs do support text decoding when used with a
206
+ custom subprocess protocol.
207
+ - Unix-specific APIs remain Unix-specific:
208
+ `create_unix_server`, `create_unix_connection`,
209
+ `add_signal_handler`, `remove_signal_handler`.
210
+ - Platform-specific limitations still apply:
211
+ Unix socket APIs and Unix signal handlers remain Unix-only, and several
212
+ subprocess options such as `pass_fds`, `user`, `group`, and `umask` are
213
+ still specific to Unix process spawning.
214
+
215
+ ## Build
216
+
217
+ Quick check:
218
+
219
+ ```bash
220
+ cargo check
221
+ ```
222
+
223
+ Release build and editable install:
224
+
225
+ ```bash
226
+ cargo build --release
227
+ uv run --with maturin maturin develop --release
228
+ ```
229
+
230
+ Build release wheels into `dist/wheels`:
231
+
232
+ ```bash
233
+ scripts/build-wheels.sh
234
+ ```
235
+
236
+ That script currently defaults to CPython `3.8 3.9 3.10 3.11 3.12 3.13 3.14`
237
+ plus free-threaded `3.14t`, and uses `uv python install` / `uv python find` to
238
+ locate interpreters.
239
+
240
+ ## Profiling
241
+
242
+ Profiling is behind the Cargo feature `profiler` and is disabled by default.
243
+ Build or install with that feature first:
244
+
245
+ ```bash
246
+ cargo build --release --features profiler
247
+ uv run --with maturin maturin develop --release --features profiler
248
+ ```
249
+
250
+ Then wrap the code you want to inspect:
251
+
252
+ ```python
253
+ import rsloop
254
+
255
+ with rsloop.profile("rsloop-flamegraph.svg", frequency=999):
256
+ rsloop.run(main())
257
+ ```
258
+
259
+ Or manage the session manually:
260
+
261
+ ```python
262
+ import rsloop
263
+
264
+ rsloop.start_profiler(frequency=999)
265
+ try:
266
+ rsloop.run(main())
267
+ finally:
268
+ rsloop.stop_profiler("rsloop-flamegraph.svg")
269
+ ```
270
+
271
+ Only `format="flamegraph"` is currently implemented. If the extension was built
272
+ without `--features profiler`, `profile()` and `start_profiler()` raise a
273
+ runtime error.
274
+
275
+ ## Examples
276
+
277
+ Run the repository examples from the project root:
278
+
279
+ ```bash
280
+ uv run python examples/01_basics.py
281
+ uv run python examples/02_fd_and_sockets.py
282
+ uv run python examples/03_streams.py
283
+ uv run python examples/04_unix_and_accepted_socket.py
284
+ uv run python examples/05_pipes_signals_subprocesses.py
285
+ ```
286
+
287
+ The repository also includes:
288
+
289
+ - `demo/fastapi_service.py` for running the same FastAPI app on stdlib
290
+ `asyncio`, `uvloop`, or `rsloop`
291
+ - `benchmarks/compare_event_loops.py` for callback, task, and TCP stream
292
+ comparisons
293
+
294
+ ## Benchmark
295
+
296
+ ```bash
297
+ uv run --with maturin maturin develop --release
298
+ uv run --with uvloop python benchmarks/compare_event_loops.py
299
+ ```
300
+
301
+ See `benchmarks/README.md` for workload details and extra flags, and
302
+ `demo/README.md` for the FastAPI loop comparison demo.
303
+
rsloop-0.1.3/README.md ADDED
@@ -0,0 +1,270 @@
1
+ <img src="./rsloop.png" alt="rsloop logo" align="center">
2
+
3
+ # An event loop for asyncio written in Rust
4
+
5
+ [![PyPI - Version](https://img.shields.io/pypi/v/rsloop)](https://pypi.org/project/rsloop/)
6
+ [![PyPI Downloads](https://static.pepy.tech/personalized-badge/rsloop?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads)](https://pepy.tech/projects/rsloop)
7
+
8
+ `rsloop` is a PyO3-based `asyncio` event loop implemented in Rust.
9
+
10
+ Each `rsloop.Loop` owns a dedicated Rust runtime thread for loop coordination
11
+ and I/O work. Python callbacks, tasks, and coroutines still run on the thread
12
+ that calls `run_forever()` or `run_until_complete()` (usually the main Python
13
+ thread).
14
+
15
+ The package exposes:
16
+
17
+ - a native extension module at `rsloop._loop`
18
+ - a Python wrapper in `python/rsloop/__init__.py`
19
+ - `rsloop.Loop`, `rsloop.new_event_loop()`, and `rsloop.run(...)`
20
+
21
+ Repository metadata currently targets Python `>=3.8`. The packaged project now
22
+ supports the core event-loop surface on Linux, macOS, and Windows, including
23
+ Windows pipe transports and subprocess workflows.
24
+
25
+ ## Install
26
+
27
+ From PyPI:
28
+
29
+ ```bash
30
+ pip install rsloop
31
+ ```
32
+
33
+ With `uv`:
34
+
35
+ ```bash
36
+ uv add rsloop
37
+ ```
38
+
39
+ ## Usage
40
+
41
+ Simple entry point:
42
+
43
+ ```python
44
+ import rsloop
45
+
46
+ async def main():
47
+ ...
48
+
49
+ rsloop.run(main())
50
+ ```
51
+
52
+ Manual loop creation also works:
53
+
54
+ ```python
55
+ import asyncio
56
+ import rsloop
57
+
58
+ loop = rsloop.new_event_loop()
59
+ asyncio.set_event_loop(loop)
60
+ try:
61
+ loop.run_until_complete(...)
62
+ finally:
63
+ asyncio.set_event_loop(None)
64
+ loop.close()
65
+ ```
66
+
67
+ Importing `rsloop` also patches `asyncio.set_event_loop()` so Python 3.8 can
68
+ accept an `rsloop.Loop` instance, matching the behavior exercised by
69
+ `tests/test_run.py`.
70
+
71
+ ## Verified Surface Area
72
+
73
+ The current codebase implements these user-facing areas.
74
+
75
+ Loop lifecycle and scheduling:
76
+
77
+ - `run_forever`, `run_until_complete`, `stop`, `close`
78
+ - `time`, `is_running`, `is_closed`
79
+ - `get_debug`, `set_debug`
80
+ - `call_soon`, `call_soon_threadsafe`, `call_later`, `call_at`
81
+ - returned `Handle` and `TimerHandle` objects with `cancel()` / `cancelled()`
82
+
83
+ Tasks, futures, and execution helpers:
84
+
85
+ - `create_future`, `create_task`
86
+ - `set_task_factory`, `get_task_factory`
87
+ - `set_exception_handler`, `get_exception_handler`,
88
+ `call_exception_handler`, `default_exception_handler`
89
+ - `set_default_executor`, `run_in_executor`
90
+ - `shutdown_asyncgens`, `shutdown_default_executor`
91
+ - callback execution under captured `contextvars.Context`
92
+ - `asyncio.get_running_loop()` support while running on `rsloop`
93
+ - `rsloop.run(...)` helper, with `asyncio.run(..., loop_factory=...)`
94
+ integration on Python 3.12+
95
+
96
+ I/O and networking:
97
+
98
+ - `add_reader`, `remove_reader`, `add_writer`, `remove_writer`
99
+ - `sock_recv`, `sock_recv_into`, `sock_sendall`, `sock_accept`, `sock_connect`
100
+ - `getaddrinfo`, `getnameinfo`
101
+ - `create_server`, `create_connection`
102
+ - `create_unix_server`, `create_unix_connection`
103
+ - `connect_accepted_socket`
104
+ - returned `Server` objects with `close()`, `is_serving()`, `get_loop()`,
105
+ and `sockets()`
106
+ - returned `StreamTransport` objects with `write()`, `writelines()`, `close()`,
107
+ `abort()`, `is_closing()`, `write_eof()`, `can_write_eof()`,
108
+ `get_extra_info()`, `get_protocol()`, `set_protocol()`,
109
+ `pause_reading()`, `resume_reading()`, `is_reading()`
110
+
111
+ Pipes, subprocesses, and signals:
112
+
113
+ - `connect_read_pipe`, `connect_write_pipe`
114
+ - `subprocess_exec`, `subprocess_shell`
115
+ - returned `ProcessTransport` and `ProcessPipeTransport` objects
116
+ - higher-level compatibility with `asyncio.create_subprocess_exec()` and
117
+ `asyncio.create_subprocess_shell()`
118
+ - Unix subprocess options including `cwd`, `env`, `executable`, `pass_fds`,
119
+ `start_new_session`, `process_group`, `user`, `group`, `extra_groups`,
120
+ `umask`, and `restore_signals`
121
+ - `add_signal_handler`, `remove_signal_handler`
122
+
123
+ Profiling:
124
+
125
+ - `profile(...)`, `profiler_running()`, `start_profiler()`, `stop_profiler()`
126
+
127
+ ## Fast Streams
128
+
129
+ Importing `rsloop` patches `asyncio.open_connection()` and
130
+ `asyncio.start_server()` by default.
131
+
132
+ That import-time behavior is controlled by `RSLOOP_USE_FAST_STREAMS` and can be
133
+ disabled with:
134
+
135
+ ```bash
136
+ export RSLOOP_USE_FAST_STREAMS=0
137
+ ```
138
+
139
+ The native fast-stream path is used only when:
140
+
141
+ - the running loop is an `rsloop.Loop`
142
+ - `ssl` is unset or `None`
143
+
144
+ Otherwise `rsloop` falls back to the stdlib `asyncio.streams` helpers.
145
+
146
+ The implementation lives in `src/fast_streams.rs` and is backed by the lower
147
+ level transport code in `src/stream_transport.rs`.
148
+
149
+ ## Current Limitations
150
+
151
+ These gaps are visible in the current implementation.
152
+
153
+ - TLS is not implemented.
154
+ - `start_tls()` is stubbed.
155
+ - `ssl=...` is rejected for `create_server`, `create_connection`,
156
+ `create_unix_server`, `create_unix_connection`, and
157
+ `connect_accepted_socket`.
158
+ - Stream transport flow control is partial:
159
+ `pause_reading()` and `resume_reading()` work, but
160
+ `get_write_buffer_size()` returns `0`,
161
+ `get_write_buffer_limits()` returns `(0, 0)`, and
162
+ `set_write_buffer_limits()` is a no-op.
163
+ - Several compatibility parameters are currently accepted only to preserve API
164
+ shape, not to provide full behavior:
165
+ `server_hostname`, `happy_eyeballs_delay`, `interleave`, `all_errors`,
166
+ `ssl_handshake_timeout`, `ssl_shutdown_timeout`, and
167
+ `shutdown_default_executor(timeout=...)`.
168
+ - Subprocess support is intentionally incomplete:
169
+ `preexec_fn` is unsupported, and text mode is rejected for
170
+ `asyncio.create_subprocess_exec()` /
171
+ `asyncio.create_subprocess_shell()` when using the stdlib subprocess stream
172
+ protocol.
173
+ - Low-level subprocess transport APIs do support text decoding when used with a
174
+ custom subprocess protocol.
175
+ - Unix-specific APIs remain Unix-specific:
176
+ `create_unix_server`, `create_unix_connection`,
177
+ `add_signal_handler`, `remove_signal_handler`.
178
+ - Platform-specific limitations still apply:
179
+ Unix socket APIs and Unix signal handlers remain Unix-only, and several
180
+ subprocess options such as `pass_fds`, `user`, `group`, and `umask` are
181
+ still specific to Unix process spawning.
182
+
183
+ ## Build
184
+
185
+ Quick check:
186
+
187
+ ```bash
188
+ cargo check
189
+ ```
190
+
191
+ Release build and editable install:
192
+
193
+ ```bash
194
+ cargo build --release
195
+ uv run --with maturin maturin develop --release
196
+ ```
197
+
198
+ Build release wheels into `dist/wheels`:
199
+
200
+ ```bash
201
+ scripts/build-wheels.sh
202
+ ```
203
+
204
+ That script currently defaults to CPython `3.8 3.9 3.10 3.11 3.12 3.13 3.14`
205
+ plus free-threaded `3.14t`, and uses `uv python install` / `uv python find` to
206
+ locate interpreters.
207
+
208
+ ## Profiling
209
+
210
+ Profiling is behind the Cargo feature `profiler` and is disabled by default.
211
+ Build or install with that feature first:
212
+
213
+ ```bash
214
+ cargo build --release --features profiler
215
+ uv run --with maturin maturin develop --release --features profiler
216
+ ```
217
+
218
+ Then wrap the code you want to inspect:
219
+
220
+ ```python
221
+ import rsloop
222
+
223
+ with rsloop.profile("rsloop-flamegraph.svg", frequency=999):
224
+ rsloop.run(main())
225
+ ```
226
+
227
+ Or manage the session manually:
228
+
229
+ ```python
230
+ import rsloop
231
+
232
+ rsloop.start_profiler(frequency=999)
233
+ try:
234
+ rsloop.run(main())
235
+ finally:
236
+ rsloop.stop_profiler("rsloop-flamegraph.svg")
237
+ ```
238
+
239
+ Only `format="flamegraph"` is currently implemented. If the extension was built
240
+ without `--features profiler`, `profile()` and `start_profiler()` raise a
241
+ runtime error.
242
+
243
+ ## Examples
244
+
245
+ Run the repository examples from the project root:
246
+
247
+ ```bash
248
+ uv run python examples/01_basics.py
249
+ uv run python examples/02_fd_and_sockets.py
250
+ uv run python examples/03_streams.py
251
+ uv run python examples/04_unix_and_accepted_socket.py
252
+ uv run python examples/05_pipes_signals_subprocesses.py
253
+ ```
254
+
255
+ The repository also includes:
256
+
257
+ - `demo/fastapi_service.py` for running the same FastAPI app on stdlib
258
+ `asyncio`, `uvloop`, or `rsloop`
259
+ - `benchmarks/compare_event_loops.py` for callback, task, and TCP stream
260
+ comparisons
261
+
262
+ ## Benchmark
263
+
264
+ ```bash
265
+ uv run --with maturin maturin develop --release
266
+ uv run --with uvloop python benchmarks/compare_event_loops.py
267
+ ```
268
+
269
+ See `benchmarks/README.md` for workload details and extra flags, and
270
+ `demo/README.md` for the FastAPI loop comparison demo.