Skip to content

Commit a5c288c

Browse files
authored
Update typing for traitlets 5.13 (#1350)
1 parent 444138c commit a5c288c

File tree

12 files changed

+56
-37
lines changed

12 files changed

+56
-37
lines changed

jupyter_server/extension/application.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
"""An extension application."""
2+
from __future__ import annotations
3+
24
import logging
35
import re
46
import sys
@@ -158,19 +160,21 @@ class method. This method can be set as a entry_point in
158160

159161
@default("open_browser")
160162
def _default_open_browser(self):
163+
assert self.serverapp is not None
161164
return self.serverapp.config["ServerApp"].get("open_browser", True)
162165

163166
@property
164167
def config_file_paths(self):
165168
"""Look on the same path as our parent for config files"""
166169
# rely on parent serverapp, which should control all config loading
170+
assert self.serverapp is not None
167171
return self.serverapp.config_file_paths
168172

169173
# The extension name used to name the jupyter config
170174
# file, jupyter_{name}_config.
171175
# This should also match the jupyter subcommand used to launch
172176
# this extension from the CLI, e.g. `jupyter {name}`.
173-
name: t.Union[str, Unicode] = "ExtensionApp" # type:ignore[assignment]
177+
name: str | Unicode = "ExtensionApp" # type:ignore[assignment]
174178

175179
@classmethod
176180
def get_extension_package(cls):
@@ -206,7 +210,7 @@ def _default_url(self):
206210
]
207211

208212
# A ServerApp is not defined yet, but will be initialized below.
209-
serverapp = Any()
213+
serverapp: ServerApp | None = Any() # type:ignore[assignment]
210214

211215
@default("serverapp")
212216
def _default_serverapp(self):
@@ -242,6 +246,7 @@ def _default_log_format(self):
242246
@default("static_url_prefix")
243247
def _default_static_url_prefix(self):
244248
static_url = f"static/{self.name}/"
249+
assert self.serverapp is not None
245250
return url_path_join(self.serverapp.base_url, static_url)
246251

247252
static_paths = List(
@@ -264,7 +269,9 @@ def _default_static_url_prefix(self):
264269

265270
settings = Dict(help=_i18n("""Settings that will passed to the server.""")).tag(config=True)
266271

267-
handlers = List(help=_i18n("""Handlers appended to the server.""")).tag(config=True)
272+
handlers: List[tuple[t.Any, ...]] = List(
273+
help=_i18n("""Handlers appended to the server.""")
274+
).tag(config=True) # type:ignore[assignment]
268275

269276
def _config_file_name_default(self):
270277
"""The default config file name."""
@@ -295,6 +302,7 @@ def _prepare_config(self):
295302
def _prepare_settings(self):
296303
"""Prepare the settings."""
297304
# Make webapp settings accessible to initialize_settings method
305+
assert self.serverapp is not None
298306
webapp = self.serverapp.web_app
299307
self.settings.update(**webapp.settings)
300308

@@ -314,6 +322,7 @@ def _prepare_settings(self):
314322

315323
def _prepare_handlers(self):
316324
"""Prepare the handlers."""
325+
assert self.serverapp is not None
317326
webapp = self.serverapp.web_app
318327

319328
# Get handlers defined by extension subclass.
@@ -352,7 +361,7 @@ def _prepare_handlers(self):
352361
)
353362
new_handlers.append(handler)
354363

355-
webapp.add_handlers(".*$", new_handlers)
364+
webapp.add_handlers(".*$", new_handlers) # type:ignore[arg-type]
356365

357366
def _prepare_templates(self):
358367
"""Add templates to web app settings if extension has templates."""
@@ -372,7 +381,7 @@ def _jupyter_server_config(self):
372381
base_config["ServerApp"].update(self.serverapp_config)
373382
return base_config
374383

375-
def _link_jupyter_server_extension(self, serverapp):
384+
def _link_jupyter_server_extension(self, serverapp: ServerApp) -> None:
376385
"""Link the ExtensionApp to an initialized ServerApp.
377386
378387
The ServerApp is stored as an attribute and config
@@ -436,6 +445,7 @@ def start(self):
436445
"""
437446
super().start()
438447
# Start the server.
448+
assert self.serverapp is not None
439449
self.serverapp.start()
440450

441451
def current_activity(self):
@@ -447,6 +457,7 @@ async def stop_extension(self):
447457

