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.
Files changed (105) hide show
  1. {async_kernel-0.14.0 → async_kernel-0.15.0}/.github/workflows/ci.yml +9 -3
  2. {async_kernel-0.14.0 → async_kernel-0.15.0}/.github/workflows/enforce-label.yml +1 -4
  3. {async_kernel-0.14.0 → async_kernel-0.15.0}/.vscode/launch.json +30 -0
  4. {async_kernel-0.14.0 → async_kernel-0.15.0}/CHANGELOG.md +51 -0
  5. {async_kernel-0.14.0 → async_kernel-0.15.0}/CONTRIBUTING.md +11 -0
  6. {async_kernel-0.14.0 → async_kernel-0.15.0}/PKG-INFO +14 -3
  7. {async_kernel-0.14.0 → async_kernel-0.15.0}/README.md +11 -1
  8. async_kernel-0.15.0/_version.py +24 -0
  9. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/notebooks/caller.ipynb +17 -10
  10. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/index.md +2 -2
  11. async_kernel-0.15.0/docs/thread_safety.md +40 -0
  12. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/usage/index.md +12 -2
  13. {async_kernel-0.14.0 → async_kernel-0.15.0}/mkdocs.yml +3 -3
  14. {async_kernel-0.14.0 → async_kernel-0.15.0}/pyproject.toml +2 -1
  15. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/asyncshell.py +5 -5
  16. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/caller.py +41 -44
  17. async_kernel-0.15.0/src/async_kernel/common.py +132 -0
  18. async_kernel-0.15.0/src/async_kernel/compat/json.py +45 -0
  19. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/debugger.py +3 -3
  20. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/interface/base.py +17 -2
  21. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/interface/callable.py +7 -53
  22. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/interface/zmq.py +6 -13
  23. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/kernel.py +41 -21
  24. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/pending.py +136 -84
  25. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/typing.py +1 -1
  26. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_callable_kernel_interface.py +11 -7
  27. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_caller.py +5 -8
  28. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_common.py +2 -22
  29. async_kernel-0.15.0/tests/test_compat.py +39 -0
  30. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_event_loop.py +1 -0
  31. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_kernel.py +2 -1
  32. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_pending.py +87 -10
  33. {async_kernel-0.14.0 → async_kernel-0.15.0}/uv.lock +314 -360
  34. async_kernel-0.14.0/_version.py +0 -34
  35. async_kernel-0.14.0/src/async_kernel/common.py +0 -138
  36. {async_kernel-0.14.0 → async_kernel-0.15.0}/.github/dependabot.yaml +0 -0
  37. {async_kernel-0.14.0 → async_kernel-0.15.0}/.github/release.yml +0 -0
  38. {async_kernel-0.14.0 → async_kernel-0.15.0}/.github/workflows/new_release.yml +0 -0
  39. {async_kernel-0.14.0 → async_kernel-0.15.0}/.github/workflows/pre-commit.yml +0 -0
  40. {async_kernel-0.14.0 → async_kernel-0.15.0}/.github/workflows/publish-docs.yml +0 -0
  41. {async_kernel-0.14.0 → async_kernel-0.15.0}/.github/workflows/publish-to-pypi.yml +0 -0
  42. {async_kernel-0.14.0 → async_kernel-0.15.0}/.gitignore +0 -0
  43. {async_kernel-0.14.0 → async_kernel-0.15.0}/.pre-commit-config.yaml +0 -0
  44. {async_kernel-0.14.0 → async_kernel-0.15.0}/.vscode/settings.json +0 -0
  45. {async_kernel-0.14.0 → async_kernel-0.15.0}/.vscode/spellright.dict +0 -0
  46. {async_kernel-0.14.0 → async_kernel-0.15.0}/IPYTHON_LICENSE +0 -0
  47. {async_kernel-0.14.0 → async_kernel-0.15.0}/LICENSE +0 -0
  48. {async_kernel-0.14.0 → async_kernel-0.15.0}/cliff.toml +0 -0
  49. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/about/changelog.md +0 -0
  50. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/about/contributing.md +0 -0
  51. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/about/index.md +0 -0
  52. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/about/license.md +0 -0
  53. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/index.md +0 -0
  54. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/javascripts/extra.js +0 -0
  55. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/notebooks/concurrency.ipynb +0 -0
  56. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/overrides/main.html +0 -0
  57. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/asyncshell.md +0 -0
  58. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/caller.md +0 -0
  59. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/comm.md +0 -0
  60. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/command.md +0 -0
  61. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/common.md +0 -0
  62. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/debugger.md +0 -0
  63. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/event_loop.md +0 -0
  64. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/interface.md +0 -0
  65. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/kernel.md +0 -0
  66. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/kernelspec.md +0 -0
  67. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/pending.md +0 -0
  68. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/typing.md +0 -0
  69. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/reference/utils.md +0 -0
  70. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/stylesheets/extra.css +0 -0
  71. {async_kernel-0.14.0 → async_kernel-0.15.0}/docs/usage/commands.md +0 -0
  72. {async_kernel-0.14.0 → async_kernel-0.15.0}/hatch_build.py +0 -0
  73. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/__init__.py +0 -0
  74. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/__main__.py +0 -0
  75. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/comm.py +0 -0
  76. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/command.py +0 -0
  77. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/compiler.py +0 -0
  78. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/event_loop/__init__.py +0 -0
  79. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/event_loop/asyncio_guest.py +0 -0
  80. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/event_loop/qt_host.py +0 -0
  81. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/event_loop/run.py +0 -0
  82. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/event_loop/tk_host.py +0 -0
  83. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/interface/__init__.py +0 -0
  84. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/iostream.py +0 -0
  85. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/kernelspec.py +0 -0
  86. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/py.typed +0 -0
  87. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/resources/logo-32x32.png +0 -0
  88. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/resources/logo-64x64.png +0 -0
  89. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/resources/logo-svg.svg +0 -0
  90. {async_kernel-0.14.0 → async_kernel-0.15.0}/src/async_kernel/utils.py +0 -0
  91. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/__init__.py +0 -0
  92. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/conftest.py +0 -0
  93. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/references.py +0 -0
  94. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_comm.py +0 -0
  95. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_command.py +0 -0
  96. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_debugger.py +0 -0
  97. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_enter_kernel.py +0 -0
  98. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_iostream.py +0 -0
  99. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_kernel_subclass.py +0 -0
  100. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_kernelspec.py +0 -0
  101. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_message_spec.py +0 -0
  102. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_typing.py +0 -0
  103. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_utils.py +0 -0
  104. {async_kernel-0.14.0 → async_kernel-0.15.0}/tests/test_zmq_messaging.py +0 -0
  105. {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.14"
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: 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
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() }}
@@ -1,12 +1,9 @@
1
1
  name: Enforce PR label
