From 2e12b7a4cfecaa75603ccc5f381d3771c7198056 Mon Sep 17 00:00:00 2001 From: Adam Dangoor Date: Sun, 4 Feb 2024 01:27:39 +0000 Subject: [PATCH 1/2] Return a new error when the server returns a 5xx status code. --- CHANGELOG.rst | 2 ++ src/vws/exceptions/custom_exceptions.py | 21 +++++++++++++++++++++ src/vws/query.py | 6 ++++++ src/vws/vws.py | 6 ++++++ 4 files changed, 35 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 281270708..2233deab5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,8 @@ Changelog Next ---- +* Return a new error (``vws.custom_exceptions.ServerError``) when the server returns a 5xx status code. + 2023.12.27 ------------ diff --git a/src/vws/exceptions/custom_exceptions.py b/src/vws/exceptions/custom_exceptions.py index ef88d53aa..41d13febf 100644 --- a/src/vws/exceptions/custom_exceptions.py +++ b/src/vws/exceptions/custom_exceptions.py @@ -42,3 +42,24 @@ class TargetProcessingTimeout(Exception): """ Exception raised when waiting for a target to be processed times out. """ + + +class ServerError(Exception): # pragma: no cover + """ + Exception raised when VWS returns a server error. + """ + + def __init__(self, response: Response) -> None: + """ + Args: + response: The response returned by Vuforia. + """ + super().__init__(response.text) + self._response = response + + @property + def response(self) -> Response: + """ + The response returned by Vuforia which included this error. + """ + return self._response diff --git a/src/vws/query.py b/src/vws/query.py index 5df811252..d4efa45b9 100644 --- a/src/vws/query.py +++ b/src/vws/query.py @@ -22,6 +22,7 @@ ) from vws.exceptions.custom_exceptions import ( RequestEntityTooLarge, + ServerError, ) from vws.include_target_data import CloudRecoIncludeTargetData from vws.reports import QueryResult, TargetData @@ -145,6 +146,11 @@ def query( if "Integer out of range" in response.text: raise MaxNumResultsOutOfRange(response=response) + if ( + response.status_code >= HTTPStatus.INTERNAL_SERVER_ERROR + ): # pragma: no cover + raise ServerError(response=response) + result_code = response.json()["result_code"] if result_code != "Success": exception = { diff --git a/src/vws/vws.py b/src/vws/vws.py index 267f88411..2962bc6b8 100644 --- a/src/vws/vws.py +++ b/src/vws/vws.py @@ -18,6 +18,7 @@ from vws.exceptions.custom_exceptions import ( OopsAnErrorOccurredPossiblyBadName, + ServerError, TargetProcessingTimeout, ) from vws.exceptions.vws_exceptions import ( @@ -188,6 +189,11 @@ def _make_request( # The Vuforia API returns a 429 response with no JSON body. raise TooManyRequests(response=response) + if ( + response.status_code >= HTTPStatus.INTERNAL_SERVER_ERROR + ): # pragma: no cover + raise ServerError(response=response) + result_code = response.json()["result_code"] if result_code == expected_result_code: From ca07d2351b576f3802d6716a9cb3ff4b49db38ad Mon Sep 17 00:00:00 2001 From: Adam Dangoor Date: Sun, 4 Feb 2024 13:19:31 +0000 Subject: [PATCH 2/2] Document ServerError might be raised in functions which might raise it --- src/vws/exceptions/custom_exceptions.py | 22 +++++++++++++ src/vws/exceptions/vws_exceptions.py | 7 ----- src/vws/query.py | 2 ++ src/vws/vws.py | 42 ++++++++++++++++++++++++- 4 files changed, 65 insertions(+), 8 deletions(-) diff --git a/src/vws/exceptions/custom_exceptions.py b/src/vws/exceptions/custom_exceptions.py index 41d13febf..5a7c1a9b5 100644 --- a/src/vws/exceptions/custom_exceptions.py +++ b/src/vws/exceptions/custom_exceptions.py @@ -63,3 +63,25 @@ def response(self) -> Response: The response returned by Vuforia which included this error. """ return self._response + + +class TooManyRequests(Exception): # pragma: no cover + """ + Exception raised when Vuforia returns a response with a result code + 'TooManyRequests'. + """ + + def __init__(self, response: Response) -> None: + """ + Args: + response: The response returned by Vuforia. + """ + super().__init__(response.text) + self._response = response + + @property + def response(self) -> Response: + """ + The response returned by Vuforia which included this error. + """ + return self._response diff --git a/src/vws/exceptions/vws_exceptions.py b/src/vws/exceptions/vws_exceptions.py index 9ff990255..3e080faf3 100644 --- a/src/vws/exceptions/vws_exceptions.py +++ b/src/vws/exceptions/vws_exceptions.py @@ -56,13 +56,6 @@ class RequestQuotaReached(VWSException): # pragma: no cover """ -class TooManyRequests(VWSException): # pragma: no cover - """ - Exception raised when Vuforia returns a response with a result code - 'TooManyRequests'. - """ - - class TargetStatusProcessing(VWSException): """ Exception raised when Vuforia returns a response with a result code diff --git a/src/vws/query.py b/src/vws/query.py index d4efa45b9..85501a3b0 100644 --- a/src/vws/query.py +++ b/src/vws/query.py @@ -95,6 +95,8 @@ def query( file in the grayscale or RGB color space. ~vws.exceptions.custom_exceptions.RequestEntityTooLarge: The given image is too large. + ~vws.exceptions.custom_exceptions.ServerError: There is an error + with Vuforia's servers. Returns: An ordered list of target details of matching targets. diff --git a/src/vws/vws.py b/src/vws/vws.py index 2962bc6b8..ca2f59963 100644 --- a/src/vws/vws.py +++ b/src/vws/vws.py @@ -20,6 +20,7 @@ OopsAnErrorOccurredPossiblyBadName, ServerError, TargetProcessingTimeout, + TooManyRequests, ) from vws.exceptions.vws_exceptions import ( AuthenticationFailure, @@ -37,7 +38,6 @@ TargetQuotaReached, TargetStatusNotSuccess, TargetStatusProcessing, - TooManyRequests, UnknownTarget, ) from vws.reports import ( @@ -167,6 +167,10 @@ def _make_request( an HTML page with the text "Oops, an error occurred". This has been seen to happen when the given name includes a bad character. + ~vws.exceptions.custom_exceptions.ServerError: There is an error + with Vuforia's servers. + ~vws.exceptions.custom_exceptions.TooManyRequests: Vuforia is rate + limiting access. json.decoder.JSONDecodeError: The server did not respond with valid JSON. This may happen if the server address is not a valid Vuforia server. @@ -274,6 +278,10 @@ def add_target( Vuforia returns an HTML page with the text "Oops, an error occurred". This has been seen to happen when the given name includes a bad character. + ~vws.exceptions.custom_exceptions.ServerError: There is an error + with Vuforia's servers. + ~vws.exceptions.custom_exceptions.TooManyRequests: Vuforia is rate + limiting access. """ image_data = _get_image_data(image=image) image_data_encoded = base64.b64encode(image_data).decode("ascii") @@ -320,6 +328,10 @@ def get_target_record(self, target_id: str) -> TargetStatusAndRecord: does not match a target in the database. ~vws.exceptions.vws_exceptions.RequestTimeTooSkewed: There is an error with the time sent to Vuforia. + ~vws.exceptions.custom_exceptions.ServerError: There is an error + with Vuforia's servers. + ~vws.exceptions.custom_exceptions.TooManyRequests: Vuforia is rate + limiting access. """ response = self._make_request( method="GET", @@ -377,6 +389,10 @@ def wait_for_target_processed( does not match a target in the database. ~vws.exceptions.vws_exceptions.RequestTimeTooSkewed: There is an error with the time sent to Vuforia. + ~vws.exceptions.custom_exceptions.ServerError: There is an error + with Vuforia's servers. + ~vws.exceptions.custom_exceptions.TooManyRequests: Vuforia is rate + limiting access. """ start_time = time.monotonic() while True: @@ -408,6 +424,10 @@ def list_targets(self) -> list[str]: known database. ~vws.exceptions.vws_exceptions.RequestTimeTooSkewed: There is an error with the time sent to Vuforia. + ~vws.exceptions.custom_exceptions.ServerError: There is an error + with Vuforia's servers. + ~vws.exceptions.custom_exceptions.TooManyRequests: Vuforia is rate + limiting access. """ response = self._make_request( method="GET", @@ -441,6 +461,10 @@ def get_target_summary_report(self, target_id: str) -> TargetSummaryReport: does not match a target in the database. ~vws.exceptions.vws_exceptions.RequestTimeTooSkewed: There is an error with the time sent to Vuforia. + ~vws.exceptions.custom_exceptions.ServerError: There is an error + with Vuforia's servers. + ~vws.exceptions.custom_exceptions.TooManyRequests: Vuforia is rate + limiting access. """ response = self._make_request( method="GET", @@ -480,6 +504,10 @@ def get_database_summary_report(self) -> DatabaseSummaryReport: known database. ~vws.exceptions.vws_exceptions.RequestTimeTooSkewed: There is an error with the time sent to Vuforia. + ~vws.exceptions.custom_exceptions.ServerError: There is an error + with Vuforia's servers. + ~vws.exceptions.custom_exceptions.TooManyRequests: Vuforia is rate + limiting access. """ response = self._make_request( method="GET", @@ -526,6 +554,10 @@ def delete_target(self, target_id: str) -> None: target is in the processing state. ~vws.exceptions.vws_exceptions.RequestTimeTooSkewed: There is an error with the time sent to Vuforia. + ~vws.exceptions.custom_exceptions.ServerError: There is an error + with Vuforia's servers. + ~vws.exceptions.custom_exceptions.TooManyRequests: Vuforia is rate + limiting access. """ self._make_request( method="DELETE", @@ -559,6 +591,10 @@ def get_duplicate_targets(self, target_id: str) -> list[str]: inactive. ~vws.exceptions.vws_exceptions.RequestTimeTooSkewed: There is an error with the time sent to Vuforia. + ~vws.exceptions.custom_exceptions.ServerError: There is an error + with Vuforia's servers. + ~vws.exceptions.custom_exceptions.TooManyRequests: Vuforia is rate + limiting access. """ response = self._make_request( method="GET", @@ -618,6 +654,10 @@ def update_target( inactive. ~vws.exceptions.vws_exceptions.RequestTimeTooSkewed: There is an error with the time sent to Vuforia. + ~vws.exceptions.custom_exceptions.ServerError: There is an error + with Vuforia's servers. + ~vws.exceptions.custom_exceptions.TooManyRequests: Vuforia is rate + limiting access. """ data: dict[str, str | bool | float | int] = {}