Skip to content

Commit 015a539

Browse files
committed
Address linting test issues
1 parent bafcdce commit 015a539

File tree

4 files changed

+60
-61
lines changed

4 files changed

+60
-61
lines changed

jupyter_server/services/kernelspecs/kernelspec_cache.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66
import os
77
import sys
88
from abc import ABC, ABCMeta, abstractmethod
9-
from typing import Dict, Optional, Union
9+
from typing import Any, Dict, Optional, Union
1010

1111
# See compatibility note on `group` keyword in https://docs.python.org/3/library/importlib.metadata.html#entry-points
1212
if sys.version_info < (3, 10): # pragma: no cover
1313
from importlib_metadata import EntryPoint, entry_points
1414
else: # pragma: no cover
1515
from importlib.metadata import EntryPoint, entry_points
1616

17-
from jupyter_client.kernelspec import KernelSpec
17+
from jupyter_client.kernelspec import KernelSpec, KernelSpecManager
1818
from traitlets.config import LoggingConfigurable
1919
from traitlets.traitlets import CBool, Instance, Unicode, default
2020

@@ -63,10 +63,10 @@ def _monitor_name_default(self):
6363

6464
# The kernelspec cache consists of a dictionary mapping the kernel name to the actual
6565
# kernelspec data (CacheItemType).
66-
cache_items: Dict
66+
cache_items: Dict[str, CacheItemType]
6767
cache_misses: int
6868

69-
def __init__(self, kernel_spec_manager, **kwargs) -> None:
69+
def __init__(self, kernel_spec_manager: KernelSpecManager, **kwargs: Any) -> None:
7070
"""Initialize the cache."""
7171
super().__init__(**kwargs)
7272
self.kernel_spec_manager = kernel_spec_manager
@@ -86,7 +86,7 @@ def __del__(self):
8686
self.kernel_spec_monitor.destroy()
8787
self.kernel_spec_monitor = None
8888

89-
async def get_kernel_spec(self, kernel_name: str) -> KernelSpec:
89+
async def get_kernel_spec(self, kernel_name: str) -> Optional[KernelSpec]:
9090
"""Get the named kernel specification.
9191
9292
This method is equivalent to calling KernelSpecManager.get_kernel_spec(). If
@@ -130,7 +130,7 @@ def get_item(self, kernel_name: str) -> Optional[KernelSpec]:
130130
If cache is disabled or the item is not in the cache, None is returned;
131131
otherwise, a KernelSpec instance of the item is returned.
132132
"""
133-
kernelspec = None
133+
kernelspec: Optional[KernelSpec] = None
134134
if self.cache_enabled:
135135
cache_item = self.cache_items.get(kernel_name.lower())
136136
if cache_item: # Convert to KernelSpec
@@ -149,7 +149,7 @@ def get_item(self, kernel_name: str) -> Optional[KernelSpec]:
149149
)
150150
return kernelspec
151151

