async-kernel 0.22.1__tar.gz → 0.22.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 (119) hide show
  1. {async_kernel-0.22.1 → async_kernel-0.22.2}/CHANGELOG.md +18 -1
  2. {async_kernel-0.22.1 → async_kernel-0.22.2}/PKG-INFO +1 -1
  3. {async_kernel-0.22.1 → async_kernel-0.22.2}/_version.py +2 -2
  4. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/caller.py +4 -4
  5. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/event_loop/zmq_poll.py +9 -6
  6. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/interface/base.py +12 -9
  7. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/messaging/zmq.py +15 -10
  8. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/utils.py +8 -2
  9. {async_kernel-0.22.1 → async_kernel-0.22.2}/.github/dependabot.yaml +0 -0
  10. {async_kernel-0.22.1 → async_kernel-0.22.2}/.github/release.yml +0 -0
  11. {async_kernel-0.22.1 → async_kernel-0.22.2}/.github/workflows/ci.yml +0 -0
  12. {async_kernel-0.22.1 → async_kernel-0.22.2}/.github/workflows/enforce-label.yml +0 -0
  13. {async_kernel-0.22.1 → async_kernel-0.22.2}/.github/workflows/new_release.yml +0 -0
  14. {async_kernel-0.22.1 → async_kernel-0.22.2}/.github/workflows/pre-commit.yml +0 -0
  15. {async_kernel-0.22.1 → async_kernel-0.22.2}/.github/workflows/publish-docs.yml +0 -0
  16. {async_kernel-0.22.1 → async_kernel-0.22.2}/.github/workflows/publish-to-pypi.yml +0 -0
  17. {async_kernel-0.22.1 → async_kernel-0.22.2}/.gitignore +0 -0
  18. {async_kernel-0.22.1 → async_kernel-0.22.2}/.pre-commit-config.yaml +0 -0
  19. {async_kernel-0.22.1 → async_kernel-0.22.2}/.vscode/launch.json +0 -0
  20. {async_kernel-0.22.1 → async_kernel-0.22.2}/.vscode/settings.json +0 -0
  21. {async_kernel-0.22.1 → async_kernel-0.22.2}/.vscode/spellright.dict +0 -0
  22. {async_kernel-0.22.1 → async_kernel-0.22.2}/CONTRIBUTING.md +0 -0
  23. {async_kernel-0.22.1 → async_kernel-0.22.2}/IPYTHON_LICENSE +0 -0
  24. {async_kernel-0.22.1 → async_kernel-0.22.2}/LICENSE +0 -0
  25. {async_kernel-0.22.1 → async_kernel-0.22.2}/README.md +0 -0
  26. {async_kernel-0.22.1 → async_kernel-0.22.2}/cliff.toml +0 -0
  27. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/about/changelog.md +0 -0
  28. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/about/contributing.md +0 -0
  29. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/about/index.md +0 -0
  30. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/about/license.md +0 -0
  31. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/index.md +0 -0
  32. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/javascripts/extra.js +0 -0
  33. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/notebooks/caller.ipynb +0 -0
  34. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/notebooks/concurrency.ipynb +0 -0
  35. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/notebooks/custom_kernel.ipynb +0 -0
  36. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/overrides/main.html +0 -0
  37. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/reference/caller.md +0 -0
  38. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/reference/comm.md +0 -0
  39. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/reference/command.md +0 -0
  40. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/reference/common.md +0 -0
  41. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/reference/debugger.md +0 -0
  42. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/reference/event_loop.md +0 -0
  43. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/reference/index.md +0 -0
  44. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/reference/interface.md +0 -0
  45. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/reference/ipshell.md +0 -0
  46. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/reference/kernel.md +0 -0
  47. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/reference/kernelspec.md +0 -0
  48. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/reference/messaging.md +0 -0
  49. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/reference/pending.md +0 -0
  50. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/reference/shell.md +0 -0
  51. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/reference/typing.md +0 -0
  52. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/reference/utils.md +0 -0
  53. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/stylesheets/extra.css +0 -0
  54. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/thread_safety.md +0 -0
  55. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/usage/commands.md +0 -0
  56. {async_kernel-0.22.1 → async_kernel-0.22.2}/docs/usage/index.md +0 -0
  57. {async_kernel-0.22.1 → async_kernel-0.22.2}/hatch_build.py +0 -0
  58. {async_kernel-0.22.1 → async_kernel-0.22.2}/mkdocs.yml +0 -0
  59. {async_kernel-0.22.1 → async_kernel-0.22.2}/pyproject.toml +0 -0
  60. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/__init__.py +0 -0
  61. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/__main__.py +0 -0
  62. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/comm.py +0 -0
  63. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/command.py +0 -0
  64. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/common.py +0 -0
  65. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/compat/attr_docs.py +0 -0
  66. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/compat/json.py +0 -0
  67. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/compiler.py +0 -0
  68. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/debugger.py +0 -0
  69. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/event_loop/__init__.py +0 -0
  70. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/event_loop/asyncio_guest.py +0 -0
  71. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/event_loop/qt_host.py +0 -0
  72. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/event_loop/run.py +0 -0
  73. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/event_loop/tk_host.py +0 -0
  74. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/interface/__init__.py +0 -0
  75. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/interface/callable.py +0 -0
  76. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/interface/ip_app.py +0 -0
  77. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/kernel.py +0 -0
  78. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/kernelspec.py +0 -0
  79. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/messaging/__init__.py +0 -0
  80. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/messaging/base.py +0 -0
  81. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/outstream.py +0 -0
  82. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/pending.py +0 -0
  83. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/py.typed +0 -0
  84. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/resources/logo-32x32.png +0 -0
  85. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/resources/logo-64x64.png +0 -0
  86. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/resources/logo-svg.svg +0 -0
  87. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/shell/__init__.py +0 -0
  88. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/shell/base.py +0 -0
  89. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/shell/ipshell.py +0 -0
  90. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/typing.py +0 -0
  91. {async_kernel-0.22.1 → async_kernel-0.22.2}/src/async_kernel/utils.py +0 -0
  92. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/__init__.py +0 -0
  93. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/conftest.py +0 -0
  94. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/references.py +0 -0
  95. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_callable_interface.py +0 -0
  96. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_caller.py +0 -0
  97. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_comm.py +0 -0
  98. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_command.py +0 -0
  99. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_common.py +0 -0
  100. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_compat.py +0 -0
  101. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_connection.py +0 -0
  102. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_debugger.py +0 -0
  103. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_debugger_static.py +0 -0
  104. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_enter_kernel.py +0 -0
  105. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_event_loop.py +0 -0
  106. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_eventloop_zmq_poll.py +0 -0
  107. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_interface.py +0 -0
  108. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_ipapp.py +0 -0
  109. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_kernel_ipshell.py +0 -0
  110. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_kernelspec.py +0 -0
  111. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_message_spec.py +0 -0
  112. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_outstream.py +0 -0
  113. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_pending.py +0 -0
  114. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_subclass.py +0 -0
  115. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_typing.py +0 -0
  116. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_utils.py +0 -0
  117. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_zmq_connection.py +0 -0
  118. {async_kernel-0.22.1 → async_kernel-0.22.2}/tests/test_zmq_subprocess.py +0 -0
  119. {async_kernel-0.22.1 → async_kernel-0.22.2}/uv.lock +0 -0
