rsloop 0.1.51__tar.gz → 0.1.53__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 (272) hide show
  1. {rsloop-0.1.51 → rsloop-0.1.53}/.github/workflows/wheels.yml +1 -1
  2. {rsloop-0.1.51 → rsloop-0.1.53}/Cargo.lock +1 -1
  3. {rsloop-0.1.51 → rsloop-0.1.53}/Cargo.toml +43 -42
  4. rsloop-0.1.53/PKG-INFO +202 -0
  5. rsloop-0.1.53/README.md +168 -0
  6. {rsloop-0.1.51 → rsloop-0.1.53}/benches/compare_event_loops.py +1 -3
  7. rsloop-0.1.53/docs/benchmarks.md +170 -0
  8. {rsloop-0.1.51 → rsloop-0.1.53}/docs/development.md +62 -5
  9. rsloop-0.1.53/docs/fast-streams.md +41 -0
  10. rsloop-0.1.53/docs/free-threading.md +43 -0
  11. {rsloop-0.1.51 → rsloop-0.1.53}/docs/how-it-works.md +43 -30
  12. {rsloop-0.1.51 → rsloop-0.1.53}/docs/index.md +3 -0
  13. {rsloop-0.1.51 → rsloop-0.1.53}/docs/rust-extensions.md +1 -1
  14. rsloop-0.1.53/docs/supported-features.md +66 -0
  15. {rsloop-0.1.51 → rsloop-0.1.53}/justfile +1 -0
  16. {rsloop-0.1.51 → rsloop-0.1.53}/mkdocs.yml +4 -0
  17. {rsloop-0.1.51 → rsloop-0.1.53}/pyproject.toml +57 -56
  18. {rsloop-0.1.51 → rsloop-0.1.53}/python/rsloop/__init__.pyi +1 -0
  19. {rsloop-0.1.51 → rsloop-0.1.53}/python/rsloop/_loop_compat.py +3 -2
  20. {rsloop-0.1.51 → rsloop-0.1.53}/qualirs.toml +48 -48
  21. {rsloop-0.1.51 → rsloop-0.1.53}/scripts/hotpath_lab.py +12 -2
  22. {rsloop-0.1.51 → rsloop-0.1.53}/src/engine/commands.rs +4 -1
  23. {rsloop-0.1.51 → rsloop-0.1.53}/src/engine/dispatcher.rs +2 -1
  24. {rsloop-0.1.51 → rsloop-0.1.53}/src/engine/loop_core.rs +5 -4
  25. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/accept.rs +10 -2
  26. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/mod.rs +31 -0
  27. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/py_server.rs +2 -0
  28. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/server.rs +1 -0
  29. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/server_core.rs +16 -3
  30. {rsloop-0.1.51 → rsloop-0.1.53}/uv.lock +1 -1
  31. rsloop-0.1.51/PKG-INFO +0 -651
  32. rsloop-0.1.51/README.md +0 -618
  33. {rsloop-0.1.51 → rsloop-0.1.53}/.cargo/config.toml +0 -0
  34. {rsloop-0.1.51 → rsloop-0.1.53}/.github/workflows/anyio.yml +0 -0
  35. {rsloop-0.1.51 → rsloop-0.1.53}/.github/workflows/kani.yml +0 -0
  36. {rsloop-0.1.51 → rsloop-0.1.53}/.github/workflows/mkdocs.yml +0 -0
  37. {rsloop-0.1.51 → rsloop-0.1.53}/.github/workflows/tests.yml +0 -0
  38. {rsloop-0.1.51 → rsloop-0.1.53}/.github/workflows/update-version.yml +0 -0
  39. {rsloop-0.1.51 → rsloop-0.1.53}/.github/workflows/vibeio-native.yml +0 -0
  40. {rsloop-0.1.51 → rsloop-0.1.53}/.gitignore +0 -0
  41. {rsloop-0.1.51 → rsloop-0.1.53}/.python-version +0 -0
  42. {rsloop-0.1.51 → rsloop-0.1.53}/.vscode/settings.json +0 -0
  43. {rsloop-0.1.51 → rsloop-0.1.53}/LICENSE +0 -0
  44. {rsloop-0.1.51 → rsloop-0.1.53}/benches/compare_granian.py +0 -0
  45. {rsloop-0.1.51 → rsloop-0.1.53}/benches/workload_matrix.py +0 -0
  46. {rsloop-0.1.51 → rsloop-0.1.53}/build.rs +0 -0
  47. {rsloop-0.1.51 → rsloop-0.1.53}/docs/examples.md +0 -0
  48. {rsloop-0.1.51 → rsloop-0.1.53}/docs/getting-started.md +0 -0
  49. {rsloop-0.1.51 → rsloop-0.1.53}/docs/hotpath-lab.md +0 -0
  50. {rsloop-0.1.51 → rsloop-0.1.53}/docs/project-structure.md +0 -0
  51. {rsloop-0.1.51 → rsloop-0.1.53}/docs/rsloop.png +0 -0
  52. {rsloop-0.1.51 → rsloop-0.1.53}/docs/verification.md +0 -0
  53. {rsloop-0.1.51 → rsloop-0.1.53}/examples/01_basics.py +0 -0
  54. {rsloop-0.1.51 → rsloop-0.1.53}/examples/02_fd_and_sockets.py +0 -0
  55. {rsloop-0.1.51 → rsloop-0.1.53}/examples/03_streams.py +0 -0
  56. {rsloop-0.1.51 → rsloop-0.1.53}/examples/04_unix_and_accepted_socket.py +0 -0
  57. {rsloop-0.1.51 → rsloop-0.1.53}/examples/05_pipes_signals_subprocesses.py +0 -0
  58. {rsloop-0.1.51 → rsloop-0.1.53}/examples/README.md +0 -0
  59. {rsloop-0.1.51 → rsloop-0.1.53}/examples/fastapi_service.py +0 -0
  60. {rsloop-0.1.51 → rsloop-0.1.53}/examples/granian_service.py +0 -0
  61. {rsloop-0.1.51 → rsloop-0.1.53}/examples/picows_server.py +0 -0
  62. {rsloop-0.1.51 → rsloop-0.1.53}/examples/picows_test.py +0 -0
  63. {rsloop-0.1.51 → rsloop-0.1.53}/examples/wsbench_websockets.py +0 -0
  64. {rsloop-0.1.51 → rsloop-0.1.53}/pyrightconfig.json +0 -0
  65. {rsloop-0.1.51 → rsloop-0.1.53}/python/rsloop/__init__.py +0 -0
  66. {rsloop-0.1.51 → rsloop-0.1.53}/python/rsloop/_bootstrap.py +0 -0
  67. {rsloop-0.1.51 → rsloop-0.1.53}/python/rsloop/_loop.pyi +0 -0
  68. {rsloop-0.1.51 → rsloop-0.1.53}/python/rsloop/_run.py +0 -0
  69. {rsloop-0.1.51 → rsloop-0.1.53}/python/rsloop/py.typed +0 -0
  70. {rsloop-0.1.51 → rsloop-0.1.53}/rust-toolchain.toml +0 -0
  71. {rsloop-0.1.51 → rsloop-0.1.53}/scripts/build-pgo-wheels.sh +0 -0
  72. {rsloop-0.1.51 → rsloop-0.1.53}/scripts/build-wheels.sh +0 -0
  73. {rsloop-0.1.51 → rsloop-0.1.53}/scripts/generate_test_tls_certs.py +0 -0
  74. {rsloop-0.1.51 → rsloop-0.1.53}/scripts/prepare_anyio_rsloop_tests.py +0 -0
  75. {rsloop-0.1.51 → rsloop-0.1.53}/scripts/python-versions.sh +0 -0
  76. {rsloop-0.1.51 → rsloop-0.1.53}/scripts/run_all_tests.py +0 -0
  77. {rsloop-0.1.51 → rsloop-0.1.53}/scripts/run_python_tests.py +0 -0
  78. {rsloop-0.1.51 → rsloop-0.1.53}/scripts/run_rust_tests.py +0 -0
  79. {rsloop-0.1.51 → rsloop-0.1.53}/scripts/test-supported-pythons.sh +0 -0
  80. {rsloop-0.1.51 → rsloop-0.1.53}/src/async_event.rs +0 -0
  81. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/asyncgens.rs +0 -0
  82. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/asyncio_cache.rs +0 -0
  83. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/connections.rs +0 -0
  84. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/executor.rs +0 -0
  85. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/fast_callbacks.rs +0 -0
  86. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/ffi_helpers.rs +0 -0
  87. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/lifecycle.rs +0 -0
  88. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/methods.rs +0 -0
  89. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/pipes.rs +0 -0
  90. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/pre_exec.rs +0 -0
  91. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/process_handles.rs +0 -0
  92. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/process_spawn.rs +0 -0
  93. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/process_stdio.rs +0 -0
  94. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/servers.rs +0 -0
  95. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/signals.rs +0 -0
  96. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/sock_ops.rs +0 -0
  97. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/socket_connect.rs +0 -0
  98. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/socket_operation.rs +0 -0
  99. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/sockets.rs +0 -0
  100. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/spawn_env.rs +0 -0
  101. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/tasks.rs +0 -0
  102. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/tls_params.rs +0 -0
  103. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api/watchers.rs +0 -0
  104. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/loop_api.rs +0 -0
  105. {rsloop-0.1.51 → rsloop-0.1.53}/src/bindings/mod.rs +0 -0
  106. {rsloop-0.1.51 → rsloop-0.1.53}/src/blocking.rs +0 -0
  107. {rsloop-0.1.51 → rsloop-0.1.53}/src/build_metadata.rs +0 -0
  108. {rsloop-0.1.51 → rsloop-0.1.53}/src/context.rs +0 -0
  109. {rsloop-0.1.51 → rsloop-0.1.53}/src/engine/callbacks.rs +0 -0
  110. {rsloop-0.1.51 → rsloop-0.1.53}/src/engine/mod.rs +0 -0
  111. {rsloop-0.1.51 → rsloop-0.1.53}/src/engine/timer_entry.rs +0 -0
  112. {rsloop-0.1.51 → rsloop-0.1.53}/src/errors.rs +0 -0
  113. {rsloop-0.1.51 → rsloop-0.1.53}/src/lib.rs +0 -0
  114. {rsloop-0.1.51 → rsloop-0.1.53}/src/module_init.rs +0 -0
  115. {rsloop-0.1.51 → rsloop-0.1.53}/src/platform/fd/mod.rs +0 -0
  116. {rsloop-0.1.51 → rsloop-0.1.53}/src/platform/fd/windows.rs +0 -0
  117. {rsloop-0.1.51 → rsloop-0.1.53}/src/platform/mod.rs +0 -0
  118. {rsloop-0.1.51 → rsloop-0.1.53}/src/python_names.rs +0 -0
  119. {rsloop-0.1.51 → rsloop-0.1.53}/src/rust_async.rs +0 -0
  120. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/mod.rs +0 -0
  121. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/process/core_events.rs +0 -0
  122. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/process/core_protocol.rs +0 -0
  123. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/process/core_state.rs +0 -0
  124. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/process/mod.rs +0 -0
  125. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/process/params.rs +0 -0
  126. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/process/py_pipes.rs +0 -0
  127. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/process/py_transport.rs +0 -0
  128. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/process/spawn.rs +0 -0
  129. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/process/worker.rs +0 -0
  130. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/buffers.rs +0 -0
  131. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/builder.rs +0 -0
  132. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/connect.rs +0 -0
  133. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/core_events.rs +0 -0
  134. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/core_protocol.rs +0 -0
  135. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/core_state.rs +0 -0
  136. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/core_write.rs +0 -0
  137. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/fast.rs +0 -0
  138. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/io_targets.rs +0 -0
  139. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/pipe_transport.rs +0 -0
  140. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/platform.rs +0 -0
  141. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/poll.rs +0 -0
  142. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/protocol.rs +0 -0
  143. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/py_transport.rs +0 -0
  144. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/reader.rs +0 -0
  145. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/reader_task.rs +0 -0
  146. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/server_types.rs +0 -0
  147. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/socket_transport.rs +0 -0
  148. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/stats.rs +0 -0
  149. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/tls_session.rs +0 -0
  150. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/tls_transport.rs +0 -0
  151. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/tuning.rs +0 -0
  152. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/worker.rs +0 -0
  153. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/write_queue.rs +0 -0
  154. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/stream/writer.rs +0 -0
  155. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/tls/material.rs +0 -0
  156. {rsloop-0.1.51 → rsloop-0.1.53}/src/transport/tls/mod.rs +0 -0
  157. {rsloop-0.1.51 → rsloop-0.1.53}/src/verification.rs +0 -0
  158. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/UPSTREAM.md +0 -0
  159. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/blocking/default.rs +0 -0
  160. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/blocking/mod.rs +0 -0
  161. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/builder.rs +0 -0
  162. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/driver/iocp.rs +0 -0
  163. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/driver/kqueue.rs +0 -0
  164. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/driver/mio.rs +0 -0
  165. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/driver/mock.rs +0 -0
  166. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/driver/mod.rs +0 -0
  167. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/driver/uring.rs +0 -0
  168. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/executor.rs +0 -0
  169. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/fd_inner.rs +0 -0
  170. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/fs/file.rs +0 -0
  171. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/fs/metadata.rs +0 -0
  172. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/fs/mod.rs +0 -0
  173. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/fs/open_options.rs +0 -0
  174. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/io/buf.rs +0 -0
  175. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/io/mod.rs +0 -0
  176. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/io/pipe.rs +0 -0
  177. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/io/splice.rs +0 -0
  178. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/io/stdio.rs +0 -0
  179. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/io/util.rs +0 -0
  180. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/lib.rs +0 -0
  181. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/net/mod.rs +0 -0
  182. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/net/tcp/listener.rs +0 -0
  183. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/net/tcp/mod.rs +0 -0
  184. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/net/tcp/stream.rs +0 -0
  185. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/net/udp.rs +0 -0
  186. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/net/unix/listener.rs +0 -0
  187. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/net/unix/mod.rs +0 -0
  188. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/net/unix/stream.rs +0 -0
  189. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/accept.rs +0 -0
  190. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/accept_unix.rs +0 -0
  191. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/connect.rs +0 -0
  192. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/fsync.rs +0 -0
  193. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/hard_link.rs +0 -0
  194. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/io_util.rs +0 -0
  195. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/mkdir.rs +0 -0
  196. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/mod.rs +0 -0
  197. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/open.rs +0 -0
  198. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/read.rs +0 -0
  199. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/readat.rs +0 -0
  200. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/readiness.rs +0 -0
  201. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/readv.rs +0 -0
  202. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/recv.rs +0 -0
  203. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/recvfrom.rs +0 -0
  204. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/rename.rs +0 -0
  205. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/send.rs +0 -0
  206. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/sendto.rs +0 -0
  207. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/socket_addr.rs +0 -0
  208. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/splice.rs +0 -0
  209. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/statx.rs +0 -0
  210. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/symlink.rs +0 -0
  211. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/unlink.rs +0 -0
  212. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/waitpid.rs +0 -0
  213. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/write.rs +0 -0
  214. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/writeat.rs +0 -0
  215. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/op/writev.rs +0 -0
  216. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/process/mod.rs +0 -0
  217. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/process/reaper.rs +0 -0
  218. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/signal/mod.rs +0 -0
  219. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/signal/unix.rs +0 -0
  220. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/signal/windows.rs +0 -0
  221. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/task.rs +0 -0
  222. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/test_support.rs +0 -0
  223. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/time/interval.rs +0 -0
  224. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/time/mod.rs +0 -0
  225. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/time/sleep.rs +0 -0
  226. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/time/timeout.rs +0 -0
  227. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/timer.rs +0 -0
  228. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/util/async_wrap.rs +0 -0
  229. {rsloop-0.1.51 → rsloop-0.1.53}/src/vibeio/util/mod.rs +0 -0
  230. {rsloop-0.1.51 → rsloop-0.1.53}/tests/conftest.py +0 -0
  231. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/_smoke.py +0 -0
  232. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/aiohttp_test.py +0 -0
  233. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/anyio_test.py +0 -0
  234. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/beanie_test.py +0 -0
  235. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/daphne_test.py +0 -0
  236. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/django_asgi_test.py +0 -0
  237. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/django_orm_test.py +0 -0
  238. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/edgy_test.py +0 -0
  239. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/falcon_test.py +0 -0
  240. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/fastapi_test.py +0 -0
  241. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/faststream_test.py +0 -0
  242. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/hypercorn_test.py +0 -0
  243. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/litestar_granian_test.py +0 -0
  244. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/litestar_test.py +0 -0
  245. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/mangum_test.py +0 -0
  246. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/ormar_test.py +0 -0
  247. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/piccolo_test.py +0 -0
  248. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/quart_test.py +0 -0
  249. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/sanic_test.py +0 -0
  250. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/sqlalchemy_test.py +0 -0
  251. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/sqlmodel_test.py +0 -0
  252. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/starlette_test.py +0 -0
  253. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/tortoise_orm_test.py +0 -0
  254. {rsloop-0.1.51 → rsloop-0.1.53}/tests/integration/packages/uvicorn_test.py +0 -0
  255. {rsloop-0.1.51 → rsloop-0.1.53}/tests/proptest-regressions/transport/stream/fast.txt +0 -0
  256. {rsloop-0.1.51 → rsloop-0.1.53}/tests/test_buffered_delivery.py +0 -0
  257. {rsloop-0.1.51 → rsloop-0.1.53}/tests/test_compat.py +0 -0
  258. {rsloop-0.1.51 → rsloop-0.1.53}/tests/test_fast_callbacks.py +0 -0
  259. {rsloop-0.1.51 → rsloop-0.1.53}/tests/test_free_threading.py +0 -0
  260. {rsloop-0.1.51 → rsloop-0.1.53}/tests/test_local_sockets.py +0 -0
  261. {rsloop-0.1.51 → rsloop-0.1.53}/tests/test_local_timers.py +0 -0
  262. {rsloop-0.1.51 → rsloop-0.1.53}/tests/test_numeric_addrinfo.py +0 -0
  263. {rsloop-0.1.51 → rsloop-0.1.53}/tests/test_run.py +0 -0
  264. {rsloop-0.1.51 → rsloop-0.1.53}/tests/test_stream_reader.py +0 -0
  265. {rsloop-0.1.51 → rsloop-0.1.53}/tests/test_subprocesses.py +0 -0
  266. {rsloop-0.1.51 → rsloop-0.1.53}/tests/test_tls.py +0 -0
  267. {rsloop-0.1.51 → rsloop-0.1.53}/tests/test_write_reentrancy.py +0 -0
  268. {rsloop-0.1.51 → rsloop-0.1.53}/tests/tooling/test_benchmark_loops.py +0 -0
  269. {rsloop-0.1.51 → rsloop-0.1.53}/tests/tooling/test_granian_benchmark.py +0 -0
  270. {rsloop-0.1.51 → rsloop-0.1.53}/tests/tooling/test_hotpath_lab.py +0 -0
  271. {rsloop-0.1.51 → rsloop-0.1.53}/tests/tooling/test_test_runner.py +0 -0
  272. {rsloop-0.1.51 → rsloop-0.1.53}/tests/typing/public_api.py +0 -0