152-
def get_all_items(self) -> Dict[str, CacheItemType]:
152+
def get_all_items(self) -> Dict: # type is Dict[str, CacheItemType]
153153
"""Retrieves all kernel specification from the cache.
154154
155155
If cache is disabled or no items are in the cache, an empty dictionary is returned;
@@ -175,9 +175,9 @@ def put_item(self, kernel_name: str, cache_item: Union[KernelSpec, CacheItemType
175175
self.log.info(f"KernelSpecCache: adding/updating kernelspec: {kernel_name}")
176176
if type(cache_item) is KernelSpec:
177177
cache_item = KernelSpecCache.kernel_spec_to_cache_item(cache_item)
178-
self.cache_items[kernel_name.lower()] = cache_item
178+
self.cache_items[kernel_name.lower()] = cache_item # type: ignore
179179

180-
def put_all_items(self, kernelspecs: Dict[str, CacheItemType]) -> None:
180+
def put_all_items(self, kernelspecs: Dict[str, Union[KernelSpec, CacheItemType]]) -> None:
181181
"""Adds or updates a dictionary of kernel specification in the cache."""
182182
for kernel_name, cache_item in kernelspecs.items():
183183
self.put_item(kernel_name, cache_item)
@@ -205,6 +205,7 @@ def kernel_spec_to_cache_item(kernelspec: KernelSpec) -> CacheItemType:
205205
@staticmethod
206206
def cache_item_to_kernel_spec(cache_item: CacheItemType) -> KernelSpec:
207207
"""Converts a CacheItemType to a KernelSpec instance for user consumption."""
208+
assert type(cache_item["spec"]) is dict
208209
kernel_spec = KernelSpec(resource_dir=cache_item["resource_dir"], **cache_item["spec"])
209210
return kernel_spec
210211

@@ -220,7 +221,7 @@ class KernelSpecMonitorBase( # type:ignore[misc]
220221

221222
@classmethod
222223
def create_instance(
223-
cls, kernel_spec_cache: KernelSpecCache, **kwargs
224+
cls, kernel_spec_cache: KernelSpecCache, **kwargs: Any
224225
) -> "KernelSpecMonitorBase":
225226
"""Creates an instance of the monitor class configured on the KernelSpecCache instance."""
226227

jupyter_server/services/kernelspecs/monitors/polling_monitor.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
import json
55
import os
66
from hashlib import md5
7-
from typing import Dict
7+
from typing import Any, Dict
88

99
from overrides import overrides
1010
from traitlets.traitlets import Float, default
1111

1212
from ..kernelspec_cache import KernelSpecCache, KernelSpecMonitorBase
1313

1414

15-
class KernelSpecPollingMonitor(KernelSpecMonitorBase):
15+
class KernelSpecPollingMonitor(KernelSpecMonitorBase): # type:ignore[misc]
1616
"""Polling monitor that uses a periodic poll period to reload the kernelspec cache."""
1717

1818
interval_env = "JUPYTER_POLLING_MONITOR_INTERVAL"
@@ -32,7 +32,7 @@ def _interval_default(self):
3232
# the churn and noise when publishing events
3333
hash_values: Dict[str, str]
3434

35-
def __init__(self, kernel_spec_cache: KernelSpecCache, **kwargs):
35+
def __init__(self, kernel_spec_cache: KernelSpecCache, **kwargs: Any):
3636
"""Initialize the handler."""
3737
super().__init__(**kwargs)
3838
self.kernel_spec_cache: KernelSpecCache = kernel_spec_cache

jupyter_server/services/kernelspecs/monitors/watchdog_monitor.py

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,25 @@
22
# Copyright (c) Jupyter Development Team.
33
# Distributed under the terms of the Modified BSD License.
44
import os
5+
from typing import Any, Set, Tuple
56

67
from overrides import overrides
7-
from watchdog.events import FileMovedEvent, FileSystemEventHandler
8+
from watchdog.events import FileSystemEventHandler
89
from watchdog.observers import Observer
910

1011
from ..kernelspec_cache import KernelSpecCache, KernelSpecMonitorBase
1112

1213

13-
class KernelSpecWatchdogMonitor(KernelSpecMonitorBase):
14+
class KernelSpecWatchdogMonitor(KernelSpecMonitorBase): # type:ignore[misc]
1415
"""Watchdog handler that filters on specific files deemed representative of a kernel specification."""
1516

16-
def __init__(self, kernel_spec_cache: KernelSpecCache, **kwargs):
17+
def __init__(self, kernel_spec_cache: KernelSpecCache, **kwargs: Any):
1718
"""Initialize the handler."""
1819
super().__init__(**kwargs)
1920
self.kernel_spec_cache: KernelSpecCache = kernel_spec_cache
2021
self.kernel_spec_manager = self.kernel_spec_cache.kernel_spec_manager
21-
self.observed_dirs = set() # Tracks which directories are being watched
22-
self.observer = None
22+
self.observed_dirs: Set[str] = set() # Tracks which directories are being watched
23+
self.observer: Any = None
2324

2425
@overrides
2526
def initialize(self) -> None:
@@ -58,7 +59,7 @@ class WatchDogHandler(FileSystemEventHandler):
5859
# files in the future) should be added to this list - at which time it should become configurable.
5960
watched_files = ["kernel.json"]
6061

61-
def __init__(self, monitor: "KernelSpecWatchdogMonitor", **kwargs):
62+
def __init__(self, monitor: "KernelSpecWatchdogMonitor", **kwargs: Any):
6263
"""Initialize the handler."""
6364
super().__init__(**kwargs)
6465
self.kernel_spec_cache = monitor.kernel_spec_cache
@@ -73,14 +74,6 @@ def dispatch(self, event):
7374
"""
7475

7576
if os.path.basename(event.src_path) in self.watched_files:
76-
src_resource_dir = os.path.dirname(event.src_path)
77-
event.src_resource_dir = src_resource_dir
78-
event.src_kernel_name = os.path.basename(src_resource_dir)
79-
if type(event) is FileMovedEvent:
80-
dest_resource_dir = os.path.dirname(event.dest_path)
81-
event.dest_resource_dir = dest_resource_dir
82-
event.dest_kernel_name = os.path.basename(dest_resource_dir)
83-
8477
super().dispatch(event)
8578

