From 51cdd37a74e58224c7f735a5ea6ebe3681b88b4d Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 9 Jan 2023 09:15:22 -0600 Subject: [PATCH] preserve last exception when things are going wrong CircuitPython 8 supports exception chaining, so that the original problem can be shown. Here's how it looks on desktop python3: ``` Traceback (most recent call last): File "/home/jepler/src/bundle/libraries/helpers/requests/adafruit_requests.py", line 527, in _get_socket sock.connect((connect_host, port)) ConnectionRefusedError: [Errno 111] Connection refused The above exception was the direct cause of the following exception: Traceback (most recent call last): File "", line 1, in File "/home/jepler/src/bundle/libraries/helpers/requests/adafruit_requests.py", line 721, in get return self.request("GET", url, **kw) File "/home/jepler/src/bundle/libraries/helpers/requests/adafruit_requests.py", line 661, in request socket = self._get_socket(host, port, proto, timeout=timeout) File "/home/jepler/src/bundle/libraries/helpers/requests/adafruit_requests.py", line 508, in _get_socket raise RuntimeError("Sending request failed") from last_exc RuntimeError: Sending request failed ``` --- adafruit_requests.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/adafruit_requests.py b/adafruit_requests.py index 73993ba..73e4dda 100644 --- a/adafruit_requests.py +++ b/adafruit_requests.py @@ -499,19 +499,22 @@ def _get_socket( )[0] retry_count = 0 sock = None + last_exc = None while retry_count < 5 and sock is None: if retry_count > 0: if any(self._socket_free.items()): self._free_sockets() else: - raise RuntimeError("Sending request failed") + raise RuntimeError("Sending request failed") from last_exc retry_count += 1 try: sock = self._socket_pool.socket(addr_info[0], addr_info[1]) - except OSError: + except OSError as exc: + last_exc = exc continue - except RuntimeError: + except RuntimeError as exc: + last_exc = exc continue connect_host = addr_info[-1][0] @@ -522,15 +525,17 @@ def _get_socket( try: sock.connect((connect_host, port)) - except MemoryError: + except MemoryError as exc: + last_exc = exc sock.close() sock = None - except OSError: + except OSError as exc: + last_exc = exc sock.close() sock = None if sock is None: - raise RuntimeError("Repeated socket failures") + raise RuntimeError("Repeated socket failures") from last_exc self._open_sockets[key] = sock self._socket_free[sock] = False @@ -650,13 +655,15 @@ def request( # We may fail to send the request if the socket we got is closed already. So, try a second # time in that case. retry_count = 0 + last_exc = None while retry_count < 2: retry_count += 1 socket = self._get_socket(host, port, proto, timeout=timeout) ok = True try: self._send_request(socket, host, method, path, headers, data, json) - except OSError: + except OSError as exc: + last_exc = exc ok = False if ok: # Read the H of "HTTP/1.1" to make sure the socket is alive. send can appear to work @@ -676,7 +683,7 @@ def request( socket = None if not socket: - raise OutOfRetries("Repeated socket failures") + raise OutOfRetries("Repeated socket failures") from last_exc resp = Response(socket, self) # our response if "location" in resp.headers and 300 <= resp.status_code <= 399: