async-kernel 0.20.0__tar.gz → 0.20.2__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 (112) hide show
  1. {async_kernel-0.20.0 → async_kernel-0.20.2}/.github/workflows/ci.yml +4 -4
  2. {async_kernel-0.20.0 → async_kernel-0.20.2}/.github/workflows/new_release.yml +1 -1
  3. {async_kernel-0.20.0 → async_kernel-0.20.2}/.github/workflows/pre-commit.yml +1 -1
  4. {async_kernel-0.20.0 → async_kernel-0.20.2}/.github/workflows/publish-docs.yml +2 -2
  5. {async_kernel-0.20.0 → async_kernel-0.20.2}/.github/workflows/publish-to-pypi.yml +2 -2
  6. {async_kernel-0.20.0 → async_kernel-0.20.2}/.pre-commit-config.yaml +1 -1
  7. {async_kernel-0.20.0 → async_kernel-0.20.2}/CHANGELOG.md +34 -0
  8. {async_kernel-0.20.0 → async_kernel-0.20.2}/PKG-INFO +1 -1
  9. {async_kernel-0.20.0 → async_kernel-0.20.2}/_version.py +2 -2
  10. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/comm.py +9 -8
  11. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/interface/base.py +20 -17
  12. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_encryption.py +1 -0
  13. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_message_spec.py +1 -0
  14. {async_kernel-0.20.0 → async_kernel-0.20.2}/uv.lock +113 -113
  15. {async_kernel-0.20.0 → async_kernel-0.20.2}/.github/dependabot.yaml +0 -0
  16. {async_kernel-0.20.0 → async_kernel-0.20.2}/.github/release.yml +0 -0
  17. {async_kernel-0.20.0 → async_kernel-0.20.2}/.github/workflows/enforce-label.yml +0 -0
  18. {async_kernel-0.20.0 → async_kernel-0.20.2}/.gitignore +0 -0
  19. {async_kernel-0.20.0 → async_kernel-0.20.2}/.vscode/launch.json +0 -0
  20. {async_kernel-0.20.0 → async_kernel-0.20.2}/.vscode/settings.json +0 -0
  21. {async_kernel-0.20.0 → async_kernel-0.20.2}/.vscode/spellright.dict +0 -0
  22. {async_kernel-0.20.0 → async_kernel-0.20.2}/CONTRIBUTING.md +0 -0
  23. {async_kernel-0.20.0 → async_kernel-0.20.2}/IPYTHON_LICENSE +0 -0
  24. {async_kernel-0.20.0 → async_kernel-0.20.2}/LICENSE +0 -0
  25. {async_kernel-0.20.0 → async_kernel-0.20.2}/README.md +0 -0
  26. {async_kernel-0.20.0 → async_kernel-0.20.2}/cliff.toml +0 -0
  27. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/about/changelog.md +0 -0
  28. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/about/contributing.md +0 -0
  29. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/about/index.md +0 -0
  30. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/about/license.md +0 -0
  31. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/index.md +0 -0
  32. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/javascripts/extra.js +0 -0
  33. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/notebooks/caller.ipynb +0 -0
  34. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/notebooks/concurrency.ipynb +0 -0
  35. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/notebooks/custom_kernel.ipynb +0 -0
  36. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/overrides/main.html +0 -0
  37. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/reference/caller.md +0 -0
  38. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/reference/comm.md +0 -0
  39. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/reference/command.md +0 -0
  40. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/reference/common.md +0 -0
  41. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/reference/debugger.md +0 -0
  42. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/reference/event_loop.md +0 -0
  43. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/reference/index.md +0 -0
  44. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/reference/interface.md +0 -0
  45. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/reference/ipshell.md +0 -0
  46. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/reference/kernel.md +0 -0
  47. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/reference/kernelspec.md +0 -0
  48. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/reference/pending.md +0 -0
  49. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/reference/shell.md +0 -0
  50. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/reference/typing.md +0 -0
  51. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/reference/utils.md +0 -0
  52. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/stylesheets/extra.css +0 -0
  53. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/thread_safety.md +0 -0
  54. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/usage/commands.md +0 -0
  55. {async_kernel-0.20.0 → async_kernel-0.20.2}/docs/usage/index.md +0 -0
  56. {async_kernel-0.20.0 → async_kernel-0.20.2}/hatch_build.py +0 -0
  57. {async_kernel-0.20.0 → async_kernel-0.20.2}/mkdocs.yml +0 -0
  58. {async_kernel-0.20.0 → async_kernel-0.20.2}/pyproject.toml +0 -0
  59. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/__init__.py +0 -0
  60. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/__main__.py +0 -0
  61. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/caller.py +0 -0
  62. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/command.py +0 -0
  63. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/common.py +0 -0
  64. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/compat/attr_docs.py +0 -0
  65. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/compat/json.py +0 -0
  66. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/compiler.py +0 -0
  67. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/debugger.py +0 -0
  68. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/event_loop/__init__.py +0 -0
  69. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/event_loop/asyncio_guest.py +0 -0
  70. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/event_loop/qt_host.py +0 -0
  71. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/event_loop/run.py +0 -0
  72. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/event_loop/tk_host.py +0 -0
  73. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/interface/__init__.py +0 -0
  74. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/interface/callable.py +0 -0
  75. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/interface/ip_app.py +0 -0
  76. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/interface/zmq.py +0 -0
  77. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/kernel.py +0 -0
  78. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/kernelspec.py +0 -0
  79. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/pending.py +0 -0
  80. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/py.typed +0 -0
  81. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/resources/logo-32x32.png +0 -0
  82. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/resources/logo-64x64.png +0 -0
  83. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/resources/logo-svg.svg +0 -0
  84. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/shell/__init__.py +0 -0
  85. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/shell/base.py +0 -0
  86. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/shell/ipshell.py +0 -0
  87. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/typing.py +0 -0
  88. {async_kernel-0.20.0 → async_kernel-0.20.2}/src/async_kernel/utils.py +0 -0
  89. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/__init__.py +0 -0
  90. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/conftest.py +0 -0
  91. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/references.py +0 -0
  92. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_base_interface.py +0 -0
  93. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_callable_interface.py +0 -0
  94. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_caller.py +0 -0
  95. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_comm.py +0 -0
  96. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_command.py +0 -0
  97. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_common.py +0 -0
  98. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_compat.py +0 -0
  99. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_debugger.py +0 -0
  100. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_debugger_static.py +0 -0
  101. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_enter_kernel.py +0 -0
  102. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_event_loop.py +0 -0
  103. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_iostream.py +0 -0
  104. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_kernel_ipshell.py +0 -0
  105. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_kernelspec.py +0 -0
  106. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_pending.py +0 -0
  107. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_subclass.py +0 -0
  108. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_typing.py +0 -0
  109. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_utils.py +0 -0
  110. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_zmq_interface.py +0 -0
  111. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/test_zmq_interface_ip.py +0 -0
  112. {async_kernel-0.20.0 → async_kernel-0.20.2}/tests/utils.py +0 -0