8679
def on_created(self, event):
@@ -89,19 +82,18 @@ def on_created(self, event):
8982
This will trigger a call to the configured KernelSpecManager to fetch the instance
9083
associated with the created file, which is then added to the cache.
9184
"""
92-
kernel_name = event.src_kernel_name
85+
resource_dir, kernel_name = WatchDogHandler._extract_info(event.src_path)
9386
try:
9487
kernelspec = self.kernel_spec_cache.kernel_spec_manager.get_kernel_spec(kernel_name)
9588
self.kernel_spec_cache.put_item(kernel_name, kernelspec)
9689
except Exception as e:
9790
self.log.warning(
98-
"The following exception occurred creating cache entry for: {src_resource_dir} "
99-
"- continuing... ({e})".format(src_resource_dir=event.src_resource_dir, e=e)
91+
f"The following exception occurred creating cache entry for: {resource_dir} - continuing... ({e})"
10092
)
10193

10294
def on_deleted(self, event):
10395
"""Fires when a watched file is deleted, triggering a removal of the corresponding item from the cache."""
104-
kernel_name = event.src_kernel_name
96+
_, kernel_name = WatchDogHandler._extract_info(event.src_path)
10597
self.kernel_spec_cache.remove_item(kernel_name)
10698

10799
def on_modified(self, event):
@@ -110,14 +102,13 @@ def on_modified(self, event):
110102
This will trigger a call to the configured KernelSpecManager to fetch the instance
111103
associated with the modified file, which is then replaced in the cache.
112104
"""
113-
kernel_name = event.src_kernel_name
105+
resource_dir, kernel_name = WatchDogHandler._extract_info(event.src_path)
114106
try:
115107
kernelspec = self.kernel_spec_cache.kernel_spec_manager.get_kernel_spec(kernel_name)
116108
self.kernel_spec_cache.put_item(kernel_name, kernelspec)
117109
except Exception as e:
118110
self.log.warning(
119-
"The following exception occurred updating cache entry for: {src_resource_dir} "
120-
"- continuing... ({e})".format(src_resource_dir=event.src_resource_dir, e=e)
111+
f"The following exception occurred updating cache entry for: {resource_dir} - continuing... ({e})"
121112
)
122113

