cuenca-validations 2.1.17.dev4__tar.gz → 2.1.18.dev1__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.17.dev4 → cuenca_validations-2.1.18.dev1}/PKG-INFO +1 -1
  2. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations/types/__init__.py +2 -0
  3. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations/types/enums.py +1 -1
  4. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations/types/identities.py +7 -3
  5. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations/types/requests.py +16 -23
  6. cuenca_validations-2.1.18.dev1/cuenca_validations/version.py +1 -0
  7. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations.egg-info/PKG-INFO +1 -1
  8. cuenca_validations-2.1.18.dev1/tests/test_requests.py +31 -0
  9. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/tests/test_types.py +3 -26
  10. cuenca_validations-2.1.17.dev4/cuenca_validations/version.py +0 -1
  11. cuenca_validations-2.1.17.dev4/tests/test_requests.py +0 -70
  12. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/LICENSE +0 -0
  13. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/README.md +0 -0
  14. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations/__init__.py +0 -0
  15. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations/card_bins.py +0 -0
  16. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations/errors.py +0 -0
  17. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations/py.typed +0 -0
  18. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations/types/card.py +0 -0
  19. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations/types/files.py +0 -0
  20. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations/types/general.py +0 -0
  21. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations/types/helpers.py +0 -0
  22. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations/types/morals.py +0 -0
  23. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations/types/queries.py +0 -0
  24. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations/typing.py +0 -0
  25. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations/validators.py +0 -0
  26. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations.egg-info/SOURCES.txt +0 -0
  27. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations.egg-info/dependency_links.txt +0 -0
  28. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations.egg-info/requires.txt +0 -0
  29. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/cuenca_validations.egg-info/top_level.txt +0 -0
  30. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/setup.cfg +0 -0
  31. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/setup.py +0 -0
  32. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/tests/__init__.py +0 -0
  33. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/tests/test_card.py +0 -0
  34. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/tests/test_errors.py +0 -0
  35. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/tests/test_helpers.py +0 -0
  36. {cuenca_validations-2.1.17.dev4 → cuenca_validations-2.1.18.dev1}/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.17.dev4
3
+ Version: 2.1.18.dev1
4
4
  Summary: Cuenca common validations
5
5
  Home-page: https://github.com/cuenca-mx/cuenca-validations
6
6
  Author: Cuenca
