Skip to content

Commit 59b4668

Browse files
committed
fix all mypy errors under rooms/
1 parent cdc24bf commit 59b4668

File tree

4 files changed

+49
-29
lines changed

4 files changed

+49
-29
lines changed

jupyter_server_documents/rooms/yroom.py

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717

1818
if TYPE_CHECKING:
1919
import logging
20-
from typing import Coroutine, Literal, Tuple, Any
20+
from typing import Callable, Coroutine, Literal, Tuple, Any
2121
from .yroom_manager import YRoomManager
22-
from jupyter_server_fileid.manager import BaseFileIdManager
22+
from jupyter_server_fileid.manager import BaseFileIdManager # type: ignore
2323
from jupyter_server.services.contents.manager import ContentsManager
24-
from pycrdt import TransactionEvent
24+
from pycrdt import TransactionEvent, Subscription
2525
from ..outputs.manager import OutputsManager
2626

2727
class YRoom(LoggingConfigurable):
@@ -136,7 +136,7 @@ class YRoom(LoggingConfigurable):
136136
documentation for more info.
137137
"""
138138

139-
_jupyter_ydoc_observers: dict[str, callable[[str, Any], Any]]
139+
_jupyter_ydoc_observers: dict[str, Callable[[str, Any], Any]]
140140
"""
141141
Dictionary of JupyterYDoc observers added by consumers of this room.
142142
@@ -167,10 +167,10 @@ class YRoom(LoggingConfigurable):
167167
`self._message_queue.put_nowait(None)`.
168168
"""
169169

170-
_awareness_subscription: pycrdt.Subscription
170+
_awareness_subscription: str
171171
"""Subscription to awareness changes."""
172172

173-
_ydoc_subscription: pycrdt.Subscription
173+
_ydoc_subscription: Subscription
174174
"""Subscription to YDoc changes."""
175175

176176
_stopped: bool
@@ -346,6 +346,8 @@ async def get_jupyter_ydoc(self) -> YBaseDoc:
346346
message = "There is no Jupyter ydoc for global awareness scenario"
347347
self.log.error(message)
348348
raise Exception(message)
349+
if self._jupyter_ydoc is None:
350+
raise RuntimeError("Jupyter YDoc is not available")
349351
if self.file_api:
350352
await self.file_api.until_content_loaded
351353
return self._jupyter_ydoc
@@ -428,7 +430,7 @@ def handle_message(self, client_id: str, message: bytes) -> None:
428430

429431
# Determine message type & subtype from header
430432
message_type = message[0]
431-
sync_message_subtype = "*"
433+
sync_message_subtype = -1 # invalid sentinel value
432434
# message subtypes only exist on sync messages, hence this condition
433435
if message_type == YMessageType.SYNC and len(message) >= 2:
434436
sync_message_subtype = message[1]
@@ -585,7 +587,7 @@ def _on_ydoc_update(self, event: TransactionEvent) -> None:
585587
self._broadcast_message(message, message_type="SyncUpdate")
586588

587589

588-
def observe_jupyter_ydoc(self, observer: callable[[str, Any], Any]) -> str:
590+
def observe_jupyter_ydoc(self, observer: Callable[[str, Any], Any]) -> str:
589591
"""
590592
Adds an observer callback to the JupyterYDoc that fires on change.
591593
The callback should accept 2 arguments:
@@ -604,8 +606,9 @@ def observe_jupyter_ydoc(self, observer: callable[[str, Any], Any]) -> str:
604606
Returns an `observer_id: str` that can be passed to
605607
`unobserve_jupyter_ydoc()` to remove the observer.
606608
"""
607-
observer_id = uuid.uuid4()
609+
observer_id = str(uuid.uuid4())
608610
self._jupyter_ydoc_observers[observer_id] = observer
611+
return observer_id
609612

610613

611614
def unobserve_jupyter_ydoc(self, observer_id: str):
@@ -745,7 +748,10 @@ def _on_awareness_update(self, type: str, changes: tuple[dict[str, Any], Any]) -
745748
self.log.debug(f"awareness update, updated_clients={updated_clients}")
746749
state = self._awareness.encode_awareness_update(updated_clients)
747750
message = pycrdt.create_awareness_message(state)
748-
self.log.debug(f"awareness update, message={message}")
751+
# !r ensures binary messages show as `b'...'` instead of being decoded
752+
# into jargon in log statements.
753+
# https://docs.python.org/3/library/string.html#format-string-syntax
754+
self.log.debug(f"awareness update, message={message!r}")
749755
self._broadcast_message(message, "AwarenessUpdate")
750756

751757

@@ -827,8 +833,11 @@ def stop(self, close_code: int = 1001, immediately: bool = False) -> None:
827833
self._message_queue.get_nowait()
828834
self._message_queue.task_done()
829835
else:
830-
client_id, message = self._message_queue.get_nowait()
831-
self.handle_message(client_id, message)
836+
queue_item = self._message_queue.get_nowait()
837+
if queue_item is not None:
838+
client_id, message = queue_item
839+
self.handle_message(client_id, message)
840+
self._message_queue.task_done()
832841

833842
# Stop the `_process_message_queue` task by enqueueing `None`
834843
self._message_queue.put_nowait(None)
@@ -924,8 +933,9 @@ def restart(self, close_code: int = 1001, immediately: bool = False) -> None:
924933
self.clients.restart()
925934

926935
# Restart `YRoomFileAPI` & reload the document
927-
self.file_api.restart()
928-
self.file_api.load_content_into(self._jupyter_ydoc)
936+
if self.file_api is not None and self._jupyter_ydoc is not None:
937+
self.file_api.restart()
938+
self.file_api.load_content_into(self._jupyter_ydoc)
929939

930940
# Restart `_process_message_queue()` task
931941
asyncio.create_task(self._process_message_queue())
@@ -952,16 +962,16 @@ def should_ignore_state_update(event: pycrdt.MapEvent) -> bool:
952962
# `False` immediately if:
953963
# - a key was updated to a value different from the previous value
954964
# - a key was added with a value different from the previous value
955-
for key in event.keys.keys():
956-
update_info = event.keys[key]
965+
for key in getattr(event, 'keys', {}).keys():
966+
update_info = getattr(event, 'keys', {})[key]
957967
action = update_info.get('action', None)
958968
if action == 'update':
959969
old_value = update_info.get('oldValue', None)
960970
new_value = update_info.get('newValue', None)
961971
if old_value != new_value:
962972
return False
963973
elif action == "add":
964-
old_value = event.target.get(key, None)
974+
old_value = getattr(event, 'target', {}).get(key, None)
965975
new_value = update_info.get('newValue', None)
966976
if old_value != new_value:
967977
return False

jupyter_server_documents/rooms/yroom_events_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from __future__ import annotations
22
from jupyter_events import EventLogger
3-
from jupyter_server_fileid.manager import BaseFileIdManager
3+
from jupyter_server_fileid.manager import BaseFileIdManager # type: ignore
44
from traitlets.config import LoggingConfigurable
55
from typing import TYPE_CHECKING
66

jupyter_server_documents/rooms/yroom_file_api.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
if TYPE_CHECKING:
1313
from typing import Any, Coroutine, Literal
1414
from .yroom import YRoom
15-
from jupyter_server_fileid.manager import BaseFileIdManager
15+
from jupyter_server_fileid.manager import BaseFileIdManager # type: ignore
1616
from jupyter_server.services.contents.manager import ContentsManager
1717
from ..outputs.manager import OutputsManager
1818

@@ -56,7 +56,6 @@ class YRoomFileAPI(LoggingConfigurable):
5656

5757
# See `filemanager.py` in `jupyter_server` for references on supported file
5858
# formats & file types.
59-
room_id: str
6059
file_format: Literal["text", "base64"]
6160
file_type: Literal["file", "notebook"]
6261
file_id: str

jupyter_server_documents/rooms/yroom_manager.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import asyncio
66
import traitlets
77
from traitlets.config import LoggingConfigurable
8-
from jupyter_server_fileid.manager import BaseFileIdManager
8+
from jupyter_server_fileid.manager import BaseFileIdManager # type: ignore
99

1010
from ..outputs.manager import OutputsManager
1111

@@ -53,7 +53,7 @@ class YRoomManager(LoggingConfigurable):
5353
this declaration only hints the type for type checkers.
5454
"""
5555