123114
def on_moved(self, event):
@@ -126,8 +117,15 @@ def on_moved(self, event):
126117
This will trigger the update of the existing cached item, replacing its resource_dir entry
127118
with that of the new destination.
128119
"""
129-
src_kernel_name = event.src_kernel_name
130-
dest_kernel_name = event.dest_kernel_name
120+
_, src_kernel_name = WatchDogHandler._extract_info(event.src_path)
121+
dest_resource_dir, dest_kernel_name = WatchDogHandler._extract_info(event.dest_path)
131122
cache_item = self.kernel_spec_cache.remove_item(src_kernel_name)
132-
cache_item["resource_dir"] = event.dest_resource_dir
133-
self.kernel_spec_cache.put_item(dest_kernel_name, cache_item)
123+
if cache_item is not None:
124+
cache_item["resource_dir"] = dest_resource_dir
125+
self.kernel_spec_cache.put_item(dest_kernel_name, cache_item)
126+
127+
@staticmethod
128+
def _extract_info(dir_name: str) -> Tuple[str, str]:
129+
"""Extracts the resource directory and kernel_name from the given dir_name."""
130+
resource_dir: str = os.path.dirname(dir_name) # includes kernel_name
131+
return resource_dir, os.path.basename(resource_dir)

tests/services/kernelspecs/test_kernelspec_cache.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@
44

55
import asyncio
66
import json
7-
import os
87
import shutil
8+
from pathlib import Path
99

1010
import pytest
1111
from jupyter_client.kernelspec import NoSuchKernel
12-
from pytest_jupyter.utils import mkdir
1312
from traitlets.config import Config
1413

1514
from jupyter_server.services.kernelspecs.kernelspec_cache import KernelSpecCache
@@ -20,38 +19,39 @@
2019
}
2120

2221

23-
def _install_kernelspec(kernels_dir, kernel_name):
22+
def _install_kernelspec(kernels_dir: Path, kernel_name: str) -> Path:
2423
"""install a sample kernel in a kernels directory"""
25-
kernelspec_dir = os.path.join(kernels_dir, kernel_name)
26-
os.makedirs(kernelspec_dir)
27-
json_file = os.path.join(kernelspec_dir, "kernel.json")
24+
kernelspec_dir = kernels_dir / kernel_name
25+
kernelspec_dir.mkdir(parents=True)
26+
json_file = Path(kernelspec_dir) / "kernel.json"
2827
named_json = kernelspec_json.copy()
29-
named_json["display_name"] = named_json["display_name"].format(kernel_name=kernel_name)
30-
with open(json_file, "w") as f:
28+
named_json["display_name"] = str(named_json["display_name"]).format(kernel_name=kernel_name)
29+
with open(str(json_file), "w") as f:
3130
json.dump(named_json, f)
3231
return kernelspec_dir
3332

3433

35-
def _modify_kernelspec(kernelspec_dir, kernel_name):
36-
json_file = os.path.join(kernelspec_dir, "kernel.json")
34+
def _modify_kernelspec(kernelspec_dir: str, kernel_name: str) -> None:
35+
json_file = Path(kernelspec_dir) / "kernel.json"
3736
kernel_json = kernelspec_json.copy()
3837
kernel_json["display_name"] = f"{kernel_name} modified!"
39-
with open(json_file, "w") as f:
38+
with open(str(json_file), "w") as f:
4039
json.dump(kernel_json, f)
4140

4241

43-
kernelspec_location = pytest.fixture(lambda jp_data_dir: mkdir(jp_data_dir, "kernels"))
44-
other_kernelspec_location = pytest.fixture(
45-
lambda jp_env_jupyter_path: mkdir(jp_env_jupyter_path, "kernels")
46-
)
42+
@pytest.fixture
43+
def other_kernelspec_location(jp_env_jupyter_path):
44+
other_location = Path(jp_env_jupyter_path) / "kernels"
45+
other_location.mkdir()
46+
return other_location
4747

4848

4949
@pytest.fixture
50-
def setup_kernelspecs(jp_environ, kernelspec_location):
50+
def setup_kernelspecs(jp_environ, jp_kernel_dir):
5151
# Only populate factory info
52-
_install_kernelspec(str(kernelspec_location), "test1")
53-
_install_kernelspec(str(kernelspec_location), "test2")
54-
_install_kernelspec(str(kernelspec_location), "test3")
52+
_install_kernelspec(jp_kernel_dir, "test1")
53+
_install_kernelspec(jp_kernel_dir, "test2")
54+
_install_kernelspec(jp_kernel_dir, "test3")
5555

5656

5757
MONITORS = ["watchdog-monitor", "polling-monitor"]
@@ -83,7 +83,7 @@ def kernel_spec_cache(
8383
app.clear_instance()
8484

8585

86-
def get_delay_factor(kernel_spec_cache: KernelSpecCache):
86+
def get_delay_factor(kernel_spec_cache: KernelSpecCache) -> float:
8787
if kernel_spec_cache.cache_enabled:
8888
if kernel_spec_cache.monitor_name == "polling-monitor":
8989
return 2.0
@@ -117,11 +117,11 @@ async def test_get_modified_spec(kernel_spec_cache):
117117
assert kspec.display_name == "test2 modified!"
118118

119119

120-
async def test_add_spec(kernel_spec_cache, kernelspec_location, other_kernelspec_location):
120+
async def test_add_spec(kernel_spec_cache, jp_kernel_dir, other_kernelspec_location):
121121
with pytest.raises(NoSuchKernel):
122122
await kernel_spec_cache.get_kernel_spec("added") # this will increment cache_miss
123123

124-
_install_kernelspec(str(other_kernelspec_location), "added")
124+
_install_kernelspec(other_kernelspec_location, "added")
125125
# this will increment cache_miss prior to load
126126
kspec = await kernel_spec_cache.get_kernel_spec("added")
127127

@@ -130,7 +130,7 @@ async def test_add_spec(kernel_spec_cache, kernelspec_location, other_kernelspec
130130
assert kernel_spec_cache.cache_misses == (2 if kernel_spec_cache.cache_enabled else 0)
131131

132132
# Add another to an existing observed directory, no cache miss here
133-
_install_kernelspec(str(kernelspec_location), "added2")
133+
_install_kernelspec(jp_kernel_dir, "added2")
134134
await asyncio.sleep(
135135
get_delay_factor(kernel_spec_cache)
136136
) # sleep to allow cache to add item (no cache miss in this case)

0 commit comments

Comments
 (0)