From 4753a9dce7d19c3c3b2dd776ba7a34a948e4bad5 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 23 Sep 2020 15:53:34 -0700 Subject: [PATCH 1/5] Check for send to return 0 When it does, close the socket and raise an Exception. This prevents leaking sockets when send fails. --- adafruit_requests.py | 114 +++++++++++++++++------------ tests/chunk_test.py | 13 +++- tests/header_test.py | 5 +- tests/legacy_mocket.py | 5 +- tests/mocket.py | 5 +- tests/post_test.py | 14 +++- tests/protocol_test.py | 26 ++++++- tests/reuse_test.py | 162 +++++++++++++++++++++++++++++++---------- 8 files changed, 251 insertions(+), 93 deletions(-) diff --git a/adafruit_requests.py b/adafruit_requests.py index 8d157f1..d6d1417 100755 --- a/adafruit_requests.py +++ b/adafruit_requests.py @@ -377,26 +377,28 @@ def __init__(self, socket_pool, ssl_context=None): self._last_response = None def _free_socket(self, socket): - if socket not in self._open_sockets.values(): raise RuntimeError("Socket not from session") self._socket_free[socket] = True + def _close_socket(self, sock): + sock.close() + del self._socket_free[sock] + key = None + for k in self._open_sockets: + if self._open_sockets[k] == sock: + key = k + break + if key: + del self._open_sockets[key] + def _free_sockets(self): free_sockets = [] for sock in self._socket_free: if self._socket_free[sock]: - sock.close() free_sockets.append(sock) for sock in free_sockets: - del self._socket_free[sock] - key = None - for k in self._open_sockets: - if self._open_sockets[k] == sock: - key = k - break - if key: - del self._open_sockets[key] + self._close_socket(sock) def _get_socket(self, host, port, proto, *, timeout=1): key = (host, port, proto) @@ -440,6 +442,56 @@ def _get_socket(self, host, port, proto, *, timeout=1): self._socket_free[sock] = False return sock + def _send(self, socket, data): + total_sent = 0 + while total_sent < len(data): + sent = socket.send(data[total_sent:]) + if sent == 0: + raise RuntimeError("Connection closed") + total_sent += sent + + def _send_request(self, socket, host, method, path, headers, data, json): + self._send(socket, bytes(method, "utf-8")) + self._send(socket, b" /") + self._send(socket, bytes(path, "utf-8")) + self._send(socket, b" HTTP/1.1\r\n") + if "Host" not in headers: + self._send(socket, b"Host: ") + self._send(socket, bytes(host, "utf-8")) + self._send(socket, b"\r\n") + if "User-Agent" not in headers: + self._send(socket, b"User-Agent: Adafruit CircuitPython\r\n") + # Iterate over keys to avoid tuple alloc + for k in headers: + self._send(socket, k.encode()) + self._send(socket, b": ") + self._send(socket, headers[k].encode()) + self._send(socket, b"\r\n") + if json is not None: + assert data is None + # pylint: disable=import-outside-toplevel + try: + import json as json_module + except ImportError: + import ujson as json_module + data = json_module.dumps(json) + self._send(socket, b"Content-Type: application/json\r\n") + if data: + if isinstance(data, dict): + self._send(socket, b"Content-Type: application/x-www-form-urlencoded\r\n") + _post_data = "" + for k in data: + _post_data = "{}&{}={}".format(_post_data, k, data[k]) + data = _post_data[1:] + self._send(socket, b"Content-Length: %d\r\n" % len(data)) + self._send(socket, b"\r\n") + if data: + if isinstance(data, bytearray): + self._send(socket, bytes(data)) + else: + self._send(socket, bytes(data, "utf-8")) + + # pylint: disable=too-many-branches, too-many-statements, unused-argument, too-many-arguments, too-many-locals def request( self, method, url, data=None, json=None, headers=None, stream=False, timeout=60 @@ -476,42 +528,11 @@ def request( self._last_response = None socket = self._get_socket(host, port, proto, timeout=timeout) - socket.send( - b"%s /%s HTTP/1.1\r\n" % (bytes(method, "utf-8"), bytes(path, "utf-8")) - ) - if "Host" not in headers: - socket.send(b"Host: %s\r\n" % bytes(host, "utf-8")) - if "User-Agent" not in headers: - socket.send(b"User-Agent: Adafruit CircuitPython\r\n") - # Iterate over keys to avoid tuple alloc - for k in headers: - socket.send(k.encode()) - socket.send(b": ") - socket.send(headers[k].encode()) - socket.send(b"\r\n") - if json is not None: - assert data is None - # pylint: disable=import-outside-toplevel - try: - import json as json_module - except ImportError: - import ujson as json_module - data = json_module.dumps(json) - socket.send(b"Content-Type: application/json\r\n") - if data: - if isinstance(data, dict): - socket.send(b"Content-Type: application/x-www-form-urlencoded\r\n") - _post_data = "" - for k in data: - _post_data = "{}&{}={}".format(_post_data, k, data[k]) - data = _post_data[1:] - socket.send(b"Content-Length: %d\r\n" % len(data)) - socket.send(b"\r\n") - if data: - if isinstance(data, bytearray): - socket.send(bytes(data)) - else: - socket.send(bytes(data, "utf-8")) + try: + self._send_request(socket, host, method, path, headers, data, json) + except: + self._close_socket(socket) + raise resp = Response(socket, self) # our response if "location" in resp.headers and 300 <= resp.status_code <= 399: @@ -557,6 +578,7 @@ def __init__(self, socket, tls_mode): self.settimeout = socket.settimeout self.send = socket.send self.recv = socket.recv + self.close = socket.close def connect(self, address): """connect wrapper to add non-standard mode parameter""" diff --git a/tests/chunk_test.py b/tests/chunk_test.py index 67f09ec..d98c117 100644 --- a/tests/chunk_test.py +++ b/tests/chunk_test.py @@ -39,10 +39,19 @@ def test_get_text(): r = s.get("http://" + host + path) sock.connect.assert_called_once_with((ip, 80)) + + sock.send.assert_has_calls( + [ + mock.call(b"GET"), + mock.call(b" /"), + mock.call(b"testwifi/index.html"), + mock.call(b" HTTP/1.1\r\n"), + ] + ) sock.send.assert_has_calls( [ - mock.call(b"GET /testwifi/index.html HTTP/1.1\r\n"), - mock.call(b"Host: wifitest.adafruit.com\r\n"), + mock.call(b"Host: "), + mock.call(b"wifitest.adafruit.com"), ] ) assert r.text == str(text, "utf-8") diff --git a/tests/header_test.py b/tests/header_test.py index 2c9db60..1d14536 100644 --- a/tests/header_test.py +++ b/tests/header_test.py @@ -14,7 +14,10 @@ def test_json(): sock = mocket.Mocket(response_headers) pool.socket.return_value = sock sent = [] - sock.send.side_effect = sent.append + def _send(data): + sent.append(data) + return len(data) + sock.send.side_effect = _send s = adafruit_requests.Session(pool) headers = {"user-agent": "blinka/1.0.0"} diff --git a/tests/legacy_mocket.py b/tests/legacy_mocket.py index 4a37bd2..d256efc 100644 --- a/tests/legacy_mocket.py +++ b/tests/legacy_mocket.py @@ -13,12 +13,15 @@ def __init__(self, response): self.settimeout = mock.Mock() self.close = mock.Mock() self.connect = mock.Mock() - self.send = mock.Mock() + self.send = mock.Mock(side_effect=self._send) self.readline = mock.Mock(side_effect=self._readline) self.recv = mock.Mock(side_effect=self._recv) self._response = response self._position = 0 + def _send(self, data): + return len(data) + def _readline(self): i = self._response.find(b"\r\n", self._position) r = self._response[self._position : i + 2] diff --git a/tests/mocket.py b/tests/mocket.py index ec9a557..916bbef 100644 --- a/tests/mocket.py +++ b/tests/mocket.py @@ -14,13 +14,16 @@ def __init__(self, response): self.settimeout = mock.Mock() self.close = mock.Mock() self.connect = mock.Mock() - self.send = mock.Mock() + self.send = mock.Mock(side_effect=self._send) self.readline = mock.Mock(side_effect=self._readline) self.recv = mock.Mock(side_effect=self._recv) self.recv_into = mock.Mock(side_effect=self._recv_into) self._response = response self._position = 0 + def _send(self, data): + return len(data) + def _readline(self): i = self._response.find(b"\r\n", self._position) r = self._response[self._position : i + 2] diff --git a/tests/post_test.py b/tests/post_test.py index c8660a2..aab887c 100644 --- a/tests/post_test.py +++ b/tests/post_test.py @@ -21,8 +21,20 @@ def test_method(): s = adafruit_requests.Session(pool) r = s.post("http://" + host + "/post") sock.connect.assert_called_once_with((ip, 80)) + + sock.send.assert_has_calls( + [ + mock.call(b"POST"), + mock.call(b" /"), + mock.call(b"post"), + mock.call(b" HTTP/1.1\r\n"), + ] + ) sock.send.assert_has_calls( - [mock.call(b"POST /post HTTP/1.1\r\n"), mock.call(b"Host: httpbin.org\r\n")] + [ + mock.call(b"Host: "), + mock.call(b"httpbin.org"), + ] ) diff --git a/tests/protocol_test.py b/tests/protocol_test.py index c7ad9da..34551da 100644 --- a/tests/protocol_test.py +++ b/tests/protocol_test.py @@ -32,10 +32,19 @@ def test_get_https_text(): r = s.get("https://" + host + path) sock.connect.assert_called_once_with((host, 443)) + sock.send.assert_has_calls( [ - mock.call(b"GET /testwifi/index.html HTTP/1.1\r\n"), - mock.call(b"Host: wifitest.adafruit.com\r\n"), + mock.call(b"GET"), + mock.call(b" /"), + mock.call(b"testwifi/index.html"), + mock.call(b" HTTP/1.1\r\n"), + ] + ) + sock.send.assert_has_calls( + [ + mock.call(b"Host: "), + mock.call(b"wifitest.adafruit.com"), ] ) assert r.text == str(text, "utf-8") @@ -54,10 +63,19 @@ def test_get_http_text(): r = s.get("http://" + host + path) sock.connect.assert_called_once_with((ip, 80)) + + sock.send.assert_has_calls( + [ + mock.call(b"GET"), + mock.call(b" /"), + mock.call(b"testwifi/index.html"), + mock.call(b" HTTP/1.1\r\n"), + ] + ) sock.send.assert_has_calls( [ - mock.call(b"GET /testwifi/index.html HTTP/1.1\r\n"), - mock.call(b"Host: wifitest.adafruit.com\r\n"), + mock.call(b"Host: "), + mock.call(b"wifitest.adafruit.com"), ] ) assert r.text == str(text, "utf-8") diff --git a/tests/reuse_test.py b/tests/reuse_test.py index 2e06931..5d49d15 100644 --- a/tests/reuse_test.py +++ b/tests/reuse_test.py @@ -10,35 +10,53 @@ text = b"This is a test of Adafruit WiFi!\r\nIf you can read this, its working :)" response = b"HTTP/1.0 200 OK\r\nContent-Length: 70\r\n\r\n" + text -# def test_get_twice(): -# pool = mocket.MocketPool() -# pool.getaddrinfo.return_value = ((None, None, None, None, (ip, 80)),) -# sock = mocket.Mocket(response + response) -# pool.socket.return_value = sock -# ssl = mocket.SSLContext() - -# s = adafruit_requests.Session(pool, ssl) -# r = s.get("https://" + host + path) - -# sock.send.assert_has_calls( -# [ -# mock.call(b"GET /testwifi/index.html HTTP/1.1\r\n"), -# mock.call(b"Host: wifitest.adafruit.com\r\n"), -# ] -# ) -# assert r.text == str(text, "utf-8") - -# r = s.get("https://" + host + path + "2") -# sock.send.assert_has_calls( -# [ -# mock.call(b"GET /testwifi/index.html2 HTTP/1.1\r\n"), -# mock.call(b"Host: wifitest.adafruit.com\r\n"), -# ] -# ) - -# assert r.text == str(text, "utf-8") -# sock.connect.assert_called_once_with((host, 443)) -# pool.socket.assert_called_once() +def test_get_twice(): + pool = mocket.MocketPool() + pool.getaddrinfo.return_value = ((None, None, None, None, (ip, 80)),) + sock = mocket.Mocket(response + response) + pool.socket.return_value = sock + ssl = mocket.SSLContext() + + s = adafruit_requests.Session(pool, ssl) + r = s.get("https://" + host + path) + + + sock.send.assert_has_calls( + [ + mock.call(b"GET"), + mock.call(b" /"), + mock.call(b"testwifi/index.html"), + mock.call(b" HTTP/1.1\r\n"), + ] + ) + sock.send.assert_has_calls( + [ + mock.call(b"Host: "), + mock.call(b"wifitest.adafruit.com"), + ] + ) + assert r.text == str(text, "utf-8") + + r = s.get("https://" + host + path + "2") + + sock.send.assert_has_calls( + [ + mock.call(b"GET"), + mock.call(b" /"), + mock.call(b"testwifi/index.html2"), + mock.call(b" HTTP/1.1\r\n"), + ] + ) + sock.send.assert_has_calls( + [ + mock.call(b"Host: "), + mock.call(b"wifitest.adafruit.com"), + ] + ) + + assert r.text == str(text, "utf-8") + sock.connect.assert_called_once_with((host, 443)) + pool.socket.assert_called_once() def test_get_twice_after_second(): @@ -51,18 +69,36 @@ def test_get_twice_after_second(): s = adafruit_requests.Session(pool, ssl) r = s.get("https://" + host + path) + sock.send.assert_has_calls( [ - mock.call(b"GET /testwifi/index.html HTTP/1.1\r\n"), - mock.call(b"Host: wifitest.adafruit.com\r\n"), + mock.call(b"GET"), + mock.call(b" /"), + mock.call(b"testwifi/index.html"), + mock.call(b" HTTP/1.1\r\n"), + ] + ) + sock.send.assert_has_calls( + [ + mock.call(b"Host: "), + mock.call(b"wifitest.adafruit.com"), ] ) r2 = s.get("https://" + host + path + "2") + sock.send.assert_has_calls( [ - mock.call(b"GET /testwifi/index.html2 HTTP/1.1\r\n"), - mock.call(b"Host: wifitest.adafruit.com\r\n"), + mock.call(b"GET"), + mock.call(b" /"), + mock.call(b"testwifi/index.html2"), + mock.call(b" HTTP/1.1\r\n"), + ] + ) + sock.send.assert_has_calls( + [ + mock.call(b"Host: "), + mock.call(b"wifitest.adafruit.com"), ] ) sock.connect.assert_called_once_with((host, 443)) @@ -87,8 +123,16 @@ def test_connect_out_of_memory(): sock.send.assert_has_calls( [ - mock.call(b"GET /testwifi/index.html HTTP/1.1\r\n"), - mock.call(b"Host: wifitest.adafruit.com\r\n"), + mock.call(b"GET"), + mock.call(b" /"), + mock.call(b"testwifi/index.html"), + mock.call(b" HTTP/1.1\r\n"), + ] + ) + sock.send.assert_has_calls( + [ + mock.call(b"Host: "), + mock.call(b"wifitest.adafruit.com"), ] ) assert r.text == str(text, "utf-8") @@ -96,8 +140,16 @@ def test_connect_out_of_memory(): r = s.get("https://" + host2 + path) sock3.send.assert_has_calls( [ - mock.call(b"GET /testwifi/index.html HTTP/1.1\r\n"), - mock.call(b"Host: wifitest2.adafruit.com\r\n"), + mock.call(b"GET"), + mock.call(b" /"), + mock.call(b"testwifi/index.html"), + mock.call(b" HTTP/1.1\r\n"), + ] + ) + sock3.send.assert_has_calls( + [ + mock.call(b"Host: "), + mock.call(b"wifitest2.adafruit.com"), ] ) @@ -105,3 +157,39 @@ def test_connect_out_of_memory(): sock.close.assert_called_once() sock.connect.assert_called_once_with((host, 443)) sock3.connect.assert_called_once_with((host2, 443)) + +def test_second_send_fails(): + pool = mocket.MocketPool() + pool.getaddrinfo.return_value = ((None, None, None, None, (ip, 80)),) + sock = mocket.Mocket(response + response) + pool.socket.return_value = sock + ssl = mocket.SSLContext() + + s = adafruit_requests.Session(pool, ssl) + r = s.get("https://" + host + path) + + sock.send.assert_has_calls( + [ + mock.call(b"testwifi/index.html"), + ] + ) + + sock.send.assert_has_calls( + [ + mock.call(b"Host: "), + mock.call(b"wifitest.adafruit.com"), + mock.call(b"\r\n"), + ] + ) + assert r.text == str(text, "utf-8") + + sock.send.side_effect = None + sock.send.return_value = 0 + + with pytest.raises(RuntimeError): + s.get("https://" + host + path + "2") + + sock.connect.assert_called_once_with((host, 443)) + # Make sure that the socket is closed after send fails. + sock.close.assert_called_once() + pool.socket.assert_called_once() From 9607753221c2736a073c13b28621f2c6089330cb Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 23 Sep 2020 16:01:44 -0700 Subject: [PATCH 2/5] Black --- adafruit_requests.py | 5 +++-- tests/header_test.py | 2 ++ tests/protocol_test.py | 4 ++-- tests/reuse_test.py | 8 ++++---- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/adafruit_requests.py b/adafruit_requests.py index d6d1417..b1f8b29 100755 --- a/adafruit_requests.py +++ b/adafruit_requests.py @@ -478,7 +478,9 @@ def _send_request(self, socket, host, method, path, headers, data, json): self._send(socket, b"Content-Type: application/json\r\n") if data: if isinstance(data, dict): - self._send(socket, b"Content-Type: application/x-www-form-urlencoded\r\n") + self._send( + socket, b"Content-Type: application/x-www-form-urlencoded\r\n" + ) _post_data = "" for k in data: _post_data = "{}&{}={}".format(_post_data, k, data[k]) @@ -491,7 +493,6 @@ def _send_request(self, socket, host, method, path, headers, data, json): else: self._send(socket, bytes(data, "utf-8")) - # pylint: disable=too-many-branches, too-many-statements, unused-argument, too-many-arguments, too-many-locals def request( self, method, url, data=None, json=None, headers=None, stream=False, timeout=60 diff --git a/tests/header_test.py b/tests/header_test.py index 1d14536..46dcc76 100644 --- a/tests/header_test.py +++ b/tests/header_test.py @@ -14,9 +14,11 @@ def test_json(): sock = mocket.Mocket(response_headers) pool.socket.return_value = sock sent = [] + def _send(data): sent.append(data) return len(data) + sock.send.side_effect = _send s = adafruit_requests.Session(pool) diff --git a/tests/protocol_test.py b/tests/protocol_test.py index 34551da..b604c81 100644 --- a/tests/protocol_test.py +++ b/tests/protocol_test.py @@ -32,7 +32,7 @@ def test_get_https_text(): r = s.get("https://" + host + path) sock.connect.assert_called_once_with((host, 443)) - + sock.send.assert_has_calls( [ mock.call(b"GET"), @@ -63,7 +63,7 @@ def test_get_http_text(): r = s.get("http://" + host + path) sock.connect.assert_called_once_with((ip, 80)) - + sock.send.assert_has_calls( [ mock.call(b"GET"), diff --git a/tests/reuse_test.py b/tests/reuse_test.py index 5d49d15..5d57308 100644 --- a/tests/reuse_test.py +++ b/tests/reuse_test.py @@ -10,6 +10,7 @@ text = b"This is a test of Adafruit WiFi!\r\nIf you can read this, its working :)" response = b"HTTP/1.0 200 OK\r\nContent-Length: 70\r\n\r\n" + text + def test_get_twice(): pool = mocket.MocketPool() pool.getaddrinfo.return_value = ((None, None, None, None, (ip, 80)),) @@ -20,7 +21,6 @@ def test_get_twice(): s = adafruit_requests.Session(pool, ssl) r = s.get("https://" + host + path) - sock.send.assert_has_calls( [ mock.call(b"GET"), @@ -38,7 +38,7 @@ def test_get_twice(): assert r.text == str(text, "utf-8") r = s.get("https://" + host + path + "2") - + sock.send.assert_has_calls( [ mock.call(b"GET"), @@ -69,7 +69,6 @@ def test_get_twice_after_second(): s = adafruit_requests.Session(pool, ssl) r = s.get("https://" + host + path) - sock.send.assert_has_calls( [ mock.call(b"GET"), @@ -86,7 +85,7 @@ def test_get_twice_after_second(): ) r2 = s.get("https://" + host + path + "2") - + sock.send.assert_has_calls( [ mock.call(b"GET"), @@ -158,6 +157,7 @@ def test_connect_out_of_memory(): sock.connect.assert_called_once_with((host, 443)) sock3.connect.assert_called_once_with((host2, 443)) + def test_second_send_fails(): pool = mocket.MocketPool() pool.getaddrinfo.return_value = ((None, None, None, None, (ip, 80)),) From 739aac58d467e214f0eac6b9fdf4ed7f95ad6579 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 23 Sep 2020 16:51:39 -0700 Subject: [PATCH 3/5] Handle send returning None like ESP32SPI does --- adafruit_requests.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/adafruit_requests.py b/adafruit_requests.py index b1f8b29..dcb9046 100755 --- a/adafruit_requests.py +++ b/adafruit_requests.py @@ -446,6 +446,8 @@ def _send(self, socket, data): total_sent = 0 while total_sent < len(data): sent = socket.send(data[total_sent:]) + if sent is None: + sent = len(data) if sent == 0: raise RuntimeError("Connection closed") total_sent += sent From 2e45952b1d9a74aa7a9420f1298b2ee769785732 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 23 Sep 2020 16:55:06 -0700 Subject: [PATCH 4/5] Black 19.10 --- tests/chunk_test.py | 5 +---- tests/post_test.py | 5 +---- tests/protocol_test.py | 10 ++-------- tests/reuse_test.py | 40 ++++++++-------------------------------- 4 files changed, 12 insertions(+), 48 deletions(-) diff --git a/tests/chunk_test.py b/tests/chunk_test.py index d98c117..585cebd 100644 --- a/tests/chunk_test.py +++ b/tests/chunk_test.py @@ -49,9 +49,6 @@ def test_get_text(): ] ) sock.send.assert_has_calls( - [ - mock.call(b"Host: "), - mock.call(b"wifitest.adafruit.com"), - ] + [mock.call(b"Host: "), mock.call(b"wifitest.adafruit.com"),] ) assert r.text == str(text, "utf-8") diff --git a/tests/post_test.py b/tests/post_test.py index aab887c..c2a9b7e 100644 --- a/tests/post_test.py +++ b/tests/post_test.py @@ -31,10 +31,7 @@ def test_method(): ] ) sock.send.assert_has_calls( - [ - mock.call(b"Host: "), - mock.call(b"httpbin.org"), - ] + [mock.call(b"Host: "), mock.call(b"httpbin.org"),] ) diff --git a/tests/protocol_test.py b/tests/protocol_test.py index b604c81..c00c485 100644 --- a/tests/protocol_test.py +++ b/tests/protocol_test.py @@ -42,10 +42,7 @@ def test_get_https_text(): ] ) sock.send.assert_has_calls( - [ - mock.call(b"Host: "), - mock.call(b"wifitest.adafruit.com"), - ] + [mock.call(b"Host: "), mock.call(b"wifitest.adafruit.com"),] ) assert r.text == str(text, "utf-8") @@ -73,9 +70,6 @@ def test_get_http_text(): ] ) sock.send.assert_has_calls( - [ - mock.call(b"Host: "), - mock.call(b"wifitest.adafruit.com"), - ] + [mock.call(b"Host: "), mock.call(b"wifitest.adafruit.com"),] ) assert r.text == str(text, "utf-8") diff --git a/tests/reuse_test.py b/tests/reuse_test.py index 5d57308..6e33e7e 100644 --- a/tests/reuse_test.py +++ b/tests/reuse_test.py @@ -30,10 +30,7 @@ def test_get_twice(): ] ) sock.send.assert_has_calls( - [ - mock.call(b"Host: "), - mock.call(b"wifitest.adafruit.com"), - ] + [mock.call(b"Host: "), mock.call(b"wifitest.adafruit.com"),] ) assert r.text == str(text, "utf-8") @@ -48,10 +45,7 @@ def test_get_twice(): ] ) sock.send.assert_has_calls( - [ - mock.call(b"Host: "), - mock.call(b"wifitest.adafruit.com"), - ] + [mock.call(b"Host: "), mock.call(b"wifitest.adafruit.com"),] ) assert r.text == str(text, "utf-8") @@ -78,10 +72,7 @@ def test_get_twice_after_second(): ] ) sock.send.assert_has_calls( - [ - mock.call(b"Host: "), - mock.call(b"wifitest.adafruit.com"), - ] + [mock.call(b"Host: "), mock.call(b"wifitest.adafruit.com"),] ) r2 = s.get("https://" + host + path + "2") @@ -95,10 +86,7 @@ def test_get_twice_after_second(): ] ) sock.send.assert_has_calls( - [ - mock.call(b"Host: "), - mock.call(b"wifitest.adafruit.com"), - ] + [mock.call(b"Host: "), mock.call(b"wifitest.adafruit.com"),] ) sock.connect.assert_called_once_with((host, 443)) pool.socket.assert_called_once() @@ -129,10 +117,7 @@ def test_connect_out_of_memory(): ] ) sock.send.assert_has_calls( - [ - mock.call(b"Host: "), - mock.call(b"wifitest.adafruit.com"), - ] + [mock.call(b"Host: "), mock.call(b"wifitest.adafruit.com"),] ) assert r.text == str(text, "utf-8") @@ -146,10 +131,7 @@ def test_connect_out_of_memory(): ] ) sock3.send.assert_has_calls( - [ - mock.call(b"Host: "), - mock.call(b"wifitest2.adafruit.com"), - ] + [mock.call(b"Host: "), mock.call(b"wifitest2.adafruit.com"),] ) assert r.text == str(text, "utf-8") @@ -169,17 +151,11 @@ def test_second_send_fails(): r = s.get("https://" + host + path) sock.send.assert_has_calls( - [ - mock.call(b"testwifi/index.html"), - ] + [mock.call(b"testwifi/index.html"),] ) sock.send.assert_has_calls( - [ - mock.call(b"Host: "), - mock.call(b"wifitest.adafruit.com"), - mock.call(b"\r\n"), - ] + [mock.call(b"Host: "), mock.call(b"wifitest.adafruit.com"), mock.call(b"\r\n"),] ) assert r.text == str(text, "utf-8") From c044eaba2e2dc525578a998eb9333958f4f2badf Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 23 Sep 2020 17:00:43 -0700 Subject: [PATCH 5/5] Lint --- adafruit_requests.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/adafruit_requests.py b/adafruit_requests.py index dcb9046..2d4d578 100755 --- a/adafruit_requests.py +++ b/adafruit_requests.py @@ -442,7 +442,8 @@ def _get_socket(self, host, port, proto, *, timeout=1): self._socket_free[sock] = False return sock - def _send(self, socket, data): + @staticmethod + def _send(socket, data): total_sent = 0 while total_sent < len(data): sent = socket.send(data[total_sent:]) @@ -453,6 +454,7 @@ def _send(self, socket, data): total_sent += sent def _send_request(self, socket, host, method, path, headers, data, json): + # pylint: disable=too-many-arguments self._send(socket, bytes(method, "utf-8")) self._send(socket, b" /") self._send(socket, bytes(path, "utf-8"))