cuenca 1.0.3.dev0__py3-none-any.whl → 2.0.0.dev1__py3-none-any.whl

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 (48) hide show
  1. cuenca/__init__.py +2 -0
  2. cuenca/resources/__init__.py +2 -0
  3. cuenca/resources/api_keys.py +11 -9
  4. cuenca/resources/arpc.py +6 -5
  5. cuenca/resources/balance_entries.py +2 -4
  6. cuenca/resources/base.py +48 -38
  7. cuenca/resources/card_activations.py +4 -2
  8. cuenca/resources/card_transactions.py +1 -1
  9. cuenca/resources/card_validations.py +7 -7
  10. cuenca/resources/cards.py +7 -6
  11. cuenca/resources/clabes.py +2 -2
  12. cuenca/resources/curp_validations.py +46 -42
  13. cuenca/resources/deposits.py +1 -1
  14. cuenca/resources/endpoints.py +25 -27
  15. cuenca/resources/file_batches.py +12 -4
  16. cuenca/resources/files.py +15 -4
  17. cuenca/resources/identities.py +13 -13
  18. cuenca/resources/kyc_validations.py +11 -8
  19. cuenca/resources/kyc_verifications.py +10 -9
  20. cuenca/resources/limited_wallets.py +4 -4
  21. cuenca/resources/login_tokens.py +7 -5
  22. cuenca/resources/otps.py +26 -0
  23. cuenca/resources/platforms.py +30 -31
  24. cuenca/resources/questionnaires.py +8 -5
  25. cuenca/resources/resources.py +2 -2
  26. cuenca/resources/savings.py +5 -5
  27. cuenca/resources/sessions.py +11 -11
  28. cuenca/resources/transfers.py +4 -3
  29. cuenca/resources/user_credentials.py +8 -3
  30. cuenca/resources/user_events.py +5 -3
  31. cuenca/resources/user_lists_validation.py +7 -3
  32. cuenca/resources/user_logins.py +7 -6
  33. cuenca/resources/users.py +49 -51
  34. cuenca/resources/verifications.py +17 -11
  35. cuenca/resources/wallet_transactions.py +1 -1
  36. cuenca/resources/webhooks.py +7 -8
  37. cuenca/resources/whatsapp_transfers.py +4 -4
  38. cuenca/version.py +1 -1
  39. {cuenca-1.0.3.dev0.dist-info → cuenca-2.0.0.dev1.dist-info}/METADATA +1 -1
  40. {cuenca-1.0.3.dev0.dist-info → cuenca-2.0.0.dev1.dist-info}/RECORD +48 -46
  41. {cuenca-1.0.3.dev0.dist-info → cuenca-2.0.0.dev1.dist-info}/WHEEL +1 -1
  42. tests/resources/test_api_keys.py +1 -1
  43. tests/resources/test_endpoints.py +1 -1
  44. tests/resources/test_otps.py +28 -0
  45. tests/resources/test_sessions.py +2 -2
  46. tests/resources/test_transfers.py +1 -1
  47. {cuenca-1.0.3.dev0.dist-info → cuenca-2.0.0.dev1.dist-info}/LICENSE +0 -0
  48. {cuenca-1.0.3.dev0.dist-info → cuenca-2.0.0.dev1.dist-info}/top_level.txt +0 -0
