@@ -106,6 +106,7 @@ def create_fake_ssl_context(
106
106
107
107
108
108
_global_connection_managers = {}
109
+ _global_key_by_socketpool = {}
109
110
_global_socketpools = {}
110
111
_global_ssl_contexts = {}
111
112
@@ -118,7 +119,7 @@ def _get_radio_hash_key(radio):
118
119
119
120
120
121
def get_radio_socketpool (radio ):
121
- """Helper to get a socket pool for common boards
122
+ """Helper to get a socket pool for common boards.
122
123
123
124
Currently supported:
124
125
@@ -168,14 +169,15 @@ def get_radio_socketpool(radio):
168
169
else :
169
170
raise AttributeError (f"Unsupported radio class: { class_name } " )
170
171
172
+ _global_key_by_socketpool [pool ] = key
171
173
_global_socketpools [key ] = pool
172
174
_global_ssl_contexts [key ] = ssl_context
173
175
174
176
return _global_socketpools [key ]
175
177
176
178
177
179
def get_radio_ssl_context (radio ):
178
- """Helper to get ssl_contexts for common boards
180
+ """Helper to get ssl_contexts for common boards.
179
181
180
182
Currently supported:
181
183
@@ -191,7 +193,7 @@ def get_radio_ssl_context(radio):
191
193
192
194
193
195
class ConnectionManager :
194
- """Connection manager for sharing open sockets (aka connections) ."""
196
+ """A library for managing sockets accross libraries ."""
195
197
196
198
def __init__ (
197
199
self ,
@@ -244,16 +246,20 @@ def _get_connected_socket( # pylint: disable=too-many-arguments
244
246
245
247
@property
246
248
def available_socket_count (self ) -> int :
247
- """Get the count of freeable open sockets"""
249
+ """Get the count of available (freed) managed sockets. """
248
250
return len (self ._available_sockets )
249
251
250
252
@property
251
253
def managed_socket_count (self ) -> int :
252
- """Get the count of open sockets"""
254
+ """Get the count of managed sockets. """
253
255
return len (self ._managed_socket_by_key )
254
256
255
257
def close_socket (self , socket : SocketType ) -> None :
256
- """Close a previously opened socket."""
258
+ """
259
+ Close a previously managed and connected socket.
260
+
261
+ - **socket_pool** *(SocketType)* – The socket you want to close
262
+ """
257
263
if socket not in self ._managed_socket_by_key .values ():
258
264
raise RuntimeError ("Socket not managed" )
259
265
socket .close ()
@@ -263,7 +269,7 @@ def close_socket(self, socket: SocketType) -> None:
263
269
self ._available_sockets .remove (socket )
264
270
265
271
def free_socket (self , socket : SocketType ) -> None :
266
- """Mark a previously opened socket as available so it can be reused if needed ."""
272
+ """Mark a managed socket as available so it can be reused."""
267
273
if socket not in self ._managed_socket_by_key .values ():
268
274
raise RuntimeError ("Socket not managed" )
269
275
self ._available_sockets .add (socket )
@@ -279,7 +285,20 @@ def get_socket(
279
285
is_ssl : bool = False ,
280
286
ssl_context : Optional [SSLContextType ] = None ,
281
287
) -> CircuitPythonSocketType :
282
- """Get a new socket and connect"""
288
+ """
289
+ Get a new socket and connect.
290
+
291
+ - **host** *(str)* – The host you are want to connect to: "www.adaftuit.com"
292
+ - **port** *(int)* – The port you want to connect to: 80
293
+ - **proto** *(str)* – The protocal you want to use: "http:"
294
+ - **session_id** *(Optional[str])* – A unique Session ID, when wanting to have multiple open
295
+ connections to the same host
296
+ - **timeout** *(float)* – Time timeout used for connecting
297
+ - **is_ssl** *(bool)* – If the connection is to be over SSL (auto set when proto is
298
+ "https:")
299
+ - **ssl_context** *(Optional[SSLContextType])* – The SSL context to use when making SSL
300
+ requests
301
+ """
283
302
if session_id :
284
303
session_id = str (session_id )
285
304
key = (host , port , proto , session_id )
@@ -331,7 +350,14 @@ def get_socket(
331
350
def connection_manager_close_all (
332
351
socket_pool : Optional [SocketpoolModuleType ] = None , release_references : bool = False
333
352
) -> None :
334
- """Close all open sockets for pool"""
353
+ """
354
+ Close all open sockets for pool, optionally release references.
355
+
356
+ - **socket_pool** *(Optional[SocketpoolModuleType])* – A specifc SocketPool you want to close
357
+ sockets for, leave blank for all SocketPools
358
+ - **release_references** *(bool)* – Set to True if you want to also clear stored references to
359
+ the SocketPool and SSL contexts
360
+ """
335
361
if socket_pool :
336
362
socket_pools = [socket_pool ]
337
363
else :
@@ -344,26 +370,24 @@ def connection_manager_close_all(
344
370
345
371
connection_manager ._free_sockets (force = True ) # pylint: disable=protected-access
346
372
347
- if release_references :
348
- radio_key = None
349
- for radio_check , pool_check in _global_socketpools .items ():
350
- if pool == pool_check :
351
- radio_key = radio_check
352
- break
373
+ if not release_references :
374
+ continue
353
375
354
- if radio_key :
355
- if radio_key in _global_socketpools :
356
- del _global_socketpools [radio_key ]
376
+ key = _global_key_by_socketpool .pop (pool )
377
+ if key :
378
+ _global_socketpools .pop (key , None )
379
+ _global_ssl_contexts .pop (key , None )
357
380
358
- if radio_key in _global_ssl_contexts :
359
- del _global_ssl_contexts [radio_key ]
360
-
361
- if pool in _global_connection_managers :
362
- del _global_connection_managers [pool ]
381
+ _global_connection_managers .pop (pool , None )
363
382
364
383
365
384
def get_connection_manager (socket_pool : SocketpoolModuleType ) -> ConnectionManager :
366
- """Get the ConnectionManager singleton for the given pool"""
385
+ """
386
+ Get the ConnectionManager singleton for the given pool.
387
+
388
+ - **socket_pool** *(Optional[SocketpoolModuleType])* – The SocketPool you want the
389
+ ConnectionManager for
390
+ """
367
391
if socket_pool not in _global_connection_managers :
368
392
_global_connection_managers [socket_pool ] = ConnectionManager (socket_pool )
369
393
return _global_connection_managers [socket_pool ]
0 commit comments