async-kernel 0.16.1__tar.gz → 0.16.3__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 (103) hide show
  1. {async_kernel-0.16.1 → async_kernel-0.16.3}/CHANGELOG.md +20 -0
  2. {async_kernel-0.16.1 → async_kernel-0.16.3}/PKG-INFO +3 -1
  3. {async_kernel-0.16.1 → async_kernel-0.16.3}/README.md +2 -0
  4. {async_kernel-0.16.1 → async_kernel-0.16.3}/_version.py +2 -2
  5. {async_kernel-0.16.1 → async_kernel-0.16.3}/pyproject.toml +1 -0
  6. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/asyncshell.py +69 -2
  7. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/kernel.py +2 -2
  8. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/test_kernel.py +16 -1
  9. {async_kernel-0.16.1 → async_kernel-0.16.3}/uv.lock +12 -1
  10. {async_kernel-0.16.1 → async_kernel-0.16.3}/.github/dependabot.yaml +0 -0
  11. {async_kernel-0.16.1 → async_kernel-0.16.3}/.github/release.yml +0 -0
  12. {async_kernel-0.16.1 → async_kernel-0.16.3}/.github/workflows/ci.yml +0 -0
  13. {async_kernel-0.16.1 → async_kernel-0.16.3}/.github/workflows/enforce-label.yml +0 -0
  14. {async_kernel-0.16.1 → async_kernel-0.16.3}/.github/workflows/new_release.yml +0 -0
  15. {async_kernel-0.16.1 → async_kernel-0.16.3}/.github/workflows/pre-commit.yml +0 -0
  16. {async_kernel-0.16.1 → async_kernel-0.16.3}/.github/workflows/publish-docs.yml +0 -0
  17. {async_kernel-0.16.1 → async_kernel-0.16.3}/.github/workflows/publish-to-pypi.yml +0 -0
  18. {async_kernel-0.16.1 → async_kernel-0.16.3}/.gitignore +0 -0
  19. {async_kernel-0.16.1 → async_kernel-0.16.3}/.pre-commit-config.yaml +0 -0
  20. {async_kernel-0.16.1 → async_kernel-0.16.3}/.vscode/launch.json +0 -0
  21. {async_kernel-0.16.1 → async_kernel-0.16.3}/.vscode/settings.json +0 -0
  22. {async_kernel-0.16.1 → async_kernel-0.16.3}/.vscode/spellright.dict +0 -0
  23. {async_kernel-0.16.1 → async_kernel-0.16.3}/CONTRIBUTING.md +0 -0
  24. {async_kernel-0.16.1 → async_kernel-0.16.3}/IPYTHON_LICENSE +0 -0
  25. {async_kernel-0.16.1 → async_kernel-0.16.3}/LICENSE +0 -0
  26. {async_kernel-0.16.1 → async_kernel-0.16.3}/cliff.toml +0 -0
  27. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/about/changelog.md +0 -0
  28. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/about/contributing.md +0 -0
  29. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/about/index.md +0 -0
  30. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/about/license.md +0 -0
  31. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/index.md +0 -0
  32. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/javascripts/extra.js +0 -0
  33. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/notebooks/caller.ipynb +0 -0
  34. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/notebooks/concurrency.ipynb +0 -0
  35. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/overrides/main.html +0 -0
  36. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/reference/asyncshell.md +0 -0
  37. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/reference/caller.md +0 -0
  38. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/reference/comm.md +0 -0
  39. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/reference/command.md +0 -0
  40. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/reference/common.md +0 -0
  41. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/reference/debugger.md +0 -0
  42. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/reference/event_loop.md +0 -0
  43. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/reference/index.md +0 -0
  44. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/reference/interface.md +0 -0
  45. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/reference/kernel.md +0 -0
  46. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/reference/kernelspec.md +0 -0
  47. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/reference/pending.md +0 -0
  48. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/reference/typing.md +0 -0
  49. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/reference/utils.md +0 -0
  50. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/stylesheets/extra.css +0 -0
  51. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/thread_safety.md +0 -0
  52. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/usage/commands.md +0 -0
  53. {async_kernel-0.16.1 → async_kernel-0.16.3}/docs/usage/index.md +0 -0
  54. {async_kernel-0.16.1 → async_kernel-0.16.3}/hatch_build.py +0 -0
  55. {async_kernel-0.16.1 → async_kernel-0.16.3}/mkdocs.yml +0 -0
  56. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/__init__.py +0 -0
  57. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/__main__.py +0 -0
  58. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/caller.py +0 -0
  59. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/comm.py +0 -0
  60. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/command.py +0 -0
  61. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/common.py +0 -0
  62. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/compat/json.py +0 -0
  63. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/compiler.py +0 -0
  64. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/debugger.py +0 -0
  65. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/event_loop/__init__.py +0 -0
  66. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/event_loop/asyncio_guest.py +0 -0
  67. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/event_loop/qt_host.py +0 -0
  68. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/event_loop/run.py +0 -0
  69. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/event_loop/tk_host.py +0 -0
  70. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/interface/__init__.py +0 -0
  71. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/interface/base.py +0 -0
  72. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/interface/callable.py +0 -0
  73. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/interface/zmq.py +0 -0
  74. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/iostream.py +0 -0
  75. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/kernelspec.py +0 -0
  76. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/pending.py +0 -0
  77. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/py.typed +0 -0
  78. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/resources/logo-32x32.png +0 -0
  79. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/resources/logo-64x64.png +0 -0
  80. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/resources/logo-svg.svg +0 -0
  81. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/typing.py +0 -0
  82. {async_kernel-0.16.1 → async_kernel-0.16.3}/src/async_kernel/utils.py +0 -0
  83. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/__init__.py +0 -0
  84. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/conftest.py +0 -0
  85. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/references.py +0 -0
  86. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/test_callable_kernel_interface.py +0 -0
  87. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/test_caller.py +0 -0
  88. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/test_comm.py +0 -0
  89. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/test_command.py +0 -0
  90. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/test_common.py +0 -0
  91. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/test_compat.py +0 -0
  92. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/test_debugger.py +0 -0
  93. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/test_enter_kernel.py +0 -0
  94. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/test_event_loop.py +0 -0
  95. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/test_iostream.py +0 -0
  96. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/test_kernel_subclass.py +0 -0
  97. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/test_kernelspec.py +0 -0
  98. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/test_message_spec.py +0 -0
  99. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/test_pending.py +0 -0
  100. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/test_typing.py +0 -0
  101. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/test_utils.py +0 -0
  102. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/test_zmq_messaging.py +0 -0
  103. {async_kernel-0.16.1 → async_kernel-0.16.3}/tests/utils.py +0 -0
