async-kernel 0.14.0__tar.gz → 0.15.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.
- {async_kernel-0.14.0 → async_kernel-0.15.0}/.github/workflows/ci.yml +9 -3
- {async_kernel-0.14.0 → async_kernel-0.15.0}/.github/workflows/enforce-label.yml +1 -4
- {async_kernel-0.14.0 → async_kernel-0.15.0}/.vscode/launch.json +30 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/CHANGELOG.md +51 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/CONTRIBUTING.md +11 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/PKG-INFO +14 -3
- {async_kernel-0.14.0 → async_kernel-0.15.0}/README.md +11 -1
- async_kernel-0.15.0/_version.py +24 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/notebooks/caller.ipynb +17 -10
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/index.md +2 -2
- async_kernel-0.15.0/docs/thread_safety.md +40 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/usage/index.md +12 -2
- {async_kernel-0.14.0 → async_kernel-0.15.0}/mkdocs.yml +3 -3
- {async_kernel-0.14.0 → async_kernel-0.15.0}/pyproject.toml +2 -1
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/asyncshell.py +5 -5
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/caller.py +41 -44
- async_kernel-0.15.0/src/async_kernel/common.py +132 -0
- async_kernel-0.15.0/src/async_kernel/compat/json.py +45 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/debugger.py +3 -3
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/interface/base.py +17 -2
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/interface/callable.py +7 -53
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/interface/zmq.py +6 -13
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/kernel.py +41 -21
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/pending.py +136 -84
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/typing.py +1 -1
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_callable_kernel_interface.py +11 -7
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_caller.py +5 -8
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_common.py +2 -22
- async_kernel-0.15.0/tests/test_compat.py +39 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_event_loop.py +1 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_kernel.py +2 -1
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_pending.py +87 -10
- {async_kernel-0.14.0 → async_kernel-0.15.0}/uv.lock +314 -360
- async_kernel-0.14.0/_version.py +0 -34
- async_kernel-0.14.0/src/async_kernel/common.py +0 -138
- {async_kernel-0.14.0 → async_kernel-0.15.0}/.github/dependabot.yaml +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/.github/release.yml +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/.github/workflows/new_release.yml +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/.github/workflows/pre-commit.yml +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/.github/workflows/publish-docs.yml +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/.github/workflows/publish-to-pypi.yml +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/.gitignore +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/.pre-commit-config.yaml +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/.vscode/settings.json +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/.vscode/spellright.dict +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/IPYTHON_LICENSE +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/LICENSE +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/cliff.toml +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/about/changelog.md +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/about/contributing.md +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/about/index.md +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/about/license.md +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/index.md +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/javascripts/extra.js +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/notebooks/concurrency.ipynb +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/overrides/main.html +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/asyncshell.md +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/caller.md +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/comm.md +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/command.md +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/common.md +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/debugger.md +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/event_loop.md +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/interface.md +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/kernel.md +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/kernelspec.md +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/pending.md +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/typing.md +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/utils.md +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/stylesheets/extra.css +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/usage/commands.md +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/hatch_build.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/__init__.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/__main__.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/comm.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/command.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/compiler.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/event_loop/__init__.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/event_loop/asyncio_guest.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/event_loop/qt_host.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/event_loop/run.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/event_loop/tk_host.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/interface/__init__.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/iostream.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/kernelspec.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/py.typed +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/resources/logo-32x32.png +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/resources/logo-64x64.png +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/resources/logo-svg.svg +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/utils.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/__init__.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/conftest.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/references.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_comm.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_command.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_debugger.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_enter_kernel.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_iostream.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_kernel_subclass.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_kernelspec.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_message_spec.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_typing.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_utils.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_zmq_messaging.py +0 -0
- {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/utils.py +0 -0
|
@@ -38,8 +38,7 @@ jobs:
|
|
|
38
38
|
- "3.11"
|
|
39
39
|
- "3.12"
|
|
40
40
|
- "3.13"
|
|
41
|
-
- "3.
|
|
42
|
-
# - "3.14t" # re-enabled when free-threading becomes more widely supported.
|
|
41
|
+
- "3.14t"
|
|
43
42
|
steps:
|
|
44
43
|
- name: Checkout
|
|
45
44
|
uses: actions/checkout@v6
|
|
@@ -54,6 +53,10 @@ jobs:
|
|
|
54
53
|
- name: Install the project
|
|
55
54
|
run: uv sync --locked --dev
|
|
56
55
|
|
|
56
|
+
- if: ${{ startsWith(matrix.os, 'windows') && !endsWith(matrix.python-version, 't')}}
|
|
57
|
+
# Pyside does not have free-threaded binary
|
|
58
|
+
run: uv sync --locked --dev --group gui
|
|
59
|
+
|
|
57
60
|
- name: Run tests
|
|
58
61
|
timeout-minutes: 5
|
|
59
62
|
run: uv run pytest -vvl --maxfail=1 --reruns 1
|
|
@@ -75,7 +78,10 @@ jobs:
|
|
|
75
78
|
|
|
76
79
|
- name: Run tests with coverage
|
|
77
80
|
timeout-minutes: 5
|
|
78
|
-
run:
|
|
81
|
+
run: |
|
|
82
|
+
uv sync --locked --dev
|
|
83
|
+
uv pip install orjson>=3.10.16
|
|
84
|
+
uv run pytest --cov --cov-report=xml --junitxml=junit.xml -o junit_family=legacy --cov-fail-under=100 --cov-report markdown-append:$GITHUB_STEP_SUMMARY
|
|
79
85
|
|
|
80
86
|
- name: Upload coverage reports to Codecov
|
|
81
87
|
if: ${{ !cancelled() }}
|
|
@@ -26,6 +26,36 @@
|
|
|
26
26
|
},
|
|
27
27
|
"justMyCode": true,
|
|
28
28
|
"args": ["-X dev", "Wd"]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"name": "Jupyterlab",
|
|
32
|
+
"type": "debugpy",
|
|
33
|
+
"request": "launch",
|
|
34
|
+
"args": [
|
|
35
|
+
"--notebook-dir=docs/notebooks",
|
|
36
|
+
"--no-browser",
|
|
37
|
+
"--ServerApp.token=''",
|
|
38
|
+
"--port=9991"
|
|
39
|
+
],
|
|
40
|
+
"cwd": "${workspaceFolder}",
|
|
41
|
+
"justMyCode": false,
|
|
42
|
+
"module": "jupyterlab",
|
|
43
|
+
"presentation": {
|
|
44
|
+
"hidden": false
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "Editor Browser",
|
|
49
|
+
"type": "editor-browser",
|
|
50
|
+
"request": "launch",
|
|
51
|
+
"url": "http://localhost:9991",
|
|
52
|
+
"webRoot": "${workspaceFolder}"
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
"compounds": [
|
|
56
|
+
{
|
|
57
|
+
"name": "Python and Jupyterlab",
|
|
58
|
+
"configurations": ["Jupyterlab", "Editor Browser"]
|
|
29
59
|
}
|
|
30
60
|
]
|
|
31
61
|
}
|
|
@@ -5,6 +5,52 @@ 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.15.0] - 2026-03-30
|
|
9
|
+
|
|
10
|
+
### <!-- 0 --> 🏗️ Breaking changes
|
|
11
|
+
|
|
12
|
+
- Provide cancellation in Pending by default [#386](https://github.com/fleming79/async-kernel/pull/386)
|
|
13
|
+
|
|
14
|
+
- Use a standard dict for the user_ns (remove LastUpdatedDict) [#380](https://github.com/fleming79/async-kernel/pull/380)
|
|
15
|
+
|
|
16
|
+
### <!-- 1 --> 🚀 Features
|
|
17
|
+
|
|
18
|
+
- Replace aiologic.Lock with aiologic.lowlevel.create_thread_oncelock for improved performance [#389](https://github.com/fleming79/async-kernel/pull/389)
|
|
19
|
+
|
|
20
|
+
- Convert Pending._done_callbacks from deque to list [#383](https://github.com/fleming79/async-kernel/pull/383)
|
|
21
|
+
|
|
22
|
+
- Free-threading preliminary support. [#379](https://github.com/fleming79/async-kernel/pull/379)
|
|
23
|
+
|
|
24
|
+
### <!-- 5 --> 📝 Documentation
|
|
25
|
+
|
|
26
|
+
- Update docstrings [#384](https://github.com/fleming79/async-kernel/pull/384)
|
|
27
|
+
|
|
28
|
+
- Add thread_safety.md [#381](https://github.com/fleming79/async-kernel/pull/381)
|
|
29
|
+
|
|
30
|
+
### <!-- 6 --> 🌀 Miscellaneous
|
|
31
|
+
|
|
32
|
+
- Change Pending.wait_sync signature to be the same as Pending.wait [#393](https://github.com/fleming79/async-kernel/pull/393)
|
|
33
|
+
|
|
34
|
+
- Tidy up [#391](https://github.com/fleming79/async-kernel/pull/391)
|
|
35
|
+
|
|
36
|
+
- Pending refactoring. [#390](https://github.com/fleming79/async-kernel/pull/390)
|
|
37
|
+
|
|
38
|
+
- Use aiologic.lowlevel.create_async_waiter instead of Event for better performance. [#388](https://github.com/fleming79/async-kernel/pull/388)
|
|
39
|
+
|
|
40
|
+
- Pending refactoring [#385](https://github.com/fleming79/async-kernel/pull/385)
|
|
41
|
+
|
|
42
|
+
- Caller.queue_call optimizations [#382](https://github.com/fleming79/async-kernel/pull/382)
|
|
43
|
+
|
|
44
|
+
- Add Kernel.run and refactor the interfaces. [#378](https://github.com/fleming79/async-kernel/pull/378)
|
|
45
|
+
|
|
46
|
+
- Use Kernel._get_run_mode for all message types. [#377](https://github.com/fleming79/async-kernel/pull/377)
|
|
47
|
+
|
|
48
|
+
- Add a VS Code launch config for to launch Jupyterlab [#376](https://github.com/fleming79/async-kernel/pull/376)
|
|
49
|
+
|
|
50
|
+
- Upgrade uv.lock and run gui tests using windows. [#375](https://github.com/fleming79/async-kernel/pull/375)
|
|
51
|
+
|
|
52
|
+
- Update uv.lock [#374](https://github.com/fleming79/async-kernel/pull/374)
|
|
53
|
+
|
|
8
54
|
## [0.14.0] - 2026-03-24
|
|
9
55
|
|
|
10
56
|
### <!-- 0 --> 🏗️ Breaking changes
|
|
@@ -17,6 +63,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
17
63
|
|
|
18
64
|
- Update readme [#371](https://github.com/fleming79/async-kernel/pull/371)
|
|
19
65
|
|
|
66
|
+
### <!-- 6 --> 🌀 Miscellaneous
|
|
67
|
+
|
|
68
|
+
- Prepare for release v0.14.0 [#373](https://github.com/fleming79/async-kernel/pull/373)
|
|
69
|
+
|
|
20
70
|
## [0.13.3] - 2026-03-23
|
|
21
71
|
|
|
22
72
|
### <!-- 0 --> 🏗️ Breaking changes
|
|
@@ -1037,6 +1087,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
1037
1087
|
|
|
1038
1088
|
- Bump the actions group across 1 directory with 2 updates [#3](https://github.com/fleming79/async-kernel/pull/3)
|
|
1039
1089
|
|
|
1090
|
+
[0.15.0]: https://github.com/fleming79/async-kernel/compare/v0.14.0..v0.15.0
|
|
1040
1091
|
[0.14.0]: https://github.com/fleming79/async-kernel/compare/v0.13.3..v0.14.0
|
|
1041
1092
|
[0.13.3]: https://github.com/fleming79/async-kernel/compare/v0.13.2..v0.13.3
|
|
1042
1093
|
[0.13.2]: https://github.com/fleming79/async-kernel/compare/v0.13.1..v0.13.2
|
|
@@ -208,3 +208,14 @@ uv run mkdocs build -s
|
|
|
208
208
|
tests can still fail for another os or python version.
|
|
209
209
|
|
|
210
210
|
[^test-pypi]: This workflow also runs on push to the main branch, but will instead publish to [TestPyPI](https://test.pypi.org/project/async-kernel/).
|
|
211
|
+
|
|
212
|
+
## VS code development
|
|
213
|
+
|
|
214
|
+
Debug configurations are included to support debugging with VS Code.
|
|
215
|
+
|
|
216
|
+
- Python: Debug Tests: This config is for attaching a debugger when launching tests.
|
|
217
|
+
The recommended way to debug tests.
|
|
218
|
+
- Python and Jupyterlab (Requires VS Code >1.112.0): This provides a compound launch configuration
|
|
219
|
+
which starts Jupyterlab and Python. The built in browser launches attaches to the Jupyter session
|
|
220
|
+
(refresh may be required after the server has started). The advantage of this configuration
|
|
221
|
+
is that all Python processes are attached to the debugger whenever a kernel is opened.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: async-kernel
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.15.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
|
|
@@ -29,6 +29,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
29
29
|
Classifier: Programming Language :: Python :: 3.12
|
|
30
30
|
Classifier: Programming Language :: Python :: 3.13
|
|
31
31
|
Classifier: Programming Language :: Python :: 3.14
|
|
32
|
+
Classifier: Programming Language :: Python :: Free Threading :: 1 - Unstable
|
|
32
33
|
Classifier: Typing :: Typed
|
|
33
34
|
Requires-Python: >=3.11
|
|
34
35
|
Requires-Dist: aiologic>=0.16.0
|
|
@@ -38,7 +39,7 @@ Requires-Dist: ipython>=9.0
|
|
|
38
39
|
Requires-Dist: jupyter-client>=8.8; sys_platform != 'emscripten'
|
|
39
40
|
Requires-Dist: jupyter-core>=5.9.1
|
|
40
41
|
Requires-Dist: matplotlib-inline>0.1
|
|
41
|
-
Requires-Dist: orjson>=3.10.16
|
|
42
|
+
Requires-Dist: orjson>=3.10.16; sys_platform == 'emscripten'
|
|
42
43
|
Requires-Dist: outcome; sys_platform != 'emscripten'
|
|
43
44
|
Requires-Dist: pyzmq>=27.0; sys_platform != 'emscripten'
|
|
44
45
|
Requires-Dist: sniffio>=1.3.0; sys_platform != 'emscripten'
|
|
@@ -65,7 +66,7 @@ that provides concurrent message handling via an asynchronous backend (asyncio o
|
|
|
65
66
|
|
|
66
67
|
The kernel provides two external interfaces:
|
|
67
68
|
|
|
68
|
-
1. Direct ZMQ socket messaging via a configuration file and kernel spec - (Jupyter,
|
|
69
|
+
1. Direct ZMQ socket messaging via a configuration file and kernel spec - (Jupyter, VS Code, etc).
|
|
69
70
|
2. An experimental callback style interface (Jupyterlite).
|
|
70
71
|
|
|
71
72
|
## Highlights
|
|
@@ -202,6 +203,16 @@ async-kernel -a async-qt --interface.host=qt --interface.backend=trio
|
|
|
202
203
|
|
|
203
204
|
For further detail about kernel spec customisation see [command line and kernel configuration](https://fleming79.github.io/async-kernel/latest/usage/commands/).
|
|
204
205
|
|
|
206
|
+
## Faster data serialization
|
|
207
|
+
|
|
208
|
+
[orjson](https://github.com/ijl/orjson) (a fast JSON library) is supported and will be used by default if it has been installed.
|
|
209
|
+
|
|
210
|
+
## Free-threading support
|
|
211
|
+
|
|
212
|
+
async-kernel's Caller's are _thread-local_ and it's methods are _internally synchronised_[^4].
|
|
213
|
+
|
|
214
|
+
[^4]: [free threading terminology](https://py-free-threading.github.io/documentation-principles/#free-threading-terminology)
|
|
215
|
+
|
|
205
216
|
## Origin
|
|
206
217
|
|
|
207
218
|
async-kernel started as a [fork](https://github.com/ipython/ipykernel/commit/8322a7684b004ee95f07b2f86f61e28146a5996d)
|
|
@@ -16,7 +16,7 @@ that provides concurrent message handling via an asynchronous backend (asyncio o
|
|
|
16
16
|
|
|
17
17
|
The kernel provides two external interfaces:
|
|
18
18
|
|
|
19
|
-
1. Direct ZMQ socket messaging via a configuration file and kernel spec - (Jupyter,
|
|
19
|
+
1. Direct ZMQ socket messaging via a configuration file and kernel spec - (Jupyter, VS Code, etc).
|
|
20
20
|
2. An experimental callback style interface (Jupyterlite).
|
|
21
21
|
|
|
22
22
|
## Highlights
|
|
@@ -153,6 +153,16 @@ async-kernel -a async-qt --interface.host=qt --interface.backend=trio
|
|
|
153
153
|
|
|
154
154
|
For further detail about kernel spec customisation see [command line and kernel configuration](https://fleming79.github.io/async-kernel/latest/usage/commands/).
|
|
155
155
|
|
|
156
|
+
## Faster data serialization
|
|
157
|
+
|
|
158
|
+
[orjson](https://github.com/ijl/orjson) (a fast JSON library) is supported and will be used by default if it has been installed.
|
|
159
|
+
|
|
160
|
+
## Free-threading support
|
|
161
|
+
|
|
162
|
+
async-kernel's Caller's are _thread-local_ and it's methods are _internally synchronised_[^4].
|
|
163
|
+
|
|
164
|
+
[^4]: [free threading terminology](https://py-free-threading.github.io/documentation-principles/#free-threading-terminology)
|
|
165
|
+
|
|
156
166
|
## Origin
|
|
157
167
|
|
|
158
168
|
async-kernel started as a [fork](https://github.com/ipython/ipykernel/commit/8322a7684b004ee95f07b2f86f61e28146a5996d)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# file generated by vcs-versioning
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"__version__",
|
|
7
|
+
"__version_tuple__",
|
|
8
|
+
"version",
|
|
9
|
+
"version_tuple",
|
|
10
|
+
"__commit_id__",
|
|
11
|
+
"commit_id",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
version: str
|
|
15
|
+
__version__: str
|
|
16
|
+
__version_tuple__: tuple[int | str, ...]
|
|
17
|
+
version_tuple: tuple[int | str, ...]
|
|
18
|
+
commit_id: str | None
|
|
19
|
+
__commit_id__: str | None
|
|
20
|
+
|
|
21
|
+
__version__ = version = '0.15.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 15, 0)
|
|
23
|
+
|
|
24
|
+
__commit_id__ = commit_id = None
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"\n",
|
|
16
16
|
"_This notebook has the Python dependencies: `trio`, `matplotlib`_\n",
|
|
17
17
|
"\n",
|
|
18
|
-
"`Caller` is a class that
|
|
18
|
+
"`Caller` is a thread-local class that coordinates the execution of functions and coroutines in the event loop of a `asyncio` or `trio` backend."
|
|
19
19
|
]
|
|
20
20
|
},
|
|
21
21
|
{
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"metadata": {},
|
|
36
36
|
"source": [
|
|
37
37
|
"A `Caller` instance can be started with one gui as a host to one backend started as a guest. \n",
|
|
38
|
+
"\n",
|
|
38
39
|
"A second backend can also be started in the same thread with or without a host gui event loop.\n",
|
|
39
40
|
"Potentially the same thread could have up to:\n",
|
|
40
41
|
"\n",
|
|
@@ -77,11 +78,10 @@
|
|
|
77
78
|
"id": "5",
|
|
78
79
|
"metadata": {},
|
|
79
80
|
"source": [
|
|
80
|
-
"There are
|
|
81
|
+
"There are two caller instances associated with the Kernel:\n",
|
|
81
82
|
"\n",
|
|
82
83
|
"- Shell: The caller for the shell channel (normally the MainThread).\n",
|
|
83
|
-
"- Control: The caller for the control channel (a child of the shell)
|
|
84
|
-
"- Shell thread_queue: A separate thread to handle shell messages in a separate thread (queued by message type and subshell_id)."
|
|
84
|
+
"- Control: The caller for the control channel (a child of the shell)."
|
|
85
85
|
]
|
|
86
86
|
},
|
|
87
87
|
{
|
|
@@ -89,7 +89,9 @@
|
|
|
89
89
|
"id": "6",
|
|
90
90
|
"metadata": {},
|
|
91
91
|
"source": [
|
|
92
|
-
"Calling `Caller()` with no arguments will return the caller for the current thread (context in Pyodide).
|
|
92
|
+
"Calling `Caller()` with no arguments will return the caller for the current thread (or context in Pyodide). \n",
|
|
93
|
+
"\n",
|
|
94
|
+
"A runtime error will occur if there is no event loop (backend) running in the current thread (unlikely in Pyodide which provides a running event loop)."
|
|
93
95
|
]
|
|
94
96
|
},
|
|
95
97
|
{
|
|
@@ -111,7 +113,7 @@
|
|
|
111
113
|
"source": [
|
|
112
114
|
"## Modifiers\n",
|
|
113
115
|
"\n",
|
|
114
|
-
"There are four modifiers that determine
|
|
116
|
+
"There are four modifiers that determine which instance is returned when calling `Caller`.\n",
|
|
115
117
|
"\n",
|
|
116
118
|
"- `CurrentThread` (default): Access the caller that belongs to the current thread (or context with Pyodide).\n",
|
|
117
119
|
"- `MainThread`: Access main thread for the Caller.\n",
|
|
@@ -285,7 +287,9 @@
|
|
|
285
287
|
"source": [
|
|
286
288
|
"### Caller.call_using_backend\n",
|
|
287
289
|
"\n",
|
|
288
|
-
"This method calls functions and coroutines using a specific asynchronous backend in the same thread.
|
|
290
|
+
"This method calls functions and coroutines using a specific asynchronous backend in the same thread. \n",
|
|
291
|
+
"\n",
|
|
292
|
+
"When the backend does not match the callers backend, it is run with the backend running as a guest."
|
|
289
293
|
]
|
|
290
294
|
},
|
|
291
295
|
{
|
|
@@ -490,10 +494,13 @@
|
|
|
490
494
|
"metadata": {},
|
|
491
495
|
"outputs": [],
|
|
492
496
|
"source": [
|
|
497
|
+
"import anyio\n",
|
|
498
|
+
"\n",
|
|
493
499
|
"async with caller.create_pending_group() as pg:\n",
|
|
494
|
-
" caller.call_soon(
|
|
495
|
-
" caller.call_later(0,
|
|
496
|
-
" caller.to_thread(
|
|
500
|
+
" caller.call_soon(anyio.sleep, 0.01)\n",
|
|
501
|
+
" caller.call_later(0, anyio.sleep, 0)\n",
|
|
502
|
+
" caller.to_thread(anyio.sleep, 0.01)\n",
|
|
503
|
+
" caller.call_using_backend(\"asyncio\", asyncio.sleep, 0.01)\n",
|
|
497
504
|
" caller.call_using_backend(\"trio\", trio.sleep, 0.01)\n",
|
|
498
505
|
" print(\"In context pending=\", len(pg.pending))\n",
|
|
499
506
|
"\n",
|
|
@@ -12,6 +12,6 @@ The reference section provides documentation for each module in async-kernel.
|
|
|
12
12
|
## Highlights
|
|
13
13
|
|
|
14
14
|
- [Kernel][async_kernel.kernel.Kernel] - The kernel.
|
|
15
|
-
- [Caller][async_kernel.caller.Caller] - Simplifies event loop management and call scheduling
|
|
16
|
-
- [Pending][async_kernel.pending.Pending] - Represents a pending result that can be
|
|
15
|
+
- [Caller][async_kernel.caller.Caller] - Simplifies event loop management and call scheduling.
|
|
16
|
+
- [Pending][async_kernel.pending.Pending] - Represents a pending result (like an [asyncio.Future][] that can be awaited anywhere).
|
|
17
17
|
- [command_line][async_kernel.command.command_line] - The command line interface.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Thread Safety of Built-in Types
|
|
2
|
+
|
|
3
|
+
- [Terminology](https://py-free-threading.github.io/documentation-principles/#free-threading-terminology)
|
|
4
|
+
|
|
5
|
+
_aync-kernel_ utilises [aiologic](https://aiologic.readthedocs.io/latest/index.html) for its _thread-safe_ primitives.
|
|
6
|
+
|
|
7
|
+
## [async_kernel.pending.Pending][]
|
|
8
|
+
|
|
9
|
+
### Guarantees
|
|
10
|
+
|
|
11
|
+
- **Internally synchronised**
|
|
12
|
+
- All Public methods can be safely called from any thread.
|
|
13
|
+
- Instance are sync/async awaitable from any thread with any backend.
|
|
14
|
+
|
|
15
|
+
- **Limitations**
|
|
16
|
+
|
|
17
|
+
[add_done_callback][async_kernel.pending.Pending.add_done_callback]: The callback is called from the thread in which it is set
|
|
18
|
+
so should provide it's own synchronisation as needed.
|
|
19
|
+
|
|
20
|
+
## [async_kernel.caller.Caller][]
|
|
21
|
+
|
|
22
|
+
`Caller` is thread-local in CPython and context-local in Pyodide.
|
|
23
|
+
|
|
24
|
+
### Guarantees
|
|
25
|
+
|
|
26
|
+
- **Internally synchronised**
|
|
27
|
+
|
|
28
|
+
- **Limitations**
|
|
29
|
+
- [queue_call][async_kernel.caller.Caller.queue_call] is internally synchronised per-function after
|
|
30
|
+
the first call (per-function) has returned.
|
|
31
|
+
|
|
32
|
+
## [async_kernel.common.Fixed][]
|
|
33
|
+
|
|
34
|
+
### Guarantees
|
|
35
|
+
|
|
36
|
+
- **Internally synchronised**
|
|
37
|
+
|
|
38
|
+
### Other classes
|
|
39
|
+
|
|
40
|
+
TODO
|
|
@@ -5,9 +5,19 @@ icon: material/note-text
|
|
|
5
5
|
# subtitle: A sub title
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
async-kernel feels like a standard kernel that offers advanced features that improved user experience.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- Separate handlers for msg_type and channel allow messages to be processed concurrently.
|
|
13
|
+
- Code execution is top-level awaitable.
|
|
14
|
+
- Choice of async backend (asyncio or trio).
|
|
15
|
+
- Choice of asyncio event loop when started by anyio (not as a guest).
|
|
16
|
+
- Optional gui host event loop.
|
|
17
|
+
- Using [Caller.call_using_backend][async_kernel.caller.Caller.call_using_backend], code from any backend can be called in any thread.
|
|
18
|
+
|
|
19
|
+
## [Command line](../usage/commands.md): Detail about command line usage including:
|
|
9
20
|
|
|
10
|
-
- [Command line](../usage/commands.md): Detail about command line usage including:
|
|
11
21
|
- Adding a kernel spec
|
|
12
22
|
- Deleting a kernel spec
|
|
13
23
|
- Starting a kernel
|
|
@@ -99,9 +99,10 @@ plugins:
|
|
|
99
99
|
- https://ipywidgets.readthedocs.io/en/stable/objects.inv
|
|
100
100
|
- https://jupyter-client.readthedocs.io/en/stable/objects.inv
|
|
101
101
|
- https://anyio.readthedocs.io/en/stable/objects.inv
|
|
102
|
-
- http://aiologic.readthedocs.io/
|
|
102
|
+
- http://aiologic.readthedocs.io/stable/objects.inv
|
|
103
103
|
- https://wrapt.readthedocs.io/en/master/objects.inv
|
|
104
104
|
- https://trio.readthedocs.io/en/stable/objects.inv
|
|
105
|
+
- https://pyzmq.readthedocs.io/en/stable/objects.inv
|
|
105
106
|
options:
|
|
106
107
|
docstring_style: google
|
|
107
108
|
docstring_options:
|
|
@@ -115,7 +116,6 @@ plugins:
|
|
|
115
116
|
members_order: source
|
|
116
117
|
merge_init_into_class: false
|
|
117
118
|
parameter_headings: true
|
|
118
|
-
# preload_modules: [mkdocstrings]
|
|
119
119
|
relative_crossrefs: true
|
|
120
120
|
scoped_crossrefs: true
|
|
121
121
|
separate_signature: true
|
|
@@ -184,7 +184,7 @@ nav:
|
|
|
184
184
|
- "event_loop": reference/event_loop.md
|
|
185
185
|
- "typing": reference/typing.md
|
|
186
186
|
- "utils": reference/utils.md
|
|
187
|
-
|
|
187
|
+
- Thread safety: thread_safety.md
|
|
188
188
|
- About:
|
|
189
189
|
- about/index.md
|
|
190
190
|
|
|
@@ -31,13 +31,14 @@ classifiers = [
|
|
|
31
31
|
"Programming Language :: Python :: 3.12",
|
|
32
32
|
"Programming Language :: Python :: 3.13",
|
|
33
33
|
"Programming Language :: Python :: 3.14",
|
|
34
|
+
"Programming Language :: Python :: Free Threading :: 1 - Unstable",
|
|
34
35
|
]
|
|
35
36
|
requires-python = ">=3.11"
|
|
36
37
|
dependencies = [
|
|
37
38
|
"anyio>=4.12",
|
|
38
39
|
"typing_extensions>=4.14",
|
|
39
40
|
"aiologic>=0.16.0",
|
|
40
|
-
"orjson>=3.10.16",
|
|
41
|
+
"orjson>=3.10.16; sys_platform == 'emscripten'",
|
|
41
42
|
"comm>=0.2",
|
|
42
43
|
"ipython>=9.0",
|
|
43
44
|
"traitlets>=5.14",
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import builtins
|
|
4
4
|
import contextlib
|
|
5
|
+
import json
|
|
5
6
|
import os
|
|
6
7
|
import pathlib
|
|
7
8
|
import sys
|
|
@@ -11,7 +12,6 @@ from typing import TYPE_CHECKING, Any, Literal, Self, overload
|
|
|
11
12
|
|
|
12
13
|
import anyio
|
|
13
14
|
import IPython.core.release
|
|
14
|
-
import orjson
|
|
15
15
|
from aiologic.lowlevel import async_checkpoint
|
|
16
16
|
from IPython.core.completer import provisionalcompleter, rectify_completions
|
|
17
17
|
from IPython.core.displayhook import DisplayHook
|
|
@@ -27,7 +27,7 @@ from typing_extensions import override
|
|
|
27
27
|
import async_kernel
|
|
28
28
|
from async_kernel import utils
|
|
29
29
|
from async_kernel.caller import Caller
|
|
30
|
-
from async_kernel.common import Fixed
|
|
30
|
+
from async_kernel.common import Fixed
|
|
31
31
|
from async_kernel.compiler import XCachingCompiler
|
|
32
32
|
from async_kernel.event_loop.run import get_runtime_matplotlib_guis
|
|
33
33
|
from async_kernel.pending import PendingManager
|
|
@@ -171,7 +171,7 @@ class AsyncInteractiveShell(InteractiveShell):
|
|
|
171
171
|
|
|
172
172
|
Notable differences:
|
|
173
173
|
- Supports a soft timeout specified via tags `timeout=<value in seconds>`[^1].
|
|
174
|
-
- `user_ns` and `user_global_ns` are same dictionary which is a fixed [
|
|
174
|
+
- `user_ns` and `user_global_ns` are same dictionary which is a fixed [dict][].
|
|
175
175
|
|
|
176
176
|
[^1]: When the execution time exceeds the timeout value, the code execution will "move on".
|
|
177
177
|
"""
|
|
@@ -194,7 +194,7 @@ class AsyncInteractiveShell(InteractiveShell):
|
|
|
194
194
|
user_ns_hidden: Fixed[Self, dict] = Fixed(lambda c: c["owner"]._get_default_ns())
|
|
195
195
|
user_global_ns: Fixed[Self, dict] = Fixed(lambda c: c["owner"]._user_ns) # pyright: ignore[reportIncompatibleMethodOverride]
|
|
196
196
|
|
|
197
|
-
_user_ns: Fixed[Self,
|
|
197
|
+
_user_ns: Fixed[Self, dict] = Fixed(dict) # pyright: ignore[reportIncompatibleVariableOverride]
|
|
198
198
|
_main_mod_cache = Fixed(dict)
|
|
199
199
|
_stop_on_error_pool: Fixed[Self, set[Callable[[], object]]] = Fixed(set)
|
|
200
200
|
_stop_on_error_info: Fixed[Self, dict[Literal["time", "execution_count"], Any]] = Fixed(dict)
|
|
@@ -726,7 +726,7 @@ class KernelMagics(Magics):
|
|
|
726
726
|
connection_file = connection_file.name
|
|
727
727
|
info = self.shell.kernel.get_connection_info()
|
|
728
728
|
print(
|
|
729
|
-
|
|
729
|
+
json.dumps(info, indent=2),
|
|
730
730
|
"Paste the above JSON into a file, and connect with:\n"
|
|
731
731
|
+ " $> jupyter <app> --existing <file>\n"
|
|
732
732
|
+ "or, if you are local, you can connect with just:\n"
|