56-
_rooms_by_id: dict[str, YRoom] = traitlets.Dict(default_value={})
56+
_rooms_by_id = traitlets.Dict(default_value={})
5757
"""
5858
Dictionary of active `YRoom` instances, keyed by room ID. Rooms are never
5959
deleted from this dictionary.
@@ -62,7 +62,7 @@ class YRoomManager(LoggingConfigurable):
6262
out-of-band. See #116.
6363
"""
6464

65-
_inactive_rooms: set[str] = traitlets.Set()
65+
_inactive_rooms = traitlets.Set()
6666
"""
6767
Set of room IDs that were marked inactive on the last iteration of
6868
`_watch_rooms()`. If a room is inactive and its ID is present in this set,
@@ -84,23 +84,34 @@ def __init__(self, *args, **kwargs):
8484

8585
@property
8686
def fileid_manager(self) -> BaseFileIdManager:
87+
if self.parent.serverapp is None:
88+
raise RuntimeError("ServerApp is not available")
8789
manager = self.parent.serverapp.web_app.settings.get("file_id_manager", None)
8890
assert isinstance(manager, BaseFileIdManager)
8991
return manager
9092

9193

9294
@property
9395
def contents_manager(self) -> ContentsManager:
96+
if self.parent.serverapp is None:
97+
raise RuntimeError("ServerApp is not available")
9498
return self.parent.serverapp.contents_manager
9599

96100

97101
@property
98102
def event_logger(self) -> EventLogger:
99-
return self.parent.serverapp.event_logger
103+
if self.parent.serverapp is None:
104+
raise RuntimeError("ServerApp is not available")
105+
event_logger = self.parent.serverapp.event_logger
106+
if event_logger is None:
107+
raise RuntimeError("Event logger is not available")
108+
return event_logger
100109

101110

102111
@property
103112
def outputs_manager(self) -> OutputsManager:
113+
if not hasattr(self.parent, 'outputs_manager'):
114+
raise RuntimeError("Outputs manager is not available")
104115
return self.parent.outputs_manager
105116

106117

@@ -156,17 +167,17 @@ def delete_room(self, room_id: str) -> None:
156167
"""
157168
yroom = self._rooms_by_id.pop(room_id, None)
158169
if not yroom:
159-
return
170+
return None
160171

161172
self.log.info(f"Stopping YRoom '{room_id}'.")
162173
try:
163174
yroom.stop()
164-
return True
175+
return None
165176
except Exception as e:
166177
self.log.exception(
167178
f"Exception raised when stopping YRoom '{room_id}: "
168179
)
169-
return False
180+
return None
170181

171182

172183
async def _watch_rooms(self) -> None:
@@ -274,9 +285,9 @@ async def stop(self) -> None:
274285

275286
# Define task that deletes the room and waits until the content is saved
276287
async def delete_then_save(room_id: str, room: YRoom):
277-
ret = self.delete_room(room_id)
288+
self.delete_room(room_id)
278289
await room.until_saved
279-
return ret
290+
return None
280291

281292
# Delete all rooms concurrently using `delete_then_save()`
282293
for room_id, room in self._rooms_by_id.items():

0 commit comments

Comments
 (0)