From 1f7fe70ffbd3810eebd74b42fcabdd27cdb5a521 Mon Sep 17 00:00:00 2001 From: Peter Annabel Date: Tue, 29 Jul 2025 11:07:32 -0500 Subject: [PATCH] Add handling of 429 Too Many Attempts response for when calls are ratelimited --- src/pyhuntress/clients/huntress_client.py | 14 ++++---------- src/pyhuntress/exceptions.py | 4 ++++ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/pyhuntress/clients/huntress_client.py b/src/pyhuntress/clients/huntress_client.py index d2fd7f5..0254cb1 100644 --- a/src/pyhuntress/clients/huntress_client.py +++ b/src/pyhuntress/clients/huntress_client.py @@ -20,6 +20,7 @@ from pyhuntress.exceptions import ( ObjectExistsError, PermissionsFailedException, ServerError, + TooManyRequestsException, ) if TYPE_CHECKING: @@ -80,15 +81,6 @@ class HuntressClient(ABC): params=cast(dict[str, Any], params or {}), stream=stream, ) -# elif rawdata: -# response = requests.request( -# method, -# url, -# headers=headers, -# data=rawdata, -# params=cast(dict[str, Any], params or {}), -# stream=stream, -# ) else: response = requests.request( method, @@ -100,7 +92,7 @@ class HuntressClient(ABC): if not response.ok: with contextlib.suppress(json.JSONDecodeError): details: dict = response.json() - if response.status_code == 400: # noqa: SIM102 (Expecting to handle other codes in the future) + if response.status_code == 400: if details.get("code") == "InvalidObject": errors = details.get("errors", []) if len(errors) > 1: @@ -125,6 +117,8 @@ class HuntressClient(ABC): raise MethodNotAllowedException(response) if response.status_code == 409: raise ConflictException(response) + if response.status_code == 429: + raise TooManyRequestsException(response) if response.status_code == 500: # if timeout is mentioned anywhere in the response then we'll retry. # Ideally we'd return immediately on any non-timeout errors (since diff --git a/src/pyhuntress/exceptions.py b/src/pyhuntress/exceptions.py index e5b8f49..4f81af3 100644 --- a/src/pyhuntress/exceptions.py +++ b/src/pyhuntress/exceptions.py @@ -75,6 +75,10 @@ class ConflictException(HuntressException): _code_explanation = "Conflict" _error_suggestion = "This resource is possibly in use or conflicts with another record." +class TooManyRequestsException(HuntressException): + _code_explanation = "Too Many Requests" + _error_suggestion = "This resource is currently being rate limited. Please wait and try again." + class ServerError(HuntressException): _code_explanation = "Internal Server Error"