Skip to content

Commit 8149586

Browse files
committed
SDK-1639: Add support for chip data
1 parent 236bc89 commit 8149586

File tree

9 files changed

+186
-6
lines changed

9 files changed

+186
-6
lines changed

examples/doc_scan/app.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@ def create_session():
6666
)
6767
.with_requested_check(RequestedIDDocumentComparisonCheckBuilder().build())
6868
.with_requested_task(
69-
RequestedTextExtractionTaskBuilder().with_manual_check_never().build()
69+
RequestedTextExtractionTaskBuilder()
70+
.with_manual_check_never()
71+
.with_chip_data_desired()
72+
.build()
7073
)
7174
.with_sdk_config(sdk_config)
7275
.with_required_document(build_required_id_document_restriction("PASSPORT"))

examples/doc_scan/templates/success.html

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,26 @@ <h5>Media</h5>
222222
</div>
223223
</div>
224224
{% endif %}
225+
226+
{% if document.document_id_photo is not none %}
227+
<div class="card">
228+
<div class="card-header" id="document-id-photo-{{ doc_num }}">
229+
<h4 class="mb-0">
230+
<button class="btn btn-link" type="button" data-toggle="collapse" data-target="#collapse-document-id-photo-{{ doc_num }}" aria-expanded="true" aria-controls="collapse-document-id-photo-{{ doc_num }}">
231+
Document ID Photo
232+
</button>
233+
</h4>
234+
</div>
235+
<div id="collapse-document-id-photo-{{ doc_num }}" class="collapse" aria-labelledby="document-id-photo-{{ doc_num }}">
236+
<div class="card-body">
237+
{% if document.document_fields.media is not none %}
238+
<img class="card-img-top" src="/media?mediaId={{ document.document_id_photo.media.id }}" />
239+
{% endif %}
240+
</div>
241+
</div>
242+
</div>
243+
{% endif %}
244+
225245
{% if document.text_extraction_tasks|length > 0 %}
226246
<div class="card">
227247
<div class="card-header" id="text-extraction-tasks-{{ doc_num }}">

yoti_python_sdk/doc_scan/constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,6 @@
2626
ALWAYS = "ALWAYS"
2727
FALLBACK = "FALLBACK"
2828
NEVER = "NEVER"
29+
30+
DESIRED = "DESIRED"
31+
IGNORE = "IGNORE"

yoti_python_sdk/doc_scan/session/create/task/text_extraction.py

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77

88

99
class RequestedTextExtractionTaskConfig(YotiSerializable):
10-
def __init__(self, manual_check):
10+
def __init__(self, manual_check, chip_data=None):
1111
"""
1212
:param manual_check: the manual check value
1313
:type manual_check: str
1414
"""
1515
self.__manual_check = manual_check
16+
self.__chip_data = chip_data
1617

1718
@property
1819
def manual_check(self):
@@ -23,8 +24,20 @@ def manual_check(self):
2324
"""
2425
return self.__manual_check
2526

27+
@property
28+
def chip_data(self):
29+
"""
30+
Describes how to use chip data from an ID document if
31+
it is available
32+
33+
:return: the chip data usage
34+
"""
35+
return self.__chip_data
36+
2637
def to_json(self):
27-
return remove_null_values({"manual_check": self.manual_check})
38+
return remove_null_values(
39+
{"manual_check": self.manual_check, "chip_data": self.chip_data}
40+
)
2841

2942

3043
class RequestedTextExtractionTask(RequestedTask):
@@ -55,6 +68,7 @@ class RequestedTextExtractionTaskBuilder(object):
5568

5669
def __init__(self):
5770
self.__manual_check = None
71+
self.__chip_data = None
5872

5973
def with_manual_check_always(self):
6074
"""
@@ -86,6 +100,28 @@ def with_manual_check_never(self):
86100
self.__manual_check = constants.NEVER
87101
return self
88102

