async-kernel 0.13.3__tar.gz → 0.14.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 (103) hide show
  1. {async_kernel-0.13.3 → async_kernel-0.14.0}/CHANGELOG.md +15 -0
  2. {async_kernel-0.13.3 → async_kernel-0.14.0}/PKG-INFO +30 -14
  3. {async_kernel-0.13.3 → async_kernel-0.14.0}/README.md +29 -13
  4. {async_kernel-0.13.3 → async_kernel-0.14.0}/_version.py +2 -2
  5. async_kernel-0.14.0/docs/reference/event_loop.md +9 -0
  6. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/usage/commands.md +18 -18
  7. {async_kernel-0.13.3 → async_kernel-0.14.0}/pyproject.toml +1 -1
  8. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/caller.py +14 -14
  9. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/event_loop/asyncio_guest.py +1 -1
  10. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/event_loop/qt_host.py +5 -3
  11. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/event_loop/run.py +27 -28
  12. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/event_loop/tk_host.py +14 -11
  13. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/interface/base.py +2 -2
  14. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/interface/zmq.py +6 -6
  15. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/typing.py +7 -22
  16. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/test_caller.py +3 -3
  17. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/test_command.py +8 -8
  18. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/test_event_loop.py +83 -8
  19. {async_kernel-0.13.3 → async_kernel-0.14.0}/uv.lock +25 -2
  20. async_kernel-0.13.3/docs/reference/event_loop.md +0 -1
  21. async_kernel-0.13.3/src/async_kernel/event_loop/asyncio_host.py +0 -41
  22. async_kernel-0.13.3/src/async_kernel/event_loop/trio_host.py +0 -47
  23. {async_kernel-0.13.3 → async_kernel-0.14.0}/.github/dependabot.yaml +0 -0
  24. {async_kernel-0.13.3 → async_kernel-0.14.0}/.github/release.yml +0 -0
  25. {async_kernel-0.13.3 → async_kernel-0.14.0}/.github/workflows/ci.yml +0 -0
  26. {async_kernel-0.13.3 → async_kernel-0.14.0}/.github/workflows/enforce-label.yml +0 -0
  27. {async_kernel-0.13.3 → async_kernel-0.14.0}/.github/workflows/new_release.yml +0 -0
  28. {async_kernel-0.13.3 → async_kernel-0.14.0}/.github/workflows/pre-commit.yml +0 -0
  29. {async_kernel-0.13.3 → async_kernel-0.14.0}/.github/workflows/publish-docs.yml +0 -0
  30. {async_kernel-0.13.3 → async_kernel-0.14.0}/.github/workflows/publish-to-pypi.yml +0 -0
  31. {async_kernel-0.13.3 → async_kernel-0.14.0}/.gitignore +0 -0
  32. {async_kernel-0.13.3 → async_kernel-0.14.0}/.pre-commit-config.yaml +0 -0
  33. {async_kernel-0.13.3 → async_kernel-0.14.0}/.vscode/launch.json +0 -0
  34. {async_kernel-0.13.3 → async_kernel-0.14.0}/.vscode/settings.json +0 -0
  35. {async_kernel-0.13.3 → async_kernel-0.14.0}/.vscode/spellright.dict +0 -0
  36. {async_kernel-0.13.3 → async_kernel-0.14.0}/CONTRIBUTING.md +0 -0
  37. {async_kernel-0.13.3 → async_kernel-0.14.0}/IPYTHON_LICENSE +0 -0
  38. {async_kernel-0.13.3 → async_kernel-0.14.0}/LICENSE +0 -0
  39. {async_kernel-0.13.3 → async_kernel-0.14.0}/cliff.toml +0 -0
  40. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/about/changelog.md +0 -0
  41. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/about/contributing.md +0 -0
  42. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/about/index.md +0 -0
  43. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/about/license.md +0 -0
  44. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/index.md +0 -0
  45. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/javascripts/extra.js +0 -0
  46. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/notebooks/caller.ipynb +0 -0
  47. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/notebooks/concurrency.ipynb +0 -0
  48. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/overrides/main.html +0 -0
  49. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/reference/asyncshell.md +0 -0
  50. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/reference/caller.md +0 -0
  51. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/reference/comm.md +0 -0
  52. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/reference/command.md +0 -0
  53. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/reference/common.md +0 -0
  54. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/reference/debugger.md +0 -0
  55. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/reference/index.md +0 -0
  56. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/reference/interface.md +0 -0
  57. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/reference/kernel.md +0 -0
  58. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/reference/kernelspec.md +0 -0
  59. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/reference/pending.md +0 -0
  60. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/reference/typing.md +0 -0
  61. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/reference/utils.md +0 -0
  62. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/stylesheets/extra.css +0 -0
  63. {async_kernel-0.13.3 → async_kernel-0.14.0}/docs/usage/index.md +0 -0
  64. {async_kernel-0.13.3 → async_kernel-0.14.0}/hatch_build.py +0 -0
  65. {async_kernel-0.13.3 → async_kernel-0.14.0}/mkdocs.yml +0 -0
  66. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/__init__.py +0 -0
  67. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/__main__.py +0 -0
  68. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/asyncshell.py +0 -0
  69. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/comm.py +0 -0
  70. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/command.py +0 -0
  71. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/common.py +0 -0
  72. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/compiler.py +0 -0
  73. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/debugger.py +0 -0
  74. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/event_loop/__init__.py +0 -0
  75. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/interface/__init__.py +0 -0
  76. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/interface/callable.py +0 -0
  77. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/iostream.py +0 -0
  78. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/kernel.py +0 -0
  79. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/kernelspec.py +0 -0
  80. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/pending.py +0 -0
  81. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/py.typed +0 -0
  82. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/resources/logo-32x32.png +0 -0
  83. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/resources/logo-64x64.png +0 -0
  84. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/resources/logo-svg.svg +0 -0
  85. {async_kernel-0.13.3 → async_kernel-0.14.0}/src/async_kernel/utils.py +0 -0
  86. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/__init__.py +0 -0
  87. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/conftest.py +0 -0
  88. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/references.py +0 -0
  89. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/test_callable_kernel_interface.py +0 -0
  90. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/test_comm.py +0 -0
  91. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/test_common.py +0 -0
  92. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/test_debugger.py +0 -0
  93. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/test_enter_kernel.py +0 -0
  94. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/test_iostream.py +0 -0
  95. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/test_kernel.py +0 -0
  96. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/test_kernel_subclass.py +0 -0
  97. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/test_kernelspec.py +0 -0
  98. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/test_message_spec.py +0 -0
  99. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/test_pending.py +0 -0
  100. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/test_typing.py +0 -0
  101. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/test_utils.py +0 -0
  102. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/test_zmq_messaging.py +0 -0
  103. {async_kernel-0.13.3 → async_kernel-0.14.0}/tests/utils.py +0 -0
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.14.0] - 2026-03-24
9
+
10
+ ### <!-- 0 --> 🏗️ Breaking changes
11
+
12
+ - Rename loop to host and Loop to Hosts [#370](https://github.com/fleming79/async-kernel/pull/370)
13
+
14
+ ### <!-- 5 --> 📝 Documentation
15
+
16
+ - Update event loop documentation. [#372](https://github.com/fleming79/async-kernel/pull/372)
17
+
18
+ - Update readme [#371](https://github.com/fleming79/async-kernel/pull/371)
19
+
8
20
  ## [0.13.3] - 2026-03-23
9
21
 
10
22
  ### <!-- 0 --> 🏗️ Breaking changes
@@ -15,6 +27,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
15
27
 
16
28
  ### <!-- 6 --> 🌀 Miscellaneous
17
29
 
30
+ - Prepare for release v0.13.3 [#369](https://github.com/fleming79/async-kernel/pull/369)
31
+
18
32
  - Minor SingleConsumerAsyncQueue optimization. [#368](https://github.com/fleming79/async-kernel/pull/368)
19
33
 
20
34
  - Fixtest_command_start_kernel_enable_matplotlib [#367](https://github.com/fleming79/async-kernel/pull/367)
@@ -1023,6 +1037,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1023
1037
 
1024
1038
  - Bump the actions group across 1 directory with 2 updates [#3](https://github.com/fleming79/async-kernel/pull/3)
1025
1039
 
1040
+ [0.14.0]: https://github.com/fleming79/async-kernel/compare/v0.13.3..v0.14.0
1026
1041
  [0.13.3]: https://github.com/fleming79/async-kernel/compare/v0.13.2..v0.13.3
1027
1042
  [0.13.2]: https://github.com/fleming79/async-kernel/compare/v0.13.1..v0.13.2
1028
1043
  [0.13.1]: https://github.com/fleming79/async-kernel/compare/v0.13.0..v0.13.1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: async-kernel
3
- Version: 0.13.3
3
+ Version: 0.14.0
4
4
  Summary: A concurrent python kernel for Jupyter supporting AnyIO, AsyncIO and Trio.
5
5
  Project-URL: Homepage, https://fleming79.github.io/async-kernel
6
6
  Project-URL: Documentation, https://fleming79.github.io/async-kernel
@@ -71,6 +71,7 @@ The kernel provides two external interfaces:
71
71
  ## Highlights
72
72
 
73
73
  - [IPython shell](https://ipython.readthedocs.io/en/stable/overview.html#enhanced-interactive-python-shell)
74
+ - top-level await ('asyncio' or 'trio' backend) in cells
74
75
  - [anyio](https://pypi.org/project/anyio/) compatible asynchronous backend ([`asyncio`](https://docs.python.org/3/library/asyncio.html) (default) or [`trio`](https://pypi.org/project/trio/))
75
76
  - [aiologic](https://aiologic.readthedocs.io/latest/) thread-safe synchronisation primitives
76
77
  - [Backend agnostic multi-thread / multi-event loop management](https://fleming79.github.io/async-kernel/latest/reference/caller/#async_kernel.caller.Caller)
@@ -85,9 +86,8 @@ The kernel provides two external interfaces:
85
86
  - [Debugger client](https://jupyterlab.readthedocs.io/en/latest/user/debugger.html#debugger)
86
87
 
87
88
  [^1]:
88
- A gui (_host_) enabled kernel runs a gui event loop with the asynchronous backend
89
- running as guest. The host must be set before the kernel is started. This was a
90
- deliberate design choice to to ensure good performance and reliability.
89
+ A gui (_host_) enabled kernel interface starts a gui's mainloop (host) which starts
90
+ the backend as a guest, then finally the Kernel is started.
91
91
 
92
92
  [^2]:
93
93
  The asyncio implementation of `start_guest_run` was written by
@@ -105,24 +105,40 @@ Another problem exists when an asynchronous execute request awaits a result that
105
105
  via a kernel message - this will cause a deadlock because the message will be stuck in the queue behind
106
106
  the _blocking_ execute request[^5].
107
107
 
108
- async-kernel handles messages according to the channel, message type and subshell id. So widget com message
108
+ async-kernel handles messages according to the channel and message type. So widget com message
109
109
  will get processed in a separate queue to an execute request. Further detail is given in the [concurrency notebook](https://fleming79.github.io/async-kernel/latest/notebooks/concurrency/), a Jupyterlite version is available [here](https://fleming79.github.io/echo-kernel/).
110
110
 
111
111
  #### Example
112
112
 
113
- Try the following using a standard kernel and then try it with async-kernel.
113
+ Make a blocking call in a Jupyter lab notebook or console.
114
114
 
115
115
  ```python
116
- # Make the shell thread busy
116
+ # Make the shell's thread busy
117
117
  import time
118
118
 
119
119
  time.sleep(1e6)
120
120
  ```
121
121
 
122
- Try the following in another cell:
122
+ While the above is _blocking_ (the kernel is _busy_).
123
123
 
124
- - code completion (`tab`)
125
- - docstring (`shift tab`)
124
+ ```python
125
+ dir() # try code completion (tab) or view the docstring (shift tab)
126
+ ```
127
+
128
+ Interrupt the kernel.
129
+
130
+ It also works for awaitables.
131
+
132
+ ```python
133
+ import ipywidgets as ipw
134
+ from aiologic import Event
135
+
136
+ b = ipw.Button(description="Click me")
137
+ event = Event()
138
+ b.on_click(lambda _: event.set())
139
+ display(b)
140
+ await event
141
+ ```
126
142
 
127
143
  [^5]:
128
144
  IPyKernel _solves_ this issue specifically for widgets by using the concept of
@@ -165,11 +181,11 @@ The kernel can be started with a gui event loop as the _host_ and the _backend_
165
181
 
166
182
  ```bash
167
183
  # tk
168
- async-kernel -a async-tk --interface.loop=tk
184
+ async-kernel -a async-tk --interface.host=tk
169
185
 
170
186
  # qt
171
187
  pip install PySide6-Essentials
172
- async-kernel -a async-qt --interface.loop=qt
188
+ async-kernel -a async-qt --interface.host=qt
173
189
  ```
174
190
 
175
191
  #### trio backend
@@ -177,11 +193,11 @@ async-kernel -a async-qt --interface.loop=qt
177
193
  ```bash
178
194
  pip install trio
179
195
  # tk
180
- async-kernel -a async-tk --interface.loop=tk --interface.backend=trio
196
+ async-kernel -a async-tk --interface.host=tk --interface.backend=trio
181
197
 
182
198
  # qt
183
199
  pip install PySide6-Essentials
184
- async-kernel -a async-qt --interface.loop=qt --interface.backend=trio
200
+ async-kernel -a async-qt --interface.host=qt --interface.backend=trio
185
201
  ```
186
202
 
187
203
  For further detail about kernel spec customisation see [command line and kernel configuration](https://fleming79.github.io/async-kernel/latest/usage/commands/).
@@ -22,6 +22,7 @@ The kernel provides two external interfaces:
22
22
  ## Highlights
23
23
 
24
24
  - [IPython shell](https://ipython.readthedocs.io/en/stable/overview.html#enhanced-interactive-python-shell)
25
+ - top-level await ('asyncio' or 'trio' backend) in cells
25
26
  - [anyio](https://pypi.org/project/anyio/) compatible asynchronous backend ([`asyncio`](https://docs.python.org/3/library/asyncio.html) (default) or [`trio`](https://pypi.org/project/trio/))
26
27
  - [aiologic](https://aiologic.readthedocs.io/latest/) thread-safe synchronisation primitives
27
28
  - [Backend agnostic multi-thread / multi-event loop management](https://fleming79.github.io/async-kernel/latest/reference/caller/#async_kernel.caller.Caller)
@@ -36,9 +37,8 @@ The kernel provides two external interfaces:
36
37
  - [Debugger client](https://jupyterlab.readthedocs.io/en/latest/user/debugger.html#debugger)
37
38
 
38
39
  [^1]:
39
- A gui (_host_) enabled kernel runs a gui event loop with the asynchronous backend
40
- running as guest. The host must be set before the kernel is started. This was a
41
- deliberate design choice to to ensure good performance and reliability.
40
+ A gui (_host_) enabled kernel interface starts a gui's mainloop (host) which starts
41
+ the backend as a guest, then finally the Kernel is started.
42
42
 
43
43
  [^2]:
44
44
  The asyncio implementation of `start_guest_run` was written by
@@ -56,24 +56,40 @@ Another problem exists when an asynchronous execute request awaits a result that
56
56
  via a kernel message - this will cause a deadlock because the message will be stuck in the queue behind
57
57
  the _blocking_ execute request[^5].
58
58
 
59
- async-kernel handles messages according to the channel, message type and subshell id. So widget com message
59
+ async-kernel handles messages according to the channel and message type. So widget com message
60
60
  will get processed in a separate queue to an execute request. Further detail is given in the [concurrency notebook](https://fleming79.github.io/async-kernel/latest/notebooks/concurrency/), a Jupyterlite version is available [here](https://fleming79.github.io/echo-kernel/).
61
61
 
62
62
  #### Example
63
63
 
64
- Try the following using a standard kernel and then try it with async-kernel.
64
+ Make a blocking call in a Jupyter lab notebook or console.
65
65
 
66
66
  ```python
67
- # Make the shell thread busy
67
+ # Make the shell's thread busy
68
68
  import time
69
69
 
70
70
  time.sleep(1e6)
71
71
  ```
72
72
 
73
- Try the following in another cell:
73
+ While the above is _blocking_ (the kernel is _busy_).
74
74
 
75
- - code completion (`tab`)
76
- - docstring (`shift tab`)
75
+ ```python
76
+ dir() # try code completion (tab) or view the docstring (shift tab)
77
+ ```
78
+
79
+ Interrupt the kernel.
80
+
81
+ It also works for awaitables.
82
+
83
+ ```python
84
+ import ipywidgets as ipw
85
+ from aiologic import Event
86
+
87
+ b = ipw.Button(description="Click me")
88
+ event = Event()
89
+ b.on_click(lambda _: event.set())
90
+ display(b)
91
+ await event
92
+ ```
77
93
 
78
94
  [^5]:
79
95
  IPyKernel _solves_ this issue specifically for widgets by using the concept of
@@ -116,11 +132,11 @@ The kernel can be started with a gui event loop as the _host_ and the _backend_
116
132
 
117
133
  ```bash
118
134
  # tk
119
- async-kernel -a async-tk --interface.loop=tk
135
+ async-kernel -a async-tk --interface.host=tk
120
136
 
121
137
  # qt
122
138
  pip install PySide6-Essentials
123
- async-kernel -a async-qt --interface.loop=qt
139
+ async-kernel -a async-qt --interface.host=qt
124
140
  ```
125
141
 
126
142
  #### trio backend
@@ -128,11 +144,11 @@ async-kernel -a async-qt --interface.loop=qt
128
144
  ```bash
129
145
  pip install trio
130
146
  # tk
131
- async-kernel -a async-tk --interface.loop=tk --interface.backend=trio
147
+ async-kernel -a async-tk --interface.host=tk --interface.backend=trio
132
148
 
133
149
  # qt
134
150
  pip install PySide6-Essentials
135
- async-kernel -a async-qt --interface.loop=qt --interface.backend=trio
151
+ async-kernel -a async-qt --interface.host=qt --interface.backend=trio
136
152
  ```
137
153
 
138
154
  For further detail about kernel spec customisation see [command line and kernel configuration](https://fleming79.github.io/async-kernel/latest/usage/commands/).
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.13.3'
32
- __version_tuple__ = version_tuple = (0, 13, 3)
31
+ __version__ = version = '0.14.0'
32
+ __version_tuple__ = version_tuple = (0, 14, 0)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -0,0 +1,9 @@
1
+ ::: async_kernel.event_loop.run
2
+
3
+ ::: async_kernel.event_loop.tk_host.TkHost
4
+ options:
5
+ show_root_heading: true
6
+
7
+ ::: async_kernel.event_loop.qt_host.QtHost
8
+ options:
9
+ show_root_heading: true
@@ -31,7 +31,7 @@ The kernel spec looks like this:
31
31
  "--start_interface=async_kernel.interface.start_kernel_zmq_interface",
32
32
  "--kernel_name=async",
33
33
  "--backend=trio",
34
- "--loop=tk"
34
+ "--host=tk"
35
35
  ],
36
36
  "env": {},
37
37
  "display_name": "Async python tk trio",
@@ -53,8 +53,8 @@ A single kernel spec is created in the folder `<sys.prefix>/share/jupyter/kernel
53
53
  - display_name: 'async'
54
54
  - backend: `asyncio`
55
55
  - backend_options: `{'use_uvloop':True}` if uvloop or winloop is installed
56
- - loop: `None`
57
- - loop_options: `None`
56
+ - host: `None`
57
+ - host_options: `None`
58
58
 
59
59
  The kernel spec can be updated by adding a kernel spec with the same name ('async').
60
60
 
@@ -63,8 +63,8 @@ The kernel spec can be updated by adding a kernel spec with the same name ('asyn
63
63
  There are two supported backends 'asyncio' and 'trio'.
64
64
 
65
65
  In CPython the [backend][async_kernel.typing.Backend] is started using [anyio.run][].
66
- The type of backend can be specified at the attribute [`interface.backend`][async_kernel.interface.BaseKernelInterface.backend].
67
- The backend_options can be specified at the attribute [`interface.backend_options'][async_kernel.interface.zmq.ZMQKernelInterface.backend_options].
66
+ The type of backend can be specified at the attribute [interface.backend][async_kernel.interface.BaseKernelInterface.backend].
67
+ The backend_options can be specified at the attribute [interface.backend_options][async_kernel.interface.zmq.ZMQKernelInterface.backend_options].
68
68
  Options can be written as a literal python string.
69
69
 
70
70
  ```console
@@ -78,7 +78,7 @@ searches for the kernel specs.
78
78
 
79
79
  The path where the kernel spec is installed/deleted can also be specified by either `prefix` or `folder`.
80
80
 
81
- **options**
81
+ **Options**
82
82
 
83
83
  - prefix (optional): the prefix to use with `PREFIX/share/jupyter/kernels` (defaults is [sys.prefix][]).
84
84
  - folder (optional) the full path to the `kernels` folder.
@@ -110,39 +110,39 @@ Below are some example kernel specs for host and backend kernel specs.
110
110
 
111
111
  ```console
112
112
  # tk host asyncio backend
113
- async-kernel -a async-tk --interface.loop=tk
113
+ async-kernel -a async-tk --interface.host=tk
114
114
 
115
115
  # tk host trio backend
116
- async-kernel -a async-tk --interface.loop=tk --backend=trio
116
+ async-kernel -a async-tk --interface.host=tk --backend=trio
117
117
  ```
118
118
 
119
119
  ### qt
120
120
 
121
121
  ```console
122
122
  # qt host asyncio backend
123
- async-kernel -a async-qt --interface.loop=qt
123
+ async-kernel -a async-qt --interface.host=qt
124
124
 
125
125
  # qt host trio backend
126
- async-kernel -a async-qt-trio --interface.loop=qt --interface.backend=trio
126
+ async-kernel -a async-qt-trio --interface.host=qt --interface.backend=trio
127
127
 
128
- # PySide6 is default. You can specify a different module via `loop_options`
129
- async-kernel -a async-qt --interface.loop=qt --interface.loop_options={'module':'PySide2'}
128
+ # PySide6 is default. You can specify a different module via `host_options`
129
+ async-kernel -a async-qt --interface.host=qt --interface.host_options={'module':'PySide2'}
130
130
  ```
131
131
 
132
- ## Loop options
132
+ ## Host options
133
133
 
134
- Options can be provided to configure how a loop loads. There are only a few options available
134
+ Options can be provided to configure how a host loads. There are only a few options available
135
135
  at present.
136
136
 
137
137
  - `host_class' `[type[Host| str]]` : A customised subclass of a [Host][async_kernel.event_loop.run.Host]
138
138
  or a dotted import path to the customised Host.
139
- - `'module': The module name on which to base the event loop. (Only applies to 'qt').
139
+ - `'module': The module name on which to base the event loop. (Only applies to [qt][async_kernel.event_loop.qt_host.QtHost]).
140
140
 
141
141
  ## Backend options
142
142
 
143
143
  Options can be provided for how the backend is started.
144
144
 
145
- - With a (gui) loop: Options for `start_guest_run`
145
+ - With a (gui) host: Options for `start_guest_run`
146
146
  - [trio.lowlevel.start_guest_run][]
147
147
  - asyncio
148
148
  - host_uses_signal_set_wakeup_fd
@@ -151,11 +151,11 @@ Options can be provided for how the backend is started.
151
151
  - task_factory,
152
152
  - context,
153
153
  - debug,
154
- - Without a (gui) loop: `backend_options` in [anyio.run][]
154
+ - Without a (gui) host: `backend_options` in [anyio.run][]
155
155
 
156
156
  ```console
157
157
  # If uvloop is installed it will be used by default. You can do this to disable it.
158
- async-kernel -a async "--interface.loop_options={'use_uvloop':False}"
158
+ async-kernel -a async "--interface.host_options={'use_uvloop':False}"
159
159
  ```
160
160
 
161
161
  ### Custom arguments
@@ -95,8 +95,8 @@ dev = [
95
95
  {include-group = "test"},
96
96
  ]
97
97
  gui = [
98
- "matplotlib>=3.10.8",
99
98
  "pyside6-essentials>=6.10.2",
99
+ {include-group = "docs"},
100
100
  ]
101
101
 
102
102
  [tool.hatch.version]
@@ -30,7 +30,7 @@ from async_kernel import utils
30
30
  from async_kernel.common import Fixed
31
31
  from async_kernel.event_loop.run import Host, get_start_guest_run
32
32
  from async_kernel.pending import Pending, PendingCancelled, PendingGroup, PendingManager, PendingTracker
33
- from async_kernel.typing import Backend, CallerCreateOptions, CallerState, Loop, NoValue, RunSettings, T
33
+ from async_kernel.typing import Backend, CallerCreateOptions, CallerState, Hosts, NoValue, RunSettings, T
34
34
 
35
35
  with contextlib.suppress(ImportError):
36
36
  # Monkey patch sniffio.current_async_library` with aiologic's version which does a better job.
@@ -211,8 +211,8 @@ class Caller(anyio.AsyncContextManagerMixin):
211
211
  _idle_time: float = 0.0
212
212
  _backend: Backend
213
213
  _backend_options: dict[str, Any] | None
214
- _loop: Loop | None
215
- _loop_options: dict[str, Any] | None
214
+ _host: Hosts | None
215
+ _host_options: dict[str, Any] | None
216
216
  _protected = False
217
217
  _use_safe_checkpoint = False
218
218
  _state: CallerState = CallerState.initial
@@ -270,14 +270,14 @@ class Caller(anyio.AsyncContextManagerMixin):
270
270
  return self._backend_options
271
271
 
272
272
  @property
273
- def loop(self) -> Loop | None:
273
+ def host(self) -> Hosts | None:
274
274
  "The gui event loop if there is one."
275
- return self._loop
275
+ return self._host
276
276
 
277
277
  @property
278
- def loop_options(self) -> dict | None:
278
+ def host_options(self) -> dict | None:
279
279
  "Options used to create the gui event loop."
280
- return self._loop_options
280
+ return self._host_options
281
281
 
282
282
  @property
283
283
  def protected(self) -> bool:
@@ -320,7 +320,7 @@ class Caller(anyio.AsyncContextManagerMixin):
320
320
  return {
321
321
  "name": self._name,
322
322
  "backend": str(self._backend),
323
- "loop": self._loop,
323
+ "host": self._host,
324
324
  "thread": self._thread.name,
325
325
  "id": self._caller_id,
326
326
  }
@@ -393,9 +393,9 @@ class Caller(anyio.AsyncContextManagerMixin):
393
393
  inst = super().__new__(cls)
394
394
  inst._name = name
395
395
  inst._backend = Backend(backend or current_async_library())
396
- inst._loop = Loop(loop) if (loop := kwargs.get("loop")) else None
396
+ inst._host = Hosts(loop) if (loop := kwargs.get("host")) else None
397
397
  inst._backend_options = kwargs.get("backend_options")
398
- inst._loop_options = kwargs.get("loop_options")
398
+ inst._host_options = kwargs.get("host_options")
399
399
  inst._protected = kwargs.get("protected", False)
400
400
  inst._zmq_context = kwargs.get("zmq_context")
401
401
  inst.log = kwargs.get("log") or logging.LoggerAdapter(logging.getLogger())
@@ -454,9 +454,9 @@ class Caller(anyio.AsyncContextManagerMixin):
454
454
  name = self.name or "async_kernel_caller"
455
455
  settings = RunSettings(
456
456
  backend=self.backend,
457
- loop=self.loop,
457
+ host=self.host,
458
458
  backend_options=self.backend_options,
459
- loop_options=self.loop_options,
459
+ host_options=self.host_options,
460
460
  )
461
461
  args = [run_caller_in_context, (), settings]
462
462
  self._thread = threading.Thread(target=async_kernel.event_loop.run, args=args, name=name, daemon=True)
@@ -713,8 +713,8 @@ class Caller(anyio.AsyncContextManagerMixin):
713
713
  if (backend := kwargs.get("backend")) and caller.backend != backend:
714
714
  msg = f"Backend mismatch! {backend=} {caller.backend=}"
715
715
  raise RuntimeError(msg)
716
- if (loop := kwargs.get("loop")) and caller.loop != loop:
717
- msg = f"Event loop mismatch! {loop=} {caller.loop=}"
716
+ if (host := kwargs.get("host")) and caller.host != host:
717
+ msg = f"Host mismatch! {host=} {caller.host=}"
718
718
  raise RuntimeError(msg)
719
719
  return caller
720
720
  if "backend" not in kwargs:
@@ -27,7 +27,7 @@ _MAXIMUM_SELECT_TIMEOUT = 24 * 60 * 60
27
27
  _THREAD_JOIN_TIMEOUT = 5 * 60
28
28
 
29
29
  GuestInfo = namedtuple("GuestInfo", [
30
- "loop",
30
+ "host",
31
31
  "task",
32
32
  ])
33
33
 
@@ -24,7 +24,7 @@ from typing import TYPE_CHECKING, Any, Literal
24
24
  from aiologic.meta import import_from
25
25
  from typing_extensions import override
26
26
 
27
- from async_kernel.typing import Loop, T
27
+ from async_kernel.typing import Hosts, T
28
28
 
29
29
  from .run import Host
30
30
 
@@ -33,12 +33,14 @@ if TYPE_CHECKING:
33
33
 
34
34
  from PySide6 import QtCore, QtWidgets # noqa: TC004
35
35
 
36
+ __all__ = ["QtHost"]
37
+
36
38
 
37
39
  class QtHost(Host[T]):
38
- LOOP = Loop.qt
40
+ HOST = Hosts.qt
39
41
  MATPLOTLIB_GUIS = ("qt",)
40
42
 
41
- def __init__(self, module: str = "PySide6") -> None:
43
+ def __init__(self, module: Literal["PySide6", "PySide2", "PyQt5", "PyQt6"] = "PySide6") -> None:
42
44
  if threading.current_thread() is not threading.main_thread():
43
45
  msg = "QT can only be run in main thread!"
44
46
  raise RuntimeError(msg)
@@ -8,7 +8,7 @@ import anyio
8
8
  from wrapt import lazy_import
9
9
 
10
10
  from async_kernel.common import import_item
11
- from async_kernel.typing import Backend, Loop, RunSettings, T
11
+ from async_kernel.typing import Backend, Hosts, RunSettings, T
12
12
 
13
13
  if TYPE_CHECKING:
14
14
  from collections.abc import Callable
@@ -39,13 +39,13 @@ def get_start_guest_run(backend: Backend):
39
39
  def run(func: Callable[..., CoroutineType[Any, Any, T]], args: tuple, settings: RunSettings, /) -> T:
40
40
  """
41
41
  Run `func` to completion asynchronously in the current thread using a [backend][async_kernel.typing.Backend]
42
- with an optional gui event loop (_host_).
42
+ with an optional host (gui event loop).
43
43
 
44
44
  The default backend is ['asyncio'][async_kernel.typing.Backend.asyncio].
45
45
 
46
- If [loop][async_kernel.typing.Loop] is specified in `settings`. A _host_ (gui) mainloop
46
+ If [host][async_kernel.typing.Hosts] is specified in `settings`. A _host_ (gui) mainloop
47
47
  will be started with the `backend` running as a guest (in the same thread). The `backend`
48
- will execute `func` asynchronously to completion. Once completed the backend and host
48
+ will execute `func` asynchronously to completion. Once completed the `backend` and `host`
49
49
  are stopped and finally the result is returned.
50
50
 
51
51
  Args:
@@ -53,13 +53,12 @@ def run(func: Callable[..., CoroutineType[Any, Any, T]], args: tuple, settings:
53
53
  args: Args to use when calling func.
54
54
  settings: Settings to use when running func.
55
55
 
56
- Custom loop:
57
- A custom event loop can be used by subclassing [Host][].
58
- The host can be specified in the settings as the option 'host_class'. The value
59
- can be the class or a dotted path if it is importable.
56
+ Custom host:
57
+ A custom host can be started by subclassing [Host][] and passed as the 'host_class' as the
58
+ class or a dotted path if it is importable.
60
59
  """
61
- if settings.get("loop"):
62
- # A loop with the backend running as a guest.
60
+ if settings.get("host"):
61
+ # A gui with the backend running as a guest.
63
62
  return Host.run(func, args, settings)
64
63
  # backend only.
65
64
  return anyio.run(
@@ -79,12 +78,12 @@ def get_runtime_matplotlib_guis(thread: threading.Thread | None = None) -> tuple
79
78
 
80
79
  class Host(Generic[T]):
81
80
  """
82
- A class that provides the necessary callbacks for `start_guest_run`.
81
+ A class that provides the necessary callbacks to run a gui event loop with a `backend` started using `start_guest_run`.
83
82
  """
84
83
 
85
- LOOP: Loop
84
+ HOST: Hosts
86
85
  MATPLOTLIB_GUIS = ()
87
- _subclasses: dict[Loop, type[Self]] = {}
86
+ _subclasses: dict[Hosts, type[Self]] = {}
88
87
  _instances: dict[threading.Thread, Host] = {}
89
88
 
90
89
  _outcome: Outcome[T] | None = None
@@ -92,8 +91,8 @@ class Host(Generic[T]):
92
91
  "A callback to start the guest. This must be called by a subclass."
93
92
 
94
93
  def __init_subclass__(cls) -> None:
95
- if cls.LOOP is not Loop.custom:
96
- cls._subclasses[cls.LOOP] = cls
94
+ if cls.HOST is not Hosts.custom:
95
+ cls._subclasses[cls.HOST] = cls
97
96
 
98
97
  @classmethod
99
98
  def current(cls, thread: threading.Thread | None = None) -> Host | None:
@@ -109,28 +108,28 @@ class Host(Generic[T]):
109
108
  msg = "A host is already running in this thread"
110
109
  raise RuntimeError(msg)
111
110
 
112
- loop = Loop(settings.get("loop"))
111
+ host = Hosts(settings.get("host"))
113
112
  backend = Backend(settings.get("backend", "asyncio"))
114
113
  backend_options = settings.get("backend_options") or {}
115
- loop_options = settings.get("loop_options") or {}
114
+ host_options = settings.get("host_options") or {}
116
115
 
117
- if "host_class" in loop_options:
118
- loop_options = loop_options.copy()
119
- cls_ = loop_options.pop("host_class")
116
+ if "host_class" in host_options:
117
+ host_options = host_options.copy()
118
+ cls_ = host_options.pop("host_class")
120
119
  if isinstance(cls_, str):
121
120
  cls_ = import_item(cls_)
122
121
  if not issubclass(cls_, cls):
123
122
  msg = f"{cls_} is not a subclass of {cls}!"
124
123
  raise TypeError(msg)
125
124
  else:
126
- assert loop != backend
127
- if loop not in cls._subclasses:
128
- import_module(f"async_kernel.event_loop.{loop}_host")
129
- assert loop in cls._subclasses, f"Host for {loop=} is not implemented correctly!"
130
- cls_ = cls._subclasses[loop]
131
- assert cls_.LOOP is loop
132
-
133
- host = cls_(**loop_options)
125
+ assert host != backend
126
+ if host not in cls._subclasses:
127
+ import_module(f"async_kernel.event_loop.{host}_host")
128
+ assert host in cls._subclasses, f"Host for {host=} is not implemented correctly!"
129
+ cls_ = cls._subclasses[host]
130
+ assert cls_.HOST is host
131
+
132
+ host = cls_(**host_options)
134
133
  # set the `start_guest` function (runs once).
135
134
  backend_options.setdefault("host_uses_signal_set_wakeup_fd", host.host_uses_signal_set_wakeup_fd)
136
135
  start_guest_run = get_start_guest_run(backend)