cuenca-validations 2.1.13__tar.gz → 2.1.14__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/PKG-INFO +1 -1
- cuenca_validations-2.1.14/cuenca_validations/types/helpers.py +44 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/requests.py +16 -19
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/validators.py +0 -9
- cuenca_validations-2.1.14/cuenca_validations/version.py +1 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations.egg-info/PKG-INFO +1 -1
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/tests/test_requests.py +2 -2
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/tests/test_types.py +6 -0
- cuenca_validations-2.1.13/cuenca_validations/types/helpers.py +0 -22
- cuenca_validations-2.1.13/cuenca_validations/version.py +0 -1
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/LICENSE +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/README.md +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/__init__.py +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/card_bins.py +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/errors.py +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/py.typed +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/__init__.py +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/card.py +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/enums.py +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/files.py +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/general.py +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/identities.py +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/morals.py +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/queries.py +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/typing.py +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations.egg-info/SOURCES.txt +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations.egg-info/dependency_links.txt +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations.egg-info/requires.txt +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations.egg-info/top_level.txt +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/setup.cfg +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/setup.py +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/tests/__init__.py +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/tests/test_card.py +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/tests/test_errors.py +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/tests/test_helpers.py +0 -0
- {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/tests/test_statement.py +0 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import datetime as dt
|
|
2
|
+
import uuid
|
|
3
|
+
from base64 import urlsafe_b64encode
|
|
4
|
+
from typing import Callable, Optional, Union
|
|
5
|
+
|
|
6
|
+
from dateutil.relativedelta import relativedelta
|
|
7
|
+
from pydantic.fields import FieldInfo
|
|
8
|
+
|
|
9
|
+
from .general import LogConfig
|
|
10
|
+
from .identities import Curp
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def uuid_field(prefix: str = '') -> Callable[[], str]:
|
|
14
|
+
def base64_uuid_func() -> str:
|
|
15
|
+
return prefix + urlsafe_b64encode(uuid.uuid4().bytes).decode()[:-2]
|
|
16
|
+
|
|
17
|
+
return base64_uuid_func
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def get_log_config(field: FieldInfo) -> Optional[LogConfig]:
|
|
21
|
+
"""Helper function to find LogConfig in field metadata"""
|
|
22
|
+
try:
|
|
23
|
+
return next(m for m in field.metadata if isinstance(m, LogConfig))
|
|
24
|
+
except StopIteration:
|
|
25
|
+
return None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_birth_date_from_curp(curp: Curp) -> dt.date:
|
|
29
|
+
curp_date = curp[4:10] # YYMMDD
|
|
30
|
+
yy = int(curp_date[:2])
|
|
31
|
+
current_yy = dt.date.today().year % 100
|
|
32
|
+
century = '19' if yy > current_yy else '20'
|
|
33
|
+
birth_date = dt.datetime.strptime(century + curp_date, '%Y%m%d').date()
|
|
34
|
+
return birth_date
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def validate_age_requirement(birth_date: Union[dt.date, Curp]) -> dt.date:
|
|
38
|
+
if isinstance(birth_date, str):
|
|
39
|
+
birth_date = get_birth_date_from_curp(birth_date)
|
|
40
|
+
|
|
41
|
+
current_date = dt.date.today()
|
|
42
|
+
if relativedelta(current_date, birth_date).years < 18:
|
|
43
|
+
raise ValueError('User does not meet age requirement.')
|
|
44
|
+
return birth_date
|
{cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/requests.py
RENAMED
|
@@ -50,7 +50,6 @@ from ..types.enums import (
|
|
|
50
50
|
WebhookObject,
|
|
51
51
|
)
|
|
52
52
|
from ..typing import DictStrAny
|
|
53
|
-
from ..validators import validate_age_requirement
|
|
54
53
|
from .card import (
|
|
55
54
|
Cvv,
|
|
56
55
|
ExpMonth,
|
|
@@ -66,6 +65,7 @@ from .general import (
|
|
|
66
65
|
SerializableIPvAnyAddress,
|
|
67
66
|
StrictPositiveInt,
|
|
68
67
|
)
|
|
68
|
+
from .helpers import validate_age_requirement
|
|
69
69
|
from .identities import (
|
|
70
70
|
AddressRequest,
|
|
71
71
|
Beneficiary,
|
|
@@ -86,7 +86,7 @@ from .morals import (
|
|
|
86
86
|
)
|
|
87
87
|
|
|
88
88
|
CUENCA_FILE_URL = (
|
|
89
|
-
r'^https:\/\/(?:stage|sandbox|api)\.cuenca\.com\/files\/([a-zA-Z0-9\-]+)$'
|
|
89
|
+
r'^https:\/\/(?:stage|sandbox|api)\.cuenca\.com\/files\/([a-zA-Z0-9\-_]+)$'
|
|
90
90
|
)
|
|
91
91
|
|
|
92
92
|
|
|
@@ -329,14 +329,14 @@ class CurpValidationRequest(BaseModel):
|
|
|
329
329
|
names: Optional[str] = None
|
|
330
330
|
first_surname: Optional[str] = None
|
|
331
331
|
second_surname: Optional[str] = Field(
|
|
332
|
-
None, description='Not necessary for foreigners'
|
|
332
|
+
default=None, description='Not necessary for foreigners'
|
|
333
333
|
)
|
|
334
334
|
date_of_birth: Optional[dt.date] = None
|
|
335
335
|
state_of_birth: Optional[State] = Field(
|
|
336
|
-
None, description='In format ISO 3166 Alpha-2'
|
|
336
|
+
default=None, description='In format ISO 3166 Alpha-2'
|
|
337
337
|
)
|
|
338
338
|
country_of_birth: Optional[Country] = Field(
|
|
339
|
-
None, description='In format ISO 3166 Alpha-2'
|
|
339
|
+
default=None, description='In format ISO 3166 Alpha-2'
|
|
340
340
|
)
|
|
341
341
|
gender: Optional[Gender] = None
|
|
342
342
|
manual_curp: Optional[Curp] = Field(
|
|
@@ -375,6 +375,15 @@ class CurpValidationRequest(BaseModel):
|
|
|
375
375
|
raise
|
|
376
376
|
return date_of_birth
|
|
377
377
|
|
|
378
|
+
@field_validator('manual_curp')
|
|
379
|
+
@classmethod
|
|
380
|
+
def validate_manual_curp_birth_date(
|
|
381
|
+
cls, manual_curp: Optional[Curp]
|
|
382
|
+
) -> Optional[Curp]:
|
|
383
|
+
if manual_curp:
|
|
384
|
+
validate_age_requirement(manual_curp)
|
|
385
|
+
return manual_curp
|
|
386
|
+
|
|
378
387
|
@model_validator(mode="before")
|
|
379
388
|
@classmethod
|
|
380
389
|
def validate_state_of_birth(cls, values: DictStrAny) -> DictStrAny:
|
|
@@ -467,24 +476,12 @@ class UserRequest(BaseModel):
|
|
|
467
476
|
@classmethod
|
|
468
477
|
def validate_birth_date(cls, curp: Optional[Curp]) -> Optional[Curp]:
|
|
469
478
|
if curp:
|
|
470
|
-
|
|
471
|
-
curp_date = curp[4:10]
|
|
472
|
-
century = (
|
|
473
|
-
'19'
|
|
474
|
-
if int(curp_date[:2]) > int(str(current_date.year)[:2])
|
|
475
|
-
else '20'
|
|
476
|
-
)
|
|
477
|
-
birth_date = dt.datetime.strptime(century + curp_date, '%Y%m%d')
|
|
478
|
-
try:
|
|
479
|
-
validate_age_requirement(birth_date)
|
|
480
|
-
except ValueError:
|
|
481
|
-
raise
|
|
479
|
+
validate_age_requirement(curp)
|
|
482
480
|
return curp
|
|
483
481
|
|
|
484
482
|
|
|
485
483
|
class UserUpdateRequest(BaseModel):
|
|
486
484
|
profession: Optional[Profession] = None
|
|
487
|
-
verification_id: Optional[str] = None
|
|
488
485
|
email_verification_id: Optional[str] = None
|
|
489
486
|
phone_verification_id: Optional[str] = None
|
|
490
487
|
address: Optional[AddressRequest] = None
|
|
@@ -492,9 +489,9 @@ class UserUpdateRequest(BaseModel):
|
|
|
492
489
|
govt_id: Optional[KYCFile] = None
|
|
493
490
|
proof_of_address: Optional[KYCFile] = None
|
|
494
491
|
proof_of_life: Optional[KYCFile] = None
|
|
495
|
-
signature: Optional[KYCFile] = None
|
|
496
492
|
curp_document_uri: Optional[SerializableHttpUrl] = None
|
|
497
493
|
fiscal_regime_code: Optional[SATRegimeCode] = None
|
|
494
|
+
pronouns: Optional[str] = None
|
|
498
495
|
|
|
499
496
|
@field_validator('beneficiaries')
|
|
500
497
|
@classmethod
|
|
@@ -3,8 +3,6 @@ import datetime as dt
|
|
|
3
3
|
from enum import Enum
|
|
4
4
|
from typing import Any, Callable, Optional, Union
|
|
5
5
|
|
|
6
|
-
from dateutil.relativedelta import relativedelta
|
|
7
|
-
|
|
8
6
|
|
|
9
7
|
def sanitize_dict(d: dict) -> dict:
|
|
10
8
|
for k, v in d.items():
|
|
@@ -42,10 +40,3 @@ def sanitize_item(
|
|
|
42
40
|
else:
|
|
43
41
|
rv = item
|
|
44
42
|
return rv
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def validate_age_requirement(birth_date: dt.date) -> dt.date:
|
|
48
|
-
current_date = dt.date.today()
|
|
49
|
-
if relativedelta(current_date, birth_date).years < 18:
|
|
50
|
-
raise ValueError('User does not meet age requirement.')
|
|
51
|
-
return birth_date
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '2.1.14'
|
|
@@ -11,12 +11,12 @@ def test_file_cuenca_url(environment: str) -> None:
|
|
|
11
11
|
tos_id='TS67dcae8e74e81bba5a77bf47',
|
|
12
12
|
location=(19.432607, -99.133209),
|
|
13
13
|
signature_image_url=(
|
|
14
|
-
f'https://{environment}.cuenca.com/files/
|
|
14
|
+
f'https://{environment}.cuenca.com/files/EFQL8_ohvoRp-PkOTYgvQYFA'
|
|
15
15
|
),
|
|
16
16
|
)
|
|
17
17
|
utos = UserTOSAgreementRequest(**request_data)
|
|
18
18
|
assert utos.signature_image_url is not None
|
|
19
|
-
assert utos.signature_image_url.file_id == '
|
|
19
|
+
assert utos.signature_image_url.file_id == 'EFQL8_ohvoRp-PkOTYgvQYFA'
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
def test_file_cuenca_url_invalid() -> None:
|
|
@@ -385,6 +385,12 @@ def test_curp_validation_request():
|
|
|
385
385
|
assert 'state_of_birth required' in str(v)
|
|
386
386
|
|
|
387
387
|
|
|
388
|
+
def test_curp_validation_request_underage() -> None:
|
|
389
|
+
with pytest.raises(ValueError) as v:
|
|
390
|
+
CurpValidationRequest(manual_curp='ABCD240614HDFSRN03')
|
|
391
|
+
assert 'User does not meet age requirement.' in str(v)
|
|
392
|
+
|
|
393
|
+
|
|
388
394
|
def test_user_update_request():
|
|
389
395
|
request = dict(
|
|
390
396
|
beneficiaries=[
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import uuid
|
|
2
|
-
from base64 import urlsafe_b64encode
|
|
3
|
-
from typing import Callable, Optional
|
|
4
|
-
|
|
5
|
-
from pydantic.fields import FieldInfo
|
|
6
|
-
|
|
7
|
-
from .general import LogConfig
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def uuid_field(prefix: str = '') -> Callable[[], str]:
|
|
11
|
-
def base64_uuid_func() -> str:
|
|
12
|
-
return prefix + urlsafe_b64encode(uuid.uuid4().bytes).decode()[:-2]
|
|
13
|
-
|
|
14
|
-
return base64_uuid_func
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def get_log_config(field: FieldInfo) -> Optional[LogConfig]:
|
|
18
|
-
"""Helper function to find LogConfig in field metadata"""
|
|
19
|
-
try:
|
|
20
|
-
return next(m for m in field.metadata if isinstance(m, LogConfig))
|
|
21
|
-
except StopIteration:
|
|
22
|
-
return None
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '2.1.13'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/identities.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations.egg-info/requires.txt
RENAMED
|
File without changes
|
{cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|