@@ -5,7 +5,21 @@ 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.22.1] - 2026-08-18
8
+ ## [0.22.2] - 2026-08-21
9
+
10
+ ### <!-- 1 --> 🚀 Features
11
+
12
+ - ZMQPoll._wake minor optimization. [#574](https://github.com/fleming79/async-kernel/pull/574)
13
+
14
+ - Replace BinarySemaphore with threading.Lock for faster performance in heavily used places. [#571](https://github.com/fleming79/async-kernel/pull/571)
15
+
16
+ ### <!-- 6 --> 🌀 Miscellaneous
17
+
18
+ - Tweak Interface startup sequence. [#573](https://github.com/fleming79/async-kernel/pull/573)
19
+
20
+ - Alan Fleming Refactor ZMQConnection to send the welcome message directly. [#572](https://github.com/fleming79/async-kernel/pull/572)
21
+
22
+ ## [0.22.1] - 2026-08-19
9
23
 
10
24
  ### <!-- 0 --> 🏗️ Breaking changes
11
25
 
@@ -17,6 +31,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
17
31
 
18
32
  ### <!-- 6 --> 🌀 Miscellaneous
19
33
 
34
+ - Prepare for release v0.22.1 [#570](https://github.com/fleming79/async-kernel/pull/570)
35
+
20
36
  - Refactor create_interface_messge_callback_handler to only use one connection [#569](https://github.com/fleming79/async-kernel/pull/569)
21
37
 
22
38
  ## [0.22.0] - 2026-08-17
@@ -1545,6 +1561,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1545
1561
 
1546
1562
  - Bump the actions group across 1 directory with 2 updates [#3](https://github.com/fleming79/async-kernel/pull/3)
1547
1563
 
1564
+ [0.22.2]: https://github.com/fleming79/async-kernel/compare/v0.22.1..v0.22.2
1548
1565
  [0.22.1]: https://github.com/fleming79/async-kernel/compare/v0.22.0..v0.22.1
1549
1566
  [0.22.0]: https://github.com/fleming79/async-kernel/compare/v0.21.0..v0.22.0
1550
1567
  [0.21.0]: https://github.com/fleming79/async-kernel/compare/v0.20.2..v0.21.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: async-kernel
3
- Version: 0.22.1
3
+ Version: 0.22.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.22.1'
22
- __version_tuple__ = version_tuple = (0, 22, 1)
21
+ __version__ = version = '0.22.2'
22
+ __version_tuple__ = version_tuple = (0, 22, 2)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -19,7 +19,7 @@ from typing import TYPE_CHECKING, Any, ClassVar, Concatenate, Generic, Literal,
19
19
  from weakref import ReferenceType
20
20
 
21
21
  import anyio
22
- from aiologic import BinarySemaphore, CountdownEvent
22
+ from aiologic import CountdownEvent
23
23
  from aiologic.lowlevel import async_checkpoint, create_async_event, current_async_library
24
24
  from aiologic.meta import await_for, iscoroutinelike
25
25
  from typing_extensions import override
@@ -191,7 +191,7 @@ class Caller:
191
191
 
192
192
  _caller_token = contextvars.ContextVar("caller_tokens", default=CALLER_MAIN_THREAD_ID)
193
193
  _instances: ClassVar[weakref.WeakValueDictionary[int, Self]] = weakref.WeakValueDictionary()
194
- _lock: ClassVar = BinarySemaphore()
194
+ _lock: ClassVar = threading.Lock()
195
195
 
196
196
  _thread: threading.Thread
197
197
  _caller_id: int
@@ -219,7 +219,7 @@ class Caller:
219
219
  _worker_pool: Fixed[Self, deque[Self]] = Fixed(deque)
220
220
 
221
221
  # Private
222
- _inst_lock: BinarySemaphore
222
+ _inst_lock: threading.Lock
223
223
  _children: set[Self]
224
224
  _tasks: set[asyncio.Task]
225
225
  _queue_map: dict[int, Pending]
@@ -394,7 +394,7 @@ class Caller:
394
394
  thread = threading.current_thread()
395
395
 
396
396
  # Add private objects
397
- inst._inst_lock = BinarySemaphore()
397
+ inst._inst_lock = threading.Lock()
398
398
  inst._children = set()
399
399
  inst._tasks = set()
400
400
  inst._queue_map = {}
@@ -41,7 +41,7 @@ class ZMQPollSocket(zmq.sugar.Socket[bytes]):
41
41
  """
42
42
 
43
43
  _zmq_poll_ref: weakref.ref[ZMQPoll]
44
- lock: BinarySemaphore
44
+ lock: threading.Lock
45
45
 
46
46
  if TYPE_CHECKING:
47
47
  # magic attributes cannot be be stored in `__annotations__`.
@@ -68,7 +68,7 @@ class ZMQPollSocket(zmq.sugar.Socket[bytes]):
68
68
  zmq_poll: ZMQPoll,
69
69
  copy_threshold: int | None = None,
70
70
  ) -> None:
71
- self.lock = BinarySemaphore()
71
+ self.lock = threading.Lock()
72
72
  self._zmq_poll_ref = weakref.ref(zmq_poll)
73
73
 
74
74
  if zmq_poll.stopped.done():
@@ -99,10 +99,13 @@ class ZMQPollSocket(zmq.sugar.Socket[bytes]):
99
99
  track: bool = False,
100
100
  **kwargs,
101
101
  ) -> MessageTracker | None:
102
- with self.lock:
102
+ self.lock.acquire()
103
+ try:
103
104
  if self.closed:
104
105
  return None
105
106
  return super().send_multipart(msg_parts, flags, copy, track)
107
+ finally:
108
+ self.lock.release()
106
109
 
107
110
  @override
108
111
  def close(self, linger=None) -> None:
@@ -189,7 +192,6 @@ class ZMQPoll:
189
192
  self._handlers: dict[T_key, Callable[[ZMQPollSocket, int], Any]] = {}
190
193
  self._count: dict[T_key, tuple[int, Callable[[], Any]] | None] = {}
191
194
  self._execute: deque[Pending] = deque[Pending[Any]]()
192
- self._not_started = False
193
195
  self.log = logging.LoggerAdapter(logging.getLogger())
194
196
  self._cancellers = deque()
195
197
  self._ctx_count = 0
@@ -321,8 +323,9 @@ class ZMQPoll:
321
323
  send = started.wait_sync()
322
324
 
323
325
  def _wake(sock=send, lock=send.lock) -> None:
324
- with lock:
325
- sock.send(b"")
326
+ lock.acquire()
327
+ sock.send(b"")
328
+ lock.release()
326
329
 
327
330
  self._wake = _wake
328
331
  self.stopped.add_done_callback(lambda _: (self := ref()) and self._on_stopped())
@@ -12,7 +12,7 @@ import weakref
12
12
  from typing import TYPE_CHECKING, Any, Generic, Literal, Self, final
13
13
 
14
14
  from aiologic import BinarySemaphore
15
- from aiologic.lowlevel import AsyncLibraryNotFoundError, current_async_library
15
+ from aiologic.lowlevel import AsyncLibraryNotFoundError, async_checkpoint, current_async_library
16
16
  from traitlets import import_item, traitlets
17
17
  from traitlets.config import Config, Configurable
18
18
  from traitlets.config.application import Application, ClassesType
@@ -395,19 +395,22 @@ class Interface(StartStopTask, Application, Generic[T_shell_co]):
395
395
  await self._pre_start()
396
396
  self.log.info("Interface started: %s", self.summary)
397
397
  started()
398
- del started
398
+ # Allow connections to react to being started.
399
+ await async_checkpoint(force=True)
400
+ # Send iopub messages captured during startup.
401
+ del started, self.iopub_send
402
+ while self._iopub_cache:
403
+ self._iopub_cache.reverse()
404
+ args, kwargs = self._iopub_cache.pop()
405
+ self.iopub_send(*args, **kwargs)
399
406
  await stop
400
407
 
401
408
  async def _pre_start(self) -> None:
402
- """Opens the kernel, starts autostart connections and releases iopub messages."""
409
+ """Perform tasks just prior to setting as started."""
410
+ # Autostart connections waiting until they have started.
403
411
  if pending := [import_item(pth)().start().started for pth in self.autostart_connections]:
404
412
  self.log.info("Waiting for connections to establish %d", len(pending))
405
- await self.caller.wait(pending)
406
- del self.iopub_send
407
- while self._iopub_cache:
408
- self._iopub_cache.reverse()
409
- args, kwargs = self._iopub_cache.pop()
410
- self.iopub_send(*args, **kwargs)
413
+ await self.caller.wait(pending)
411
414
 
412
415
  def update_connections(self, *new: Connection[Self]) -> None:
413
416
  """Update the list of connections.
@@ -158,8 +158,8 @@ class ZMQConnection(ZMQMessage, Connection[T_interface_co], Generic[T_interface_
158
158
  msg = socket.recv()
159
159
  if msg[0] == 1:
160
160
  ident = msg[1:]
161
- # Note: The welcome message is cached until parent._started is called.
162
- self.parent.iopub_send(MsgType.iopub_welcome, content={"subscription": ident.decode()}, ident=ident)
161
+ msg = self.msg(MsgType.iopub_welcome, {"subscription": ident.decode()}, Channel.iopub)
162
+ self.session.send(socket, msg, ident=[ident]) # pyright: ignore[reportArgumentType]
163
163
 
164
164
  def handler(sock, event, channel: Channel, recv=self.session.recv, handle_msg=self.handle_incoming_msg) -> None:
165
165
  # Thread: zmq_poll_thread
@@ -169,6 +169,9 @@ class ZMQConnection(ZMQMessage, Connection[T_interface_co], Generic[T_interface_
169
169
 
170
170
  with self.zmq_poll as zpoll:
171
171
  await self._bind_sockets()
172
+ self.parent.update_connections(self)
173
+ started()
174
+ await self.parent.started
172
175
  with (
173
176
  zpoll.event_handler(self._sockets[Channel.control], partial(handler, channel=Channel.control)),
174
177
  zpoll.event_handler(self._sockets[Channel.shell], functools.partial(handler, channel=Channel.shell)),
@@ -176,7 +179,8 @@ class ZMQConnection(ZMQMessage, Connection[T_interface_co], Generic[T_interface_
176
179
  zpoll.event_handler(self._sockets[Channel.heartbeat], heartbeat_handler),
177
180
  zpoll.event_handler(self._sockets[Channel.iopub], iopub_reg_handler),
178
181
  ):
179
- await super().connection_task(started, stop)
182
+ await stop
183
+ self.parent.update_connections()
180
184
 
181
185
  async def _bind_sockets(self):
182
186
  """Create, configure and bind all sockets."""
@@ -395,7 +399,7 @@ class ZMQClient(BaseClient[T_interface_co], ZMQMessage, Generic[T_interface_co])
395
399
  @asynccontextmanager
396
400
  @override
397
401
  async def iopub_subscribe(
398
- self, topic=b"", *, timeout: float | None = 1.0
402
+ self, topic=b"", *, timeout: float | None = 10.0
399
403
  ) -> AsyncGenerator[SingleAsyncQueue[Message]]:
400
404
 
401
405
  def forward_messages(sock: ZMQPollSocket, event: int) -> None:
@@ -414,10 +418,11 @@ class ZMQClient(BaseClient[T_interface_co], ZMQMessage, Generic[T_interface_co])
414
418
  iopub = await self._connect_socket(Channel.iopub)
415
419
  with iopub, self.zmq_poll.event_handler(iopub, forward_messages, canceller=canceller), scope:
416
420
  iopub.subscribe(topic)
417
- self.log.debug("Waiting for welcome message.")
418
- if await ready.with_(timeout=timeout):
419
- self.log.debug("Welcome message received.")
420
- else:
421
- msg = f"Welcome message not received after {timeout:0.1f}s!"
422
- raise TimeoutError(msg)
421
+ if timeout is not None:
422
+ self.log.debug("Waiting for welcome message.")
423
+ if await ready.with_(timeout=timeout):
424
+ self.log.debug("Welcome message received.")
425
+ else:
426
+ msg = f"Welcome message not received after {timeout:0.1f}s!"
427
+ raise TimeoutError(msg)
423
428
  yield queue
@@ -4,6 +4,7 @@ import importlib.util
4
4
  import os
5
5
  from typing import TYPE_CHECKING, Any
6
6
 
7
+ import anyio
7
8
  import pytest
8
9
 
9
10
  import async_kernel.utils
@@ -66,8 +67,13 @@ async def read_until_msg_type(reader: AsyncGenerator, msg_type: IOPubMsgTypeAlia
66
67
  Args:
67
68
  reader: An async iterator for a queue returned from iopub subscribe.
68
69
  msg_type: The type of iopub message to wait for."""
69
- while (msg := await anext(reader))["header"]["msg_type"] != msg_type:
70
- continue
70
+ try:
71
+ with anyio.fail_after(TIMEOUT):
72
+ while (msg := await anext(reader))["header"]["msg_type"] != msg_type:
73
+ continue
74
+ except TimeoutError as e:
75
+ msg_ = f"Timeout waiting for {msg_type=} {content_checks=}"
76
+ raise TimeoutError(msg_) from e
71
77
  check_pub_message(msg, msg_type=msg_type, **content_checks)
72
78
  return msg
73
79
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes