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.
Files changed (36) hide show
  1. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/PKG-INFO +1 -1
  2. cuenca_validations-2.1.14/cuenca_validations/types/helpers.py +44 -0
  3. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/requests.py +16 -19
  4. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/validators.py +0 -9
  5. cuenca_validations-2.1.14/cuenca_validations/version.py +1 -0
  6. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations.egg-info/PKG-INFO +1 -1
  7. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/tests/test_requests.py +2 -2
  8. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/tests/test_types.py +6 -0
  9. cuenca_validations-2.1.13/cuenca_validations/types/helpers.py +0 -22
  10. cuenca_validations-2.1.13/cuenca_validations/version.py +0 -1
  11. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/LICENSE +0 -0
  12. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/README.md +0 -0
  13. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/__init__.py +0 -0
  14. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/card_bins.py +0 -0
  15. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/errors.py +0 -0
  16. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/py.typed +0 -0
  17. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/__init__.py +0 -0
  18. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/card.py +0 -0
  19. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/enums.py +0 -0
  20. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/files.py +0 -0
  21. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/general.py +0 -0
  22. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/identities.py +0 -0
  23. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/morals.py +0 -0
  24. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/types/queries.py +0 -0
  25. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations/typing.py +0 -0
  26. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations.egg-info/SOURCES.txt +0 -0
  27. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations.egg-info/dependency_links.txt +0 -0
  28. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations.egg-info/requires.txt +0 -0
  29. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/cuenca_validations.egg-info/top_level.txt +0 -0
  30. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/setup.cfg +0 -0
  31. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/setup.py +0 -0
  32. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/tests/__init__.py +0 -0
  33. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/tests/test_card.py +0 -0
  34. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/tests/test_errors.py +0 -0
  35. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/tests/test_helpers.py +0 -0
  36. {cuenca_validations-2.1.13 → cuenca_validations-2.1.14}/tests/test_statement.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cuenca_validations
3
- Version: 2.1.13
3
+ Version: 2.1.14
4
4
  Summary: Cuenca common validations
5
5
  Home-page: https://github.com/cuenca-mx/cuenca-validations
6
6
  Author: Cuenca
@@ -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
@@ -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
- current_date = dt.datetime.utcnow()
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'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cuenca_validations
3
- Version: 2.1.13
3
+ Version: 2.1.14
4
4
  Summary: Cuenca common validations
5
5
  Home-page: https://github.com/cuenca-mx/cuenca-validations
6
6
  Author: Cuenca
@@ -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/EFQL87ohvoRp-PkOTYgvQYFA'
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 == 'EFQL87ohvoRp-PkOTYgvQYFA'
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'