448458
def stop(self):
449459
"""Stop the underlying Jupyter server."""
460+
assert self.serverapp is not None
450461
self.serverapp.stop()
451462
self.serverapp.clear_instance()
452463

jupyter_server/extension/manager.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
"""The extension manager."""
2+
from __future__ import annotations
3+
24
import importlib
35

46
from tornado.gen import multi

jupyter_server/extension/serverextension.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ def list_server_extensions(self) -> None:
355355
self.log.info(f" {name} {version} {GREEN_OK}")
356356
except Exception as err:
357357
exc_info = False
358-
if int(self.log_level) <= logging.DEBUG:
358+
if int(self.log_level) <= logging.DEBUG: # type:ignore[call-overload]
359359
exc_info = True
360360
self.log.warning(f" {RED_X} {err}", exc_info=exc_info)
361361
# Add a blank line between paths.

jupyter_server/gateway/gateway_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ def _gateway_retry_max_default(self):
462462
)
463463
gateway_token_renewer_class_env = "JUPYTER_GATEWAY_TOKEN_RENEWER_CLASS"
464464
gateway_token_renewer_class = Type(
465-
klass=GatewayTokenRenewerBase, # type:ignore[type-abstract]
465+
klass=GatewayTokenRenewerBase,
466466
config=True,
467467
help="""The class to use for Gateway token renewal. (JUPYTER_GATEWAY_TOKEN_RENEWER_CLASS env var)""",
468468
)
@@ -546,7 +546,7 @@ def __init__(self, **kwargs):
546546
"""Initialize a gateway client."""
547547
super().__init__(**kwargs)
548548
self._connection_args = {} # initialized on first use
549-
self.gateway_token_renewer = self.gateway_token_renewer_class(parent=self, log=self.log) # type:ignore[operator]
549+
self.gateway_token_renewer = self.gateway_token_renewer_class(parent=self, log=self.log) # type:ignore[abstract]
550550

551551
# store of cookies with store time
552552
self._cookies: ty.Dict[str, ty.Tuple[Morsel, datetime]] = {}

jupyter_server/gateway/managers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ async def refresh_model(self, model=None):
456456
# this kernel manager. The current kernel manager instance may not have
457457
# a parent instance if, say, a server extension is using another application
458458
# (e.g., papermill) that uses a KernelManager instance directly.
459-
self.parent._kernel_connections[self.kernel_id] = int(model["connections"])
459+
self.parent._kernel_connections[self.kernel_id] = int(model["connections"]) # type:ignore[index]
460460

461461
self.kernel = model
462462
return model

jupyter_server/serverapp.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,7 +1086,7 @@ def _deprecated_token(self, change: t.Any) -> None:
10861086
self._warn_deprecated_config(change, "IdentityProvider")
10871087

