Skip to content

Commit 4e342ab

Browse files
committed
SDK-1582: Include response error in exception message
1 parent 5e8ca74 commit 4e342ab

File tree

4 files changed

+129
-2
lines changed

4 files changed

+129
-2
lines changed

yoti_python_sdk/doc_scan/exception/doc_scan_exception.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import json
2+
3+
14
class DocScanException(Exception):
25
"""
36
Exception thrown by the Yoti Doc Scan client
@@ -13,7 +16,11 @@ def __init__(self, message, response):
1316
"""
1417
Exception.__init__(self)
1518

16-
self.__message = message
19+
response_message = self.__format_response_message(response)
20+
21+
self.__message = message + (
22+
" - " + response_message if response_message else ""
23+
)
1724
self.__response = response
1825

1926
@property
@@ -56,5 +63,32 @@ def content(self):
5663
"""
5764
return self.__response.content
5865

66+
def __format_response_message(self, response):
67+
"""
68+
Return the formatted response message
69+
70+
:return: the formatted message
71+
:rtype: string or None
72+
"""
73+
if response.headers.get("Content-Type") != "application/json":
74+
return None
75+
76+
parsed = json.loads(response.text)
77+
78+
if not parsed.get("code") or not parsed.get("message"):
79+
return None
80+
81+
code_message = parsed.get("code") + " - " + parsed.get("message")
82+
83+
errors = []
84+
for error in parsed.get("errors", []):
85+
if error.get("property") and error.get("message"):
86+
errors.append(error.get("property") + ' "' + error.get("message") + '"')
87+
88+
if len(errors) > 0:
89+
return code_message + ": " + ", ".join(errors)
90+
91+
return code_message
92+
5993
def __str__(self):
6094
return self.__message

yoti_python_sdk/tests/doc_scan/exception/__init__.py

Whitespace-only changes.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import json
2+
3+
from yoti_python_sdk.doc_scan.exception import DocScanException
4+
from yoti_python_sdk.tests.mocks import MockResponse
5+
6+
7+
def test_return_message():
8+
response = MockResponse(status_code=400, text="some response")
9+
exception = DocScanException("some error", response)
10+
11+
assert exception.message == "some error"
12+
13+
14+
def test_return_only_message_when_html_response():
15+
response = MockResponse(
16+
status_code=400,
17+
text="<html>some html</html>",
18+
headers={"Content-Type": "text/html"},
19+
)
20+
exception = DocScanException("some error", response)
21+
22+
assert exception.message == "some error"
23+
24+
25+
def test_return_only_message_when_json_response_has_no_message_property():
26+
response = MockResponse(
27+
status_code=400,
28+
text=json.dumps({}),
29+
headers={"Content-Type": "application/json"},
30+
)
31+
exception = DocScanException("some error", response)
32+
33+
assert exception.message == "some error"
34+
35+
36+
def test_return_formatted_response_code_and_message():
37+
response = MockResponse(
38+
status_code=400,
39+
text=json.dumps({"code": "SOME_CODE", "message": "some message"}),
40+
headers={"Content-Type": "application/json"},
41+
)
42+
exception = DocScanException("some error", response)
43+
44+
assert exception.message == "some error - SOME_CODE - some message"
45+
46+
47+
def test_return_formatted_response_code_message_and_errors():
48+
response = MockResponse(
49+
status_code=400,
50+
text=json.dumps(
51+
{
52+
"code": "SOME_CODE",
53+
"message": "some message",
54+
"errors": [
55+
{"property": "some.property", "message": "some message"},
56+
{
57+
"property": "some.other.property",
58+
"message": "some other message",
59+
},
60+
],
61+
}
62+
),
63+
headers={"Content-Type": "application/json"},
64+
)
65+
exception = DocScanException("some error", response)
66+
67+
assert (
68+
exception.message
69+
== 'some error - SOME_CODE - some message: some.property "some message", some.other.property "some other message"'
70+
)
71+
72+
73+
def test_excludes_errors_without_property_or_message():
74+
response = MockResponse(
75+
status_code=400,
76+
text=json.dumps(
77+
{
78+
"code": "SOME_CODE",
79+
"message": "some message",
80+
"errors": [
81+
{"message": "some message"},
82+
{"property": "some.other.property"},
83+
],
84+
}
85+
),
86+
headers={"Content-Type": "application/json"},
87+
)
88+
exception = DocScanException("some error", response)
89+
90+
assert exception.message == "some error - SOME_CODE - some message"

yoti_python_sdk/tests/mocks.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import base64
22
from uuid import UUID
3+
from requests.structures import CaseInsensitiveDict
34

45
from yoti_python_sdk.http import RequestHandler
56
from yoti_python_sdk.http import SignedRequest
@@ -11,7 +12,9 @@ def __init__(self, status_code, text, headers=None, content=None):
1112
if headers is None:
1213
headers = dict()
1314

14-
super(MockResponse, self).__init__(status_code, text, headers, content)
15+
super(MockResponse, self).__init__(
16+
status_code, text, CaseInsensitiveDict(headers), content
17+
)
1518

1619

1720
class MockRequestHandler(RequestHandler):

0 commit comments

Comments
 (0)