@@ -41,7 +41,7 @@ jobs:
41
41
  - os_name: windows-arm64
42
42
  runner: windows-11-arm
43
43
  rust_target: aarch64-pc-windows-msvc
44
- python_versions: "3.11 3.12 3.13 3.14"
44
+ python_versions: "3.11 3.12 3.13 3.14 3.15"
45
45
  - os_name: macos-intel
46
46
  runner: macos-15-intel
47
47
  rust_target: x86_64-apple-darwin
@@ -869,7 +869,7 @@ dependencies = [
869
869
 
870
870
  [[package]]
871
871
  name = "rsloop"
872
- version = "0.1.51"
872
+ version = "0.1.53"
873
873
  dependencies = [
874
874
  "async-channel 2.5.0",
875
875
  "async-io",
@@ -1,45 +1,37 @@
1
1
  [package]
2
2
  name = "rsloop"
3
- version = "0.1.51"
3
+ version = "0.1.53"
4
4
  edition = "2024"
5
5
  description = "An event loop for asyncio written in Rust"
6
- license = "Apache-2.0"
6
+ documentation = "https://github.com/RustedBytes/rsloop#readme"
7
7
  readme = "README.md"
8
- repository = "https://github.com/RustedBytes/rsloop"
9
8
  homepage = "https://github.com/RustedBytes/rsloop"
10
- documentation = "https://github.com/RustedBytes/rsloop#readme"
9
+ repository = "https://github.com/RustedBytes/rsloop"
10
+ license = "Apache-2.0"
11
+
12
+ [package.metadata.kani.flags]
13
+ # Force every proof that reaches a loop to state and review its own bound.
14
+ default-unwind = "1"
11
15
 
12
16
  [lib]
13
- name = "rsloop"
14
17
  crate-type = ["cdylib", "rlib"]
15
-
16
- [features]
17
- default = []
18
- # Embedded-runtime modules are opt-in; production wheels retain the default
19
- # networking/timer build unless a feature is explicitly requested.
20
- fs = []
21
- process = ["dep:async-channel"]
22
- signal = ["dep:once_cell", "dep:errno"]
23
- pipe = []
24
- stdio = []
25
- splice = []
26
- blocking-default = ["dep:rusty_pool"]
18
+ name = "rsloop"
27
19
 
28
20
  [dependencies]
29
- errno = { version = "0.3", optional = true }
30
21
  async-channel = { version = "2", optional = true }
31
22
  async-io = "2"
32
23
  async-std = "1"
33
24
  crossbeam-channel = "0.5"
34
25
  crossbeam-queue = "0.3"
26
+ errno = { version = "0.3", optional = true }
35
27
  futures = { version = "0.3", default-features = false, features = ["std"] }
36
28
  futures-util = "0.3"
37
29
  libc = "0.2"
38
30
  memchr = "2"
39
31
  mio = "1"
32
+ once_cell = { version = "1", optional = true }
40
33
  oneshot = { version = "0.2", features = ["async", "std"] }
41
34
  pin-project-lite = "0.2"
42
- once_cell = { version = "1", optional = true }
43
35
  pyo3 = { version = "0.29.2" }
44
36
  pyo3-async-runtimes = { version = "0.29", features = ["async-std-runtime"] }
45
37
  rustls = "0.23"
@@ -50,48 +42,57 @@ signal-hook = "0.4"
50
42
  slab = "0.4"
51
43
  socket2 = "0.6"
52
44
  tokio = { version = "1", default-features = false, features = ["io-util"] }
45
+
46
+ [dev-dependencies]
47
+ proptest = { version = "1", default-features = false, features = ["std"] }
48
+
49
+ [build-dependencies]
50
+ pyo3-build-config = "0.29.2"
51
+
53
52
  [target.'cfg(target_os = "linux")'.dependencies]
54
53
  io-uring = "0.7"
55
54
 
56
- [target.'cfg(unix)'.dependencies]
57
- mio = { version = "1", features = ["os-poll", "os-ext"] }
55
+ [target."cfg(unix)".dependencies]
56
+ mio = { version = "1", features = ["os-ext", "os-poll"] }
58
57
 
59
- [target.'cfg(windows)'.dependencies]
58
+ [target."cfg(windows)".dependencies]
60
59
  windows-sys = { version = "0.61", features = ["Wdk_Foundation", "Wdk_Storage_FileSystem", "Wdk_System_IO", "Wdk_System_SystemServices", "Win32_Foundation", "Win32_Networking_WinSock", "Win32_Security", "Win32_Storage_FileSystem", "Win32_System_Console", "Win32_System_IO", "Win32_System_Pipes", "Win32_System_SystemInformation", "Win32_System_Threading"] }
61
60
 
62
- [build-dependencies]
63
- pyo3-build-config = "0.29.2"
64
-
65
- [dev-dependencies]
66
- proptest = { version = "1", default-features = false, features = ["std"] }
61
+ [features]
62
+ default = []
63
+ blocking-default = ["dep:rusty_pool"]
64
+ # Embedded-runtime modules are opt-in; production wheels retain the default
65
+ # networking/timer build unless a feature is explicitly requested.
66
+ fs = []
67
+ pipe = []
68
+ process = ["dep:async-channel"]
69
+ signal = ["dep:errno", "dep:once_cell"]
70
+ splice = []
71
+ stdio = []
67
72
 
68
73
  [lints.clippy]
74
+ await_holding_lock = "warn"
75
+ await_holding_refcell_ref = "warn"
76
+ cast_ptr_alignment = "warn"
77
+ complexity = { level = "warn", priority = -1 }
69
78
  # Enforce bug, concurrency, and performance checks rather than style preferences.
70
79
  correctness = { level = "deny", priority = -1 }
71
- suspicious = { level = "warn", priority = -1 }
72
- perf = { level = "warn", priority = -1 }
73
- complexity = { level = "warn", priority = -1 }
74
- style = { level = "allow", priority = -1 }
75
- pedantic = { level = "allow", priority = -1 }
76
80
  # Keep safety checks even when they belong to an otherwise disabled group.
77
81
  missing_safety_doc = "warn"
78
- cast_ptr_alignment = "warn"
79
- await_holding_lock = "warn"
80
- await_holding_refcell_ref = "warn"
82
+ pedantic = { level = "allow", priority = -1 }
83
+ perf = { level = "warn", priority = -1 }
84
+ style = { level = "allow", priority = -1 }
85
+ suspicious = { level = "warn", priority = -1 }
81
86
 
82
87
  [lints.rust]
83
88
  unexpected_cfgs = { level = "warn", check-cfg = ["cfg(kani)", "cfg(musl_v1_2_3)", "cfg(syscall_accept4)", "cfg(feature, values(\"blocking-default\", \"fs\", \"pipe\", \"process\", \"signal\", \"splice\", \"stdio\"))"] }
84
89
 
85
- [package.metadata.kani.flags]
86
- # Force every proof that reaches a loop to state and review its own bound.
87
- default-unwind = "1"
90
+ [profile.bench]
91
+ inherits = "release"
88
92
 
89
93
  [profile.release]
90
94
  opt-level = 3
91
95
  lto = "fat"
92
- codegen-units = 1
93
96
  incremental = false
97
+ codegen-units = 1
94
98
  # strip = true
95
-
96
- [profile.bench]
97
- inherits = "release"
rsloop-0.1.53/PKG-INFO ADDED
@@ -0,0 +1,202 @@
1
+ Metadata-Version: 2.4
2
+ Name: rsloop
3
+ Version: 0.1.53
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 :: Microsoft :: Windows
9
+ Classifier: Operating System :: POSIX :: Linux
10
+ Classifier: Programming Language :: Python
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3 :: Only
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Programming Language :: Python :: 3.15
19
+ Classifier: Programming Language :: Python :: Free Threading :: 2 - Beta
20
+ Classifier: Programming Language :: Rust
21
+ Classifier: Topic :: Software Development :: Libraries
22
+ Classifier: Topic :: System :: Networking
23
+ License-File: LICENSE
24
+ Summary: An event loop for asyncio written in Rust
25
+ Keywords: asyncio,event-loop,pyo3,python,rust
26
+ Home-Page: https://github.com/RustedBytes/rsloop
27
+ Author: Yehor Smoliakov <egorsmkv@gmail.com>
28
+ Requires-Python: >=3.10
29
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
30
+ Project-URL: Homepage, https://github.com/RustedBytes/rsloop
31
+ Project-URL: Issues, https://github.com/RustedBytes/rsloop/issues
32
+ Project-URL: Repository, https://github.com/RustedBytes/rsloop
33
+
34
+ <img src="./docs/rsloop.png" alt="rsloop logo" align="center">
35
+
36
+ # An event loop for asyncio written in Rust
37
+
38
+ [![PyPI - Version](https://img.shields.io/pypi/v/rsloop)](https://pypi.org/project/rsloop/)
39
+ [![Tests](https://github.com/RustedBytes/rsloop/actions/workflows/tests.yml/badge.svg)](https://github.com/RustedBytes/rsloop/actions/workflows/tests.yml)
40
+ [![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)
41
+
42
+ `rsloop` is a PyO3-based `asyncio` event loop implemented in Rust.
43
+
44
+ Each `rsloop.Loop` owns a dedicated Rust runtime thread for loop coordination
45
+ and I/O work. That thread runs an rsloop-specialized `vibeio` runtime, using
46
+ io_uring on Linux, IOCP on Windows, and native kqueue readiness on macOS.
47
+ Native-stream TCP reads and Unix-domain socket reads run on that runtime. On Unix, generic
48
+ TCP protocol readers use a second `vibeio` runtime on the Python loop thread
49
+ (io_uring on Linux), avoiding cross-thread delivery of each read. Non-TLS accepts
50
+ run on either runtime depending on where the server starts. Python callbacks,
51
+ tasks, and coroutines run on the thread that calls
52
+ `run_forever()` or `run_until_complete()` (usually the main Python thread).
53
+
54
+ The package exposes:
55
+
56
+ - a native extension module at `rsloop._loop`
57
+ - a Python wrapper in [`python/rsloop/__init__.py`](./python/rsloop/__init__.py)
58
+ - `rsloop.Loop`, `rsloop.EventLoopPolicy`, `rsloop.new_event_loop()`,
59
+ `rsloop.run(...)`, `rsloop.install()`, `rsloop.uninstall()`, and
60
+ `rsloop.build_info()`
61
+
62
+ Repository metadata supports CPython 3.10 through 3.15.
63
+ The native runtime requires Linux 6.1+, macOS 13+, or Windows 10+ so its hot
64
+ paths can rely on modern completion, timer, and scheduler primitives.
65
+ Free-threaded CPython (`3.14t`) is supported: the extension declares
66
+ `gil_used = false`, so importing it no longer re-enables the GIL. See
67
+ [Free-Threaded CPython](./docs/free-threading.md) for what that does and does not
68
+ buy you.
69
+
70
+ ## Documentation
71
+
72
+ Project documentation now lives in [`docs/`](./docs/).
73
+
74
+ If you are new to the repository, start with:
75
+
76
+ - [`docs/index.md`](./docs/index.md)
77
+ - [`docs/getting-started.md`](./docs/getting-started.md)
78
+ - [`docs/supported-features.md`](./docs/supported-features.md)
79
+ - [`docs/fast-streams.md`](./docs/fast-streams.md)
80
+ - [`docs/free-threading.md`](./docs/free-threading.md)
81
+ - [`docs/rust-extensions.md`](./docs/rust-extensions.md)
82
+ - [`docs/how-it-works.md`](./docs/how-it-works.md)
83
+ - [`docs/project-structure.md`](./docs/project-structure.md)
84
+ - [`docs/development.md`](./docs/development.md) for building, testing, and profiling
85
+
86
+ To browse the docs locally with MkDocs:
87
+
88
+ ```bash
89
+ uvx --from mkdocs mkdocs serve
90
+ ```
91
+
92
+ ## Install
93
+
94
+ From PyPI:
95
+
96
+ ```bash
97
+ pip install rsloop
98
+ ```
99
+
100
+ With `uv`:
101
+
102
+ ```bash
103
+ uv add rsloop
104
+ ```
105
+
106
+ From [conda-forge](https://conda-forge.org), using [pixi](https://pixi.prefix.dev/latest/#installation):
107
+
108
+ ```bash
109
+ pixi add rsloop
110
+ ```
111
+
112
+ ## Usage
113
+
114
+ Simple entry point:
115
+
116
+ ```python
117
+ import rsloop
118
+
119
+
120
+ async def main(): ...
121
+
122
+
123
+ rsloop.run(main())
124
+ ```
125
+
126
+ Install as the default asyncio event loop policy:
127
+
128
+ ```python
129
+ import asyncio
130
+ import rsloop
131
+
132
+ rsloop.install()
133
+ try:
134
+ asyncio.run(main())
135
+ finally:
136
+ rsloop.uninstall()
137
+ ```
138
+
139
+ Manual loop creation also works:
140
+
141
+ ```python
142
+ import asyncio
143
+ import rsloop
144
+
145
+ loop = rsloop.new_event_loop()
146
+ asyncio.set_event_loop(loop)
147
+ try:
148
+ loop.run_until_complete(...)
149
+ finally:
150
+ asyncio.set_event_loop(None)
151
+ loop.close()
152
+ ```
153
+
154
+ Importing `rsloop` also patches `asyncio.set_event_loop()` so Python 3.10 can
155
+ accept an `rsloop.Loop` instance, matching the behavior exercised by
156
+ [`tests/test_run.py`](./tests/test_run.py).
157
+
158
+ ## Examples
159
+
160
+ Run the repository examples from the project root:
161
+
162
+ ```bash
163
+ uv run python examples/01_basics.py
164
+ uv run python examples/02_fd_and_sockets.py
165
+ uv run python examples/03_streams.py
166
+ uv run python examples/04_unix_and_accepted_socket.py
167
+ uv run python examples/05_pipes_signals_subprocesses.py
168
+ ```
169
+
170
+ Example files:
171
+ [`examples/01_basics.py`](./examples/01_basics.py),
172
+ [`examples/02_fd_and_sockets.py`](./examples/02_fd_and_sockets.py),
173
+ [`examples/03_streams.py`](./examples/03_streams.py),
174
+ [`examples/04_unix_and_accepted_socket.py`](./examples/04_unix_and_accepted_socket.py),
175
+ [`examples/05_pipes_signals_subprocesses.py`](./examples/05_pipes_signals_subprocesses.py).
176
+
177
+ The repository also includes:
178
+
179
+ - [`examples/fastapi_service.py`](./examples/fastapi_service.py) for running the same
180
+ FastAPI app on stdlib `asyncio`, `uvloop`, or `rsloop`
181
+ - [`examples/granian_service.py`](./examples/granian_service.py) for registering
182
+ `rsloop` as Granian's worker event loop
183
+ - [`benches/compare_event_loops.py`](./benches/compare_event_loops.py)
184
+ for callback, task, and TCP stream comparisons
185
+ - [`benches/compare_granian.py`](./benches/compare_granian.py) for Granian HTTP
186
+ throughput and latency comparisons with `oha`
187
+
188
+ ## Benchmarks
189
+
190
+ See [benchmark results and reproduction commands](./docs/benchmarks.md).
191
+
192
+ ## Acknowledgements
193
+
194
+ `rsloop` builds on the Python `asyncio` model and is implemented with
195
+ [PyO3](https://pyo3.rs/) on the Rust side. Runtime and socket I/O are powered by
196
+ [vibeio](https://crates.io/crates/vibeio).
197
+
198
+ ## License
199
+
200
+ This project is licensed under the Apache License, Version 2.0. See
201
+ [`LICENSE`](./LICENSE) for the full text.
202
+
@@ -0,0 +1,168 @@
1
+ <img src="./docs/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
+ [![Tests](https://github.com/RustedBytes/rsloop/actions/workflows/tests.yml/badge.svg)](https://github.com/RustedBytes/rsloop/actions/workflows/tests.yml)
7
+ [![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)
8
+
9
+ `rsloop` is a PyO3-based `asyncio` event loop implemented in Rust.
10
+
11
+ Each `rsloop.Loop` owns a dedicated Rust runtime thread for loop coordination
12
+ and I/O work. That thread runs an rsloop-specialized `vibeio` runtime, using
13
+ io_uring on Linux, IOCP on Windows, and native kqueue readiness on macOS.
14
+ Native-stream TCP reads and Unix-domain socket reads run on that runtime. On Unix, generic
15
+ TCP protocol readers use a second `vibeio` runtime on the Python loop thread
16
+ (io_uring on Linux), avoiding cross-thread delivery of each read. Non-TLS accepts
17
+ run on either runtime depending on where the server starts. Python callbacks,
18
+ tasks, and coroutines run on the thread that calls
19
+ `run_forever()` or `run_until_complete()` (usually the main Python thread).
20
+
21
+ The package exposes:
22
+
23
+ - a native extension module at `rsloop._loop`
24
+ - a Python wrapper in [`python/rsloop/__init__.py`](./python/rsloop/__init__.py)
25
+ - `rsloop.Loop`, `rsloop.EventLoopPolicy`, `rsloop.new_event_loop()`,
26
+ `rsloop.run(...)`, `rsloop.install()`, `rsloop.uninstall()`, and
27
+ `rsloop.build_info()`
28
+
29
+ Repository metadata supports CPython 3.10 through 3.15.
30
+ The native runtime requires Linux 6.1+, macOS 13+, or Windows 10+ so its hot
31
+ paths can rely on modern completion, timer, and scheduler primitives.
32
+ Free-threaded CPython (`3.14t`) is supported: the extension declares
33
+ `gil_used = false`, so importing it no longer re-enables the GIL. See
34
+ [Free-Threaded CPython](./docs/free-threading.md) for what that does and does not
35
+ buy you.
36
+
37
+ ## Documentation
38
+
39
+ Project documentation now lives in [`docs/`](./docs/).
40
+
41
+ If you are new to the repository, start with:
42
+
43
+ - [`docs/index.md`](./docs/index.md)
44
+ - [`docs/getting-started.md`](./docs/getting-started.md)
45
+ - [`docs/supported-features.md`](./docs/supported-features.md)
46
+ - [`docs/fast-streams.md`](./docs/fast-streams.md)
47
+ - [`docs/free-threading.md`](./docs/free-threading.md)
48
+ - [`docs/rust-extensions.md`](./docs/rust-extensions.md)
49
+ - [`docs/how-it-works.md`](./docs/how-it-works.md)
50
+ - [`docs/project-structure.md`](./docs/project-structure.md)
51
+ - [`docs/development.md`](./docs/development.md) for building, testing, and profiling
52
+
53
+ To browse the docs locally with MkDocs:
54
+
55
+ ```bash
56
+ uvx --from mkdocs mkdocs serve
57
+ ```
58
+
59
+ ## Install
60
+
61
+ From PyPI:
62
+
63
+ ```bash
64
+ pip install rsloop
65
+ ```
66
+
67
+ With `uv`:
68
+
69
+ ```bash
70
+ uv add rsloop
71
+ ```
72
+
73
+ From [conda-forge](https://conda-forge.org), using [pixi](https://pixi.prefix.dev/latest/#installation):
74
+
75
+ ```bash
76
+ pixi add rsloop
77
+ ```
78
+
79
+ ## Usage
80
+
81
+ Simple entry point:
82
+
83
+ ```python
84
+ import rsloop
85
+
86
+
87
+ async def main(): ...
88
+
89
+
90
+ rsloop.run(main())
91
+ ```
92
+
93
+ Install as the default asyncio event loop policy:
94
+
95
+ ```python
96
+ import asyncio
97
+ import rsloop
98
+
99
+ rsloop.install()
100
+ try:
101
+ asyncio.run(main())
102
+ finally:
103
+ rsloop.uninstall()
104
+ ```
105
+
106
+ Manual loop creation also works:
107
+
108
+ ```python
109
+ import asyncio
110
+ import rsloop
111
+
112
+ loop = rsloop.new_event_loop()
113
+ asyncio.set_event_loop(loop)
114
+ try:
115
+ loop.run_until_complete(...)
116
+ finally:
117
+ asyncio.set_event_loop(None)
118
+ loop.close()
119
+ ```
120
+
121
+ Importing `rsloop` also patches `asyncio.set_event_loop()` so Python 3.10 can
122
+ accept an `rsloop.Loop` instance, matching the behavior exercised by
123
+ [`tests/test_run.py`](./tests/test_run.py).
124
+
125
+ ## Examples
126
+
127
+ Run the repository examples from the project root:
128
+
129
+ ```bash
130
+ uv run python examples/01_basics.py
131
+ uv run python examples/02_fd_and_sockets.py
132
+ uv run python examples/03_streams.py
133
+ uv run python examples/04_unix_and_accepted_socket.py
134
+ uv run python examples/05_pipes_signals_subprocesses.py
135
+ ```
136
+
137
+ Example files:
138
+ [`examples/01_basics.py`](./examples/01_basics.py),
139
+ [`examples/02_fd_and_sockets.py`](./examples/02_fd_and_sockets.py),
140
+ [`examples/03_streams.py`](./examples/03_streams.py),
141
+ [`examples/04_unix_and_accepted_socket.py`](./examples/04_unix_and_accepted_socket.py),
142
+ [`examples/05_pipes_signals_subprocesses.py`](./examples/05_pipes_signals_subprocesses.py).
143
+
144
+ The repository also includes:
145
+
146
+ - [`examples/fastapi_service.py`](./examples/fastapi_service.py) for running the same
147
+ FastAPI app on stdlib `asyncio`, `uvloop`, or `rsloop`
148
+ - [`examples/granian_service.py`](./examples/granian_service.py) for registering
149
+ `rsloop` as Granian's worker event loop
150
+ - [`benches/compare_event_loops.py`](./benches/compare_event_loops.py)
151
+ for callback, task, and TCP stream comparisons
152
+ - [`benches/compare_granian.py`](./benches/compare_granian.py) for Granian HTTP
153
+ throughput and latency comparisons with `oha`
154
+
155
+ ## Benchmarks
156
+
157
+ See [benchmark results and reproduction commands](./docs/benchmarks.md).
158
+
159
+ ## Acknowledgements
160
+
161
+ `rsloop` builds on the Python `asyncio` model and is implemented with
162
+ [PyO3](https://pyo3.rs/) on the Rust side. Runtime and socket I/O are powered by
163
+ [vibeio](https://crates.io/crates/vibeio).
164
+
165
+ ## License
166
+
167
+ This project is licensed under the Apache License, Version 2.0. See
168
+ [`LICENSE`](./LICENSE) for the full text.
@@ -533,9 +533,7 @@ def run_child(
533
533
  if not lines:
534
534
  raise RuntimeError(f"{loop_name}/{workload} produced no output")
535
535
  payload = next(
536
- json.loads(line)
537
- for line in reversed(lines)
538
- if line.lstrip().startswith("{")
536
+ json.loads(line) for line in reversed(lines) if line.lstrip().startswith("{")
539
537
  )
540
538
  return ChildResult(
541
539
  loop=payload["loop"],