async-kernel 0.18.0__tar.gz → 0.18.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 (105) hide show
  1. {async_kernel-0.18.0 → async_kernel-0.18.2}/CHANGELOG.md +24 -0
  2. {async_kernel-0.18.0 → async_kernel-0.18.2}/PKG-INFO +1 -1
  3. {async_kernel-0.18.0 → async_kernel-0.18.2}/_version.py +2 -2
  4. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/caller.py +5 -3
  5. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/interface/base.py +2 -1
  6. async_kernel-0.18.2/src/async_kernel/iostream.py +61 -0
  7. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/utils.py +2 -2
  8. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/test_caller.py +3 -3
  9. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/test_iostream.py +2 -1
  10. async_kernel-0.18.0/src/async_kernel/iostream.py +0 -69
  11. {async_kernel-0.18.0 → async_kernel-0.18.2}/.github/dependabot.yaml +0 -0
  12. {async_kernel-0.18.0 → async_kernel-0.18.2}/.github/release.yml +0 -0
  13. {async_kernel-0.18.0 → async_kernel-0.18.2}/.github/workflows/ci.yml +0 -0
  14. {async_kernel-0.18.0 → async_kernel-0.18.2}/.github/workflows/enforce-label.yml +0 -0
  15. {async_kernel-0.18.0 → async_kernel-0.18.2}/.github/workflows/new_release.yml +0 -0
  16. {async_kernel-0.18.0 → async_kernel-0.18.2}/.github/workflows/pre-commit.yml +0 -0
  17. {async_kernel-0.18.0 → async_kernel-0.18.2}/.github/workflows/publish-docs.yml +0 -0
  18. {async_kernel-0.18.0 → async_kernel-0.18.2}/.github/workflows/publish-to-pypi.yml +0 -0
  19. {async_kernel-0.18.0 → async_kernel-0.18.2}/.gitignore +0 -0
  20. {async_kernel-0.18.0 → async_kernel-0.18.2}/.pre-commit-config.yaml +0 -0
  21. {async_kernel-0.18.0 → async_kernel-0.18.2}/.vscode/launch.json +0 -0
  22. {async_kernel-0.18.0 → async_kernel-0.18.2}/.vscode/settings.json +0 -0
  23. {async_kernel-0.18.0 → async_kernel-0.18.2}/.vscode/spellright.dict +0 -0
  24. {async_kernel-0.18.0 → async_kernel-0.18.2}/CONTRIBUTING.md +0 -0
  25. {async_kernel-0.18.0 → async_kernel-0.18.2}/IPYTHON_LICENSE +0 -0
  26. {async_kernel-0.18.0 → async_kernel-0.18.2}/LICENSE +0 -0
  27. {async_kernel-0.18.0 → async_kernel-0.18.2}/README.md +0 -0
  28. {async_kernel-0.18.0 → async_kernel-0.18.2}/cliff.toml +0 -0
  29. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/about/changelog.md +0 -0
  30. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/about/contributing.md +0 -0
  31. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/about/index.md +0 -0
  32. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/about/license.md +0 -0
  33. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/index.md +0 -0
  34. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/javascripts/extra.js +0 -0
  35. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/notebooks/caller.ipynb +0 -0
  36. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/notebooks/concurrency.ipynb +0 -0
  37. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/notebooks/custom_kernel.ipynb +0 -0
  38. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/overrides/main.html +0 -0
  39. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/reference/asyncshell.md +0 -0
  40. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/reference/caller.md +0 -0
  41. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/reference/comm.md +0 -0
  42. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/reference/command.md +0 -0
  43. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/reference/common.md +0 -0
  44. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/reference/debugger.md +0 -0
  45. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/reference/event_loop.md +0 -0
  46. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/reference/index.md +0 -0
  47. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/reference/interface.md +0 -0
  48. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/reference/kernel.md +0 -0
  49. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/reference/kernelspec.md +0 -0
  50. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/reference/pending.md +0 -0
  51. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/reference/typing.md +0 -0
  52. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/reference/utils.md +0 -0
  53. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/stylesheets/extra.css +0 -0
  54. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/thread_safety.md +0 -0
  55. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/usage/commands.md +0 -0
  56. {async_kernel-0.18.0 → async_kernel-0.18.2}/docs/usage/index.md +0 -0
  57. {async_kernel-0.18.0 → async_kernel-0.18.2}/hatch_build.py +0 -0
  58. {async_kernel-0.18.0 → async_kernel-0.18.2}/mkdocs.yml +0 -0
  59. {async_kernel-0.18.0 → async_kernel-0.18.2}/pyproject.toml +0 -0
  60. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/__init__.py +0 -0
  61. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/__main__.py +0 -0
  62. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/asyncshell.py +0 -0
  63. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/comm.py +0 -0
  64. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/command.py +0 -0
  65. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/common.py +0 -0
  66. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/compat/json.py +0 -0
  67. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/compiler.py +0 -0
  68. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/debugger.py +0 -0
  69. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/event_loop/__init__.py +0 -0
  70. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/event_loop/asyncio_guest.py +0 -0
  71. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/event_loop/qt_host.py +0 -0
  72. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/event_loop/run.py +0 -0
  73. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/event_loop/tk_host.py +0 -0
  74. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/interface/__init__.py +0 -0
  75. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/interface/callable.py +0 -0
  76. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/interface/zmq.py +0 -0
  77. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/kernel.py +0 -0
  78. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/kernelspec.py +0 -0
  79. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/pending.py +0 -0
  80. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/py.typed +0 -0
  81. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/resources/logo-32x32.png +0 -0
  82. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/resources/logo-64x64.png +0 -0
  83. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/resources/logo-svg.svg +0 -0
  84. {async_kernel-0.18.0 → async_kernel-0.18.2}/src/async_kernel/typing.py +0 -0
  85. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/__init__.py +0 -0
  86. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/conftest.py +0 -0
  87. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/references.py +0 -0
  88. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/test_callable_kernel_interface.py +0 -0
  89. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/test_comm.py +0 -0
  90. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/test_command.py +0 -0
  91. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/test_common.py +0 -0
  92. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/test_compat.py +0 -0
  93. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/test_debugger.py +0 -0
  94. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/test_enter_kernel.py +0 -0
  95. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/test_event_loop.py +0 -0
  96. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/test_kernel.py +0 -0
  97. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/test_kernel_subclass.py +0 -0
  98. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/test_kernelspec.py +0 -0
  99. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/test_message_spec.py +0 -0
  100. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/test_pending.py +0 -0
  101. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/test_typing.py +0 -0
  102. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/test_utils.py +0 -0
  103. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/test_zmq_messaging.py +0 -0
  104. {async_kernel-0.18.0 → async_kernel-0.18.2}/tests/utils.py +0 -0
  105. {async_kernel-0.18.0 → async_kernel-0.18.2}/uv.lock +0 -0
