Skip to content

Commit 20c7c02

Browse files
Merge pull request #321 from getyoti/feature/watchlist
SDK-1901: Adding WATCHLIST_SCREENING check
2 parents 9af34b3 + d408479 commit 20c7c02

File tree

8 files changed

+229
-4
lines changed

8 files changed

+229
-4
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,4 @@ examples/yoti_example_django/*.pem
105105
examples/yoti_example_flask/*.pem
106106

107107
.scannerwork
108-
.venv/
108+
.venv/

yoti_python_sdk/doc_scan/constants.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,5 @@
3636
IGNORE = "IGNORE"
3737

3838
PROOF_OF_ADDRESS = "PROOF_OF_ADDRESS"
39+
40+
WATCHLIST_SCREENING_CHECK_TYPE = "WATCHLIST_SCREENING"

yoti_python_sdk/doc_scan/session/create/check/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22
from .document_comparison import RequestedIDDocumentComparisonCheckBuilder
33
from .face_match import RequestedFaceMatchCheckBuilder
44
from .liveness import RequestedLivenessCheckBuilder
5+
from .watchlist_screen import WatchlistScreeningCheckBuilder
6+
57

68
__all__ = [
79
"RequestedDocumentAuthenticityCheckBuilder",
810
"RequestedIDDocumentComparisonCheckBuilder",
911
"RequestedFaceMatchCheckBuilder",
1012
"RequestedLivenessCheckBuilder",
13+
"WatchlistScreeningCheckBuilder",
1114
]
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import unicode_literals
3+
4+
from yoti_python_sdk.doc_scan import constants
5+
from yoti_python_sdk.utils import YotiSerializable, remove_null_values
6+
from .requested_check import RequestedCheck
7+
8+
9+
class WatchlistScreeningCheckConfig(YotiSerializable):
10+
"""
11+
The configuration applied when creating a Watchlist screening check.
12+
"""
13+
14+
def __init__(self, manual_check, categories):
15+
"""
16+
:param manual_check: the watchlist screening check manual_check eg. "NEVER"
17+
:type type: str
18+
:param categories: list of categories for watchlist screening check config
19+
:type max_retries: list
20+
"""
21+
self.__categories = categories
22+
self.__manual_check = manual_check
23+
24+
@property
25+
def manual_check(self):
26+
"""
27+
Watchlist screening check manual check value
28+
29+
:return: str
30+
"""
31+
return self.__manual_check
32+
33+
@property
34+
def categories(self):
35+
"""
36+
Watchlist screening check categories
37+
38+
:return: list
39+
"""
40+
return self.__categories
41+
42+
def to_json(self):
43+
return remove_null_values(
44+
{"manual_check": self.manual_check, "categories": self.__categories}
45+
)
46+
47+
48+
class WatchlistScreeningCheck(RequestedCheck):
49+
"""
50+
Requests creation of a Watchlist screening check
51+
"""
52+
53+
def __init__(self, config):
54+
"""
55+
:param config: the Watchlist screening check configuration
56+
:type config: WatchlistScreeningCheckConfig
57+
"""
58+
self.__config = config
59+
60+
@property
61+
def type(self):
62+
return constants.WATCHLIST_SCREENING_CHECK_TYPE
63+
64+
@property
65+
def config(self):
66+
return self.__config
67+
68+
69+
class WatchlistScreeningCheckBuilder(object):
70+
"""
71+
Builder to assist creation of :class:`WatchlistScreeningCheck`
72+
"""
73+
74+
def __init__(self):
75+
self.__categories = None
76+
self.__manual_check = None
77+
78+
def with_categories(self, categories):
79+
"""
80+
Sets the WatchListScreeningCheck categories
81+
82+
:return: the builder
83+
:rtype: WatchlistScreeningCheckBuilder
84+
"""
85+
self.__categories = categories
86+
87+
return self
88+
89+
def with_manual_check(self, manual_check):
90+
"""
91+
Sets the WatchListScreeningCheck manual_check
92+
93+
:param liveness_type: the manual_check
94+
:type liveness_type: str
95+
:return: the builder
96+
:rtype: WatchlistScreeningCheckBuilder
97+
"""
98+
self.__manual_check = manual_check
99+
100+
return self
101+
102+
def build(self):
103+
config = WatchlistScreeningCheckConfig(self.__manual_check, self.__categories or [])
104+
return WatchlistScreeningCheck(config)

yoti_python_sdk/doc_scan/session/retrieve/check_response.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,11 @@ class SupplementaryDocumentTextDataCheckResponse(CheckResponse):
184184
"""
185185

186186
pass
187+
188+
189+
class WatchlistScreeningCheckResponse(CheckResponse):
190+
"""
191+
Represents a watchlist screening check for a given session
192+
"""
193+
194+
pass

yoti_python_sdk/doc_scan/session/retrieve/get_session_result.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
LivenessCheckResponse,
1717
TextDataCheckResponse,
1818
SupplementaryDocumentTextDataCheckResponse,
19+
WatchlistScreeningCheckResponse,
1920
)
2021
from .resource_container import ResourceContainer
2122

@@ -80,6 +81,7 @@ def __parse_check(check):
8081
constants.ID_DOCUMENT_FACE_MATCH: FaceMatchCheckResponse,
8182
constants.ID_DOCUMENT_TEXT_DATA_CHECK: TextDataCheckResponse,
8283
constants.LIVENESS: LivenessCheckResponse,
84+
constants.WATCHLIST_SCREENING_CHECK_TYPE: WatchlistScreeningCheckResponse,
8385
constants.ID_DOCUMENT_COMPARISON: IDDocumentComparisonCheckResponse,
8486
constants.SUPPLEMENTARY_DOCUMENT_TEXT_DATA_CHECK: SupplementaryDocumentTextDataCheckResponse,
8587
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import json
2+
import unittest
3+
4+
from yoti_python_sdk.doc_scan import constants
5+
from yoti_python_sdk.doc_scan.session.create.check import (
6+
WatchlistScreeningCheckBuilder,
7+
)
8+
from yoti_python_sdk.doc_scan.session.create.check.requested_check import RequestedCheck
9+
from yoti_python_sdk.doc_scan.session.create.check.watchlist_screen import (
10+
WatchlistScreeningCheck,
11+
WatchlistScreeningCheckConfig,
12+
)
13+
from yoti_python_sdk.utils import YotiEncoder
14+
from yoti_python_sdk.doc_scan.constants import WATCHLIST_SCREENING_CHECK_TYPE
15+
16+
17+
class WatchlistScreeningCheckTest(unittest.TestCase):
18+
def test_should_build_correctly_with_manual_check(self):
19+
dummy_manual_check = "DUMMY_VALUE"
20+
21+
result = (
22+
WatchlistScreeningCheckBuilder()
23+
.with_manual_check(dummy_manual_check)
24+
.build()
25+
)
26+
27+
assert isinstance(result, RequestedCheck)
28+
assert isinstance(result, WatchlistScreeningCheck)
29+
30+
assert result.type == constants.WATCHLIST_SCREENING_CHECK_TYPE
31+
assert result.config.manual_check == dummy_manual_check
32+
assert result.config.categories == []
33+
34+
def test_should_build_corretly_with_categories(self):
35+
dummy_categories = ["FIRST", "SECOND"]
36+
37+
result = (
38+
WatchlistScreeningCheckBuilder()
39+
.with_categories(dummy_categories)
40+
.build()
41+
)
42+
43+
assert isinstance(result, RequestedCheck)
44+
assert isinstance(result, WatchlistScreeningCheck)
45+
46+
assert result.type == constants.WATCHLIST_SCREENING_CHECK_TYPE
47+
assert result.config.categories == dummy_categories
48+
assert result.config.manual_check is None
49+
50+
def test_should_build_correctly_with_manual_check_and_categories(self):
51+
dummy_manual_check = "DUMMY_VALUE"
52+
dummy_categories = ["FIRST", "SECOND"]
53+
54+
result = (
55+
WatchlistScreeningCheckBuilder()
56+
.with_manual_check(dummy_manual_check)
57+
.with_categories(dummy_categories)
58+
.build()
59+
)
60+
61+
assert isinstance(result, RequestedCheck)
62+
assert isinstance(result, WatchlistScreeningCheck)
63+
64+
assert result.type == constants.WATCHLIST_SCREENING_CHECK_TYPE
65+
assert result.config.manual_check == dummy_manual_check
66+
assert result.config.categories == dummy_categories
67+
68+
def test_should_serialize_to_json_without_error(self):
69+
another_dummy_manual_check = "DUMMY_VALUE"
70+
another_dummy_categories = ["FIRST", "SECOND"]
71+
72+
result = (
73+
WatchlistScreeningCheckBuilder()
74+
.with_manual_check(another_dummy_manual_check)
75+
.with_categories(another_dummy_categories)
76+
.build()
77+
)
78+
79+
s = json.dumps(result, cls=YotiEncoder)
80+
assert s is not None and s != ""
81+
82+
result = (
83+
WatchlistScreeningCheckBuilder()
84+
.with_categories(another_dummy_categories)
85+
.build()
86+
)
87+
88+
s = json.dumps(result, cls=YotiEncoder)
89+
assert s is not None and s != ""
90+
91+
s = json.loads(s)
92+
assert s.get("type") == WATCHLIST_SCREENING_CHECK_TYPE
93+
assert s.get("config") == {"categories": another_dummy_categories}
94+
95+
result = (
96+
WatchlistScreeningCheckBuilder()
97+
.with_manual_check(another_dummy_manual_check)
98+
.build()
99+
)
100+
101+
s = json.dumps(result, cls=YotiEncoder)
102+
assert s is not None and s != ""
103+
104+
s = json.loads(s)
105+
assert s.get("type") == WATCHLIST_SCREENING_CHECK_TYPE
106+
assert s.get("config") == {"manual_check": "DUMMY_VALUE", "categories": []}

yoti_python_sdk/tests/test_anchor.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import pytz
44
import time
55
from datetime import datetime
6+
from datetime import timedelta
67

78
import yoti_python_sdk
89
from yoti_python_sdk import config
@@ -118,11 +119,10 @@ def test_processing_unknown_anchor_data():
118119
(anchor.value, anchor.anchor_type, anchor.sub_type) for anchor in anchors
119120
]
120121

121-
expected_timestamp = datetime(2019, 3, 5, 10, 45, 11, 840037).replace(tzinfo=None)
122-
actual_timestamp = anchors[0].signed_timestamp.astimezone(pytz.utc).replace(tzinfo=None)
122+
expected_timestamp = datetime(2019, 3, 5, 10, 45, 11, 840037, tzinfo=pytz.utc)
123+
actual_timestamp = anchors[0].signed_timestamp.astimezone(pytz.utc)
123124

124125
assert expected_timestamp == actual_timestamp
125-
126126
assert "document-registration-server" in [
127127
a.value for a in anchors[0].origin_server_certs.issuer
128128
]

0 commit comments

Comments
 (0)