Skip to content

Commit 85a0fa0

Browse files
Merge pull request #2885 from VWS-Python/adamtheturtle/vwserror-result-code
Centralize VWS result code exception mapping
2 parents 66d4873 + ba1d67e commit 85a0fa0

File tree

7 files changed

+97
-136
lines changed

7 files changed

+97
-136
lines changed

src/vws/async_vumark_service.py

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,9 @@
77
from beartype import BeartypeConf, beartype
88

99
from vws._async_vws_request import async_target_api_request
10+
from vws.exceptions.base_exceptions import VWSError
1011
from vws.exceptions.custom_exceptions import ServerError
11-
from vws.exceptions.vws_exceptions import (
12-
AuthenticationFailureError,
13-
BadRequestError,
14-
DateRangeError,
15-
FailError,
16-
InvalidAcceptHeaderError,
17-
InvalidInstanceIdError,
18-
InvalidTargetTypeError,
19-
RequestTimeTooSkewedError,
20-
TargetStatusNotSuccessError,
21-
TooManyRequestsError,
22-
UnknownTargetError,
23-
)
12+
from vws.exceptions.vws_exceptions import TooManyRequestsError
2413
from vws.transports import AsyncHTTPXTransport, AsyncTransport
2514
from vws.vumark_accept import VuMarkAccept
2615