103+
def with_chip_data_desired(self):
104+
"""
105+
The TextExtractionTask will use chip data if it is available
106+
107+
:return: the builder
108+
:rtype: RequestedTextExtractionTaskBuilder
109+
"""
110+
self.__chip_data = constants.DESIRED
111+
return self
112+
113+
def with_chip_data_ignore(self):
114+
"""
115+
The TextExtractionTask will ignore chip data
116+
117+
:return: the builder
118+
:rtype: RequestedTextExtractionTaskBuilder
119+
"""
120+
self.__chip_data = constants.IGNORE
121+
return self
122+
89123
def build(self):
90-
config = RequestedTextExtractionTaskConfig(self.__manual_check)
124+
config = RequestedTextExtractionTaskConfig(
125+
self.__manual_check, self.__chip_data
126+
)
91127
return RequestedTextExtractionTask(config)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import unicode_literals
3+
4+
from yoti_python_sdk.doc_scan.session.retrieve.media_response import MediaResponse
5+
6+
7+
class DocumentIdPhotoResponse(object):
8+
"""
9+
Represents the document ID photo response
10+
"""
11+
12+
def __init__(self, data=None):
13+
"""
14+
:param data: the data to parse
15+
:type data: dict or None
16+
"""
17+
if data is None:
18+
data = dict()
19+
20+
if "media" in data.keys():
21+
self.__media = MediaResponse(data["media"])
22+
else:
23+
self.__media = None
24+
25+
@property
26+
def media(self):
27+
"""
28+
The media object for the document ID photo
29+
30+
:return: the media
31+
:rtype: MediaResponse or None
32+
"""
33+
return self.__media

yoti_python_sdk/doc_scan/session/retrieve/id_document_resource_response.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
from yoti_python_sdk.doc_scan.session.retrieve.document_fields_response import (
55
DocumentFieldsResponse,
66
)
7+
from yoti_python_sdk.doc_scan.session.retrieve.document_id_photo_response import (
8+
DocumentIdPhotoResponse,
9+
)
710
from yoti_python_sdk.doc_scan.session.retrieve.page_response import PageResponse
811
from yoti_python_sdk.doc_scan.session.retrieve.resource_response import ResourceResponse
912
from yoti_python_sdk.doc_scan.session.retrieve.task_response import (
@@ -34,6 +37,11 @@ def __init__(self, data=None):
3437
if "document_fields" in data.keys()
3538
else None
3639
)
40+
self.__document_id_photo = (
41+
DocumentIdPhotoResponse(data["document_id_photo"])
42+
if "document_id_photo" in data.keys()
43+
else None
44+
)
3745

3846
@property
3947
def document_type(self):
@@ -75,6 +83,16 @@ def document_fields(self):
7583
"""
7684
return self.__document_fields
7785

86+
@property
87+
def document_id_photo(self):
88+
"""
89+
Returns the associated document ID photo
90+
91+
:return: the document ID photo
92+
:rtype: DocumentIdPhotoResponse
93+
"""
94+
return self.__document_id_photo
95+
7896
@property
7997
def text_extraction_tasks(self):
8098
"""

yoti_python_sdk/tests/doc_scan/session/create/task/test_text_extraction_task.py

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,18 @@
1515

1616

1717
class RequestedTextExtractionTaskTest(unittest.TestCase):
18-
def test_should_build_with_manual_check_always(self):
19-
result = RequestedTextExtractionTaskBuilder().with_manual_check_always().build()
18+
def test_should_build_text_data_extraction_task(self):
19+
result = RequestedTextExtractionTaskBuilder().build()
2020

2121
assert isinstance(result, RequestedTask)
2222
assert isinstance(result, RequestedTextExtractionTask)
2323
assert isinstance(result.config, RequestedTextExtractionTaskConfig)
2424

2525
assert result.type == "ID_DOCUMENT_TEXT_DATA_EXTRACTION"
26+
27+
def test_should_build_with_manual_check_always(self):
28+
result = RequestedTextExtractionTaskBuilder().with_manual_check_always().build()
29+
2630
assert result.config.manual_check == "ALWAYS"
2731

2832
def test_should_build_with_manual_check_fallback(self):
@@ -37,12 +41,46 @@ def test_should_build_with_manual_check_never(self):
3741

3842
assert result.config.manual_check == "NEVER"
3943

