@@ -206,13 +206,13 @@ def run_javascript(self, code: str, *, timeout: float = 1.0) -> AwaitableRespons
206
206
:return: AwaitableResponse that can be awaited to get the result of the JavaScript code
207
207
"""
208
208
request_id = str (uuid .uuid4 ())
209
- target_id = self ._temporary_socket_id or self . id
209
+ target_id = self .target
210
210
211
211
def send_and_forget ():
212
212
self .outbox .enqueue_message ('run_javascript' , {'code' : code }, target_id )
213
213
214
214
async def send_and_wait ():
215
- if self is self .auto_index_client :
215
+ if self is self .auto_index_client and not self . _temporary_socket_id :
216
216
raise RuntimeError ('Cannot await JavaScript responses on the auto-index page. '
217
217
'There could be multiple clients connected and it is not clear which one to wait for.' )
218
218
self .outbox .enqueue_message ('run_javascript' , {'code' : code , 'request_id' : request_id }, target_id )
@@ -223,11 +223,12 @@ async def send_and_wait():
223
223
def open (self , target : Union [Callable [..., Any ], str ], new_tab : bool = False ) -> None :
224
224
"""Open a new page in the client."""
225
225
path = target if isinstance (target , str ) else self .page_routes [target ]
226
- self .outbox .enqueue_message ('open' , {'path' : path , 'new_tab' : new_tab }, self .id )
226
+ self .outbox .enqueue_message ('open' , {'path' : path , 'new_tab' : new_tab }, self .target )
227
227
228
228
def download (self , src : Union [str , bytes ], filename : Optional [str ] = None , media_type : str = '' ) -> None :
229
229
"""Download a file from a given URL or raw bytes."""
230
- self .outbox .enqueue_message ('download' , {'src' : src , 'filename' : filename , 'media_type' : media_type }, self .id )
230
+ self .outbox .enqueue_message ('download' , {'src' : src , 'filename' : filename , 'media_type' : media_type },
231
+ self .target )
231
232
232
233
def on_connect (self , handler : Union [Callable [..., Any ], Awaitable ]) -> None :
233
234
"""Add a callback to be invoked when the client connects."""
@@ -278,15 +279,15 @@ def _cancel_delete_task(self, document_id: str) -> None:
278
279
if document_id in self ._delete_tasks :
279
280
self ._delete_tasks .pop (document_id ).cancel ()
280
281
281
- def handle_event (self , msg : Dict ) -> None :
282
+ def handle_event (self , sid : str , msg : Dict ) -> None :
282
283
"""Forward an event to the corresponding element."""
283
284
with self :
284
285
sender = self .elements .get (msg ['id' ])
285
286
if sender is not None and not sender .is_ignoring_events :
286
287
msg ['args' ] = [None if arg is None else json .loads (arg ) for arg in msg .get ('args' , [])]
287
288
if len (msg ['args' ]) == 1 :
288
289
msg ['args' ] = msg ['args' ][0 ]
289
- sender ._handle_event (msg ) # pylint: disable=protected-access
290
+ sender ._handle_event (sid , msg ) # pylint: disable=protected-access
290
291
291
292
def handle_javascript_response (self , msg : Dict ) -> None :
292
293
"""Store the result of a JavaScript command."""
@@ -354,6 +355,14 @@ def individual_target(self, socket_id: str) -> Iterator[None]:
354
355
yield
355
356
self ._temporary_socket_id = None
356
357
358
+ @property
359
+ def target (self ) -> str :
360
+ """Return the target of the client.
361
+
362
+ This is usually the client ID, but can be overridden by the ``individual_target`` context manager.
363
+ """
364
+ return self ._temporary_socket_id or self .id
365
+
357
366
@classmethod
358
367
async def prune_instances (cls ) -> None :
359
368
"""Prune stale clients in an endless loop."""
0 commit comments