@@ -5,6 +5,26 @@ 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.18.2] - 2026-05-03
9
+
10
+ ### <!-- 2 --> 🐛 Fixes
11
+
12
+ - Fix Caller.call_later not sleeping correctly. [#454](https://github.com/fleming79/async-kernel/pull/454)
13
+
14
+ ## [0.18.1] - 2026-04-26
15
+
16
+ ### <!-- 2 --> 🐛 Fixes
17
+
18
+ - Refactor OutStream and fix utils.redirect_stderr. [#450](https://github.com/fleming79/async-kernel/pull/450)
19
+
20
+ ### <!-- 6 --> 🌀 Miscellaneous
21
+
22
+ - Prepare for release v0.18.1 [#453](https://github.com/fleming79/async-kernel/pull/453)
23
+
24
+ - Check trio is available early when creating a Caller for a trio backend. [#452](https://github.com/fleming79/async-kernel/pull/452)
25
+
26
+ - Remove unnecessary line. [#451](https://github.com/fleming79/async-kernel/pull/451)
27
+
8
28
  ## [0.18.0] - 2026-04-25
9
29
 
10
30
  ### <!-- 0 --> 🏗️ Breaking changes
@@ -27,6 +47,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
27
47
 
28
48
  ### <!-- 6 --> 🌀 Miscellaneous
29
49
 
50
+ - Prepare for release v0.18.0 [#449](https://github.com/fleming79/async-kernel/pull/449)
51
+
30
52
  - Refactor AsyncInteractiveShell.shell method [#448](https://github.com/fleming79/async-kernel/pull/448)
31
53
 
32
54
  - Refactor Caller.as_completed. [#447](https://github.com/fleming79/async-kernel/pull/447)
@@ -1251,6 +1273,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1251
1273
 
1252
1274
  - Bump the actions group across 1 directory with 2 updates [#3](https://github.com/fleming79/async-kernel/pull/3)
1253
1275
 
1276
+ [0.18.2]: https://github.com/fleming79/async-kernel/compare/v0.18.1..v0.18.2
1277
+ [0.18.1]: https://github.com/fleming79/async-kernel/compare/v0.18.0..v0.18.1
1254
1278
  [0.18.0]: https://github.com/fleming79/async-kernel/compare/v0.17.1..v0.18.0
1255
1279
  [0.17.1]: https://github.com/fleming79/async-kernel/compare/v0.17.0..v0.17.1
1256
1280
  [0.17.0]: https://github.com/fleming79/async-kernel/compare/v0.16.4..v0.17.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: async-kernel
3
- Version: 0.18.0
3
+ Version: 0.18.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.18.0'
22
- __version_tuple__ = version_tuple = (0, 18, 0)
21
+ __version__ = version = '0.18.2'
22
+ __version_tuple__ = version_tuple = (0, 18, 2)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -371,6 +371,8 @@ class Caller(anyio.AsyncContextManagerMixin):
371
371
  inst = super().__new__(cls)
372
372
  inst._name = name
373
373
  inst._backend = Backend(backend or current_async_library())
374
+ if inst._backend is Backend.trio:
375
+ trio.sleep # noqa: B018 # Check trio is available.
374
376
  inst._host = Hosts(loop) if (loop := kwargs.get("host")) else None
375
377
  inst._backend_options = kwargs.get("backend_options")
376
378
  inst._host_options = kwargs.get("host_options")
@@ -736,7 +738,7 @@ class Caller(anyio.AsyncContextManagerMixin):
736
738
  else:
737
739
  if not (queue := self._guest_queues.get(backend)):
738
740
  with self._child_lock:
739
- if backend:
741
+ if backend is Backend.trio:
740
742
  trio.sleep # noqa: B018 # Check trio is available.
741
743
  if not (queue := self._guest_queues.get(backend)):
742
744
  queue = SingleAsyncQueue(reject=self._reject)
@@ -788,8 +790,8 @@ class Caller(anyio.AsyncContextManagerMixin):
788
790
  """
789
791
 
790
792
  async def _call_later(*args: P.args, **kwargs: P.kwargs) -> T:
791
- if (delay := time.monotonic() - start_time) > 0:
792
- await anyio.sleep(delay)
793
+ if (delay_ := start_time - time.monotonic() + delay) > 0:
794
+ await anyio.sleep(delay_)
793
795
  if inspect.iscoroutine(result := func(*args, **kwargs)):
794
796
  result = await result
795
797
  return result # pyright: ignore[reportReturnType]
@@ -210,7 +210,8 @@ class BaseKernelInterface(traitlets.HasTraits, anyio.AsyncContextManagerMixin):
210
210
  echo.write(string) # pragma: no cover
211
211
  echo.flush() # pragma: no cover
212
212
 
213
- wrapper = OutStream(flusher=flusher, mode=name)
213
+ context = utils._stdout_context if name == "stdout" else utils._stderr_context # pyright: ignore[reportPrivateUsage]
214
+ wrapper = OutStream(send=flusher, context=context)
214
215
  setattr(sys, name, wrapper)
215
216
 
216
217
  return restore
@@ -0,0 +1,61 @@
1
+ from __future__ import annotations
2
+
3
+ from io import TextIOBase
4
+ from typing import TYPE_CHECKING, Literal
5
+
6
+ from typing_extensions import override
7
+
8
+ if TYPE_CHECKING:
9
+ from collections.abc import Callable
10
+ from contextlib import _SupportsRedirect # pyright: ignore[reportPrivateUsage]
11
+ from contextvars import ContextVar
12
+
13
+
14
+ class OutStream(TextIOBase):
15
+ """
16
+ A file like object that sends or redirects text as it is written.
17
+ """
18
+
19
+ def __init__(self, send: Callable[[str], None], context: ContextVar[_SupportsRedirect | None]) -> None:
20
+ """
21
+ Args:
22
+ send: A callback to send text as it is written.
23
+ context: A context variable to an potential alternate target for the text.
24
+ """
25
+ super().__init__()
26
+ self._send = send
27
+ self._context: ContextVar[_SupportsRedirect | None] = context
28
+
29
+ @override
30
+ def isatty(self) -> Literal[True]:
31
+ return True
32
+
33
+ @override
34
+ def readable(self) -> Literal[False]:
35
+ return False
36
+
37
+ @override
38
+ def seekable(self) -> Literal[False]:
39
+ return False
40
+
41
+ @override
42
+ def writable(self) -> Literal[True]:
43
+ return True
44
+
45
+ @override
46
+ def flush(self) -> None:
47
+ if c_out := self._context.get():
48
+ c_out.flush()
49
+
50
+ @override
51
+ def write(self, string: str) -> int:
52
+ if out := self._context.get():
53
+ out.write(string)
54
+ else:
55
+ self._send(string)
56
+ return len(string)
57
+
58
+ @override
59
+ def writelines(self, sequence) -> None:
60
+ self.write("".join(sequence))
61
+ self.flush()
@@ -230,8 +230,8 @@ def redirect_stderr(stream: _SupportsRedirectT, /) -> Generator[_SupportsRedirec
230
230
  """
231
231
 
232
232
  assert get_kernel().event_started
233
- token = _stdout_context.set(stream)
233
+ token = _stderr_context.set(stream)
234
234
  try:
235
235
  yield stream
236
236
  finally:
237
- _stdout_context.reset(token)
237
+ _stderr_context.reset(token)
@@ -124,9 +124,9 @@ class TestCaller:
124
124
 
125
125
  async def test_sync(self):
126
126
  async with Caller("manual") as caller:
127
- is_called = Event()
128
- caller.call_later(0.01, is_called.set)
129
- await is_called
127
+ start_time = time.monotonic()
128
+ dt = await caller.call_later(0.01, time.monotonic) - start_time
129
+ assert dt > 0.01
130
130
 
131
131
  async def test_manual_stop(self):
132
132
  async with Caller("manual") as caller:
@@ -4,6 +4,7 @@ import io
4
4
 
5
5
  import pytest
6
6
 
7
+ from async_kernel import utils as as_utils
7
8
  from async_kernel.iostream import OutStream
8
9
 
9
10
 
@@ -15,7 +16,7 @@ def test_io_api():
15
16
  nonlocal output
16
17
  output += string
17
18
 
18
- stream = OutStream(flusher, mode="stdout")
19
+ stream = OutStream(flusher, context=as_utils._stdout_context) # pyright: ignore[reportPrivateUsage]
19
20
 
20
21
  assert stream.errors is None
21
22
  with pytest.raises(io.UnsupportedOperation):
@@ -1,69 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from io import TextIOBase
4
- from typing import TYPE_CHECKING, Literal
5
-
6
- from aiologic import Lock
7
- from typing_extensions import override
8
-
9
- import async_kernel
10
- from async_kernel.common import Fixed
11
-
12
- if TYPE_CHECKING:
13
- from collections.abc import Callable
14
-
15
-
16
- class OutStream(TextIOBase):
17
- """A file like object that calls the flusher with the string output when flush is called."""
18
-
19
- _write_lock = Fixed(Lock)
20
-
21
- def __init__(self, flusher: Callable[[str], None], *, mode: str) -> None:
22
- """
23
- Args:
24
- flusher: A callback responsible for sending the output.
25
- ctx: The context variable to redirect output.
26
-
27
- [reference for IOBase](https://docs.python.org/3/library/io.html#io.IOBase)
28
- """
29
- super().__init__()
30
- self._flusher = flusher
31
- self._out = ""
32
- self._ctx = {"stdout": async_kernel.utils._stdout_context, "stderr": async_kernel.utils._stdout_context}[mode] # pyright: ignore[reportPrivateUsage]
33
-
34
- @override
35
- def isatty(self) -> Literal[True]:
36
- return True
37
-
38
- @override
39
- def readable(self) -> Literal[False]:
40
- return False
41
-
42
- @override
43
- def seekable(self) -> Literal[False]:
44
- return False
45
-
46
- @override
47
- def writable(self) -> Literal[True]:
48
- return True
49
-
50
- @override
51
- def flush(self) -> None:
52
- if out := self._out:
53
- self._out = ""
54
- self._flusher(out)
55
-
56
- @override
57
- def write(self, string: str) -> int:
58
- if out := self._ctx.get():
59
- out.write(string)
60
- out.flush()
61
- else:
62
- with self._write_lock:
63
- self._out = string
64
- self.flush()
65
- return len(string)
66
-
67
- @override
68
- def writelines(self, sequence) -> None:
69
- self.write("".join(sequence))
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes