3232
3333class WebSocketDisconnect (Exception ):
3434 """Exception raised when a WebSocket connection is disconnected."""
35-
35+
3636 def __init__ (self , code : int = 1000 , reason : str = "" ):
3737 self .code = code
3838 self .reason = reason
@@ -44,28 +44,28 @@ class WebSocketAdapter:
4444 Adapter class that provides a modern WebSocket interface
4545 wrapping Robyn's WebSocketConnector for compatibility.
4646 """
47-
47+
4848 def __init__ (self , websocket_connector : WebSocketConnector , message : str = None ):
4949 self ._connector = websocket_connector
5050 self ._message = message
5151 self ._accepted = False
52-
52+
5353 async def accept (self ):
5454 """Accept the WebSocket connection (no-op in Robyn as it's auto-accepted)"""
5555 self ._accepted = True
56-
56+
5757 async def close (self , code : int = 1000 ):
5858 """Close the WebSocket connection"""
5959 self ._connector .close ()
60-
60+
6161 async def send_text (self , data : str ):
6262 """Send text data to the WebSocket"""
6363 await self ._connector .async_send_to (self ._connector .id , data )
64-
64+
6565 async def send_bytes (self , data : bytes ):
6666 """Send binary data to the WebSocket"""
67- await self ._connector .async_send_to (self ._connector .id , data .decode (' utf-8' ))
68-
67+ await self ._connector .async_send_to (self ._connector .id , data .decode (" utf-8" ))
68+
6969 async def receive_text (self ) -> str :
7070 """Receive text data from the WebSocket"""
7171 if self ._message is not None :
@@ -75,42 +75,44 @@ async def receive_text(self) -> str:
7575 # Note: In a real implementation, this would need to handle the message queue
7676 # For now, we return the current message if available
7777 return ""
78-
78+
7979 async def receive_bytes (self ) -> bytes :
8080 """Receive binary data from the WebSocket"""
8181 text = await self .receive_text ()
82- return text .encode (' utf-8' )
83-
82+ return text .encode (" utf-8" )
83+
8484 async def send_json (self , data ):
8585 """Send JSON data to the WebSocket"""
8686 import json
87+
8788 await self .send_text (json .dumps (data ))
88-
89+
8990 async def receive_json (self ):
9091 """Receive JSON data from the WebSocket"""
9192 import json
93+
9294 text = await self .receive_text ()
9395 return json .loads (text ) if text else None
94-
96+
9597 @property
9698 def query_params (self ):
9799 """Access query parameters"""
98100 return self ._connector .query_params
99-
101+
100102 @property
101103 def path_params (self ):
102104 """Access path parameters"""
103- return getattr (self ._connector , ' path_params' , {})
104-
105+ return getattr (self ._connector , " path_params" , {})
106+
105107 @property
106108 def headers (self ):
107109 """Access request headers"""
108- return getattr (self ._connector , ' headers' , {})
109-
110+ return getattr (self ._connector , " headers" , {})
111+
110112 @property
111113 def client (self ):
112114 """Client information"""
113- return getattr (self ._connector , ' client' , None )
115+ return getattr (self ._connector , " client" , None )
114116
115117
116118def _normalize_endpoint (endpoint : str ) -> str :
@@ -367,28 +369,29 @@ def websocket(self, endpoint: str):
367369 """
368370 Modern WebSocket decorator that accepts a single handler function.
369371 The handler function receives a WebSocket object and can optionally have on_connect and on_close callbacks.
370-
372+
371373 Usage:
372374 @app.websocket("/ws")
373375 async def websocket_endpoint(websocket):
374376 await websocket.accept()
375377 while True:
376378 data = await websocket.receive_text()
377379 await websocket.send_text(f"Echo: {data}")
378-
380+
379381 # With optional callbacks:
380382 @websocket_endpoint.on_connect
381383 async def on_connect(websocket):
382384 await websocket.send_text("Connected!")
383-
384- @websocket_endpoint.on_close
385+
386+ @websocket_endpoint.on_close
385387 async def on_close(websocket):
386388 print("Disconnected")
387389 """
390+
388391 def decorator (handler ):
389392 # Dictionary to store handlers for this WebSocket endpoint
390393 handlers = {}
391-
394+
392395 # Create the main message handler
393396 async def message_handler (websocket_connector , msg , * args , ** kwargs ):
394397 # Convert WebSocketConnector to modern WebSocket interface
@@ -405,53 +408,53 @@ async def message_handler(websocket_connector, msg, *args, **kwargs):
405408 if "connection closed" in str (e ).lower () or "websocket" in str (e ).lower ():
406409 return ""
407410 raise e
408-
411+
409412 # Create FunctionInfo for the message handler
410413 params = dict (inspect .signature (message_handler ).parameters )
411414 num_params = len (params )
412415 is_async = asyncio .iscoroutinefunction (message_handler )
413416 injected_dependencies = self .dependencies .get_dependency_map (self )
414-
417+
415418 handlers ["message" ] = FunctionInfo (message_handler , is_async , num_params , params , kwargs = injected_dependencies )
416-
419+
417420 # Add methods to the handler to allow attaching on_connect and on_close
418421 def add_on_connect (connect_handler ):
419422 def connect_wrapper (websocket_connector , * args , ** kwargs ):
420423 websocket_adapter = WebSocketAdapter (websocket_connector )
421424 if asyncio .iscoroutinefunction (connect_handler ):
422425 return asyncio .create_task (connect_handler (websocket_adapter ))
423426 return connect_handler (websocket_adapter )
424-
427+
425428 # Create FunctionInfo for connect handler
426429 connect_params = dict (inspect .signature (connect_wrapper ).parameters )
427430 connect_num_params = len (connect_params )
428431 connect_is_async = asyncio .iscoroutinefunction (connect_wrapper )
429432 handlers ["connect" ] = FunctionInfo (connect_wrapper , connect_is_async , connect_num_params , connect_params , kwargs = injected_dependencies )
430433 return connect_handler
431-
434+
432435 def add_on_close (close_handler ):
433436 def close_wrapper (websocket_connector , * args , ** kwargs ):
434437 websocket_adapter = WebSocketAdapter (websocket_connector )
435438 if asyncio .iscoroutinefunction (close_handler ):
436439 return asyncio .create_task (close_handler (websocket_adapter ))
437440 return close_handler (websocket_adapter )
438-
441+
439442 # Create FunctionInfo for close handler
440443 close_params = dict (inspect .signature (close_wrapper ).parameters )
441444 close_num_params = len (close_params )
442445 close_is_async = asyncio .iscoroutinefunction (close_wrapper )
443446 handlers ["close" ] = FunctionInfo (close_wrapper , close_is_async , close_num_params , close_params , kwargs = injected_dependencies )
444447 return close_handler
445-
448+
446449 # Attach methods to the handler function
447450 handler .on_connect = add_on_connect
448451 handler .on_close = add_on_close
449452 handler ._ws_handlers = handlers # Store reference to handlers dict
450-
453+
451454 # Add the WebSocket to the router
452455 self .add_web_socket (endpoint , handlers )
453456 return handler
454-
457+
455458 return decorator
456459
457460 def _add_event_handler (self , event_type : Events , handler : Callable ) -> None :
@@ -859,15 +862,15 @@ def websocket(self, endpoint: str):
859862 """
860863 Modern WebSocket decorator for SubRouter that accepts a single handler function.
861864 Works the same as the main Robyn websocket decorator but with prefix support.
862-
865+
863866 Usage:
864867 @subrouter.websocket("/ws")
865868 async def websocket_endpoint(websocket):
866869 await websocket.accept()
867870 while True:
868871 data = await websocket.receive_text()
869872 await websocket.send_text(f"Echo: {data}")
870-
873+
871874 # With optional callbacks:
872875 @websocket_endpoint.on_connect
873876 async def on_connect(websocket):
0 commit comments