44+
def test_should_build_with_chip_data_desired(self):
45+
result = RequestedTextExtractionTaskBuilder().with_chip_data_desired().build()
46+
47+
assert result.config.chip_data == "DESIRED"
48+
49+
def test_should_build_with_chip_data_ignore(self):
50+
result = RequestedTextExtractionTaskBuilder().with_chip_data_ignore().build()
51+
52+
assert result.config.chip_data == "IGNORE"
53+
4054
def test_should_serialize_to_json_without_error(self):
4155
result = RequestedTextExtractionTaskBuilder().with_manual_check_never().build()
4256

4357
s = json.dumps(result, cls=YotiEncoder)
4458
assert s is not None and s != ""
4559

60+
def test_to_json_should_return_correct_properties(self):
61+
result = (
62+
RequestedTextExtractionTaskBuilder()
63+
.with_manual_check_always()
64+
.with_chip_data_desired()
65+
.build()
66+
)
67+
68+
json = result.to_json()
69+
assert json is not None
70+
71+
json_config = json.get("config").to_json()
72+
assert json_config.get("manual_check") == "ALWAYS"
73+
assert json_config.get("chip_data") == "DESIRED"
74+
75+
def test_to_json_should_not_include_null_config_values(self):
76+
result = RequestedTextExtractionTaskBuilder().build()
77+
78+
json = result.to_json()
79+
assert json is not None
80+
81+
json_config = json.get("config").to_json()
82+
assert json_config == {}
83+
4684

4785
if __name__ == "__main__":
4886
unittest.main()
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import unittest
2+
3+
from yoti_python_sdk.doc_scan.session.retrieve.document_id_photo_response import (
4+
DocumentIdPhotoResponse,
5+
)
6+
from yoti_python_sdk.doc_scan.session.retrieve.media_response import MediaResponse
7+
8+
9+
class DocumentIdPhotoResponseTest(unittest.TestCase):
10+
def test_should_parse_correctly(self):
11+
data = {"media": {}}
12+
13+
result = DocumentIdPhotoResponse(data)
14+
assert isinstance(result.media, MediaResponse)
15+
16+
def test_should_not_throw_exception_for_none(self):
17+
result = DocumentIdPhotoResponse(None)
18+
assert result.media is None
19+
20+
21+
if __name__ == "__main__":
22+
unittest.main()

yoti_python_sdk/tests/doc_scan/session/retrieve/test_id_document_resource_response.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
from yoti_python_sdk.doc_scan.session.retrieve.document_fields_response import (
44
DocumentFieldsResponse,
55
)
6+
from yoti_python_sdk.doc_scan.session.retrieve.document_id_photo_response import (
7+
DocumentIdPhotoResponse,
8+
)
69
from yoti_python_sdk.doc_scan.session.retrieve.id_document_resource_response import (
710
IdDocumentResourceResponse,
811
)
@@ -22,6 +25,7 @@ class IdDocumentResourceResponseTest(unittest.TestCase):
2225
]
2326
SOME_PAGES = [{"first": "page"}, {"second": "page"}]
2427
SOME_DOCUMENT_FIELDS = {"media": {}}
28+
SOME_DOCUMENT_ID_PHOTO = {"media": {}}
2529

2630
def test_should_parse_correctly(self):
2731
data = {
@@ -31,6 +35,7 @@ def test_should_parse_correctly(self):
3135
"tasks": self.SOME_TASKS,
3236
"pages": self.SOME_PAGES,
3337
"document_fields": self.SOME_DOCUMENT_FIELDS,
38+
"document_id_photo": self.SOME_DOCUMENT_ID_PHOTO,
3439
}
3540

3641
result = IdDocumentResourceResponse(data)
@@ -41,6 +46,7 @@ def test_should_parse_correctly(self):
4146
assert len(result.tasks) == 2
4247
assert len(result.pages) == 2
4348
assert isinstance(result.document_fields, DocumentFieldsResponse)
49+
assert isinstance(result.document_id_photo, DocumentIdPhotoResponse)
4450

4551
def test_should_parse_when_none(self):
4652
result = IdDocumentResourceResponse(None)
@@ -51,6 +57,7 @@ def test_should_parse_when_none(self):
5157
assert len(result.tasks) == 0
5258
assert len(result.pages) == 0
5359
assert result.document_fields is None
60+
assert result.document_id_photo is None
5461

5562
def test_should_parse_tasks_with_type(self):
5663
data = {

0 commit comments

Comments
 (0)