11"""
22A new Kernel client that is aware of ydocuments.
33"""
4+ from __future__ import annotations
45import anyio
56import asyncio
6- import json
77import typing as t
88
99from traitlets import Set , Instance , Any , Type , default
1616
1717from .kernel_client_abc import AbstractDocumentAwareKernelClient
1818
19+ if t .TYPE_CHECKING :
20+ from jupyter_server_documents .rooms .yroom_manager import YRoomManager
21+
1922
2023class DocumentAwareKernelClient (AsyncKernelClient ):
2124 """
@@ -39,11 +42,6 @@ def _default_message_cache(self):
3942 # message is received.
4043 _listeners = Set (allow_none = True )
4144
42- # A set of YRooms that will intercept output and kernel
43- # status messages.
44- _yrooms : t .Set [YRoom ] = Set (trait = Instance (YRoom ), default_value = set ())
45-
46-
4745 output_processor = Instance (
4846 OutputProcessor ,
4947 allow_none = True
@@ -58,6 +56,24 @@ def _default_message_cache(self):
5856 def _default_output_processor (self ) -> OutputProcessor :
5957 self .log .info ("Creating output processor" )
6058 return self .output_process_class (parent = self , config = self .config )
59+
60+ _yroom_manager : YRoomManager | None
61+ """
62+ The YRoomManager registered via `self.bind_yroom_manager()`, which must be
63+ called before adding any `YRoom` via `self.add_yroom()`.
64+ """
65+
66+ _yroom_ids : set [str ]
67+ """
68+ The set of room IDs that are registered with this kernel client. This class
69+ stores room IDs instead of `YRoom` instances because `YRoom` instances may
70+ be deleted once inactive.
71+ """
72+
73+ def __init__ (self , * args , ** kwargs ):
74+ super ().__init__ (* args , ** kwargs )
75+ self ._yroom_manager = None
76+ self ._yroom_ids = set ()
6177
6278 async def start_listening (self ):
6379 """Start listening to messages coming from the kernel.
@@ -286,18 +302,63 @@ async def handle_document_related_message(self, msg: t.List[bytes]) -> t.Optiona
286302 # Default return if message is processed and does not need forwarding
287303 return msg
288304
305+ @property
306+ def _yrooms (self ) -> list [YRoom ]:
307+ """
308+ Returns the list of YRoom instances registered to this kernel client.
309+ """
310+ if len (self ._yroom_ids ) == 0 :
311+ return []
312+
313+ assert self ._yroom_manager
314+ rooms : list [YRoom ] = []
315+
316+ # Always call `get_room()` to get the latest reference to the room. We
317+ # must do this since rooms may be deleted upon inactivity. The
318+ # `get_room()` method returns a cached value as long as the room was not
319+ # deleted, so this is very fast in most cases.
320+ for room_id in self ._yroom_ids :
321+ room = self ._yroom_manager .get_room (room_id )
322+ rooms .append (room )
323+
324+ return rooms
325+
289326 async def add_yroom (self , yroom : YRoom ):
290327 """
291- Register a YRoom with this kernel client. YRooms will
292- intercept display and kernel status messages.
328+ Register a `YRoom` with this kernel client, given the room ID.
329+ Registered `YRoom`s will intercept display and kernel status messages.
330+
331+ `self.bind_yroom_manager()` must be called before using this method.
293332 """
294- self ._yrooms .add (yroom )
333+ assert self ._yroom_manager
334+ self ._yroom_ids .add (yroom .room_id )
335+ self .log .info (
336+ f"Added room '{ yroom .room_id } ' to kernel '{ self .kernel_name } '. "
337+ f"Total rooms: { len (self ._yroom_ids )} "
338+ )
295339
296340 async def remove_yroom (self , yroom : YRoom ):
297341 """
298- De-register a YRoom from handling kernel client messages.
342+ De-register a `YRoom` from this kernel client, given the room ID.
343+
344+ `self.bind_yroom_manager()` must be called before using this method.
345+ """
346+ self ._yrooms_ids .discard (yroom .room_id )
347+ self .log .info (
348+ f"Removed room '{ yroom .room_id } ' from kernel '{ self .kernel_name } '. "
349+ f"Total rooms: { len (self ._yroom_ids )} "
350+ )
351+
352+ @property
353+ def yroom_manager (self ) -> YRoomManager :
354+ return self ._yroom_manager
355+
356+ def bind_yroom_manager (self , yroom_manager : YRoomManager ):
357+ """
358+ Binds a reference to the `YRoomManager` singleton to this instance. This
359+ method must be called before adding a room.
299360 """
300- self ._yrooms . discard ( yroom )
361+ self ._yroom_manager = yroom_manager
301362
302363
303364AbstractDocumentAwareKernelClient .register (DocumentAwareKernelClient )
0 commit comments