2
2
 
3
- concurrency:
4
- group: label-${{ github.ref }}
5
- cancel-in-progress: true
6
-
7
3
  on:
8
4
  pull_request:
9
5
  types: [labeled, unlabeled, opened, edited, synchronize]
6
+
10
7
  jobs:
11
8
  enforce-label:
12
9
  runs-on: ubuntu-latest
@@ -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.14.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, VScode, etc).
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, VScode, etc).
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 enables standard functions and coroutines to be called in the event loop of a `asyncio` or `trio` backend. Scheduling is thread-safe, methods that return `Pending` are thread-safe cancellable and awaitable."
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 three caller instances associated with the Kernel:\n",
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).\n",
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). A runtime error will occur if when there is no backend running in the current thread (in Pyodide the main caller is always available)."
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 the instance returned when calling `Caller`.\n",
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. When the backend does not match the callers backend, it is run with the backend running as a guest."
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(asyncio.sleep, 0.01)\n",
495
- " caller.call_later(0, asyncio.sleep, 0)\n",
496
- " caller.to_thread(asyncio.sleep, 0.01)\n",
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 (thread-safe).
16
- - [Pending][async_kernel.pending.Pending] - Represents a pending result that can be set, awaited and cancelled (thread-safe).
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
- # Usage
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/latest/objects.inv
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, LastUpdatedDict
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 [async_kernel.common.LastUpdatedDict][].
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, LastUpdatedDict] = Fixed(LastUpdatedDict) # pyright: ignore[reportIncompatibleVariableOverride]
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
- orjson.dumps(info, option=orjson.OPT_INDENT_2).decode(),
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"