Skip to content

Instantly share code, notes, and snippets.

@jsstevenson
Created October 3, 2025 18:24
Show Gist options
  • Select an option

  • Save jsstevenson/58ca189a22bcb7f336789ac0870bb7f5 to your computer and use it in GitHub Desktop.

Select an option

Save jsstevenson/58ca189a22bcb7f336789ac0870bb7f5 to your computer and use it in GitHub Desktop.
self = <botocore.awsrequest.AWSHTTPConnectionPool object at 0x11195bf50>, conn = <botocore.awsrequest.AWSHTTPConnection object at 0x1119d4b90>
method = 'POST', url = '/Execute'
body = b'{"sql": "DROP DATABASE IF EXISTS `varcat`;", "secretArn": "arn:aws:secretsmanager:us-east-1:123456789012:secret:dummy", "resourceArn": "arn:aws:rds:us-east-1:123456789012:cluster:dummy"}'
headers = {'Content-Type': b'application/json', 'User-Agent': b'Boto3/1.40.42 md/Botocore#1.40.42 ua/2.1 os/macos#24.6.0 md/arch...vocation-id': b'e1996f6f-cd92-4adf-9410-7fcac12dce9e', 'amz-sdk-request': b'attempt=5; max=5', 'Content-Length': '186'}
retries = Retry(total=False, connect=None, read=None, redirect=0, status=None), timeout = Timeout(connect=60, read=60, total=None)
chunked = False, response_conn = <botocore.awsrequest.AWSHTTPConnection object at 0x1119d4b90>, preload_content = False
decode_content = False, enforce_content_length = True
def _make_request(
self,
conn: BaseHTTPConnection,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | None = None,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
chunked: bool = False,
response_conn: BaseHTTPConnection | None = None,
preload_content: bool = True,
decode_content: bool = True,
enforce_content_length: bool = True,
) -> BaseHTTPResponse:
"""
Perform a request on a given urllib connection object taken from our
pool.
:param conn:
a connection from one of our connection pools
:param method:
HTTP request method (such as GET, POST, PUT, etc.)
:param url:
The URL to perform the request on.
:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.
:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.
:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.
Pass ``None`` to retry until you receive a response. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.
If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.
:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.
:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.
:param chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.
:param response_conn:
Set this to ``None`` if you will handle releasing the connection or
set the connection to have the response release it.
:param preload_content:
If True, the response's body will be preloaded during construction.
:param decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.
:param enforce_content_length:
Enforce content length checking. Body returned by server must match
value of Content-Length header, if present. Otherwise, raise error.
"""
self.num_requests += 1
timeout_obj = self._get_timeout(timeout)
timeout_obj.start_connect()
conn.timeout = Timeout.resolve_default_timeout(timeout_obj.connect_timeout)
try:
# Trigger any extra validation we need to do.
try:
self._validate_conn(conn)
except (SocketTimeout, BaseSSLError) as e:
self._raise_timeout(err=e, url=url, timeout_value=conn.timeout)
raise
# _validate_conn() starts the connection to an HTTPS proxy
# so we need to wrap errors with 'ProxyError' here too.
except (
OSError,
NewConnectionError,
TimeoutError,
BaseSSLError,
CertificateError,
SSLError,
) as e:
new_e: Exception = e
if isinstance(e, (BaseSSLError, CertificateError)):
new_e = SSLError(e)
# If the connection didn't successfully connect to it's proxy
# then there
if isinstance(
new_e, (OSError, NewConnectionError, TimeoutError, SSLError)
) and (conn and conn.proxy and not conn.has_connected_to_proxy):
new_e = _wrap_proxy_error(new_e, conn.proxy.scheme)
raise new_e
# conn.request() calls http.client.*.request, not the method in
# urllib3.request. It also calls makefile (recv) on the socket.
try:
conn.request(
method,
url,
body=body,
headers=headers,
chunked=chunked,
preload_content=preload_content,
decode_content=decode_content,
enforce_content_length=enforce_content_length,
)
# We are swallowing BrokenPipeError (errno.EPIPE) since the server is
# legitimately able to close the connection after sending a valid response.
# With this behaviour, the received response is still readable.
except BrokenPipeError:
pass
except OSError as e:
# MacOS/Linux
# EPROTOTYPE and ECONNRESET are needed on macOS
# https://erickt.github.io/blog/2014/11/19/adventures-in-debugging-a-potential-osx-kernel-bug/
# Condition changed later to emit ECONNRESET instead of only EPROTOTYPE.
if e.errno != errno.EPROTOTYPE and e.errno != errno.ECONNRESET:
raise
# Reset the timeout for the recv() on the socket
read_timeout = timeout_obj.read_timeout
if not conn.is_closed:
# In Python 3 socket.py will catch EAGAIN and return None when you
# try and read into the file pointer created by http.client, which
# instead raises a BadStatusLine exception. Instead of catching
# the exception and assuming all BadStatusLine exceptions are read
# timeouts, check for a zero timeout before making the request.
if read_timeout == 0:
raise ReadTimeoutError(
self, url, f"Read timed out. (read timeout={read_timeout})"
)
conn.timeout = read_timeout
# Receive the response from the server
try:
> response = conn.getresponse()
^^^^^^^^^^^^^^^^^^
.venv/lib/python3.12/site-packages/urllib3/connectionpool.py:534:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.venv/lib/python3.12/site-packages/urllib3/connection.py:565: in getresponse
httplib_response = super().getresponse()
^^^^^^^^^^^^^^^^^^^^^
../../.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/http/client.py:1430: in getresponse
response.begin()
../../.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/http/client.py:331: in begin
version, status, reason = self._read_status()
^^^^^^^^^^^^^^^^^^^
../../.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/http/client.py:292: in _read_status
line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <socket.SocketIO object at 0x1119d4c70>, b = <memory at 0x1111534c0>
def readinto(self, b):
"""Read up to len(b) bytes into the writable buffer *b* and return
the number of bytes read. If the socket is non-blocking and no bytes
are available, None is returned.
If *b* is non-empty, a 0 return value indicates that the connection
was shutdown at the other end.
"""
self._checkClosed()
self._checkReadable()
if self._timeout_occurred:
raise OSError("cannot read from timed out object")
while True:
try:
> return self._sock.recv_into(b)
^^^^^^^^^^^^^^^^^^^^^^^
E TimeoutError: timed out
../../.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/socket.py:720: TimeoutError
The above exception was the direct cause of the following exception:
self = <botocore.httpsession.URLLib3Session object at 0x1111e8050>
request = <AWSPreparedRequest stream_output=False, method=POST, url=http://localhost:8081/Execute, headers={'Content-Type': b'ap...ocation-id': b'e1996f6f-cd92-4adf-9410-7fcac12dce9e', 'amz-sdk-request': b'attempt=5; max=5', 'Content-Length': '186'}>
def send(self, request):
try:
proxy_url = self._proxy_config.proxy_url_for(request.url)
manager = self._get_connection_manager(request.url, proxy_url)
conn = manager.connection_from_url(request.url)
self._setup_ssl_cert(conn, request.url, self._verify)
if ensure_boolean(
os.environ.get('BOTO_EXPERIMENTAL__ADD_PROXY_HOST_HEADER', '')
):
# This is currently an "experimental" feature which provides
# no guarantees of backwards compatibility. It may be subject
# to change or removal in any patch version. Anyone opting in
# to this feature should strictly pin botocore.
host = urlparse(request.url).hostname
conn.proxy_headers['host'] = host
request_target = self._get_request_target(request.url, proxy_url)
> urllib_response = conn.urlopen(
method=request.method,
url=request_target,
body=request.body,
headers=request.headers,
retries=Retry(False),
assert_same_host=False,
preload_content=False,
decode_content=False,
chunked=self._chunked(request.headers),
)
.venv/lib/python3.12/site-packages/botocore/httpsession.py:465:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.venv/lib/python3.12/site-packages/urllib3/connectionpool.py:841: in urlopen
retries = retries.increment(
.venv/lib/python3.12/site-packages/urllib3/util/retry.py:449: in increment
raise reraise(type(error), error, _stacktrace)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.12/site-packages/urllib3/util/util.py:39: in reraise
raise value
.venv/lib/python3.12/site-packages/urllib3/connectionpool.py:787: in urlopen
response = self._make_request(
.venv/lib/python3.12/site-packages/urllib3/connectionpool.py:536: in _make_request
self._raise_timeout(err=e, url=url, timeout_value=read_timeout)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <botocore.awsrequest.AWSHTTPConnectionPool object at 0x11195bf50>, err = TimeoutError('timed out'), url = '/Execute'
timeout_value = 60
def _raise_timeout(
self,
err: BaseSSLError | OSError | SocketTimeout,
url: str,
timeout_value: _TYPE_TIMEOUT | None,
) -> None:
"""Is the error actually a timeout? Will raise a ReadTimeout or pass"""
if isinstance(err, SocketTimeout):
> raise ReadTimeoutError(
self, url, f"Read timed out. (read timeout={timeout_value})"
) from err
E urllib3.exceptions.ReadTimeoutError: AWSHTTPConnectionPool(host='localhost', port=8081): Read timed out. (read timeout=60)
.venv/lib/python3.12/site-packages/urllib3/connectionpool.py:367: ReadTimeoutError
During handling of the above exception, another exception occurred:
rds = <botocore.client.RDSDataService object at 0x111913d70>
rds_params = {'resourceArn': 'arn:aws:rds:us-east-1:123456789012:cluster:dummy', 'secretArn': 'arn:aws:secretsmanager:us-east-1:123456789012:secret:dummy'}
_set_env = None
@pytest.fixture(scope="module")
def schema(rds, rds_params, _set_env): # noqa: PT004
> rds.execute_statement(sql="DROP DATABASE IF EXISTS `varcat`;", **rds_params)
tests/integration/conftest.py:70:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.venv/lib/python3.12/site-packages/botocore/client.py:602: in _api_call
return self._make_api_call(operation_name, kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.12/site-packages/botocore/context.py:123: in wrapper
return func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.12/site-packages/botocore/client.py:1060: in _make_api_call
http, parsed_response = self._make_request(
.venv/lib/python3.12/site-packages/botocore/client.py:1084: in _make_request
return self._endpoint.make_request(operation_model, request_dict)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.12/site-packages/botocore/endpoint.py:119: in make_request
return self._send_request(request_dict, operation_model)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.12/site-packages/botocore/endpoint.py:200: in _send_request
while self._needs_retry(
.venv/lib/python3.12/site-packages/botocore/endpoint.py:360: in _needs_retry
responses = self._event_emitter.emit(
.venv/lib/python3.12/site-packages/botocore/hooks.py:412: in emit
return self._emitter.emit(aliased_event_name, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.12/site-packages/botocore/hooks.py:256: in emit
return self._emit(event_name, kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.12/site-packages/botocore/hooks.py:239: in _emit
response = handler(**kwargs)
^^^^^^^^^^^^^^^^^
.venv/lib/python3.12/site-packages/botocore/retryhandler.py:207: in __call__
if self._checker(**checker_kwargs):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.12/site-packages/botocore/retryhandler.py:284: in __call__
should_retry = self._should_retry(
.venv/lib/python3.12/site-packages/botocore/retryhandler.py:320: in _should_retry
return self._checker(attempt_number, response, caught_exception)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.12/site-packages/botocore/retryhandler.py:363: in __call__
checker_response = checker(
.venv/lib/python3.12/site-packages/botocore/retryhandler.py:247: in __call__
return self._check_caught_exception(
.venv/lib/python3.12/site-packages/botocore/retryhandler.py:416: in _check_caught_exception
raise caught_exception
.venv/lib/python3.12/site-packages/botocore/endpoint.py:279: in _do_get_response
http_response = self._send(request)
^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.12/site-packages/botocore/endpoint.py:383: in _send
return self.http_session.send(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <botocore.httpsession.URLLib3Session object at 0x1111e8050>
request = <AWSPreparedRequest stream_output=False, method=POST, url=http://localhost:8081/Execute, headers={'Content-Type': b'ap...ocation-id': b'e1996f6f-cd92-4adf-9410-7fcac12dce9e', 'amz-sdk-request': b'attempt=5; max=5', 'Content-Length': '186'}>
def send(self, request):
try:
proxy_url = self._proxy_config.proxy_url_for(request.url)
manager = self._get_connection_manager(request.url, proxy_url)
conn = manager.connection_from_url(request.url)
self._setup_ssl_cert(conn, request.url, self._verify)
if ensure_boolean(
os.environ.get('BOTO_EXPERIMENTAL__ADD_PROXY_HOST_HEADER', '')
):
# This is currently an "experimental" feature which provides
# no guarantees of backwards compatibility. It may be subject
# to change or removal in any patch version. Anyone opting in
# to this feature should strictly pin botocore.
host = urlparse(request.url).hostname
conn.proxy_headers['host'] = host
request_target = self._get_request_target(request.url, proxy_url)
urllib_response = conn.urlopen(
method=request.method,
url=request_target,
body=request.body,
headers=request.headers,
retries=Retry(False),
assert_same_host=False,
preload_content=False,
decode_content=False,
chunked=self._chunked(request.headers),
)
http_response = botocore.awsrequest.AWSResponse(
request.url,
urllib_response.status,
urllib_response.headers,
urllib_response,
)
if not request.stream_output:
# Cause the raw stream to be exhausted immediately. We do it
# this way instead of using preload_content because
# preload_content will never buffer chunked responses
http_response.content
return http_response
except URLLib3SSLError as e:
raise SSLError(endpoint_url=request.url, error=e)
except (NewConnectionError, socket.gaierror) as e:
raise EndpointConnectionError(endpoint_url=request.url, error=e)
except ProxyError as e:
raise ProxyConnectionError(
proxy_url=mask_proxy_url(proxy_url), error=e
)
except URLLib3ConnectTimeoutError as e:
raise ConnectTimeoutError(endpoint_url=request.url, error=e)
except URLLib3ReadTimeoutError as e:
> raise ReadTimeoutError(endpoint_url=request.url, error=e)
E botocore.exceptions.ReadTimeoutError: Read timeout on endpoint URL: "http://localhost:8081/Execute"
.venv/lib/python3.12/site-packages/botocore/httpsession.py:502: ReadTimeoutError
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment