async-kernel 0.17.0__tar.gz → 0.17.1__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.
- {async_kernel-0.17.0 → async_kernel-0.17.1}/.github/workflows/ci.yml +2 -2
- {async_kernel-0.17.0 → async_kernel-0.17.1}/.github/workflows/publish-docs.yml +1 -1
- {async_kernel-0.17.0 → async_kernel-0.17.1}/.pre-commit-config.yaml +4 -4
- {async_kernel-0.17.0 → async_kernel-0.17.1}/CHANGELOG.md +24 -1
- {async_kernel-0.17.0 → async_kernel-0.17.1}/CONTRIBUTING.md +4 -8
- {async_kernel-0.17.0 → async_kernel-0.17.1}/PKG-INFO +1 -1
- {async_kernel-0.17.0 → async_kernel-0.17.1}/_version.py +2 -2
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/notebooks/caller.ipynb +1 -1
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/notebooks/concurrency.ipynb +157 -7
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/asyncshell.py +59 -23
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/caller.py +1 -2
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/interface/base.py +150 -159
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/interface/callable.py +2 -2
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/interface/zmq.py +2 -2
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/typing.py +42 -24
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/test_kernel.py +35 -32
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/test_typing.py +3 -3
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/test_utils.py +3 -1
- {async_kernel-0.17.0 → async_kernel-0.17.1}/uv.lock +75 -80
- {async_kernel-0.17.0 → async_kernel-0.17.1}/.github/dependabot.yaml +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/.github/release.yml +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/.github/workflows/enforce-label.yml +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/.github/workflows/new_release.yml +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/.github/workflows/pre-commit.yml +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/.github/workflows/publish-to-pypi.yml +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/.gitignore +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/.vscode/launch.json +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/.vscode/settings.json +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/.vscode/spellright.dict +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/IPYTHON_LICENSE +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/LICENSE +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/README.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/cliff.toml +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/about/changelog.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/about/contributing.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/about/index.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/about/license.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/index.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/javascripts/extra.js +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/notebooks/custom_kernel.ipynb +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/overrides/main.html +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/reference/asyncshell.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/reference/caller.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/reference/comm.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/reference/command.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/reference/common.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/reference/debugger.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/reference/event_loop.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/reference/index.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/reference/interface.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/reference/kernel.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/reference/kernelspec.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/reference/pending.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/reference/typing.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/reference/utils.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/stylesheets/extra.css +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/thread_safety.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/usage/commands.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/docs/usage/index.md +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/hatch_build.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/mkdocs.yml +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/pyproject.toml +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/__init__.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/__main__.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/comm.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/command.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/common.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/compat/json.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/compiler.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/debugger.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/event_loop/__init__.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/event_loop/asyncio_guest.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/event_loop/qt_host.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/event_loop/run.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/event_loop/tk_host.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/interface/__init__.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/iostream.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/kernel.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/kernelspec.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/pending.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/py.typed +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/resources/logo-32x32.png +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/resources/logo-64x64.png +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/resources/logo-svg.svg +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/src/async_kernel/utils.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/__init__.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/conftest.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/references.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/test_callable_kernel_interface.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/test_caller.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/test_comm.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/test_command.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/test_common.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/test_compat.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/test_debugger.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/test_enter_kernel.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/test_event_loop.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/test_iostream.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/test_kernel_subclass.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/test_kernelspec.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/test_message_spec.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/test_pending.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/test_zmq_messaging.py +0 -0
- {async_kernel-0.17.0 → async_kernel-0.17.1}/tests/utils.py +0 -0
|
@@ -25,7 +25,7 @@ jobs:
|
|
|
25
25
|
- name: Type checking with basedpyright
|
|
26
26
|
run: |
|
|
27
27
|
uv sync
|
|
28
|
-
uvx basedpyright@1.39.
|
|
28
|
+
uvx basedpyright@1.39.3
|
|
29
29
|
|
|
30
30
|
test:
|
|
31
31
|
needs: type-checking
|
|
@@ -110,5 +110,5 @@ jobs:
|
|
|
110
110
|
timeout-minutes: 5
|
|
111
111
|
run: |
|
|
112
112
|
uv sync --group docs
|
|
113
|
-
uv run async-kernel -a async-docs --shell.timeout=
|
|
113
|
+
uv run async-kernel -a async-docs --shell.timeout=1
|
|
114
114
|
uv run mkdocs build -s
|
|
@@ -40,7 +40,7 @@ jobs:
|
|
|
40
40
|
- name: Install the project
|
|
41
41
|
run: |
|
|
42
42
|
uv sync --group docs
|
|
43
|
-
uv run async-kernel -a async-docs --shell.timeout=
|
|
43
|
+
uv run async-kernel -a async-docs --shell.timeout=1 # The 'async-docs' kernel is specified as the kernel for mkdocs-jupyter
|
|
44
44
|
|
|
45
45
|
- name: Version info
|
|
46
46
|
id: version
|
|
@@ -28,12 +28,12 @@ repos:
|
|
|
28
28
|
- id: check-json5
|
|
29
29
|
|
|
30
30
|
- repo: https://github.com/python-jsonschema/check-jsonschema
|
|
31
|
-
rev: 0.37.
|
|
31
|
+
rev: 0.37.1
|
|
32
32
|
hooks:
|
|
33
33
|
- id: check-github-workflows
|
|
34
34
|
|
|
35
35
|
- repo: https://github.com/rbubley/mirrors-prettier
|
|
36
|
-
rev: v3.8.
|
|
36
|
+
rev: v3.8.3
|
|
37
37
|
hooks:
|
|
38
38
|
- id: prettier
|
|
39
39
|
types_or: [yaml, html, json]
|
|
@@ -59,7 +59,7 @@ repos:
|
|
|
59
59
|
- id: python-use-type-annotations
|
|
60
60
|
|
|
61
61
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
62
|
-
rev: v0.15.
|
|
62
|
+
rev: v0.15.11
|
|
63
63
|
hooks:
|
|
64
64
|
- id: ruff-check
|
|
65
65
|
types_or: [python, jupyter]
|
|
@@ -68,7 +68,7 @@ repos:
|
|
|
68
68
|
types_or: [python, jupyter]
|
|
69
69
|
|
|
70
70
|
- repo: https://github.com/scientific-python/cookie
|
|
71
|
-
rev: 2026.
|
|
71
|
+
rev: 2026.04.04
|
|
72
72
|
hooks:
|
|
73
73
|
- id: sp-repo-review
|
|
74
74
|
additional_dependencies: ["repo-review[cli]"]
|
|
@@ -5,7 +5,25 @@ 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.17.
|
|
8
|
+
## [0.17.1] - 2026-04-23
|
|
9
|
+
|
|
10
|
+
### <!-- 0 --> 🏗️ Breaking changes
|
|
11
|
+
|
|
12
|
+
- Drop the tag 'suppress_error'. [#436](https://github.com/fleming79/async-kernel/pull/436)
|
|
13
|
+
|
|
14
|
+
- BaseKernelInterface refactoring [#434](https://github.com/fleming79/async-kernel/pull/434)
|
|
15
|
+
|
|
16
|
+
### <!-- 1 --> 🚀 Features
|
|
17
|
+
|
|
18
|
+
- Add asyncio and trio cell and line magic [#437](https://github.com/fleming79/async-kernel/pull/437)
|
|
19
|
+
|
|
20
|
+
- Support specifing the thread with cell magic and passing thread options [#435](https://github.com/fleming79/async-kernel/pull/435)
|
|
21
|
+
|
|
22
|
+
### <!-- 6 --> 🌀 Miscellaneous
|
|
23
|
+
|
|
24
|
+
- Update pre-commit, uv.lock and basedpyright [#438](https://github.com/fleming79/async-kernel/pull/438)
|
|
25
|
+
|
|
26
|
+
## [0.17.0] - 2026-04-22
|
|
9
27
|
|
|
10
28
|
### <!-- 0 --> 🏗️ Breaking changes
|
|
11
29
|
|
|
@@ -15,6 +33,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
15
33
|
|
|
16
34
|
- Make AsyncInteractiveShell and AsyncInteractiveSubshell easier to subclass. [#430](https://github.com/fleming79/async-kernel/pull/430)
|
|
17
35
|
|
|
36
|
+
### <!-- 6 --> 🌀 Miscellaneous
|
|
37
|
+
|
|
38
|
+
- Prepare for release v0.17.0 [#433](https://github.com/fleming79/async-kernel/pull/433)
|
|
39
|
+
|
|
18
40
|
## [0.16.4] - 2026-04-15
|
|
19
41
|
|
|
20
42
|
### <!-- 2 --> 🐛 Fixes
|
|
@@ -1197,6 +1219,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
1197
1219
|
|
|
1198
1220
|
- Bump the actions group across 1 directory with 2 updates [#3](https://github.com/fleming79/async-kernel/pull/3)
|
|
1199
1221
|
|
|
1222
|
+
[0.17.1]: https://github.com/fleming79/async-kernel/compare/v0.17.0..v0.17.1
|
|
1200
1223
|
[0.17.0]: https://github.com/fleming79/async-kernel/compare/v0.16.4..v0.17.0
|
|
1201
1224
|
[0.16.4]: https://github.com/fleming79/async-kernel/compare/v0.16.3..v0.16.4
|
|
1202
1225
|
[0.16.3]: https://github.com/fleming79/async-kernel/compare/v0.16.2..v0.16.3
|
|
@@ -25,7 +25,7 @@ Additional steps to build documentation (optional):
|
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
27
|
uv sync --group docs
|
|
28
|
-
uv run async-kernel -a async-docs --main_shell.timeout=
|
|
28
|
+
uv run async-kernel -a async-docs --main_shell.timeout=1
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
### Running tests
|
|
@@ -100,7 +100,7 @@ The 'docs' group specified extra packages are required to build documentation.
|
|
|
100
100
|
|
|
101
101
|
```bash
|
|
102
102
|
uv sync --group docs
|
|
103
|
-
uv run async-kernel -a async-docs --main_shell.timeout=
|
|
103
|
+
uv run async-kernel -a async-docs --main_shell.timeout=1
|
|
104
104
|
```
|
|
105
105
|
|
|
106
106
|
#### Test the docs
|
|
@@ -114,7 +114,7 @@ uv run mkdocs build -s
|
|
|
114
114
|
The command:
|
|
115
115
|
|
|
116
116
|
```bash
|
|
117
|
-
uv run async-kernel -a async-docs --main_shell.timeout=
|
|
117
|
+
uv run async-kernel -a async-docs --main_shell.timeout=1
|
|
118
118
|
```
|
|
119
119
|
|
|
120
120
|
Defines a new kernel spec with the name "async-docs" that sets the `shell.timeout` to 100ms.
|
|
@@ -145,13 +145,9 @@ Notebooks are included in the documentation by the plugin [mkdocs-jupyter](https
|
|
|
145
145
|
|
|
146
146
|
!!! info
|
|
147
147
|
|
|
148
|
-
We use the kernel spec named 'async-docs' which has a cell execute timeout of
|
|
148
|
+
We use the kernel spec named 'async-docs' which has a cell execute timeout of 1s. This is used
|
|
149
149
|
to advance execution through long running cells.
|
|
150
150
|
|
|
151
|
-
The [suppress-error][async_kernel.typing.Tags.suppress_error] tag is inserted in code cells to enable
|
|
152
|
-
with generating documentation. The symbol '⚠' is an indicator that the error was suppressed. Normally
|
|
153
|
-
this is due to the timeout but there is no distinction on the type of error.
|
|
154
|
-
|
|
155
151
|
#### Useful links
|
|
156
152
|
|
|
157
153
|
These links are not relevant for docstrings.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: async-kernel
|
|
3
|
-
Version: 0.17.
|
|
3
|
+
Version: 0.17.1
|
|
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
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.17.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 17,
|
|
21
|
+
__version__ = version = '0.17.1'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 17, 1)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -233,7 +233,7 @@
|
|
|
233
233
|
"source": [
|
|
234
234
|
"## Caller methods that return Pending\n",
|
|
235
235
|
"\n",
|
|
236
|
-
"Pending is
|
|
236
|
+
"Pending is a thread-safe representation of a future result. It was designed to provide thread-safe functionality similar [asyncio.Future](https://docs.python.org/3/library/asyncio-future.html#asyncio.Future) and was named `Pending` to avoid confusion about differences in functionality to that of `asyncio.Future` and `concurrent.futures.Future`.\n",
|
|
237
237
|
"\n",
|
|
238
238
|
"The following functions return a `Pending` object:\n",
|
|
239
239
|
"\n",
|
|
@@ -187,10 +187,7 @@
|
|
|
187
187
|
"editable": true,
|
|
188
188
|
"slideshow": {
|
|
189
189
|
"slide_type": ""
|
|
190
|
-
}
|
|
191
|
-
"tags": [
|
|
192
|
-
"suppress-error"
|
|
193
|
-
]
|
|
190
|
+
}
|
|
194
191
|
},
|
|
195
192
|
"outputs": [],
|
|
196
193
|
"source": [
|
|
@@ -223,13 +220,12 @@
|
|
|
223
220
|
"slide_type": ""
|
|
224
221
|
},
|
|
225
222
|
"tags": [
|
|
226
|
-
"thread"
|
|
227
|
-
"suppress-error"
|
|
223
|
+
"thread"
|
|
228
224
|
]
|
|
229
225
|
},
|
|
230
226
|
"outputs": [],
|
|
231
227
|
"source": [
|
|
232
|
-
"# This time we'll use the tag to run the cell in a
|
|
228
|
+
"# This time we'll use the tag to run the cell in a worker thread\n",
|
|
233
229
|
"await demo()"
|
|
234
230
|
]
|
|
235
231
|
},
|
|
@@ -249,6 +245,160 @@
|
|
|
249
245
|
"# thread\n",
|
|
250
246
|
"%callers # magic provided by async-kernel"
|
|
251
247
|
]
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
"cell_type": "markdown",
|
|
251
|
+
"id": "11",
|
|
252
|
+
"metadata": {},
|
|
253
|
+
"source": [
|
|
254
|
+
"We can also specify CallerCreateOptions as part of the top line"
|
|
255
|
+
]
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"cell_type": "code",
|
|
259
|
+
"execution_count": null,
|
|
260
|
+
"id": "12",
|
|
261
|
+
"metadata": {},
|
|
262
|
+
"outputs": [],
|
|
263
|
+
"source": [
|
|
264
|
+
"# thread name=\"My thread\"\n",
|
|
265
|
+
"%callers"
|
|
266
|
+
]
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
"cell_type": "markdown",
|
|
270
|
+
"id": "13",
|
|
271
|
+
"metadata": {},
|
|
272
|
+
"source": [
|
|
273
|
+
"## Asynchronous magic\n",
|
|
274
|
+
"\n",
|
|
275
|
+
"Asynchronous line (%) and cell (%%) magic functions are supported. Any line or cell magic that returns an awaitable is awaited before proceeding.\n",
|
|
276
|
+
"\n",
|
|
277
|
+
"- **[thread magic](#thread-magic)**\n",
|
|
278
|
+
"- **[asyncio magic](#specify-the-backend)**\n",
|
|
279
|
+
"- **[trio magic](#specify-the-backend)**\n",
|
|
280
|
+
"\n",
|
|
281
|
+
"### thread magic\n",
|
|
282
|
+
"\n",
|
|
283
|
+
"This will run the code in a thread. When no settings are provided a cell worker thread is used.\n",
|
|
284
|
+
"\n",
|
|
285
|
+
"#### Comparing thread magic with thread run mode\n",
|
|
286
|
+
"\n",
|
|
287
|
+
"- thread magic (`%%thread`) is an asynchronous magic that executes the associated **code** in a separate thread. \n",
|
|
288
|
+
"- [thread run mode](#run-mode-thread) (`# thread`) instructs the kernel to run the **entire cell** in a separate thread, bypassing the shell execute request queue."
|
|
289
|
+
]
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
"cell_type": "code",
|
|
293
|
+
"execution_count": null,
|
|
294
|
+
"id": "14",
|
|
295
|
+
"metadata": {},
|
|
296
|
+
"outputs": [],
|
|
297
|
+
"source": [
|
|
298
|
+
"# Run the magic 'callers' in a caller worker thread.\n",
|
|
299
|
+
"%thread %callers "
|
|
300
|
+
]
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
"cell_type": "markdown",
|
|
304
|
+
"id": "15",
|
|
305
|
+
"metadata": {},
|
|
306
|
+
"source": [
|
|
307
|
+
"To specify a thread (caller) by name"
|
|
308
|
+
]
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
"cell_type": "code",
|
|
312
|
+
"execution_count": null,
|
|
313
|
+
"id": "16",
|
|
314
|
+
"metadata": {},
|
|
315
|
+
"outputs": [],
|
|
316
|
+
"source": [
|
|
317
|
+
"%%thread name=\"My executor\" \n",
|
|
318
|
+
"%callers"
|
|
319
|
+
]
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
"cell_type": "markdown",
|
|
323
|
+
"id": "17",
|
|
324
|
+
"metadata": {},
|
|
325
|
+
"source": [
|
|
326
|
+
"Many of arguments accepted on `Caller.get` are also supported. Let's use a thread with a trio backend."
|
|
327
|
+
]
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
"cell_type": "code",
|
|
331
|
+
"execution_count": null,
|
|
332
|
+
"id": "18",
|
|
333
|
+
"metadata": {},
|
|
334
|
+
"outputs": [],
|
|
335
|
+
"source": [
|
|
336
|
+
"%%thread name=\"My trio executor\" backend=trio\n",
|
|
337
|
+
"%callers\n",
|
|
338
|
+
"\n",
|
|
339
|
+
"import trio\n",
|
|
340
|
+
"\n",
|
|
341
|
+
"await trio.sleep(0)"
|
|
342
|
+
]
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
"cell_type": "markdown",
|
|
346
|
+
"id": "19",
|
|
347
|
+
"metadata": {},
|
|
348
|
+
"source": [
|
|
349
|
+
"## Specify the backend\n",
|
|
350
|
+
"\n",
|
|
351
|
+
"Code that is written for a specific backend ('asyncio' or 'trio') can be run in the same thread with one of the following:\n",
|
|
352
|
+
"\n",
|
|
353
|
+
"- Line magic - The code following the magic on the same line is run using the specified backend.\n",
|
|
354
|
+
" - `%trio` \n",
|
|
355
|
+
" - `%asyncio` \n",
|
|
356
|
+
"\n",
|
|
357
|
+
"- Cell magic - The code block is run using the specified backend. \n",
|
|
358
|
+
" - `%%trio`\n",
|
|
359
|
+
" - `%asyncio`\n",
|
|
360
|
+
"\n",
|
|
361
|
+
"**Note: trio must be installed for this demo to work.**"
|
|
362
|
+
]
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
"cell_type": "code",
|
|
366
|
+
"execution_count": null,
|
|
367
|
+
"id": "20",
|
|
368
|
+
"metadata": {},
|
|
369
|
+
"outputs": [],
|
|
370
|
+
"source": [
|
|
371
|
+
"%asyncio await asyncio.sleep(0) # This code gets run in an asyncio task \n",
|
|
372
|
+
"%trio await trio.sleep(0) # trio run as line magic"
|
|
373
|
+
]
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
"cell_type": "code",
|
|
377
|
+
"execution_count": null,
|
|
378
|
+
"id": "21",
|
|
379
|
+
"metadata": {},
|
|
380
|
+
"outputs": [],
|
|
381
|
+
"source": [
|
|
382
|
+
"%%trio # trio cell magic\n",
|
|
383
|
+
"\n",
|
|
384
|
+
"def print_info():\n",
|
|
385
|
+
" from aiologic.lowlevel import current_async_library\n",
|
|
386
|
+
" print(f\"\"\"\n",
|
|
387
|
+
" Kernel backend: {get_ipython().kernel.interface.backend}\n",
|
|
388
|
+
" Current backend: { current_async_library()}\n",
|
|
389
|
+
" \"\"\") \n",
|
|
390
|
+
"\n",
|
|
391
|
+
"\n",
|
|
392
|
+
"print_info()\n",
|
|
393
|
+
"await trio.sleep(0)\n",
|
|
394
|
+
"\n",
|
|
395
|
+
"%callers\n",
|
|
396
|
+
"\n",
|
|
397
|
+
"%asyncio print_info()\n",
|
|
398
|
+
"%asyncio %callers\n",
|
|
399
|
+
"\n",
|
|
400
|
+
"await trio.sleep(0)"
|
|
401
|
+
]
|
|
252
402
|
}
|
|
253
403
|
],
|
|
254
404
|
"metadata": {
|
|
@@ -19,7 +19,7 @@ from IPython.core.displaypub import DisplayPublisher
|
|
|
19
19
|
from IPython.core.history import HistoryManager
|
|
20
20
|
from IPython.core.interactiveshell import InteractiveShell
|
|
21
21
|
from IPython.core.interactiveshell import _modified_open as _modified_open_ # pyright: ignore[reportPrivateUsage]
|
|
22
|
-
from IPython.core.magic import Magics, line_cell_magic, line_magic, magics_class
|
|
22
|
+
from IPython.core.magic import Magics, line_cell_magic, line_magic, magics_class, no_var_expand
|
|
23
23
|
from IPython.utils.tokenutil import token_at_cursor
|
|
24
24
|
from jupyter_core.paths import jupyter_runtime_dir
|
|
25
25
|
from traitlets import traitlets
|
|
@@ -32,7 +32,7 @@ from async_kernel.common import Fixed, KernelInterrupt, import_item
|
|
|
32
32
|
from async_kernel.compiler import XCachingCompiler
|
|
33
33
|
from async_kernel.event_loop.run import get_runtime_matplotlib_guis
|
|
34
34
|
from async_kernel.pending import PendingManager
|
|
35
|
-
from async_kernel.typing import Channel, Content, Message, NoValue, Tags
|
|
35
|
+
from async_kernel.typing import Channel, Content, Message, NoValue, RunMode, Tags
|
|
36
36
|
|
|
37
37
|
if TYPE_CHECKING:
|
|
38
38
|
from collections.abc import Callable, Generator
|
|
@@ -402,6 +402,14 @@ class AsyncInteractiveShell(InteractiveShell):
|
|
|
402
402
|
except TypeError:
|
|
403
403
|
return result
|
|
404
404
|
|
|
405
|
+
def transform_cell_async(self, raw_cell: str) -> str:
|
|
406
|
+
"Transform the cell and substitute magic calls with an awaitable wrapper."
|
|
407
|
+
return (
|
|
408
|
+
self.transform_cell(raw_cell)
|
|
409
|
+
.replace("get_ipython().run_line_magic(", "await get_ipython().run_line_magic_async(")
|
|
410
|
+
.replace("get_ipython().run_cell_magic(", "await get_ipython().run_cell_magic_async(")
|
|
411
|
+
)
|
|
412
|
+
|
|
405
413
|
async def execute_request(
|
|
406
414
|
self,
|
|
407
415
|
code: str = "",
|
|
@@ -424,17 +432,11 @@ class AsyncInteractiveShell(InteractiveShell):
|
|
|
424
432
|
try:
|
|
425
433
|
tags: list[str] = utils.get_tags()
|
|
426
434
|
timeout: float = utils.get_timeout(tags=tags)
|
|
427
|
-
suppress_error: bool = Tags.suppress_error in tags
|
|
428
435
|
raises_exception: bool = Tags.raises_exception in tags
|
|
429
436
|
stop_on_error_override: bool = Tags.stop_on_error in tags
|
|
430
|
-
transformed_cell = (
|
|
431
|
-
self.transform_cell(code)
|
|
432
|
-
.replace("get_ipython().run_line_magic(", "await get_ipython().run_line_magic_async(")
|
|
433
|
-
.replace("get_ipython().run_cell_magic(", "await get_ipython().run_cell_magic_async(")
|
|
434
|
-
)
|
|
435
437
|
if stop_on_error_override:
|
|
436
438
|
stop_on_error = utils.get_tag_value(Tags.stop_on_error, stop_on_error)
|
|
437
|
-
elif
|
|
439
|
+
elif raises_exception:
|
|
438
440
|
stop_on_error = False
|
|
439
441
|
|
|
440
442
|
if silent:
|
|
@@ -464,7 +466,7 @@ class AsyncInteractiveShell(InteractiveShell):
|
|
|
464
466
|
raw_cell=code,
|
|
465
467
|
store_history=store_history,
|
|
466
468
|
silent=silent,
|
|
467
|
-
transformed_cell=
|
|
469
|
+
transformed_cell=self.transform_cell_async(code),
|
|
468
470
|
shell_futures=True,
|
|
469
471
|
cell_id=cell_id,
|
|
470
472
|
)
|
|
@@ -482,7 +484,7 @@ class AsyncInteractiveShell(InteractiveShell):
|
|
|
482
484
|
self.events.trigger("post_execute")
|
|
483
485
|
if not silent:
|
|
484
486
|
self.events.trigger("post_run_cell", result)
|
|
485
|
-
if (err) and (
|
|
487
|
+
if (err) and (isinstance(err, anyio.get_cancelled_exc_class()) and (timeout != 0)):
|
|
486
488
|
# Suppress the error due to either:
|
|
487
489
|
# 1. tag
|
|
488
490
|
# 2. timeout
|
|
@@ -583,10 +585,6 @@ class AsyncInteractiveShell(InteractiveShell):
|
|
|
583
585
|
|
|
584
586
|
@override
|
|
585
587
|
def _showtraceback(self, etype, evalue, stb) -> None:
|
|
586
|
-
if Tags.suppress_error in utils.get_tags():
|
|
587
|
-
if msg := utils.get_tag_value(Tags.suppress_error, "⚠"):
|
|
588
|
-
print(msg)
|
|
589
|
-
return
|
|
590
588
|
if utils.get_timeout() != 0.0 and etype is anyio.get_cancelled_exc_class():
|
|
591
589
|
etype, evalue, stb = TimeoutError, "Cell execute timeout", []
|
|
592
590
|
self.kernel.interface.iopub_send(
|
|
@@ -931,6 +929,7 @@ class KernelMagics(Magics):
|
|
|
931
929
|
)
|
|
932
930
|
print(f"Current shell:\t{self.shell}\n\n{subshell_list}")
|
|
933
931
|
|
|
932
|
+
@no_var_expand
|
|
934
933
|
@line_magic
|
|
935
934
|
async def pip(self, line: str) -> Any | None:
|
|
936
935
|
"""Run the pip package manager for the current environment.
|
|
@@ -965,6 +964,7 @@ class KernelMagics(Magics):
|
|
|
965
964
|
|
|
966
965
|
return None
|
|
967
966
|
|
|
967
|
+
@no_var_expand
|
|
968
968
|
@line_magic
|
|
969
969
|
async def uv(self, line) -> None:
|
|
970
970
|
"""Run the uv package manager for the current environment.
|
|
@@ -979,19 +979,55 @@ class KernelMagics(Magics):
|
|
|
979
979
|
if process.stderr:
|
|
980
980
|
tg.start_soon(_forward_transport_stream, process.stderr, sys.stdout)
|
|
981
981
|
|
|
982
|
+
@no_var_expand
|
|
982
983
|
@line_cell_magic
|
|
983
|
-
async def
|
|
984
|
+
async def thread(self, line: str, cell: str | None = None) -> None:
|
|
984
985
|
"""
|
|
985
|
-
Run python code.
|
|
986
|
+
Run the python code in a caller managed child thread.
|
|
986
987
|
|
|
987
|
-
|
|
988
|
+
Both line and cell magic are supported.
|
|
989
|
+
|
|
990
|
+
For cell_magic, [CallerCreateOptions][async_kernel.typing.CallerCreateOptions] can be passed as literals.
|
|
991
|
+
|
|
992
|
+
Example:
|
|
993
|
+
%%thread name="Trio executor" backend=trio
|
|
988
994
|
"""
|
|
989
|
-
shell = SubshellManager.get_shell()
|
|
990
|
-
|
|
991
|
-
|
|
995
|
+
shell: AsyncInteractiveShell | AsyncInteractiveSubshell = SubshellManager.get_shell()
|
|
996
|
+
if cell is None:
|
|
997
|
+
cell = line
|
|
998
|
+
options: Any = None
|
|
999
|
+
else:
|
|
1000
|
+
options = RunMode.line_to_options(line)
|
|
1001
|
+
caller = shell.kernel.caller
|
|
1002
|
+
await (caller.get(**options).call_soon if options else caller.to_thread)(
|
|
1003
|
+
shell.run_cell_async,
|
|
992
1004
|
raw_cell=cell,
|
|
993
1005
|
store_history=False,
|
|
994
1006
|
silent=True,
|
|
995
|
-
cell_id=
|
|
996
|
-
transformed_cell=shell.
|
|
1007
|
+
cell_id=None,
|
|
1008
|
+
transformed_cell=shell.transform_cell_async(cell),
|
|
997
1009
|
)
|
|
1010
|
+
|
|
1011
|
+
async def _call_using_backend(self, backend: Literal["asyncio", "trio"], code: str):
|
|
1012
|
+
shell: AsyncInteractiveShell | AsyncInteractiveSubshell = SubshellManager.get_shell()
|
|
1013
|
+
await Caller().call_using_backend(
|
|
1014
|
+
backend,
|
|
1015
|
+
shell.run_cell_async,
|
|
1016
|
+
raw_cell=code,
|
|
1017
|
+
store_history=False,
|
|
1018
|
+
silent=True,
|
|
1019
|
+
cell_id=None,
|
|
1020
|
+
transformed_cell=shell.transform_cell_async(code),
|
|
1021
|
+
)
|
|
1022
|
+
|
|
1023
|
+
@no_var_expand
|
|
1024
|
+
@line_cell_magic
|
|
1025
|
+
async def asyncio(self, line: str, cell: str | None = None) -> None:
|
|
1026
|
+
""
|
|
1027
|
+
await self._call_using_backend("asyncio", cell or line)
|
|
1028
|
+
|
|
1029
|
+
@no_var_expand
|
|
1030
|
+
@line_cell_magic
|
|
1031
|
+
async def trio(self, line: str, cell: str | None = None) -> None:
|
|
1032
|
+
""
|
|
1033
|
+
await self._call_using_backend("trio", cell or line)
|
|
@@ -834,8 +834,7 @@ class Caller(anyio.AsyncContextManagerMixin):
|
|
|
834
834
|
**kwargs: Keyword arguments to use with `func`.
|
|
835
835
|
|
|
836
836
|
Notes:
|
|
837
|
-
|
|
838
|
-
- **Only use this to execute coroutines that require a specific backend to run in the caller's thread.**
|
|
837
|
+
**Only use this method to execute coroutines that require a specific backend to run in the caller's thread.**
|
|
839
838
|
"""
|
|
840
839
|
return self.schedule_call(func, args, kwargs, None, PendingTracker, Backend(backend))
|
|
841
840
|
|