cuenca/__init__.py CHANGED
@@ -23,6 +23,7 @@ __all__ = [
23
23
  'KYCVerification',
24
24
  'LimitedWallet',
25
25
  'LoginToken',
26
+ 'Otp',
26
27
  'Platform',
27
28
  'Questionnaires',
28
29
  'Saving',
@@ -70,6 +71,7 @@ from .resources import (
70
71
  KYCVerification,
71
72
  LimitedWallet,
72
73
  LoginToken,
74
+ Otp,
73
75
  Platform,
74
76
  Questionnaires,
75
77
  Saving,
@@ -22,6 +22,7 @@ __all__ = [
22
22
  'KYCVerification',
23
23
  'LimitedWallet',
24
24
  'LoginToken',
25
+ 'Otp',
25
26
  'Platform',
26
27
  'Questionnaires',
27
28
  'Saving',
@@ -62,6 +63,7 @@ from .kyc_validations import KYCValidation
62
63
  from .kyc_verifications import KYCVerification
63
64
  from .limited_wallets import LimitedWallet
64
65
  from .login_tokens import LoginToken
66
+ from .otps import Otp
65
67
  from .platforms import Platform
66
68
  from .questionnaires import Questionnaires
67
69
  from .resources import RESOURCES
@@ -1,7 +1,8 @@
1
1
  import datetime as dt
2
- from typing import ClassVar, Optional
2
+ from typing import ClassVar, Optional, cast
3
3
 
4
4
  from cuenca_validations.types import ApiKeyQuery, ApiKeyUpdateRequest
5
+ from pydantic import ConfigDict
5
6
 
6
7
  from ..http import Session, session as global_session
7
8
  from .base import Creatable, Queryable, Retrievable, Updateable
@@ -12,11 +13,10 @@ class ApiKey(Creatable, Queryable, Retrievable, Updateable):
12
13
  _query_params: ClassVar = ApiKeyQuery
13
14
 
14
15
  secret: str
15
- deactivated_at: Optional[dt.datetime]
16
- user_id: Optional[str]
17
-
18
- class Config:
19
- schema_extra = {
16
+ deactivated_at: Optional[dt.datetime] = None
17
+ user_id: Optional[str] = None
18
+ model_config = ConfigDict(
19
+ json_schema_extra={
20
20
  'example': {
21
21
  'id': 'AKNEUInh69SuKXXmK95sROwQ',
22
22
  'updated_at': '2021-08-24T14:15:22Z',
@@ -26,6 +26,7 @@ class ApiKey(Creatable, Queryable, Retrievable, Updateable):
26
26
  'user_id': 'USWqY5cvkISJOxHyEKjAKf8w',
27
27
  }
28
28
  }
29
+ )
29
30
 
30
31
  @property
31
32
  def active(self) -> bool:
@@ -36,7 +37,7 @@ class ApiKey(Creatable, Queryable, Retrievable, Updateable):
36
37
 
37
38
  @classmethod
38
39
  def create(cls, *, session: Session = global_session) -> 'ApiKey':
39
- return cls._create(session=session)
40
+ return cast('ApiKey', cls._create(session=session))
40
41
 
41
42
  @classmethod
42
43
  def deactivate(
@@ -55,7 +56,7 @@ class ApiKey(Creatable, Queryable, Retrievable, Updateable):
55
56
  """
56
57
  url = cls._resource + f'/{api_key_id}'
57
58
  resp = session.delete(url, dict(minutes=minutes))
58
- return cls(**resp)
59
+ return cast('ApiKey', cls._from_dict(resp))
59
60
 
60
61
  @classmethod
61
62
  def update(
@@ -74,4 +75,5 @@ class ApiKey(Creatable, Queryable, Retrievable, Updateable):
74
75
  req = ApiKeyUpdateRequest(
75
76
  metadata=metadata, user_id=user_id, platform_id=platform_id
76
77
  )
77
- return cls._update(api_key_id, **req.dict(), session=session)
78
+ resp = cls._update(api_key_id, **req.dict(), session=session)
79
+ return cast('ApiKey', resp)
cuenca/resources/arpc.py CHANGED
@@ -1,6 +1,7 @@
1
1
  import datetime as dt
2
- from typing import ClassVar, Optional
2
+ from typing import ClassVar, Optional, cast
3
3
 
4
+ from cuenca_validations.types.enums import TrackDataMethod
4
5
  from cuenca_validations.types.requests import ARPCRequest
5
6
 
6
7
  from ..http import Session, session as global_session
@@ -23,8 +24,8 @@ class Arpc(Creatable):
23
24
 
24
25
  created_at: dt.datetime
25
26
  card_uri: str
26
- is_valid_arqc: Optional[bool]
27
- arpc: Optional[str]
27
+ is_valid_arqc: Optional[bool] = None
28
+ arpc: Optional[str] = None
28
29
 
29
30
  @classmethod
30
31
  def create(
@@ -50,6 +51,6 @@ class Arpc(Creatable):
50
51
  transaction_counter=transaction_counter,
51
52
  pan_sequence=pan_sequence,
52
53
  unique_number=unique_number,
53
- track_data_method=track_data_method,
54
+ track_data_method=cast(TrackDataMethod, track_data_method),
54
55
  )
55
- return cls._create(session=session, **req.dict())
56
+ return cast('Arpc', cls._create(session=session, **req.model_dump()))
@@ -1,4 +1,4 @@
1
- from typing import ClassVar, TypeVar, cast
1
+ from typing import ClassVar, Union, cast
2
2
 
3
3
  from cuenca_validations.types import BalanceEntryQuery, EntryType
4
4
 
@@ -8,9 +8,7 @@ from .cards import Card
8
8
  from .resources import retrieve_uri
9
9
  from .service_providers import ServiceProvider
10
10
 
11
- FundingInstrument = TypeVar(
12
- 'FundingInstrument', Account, ServiceProvider, Card
13
- )
11
+ FundingInstrument = Union[Account, ServiceProvider, Card]
14
12
 
15
13
 
16
14
  class BalanceEntry(Retrievable, Queryable):
cuenca/resources/base.py CHANGED
@@ -2,7 +2,7 @@ import base64
2
2
  import datetime as dt
3
3
  import json
4
4
  from io import BytesIO
5
- from typing import ClassVar, Generator, Optional, Type, TypeVar
5
+ from typing import Any, ClassVar, Dict, Generator, Optional
6
6
  from urllib.parse import urlencode
7
7
 
8
8
  from cuenca_validations.types import (
@@ -12,36 +12,48 @@ from cuenca_validations.types import (
12
12
  TransactionQuery,
13
13
  TransactionStatus,
14
14
  )
15
- from pydantic import BaseModel, Extra
15
+ from pydantic import BaseModel
16
16
 
17
17
  from ..exc import MultipleResultsFound, NoResultFound
18
18
  from ..http import Session, session as global_session
19
19
 
20
- R_co = TypeVar('R_co', bound='Resource', covariant=True)
21
- Q_co = TypeVar('Q_co', bound='Queryable', covariant=True)
22
-
23
20
 
24
21
  class Resource(BaseModel):
25
22
  _resource: ClassVar[str]
26
23
 
27
24
  id: str
28
25
 
29
- class Config:
30
- extra = Extra.ignore
26
+ @classmethod
27
+ def _from_dict(cls, obj_dict: Dict[str, Any]) -> 'Resource':
28
+ cls._filter_excess_fields(obj_dict)
29
+ return cls(**obj_dict)
30
+
31
+ @classmethod
32
+ def _filter_excess_fields(cls, obj_dict):
33
+ """
34
+ dataclasses don't allow __init__ to be called with excess fields. This
35
+ method allows the API to add fields in the response body without
36
+ breaking the client
37
+ """
38
+ excess = set(obj_dict.keys()) - set(
39
+ cls.schema().get("properties").keys()
40
+ )
41
+ for f in excess:
42
+ del obj_dict[f]
31
43
 
32
44
  def to_dict(self):
33
- return SantizedDict(self.dict())
45
+ return SantizedDict(self.model_dump())
34
46
 
35
47
 
36
48
  class Retrievable(Resource):
37
49
  @classmethod
38
50
  def retrieve(
39
- cls: Type[R_co], id: str, *, session: Session = global_session
40
- ) -> R_co:
51
+ cls, id: str, *, session: Session = global_session
52
+ ) -> Resource:
41
53
  resp = session.get(f'/{cls._resource}/{id}')
42
- return cls(**resp)
54
+ return cls._from_dict(resp)
43
55
 
44
- def refresh(self, *, session: Session = global_session) -> None:
56
+ def refresh(self, *, session: Session = global_session):
45
57
  new = self.retrieve(self.id, session=session)
46
58
  for attr, value in new.__dict__.items():
47
59
  setattr(self, attr, value)
@@ -49,11 +61,9 @@ class Retrievable(Resource):
49
61
 
50
62
  class Creatable(Resource):
51
63
  @classmethod
52
- def _create(
53
- cls: Type[R_co], *, session: Session = global_session, **data
54
- ) -> R_co:
64
+ def _create(cls, *, session: Session = global_session, **data) -> Resource:
55
65
  resp = session.post(cls._resource, data)
56
- return cls(**resp)
66
+ return cls._from_dict(resp)
57
67
 
58
68
 
59
69
  class Updateable(Resource):
@@ -62,31 +72,31 @@ class Updateable(Resource):
62
72
 
63
73
  @classmethod
64
74
  def _update(
65
- cls: Type[R_co], id: str, *, session: Session = global_session, **data
66
- ) -> R_co:
75
+ cls, id: str, *, session: Session = global_session, **data
76
+ ) -> Resource:
67
77
  resp = session.patch(f'/{cls._resource}/{id}', data)
68
- return cls(**resp)
78
+ return cls._from_dict(resp)
69
79
 
70
80
 
71
81
  class Deactivable(Resource):
72
- deactivated_at: Optional[dt.datetime]
82
+ deactivated_at: Optional[dt.datetime] = None
73
83
 
74
84
  @classmethod
75
85
  def deactivate(
76
- cls: Type[R_co], id: str, *, session: Session = global_session, **data
77
- ) -> R_co:
86
+ cls, id: str, *, session: Session = global_session, **data
87
+ ) -> Resource:
78
88
  resp = session.delete(f'/{cls._resource}/{id}', data)
79
- return cls(**resp)
89
+ return cls._from_dict(resp)
80
90
 
81
91
  @property
82
- def is_active(self) -> bool:
92
+ def is_active(self):
83
93
  return not self.deactivated_at
84
94
 
85
95
 
86
96
  class Downloadable(Resource):
87
97
  @classmethod
88
98
  def download(
89
- cls: Type[R_co],
99
+ cls,
90
100
  id: str,
91
101
  file_format: FileFormat = FileFormat.any,
92
102
  *,
@@ -111,13 +121,13 @@ class Downloadable(Resource):
111
121
  class Uploadable(Resource):
112
122
  @classmethod
113
123
  def _upload(
114
- cls: Type[R_co],
124
+ cls,
115
125
  file: bytes,
116
126
  user_id: str,
117
127
  *,
118
128
  session: Session = global_session,
119
129
  **data,
120
- ) -> R_co:
130
+ ) -> Resource:
121
131
  encoded_file = base64.b64encode(file)
122
132
  resp = session.request(
123
133
  'post',
@@ -128,7 +138,7 @@ class Uploadable(Resource):
128
138
  **{k: (None, v) for k, v in data.items()},
129
139
  ),
130
140
  )
131
- return cls(**json.loads(resp))
141
+ return cls._from_dict(json.loads(resp))
132
142
 
133
143
 
134
144
  class Queryable(Resource):
@@ -138,8 +148,8 @@ class Queryable(Resource):
138
148
 
139
149
  @classmethod
140
150
  def one(
141
- cls: Type[Q_co], *, session: Session = global_session, **query_params
142
- ) -> Q_co:
151
+ cls, *, session: Session = global_session, **query_params
152
+ ) -> Resource:
143
153
  q = cls._query_params(limit=2, **query_params)
144
154
  resp = session.get(cls._resource, q.dict())
145
155
  items = resp['items']
@@ -148,12 +158,12 @@ class Queryable(Resource):
148
158
  raise NoResultFound
149
159
  if len_items > 1:
150
160
  raise MultipleResultsFound
151
- return cls(**items[0])
161
+ return cls._from_dict(items[0])
152
162
 
153
163
  @classmethod
154
164
  def first(
155
- cls: Type[Q_co], *, session: Session = global_session, **query_params
156
- ) -> Optional[Q_co]:
165
+ cls, *, session: Session = global_session, **query_params
166
+ ) -> Optional[Resource]:
157
167
  q = cls._query_params(limit=1, **query_params)
158
168
  resp = session.get(cls._resource, q.dict())
159
169
  try:
@@ -161,12 +171,12 @@ class Queryable(Resource):
161
171
  except IndexError:
162
172
  rv = None
163
173
  else:
164
- rv = cls(**item)
174
+ rv = cls._from_dict(item)
165
175
  return rv
166
176
 
167
177
  @classmethod
168
178
  def count(
169
- cls: Type[Q_co], *, session: Session = global_session, **query_params
179
+ cls, *, session: Session = global_session, **query_params
170
180
  ) -> int:
171
181
  q = cls._query_params(count=True, **query_params)
172
182
  resp = session.get(cls._resource, q.dict())
@@ -174,14 +184,14 @@ class Queryable(Resource):
174
184
 
175
185
  @classmethod
176
186
  def all(
177
- cls: Type[Q_co], *, session: Session = global_session, **query_params
178
- ) -> Generator[Q_co, None, None]:
187
+ cls, *, session: Session = global_session, **query_params
188
+ ) -> Generator[Resource, None, None]:
179
189
  session = session or global_session
180
190
  q = cls._query_params(**query_params)
181
191
  next_page_uri = f'{cls._resource}?{urlencode(q.dict())}'
182
192
  while next_page_uri:
183
193
  page = session.get(next_page_uri)
184
- yield from (cls(**item) for item in page['items'])
194
+ yield from (cls._from_dict(item) for item in page['items'])
185
195
  next_page_uri = page['next_page_uri']
186
196
 
187
197
 
@@ -15,7 +15,7 @@ class CardActivation(Creatable):
15
15
  created_at: dt.datetime
16
16
  user_id: str
17
17
  ip_address: str
18
- card_uri: Optional[str]
18
+ card_uri: Optional[str] = None
19
19
  success: bool
20
20
 
21
21
  @classmethod
@@ -42,7 +42,9 @@ class CardActivation(Creatable):
42
42
  exp_year=exp_year,
43
43
  cvv2=cvv2,
44
44
  )
45
- return cls._create(session=session, **req.dict())
45
+ return cast(
46
+ 'CardActivation', cls._create(session=session, **req.model_dump())
47
+ )
46
48
 
47
49
  @property
48
50
  def card(self) -> Optional[Card]:
@@ -24,7 +24,7 @@ class CardTransaction(Transaction):
24
24
  card_last4: str
25
25
  card_type: CardType
26
26
  metadata: dict
27
- error_type: Optional[CardErrorType]
27
+ error_type: Optional[CardErrorType] = None
28
28
 
29
29
  @property # type: ignore
30
30
  def related_card_transactions(self) -> Optional[List['CardTransaction']]:
@@ -18,11 +18,11 @@ class CardValidation(Creatable):
18
18
  user_id: str
19
19
  card_status: CardStatus
20
20
  card_type: CardType
21
- is_valid_cvv: Optional[bool]
22
- is_valid_cvv2: Optional[bool]
23
- is_valid_icvv: Optional[bool]
24
- is_valid_pin_block: Optional[bool]
25
- is_valid_exp_date: Optional[bool]
21
+ is_valid_cvv: Optional[bool] = None
22
+ is_valid_cvv2: Optional[bool] = None
23
+ is_valid_icvv: Optional[bool] = None
24
+ is_valid_pin_block: Optional[bool] = None
25
+ is_valid_exp_date: Optional[bool] = None
26
26
  is_pin_attempts_exceeded: bool
27
27
  is_expired: bool
28
28
  platform_id: Optional[str] = None
@@ -37,7 +37,7 @@ class CardValidation(Creatable):
37
37
  exp_month: Optional[int] = None,
38
38
  exp_year: Optional[int] = None,
39
39
  pin_block: Optional[str] = None,
40
- pin_attempts_exceeded: Optional[str] = None,
40
+ pin_attempts_exceeded: Optional[bool] = None,
41
41
  *,
42
42
  session: Session = global_session,
43
43
  ) -> 'CardValidation':
@@ -52,7 +52,7 @@ class CardValidation(Creatable):
52
52
  pin_attempts_exceeded=pin_attempts_exceeded,
53
53
  )
54
54
  return cast(
55
- 'CardValidation', cls._create(session=session, **req.dict())
55
+ 'CardValidation', cls._create(session=session, **req.model_dump())
56
56
  )
57
57
 
58
58
  @property
cuenca/resources/cards.py CHANGED
@@ -1,5 +1,5 @@
1
1
  import datetime as dt
2
- from typing import ClassVar, Optional
2
+ from typing import ClassVar, Optional, cast
3
3
 
4
4
  from cuenca_validations.types import (
5
5
  CardFundingType,
@@ -21,12 +21,12 @@ class Card(Retrievable, Queryable, Creatable, Updateable):
21
21
  _resource: ClassVar = 'cards'
22
22
  _query_params: ClassVar = CardQuery
23
23
 
24
- user_id: Optional[str]
24
+ user_id: Optional[str] = None
25
25
  number: str
26
26
  exp_month: int
27
27
  exp_year: int
28
28
  cvv2: str
29
- pin: Optional[str]
29
+ pin: Optional[str] = None
30
30
  type: CardType
31
31
  status: CardStatus
32
32
  issuer: CardIssuer
@@ -81,7 +81,7 @@ class Card(Retrievable, Queryable, Creatable, Updateable):
81
81
  card_holder_user_id=card_holder_user_id,
82
82
  is_dynamic_cvv=is_dynamic_cvv,
83
83
  )
84
- return cls._create(session=session, **req.dict())
84
+ return cast('Card', cls._create(session=session, **req.dict()))
85
85
 
86
86
  @classmethod
87
87
  def update(
@@ -106,7 +106,8 @@ class Card(Retrievable, Queryable, Creatable, Updateable):
106
106
  req = CardUpdateRequest(
107
107
  status=status, pin_block=pin_block, is_dynamic_cvv=is_dynamic_cvv
108
108
  )
109
- return cls._update(card_id, session=session, **req.dict())
109
+ resp = cls._update(card_id, session=session, **req.dict())
110
+ return cast('Card', resp)
110
111
 
111
112
  @classmethod
112
113
  def deactivate(
@@ -117,4 +118,4 @@ class Card(Retrievable, Queryable, Creatable, Updateable):
117
118
  """
118
119
  url = f'{cls._resource}/{card_id}'
119
120
  resp = session.delete(url)
120
- return cls(**resp)
121
+ return cast('Card', cls._from_dict(resp))
@@ -1,4 +1,4 @@
1
- from typing import ClassVar
1
+ from typing import ClassVar, cast
2
2
 
3
3
  from ..http import Session, session as global_session
4
4
  from .base import Creatable, Queryable, Retrievable
@@ -11,4 +11,4 @@ class Clabe(Creatable, Queryable, Retrievable):
11
11
 
12
12
  @classmethod
13
13
  def create(cls, session: Session = global_session):
14
- return cls._create(session=session)
14
+ return cast('Clabe', cls._create(session=session))
@@ -1,5 +1,5 @@
1
1
  import datetime as dt
2
- from typing import ClassVar, Optional
2
+ from typing import ClassVar, Optional, cast
3
3
 
4
4
  from cuenca_validations.types import (
5
5
  Country,
@@ -8,6 +8,7 @@ from cuenca_validations.types import (
8
8
  State,
9
9
  )
10
10
  from cuenca_validations.types.identities import CurpField
11
+ from pydantic import ConfigDict, Field
11
12
 
12
13
  from ..http import Session, session as global_session
13
14
  from .base import Creatable, Retrievable
@@ -17,44 +18,43 @@ class CurpValidation(Creatable, Retrievable):
17
18
  _resource: ClassVar = 'curp_validations'
18
19
 
19
20
  created_at: dt.datetime
20
- names: Optional[str] = None
21
- first_surname: Optional[str] = None
22
- second_surname: Optional[str] = None
23
- date_of_birth: Optional[dt.date] = None
24
- country_of_birth: Optional[Country] = None
25
- state_of_birth: Optional[State] = None
26
- gender: Optional[Gender] = None
27
- nationality: Optional[Country] = None
28
- manual_curp: Optional[CurpField] = None
29
- calculated_curp: CurpField
30
- validated_curp: Optional[CurpField] = None
31
- renapo_curp_match: bool
32
- renapo_full_match: bool
33
-
34
- class Config:
35
- fields = {
36
- 'names': {'description': 'Official name from Renapo'},
37
- 'first_surname': {'description': 'Official surname from Renapo'},
38
- 'second_surname': {'description': 'Official surname from Renapo'},
39
- 'country_of_birth': {'description': 'In format ISO 3166 Alpha-2'},
40
- 'state_of_birth': {'description': 'In format ISO 3166 Alpha-2'},
41
- 'nationality': {'description': 'In format ISO 3166 Alpha-2'},
42
- 'manual_curp': {'description': 'curp provided in request'},
43
- 'calculated_curp': {
44
- 'description': 'Calculated CURP based on request data'
45
- },
46
- 'validated_curp': {
47
- 'description': 'CURP validated in Renapo, null if not exists'
48
- },
49
- 'renapo_curp_match': {
50
- 'description': 'True if CURP exists and is valid'
51
- },
52
- 'renapo_full_match': {
53
- 'description': 'True if all fields provided match the response'
54
- ' from RENAPO. Accents in names are ignored'
55
- },
56
- }
57
- schema_extra = {
21
+ names: Optional[str] = Field(None, description='Official name from Renapo')
22
+ first_surname: Optional[str] = Field(
23
+ None, description='Official surname from Renapo'
24
+ )
25
+ second_surname: Optional[str] = Field(
26
+ None, description='Official surname from Renapo'
27
+ )
28
+ date_of_birth: Optional[dt.date] = Field(
29
+ None, description='In format ISO 3166 Alpha-2'
30
+ )
31
+ country_of_birth: Optional[Country] = Field(
32
+ None, description='In format ISO 3166 Alpha-2'
33
+ )
34
+ state_of_birth: Optional[State] = Field(None, description='State of birth')
35
+ gender: Optional[Gender] = Field(None, description='Gender')
36
+ nationality: Optional[Country] = Field(
37
+ None, description='In format ISO 3166 Alpha-2'
38
+ )
39
+ manual_curp: Optional[CurpField] = Field(
40
+ None, description='curp provided in request'
41
+ )
42
+ calculated_curp: CurpField = Field(
43
+ ..., description='Calculated CURP based on request data'
44
+ )
45
+ validated_curp: Optional[CurpField] = Field(
46
+ None, description='CURP validated in Renapo, null if not exists'
47
+ )
48
+ renapo_curp_match: bool = Field(
49
+ ..., description='True if CURP exists and is valid'
50
+ )
51
+ renapo_full_match: bool = Field(
52
+ ...,
53
+ description='True if all fields provided match the response from '
54
+ 'RENAPO. Accents in names are ignored',
55
+ )
56
+ model_config = ConfigDict(
57
+ json_schema_extra={
58
58
  'example': {
59
59
  'id': 'CVNEUInh69SuKXXmK95sROwQ',
60
60
  'created_at': '2019-08-24T14:15:22Z',
@@ -72,7 +72,8 @@ class CurpValidation(Creatable, Retrievable):
72
72
  'renapo_curp_match': True,
73
73
  'renapo_full_match': True,
74
74
  }
75
- }
75
+ },
76
+ )
76
77
 
77
78
  @classmethod
78
79
  def create(
@@ -94,8 +95,11 @@ class CurpValidation(Creatable, Retrievable):
94
95
  second_surname=second_surname,
95
96
  date_of_birth=date_of_birth,
96
97
  state_of_birth=state_of_birth,
97
- country_of_birth=country_of_birth,
98
+ country_of_birth=cast(Country, country_of_birth),
98
99
  gender=gender,
99
100
  manual_curp=manual_curp,
100
101
  )
101
- return cls._create(session=session, **req.dict())
102
+ return cast(
103
+ 'CurpValidation',
104
+ cls._create(session=session, **req.model_dump()),
105
+ )
@@ -13,7 +13,7 @@ class Deposit(Transaction):
13
13
 
14
14
  network: DepositNetwork
15
15
  source_uri: str
16
- tracking_key: Optional[str] # clave rastreo if network is SPEI
16
+ tracking_key: Optional[str] = None # clave rastreo if network is SPEI
17
17
 
18
18
  @property # type: ignore
19
19
  def source(self) -> Account: