Skip to content

Commit b61accf

Browse files
authored
BUG: Fix Kwarg only in update_env (#989)
* BUG: Fix Kwarg only in update_env closes jupyterlab/jupyterlab#15301 * add typing informations * use str annotations
1 parent 79fa122 commit b61accf

File tree

3 files changed

+44
-5
lines changed

3 files changed

+44
-5
lines changed

jupyter_client/manager.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from traitlets import (
2020
Any,
2121
Bool,
22+
Dict,
2223
DottedObjectName,
2324
Float,
2425
Instance,
@@ -206,7 +207,7 @@ def ipykernel(self) -> bool:
206207
return self.kernel_name in {"python", "python2", "python3"}
207208

208209
# Protected traits
209-
_launch_args: Any = Any()
210+
_launch_args: t.Optional["Dict[str, Any]"] = Dict(allow_none=True)
210211
_control_socket: Any = Any()
211212

212213
_restarter: Any = Any()
@@ -281,7 +282,13 @@ def update_env(self, *, env: t.Dict[str, str]) -> None:
281282
282283
.. version-added: 8.5
283284
"""
284-
self._launch_args["env"].update(env)
285+
# Mypy think this is unreachable as it see _launch_args as Dict, not t.Dict
286+
if (
287+
isinstance(self._launch_args, dict)
288+
and "env" in self._launch_args
289+
and isinstance(self._launch_args["env"], dict) # type: ignore [unreachable]
290+
):
291+
self._launch_args["env"].update(env) # type: ignore [unreachable]
285292

286293
def format_kernel_cmd(self, extra_arguments: t.Optional[t.List[str]] = None) -> t.List[str]:
287294
"""Replace templated args (e.g. {connection_file})"""
@@ -307,13 +314,14 @@ def format_kernel_cmd(self, extra_arguments: t.Optional[t.List[str]] = None) ->
307314
# is not usable by non python kernels because the path is being rerouted when
308315
# inside of a store app.
309316
# See this bug here: https://bugs.python.org/issue41196
310-
ns = {
317+
ns: t.Dict[str, t.Any] = {
311318
"connection_file": os.path.realpath(self.connection_file),
312319
"prefix": sys.prefix,
313320
}
314321

315322
if self.kernel_spec: # type:ignore[truthy-bool]
316323
ns["resource_dir"] = self.kernel_spec.resource_dir
324+
assert isinstance(self._launch_args, dict)
317325

318326
ns.update(self._launch_args)
319327

@@ -371,7 +379,8 @@ async def _async_pre_start_kernel(
371379
self.shutting_down = False
372380
self.kernel_id = self.kernel_id or kw.pop("kernel_id", str(uuid.uuid4()))
373381
# save kwargs for use in restart
374-
self._launch_args = kw.copy()
382+
# assigning Traitlets Dicts to Dict make mypy unhappy but is ok
383+
self._launch_args = kw.copy() # type:ignore [assignment]
375384
if self.provisioner is None: # will not be None on restarts
376385
self.provisioner = KPF.instance(parent=self.parent).create_provisioner_instance(
377386
self.kernel_id,

jupyter_client/multikernelmanager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ def update_env(self, *, kernel_id: str, env: t.Dict[str, str]) -> None:
223223
.. version-added: 8.5
224224
"""
225225
if kernel_id in self:
226-
self._kernels[kernel_id].update_env(env)
226+
self._kernels[kernel_id].update_env(env=env)
227227

228228
async def _add_kernel_when_ready(
229229
self, kernel_id: str, km: KernelManager, kernel_awaitable: t.Awaitable

tests/test_manager.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,33 @@ def test_connection_file_real_path():
3232
km._launch_args = {}
3333
cmds = km.format_kernel_cmd()
3434
assert cmds[4] == "foobar"
35+
36+
37+
def test_env_update_launch_args_not_set():
38+
km = KernelManager()
39+
km.update_env(env={"A": "A"})
40+
41+
42+
def test_env_update_launch_args_not_dict():
43+
km = KernelManager()
44+
km._launch_args = None
45+
km.update_env(env={"B": "B"})
46+
47+
48+
def test_env_update_launch_args_no_env():
49+
km = KernelManager()
50+
km._launch_args = {}
51+
km.update_env(env={"C": "C"})
52+
53+
54+
def test_env_update_launch_args_env_not_dict():
55+
km = KernelManager()
56+
km._launch_args = {"env": None}
57+
km.update_env(env={"D": "D"})
58+
59+
60+
def test_env_update_launch_args_env_dic():
61+
km = KernelManager()
62+
km._launch_args = {"env": {}}
63+
km.update_env(env={"E": "E"})
64+
assert km._launch_args["env"]["E"] == "E"

0 commit comments

Comments
 (0)