@@ -15,7 +15,7 @@ jobs:
15
15
  type-checking:
16
16
  runs-on: ubuntu-latest
17
17
  steps:
18
- - uses: actions/checkout@v6
18
+ - uses: actions/checkout@v7
19
19
  with:
20
20
  fetch-depth: 0
21
21
 
@@ -42,7 +42,7 @@ jobs:
42
42
  - "3.15"
43
43
  steps:
44
44
  - name: Checkout
45
- uses: actions/checkout@v6
45
+ uses: actions/checkout@v7
46
46
 
47
47
  - name: Install uv
48
48
  uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
@@ -82,7 +82,7 @@ jobs:
82
82
  needs: type-checking
83
83
  runs-on: ubuntu-latest
84
84
  steps:
85
- - uses: actions/checkout@v6
85
+ - uses: actions/checkout@v7
86
86
  with:
87
87
  fetch-depth: 0
88
88
 
@@ -111,7 +111,7 @@ jobs:
111
111
  needs: type-checking
112
112
  runs-on: ubuntu-latest
113
113
  steps:
114
- - uses: actions/checkout@v6
114
+ - uses: actions/checkout@v7
115
115
  with:
116
116
  fetch-depth: 0
117
117
 
@@ -26,7 +26,7 @@ jobs:
26
26
  pull-requests: write
27
27
  steps:
28
28
  - name: Checkout
29
- uses: actions/checkout@v6
29
+ uses: actions/checkout@v7
30
30
  with:
31
31
  fetch-depth: 0
32
32
  ref: main
@@ -7,7 +7,7 @@ jobs:
7
7
  name: Pre-commit
8
8
  runs-on: ubuntu-latest
9
9
  steps:
10
- - uses: actions/checkout@v6
10
+ - uses: actions/checkout@v7
11
11
  - uses: actions/setup-python@v6
12
12
  with:
13
13
  python-version: 3.x
@@ -20,7 +20,7 @@ jobs:
20
20
  name: Deploy dev or latest version
21
21
  runs-on: ubuntu-latest
22
22
  steps:
23
- - uses: actions/checkout@v6
23
+ - uses: actions/checkout@v7
24
24
  - name: Configure Git Credentials
25
25
  run: |
26
26
  git config user.name github-actions[bot]
@@ -32,7 +32,7 @@ jobs:
32
32
  version-file: "pyproject.toml"
33
33
 
34
34
  - name: Checkout
35
- uses: actions/checkout@v6
35
+ uses: actions/checkout@v7
36
36
  with:
37
37
  fetch-depth: 0
38
38
 
@@ -25,7 +25,7 @@ jobs:
25
25
  outputs:
26
26
  TAG: ${{ steps.tag_info.outputs.tag }}
27
27
  steps:
28
- - uses: actions/checkout@v6
28
+ - uses: actions/checkout@v7
29
29
  with:
30
30
  persist-credentials: false
31
31
  # Fetch full history for setuptools-scm
@@ -104,7 +104,7 @@ jobs:
104
104
  env:
105
105
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
106
106
  steps:
107
- - uses: actions/checkout@v6
107
+ - uses: actions/checkout@v7
108
108
  with:
109
109
  persist-credentials: false
110
110
  # Fetch full history for setuptools-scm
@@ -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.18
62
+ rev: v0.15.19
63
63
  hooks:
64
64
  - id: ruff-check
65
65
  types_or: [python, jupyter]