@@ -5,6 +5,22 @@ 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.16.3] - 2026-04-12
9
+
10
+ ### <!-- 6 --> 🌀 Miscellaneous
11
+
12
+ - Run comm_open and com_close message handlers in the shell thread. [#426](https://github.com/fleming79/async-kernel/pull/426)
13
+
14
+ ## [0.16.2] - 2026-04-12
15
+
16
+ ### <!-- 1 --> 🚀 Features
17
+
18
+ - Provide async line magic support [#424](https://github.com/fleming79/async-kernel/pull/424)
19
+
20
+ ### <!-- 6 --> 🌀 Miscellaneous
21
+
22
+ - Prepare for release v0.16.2 [#425](https://github.com/fleming79/async-kernel/pull/425)
23
+
8
24
  ## [0.16.1] - 2026-04-08
9
25
 
10
26
  ### <!-- 1 --> 🚀 Features
@@ -13,6 +29,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
13
29
 
14
30
  ### <!-- 6 --> 🌀 Miscellaneous
15
31
 
32
+ - Prepare for release v0.16.1 [#423](https://github.com/fleming79/async-kernel/pull/423)
33
+
16
34
  - Test against Python 3.15 [#422](https://github.com/fleming79/async-kernel/pull/422)
17
35
 
18
36
  ## [0.16.0] - 2026-04-06
@@ -1157,6 +1175,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1157
1175
 
1158
1176
  - Bump the actions group across 1 directory with 2 updates [#3](https://github.com/fleming79/async-kernel/pull/3)
1159
1177
 
1178
+ [0.16.3]: https://github.com/fleming79/async-kernel/compare/v0.16.2..v0.16.3
1179
+ [0.16.2]: https://github.com/fleming79/async-kernel/compare/v0.16.1..v0.16.2
1160
1180
  [0.16.1]: https://github.com/fleming79/async-kernel/compare/v0.16.0..v0.16.1
1161
1181
  [0.16.0]: https://github.com/fleming79/async-kernel/compare/v0.15.0..v0.16.0
1162
1182
  [0.15.0]: https://github.com/fleming79/async-kernel/compare/v0.14.0..v0.15.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: async-kernel
3
- Version: 0.16.1
3
+ Version: 0.16.3
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
@@ -74,6 +74,7 @@ The kernel provides two external interfaces:
74
74
 
75
75
  - [IPython shell](https://ipython.readthedocs.io/en/stable/overview.html#enhanced-interactive-python-shell)
76
76
  - top-level await ('asyncio' or 'trio' backend) in cells
77
+ - async magic function support in cells
77
78
  - [anyio](https://pypi.org/project/anyio/) compatible asynchronous backend ([`asyncio`](https://docs.python.org/3/library/asyncio.html) (default) or [`trio`](https://pypi.org/project/trio/))
78
79
  - [aiologic](https://aiologic.readthedocs.io/latest/) thread-safe synchronisation primitives
79
80
  - [Backend agnostic multi-thread / multi-event loop management](https://fleming79.github.io/async-kernel/latest/reference/caller/#async_kernel.caller.Caller)
@@ -85,6 +86,7 @@ The kernel provides two external interfaces:
85
86
  - [x] qt host and asyncio[^2] or trio[^3] backend running as a guest
86
87
  - [Experimental](https://github.com/fleming79/echo-kernel) support for
87
88
  [Jupyterlite](https://github.com/jupyterlite/jupyterlite) (try it online [here](https://fleming79.github.io/echo-kernel/) 👈)
89
+ - `%pip install` magic (using micropip)
88
90
  - [Debugger client](https://jupyterlab.readthedocs.io/en/latest/user/debugger.html#debugger)
89
91
 
90
92
  [^1]:
@@ -23,6 +23,7 @@ The kernel provides two external interfaces:
23
23
 
24
24
  - [IPython shell](https://ipython.readthedocs.io/en/stable/overview.html#enhanced-interactive-python-shell)
25
25
  - top-level await ('asyncio' or 'trio' backend) in cells
26
+ - async magic function support in cells
26
27
  - [anyio](https://pypi.org/project/anyio/) compatible asynchronous backend ([`asyncio`](https://docs.python.org/3/library/asyncio.html) (default) or [`trio`](https://pypi.org/project/trio/))
27
28
  - [aiologic](https://aiologic.readthedocs.io/latest/) thread-safe synchronisation primitives
28
29
  - [Backend agnostic multi-thread / multi-event loop management](https://fleming79.github.io/async-kernel/latest/reference/caller/#async_kernel.caller.Caller)
@@ -34,6 +35,7 @@ The kernel provides two external interfaces:
34
35
  - [x] qt host and asyncio[^2] or trio[^3] backend running as a guest
35
36
  - [Experimental](https://github.com/fleming79/echo-kernel) support for
36
37
  [Jupyterlite](https://github.com/jupyterlite/jupyterlite) (try it online [here](https://fleming79.github.io/echo-kernel/) 👈)
38
+ - `%pip install` magic (using micropip)
37
39
  - [Debugger client](https://jupyterlab.readthedocs.io/en/latest/user/debugger.html#debugger)
38
40
 
39
41
  [^1]:
@@ -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.16.1'
22
- __version_tuple__ = version_tuple = (0, 16, 1)
21
+ __version__ = version = '0.16.3'
22
+ __version_tuple__ = version_tuple = (0, 16, 3)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -93,6 +93,7 @@ uvloop = ["uvloop; python_version <= '3.13' and sys_platform != 'win32' and impl
93
93
  dev = [
94
94
  "debugpy",
95
95
  "ipykernel; implementation_name == 'cpython'",
96
+ "pip; implementation_name == 'cpython'",
96
97
  {include-group = "uvloop"},
97
98
  {include-group = "test"},
98
99
  ]
@@ -8,7 +8,7 @@ import pathlib
8
8
  import sys
9
9
  import time
10
10
  from collections.abc import Callable
11
- from typing import TYPE_CHECKING, Any, Literal, Self, overload
11
+ from typing import TYPE_CHECKING, Any, Literal, Self, TextIO, overload
12
12
 
13
13
  import anyio
14
14
  import IPython.core.release
@@ -37,6 +37,7 @@ from async_kernel.typing import Channel, Content, Message, NoValue, Tags
37
37
  if TYPE_CHECKING:
38
38
  from collections.abc import Callable, Generator
39
39
 
40
+ from anyio.abc import ByteReceiveStream
40
41
  from traitlets.config import Configurable
41
42
 
42
43
  from async_kernel import Kernel
@@ -45,6 +46,13 @@ if TYPE_CHECKING:
45
46
  __all__ = ["AsyncInteractiveShell"]
46
47
 
47
48
 
49
+ async def _forward_transport_stream(transport_stream: ByteReceiveStream, out: TextIO, /) -> None:
50
+ from anyio.streams.text import TextReceiveStream # noqa: PLC0415
51
+
52
+ async for text in TextReceiveStream(transport_stream):
53
+ out.write(text)
54
+
55
+
48
56
  class AsyncDisplayHook(DisplayHook):
49
57
  """
50
58
  A displayhook subclass that publishes data using [iopub_send][async_kernel.kernel.Kernel.iopub_send].
@@ -168,6 +176,7 @@ class AsyncInteractiveShell(InteractiveShell):
168
176
  Notable differences:
169
177
  - Supports a soft timeout specified via tags `timeout=<value in seconds>`[^1].
170
178
  - `user_ns` and `user_global_ns` are same dictionary which is a fixed [dict][].
179
+ - Supports async magic functions (See [KernelMagics.pip][]).
171
180
 
172
181
  [^1]: When the execution time exceeds the timeout value, the code execution will "move on".
173
182
  """
@@ -320,6 +329,14 @@ class AsyncInteractiveShell(InteractiveShell):
320
329
  def ns_table(self) -> dict[str, dict[Any, Any] | dict[str, Any]]:
321
330
  return {"user_global": self.user_global_ns, "user_local": self.user_ns, "builtin": builtins.__dict__}
322
331
 
332
+ async def run_line_magic_async(self, magic_name: str, line: str, _stack_depth=1) -> Any:
333
+ "Call and awaits [run_line_magic][IPython.core.interactiveshell.InteractiveShell.run_line_magic]."
334
+ result = self.run_line_magic(magic_name, line, _stack_depth)
335
+ try:
336
+ return await result # pyright: ignore[reportGeneralTypeIssues]
337
+ except TypeError:
338
+ return result
339
+
323
340
  async def _execute_request(
324
341
  self,
325
342
  code: str = "",
@@ -378,7 +395,9 @@ class AsyncInteractiveShell(InteractiveShell):
378
395
  raw_cell=code,
379
396
  store_history=store_history,
380
397
  silent=silent,
381
- transformed_cell=self.transform_cell(code),
398
+ transformed_cell=self.transform_cell(code).replace(
399
+ "get_ipython().run_line_magic(", "await get_ipython().run_line_magic_async("
400
+ ),
382
401
  shell_futures=True,
383
402
  cell_id=cell_id,
384
403
  )
@@ -774,5 +793,53 @@ class KernelMagics(Magics):
774
793
  )
775
794
  print(f"Current shell:\t{self.shell}\n\n{subshell_list}")
776
795
 
796
+ @line_magic
797
+ async def pip(self, line: str) -> Any | None:
798
+ """Run the pip package manager for the current environment.
799
+
800
+ Usage:
801
+ %pip install [pkgs]
802
+ """
803
+ if sys.platform == "emscripten":
804
+ import micropip # noqa: PLC0415
805
+
806
+ match line.split(maxsplit=1)[0]:
807
+ case "install":
808
+ requirements = [
809
+ f"emfs:{n}" if n.startswith(".") else n for n in line.removeprefix("install").split()
810
+ ]
811
+ return await micropip.install(requirements, verbose=True)
812
+ case "uninstall":
813
+ return micropip.uninstall(line.removeprefix("uninstall").split(), verbose=True)
814
+ case "freeze":
815
+ return micropip.freeze()
816
+ case "list":
817
+ return micropip.list()
818
+ case _ as name:
819
+ print("Unsupported command:", name)
820
+ else:
821
+ cmd = [sys.executable, "-m", "pip", *line.split()]
822
+ async with await anyio.open_process(cmd) as process, anyio.create_task_group() as tg:
823
+ if process.stdout:
824
+ tg.start_soon(_forward_transport_stream, process.stdout, sys.stdout)
825
+ if process.stderr:
826
+ tg.start_soon(_forward_transport_stream, process.stderr, sys.stderr)
827
+
828
+ return None
829
+
830
+ @line_magic
831
+ async def uv(self, line) -> None:
832
+ """Run the uv package manager for the current environment.
833
+
834
+ Usage:
835
+ %uv pip install [pkgs]
836
+ """
837
+ cmd = ["uv", *line.split()]
838
+ async with await anyio.open_process(cmd) as process, anyio.create_task_group() as tg:
839
+ if process.stdout:
840
+ tg.start_soon(_forward_transport_stream, process.stdout, sys.stdout)
841
+ if process.stderr:
842
+ tg.start_soon(_forward_transport_stream, process.stderr, sys.stdout)
843
+
777
844
 
778
845
  InteractiveShellABC.register(AsyncInteractiveShell)
@@ -46,7 +46,7 @@ if TYPE_CHECKING:
46
46
 
47
47
  __all__ = ["Kernel", "KernelInterrupt"]
48
48
 
49
- RUN_IN_SHELL = (MsgType.execute_request, MsgType.comm_msg)
49
+ RUN_IN_SHELL_THREAD = (MsgType.execute_request, MsgType.comm_msg, MsgType.comm_open, MsgType.comm_close)
50
50
  """
51
51
  Shell message types that are handled in the shell's thread (typically the _MainThread_).
52
52
 
@@ -435,7 +435,7 @@ class Kernel(traitlets.HasTraits, anyio.AsyncContextManagerMixin):
435
435
  handler = self._get_handler(subshell_id, msg_type, send_reply)
436
436
  run_mode = self._get_run_mode(msg_type, job)
437
437
  caller = self.callers[channel]
438
- if channel is Channel.shell and msg_type not in RUN_IN_SHELL:
438
+ if channel is Channel.shell and msg_type not in RUN_IN_SHELL_THREAD:
439
439
  caller = self.callers[Channel.control]
440
440
  # Schedule job
441
441
  match run_mode:
@@ -420,7 +420,16 @@ async def test_debug_static_richInspectVariables(client: AsyncKernelClient, vari
420
420
  assert reply["content"]["status"] == "ok"
421
421
 
422
422
 
423
- @pytest.mark.parametrize("code", argvalues=["%connect_info", "%callers", "%subshell"])
423
+ @pytest.mark.parametrize(
424
+ "code",
425
+ argvalues=[
426
+ "%connect_info",
427
+ "%callers",
428
+ "%subshell",
429
+ "%pip install anyio",
430
+ "%uv pip install anyio",
431
+ ],
432
+ )
424
433
  async def test_magic(client: AsyncKernelClient, code: str, kernel: Kernel, monkeypatch):
425
434
  await utils.clear_iopub(client)
426
435
  monkeypatch.setenv("JUPYTER_RUNTIME_DIR", str(pathlib.Path(kernel.connection_file).parent))
@@ -431,6 +440,12 @@ async def test_magic(client: AsyncKernelClient, code: str, kernel: Kernel, monke
431
440
  assert stdout
432
441
 
433
442
 
443
+ @pytest.mark.parametrize("code", argvalues=["%connect_info"])
444
+ async def test_magic_sync(client: AsyncKernelClient, code: str, kernel: Kernel, monkeypatch):
445
+ result = kernel.main_shell.run_cell(code)
446
+ assert result.success
447
+
448
+
434
449
  async def test_shell_enable_gui(kernel: Kernel):
435
450
  # used by ipython AutoMagicChecker via is_shadowed (requires 'builitin')
436
451
  assert set(kernel.shell.ns_table) == {"user_global", "user_local", "builtin"}
@@ -139,6 +139,7 @@ dependencies = [
139
139
  dev = [
140
140
  { name = "debugpy" },
141
141
  { name = "ipykernel", marker = "implementation_name == 'cpython'" },
142
+ { name = "pip", marker = "implementation_name == 'cpython'" },
142
143
  { name = "pytest" },
143
144
  { name = "pytest-cov" },
144
145
  { name = "pytest-mock" },
@@ -212,6 +213,7 @@ requires-dist = [
212
213
  dev = [
213
214
  { name = "debugpy" },
214
215
  { name = "ipykernel", marker = "implementation_name == 'cpython'" },
216
+ { name = "pip", marker = "implementation_name == 'cpython'" },
215
217
  { name = "pytest", specifier = ">=8.4,<9" },
216
218
  { name = "pytest-cov", specifier = ">=7.0.0" },
217
219
  { name = "pytest-mock" },
@@ -2126,7 +2128,7 @@ name = "pexpect"
2126
2128
  version = "4.9.0"
2127
2129
  source = { registry = "https://pypi.org/simple" }
2128
2130
  dependencies = [
2129
- { name = "ptyprocess" },
2131
+ { name = "ptyprocess", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
2130
2132
  ]
2131
2133
  sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" }
2132
2134
  wheels = [
@@ -2220,6 +2222,15 @@ wheels = [
2220
2222
  { url = "https://files.pythonhosted.org/packages/bc/60/5382c03e1970de634027cee8e1b7d39776b778b81812aaf45b694dfe9e28/pillow-12.2.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:bfa9c230d2fe991bed5318a5f119bd6780cda2915cca595393649fc118ab895e", size = 7080946, upload-time = "2026-04-01T14:46:11.734Z" },
2221
2223
  ]
2222
2224
 
2225
+ [[package]]
2226
+ name = "pip"
2227
+ version = "26.0.1"
2228
+ source = { registry = "https://pypi.org/simple" }
2229
+ sdist = { url = "https://files.pythonhosted.org/packages/48/83/0d7d4e9efe3344b8e2fe25d93be44f64b65364d3c8d7bc6dc90198d5422e/pip-26.0.1.tar.gz", hash = "sha256:c4037d8a277c89b320abe636d59f91e6d0922d08a05b60e85e53b296613346d8", size = 1812747, upload-time = "2026-02-05T02:20:18.702Z" }
2230
+ wheels = [
2231
+ { url = "https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl", hash = "sha256:bdb1b08f4274833d62c1aa29e20907365a2ceb950410df15fc9521bad440122b", size = 1787723, upload-time = "2026-02-05T02:20:16.416Z" },
2232
+ ]
2233
+
2223
2234
  [[package]]
2224
2235
  name = "platformdirs"
2225
2236
  version = "4.9.4"
File without changes
File without changes
File without changes
File without changes