11from __future__ import annotations
2- import logging
2+
33import asyncio
4+ import logging
5+ from datetime import datetime
6+ from queue import Queue
7+ from typing import TYPE_CHECKING
8+
49import httpx
5- from ably . transport . websockettransport import WebSocketTransport , ProtocolMessageAction
10+
611from ably .transport .defaults import Defaults
12+ from ably .transport .websockettransport import ProtocolMessageAction , WebSocketTransport
13+ from ably .types .connectiondetails import ConnectionDetails
714from ably .types .connectionerrors import ConnectionErrors
815from ably .types .connectionstate import ConnectionEvent , ConnectionState , ConnectionStateChange
916from ably .types .tokendetails import TokenDetails
10- from ably .util .exceptions import AblyException , IncompatibleClientIdException
1117from ably .util .eventemitter import EventEmitter
12- from datetime import datetime
13- from ably .util .helper import get_random_id , Timer , is_token_error
14- from typing import Optional , TYPE_CHECKING
15- from ably .types .connectiondetails import ConnectionDetails
16- from queue import Queue
18+ from ably .util .exceptions import AblyException , IncompatibleClientIdException
19+ from ably .util .helper import Timer , get_random_id , is_token_error
1720
1821if TYPE_CHECKING :
1922 from ably .realtime .realtime import AblyRealtime
@@ -26,23 +29,23 @@ def __init__(self, realtime: AblyRealtime, initial_state):
2629 self .options = realtime .options
2730 self .__ably = realtime
2831 self .__state : ConnectionState = initial_state
29- self .__ping_future : Optional [ asyncio .Future ] = None
32+ self .__ping_future : asyncio .Future | None = None
3033 self .__timeout_in_secs : float = self .options .realtime_request_timeout / 1000
31- self .transport : Optional [ WebSocketTransport ] = None
32- self .__connection_details : Optional [ ConnectionDetails ] = None
33- self .connection_id : Optional [ str ] = None
34+ self .transport : WebSocketTransport | None = None
35+ self .__connection_details : ConnectionDetails | None = None
36+ self .connection_id : str | None = None
3437 self .__fail_state = ConnectionState .DISCONNECTED
35- self .transition_timer : Optional [ Timer ] = None
36- self .suspend_timer : Optional [ Timer ] = None
37- self .retry_timer : Optional [ Timer ] = None
38- self .connect_base_task : Optional [ asyncio .Task ] = None
39- self .disconnect_transport_task : Optional [ asyncio .Task ] = None
38+ self .transition_timer : Timer | None = None
39+ self .suspend_timer : Timer | None = None
40+ self .retry_timer : Timer | None = None
41+ self .connect_base_task : asyncio .Task | None = None
42+ self .disconnect_transport_task : asyncio .Task | None = None
4043 self .__fallback_hosts : list [str ] = self .options .get_fallback_realtime_hosts ()
4144 self .queued_messages : Queue = Queue ()
42- self .__error_reason : Optional [ AblyException ] = None
45+ self .__error_reason : AblyException | None = None
4346 super ().__init__ ()
4447
45- def enact_state_change (self , state : ConnectionState , reason : Optional [ AblyException ] = None ) -> None :
48+ def enact_state_change (self , state : ConnectionState , reason : AblyException | None = None ) -> None :
4649 current_state = self .__state
4750 log .debug (f'ConnectionManager.enact_state_change(): { current_state } -> { state } ; reason = { reason } ' )
4851 self .__state = state
@@ -122,7 +125,7 @@ async def ping(self) -> float:
122125 try :
123126 response = await self .__ping_future
124127 except asyncio .CancelledError :
125- raise AblyException ("Ping request cancelled due to request timeout" , 504 , 50003 )
128+ raise AblyException ("Ping request cancelled due to request timeout" , 504 , 50003 ) from None
126129 return response
127130
128131 self .__ping_future = asyncio .Future ()
@@ -136,14 +139,14 @@ async def ping(self) -> float:
136139 try :
137140 await asyncio .wait_for (self .__ping_future , self .__timeout_in_secs )
138141 except asyncio .TimeoutError :
139- raise AblyException ("Timeout waiting for ping response" , 504 , 50003 )
142+ raise AblyException ("Timeout waiting for ping response" , 504 , 50003 ) from None
140143
141144 ping_end_time = datetime .now ().timestamp ()
142145 response_time_ms = (ping_end_time - ping_start_time ) * 1000
143146 return round (response_time_ms , 2 )
144147
145148 def on_connected (self , connection_details : ConnectionDetails , connection_id : str ,
146- reason : Optional [ AblyException ] = None ) -> None :
149+ reason : AblyException | None = None ) -> None :
147150 self .__fail_state = ConnectionState .DISCONNECTED
148151
149152 self .__connection_details = connection_details
@@ -233,15 +236,15 @@ async def on_closed(self) -> None:
233236 def on_channel_message (self , msg : dict ) -> None :
234237 self .__ably .channels ._on_channel_message (msg )
235238
236- def on_heartbeat (self , id : Optional [ str ] ) -> None :
239+ def on_heartbeat (self , id : str | None ) -> None :
237240 if self .__ping_future :
238241 # Resolve on heartbeat from ping request.
239242 if self .__ping_id == id :
240243 if not self .__ping_future .cancelled ():
241244 self .__ping_future .set_result (None )
242245 self .__ping_future = None
243246
244- def deactivate_transport (self , reason : Optional [ AblyException ] = None ):
247+ def deactivate_transport (self , reason : AblyException | None = None ):
245248 self .transport = None
246249 self .notify_state (ConnectionState .DISCONNECTED , reason )
247250
@@ -275,7 +278,7 @@ def start_connect(self) -> None:
275278 self .start_transition_timer (ConnectionState .CONNECTING )
276279 self .connect_base_task = asyncio .create_task (self .connect_base ())
277280
278- async def connect_with_fallback_hosts (self , fallback_hosts : list ) -> Optional [ Exception ] :
281+ async def connect_with_fallback_hosts (self , fallback_hosts : list ) -> Exception | None :
279282 for host in fallback_hosts :
280283 try :
281284 if self .check_connection ():
@@ -343,8 +346,8 @@ async def on_transport_failed(exception):
343346 except asyncio .CancelledError :
344347 return
345348
346- def notify_state (self , state : ConnectionState , reason : Optional [ AblyException ] = None ,
347- retry_immediately : Optional [ bool ] = None ) -> None :
349+ def notify_state (self , state : ConnectionState , reason : AblyException | None = None ,
350+ retry_immediately : bool | None = None ) -> None :
348351 # RTN15a
349352 retry_immediately = (retry_immediately is not False ) and (
350353 state == ConnectionState .DISCONNECTED and self .__state == ConnectionState .CONNECTED )
@@ -383,7 +386,7 @@ def notify_state(self, state: ConnectionState, reason: Optional[AblyException] =
383386 self .fail_queued_messages (reason )
384387 self .ably .channels ._propagate_connection_interruption (state , reason )
385388
386- def start_transition_timer (self , state : ConnectionState , fail_state : Optional [ ConnectionState ] = None ) -> None :
389+ def start_transition_timer (self , state : ConnectionState , fail_state : ConnectionState | None = None ) -> None :
387390 log .debug (f'ConnectionManager.start_transition_timer(): transition state = { state } ' )
388391
389392 if self .transition_timer :
@@ -520,5 +523,5 @@ def state(self) -> ConnectionState:
520523 return self .__state
521524
522525 @property
523- def connection_details (self ) -> Optional [ ConnectionDetails ] :
526+ def connection_details (self ) -> ConnectionDetails | None :
524527 return self .__connection_details
0 commit comments