@@ -154,17 +143,7 @@ async def generate_vumark_instance(
154143

155144
result_code = json.loads(s=response.text)["result_code"]
156145

157-
exception = {
158-
"AuthenticationFailure": (AuthenticationFailureError),
159-
"BadRequest": BadRequestError,
160-
"DateRangeError": DateRangeError,
161-
"Fail": FailError,
162-
"InvalidAcceptHeader": InvalidAcceptHeaderError,
163-
"InvalidInstanceId": InvalidInstanceIdError,
164-
"InvalidTargetType": InvalidTargetTypeError,
165-
"RequestTimeTooSkewed": RequestTimeTooSkewedError,
166-
"TargetStatusNotSuccess": (TargetStatusNotSuccessError),
167-
"UnknownTarget": UnknownTargetError,
168-
}[result_code]
169-
170-
raise exception(response=response)
146+
raise VWSError.from_result_code(
147+
result_code=result_code,
148+
response=response,
149+
)

src/vws/async_vws.py

Lines changed: 6 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,12 @@
1111
from vws._async_vws_request import async_target_api_request
1212
from vws._image_utils import ImageType as _ImageType
1313
from vws._image_utils import get_image_data as _get_image_data
14+
from vws.exceptions.base_exceptions import VWSError
1415
from vws.exceptions.custom_exceptions import (
1516
ServerError,
1617
TargetProcessingTimeoutError,
1718
)
18-
from vws.exceptions.vws_exceptions import (
19-
AuthenticationFailureError,
20-
BadImageError,
21-
BadRequestError,
22-
DateRangeError,
23-
FailError,
24-
ImageTooLargeError,
25-
MetadataTooLargeError,
26-
ProjectHasNoAPIAccessError,
27-
ProjectInactiveError,
28-
ProjectSuspendedError,
29-
RequestQuotaReachedError,
30-
RequestTimeTooSkewedError,
31-
TargetNameExistError,
32-
TargetQuotaReachedError,
33-
TargetStatusNotSuccessError,
34-
TargetStatusProcessingError,
35-
TooManyRequestsError,
36-
UnknownTargetError,
37-
)
19+
from vws.exceptions.vws_exceptions import TooManyRequestsError
3820
from vws.reports import (
3921
DatabaseSummaryReport,
4022
TargetStatusAndRecord,
@@ -158,27 +140,10 @@ async def make_request(
158140
if result_code == expected_result_code:
159141
return response
160142

161-
exception = {
162-
"AuthenticationFailure": AuthenticationFailureError,
163-
"BadImage": BadImageError,
164-
"BadRequest": BadRequestError,
165-
"DateRangeError": DateRangeError,
166-
"Fail": FailError,
167-
"ImageTooLarge": ImageTooLargeError,
168-
"MetadataTooLarge": MetadataTooLargeError,
169-
"ProjectHasNoAPIAccess": ProjectHasNoAPIAccessError,
170-
"ProjectInactive": ProjectInactiveError,
171-
"ProjectSuspended": ProjectSuspendedError,
172-
"RequestQuotaReached": RequestQuotaReachedError,
173-
"RequestTimeTooSkewed": RequestTimeTooSkewedError,
174-
"TargetNameExist": TargetNameExistError,
175-
"TargetQuotaReached": TargetQuotaReachedError,
176-
"TargetStatusNotSuccess": TargetStatusNotSuccessError,
177-
"TargetStatusProcessing": TargetStatusProcessingError,
178-
"UnknownTarget": UnknownTargetError,
179-
}[result_code]
180-
181-
raise exception(response=response)
143+
raise VWSError.from_result_code(
144+
result_code=result_code,
145+
response=response,
146+
)
182147

183148
async def add_target(
184149
self,

src/vws/exceptions/base_exceptions.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
Cloud Recognition Web API.
55
"""
66

7+
from collections.abc import Mapping
8+
from typing import ClassVar
9+
710
from beartype import beartype
811

912
from vws.response import Response
@@ -35,6 +38,8 @@ class VWSError(Exception):
3538
https://developer.vuforia.com/library/web-api/cloud-targets-web-services-api#result-codes.
3639
"""
3740

41+
_exceptions_by_result_code: ClassVar[dict[str, type["VWSError"]]] = {}
42+
3843
def __init__(self, response: Response) -> None:
3944
"""
4045
Args:
@@ -43,6 +48,26 @@ def __init__(self, response: Response) -> None:
4348
super().__init__()
4449
self._response = response
4550

51+
@classmethod
52+
def register_exceptions_by_result_code(
53+
cls,
54+
*,
55+
exceptions_by_result_code: Mapping[str, type["VWSError"]],
56+
) -> None:
57+
"""Register ``result_code`` to exception mappings."""
58+
cls._exceptions_by_result_code.update(exceptions_by_result_code)
59+
60+
@classmethod
61+
def from_result_code(
62+
cls,
63+
*,
64+
result_code: str,
65+
response: Response,
66+
) -> "VWSError":
67+
"""Create the mapped exception for a VWS ``result_code``."""
68+
exception_type = cls._exceptions_by_result_code[result_code]
69+
return exception_type(response=response)
70+
4671
@property
4772
def response(self) -> Response:
4873
"""The response returned by Vuforia which included this error."""

src/vws/exceptions/vws_exceptions.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,3 +202,29 @@ class InvalidTargetTypeError(VWSError):
202202
"""Exception raised when Vuforia returns a response with a result code
203203
``InvalidTargetType``.
204204
"""
205+
206+
207+
VWSError.register_exceptions_by_result_code(
208+
exceptions_by_result_code={
209+
"AuthenticationFailure": AuthenticationFailureError,
210+
"BadImage": BadImageError,
211+
"BadRequest": BadRequestError,
212+
"DateRangeError": DateRangeError,
213+
"Fail": FailError,
214+
"ImageTooLarge": ImageTooLargeError,
215+
"InvalidAcceptHeader": InvalidAcceptHeaderError,
216+
"InvalidInstanceId": InvalidInstanceIdError,
217+
"InvalidTargetType": InvalidTargetTypeError,
218+
"MetadataTooLarge": MetadataTooLargeError,
219+
"ProjectHasNoAPIAccess": ProjectHasNoAPIAccessError,
220+
"ProjectInactive": ProjectInactiveError,
221+
"ProjectSuspended": ProjectSuspendedError,
222+
"RequestQuotaReached": RequestQuotaReachedError,
223+
"RequestTimeTooSkewed": RequestTimeTooSkewedError,
224+
"TargetNameExist": TargetNameExistError,
225+
"TargetQuotaReached": TargetQuotaReachedError,
226+
"TargetStatusNotSuccess": TargetStatusNotSuccessError,
227+
"TargetStatusProcessing": TargetStatusProcessingError,
228+
"UnknownTarget": UnknownTargetError,
229+
},
230+
)

src/vws/vumark_service.py

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,9 @@
66
from beartype import BeartypeConf, beartype
77

88
from vws._vws_request import target_api_request
9+
from vws.exceptions.base_exceptions import VWSError
910
from vws.exceptions.custom_exceptions import ServerError
10-
from vws.exceptions.vws_exceptions import (
11-
AuthenticationFailureError,
12-
BadRequestError,
13-
DateRangeError,
14-
FailError,
15-
InvalidAcceptHeaderError,
16-
InvalidInstanceIdError,
17-
InvalidTargetTypeError,
18-
RequestTimeTooSkewedError,
19-
TargetStatusNotSuccessError,
20-
TooManyRequestsError,
21-
UnknownTargetError,
22-
)
11+
from vws.exceptions.vws_exceptions import TooManyRequestsError
2312
from vws.transports import RequestsTransport, Transport
2413
from vws.vumark_accept import VuMarkAccept
2514

@@ -135,17 +124,7 @@ def generate_vumark_instance(
135124

136125
result_code = json.loads(s=response.text)["result_code"]
137126

138-
exception = {
139-
"AuthenticationFailure": AuthenticationFailureError,
140-
"BadRequest": BadRequestError,
141-
"DateRangeError": DateRangeError,
142-
"Fail": FailError,
143-
"InvalidAcceptHeader": InvalidAcceptHeaderError,
144-
"InvalidInstanceId": InvalidInstanceIdError,
145-
"InvalidTargetType": InvalidTargetTypeError,
146-
"RequestTimeTooSkewed": RequestTimeTooSkewedError,
147-
"TargetStatusNotSuccess": TargetStatusNotSuccessError,
148-
"UnknownTarget": UnknownTargetError,
149-
}[result_code]
150-
151-
raise exception(response=response)
127+
raise VWSError.from_result_code(
128+
result_code=result_code,
129+
response=response,
130+
)

src/vws/vws.py

Lines changed: 6 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,12 @@
1010
from vws._image_utils import ImageType as _ImageType
1111
from vws._image_utils import get_image_data as _get_image_data
1212
from vws._vws_request import target_api_request
13+
from vws.exceptions.base_exceptions import VWSError
1314
from vws.exceptions.custom_exceptions import (
1415
ServerError,
1516
TargetProcessingTimeoutError,
1617
)
17-
from vws.exceptions.vws_exceptions import (
18-
AuthenticationFailureError,
19-
BadImageError,
20-
BadRequestError,
21-
DateRangeError,
22-
FailError,
23-
ImageTooLargeError,
24-
MetadataTooLargeError,
25-
ProjectHasNoAPIAccessError,
26-
ProjectInactiveError,
27-
ProjectSuspendedError,
28-
RequestQuotaReachedError,
29-
RequestTimeTooSkewedError,
30-
TargetNameExistError,
31-
TargetQuotaReachedError,
32-
TargetStatusNotSuccessError,
33-
TargetStatusProcessingError,
34-
TooManyRequestsError,
35-
UnknownTargetError,
36-
)
18+
from vws.exceptions.vws_exceptions import TooManyRequestsError
3719
from vws.reports import (
3820
DatabaseSummaryReport,
3921
TargetStatusAndRecord,
@@ -143,27 +125,10 @@ def make_request(
143125
if result_code == expected_result_code:
144126
return response
145127

146-
exception = {
147-
"AuthenticationFailure": AuthenticationFailureError,
148-
"BadImage": BadImageError,
149-
"BadRequest": BadRequestError,
150-
"DateRangeError": DateRangeError,
151-
"Fail": FailError,
152-
"ImageTooLarge": ImageTooLargeError,
153-
"MetadataTooLarge": MetadataTooLargeError,
154-
"ProjectHasNoAPIAccess": ProjectHasNoAPIAccessError,
155-
"ProjectInactive": ProjectInactiveError,
156-
"ProjectSuspended": ProjectSuspendedError,
157-
"RequestQuotaReached": RequestQuotaReachedError,
158-
"RequestTimeTooSkewed": RequestTimeTooSkewedError,
159-
"TargetNameExist": TargetNameExistError,
160-
"TargetQuotaReached": TargetQuotaReachedError,
161-
"TargetStatusNotSuccess": TargetStatusNotSuccessError,
162-
"TargetStatusProcessing": TargetStatusProcessingError,
163-
"UnknownTarget": UnknownTargetError,
164-
}[result_code]
165-
166-
raise exception(response=response)
128+
raise VWSError.from_result_code(
129+
result_code=result_code,
130+
response=response,
131+
)
167132

168133
def add_target(
169134
self,

tests/test_vws_exceptions.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
TargetStatusProcessingError,
3838
UnknownTargetError,
3939
)
40+
from vws.response import Response
4041
from vws.vumark_accept import VuMarkAccept
4142

4243

@@ -451,3 +452,24 @@ def test_base_exception(
451452
active_flag=True,
452453
application_metadata=None,
453454
)
455+
456+
457+
def test_vwserror_from_result_code() -> None:
458+
"""``VWSError.from_result_code`` returns the mapped exception."""
459+
response = Response(
460+
text='{"result_code":"UnknownTarget"}',
461+
url="https://example.com/targets/123",
462+
status_code=HTTPStatus.NOT_FOUND,
463+
headers={},
464+
request_body=None,
465+
tell_position=0,
466+
content=b"",
467+
)
468+
469+
exception = VWSError.from_result_code(
470+
result_code="UnknownTarget",
471+
response=response,
472+
)
473+
474+
assert isinstance(exception, UnknownTargetError)
475+
assert exception.response is response

0 commit comments

Comments
 (0)