@@ -5,6 +5,36 @@ 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.20.2] - 2026-06-29
9
+
10
+ ### <!-- 5 --> 📝 Documentation
11
+
12
+ - Update docstrings for BaseInterface. [#508](https://github.com/fleming79/async-kernel/pull/508)
13
+
14
+ ### <!-- 6 --> 🌀 Miscellaneous
15
+
16
+ - Avoid attribute error in Comm.publish_msg in case the parent is gc before the object. [#511](https://github.com/fleming79/async-kernel/pull/511)
17
+
18
+ - Update uv.lock and pre-commit-config.yaml [#510](https://github.com/fleming79/async-kernel/pull/510)
19
+
20
+ - Add more clear_iopub to tests that use utils.check_pub_message. [#509](https://github.com/fleming79/async-kernel/pull/509)
21
+
22
+ - Swap async_sleep_forever for create_async_waiter in [#507](https://github.com/fleming79/async-kernel/pull/507)
23
+
24
+ - Refactor BaseInterface context and stop. [#506](https://github.com/fleming79/async-kernel/pull/506)
25
+
26
+ ## [0.20.1] - 2026-06-22
27
+
28
+ ### <!-- 2 --> 🐛 Fixes
29
+
30
+ - Use a long sleep in a loop instead of anyio.sleep_forever which returns immediately on pyodide. [#504](https://github.com/fleming79/async-kernel/pull/504)
31
+
32
+ ### <!-- 6 --> 🌀 Miscellaneous
33
+
34
+ - Prepare for release v0.20.1 [#505](https://github.com/fleming79/async-kernel/pull/505)
35
+
36
+ - Bump actions/checkout from 6 to 7 in the actions group [#503](https://github.com/fleming79/async-kernel/pull/503)
37
+
8
38
  ## [0.20.0] - 2026-06-22
9
39
 
10
40
  ### <!-- 0 --> 🏗️ Breaking changes
@@ -25,6 +55,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
25
55
 
26
56
  ### <!-- 6 --> 🌀 Miscellaneous
27
57
 
58
+ - Prepare for release v0.20.0 [#502](https://github.com/fleming79/async-kernel/pull/502)
59
+
28
60
  - Use cancellation for interface shutdown. [#501](https://github.com/fleming79/async-kernel/pull/501)
29
61
 
30
62
  - Use a Countdown event in _start_hb_iopub_shell_control_threads. [#500](https://github.com/fleming79/async-kernel/pull/500)
@@ -1387,6 +1419,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1387
1419
 
1388
1420
  - Bump the actions group across 1 directory with 2 updates [#3](https://github.com/fleming79/async-kernel/pull/3)
1389
1421
 
1422
+ [0.20.2]: https://github.com/fleming79/async-kernel/compare/v0.20.1..v0.20.2
1423
+ [0.20.1]: https://github.com/fleming79/async-kernel/compare/v0.20.0..v0.20.1
1390
1424
  [0.20.0]: https://github.com/fleming79/async-kernel/compare/v0.19.2..v0.20.0
1391
1425
  [0.19.2]: https://github.com/fleming79/async-kernel/compare/v0.19.1..v0.19.2
1392
1426
  [0.19.1]: https://github.com/fleming79/async-kernel/compare/v0.19.0..v0.19.1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: async-kernel
3
- Version: 0.20.0
3
+ Version: 0.20.2
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.20.0'
22
- __version_tuple__ = version_tuple = (0, 20, 0)
21
+ __version__ = version = '0.20.2'
22
+ __version_tuple__ = version_tuple = (0, 20, 2)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -34,14 +34,15 @@ class Comm(HasInterface, BaseComm):
34
34
  ) -> None:
35
35
  """Helper for sending a comm message on IOPub."""
36
36
  content = {"data": {} if data is None else data, "comm_id": self.comm_id} | keys
37
- self.parent.iopub_send(
38
- msg_or_type=msg_type,
39
- content=content,
40
- metadata=metadata,
41
- parent=None,
42
- ident=self.topic,
43
- buffers=buffers,
44
- )
37
+ if parent := self.parent:
38
+ parent.iopub_send(
39
+ msg_or_type=msg_type,
40
+ content=content,
41
+ metadata=metadata,
42
+ parent=None,
43
+ ident=self.topic,
44
+ buffers=buffers,
45
+ )
45
46
 
46
47
  @override
47
48
  def handle_msg(self, msg: comm.base_comm.MessageType) -> None:
@@ -14,7 +14,7 @@ from typing import TYPE_CHECKING, Any, Generic, Literal, Self, final
14
14
  from uuid import uuid4
15
15
 
16
16
  import anyio
17
- from aiologic.lowlevel import AsyncLibraryNotFoundError, current_async_library
17
+ from aiologic.lowlevel import AsyncLibraryNotFoundError, async_sleep_forever, current_async_library
18
18
  from traitlets import traitlets
19
19
  from traitlets.config import Config, Configurable
20
20
  from traitlets.config.application import Application, ClassesType
@@ -32,6 +32,7 @@ from async_kernel.typing import (
32
32
  Hosts,
33
33
  Message,
34
34
  MsgHeader,
35
+ MsgType,
35
36
  NoValue,
36
37
  RunSettings,
37
38
  T,
@@ -82,10 +83,12 @@ class DictValueLiteralEval(traitlets.Dict):
82
83
 
83
84
  class BaseInterface(Application, anyio.AsyncContextManagerMixin, Generic[T_shell_co]):
84
85
  """
85
- The base class for a singleton kernel interface.
86
+ The base class for kernel interface (singleton).
86
87
 
87
- This singleton provides configuration and convenient references to other objects.
88
- This is where kerenels should be launched f
88
+ The interface creates the kernel and provides external communication. It is also
89
+ the parent object for all objects that subclass from `HasInterface`. Configurable
90
+ objects that subclass from `HasInterface` inherit their configuration from the
91
+ interface (Application).
89
92
 
90
93
  Usage:
91
94
  launch:
@@ -95,6 +98,7 @@ class BaseInterface(Application, anyio.AsyncContextManagerMixin, Generic[T_shell
95
98
  async context:
96
99
  ```python
97
100
  async with Interface() as interface:
101
+ interface.kernel
98
102
  ...
99
103
  ```
100
104
  """
@@ -304,7 +308,8 @@ class BaseInterface(Application, anyio.AsyncContextManagerMixin, Generic[T_shell
304
308
 
305
309
  Warning:
306
310
  - Running in a thread other than the 'MainThread' is permitted, but discouraged.
307
- - Blocking calls can only be interrupted in the 'MainThread' because [*'threads cannot be destroyed, stopped, suspended, resumed, or interrupted'*](https://docs.python.org/3/library/threading.html#module-threading).
311
+ - Blocking calls can only be interrupted in the 'MainThread' because
312
+ [*'threads cannot be destroyed, stopped, suspended, resumed, or interrupted'*](https://docs.python.org/3/library/threading.html#module-threading).
308
313
  - Some libraries may assume the call is occurring in the 'MainThread'.
309
314
  - If there is an `asyncio` or `trio` event loop already running in the desired thread;
310
315
  start asynchronously instead (`async with interface: ...`).
@@ -353,7 +358,12 @@ class BaseInterface(Application, anyio.AsyncContextManagerMixin, Generic[T_shell
353
358
  try:
354
359
  async with caller:
355
360
  with anyio.CancelScope() as scope:
356
- self._scope = scope
361
+
362
+ def stop(_):
363
+ self.log.info("Stopping kernel")
364
+ caller.call_later(0.5, scope.cancel, "Stopping kernel")
365
+
366
+ self.stopping.add_done_callback(stop)
357
367
  try:
358
368
  async with self.kernel.running():
359
369
  if set_started:
@@ -381,20 +391,17 @@ class BaseInterface(Application, anyio.AsyncContextManagerMixin, Generic[T_shell
381
391
  """
382
392
  try:
383
393
  async with self:
384
- await anyio.sleep_forever()
394
+ # Wait forever. This will exit when stop is called.
395
+ await async_sleep_forever()
385
396
  finally:
386
397
  if stopped:
387
398
  stopped()
388
399
 
389
400
  def stop(self) -> None:
390
401
  """
391
- Stop the kernel.
402
+ Stop the kernel and this interface.
392
403
  """
393
404
  self.stopping.set_result(None)
394
- if scope := getattr(self, "_scope", None):
395
- del self._scope
396
- self.log.info("Stopping kernel")
397
- self.callers[Channel.shell].call_later(0.5, scope.cancel, "Stopping kernel")
398
405
  if not self.started.done():
399
406
  self.started.cancel("Stopped early")
400
407
  if BaseInterface._instance is self:
@@ -412,7 +419,7 @@ class BaseInterface(Application, anyio.AsyncContextManagerMixin, Generic[T_shell
412
419
 
413
420
  def msg(
414
421
  self,
415
- msg_type: str,
422
+ msg_type: str | MsgType,
416
423
  *,
417
424
  content: T | None = None,
418
425
  parent: Message | dict[str, Any] | None = None,
@@ -422,10 +429,6 @@ class BaseInterface(Application, anyio.AsyncContextManagerMixin, Generic[T_shell
422
429
  ) -> Message[T]:
423
430
  """
424
431
  Create a new message.
425
-
426
- This format is different from what is sent over the wire. The
427
- serialize/deserialize methods converts this nested message dict to the wire
428
- format, which is a list of message parts.
429
432
  """
430
433
  parent = parent or utils.get_parent_message()
431
434
  if header is None:
@@ -17,6 +17,7 @@ def encryption(request):
17
17
 
18
18
  async def test_curve_encryption(subprocess_kernels_client: AsyncKernelClient, encryption: str):
19
19
  client = subprocess_kernels_client
20
+ await utils.clear_iopub(client)
20
21
  if encryption == "curve":
21
22
  assert client.curve_publickey
22
23
  assert client.curve_secretkey
@@ -23,6 +23,7 @@ async def test_execute(client: AsyncKernelClient, kernel: Kernel):
23
23
 
24
24
 
25
25
  async def test_execute_suppress(client: AsyncKernelClient, kernel: Kernel):
26
+ await utils.clear_iopub(client)
26
27
  for mode in ["normal", "suppress"]:
27
28
  msg_id = client.execute(code="123" if mode == "normal" else "123;")
28
29
  reply = await utils.get_reply(client, msg_id, clear_pub=False)