For posterity, I record here the traceback triggered by iNaturalist hanging up on us. I will discuss with @jcook (pyinaturalist maintainer). I know pyinat has some retry logic for handling various exceptions that can be encountered, but I donāt think that POST is one of them (and I can think of good reasons why it normally shouldnāt be!) Now, pyinaturalist ultimately uses urllib3.util.Retry, and the doc for that does not include POST as one of the default allowed methods:
https://urllib3.readthedocs.io/en/stable/reference/urllib3.util.html#urllib3.util.Retry.DEFAULT_ALLOWED_METHODS
Iām pretty sure that the remote hanging up on us is new behaviour, but since that couldāve happened anyway, even if it has recently become more frequent, I think pyinaturalist probably needs to have exception handling for this particular case.
Exception in command 'event join'
Traceback (most recent call last):
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/urllib3/connectionpool.py", line 787, in urlopen
response = self._make_request(
^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/urllib3/connectionpool.py", line 534, in _make_request
response = conn.getresponse()
^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/urllib3/connection.py", line 516, in getresponse
httplib_response = super().getresponse()
^^^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/3.11.10/lib/python3.11/http/client.py", line 1395, in getresponse
response.begin()
File "/home/redbot/.pyenv/versions/3.11.10/lib/python3.11/http/client.py", line 325, in begin
version, status, reason = self._read_status()
^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/3.11.10/lib/python3.11/http/client.py", line 294, in _read_status
raise RemoteDisconnected("Remote end closed connection without"
http.client.RemoteDisconnected: Remote end closed connection without response
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/requests/adapters.py", line 667, in send
resp = conn.urlopen(
^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/urllib3/connectionpool.py", line 841, in urlopen
retries = retries.increment(
^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/urllib3/util/retry.py", line 474, in increment
raise reraise(type(error), error, _stacktrace)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/urllib3/util/util.py", line 38, in reraise
raise value.with_traceback(tb)
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/urllib3/connectionpool.py", line 787, in urlopen
response = self._make_request(
^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/urllib3/connectionpool.py", line 534, in _make_request
response = conn.getresponse()
^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/urllib3/connection.py", line 516, in getresponse
httplib_response = super().getresponse()
^^^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/3.11.10/lib/python3.11/http/client.py", line 1395, in getresponse
response.begin()
File "/home/redbot/.pyenv/versions/3.11.10/lib/python3.11/http/client.py", line 325, in begin
version, status, reason = self._read_status()
^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/3.11.10/lib/python3.11/http/client.py", line 294, in _read_status
raise RemoteDisconnected("Remote end closed connection without"
urllib3.exceptions.ProtocolError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/discord/ext/commands/core.py", line 235, in wrapped
ret = await coro(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.local/share/Dronefly/cogs/CogManager/cogs/inatcog/utils.py", line 60, in wrapped
await coro(*args, **kwargs)
File "/home/redbot/.local/share/Dronefly/cogs/CogManager/cogs/inatcog/commands/event.py", line 166, in event_join
msg = await self._event_action(
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.local/share/Dronefly/cogs/CogManager/cogs/inatcog/commands/event.py", line 135, in _event_action
update_response = await client.projects.add_users(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.local/share/Dronefly/cogs/CogManager/cogs/inatcog/client.py", line 18, in async_wrapper
return await asyncio.wait_for(future, timeout=20)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/3.11.10/lib/python3.11/asyncio/tasks.py", line 489, in wait_for
return fut.result()
^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/3.11.10/lib/python3.11/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/pyinaturalist/controllers/project_controller.py", line 145, in add_users
response = self.client.request(add_project_users, project_id, user_ids, auth=True, **params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/pyinaturalist/client.py", line 153, in request
kwargs = self.add_defaults(request_function, kwargs, auth)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/dronefly/core/clients/inat.py", line 40, in add_defaults
_kwargs = super().add_defaults(request_function, kwargs, auth)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/pyinaturalist/client.py", line 111, in add_defaults
client_kwargs['access_token'] = get_access_token(**self.creds) # type: ignore
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/pyinaturalist/auth.py", line 97, in get_access_token
response = session.post(f'{API_V0}/oauth/token', json=payload)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/requests_cache/session.py", line 138, in post
return self.request('POST', url, data=data, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/pyinaturalist/session.py", line 273, in request
response = self.send(
^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/pyinaturalist/session.py", line 322, in send
response = super().send(
^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/requests_cache/session.py", line 230, in send
response = self._send_and_cache(request, actions, cached_response, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/requests_cache/session.py", line 254, in _send_and_cache
response = super().send(request, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/requests_ratelimiter/requests_ratelimiter.py", line 95, in send
response = super().send(request, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/requests/sessions.py", line 703, in send
r = adapter.send(request, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/requests/adapters.py", line 682, in send
raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/discord/ext/commands/bot.py", line 1366, in invoke
await ctx.command.invoke(ctx)
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/redbot/core/commands/commands.py", line 825, in invoke
await super().invoke(ctx)
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/discord/ext/commands/core.py", line 1650, in invoke
await ctx.invoked_subcommand.invoke(ctx)
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/discord/ext/commands/core.py", line 1029, in invoke
await injected(*ctx.args, **ctx.kwargs) # type: ignore
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/redbot/.pyenv/versions/red-Dronefly/lib/python3.11/site-packages/discord/ext/commands/core.py", line 244, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))