50
50
51
51
"""
52
52
53
- import gc
54
-
55
53
__version__ = "0.0.0-auto.0"
56
54
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Requests.git"
57
55
@@ -61,16 +59,23 @@ def __init__(self, response):
61
59
self ._response = response
62
60
63
61
def read (self , size = - 1 ):
62
+ """Read as much as available or up to size and return it in a byte string.
63
+
64
+ Do NOT use this unless you really need to. Reusing memory with `readinto` is much better.
65
+ """
64
66
if size == - 1 :
65
67
return self ._response .content
66
68
return self ._response .socket .recv (size )
67
69
68
70
def readinto (self , buf ):
69
- return self ._response ._readinto (buf )
71
+ """Read as much as available into buf or until it is full. Returns the number of bytes read
72
+ into buf."""
73
+ return self ._response ._readinto (buf ) # pylint: disable=protected-access
70
74
71
75
72
76
class Response :
73
77
"""The response from a request, contains all the headers/content"""
78
+ # pylint: disable=too-many-instance-attributes
74
79
75
80
encoding = None
76
81
@@ -98,7 +103,6 @@ def __init__(self, sock, session=None):
98
103
self .reason = self ._readto (b"\r \n " )
99
104
self ._parse_headers ()
100
105
self ._raw = None
101
- self ._content_read = 0
102
106
self ._session = session
103
107
104
108
def __enter__ (self ):
@@ -114,8 +118,7 @@ def _recv_into(self, buf, size=0):
114
118
read_size = len (b )
115
119
buf [:read_size ] = b
116
120
return read_size
117
- else :
118
- return self .socket .recv_into (buf , size )
121
+ return self .socket .recv_into (buf , size )
119
122
120
123
def _readto (self , first , second = b"" ):
121
124
buf = self ._receive_buffer
@@ -216,7 +219,7 @@ def _throw_away(self, nbytes):
216
219
nbytes -= self ._read_from_buffer (nbytes = nbytes )
217
220
218
221
buf = self ._receive_buffer
219
- for i in range (nbytes // len (buf )):
222
+ for _ in range (nbytes // len (buf )):
220
223
self ._recv_into (buf )
221
224
remaining = nbytes % len (buf )
222
225
if remaining :
@@ -239,7 +242,7 @@ def close(self):
239
242
self ._throw_away (chunk_size + 2 )
240
243
self ._parse_headers ()
241
244
if self ._session :
242
- self ._session .free_socket (self .socket )
245
+ self ._session ._free_socket (self .socket ) # pylint: disable=protected-access
243
246
else :
244
247
self .socket .close ()
245
248
self .socket = None
@@ -340,6 +343,7 @@ def iter_content(self, chunk_size=1, decode_unicode=False):
340
343
341
344
342
345
class Session :
346
+ """HTTP session that shares sockets and ssl context."""
343
347
def __init__ (self , socket_pool , ssl_context = None ):
344
348
self ._socket_pool = socket_pool
345
349
self ._ssl_context = ssl_context
@@ -348,11 +352,28 @@ def __init__(self, socket_pool, ssl_context=None):
348
352
self ._socket_free = {}
349
353
self ._last_response = None
350
354
351
- def free_socket (self , socket ):
355
+ def _free_socket (self , socket ):
356
+
352
357
if socket not in self ._open_sockets .values ():
353
358
raise RuntimeError ("Socket not from session" )
354
359
self ._socket_free [socket ] = True
355
360
361
+ def _free_sockets (self ):
362
+ free_sockets = []
363
+ for sock in self ._socket_free :
364
+ if self ._socket_free [sock ]:
365
+ sock .close ()
366
+ free_sockets .append (sock )
367
+ for sock in free_sockets :
368
+ del self ._socket_free [sock ]
369
+ key = None
370
+ for k in self ._open_sockets :
371
+ if self ._open_sockets [k ] == sock :
372
+ key = k
373
+ break
374
+ if key :
375
+ del self ._open_sockets [key ]
376
+
356
377
def _get_socket (self , host , port , proto , * , timeout = 1 ):
357
378
key = (host , port , proto )
358
379
if key in self ._open_sockets :
@@ -381,20 +402,7 @@ def _get_socket(self, host, port, proto, *, timeout=1):
381
402
382
403
# We couldn't connect due to memory so clean up the open sockets.
383
404
if not ok :
384
- free_sockets = []
385
- for s in self ._socket_free :
386
- if self ._socket_free [s ]:
387
- s .close ()
388
- free_sockets .append (s )
389
- for s in free_sockets :
390
- del self ._socket_free [s ]
391
- key = None
392
- for k in self ._open_sockets :
393
- if self ._open_sockets [k ] == s :
394
- key = k
395
- break
396
- if key :
397
- del self ._open_sockets [key ]
405
+ self ._free_sockets ()
398
406
# Recreate the socket because the ESP-IDF won't retry the connection if it failed once.
399
407
sock = None # Clear first so the first socket can be cleaned up.
400
408
sock = self ._socket_pool .socket (addr_info [0 ], addr_info [1 ], addr_info [2 ])
@@ -466,7 +474,7 @@ def request(
466
474
socket .send (b"Content-Type: application/json\r \n " )
467
475
if data :
468
476
if isinstance (data , dict ):
469
- sock .send (b"Content-Type: application/x-www-form-urlencoded\r \n " )
477
+ socket .send (b"Content-Type: application/x-www-form-urlencoded\r \n " )
470
478
_post_data = ""
471
479
for k in data :
472
480
_post_data = "{}&{}={}" .format (_post_data , k , data [k ])
@@ -513,22 +521,28 @@ def delete(self, url, **kw):
513
521
514
522
# Backwards compatible API:
515
523
516
- _default_session = None
524
+ _default_session = None # pylint: disable=invalid-name
517
525
518
526
519
- class FakeSSLContext :
520
- def wrap_socket (self , socket , server_hostname = None ):
527
+ class _FakeSSLContext :
528
+ @staticmethod
529
+ def wrap_socket (socket , server_hostname = None ):
530
+ """Return the same socket"""
531
+ # pylint: disable=unused-argument
521
532
return socket
522
533
523
534
524
535
def set_socket (sock , iface = None ):
525
- global _default_session
526
- _default_session = Session (sock , FakeSSLContext ())
536
+ """Legacy API for setting the socket and network interface. Use a `Session` instead."""
537
+ global _default_session # pylint: disable=global-statement,invalid-name
538
+ _default_session = Session (sock , _FakeSSLContext ())
527
539
if iface :
528
540
sock .set_interface (iface )
529
541
530
542
531
543
def request (method , url , data = None , json = None , headers = None , stream = False , timeout = 1 ):
544
+ """Send HTTP request"""
545
+ # pylint: disable=too-many-arguments
532
546
_default_session .request (
533
547
method ,
534
548
url ,
0 commit comments