@@ -14,6 +14,7 @@ __all__ = [
14
14
  'BankAccountStatus',
15
15
  'BatchFileMetadata',
16
16
  'Beneficiary',
17
+ 'BeneficiaryRequest',
17
18
  'BillPaymentQuery',
18
19
  'CardErrorType',
19
20
  'CardFundingType',
@@ -221,6 +222,7 @@ from .queries import (
221
222
  from .requests import (
222
223
  ApiKeyUpdateRequest,
223
224
  BankAccountValidationRequest,
225
+ BeneficiaryRequest,
224
226
  CurpValidationRequest,
225
227
  EndpointRequest,
226
228
  EndpointUpdateRequest,
@@ -259,6 +259,7 @@ class KYCValidationSource(str, Enum):
259
259
  class Gender(str, Enum):
260
260
  female = 'female'
261
261
  male = 'male'
262
+ non_binary = 'non_binary'
262
263
 
263
264
 
264
265
  class State(str, Enum):
@@ -588,7 +589,6 @@ class SessionType(str, Enum):
588
589
  account_entries = 'session.account_entries'
589
590
  download_file = 'session.download_file'
590
591
  upload_file = 'session.upload_file'
591
- onboarding_verification = 'session.onboarding_verification'
592
592
 
593
593
 
594
594
  class WebhookObject(str, Enum):
@@ -1,5 +1,5 @@
1
1
  import datetime as dt
2
- from typing import Annotated, Optional
2
+ from typing import Annotated, Optional, Union
3
3
 
4
4
  from pydantic import BaseModel, ConfigDict, Field, SecretStr, StringConstraints
5
5
  from pydantic_extra_types.phone_numbers import PhoneNumber
@@ -89,12 +89,12 @@ class AddressRequest(BaseModel):
89
89
  )
90
90
 
91
91
 
92
- class Beneficiary(BaseModel):
92
+ class BaseBeneficiary(BaseModel):
93
93
  name: str
94
94
  birth_date: dt.date
95
- phone_number: PhoneNumber
96
95
  user_relationship: str
97
96
  percentage: Annotated[int, Field(ge=1, le=100)]
97
+
98
98
  model_config = ConfigDict(
99
99
  json_schema_extra={
100
100
  "example": {
@@ -108,6 +108,10 @@ class Beneficiary(BaseModel):
108
108
  )
109
109
 
110
110
 
111
+ class Beneficiary(BaseBeneficiary):
112
+ phone_number: Union[PhoneNumber, str]
113
+
114
+
111
115
  class VerificationErrors(BaseModel):
112
116
  identifier: str = Field(
113
117
  description='Unique identifier for the step validation'
@@ -73,7 +73,7 @@ from .general import (
73
73
  from .helpers import validate_age_requirement
74
74
  from .identities import (
75
75
  AddressRequest,
76
- Beneficiary,
76
+ BaseBeneficiary,
77
77
  Curp,
78
78
  KYCFile,
79
79
  Password,
@@ -330,7 +330,7 @@ class UserPldRiskLevelRequest(BaseModel):
330
330
  level: float = Field(ge=0.0, le=1.0)
331
331
 
332
332
 
333
- class CurpValidationRequest(BaseModel):
333
+ class CurpValidationRequest(BaseRequest):
334
334
  names: Optional[str] = None
335
335
  first_surname: Optional[str] = None
336
336
  second_surname: Optional[str] = Field(
@@ -439,13 +439,13 @@ class FileCuencaUrl(str):
439
439
  )
440
440
 
441
441
 
442
- class UserTOSAgreementRequest(BaseModel):
442
+ class UserTOSAgreementRequest(BaseRequest):
443
443
  tos_id: str
444
444
  location: Coordinate
445
445
  signature_image_url: Optional[FileCuencaUrl] = None
446
446
 
447
447
 
448
- class UserRequest(BaseModel):
448
+ class UserRequest(BaseRequest):
449
449
  curp: Curp = Field(
450
450
  description=(
451
451
  'Mexican government ID (18 characters). ' 'Must be pre-validated.'
@@ -495,12 +495,16 @@ class UserRequest(BaseModel):
495
495
  return profession
496
496
 
497
497
 
498
- class UserUpdateRequest(BaseModel):
498
+ class BeneficiaryRequest(BaseBeneficiary, BaseRequest):
499
+ phone_number: PhoneNumber
500
+
501
+
502
+ class UserUpdateRequest(BaseRequest):
499
503
  profession: Optional[Profession] = None
500
504
  email_verification_id: Optional[str] = None
501
505
  phone_verification_id: Optional[str] = None
502
506
  address: Optional[AddressRequest] = None
503
- beneficiaries: Optional[list[Beneficiary]] = None
507
+ beneficiaries: Optional[list[BeneficiaryRequest]] = None
504
508
  govt_id: Optional[KYCFile] = None
505
509
  proof_of_address: Optional[KYCFile] = None
506
510
  proof_of_life: Optional[KYCFile] = None
@@ -518,7 +522,7 @@ class UserUpdateRequest(BaseModel):
518
522
  @field_validator('beneficiaries')
519
523
  @classmethod
520
524
  def beneficiary_percentage(
521
- cls, beneficiaries: Optional[list[Beneficiary]] = None
525
+ cls, beneficiaries: Optional[list[BeneficiaryRequest]] = None
522
526
  ):
523
527
  if beneficiaries and sum(b.percentage for b in beneficiaries) != 100:
524
528
  raise ValueError('The total percentage should be 100%')
@@ -547,16 +551,6 @@ class SessionRequest(BaseRequest):
547
551
  type: SessionType
548
552
  success_url: Optional[SerializableAnyUrl] = None
549
553
  failure_url: Optional[SerializableAnyUrl] = None
550
- resource_id: Optional[str] = None
551
-
552
- @model_validator(mode='before')
553
- @classmethod
554
- def validate_metadata(cls, values: dict) -> dict:
555
- type, resource_id = values['type'], values.get('resource_id')
556
- if type == SessionType.onboarding_verification and not resource_id:
557
- raise ValueError('Resource id expected for this session')
558
- return values
559
-
560
554
  model_config = ConfigDict(
561
555
  json_schema_extra={
562
556
  'example': {
@@ -564,7 +558,6 @@ class SessionRequest(BaseRequest):
564
558
  'type': 'session.registration',
565
559
  'success_url': 'http://example_success.com',
566
560
  'failure_url': 'http://example_failure.com',
567
- 'resource_id': 'some_resource_id',
568
561
  }
569
562
  }
570
563
  )
@@ -601,7 +594,7 @@ class FileBatchUploadRequest(BaseModel):
601
594
  user_id: str
602
595
 
603
596
 
604
- class VerificationRequest(BaseModel):
597
+ class VerificationRequest(BaseRequest):
605
598
  type: VerificationType
606
599
  recipient: Union[EmailStr, PhoneNumber] = Field(
607
600
  description='Phone or email to validate'
@@ -625,7 +618,7 @@ class VerificationRequest(BaseModel):
625
618
  )
626
619
 
627
620
 
628
- class VerificationAttemptRequest(BaseModel):
621
+ class VerificationAttemptRequest(BaseRequest):
629
622
  code: Annotated[
630
623
  str,
631
624
  StringConstraints(strict=True, min_length=6, max_length=6),
@@ -666,11 +659,11 @@ class KYCValidationRequest(BaseRequest):
666
659
  force: bool = False
667
660
 
668
661
 
669
- class BankAccountValidationRequest(BaseModel):
662
+ class BankAccountValidationRequest(BaseRequest):
670
663
  account_number: Union[Clabe, PaymentCardNumber]
671
664
 
672
665
 
673
- class UserListsRequest(BaseModel):
666
+ class UserListsRequest(BaseRequest):
674
667
  curp: Optional[Curp] = Field(None, description='Curp to review on lists')
675
668
  rfc: Optional[Rfc] = Field(None, description='Rfc to review on lists')
676
669
  account_number: Optional[Union[Clabe, PaymentCardNumber]] = Field(
@@ -769,5 +762,5 @@ class PartnerUpdateRequest(BaseRequest):
769
762
  shareholders: Optional[list[Shareholder]] = None
770
763
 
771
764
 
772
- class PhoneVerificationAssociationRequest(BaseModel):
765
+ class PhoneVerificationAssociationRequest(BaseRequest):
773
766
  verification_id: str
@@ -0,0 +1 @@
1
+ __version__ = '2.1.18.dev1'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cuenca_validations
3
- Version: 2.1.17.dev4
3
+ Version: 2.1.18.dev1
4
4
  Summary: Cuenca common validations
5
5
  Home-page: https://github.com/cuenca-mx/cuenca-validations
6
6
  Author: Cuenca
@@ -0,0 +1,31 @@
1
+ import pytest
2
+ from pydantic import ValidationError
3
+
4
+ from cuenca_validations.types.requests import UserTOSAgreementRequest
5
+ from cuenca_validations.typing import DictStrAny
6
+
7
+
8
+ @pytest.mark.parametrize('environment', ['stage', 'sandbox', 'api'])
9
+ def test_file_cuenca_url(environment: str) -> None:
10
+ request_data: DictStrAny = dict(
11
+ tos_id='TS67dcae8e74e81bba5a77bf47',
12
+ location=(19.432607, -99.133209),
13
+ signature_image_url=(
14
+ f'https://{environment}.cuenca.com/files/EFQL8_ohvoRp-PkOTYgvQYFA'
15
+ ),
16
+ )
17
+ utos = UserTOSAgreementRequest(**request_data)
18
+ assert utos.signature_image_url is not None
19
+ assert utos.signature_image_url.file_id == 'EFQL8_ohvoRp-PkOTYgvQYFA'
20
+
21
+
22
+ def test_file_cuenca_url_invalid() -> None:
23
+ request_data: DictStrAny = dict(
24
+ tos_id='TS67dcae8e74e81bba5a77bf47',
25
+ location=(19.432607, -99.133209),
26
+ signature_image_url=(
27
+ 'https://cuenca.com/files/EFQL87ohvoRp-PkOTYgvQYFA/invalid'
28
+ ),
29
+ )
30
+ with pytest.raises(ValidationError):
31
+ UserTOSAgreementRequest(**request_data)
@@ -394,7 +394,9 @@ def test_curp_validation_request():
394
394
  assert all(field in error_msg for field in required_fields)
395
395
 
396
396
  req_curp = CurpValidationRequest(**request)
397
- assert req_curp.model_dump() == request
397
+ # exclude_none=False to test that the request equals the original dict,
398
+ # since normally exclude_none defaults to True in BaseRequest.model_dump()
399
+ assert req_curp.model_dump(exclude_none=False) == request
398
400
 
399
401
  request['date_of_birth'] = dt.date(2006, 5, 17)
400
402
 
@@ -435,16 +437,11 @@ def test_user_update_request():
435
437
  percentage=50,
436
438
  ),
437
439
  ],
438
- curp_document_uri='https://sandbox.cuenca.com/files/EF123',
439
440
  profession=Profession.empleado,
440
441
  )
441
442
  update_req = UserUpdateRequest(**request)
442
443
  beneficiaries = [b.model_dump() for b in update_req.beneficiaries]
443
444
  assert beneficiaries == request['beneficiaries']
444
- assert (
445
- update_req.curp_document_uri.unicode_string()
446
- == request['curp_document_uri']
447
- )
448
445
  assert update_req.profession == Profession.empleado
449
446
 
450
447
  request['beneficiaries'] = [
@@ -480,26 +477,6 @@ def test_user_update_request():
480
477
  assert 'The total percentage should be 100%' in str(v)
481
478
  request.pop('beneficiaries')
482
479
 
483
- tos_request = dict(
484
- terms_of_service=dict(
485
- version='2022-01-01',
486
- ip='127.0.0.1',
487
- location='1111,1111',
488
- type='ifpe',
489
- )
490
- )
491
- UserUpdateRequest(**tos_request)
492
-
493
- tos_request = dict(
494
- terms_of_service=dict(
495
- version='2022-01-01',
496
- ip='2001:0db8:0000:0000:0000:ff00:0042:8329',
497
- location='1111,1111',
498
- type='ifpe',
499
- )
500
- )
501
- UserUpdateRequest(**tos_request)
502
-
503
480
  kyc_request = dict(
504
481
  govt_id=dict(
505
482
  type='ine',
@@ -1 +0,0 @@
1
- __version__ = '2.1.17.dev4'
@@ -1,70 +0,0 @@
1
- import pytest
2
- from pydantic import ValidationError
3
-
4
- from cuenca_validations.types.enums import SessionType
5
- from cuenca_validations.types.requests import (
6
- SessionRequest,
7
- UserTOSAgreementRequest,
8
- )
9
- from cuenca_validations.typing import DictStrAny
10
-
11
-
12
- @pytest.mark.parametrize('environment', ['stage', 'sandbox', 'api'])
13
- def test_file_cuenca_url(environment: str) -> None:
14
- request_data: DictStrAny = dict(
15
- tos_id='TS67dcae8e74e81bba5a77bf47',
16
- location=(19.432607, -99.133209),
17
- signature_image_url=(
18
- f'https://{environment}.cuenca.com/files/EFQL8_ohvoRp-PkOTYgvQYFA'
19
- ),
20
- )
21
- utos = UserTOSAgreementRequest(**request_data)
22
- assert utos.signature_image_url is not None
23
- assert utos.signature_image_url.file_id == 'EFQL8_ohvoRp-PkOTYgvQYFA'
24
-
25
-
26
- def test_file_cuenca_url_invalid() -> None:
27
- request_data: DictStrAny = dict(
28
- tos_id='TS67dcae8e74e81bba5a77bf47',
29
- location=(19.432607, -99.133209),
30
- signature_image_url=(
31
- 'https://cuenca.com/files/EFQL87ohvoRp-PkOTYgvQYFA/invalid'
32
- ),
33
- )
34
- with pytest.raises(ValidationError):
35
- UserTOSAgreementRequest(**request_data)
36
-
37
-
38
- def test_session_request_without_metadata():
39
- request_data = {
40
- 'user_id': 'USWqY5cvkISJOxHyEKjAKf8w',
41
- 'type': 'session.curp_validation',
42
- }
43
- request = SessionRequest(**request_data)
44
- assert request.type == SessionType.curp_validation
45
- assert request.user_id == 'USWqY5cvkISJOxHyEKjAKf8w'
46
-
47
-
48
- def test_session_request_with_resource_id():
49
- request_data = {
50
- 'user_id': 'USWqY5cvkISJOxHyEKjAKf8w',
51
- 'type': 'session.onboarding_verification',
52
- 'resource_id': 'some_verification_id',
53
- }
54
- request = SessionRequest(**request_data)
55
- assert request.type == SessionType.onboarding_verification
56
- assert request.user_id == 'USWqY5cvkISJOxHyEKjAKf8w'
57
- assert request.resource_id
58
- assert request.resource_id == 'some_verification_id'
59
-
60
-
61
- def test_metamap_session_request_without_metadata():
62
- request_data = {
63
- 'user_id': 'USWqY5cvkISJOxHyEKjAKf8w',
64
- 'type': 'session.onboarding_verification',
65
- }
66
-
67
- with pytest.raises(ValidationError) as exception:
68
- SessionRequest(**request_data)
69
-
70
- assert 'Resource id expected for this session' in str(exception)