10881088
@default("token")
1089-
def _deprecated_token_access(self) -> None:
1089+
def _deprecated_token_access(self) -> str:
10901090
warnings.warn(
10911091
"ServerApp.token config is deprecated in jupyter-server 2.0. Use IdentityProvider.token",
10921092
DeprecationWarning,
@@ -1884,7 +1884,7 @@ def init_configurables(self) -> None:
18841884
self.gateway_config = GatewayClient.instance(parent=self)
18851885

18861886
if not issubclass(
1887-
self.kernel_manager_class, # type:ignore[arg-type]
1887+
self.kernel_manager_class,
18881888
AsyncMappingKernelManager,
18891889
):
18901890
warnings.warn(
@@ -1894,7 +1894,7 @@ def init_configurables(self) -> None:
18941894
)
18951895

18961896
if not issubclass(
1897-
self.contents_manager_class, # type:ignore[arg-type]
1897+
self.contents_manager_class,
18981898
AsyncContentsManager,
18991899
):
19001900
warnings.warn(
@@ -1925,8 +1925,8 @@ def init_configurables(self) -> None:
19251925
"because jupyter-client's version does not allow them (should be >8.3.0)."
19261926
)
19271927

1928-
self.kernel_manager = self.kernel_manager_class(**kwargs) # type:ignore[operator]
1929-
self.contents_manager = self.contents_manager_class( # type:ignore[operator]
1928+
self.kernel_manager = self.kernel_manager_class(**kwargs)
1929+
self.contents_manager = self.contents_manager_class(
19301930
parent=self,
19311931
log=self.log,
19321932
)
@@ -1968,11 +1968,11 @@ def init_configurables(self) -> None:
19681968
f"Ignoring deprecated config ServerApp.login_handler_class={self.login_handler_class}."
19691969
" Superseded by ServerApp.identity_provider_class={self.identity_provider_class}."
19701970
)
1971-
self.identity_provider = self.identity_provider_class(**identity_provider_kwargs) # type:ignore[operator]
1971+
self.identity_provider = self.identity_provider_class(**identity_provider_kwargs)
19721972

19731973
if self.identity_provider_class is LegacyIdentityProvider:
19741974
# legacy config stored the password in tornado_settings
1975-
self.tornado_settings["password"] = self.identity_provider.hashed_password
1975+
self.tornado_settings["password"] = self.identity_provider.hashed_password # type:ignore[attr-defined]
19761976
self.tornado_settings["token"] = self.identity_provider.token
19771977

19781978
if self._token_set:
@@ -1989,7 +1989,7 @@ def init_configurables(self) -> None:
19891989
# that means it has some config that should take higher priority than deprecated ServerApp.token
19901990
self.log.warning("Ignoring deprecated ServerApp.token config")
19911991

1992-
self.authorizer = self.authorizer_class( # type:ignore[operator]
1992+
self.authorizer = self.authorizer_class(
19931993
parent=self, log=self.log, identity_provider=self.identity_provider
19941994
)
19951995

jupyter_server/services/contents/manager.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
"""A base class for contents managers."""
22
# Copyright (c) Jupyter Development Team.
33
# Distributed under the terms of the Modified BSD License.
4+
from __future__ import annotations
5+
46
import itertools
57
import json
68
import os
79
import re
10+
import typing as t
811
import warnings
912
from fnmatch import fnmatch
1013

@@ -259,8 +262,8 @@ def run_post_save_hook(self, model, os_path):
259262
msg = "fUnexpected error while running post hook save: {e}"
260263
raise HTTPError(500, msg) from None
261264

262-
_pre_save_hooks = List()
263-
_post_save_hooks = List()
265+
_pre_save_hooks: List[t.Any] = List()
266+
_post_save_hooks: List[t.Any] = List()
264267

265268
def register_pre_save_hook(self, hook):
266269
"""Register a pre save hook."""

jupyter_server/services/kernels/connection/channels.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
"""An implementation of a kernel connection."""
2+
from __future__ import annotations
3+
24
import asyncio
35
import json
46
import time
7+
import typing as t
58
import weakref
69
from concurrent.futures import Future
710
from textwrap import dedent
8-
from typing import Dict as Dict_t
9-
from typing import MutableSet, cast
1011

1112
from jupyter_client import protocol_version as client_protocol_version
1213
from tornado import gen, web
@@ -95,8 +96,8 @@ def write_message(self):
9596
# class-level registry of open sessions
9697
# allows checking for conflict on session-id,
9798
# which is used as a zmq identity and must be unique.
98-
_open_sessions: Dict_t[str, KernelWebsocketHandler] = {}
99-
_open_sockets: MutableSet["ZMQChannelsWebsocketConnection"] = weakref.WeakSet()
99+
_open_sessions: dict[str, KernelWebsocketHandler] = {}
100+
_open_sockets: t.MutableSet[ZMQChannelsWebsocketConnection] = weakref.WeakSet()
100101

101102
_kernel_info_future: Future
102103
_close_future: Future
@@ -127,7 +128,7 @@ def _default_close_future(self):
127128
# Queue of (time stamp, byte count)
128129
# Allows you to specify that the byte count should be lowered
129130
# by a delta amount at some point in the future.
130-
_iopub_window_byte_queue = List([])
131+
_iopub_window_byte_queue: List[t.Any] = List([])
131132

132133
@classmethod
133134
async def close_all(cls):
@@ -285,7 +286,7 @@ async def _register_session(self):
285286
if (
286287
self.kernel_id in self.multi_kernel_manager
287288
): # only update open sessions if kernel is actively managed
288-
self._open_sessions[self.session_key] = cast(
289+
self._open_sessions[self.session_key] = t.cast(
289290
KernelWebsocketHandler, self.websocket_handler
290291
)
291292

jupyter_server/services/kernels/kernelmanager.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
"""
66
# Copyright (c) Jupyter Development Team.
77
# Distributed under the terms of the Modified BSD License.
8+
from __future__ import annotations
9+
810
import asyncio
911
import os
1012
import pathlib
@@ -13,8 +15,6 @@
1315
from collections import defaultdict
1416
from datetime import datetime, timedelta
1517
from functools import partial, wraps
16-
from typing import Dict as DictType
17-
from typing import Optional
1818

1919
from jupyter_client.ioloop.manager import AsyncIOLoopKernelManager
2020
from jupyter_client.multikernelmanager import AsyncMultiKernelManager, MultiKernelManager
@@ -64,7 +64,7 @@ def _default_kernel_manager_class(self):
6464

6565
_kernel_connections = Dict()
6666

67-
_kernel_ports: DictType[str, t.List[int]] = Dict() # type: ignore[assignment]
67+
_kernel_ports: dict[str, list[int]] = Dict() # type: ignore[assignment]
6868

6969
_culler_callback = None
7070

@@ -206,7 +206,7 @@ async def _remove_kernel_when_ready(self, kernel_id, kernel_awaitable):
206206
# TODO DEC 2022: Revise the type-ignore once the signatures have been changed upstream
207207
# https://github.com/jupyter/jupyter_client/pull/905
208208
async def _async_start_kernel( # type:ignore[override]
209-
self, *, kernel_id: Optional[str] = None, path: Optional[ApiPath] = None, **kwargs: str
209+
self, *, kernel_id: str | None = None, path: ApiPath | None = None, **kwargs: str
210210
) -> str:
211211
"""Start a kernel for a session and return its kernel_id.
212212
@@ -797,12 +797,12 @@ class ServerKernelManager(AsyncIOLoopKernelManager):
797797
# schema to register with this kernel manager's eventlogger.
798798
# This trait should not be overridden.
799799
@property
800-
def core_event_schema_paths(self) -> t.List[pathlib.Path]:
800+
def core_event_schema_paths(self) -> list[pathlib.Path]:
801801
return [DEFAULT_EVENTS_SCHEMA_PATH / "kernel_actions" / "v1.yaml"]
802802

803803
# This trait is intended for subclasses to override and define
804804
# custom event schemas.
805-
extra_event_schema_paths = List(
805+
extra_event_schema_paths: List[str] = List( # type:ignore[assignment]
806806
default_value=[],
807807
help="""
808808
A list of pathlib.Path objects pointing at to register with

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ nowarn = "test -W default {args}"
104104

105105
[tool.hatch.envs.typing]
106106
features = ["test"]
107-
dependencies = [ "mypy~=1.6", "traitlets>=5.11.2", "jupyter_core>=5.3.2", "jupyter_client>=8.5"]
107+
dependencies = [ "mypy~=1.6", "traitlets>=5.13", "jupyter_core>=5.5", "jupyter_client>=8.5"]
108108
[tool.hatch.envs.typing.scripts]
109109
test = "mypy --install-types --non-interactive {args:.}"
110110

tests/extension/mockextensions/app.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import os
24

35
from jupyter_events import EventLogger
@@ -44,7 +46,7 @@ def get(self):
4446

4547
class MockExtensionApp(ExtensionAppJinjaMixin, ExtensionApp):
4648
name = "mockextension"
47-
template_paths = List().tag(config=True)
49+
template_paths: List[str] = List().tag(config=True) # type:ignore[assignment]
4850
static_paths = [STATIC_PATH] # type:ignore[assignment]
4951
mock_trait = Unicode("mock trait", config=True)
5052
loaded = False
@@ -59,7 +61,7 @@ def initialize_settings(self):
5961
# Only add this event if it hasn't already been added.
6062
# Log the error if it fails, but don't crash the app.
6163
try:
62-
elogger: EventLogger = self.serverapp.event_logger
64+
elogger: EventLogger = self.serverapp.event_logger # type:ignore[union-attr, assignment]
6365
elogger.register_event_schema(EVENT_SCHEMA)
6466
except SchemaRegistryException as err:
6567
self.log.error(err)

tests/services/kernels/test_connection.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
from jupyter_server.services.kernels.websocket import KernelWebsocketHandler
1212

1313

14-
async def test_websocket_connection(jp_serverapp):
15-
app: ServerApp = jp_serverapp
16-
kernel_id = await app.kernel_manager.start_kernel()
14+
async def test_websocket_connection(jp_serverapp: ServerApp) -> None:
15+
app = jp_serverapp
16+
kernel_id = await app.kernel_manager.start_kernel() # type:ignore[has-type]
1717
kernel = app.kernel_manager.get_kernel(kernel_id)
1818
request = HTTPRequest("foo", "GET")
1919
request.connection = MagicMock()

0 commit comments

Comments
 (0)