Skip to content

Commit

Permalink
Update typings for traitlets 5.10 (#1330)
Browse files Browse the repository at this point in the history
  • Loading branch information
blink1073 authored Sep 28, 2023
1 parent 46e685b commit 3544deb
Show file tree
Hide file tree
Showing 17 changed files with 92 additions and 67 deletions.
4 changes: 2 additions & 2 deletions examples/simple/simple_ext1/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ class SimpleApp1(ExtensionAppJinjaMixin, ExtensionApp):
load_other_extensions = True

# Local path to static files directory.
static_paths = [DEFAULT_STATIC_FILES_PATH]
static_paths = [DEFAULT_STATIC_FILES_PATH] # type:ignore[assignment]

# Local path to templates directory.
template_paths = [DEFAULT_TEMPLATE_FILES_PATH]
template_paths = [DEFAULT_TEMPLATE_FILES_PATH] # type:ignore[assignment]

configA = Unicode("", config=True, help="Config A example.") # noqa

Expand Down
4 changes: 2 additions & 2 deletions examples/simple/simple_ext2/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ class SimpleApp2(ExtensionAppJinjaMixin, ExtensionApp):
load_other_extensions = True

# Local path to static files directory.
static_paths = [DEFAULT_STATIC_FILES_PATH]
static_paths = [DEFAULT_STATIC_FILES_PATH] # type:ignore[assignment]

# Local path to templates directory.
template_paths = [DEFAULT_TEMPLATE_FILES_PATH]
template_paths = [DEFAULT_TEMPLATE_FILES_PATH] # type:ignore[assignment]

configD = Unicode("", config=True, help="Config D example.") # noqa

Expand Down
14 changes: 9 additions & 5 deletions jupyter_server/auth/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -702,22 +702,24 @@ def auth_enabled(self):

def get_user(self, handler: JupyterHandler) -> User | None:
"""Get the user."""
user = self.login_handler_class.get_user(handler)
user = self.login_handler_class.get_user(handler) # type:ignore[attr-defined]
if user is None:
return None
return _backward_compat_user(user)

@property
def login_available(self):
return self.login_handler_class.get_login_available(self.settings)
return self.login_handler_class.get_login_available( # type:ignore[attr-defined]
self.settings
)

def should_check_origin(self, handler: JupyterHandler) -> bool:
"""Whether we should check origin."""
return self.login_handler_class.should_check_origin(handler)
return self.login_handler_class.should_check_origin(handler) # type:ignore[attr-defined]

def is_token_authenticated(self, handler: JupyterHandler) -> bool:
"""Whether we are token authenticated."""
return self.login_handler_class.is_token_authenticated(handler)
return self.login_handler_class.is_token_authenticated(handler) # type:ignore[attr-defined]

def validate_security(
self,
Expand All @@ -732,4 +734,6 @@ def validate_security(
self.log.critical(_i18n("Hint: run the following command to set a password"))
self.log.critical(_i18n("\t$ python -m jupyter_server.auth password"))
sys.exit(1)
return self.login_handler_class.validate_security(app, ssl_options)
return self.login_handler_class.validate_security( # type:ignore[attr-defined]
app, ssl_options
)
2 changes: 1 addition & 1 deletion jupyter_server/extension/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ def load_extension(self, name):
"""Load an extension by name."""
extension = self.extensions.get(name)

if extension.enabled:
if extension and extension.enabled:
try:
extension.load_all_points(self.serverapp)
except Exception as e:
Expand Down
6 changes: 4 additions & 2 deletions jupyter_server/gateway/connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def disconnect(self):
if self.ws is not None:
# Close connection
self.ws.close()
elif not self.ws_future.done():
elif self.ws_future and not self.ws_future.done():
# Cancel pending connection. Since future.cancel() is a noop on tornado, we'll track cancellation locally
self.ws_future.cancel()
self.log.debug(f"_disconnect: future cancelled, disconnected: {self.disconnected}")
Expand All @@ -93,6 +93,8 @@ async def _read_messages(self):
if not self.disconnected:
self.log.warning(f"Lost connection to Gateway: {self.kernel_id}")
break
if isinstance(message, bytes):
message = message.decode("utf8")
self.handle_outgoing_message(
message
) # pass back to notebook client (see self.on_open and WebSocketChannelsHandler.open)
Expand Down Expand Up @@ -136,7 +138,7 @@ def handle_outgoing_message(self, incoming_msg: str, *args: Any) -> None:

def handle_incoming_message(self, message: str) -> None:
"""Send message to gateway server."""
if self.ws is None:
if self.ws is None and self.ws_future is not None:
loop = IOLoop.current()
loop.add_future(self.ws_future, lambda future: self.handle_incoming_message(message))
else:
Expand Down
44 changes: 24 additions & 20 deletions jupyter_server/gateway/gateway_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def _url_validate(self, proposal):
@default("ws_url")
def _ws_url_default(self):
default_value = os.environ.get(self.ws_url_env)
if default_value is None and self.gateway_enabled:
if self.url is not None and default_value is None and self.gateway_enabled:
default_value = self.url.lower().replace("http", "ws")
return default_value

Expand Down Expand Up @@ -462,7 +462,7 @@ def _gateway_retry_max_default(self):
)
gateway_token_renewer_class_env = "JUPYTER_GATEWAY_TOKEN_RENEWER_CLASS"
gateway_token_renewer_class = Type(
klass=GatewayTokenRenewerBase,
klass=GatewayTokenRenewerBase, # type:ignore[type-abstract]
config=True,
help="""The class to use for Gateway token renewal. (JUPYTER_GATEWAY_TOKEN_RENEWER_CLASS env var)""",
)
Expand Down Expand Up @@ -546,7 +546,9 @@ def __init__(self, **kwargs):
"""Initialize a gateway client."""
super().__init__(**kwargs)
self._connection_args = {} # initialized on first use
self.gateway_token_renewer = self.gateway_token_renewer_class(parent=self, log=self.log)
self.gateway_token_renewer = self.gateway_token_renewer_class(
parent=self, log=self.log
) # type:ignore[operator]

# store of cookies with store time
self._cookies: ty.Dict[str, ty.Tuple[Morsel, datetime]] = {}
Expand All @@ -570,11 +572,12 @@ def init_connection_args(self):
# Ensure any adjustments are reflected in env.
os.environ["KERNEL_LAUNCH_TIMEOUT"] = str(GatewayClient.KERNEL_LAUNCH_TIMEOUT)

self._connection_args["headers"] = json.loads(self.headers)
if self.auth_header_key not in self._connection_args["headers"]:
self._connection_args["headers"].update(
{f"{self.auth_header_key}": f"{self.auth_scheme} {self.auth_token}"}
)
if self.headers:
self._connection_args["headers"] = json.loads(self.headers)
if self.auth_header_key not in self._connection_args["headers"]:
self._connection_args["headers"].update(
{f"{self.auth_header_key}": f"{self.auth_scheme} {self.auth_token}"}
)
self._connection_args["connect_timeout"] = self.connect_timeout
self._connection_args["request_timeout"] = self.request_timeout
self._connection_args["validate_cert"] = self.validate_cert
Expand All @@ -598,18 +601,19 @@ def load_connection_args(self, **kwargs):

# Give token renewal a shot at renewing the token
prev_auth_token = self.auth_token
try:
self.auth_token = self.gateway_token_renewer.get_token(
self.auth_header_key, self.auth_scheme, self.auth_token
)
except Exception as ex:
self.log.error(
f"An exception occurred attempting to renew the "
f"Gateway authorization token using an instance of class "
f"'{self.gateway_token_renewer_class}'. The request will "
f"proceed using the current token value. Exception was: {ex}"
)
self.auth_token = prev_auth_token
if self.auth_token:
try:
self.auth_token = self.gateway_token_renewer.get_token(
self.auth_header_key, self.auth_scheme, self.auth_token
)
except Exception as ex:
self.log.error(
f"An exception occurred attempting to renew the "
f"Gateway authorization token using an instance of class "
f"'{self.gateway_token_renewer_class}'. The request will "
f"proceed using the current token value. Exception was: {ex}"
)
self.auth_token = prev_auth_token

for arg, value in self._connection_args.items():
if arg == "headers":
Expand Down
6 changes: 5 additions & 1 deletion jupyter_server/gateway/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ def _replace_path_kernelspec_resources(self, kernel_specs):
This enables clients to properly route through jupyter_server to a gateway
for kernel resources such as logo files
"""
if not self.parent:
return {}
kernelspecs = kernel_specs["kernelspecs"]
for kernel_name in kernelspecs:
resources = kernelspecs[kernel_name]["resources"]
Expand Down Expand Up @@ -273,6 +275,8 @@ async def get_all_specs(self):
# If different log a warning and reset the default. However, the
# caller of this method will still return this server's value until
# the next fetch of kernelspecs - at which time they'll match.
if not self.parent:
return {}
km = self.parent.kernel_manager
remote_default_kernel_name = fetched_kspecs.get("default")
if remote_default_kernel_name != km.default_kernel_name:
Expand Down Expand Up @@ -416,7 +420,7 @@ def client(self, **kwargs):

# add kwargs last, for manual overrides
kw.update(kwargs)
return self.client_factory(**kw)
return self.client_factory(**kw) # type:ignore[operator]

async def refresh_model(self, model=None):
"""Refresh the kernel model.
Expand Down
30 changes: 18 additions & 12 deletions jupyter_server/serverapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -1879,21 +1879,25 @@ def init_configurables(self):
# this determination, instantiate the GatewayClient config singleton.
self.gateway_config = GatewayClient.instance(parent=self)

if not issubclass(self.kernel_manager_class, AsyncMappingKernelManager):
if not issubclass(
self.kernel_manager_class, AsyncMappingKernelManager # type:ignore[arg-type]
):
warnings.warn(
"The synchronous MappingKernelManager class is deprecated and will not be supported in Jupyter Server 3.0",
DeprecationWarning,
stacklevel=2,
)

if not issubclass(self.contents_manager_class, AsyncContentsManager):
if not issubclass(
self.contents_manager_class, AsyncContentsManager # type:ignore[arg-type]
):
warnings.warn(
"The synchronous ContentsManager classes are deprecated and will not be supported in Jupyter Server 3.0",
DeprecationWarning,
stacklevel=2,
)

self.kernel_spec_manager = self.kernel_spec_manager_class(
self.kernel_spec_manager = self.kernel_spec_manager_class( # type:ignore[operator]
parent=self,
)

Expand All @@ -1915,21 +1919,21 @@ def init_configurables(self):
"because jupyter-client's version does not allow them (should be >8.3.0)."
)

self.kernel_manager = self.kernel_manager_class(**kwargs)
self.contents_manager = self.contents_manager_class(
self.kernel_manager = self.kernel_manager_class(**kwargs) # type:ignore[operator]
self.contents_manager = self.contents_manager_class( # type:ignore[operator]
parent=self,
log=self.log,
)
# Trigger a default/validation here explicitly while we still support the
# deprecated trait on ServerApp (FIXME remove when deprecation finalized)
self.contents_manager.preferred_dir # noqa
self.session_manager = self.session_manager_class(
self.session_manager = self.session_manager_class( # type:ignore[operator]
parent=self,
log=self.log,
kernel_manager=self.kernel_manager,
contents_manager=self.contents_manager,
)
self.config_manager = self.config_manager_class(
self.config_manager = self.config_manager_class( # type:ignore[operator]
parent=self,
log=self.log,
)
Expand Down Expand Up @@ -1958,7 +1962,9 @@ def init_configurables(self):
f"Ignoring deprecated config ServerApp.login_handler_class={self.login_handler_class}."
" Superseded by ServerApp.identity_provider_class={self.identity_provider_class}."
)
self.identity_provider = self.identity_provider_class(**identity_provider_kwargs)
self.identity_provider = self.identity_provider_class(
**identity_provider_kwargs
) # type:ignore[operator]

if self.identity_provider_class is LegacyIdentityProvider:
# legacy config stored the password in tornado_settings
Expand All @@ -1979,7 +1985,7 @@ def init_configurables(self):
# that means it has some config that should take higher priority than deprecated ServerApp.token
self.log.warning("Ignoring deprecated ServerApp.token config")

self.authorizer = self.authorizer_class(
self.authorizer = self.authorizer_class( # type:ignore[operator]
parent=self, log=self.log, identity_provider=self.identity_provider
)

Expand Down Expand Up @@ -2100,7 +2106,7 @@ def init_webapp(self):
if not self.ssl_options:
# could be an empty dict or None
# None indicates no SSL config
self.ssl_options = None
self.ssl_options = None # type:ignore[assignment]
else:
# SSL may be missing, so only import it if it's to be used
import ssl
Expand Down Expand Up @@ -2130,7 +2136,7 @@ def init_resources(self):
old_soft, old_hard = resource.getrlimit(resource.RLIMIT_NOFILE)
soft = self.min_open_files_limit
hard = old_hard
if old_soft < soft:
if soft is not None and old_soft < soft:
if hard < soft:
hard = soft
self.log.debug(
Expand Down Expand Up @@ -2911,7 +2917,7 @@ async def _cleanup(self):
await self.cleanup_extensions()
await self.cleanup_kernels()
try:
await self.kernel_websocket_connection_class.close_all()
await self.kernel_websocket_connection_class.close_all() # type:ignore[attr-defined]
except AttributeError:
# This can happen in two different scenarios:
#
Expand Down
5 changes: 2 additions & 3 deletions jupyter_server/services/contents/filecheckpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,9 @@ class FileCheckpoints(FileManagerMixin, Checkpoints):
root_dir = Unicode(config=True)

def _root_dir_default(self):
try:
return self.parent.root_dir
except AttributeError:
if not self.parent:
return os.getcwd()
return self.parent.root_dir

# ContentsManager-dependent checkpoint API
def create_checkpoint(self, contents_mgr, path):
Expand Down
7 changes: 4 additions & 3 deletions jupyter_server/services/contents/filemanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,9 @@ class FileContentsManager(FileManagerMixin, ContentsManager):

@default("root_dir")
def _default_root_dir(self):
try:
return self.parent.root_dir
except AttributeError:
if not self.parent:
return os.getcwd()
return self.parent.root_dir

@validate("root_dir")
def _validate_root_dir(self, proposal):
Expand All @@ -65,6 +64,8 @@ def _validate_root_dir(self, proposal):

@default("preferred_dir")
def _default_preferred_dir(self):
if not self.parent:
return ""
try:
value = self.parent.preferred_dir
if value == self.parent.root_dir:
Expand Down
15 changes: 8 additions & 7 deletions jupyter_server/services/contents/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,12 @@ def _validate_preferred_dir(self, proposal):
raise TraitError(e.log_message) from e
if not dir_exists:
raise TraitError(_i18n("Preferred directory not found: %r") % value)
try:
if value != self.parent.preferred_dir:
self.parent.preferred_dir = os.path.join(self.root_dir, *value.split("/"))
except (AttributeError, TraitError):
pass
if self.parent:
try:
if value != self.parent.preferred_dir:
self.parent.preferred_dir = os.path.join(self.root_dir, *value.split("/"))
except TraitError:
pass
return value

allow_hidden = Bool(False, config=True, help="Allow access to hidden files")
Expand Down Expand Up @@ -324,7 +325,7 @@ def run_post_save_hooks(self, model, os_path):

@default("checkpoints")
def _default_checkpoints(self):
return self.checkpoints_class(**self.checkpoints_kwargs)
return self.checkpoints_class(**self.checkpoints_kwargs) # type:ignore[operator]

@default("checkpoints_kwargs")
def _default_checkpoints_kwargs(self):
Expand Down Expand Up @@ -760,7 +761,7 @@ class AsyncContentsManager(ContentsManager):

@default("checkpoints")
def _default_checkpoints(self):
return self.checkpoints_class(**self.checkpoints_kwargs)
return self.checkpoints_class(**self.checkpoints_kwargs) # type:ignore[operator]

@default("checkpoints_kwargs")
def _default_checkpoints_kwargs(self):
Expand Down
3 changes: 2 additions & 1 deletion jupyter_server/services/events/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ async def get(self, *args, **kwargs):
"""Get an event socket."""
self.pre_get()
res = super().get(*args, **kwargs)
await res
if res is not None:
await res

async def event_listener(self, logger: EventLogger, schema_id: str, data: dict) -> None:
"""Write an event message."""
Expand Down
Loading

0 comments on commit 3544deb

Please sign in to comment.