@@ -131,6 +131,7 @@ def __init__(self, reconnection=True, reconnection_attempts=0,
131131 self .namespace_handlers = {}
132132 self .callbacks = {}
133133 self ._binary_packet = None
134+ self ._connect_event = None
134135 self ._reconnect_task = None
135136 self ._reconnect_abort = None
136137
@@ -233,7 +234,8 @@ def register_namespace(self, namespace_handler):
233234 namespace_handler
234235
235236 def connect (self , url , headers = {}, transports = None ,
236- namespaces = None , socketio_path = 'socket.io' ):
237+ namespaces = None , socketio_path = 'socket.io' , wait = True ,
238+ wait_timeout = 1 ):
237239 """Connect to a Socket.IO server.
238240
239241 :param url: The URL of the Socket.IO server. It can include custom
@@ -250,16 +252,24 @@ def connect(self, url, headers={}, transports=None,
250252 :param socketio_path: The endpoint where the Socket.IO server is
251253 installed. The default value is appropriate for
252254 most cases.
253-
254- Note: The connection mechannism occurs in the background and will
255- complete at some point after this function returns. The connection
256- will be established when the ``connect`` event is invoked.
255+ :param wait: if set to ``True`` (the default) the call only returns
256+ when all the namespaces are connected. If set to
257+ ``False``, the call returns as soon as the Engine.IO
258+ transport is connected, and the namespaces will connect
259+ in the background.
260+ :param wait_timeout: How long the client should wait for the
261+ connection. The default is 1 second. This
262+ argument is only considered when ``wait`` is set
263+ to ``True``.
257264
258265 Example usage::
259266
260267 sio = socketio.Client()
261268 sio.connect('http://localhost:5000')
262269 """
270+ if self .connected :
271+ raise exceptions .ConnectionError ('Already connected' )
272+
263273 self .connection_url = url
264274 self .connection_headers = headers
265275 self .connection_transports = transports
@@ -274,6 +284,11 @@ def connect(self, url, headers={}, transports=None,
274284 elif isinstance (namespaces , str ):
275285 namespaces = [namespaces ]
276286 self .connection_namespaces = namespaces
287+ self .namespaces = {}
288+ if self ._connect_event is None :
289+ self ._connect_event = self .eio .create_event ()
290+ else :
291+ self ._connect_event .clear ()
277292 try :
278293 self .eio .connect (url , headers = headers , transports = transports ,
279294 engineio_path = socketio_path )
@@ -282,6 +297,17 @@ def connect(self, url, headers={}, transports=None,
282297 'connect_error' , '/' ,
283298 exc .args [1 ] if len (exc .args ) > 1 else exc .args [0 ])
284299 raise exceptions .ConnectionError (exc .args [0 ]) from None
300+
301+ if wait :
302+ while self ._connect_event .wait (timeout = wait_timeout ):
303+ self ._connect_event .clear ()
304+ if set (self .namespaces ) == set (self .connection_namespaces ):
305+ break
306+ if set (self .namespaces ) != set (self .connection_namespaces ):
307+ self .disconnect ()
308+ raise exceptions .ConnectionError (
309+ 'One or more namespaces failed to connect' )
310+
285311 self .connected = True
286312
287313 def wait (self ):
@@ -483,6 +509,7 @@ def _handle_connect(self, namespace, data):
483509 self .logger .info ('Namespace {} is connected' .format (namespace ))
484510 self .namespaces [namespace ] = (data or {}).get ('sid' , self .sid )
485511 self ._trigger_event ('connect' , namespace = namespace )
512+ self ._connect_event .set ()
486513
487514 def _handle_disconnect (self , namespace ):
488515 if not self .connected :
@@ -534,6 +561,7 @@ def _handle_error(self, namespace, data):
534561 elif not isinstance (data , (tuple , list )):
535562 data = (data ,)
536563 self ._trigger_event ('connect_error' , namespace , * data )
564+ self ._connect_event .set ()
537565 if namespace in self .namespaces :
538566 del self .namespaces [namespace ]
539567 if namespace == '/' :
0 commit comments