cuenca 1.0.3.dev1__tar.gz → 2.0.0__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 (114) hide show
  1. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/PKG-INFO +20 -7
  2. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/__init__.py +1 -3
  3. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/api_keys.py +7 -6
  4. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/arpc.py +3 -3
  5. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/balance_entries.py +2 -4
  6. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/base.py +46 -19
  7. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/card_activations.py +2 -2
  8. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/card_transactions.py +5 -5
  9. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/card_validations.py +6 -8
  10. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/cards.py +4 -4
  11. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/curp_validations.py +42 -42
  12. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/deposits.py +1 -1
  13. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/endpoints.py +24 -29
  14. cuenca-2.0.0/cuenca/resources/file_batches.py +32 -0
  15. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/files.py +1 -1
  16. cuenca-2.0.0/cuenca/resources/identities.py +39 -0
  17. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/kyc_validations.py +10 -8
  18. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/kyc_verifications.py +10 -8
  19. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/limited_wallets.py +5 -5
  20. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/login_tokens.py +5 -2
  21. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/otps.py +7 -4
  22. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/platforms.py +25 -28
  23. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/questionnaires.py +5 -3
  24. cuenca-2.0.0/cuenca/resources/resources.py +25 -0
  25. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/savings.py +5 -5
  26. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/service_providers.py +2 -2
  27. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/sessions.py +8 -7
  28. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/transfers.py +6 -6
  29. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/user_credentials.py +2 -2
  30. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/user_events.py +5 -2
  31. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/user_lists_validation.py +4 -4
  32. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/user_logins.py +6 -4
  33. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/users.py +45 -52
  34. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/verifications.py +10 -9
  35. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/wallet_transactions.py +2 -2
  36. cuenca-2.0.0/cuenca/resources/webhooks.py +13 -0
  37. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/whatsapp_transfers.py +4 -4
  38. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/version.py +1 -1
  39. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca.egg-info/PKG-INFO +20 -7
  40. cuenca-2.0.0/cuenca.egg-info/requires.txt +3 -0
  41. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/setup.py +9 -5
  42. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/conftest.py +3 -4
  43. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_card_activations.py +4 -4
  44. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_cards.py +0 -8
  45. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_commissions.py +2 -2
  46. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_endpoints.py +1 -1
  47. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_otps.py +1 -1
  48. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_sessions.py +1 -5
  49. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_transfers.py +1 -1
  50. cuenca-1.0.3.dev1/cuenca/resources/file_batches.py +0 -25
  51. cuenca-1.0.3.dev1/cuenca/resources/identities.py +0 -39
  52. cuenca-1.0.3.dev1/cuenca/resources/resources.py +0 -21
  53. cuenca-1.0.3.dev1/cuenca/resources/webhooks.py +0 -18
  54. cuenca-1.0.3.dev1/cuenca.egg-info/requires.txt +0 -5
  55. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/LICENSE +0 -0
  56. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/README.md +0 -0
  57. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/exc.py +0 -0
  58. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/http/__init__.py +0 -0
  59. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/http/client.py +0 -0
  60. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/jwt.py +0 -0
  61. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/py.typed +0 -0
  62. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/__init__.py +0 -0
  63. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/accounts.py +0 -0
  64. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/bill_payments.py +0 -0
  65. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/cash_references.py +0 -0
  66. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/clabes.py +0 -0
  67. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/commissions.py +0 -0
  68. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/identity_events.py +0 -0
  69. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca/resources/statements.py +0 -0
  70. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca.egg-info/SOURCES.txt +0 -0
  71. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca.egg-info/dependency_links.txt +0 -0
  72. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/cuenca.egg-info/top_level.txt +0 -0
  73. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/setup.cfg +0 -0
  74. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/__init__.py +0 -0
  75. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/http/__init__.py +0 -0
  76. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/http/conftest.py +0 -0
  77. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/http/test_client.py +0 -0
  78. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/__init__.py +0 -0
  79. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_accounts.py +0 -0
  80. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_api_keys.py +0 -0
  81. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_arpc.py +0 -0
  82. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_balance_entries.py +0 -0
  83. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_bill_payments.py +0 -0
  84. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_card_transactions.py +0 -0
  85. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_card_validations.py +0 -0
  86. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_cash_references.py +0 -0
  87. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_clabes.py +0 -0
  88. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_curp_validations.py +0 -0
  89. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_deposits.py +0 -0
  90. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_file_batches.py +0 -0
  91. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_files.py +0 -0
  92. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_identities.py +0 -0
  93. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_identity_events.py +0 -0
  94. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_kyc_validations.py +0 -0
  95. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_kyc_verifications.py +0 -0
  96. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_limited_wallets.py +0 -0
  97. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_login_tokens.py +0 -0
  98. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_platforms.py +0 -0
  99. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_questionnaires.py +0 -0
  100. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_resources.py +0 -0
  101. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_savings.py +0 -0
  102. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_service_providers.py +0 -0
  103. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_statements.py +0 -0
  104. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_user_credentials.py +0 -0
  105. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_user_events.py +0 -0
  106. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_user_lists_validation.py +0 -0
  107. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_user_logins.py +0 -0
  108. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_users.py +0 -0
  109. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_verifications.py +0 -0
  110. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_wallet_transactions.py +0 -0
  111. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_webhooks.py +0 -0
  112. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/resources/test_whatsapp_transfers.py +0 -0
  113. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/test_cuenca.py +0 -0
  114. {cuenca-1.0.3.dev1 → cuenca-2.0.0}/tests/test_jwt.py +0 -0
@@ -1,19 +1,32 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: cuenca
3
- Version: 1.0.3.dev1
3
+ Version: 2.0.0
4
4
  Summary: Cuenca API Client
5
5
  Home-page: https://github.com/cuenca-mx/cuenca-python
6
6
  Author: Cuenca
7
7
  Author-email: dev@cuenca.com
8
- Classifier: Programming Language :: Python :: 3.8
8
+ Classifier: Programming Language :: Python :: 3.9
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
9
13
  Classifier: License :: OSI Approved :: MIT License
10
14
  Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.8
15
+ Requires-Python: >=3.9
12
16
  Description-Content-Type: text/markdown
13
17
  License-File: LICENSE
14
- Requires-Dist: requests<28,>=2.24
15
- Requires-Dist: dataclasses>=0.7; python_version < "3.8"
16
- Requires-Dist: cuenca-validations<0.12.0,>=0.11.3
18
+ Requires-Dist: requests>=2.32.0
19
+ Requires-Dist: cuenca-validations>=2.0.0
20
+ Requires-Dist: pydantic-extra-types>=2.10.0
21
+ Dynamic: author
22
+ Dynamic: author-email
23
+ Dynamic: classifier
24
+ Dynamic: description
25
+ Dynamic: description-content-type
26
+ Dynamic: home-page
27
+ Dynamic: requires-dist
28
+ Dynamic: requires-python
29
+ Dynamic: summary
17
30
 
18
31
  # Cuenca – Python client library
19
32
 
@@ -44,8 +44,6 @@ __all__ = [
44
44
  'get_balance',
45
45
  ]
46
46
 
47
- from typing import cast
48
-
49
47
  from . import http
50
48
  from .resources import (
51
49
  Account,
@@ -96,5 +94,5 @@ session = http.session
96
94
 
97
95
 
98
96
  def get_balance(session: http.Session = session) -> int:
99
- balance_entry = cast('BalanceEntry', BalanceEntry.first(session=session))
97
+ balance_entry = BalanceEntry.first(session=session)
100
98
  return balance_entry.rolling_balance if balance_entry else 0
@@ -2,6 +2,7 @@ import datetime as dt
2
2
  from typing import ClassVar, Optional
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:
@@ -74,4 +75,4 @@ 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
+ return cls._update(api_key_id, **req.model_dump(), session=session)
@@ -23,8 +23,8 @@ class Arpc(Creatable):
23
23
 
24
24
  created_at: dt.datetime
25
25
  card_uri: str
26
- is_valid_arqc: Optional[bool]
27
- arpc: Optional[str]
26
+ is_valid_arqc: Optional[bool] = None
27
+ arpc: Optional[str] = None
28
28
 
29
29
  @classmethod
30
30
  def create(
@@ -52,4 +52,4 @@ class Arpc(Creatable):
52
52
  unique_number=unique_number,
53
53
  track_data_method=track_data_method,
54
54
  )
55
- return cls._create(session=session, **req.dict())
55
+ return 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):
@@ -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, cast
5
+ from typing import Any, ClassVar, Generator, Optional, Type, TypeVar, cast
6
6
  from urllib.parse import urlencode
7
7
 
8
8
  from cuenca_validations.types import (
@@ -12,7 +12,7 @@ from cuenca_validations.types import (
12
12
  TransactionQuery,
13
13
  TransactionStatus,
14
14
  )
15
- from pydantic import BaseModel, Extra
15
+ from pydantic import BaseModel, ConfigDict
16
16
 
17
17
  from ..exc import MultipleResultsFound, NoResultFound
18
18
  from ..http import Session, session as global_session
@@ -25,17 +25,21 @@ class Resource(BaseModel):
25
25
 
26
26
  id: str
27
27
 
28
- class Config:
29
- extra = Extra.ignore
28
+ model_config = ConfigDict(
29
+ extra="ignore",
30
+ )
30
31
 
31
32
  def to_dict(self):
32
- return SantizedDict(self.dict())
33
+ return SantizedDict(self.model_dump())
33
34
 
34
35
 
35
36
  class Retrievable(Resource):
36
37
  @classmethod
37
38
  def retrieve(
38
- cls: Type[R_co], id: str, *, session: Session = global_session
39
+ cls: Type[R_co],
40
+ id: str,
41
+ *,
42
+ session: Session = global_session,
39
43
  ) -> R_co:
40
44
  resp = session.get(f'/{cls._resource}/{id}')
41
45
  return cls(**resp)
@@ -49,7 +53,10 @@ class Retrievable(Resource):
49
53
  class Creatable(Resource):
50
54
  @classmethod
51
55
  def _create(
52
- cls: Type[R_co], *, session: Session = global_session, **data
56
+ cls: Type[R_co],
57
+ *,
58
+ session: Session = global_session,
59
+ **data: Any,
53
60
  ) -> R_co:
54
61
  resp = session.post(cls._resource, data)
55
62
  return cls(**resp)
@@ -61,18 +68,26 @@ class Updateable(Resource):
61
68
 
62
69
  @classmethod
63
70
  def _update(
64
- cls: Type[R_co], id: str, *, session: Session = global_session, **data
71
+ cls: Type[R_co],
72
+ id: str,
73
+ *,
74
+ session: Session = global_session,
75
+ **data: Any,
65
76
  ) -> R_co:
66
77
  resp = session.patch(f'/{cls._resource}/{id}', data)
67
78
  return cls(**resp)
68
79
 
69
80
 
70
81
  class Deactivable(Resource):
71
- deactivated_at: Optional[dt.datetime]
82
+ deactivated_at: Optional[dt.datetime] = None
72
83
 
73
84
  @classmethod
74
85
  def deactivate(
75
- cls: Type[R_co], id: str, *, session: Session = global_session, **data
86
+ cls: Type[R_co],
87
+ id: str,
88
+ *,
89
+ session: Session = global_session,
90
+ **data: Any,
76
91
  ) -> R_co:
77
92
  resp = session.delete(f'/{cls._resource}/{id}', data)
78
93
  return cls(**resp)
@@ -115,7 +130,7 @@ class Uploadable(Resource):
115
130
  user_id: str,
116
131
  *,
117
132
  session: Session = global_session,
118
- **data,
133
+ **data: Any,
119
134
  ) -> R_co:
120
135
  encoded_file = base64.b64encode(file)
121
136
  resp = session.request(
@@ -137,10 +152,13 @@ class Queryable(Resource):
137
152
 
138
153
  @classmethod
139
154
  def one(
140
- cls: Type[R_co], *, session: Session = global_session, **query_params
155
+ cls: Type[R_co],
156
+ *,
157
+ session: Session = global_session,
158
+ **query_params: Any,
141
159
  ) -> R_co:
142
160
  q = cast(Queryable, cls)._query_params(limit=2, **query_params)
143
- resp = session.get(cls._resource, q.dict())
161
+ resp = session.get(cls._resource, q.model_dump())
144
162
  items = resp['items']
145
163
  len_items = len(items)
146
164
  if not len_items:
@@ -151,10 +169,13 @@ class Queryable(Resource):
151
169
 
152
170
  @classmethod
153
171
  def first(
154
- cls: Type[R_co], *, session: Session = global_session, **query_params
172
+ cls: Type[R_co],
173
+ *,
174
+ session: Session = global_session,
175
+ **query_params: Any,
155
176
  ) -> Optional[R_co]:
156
177
  q = cast(Queryable, cls)._query_params(limit=1, **query_params)
157
- resp = session.get(cls._resource, q.dict())
178
+ resp = session.get(cls._resource, q.model_dump())
158
179
  try:
159
180
  item = resp['items'][0]
160
181
  except IndexError:
@@ -165,19 +186,25 @@ class Queryable(Resource):
165
186
 
166
187
  @classmethod
167
188
  def count(
168
- cls: Type[R_co], *, session: Session = global_session, **query_params
189
+ cls: Type[R_co],
190
+ *,
191
+ session: Session = global_session,
192
+ **query_params: Any,
169
193
  ) -> int:
170
194
  q = cast(Queryable, cls)._query_params(count=True, **query_params)
171
- resp = session.get(cls._resource, q.dict())
195
+ resp = session.get(cls._resource, q.model_dump())
172
196
  return resp['count']
173
197
 
174
198
  @classmethod
175
199
  def all(
176
- cls: Type[R_co], *, session: Session = global_session, **query_params
200
+ cls: Type[R_co],
201
+ *,
202
+ session: Session = global_session,
203
+ **query_params: Any,
177
204
  ) -> Generator[R_co, None, None]:
178
205
  session = session or global_session
179
206
  q = cast(Queryable, cls)._query_params(**query_params)
180
- next_page_uri = f'{cls._resource}?{urlencode(q.dict())}'
207
+ next_page_uri = f'{cls._resource}?{urlencode(q.model_dump())}'
181
208
  while next_page_uri:
182
209
  page = session.get(next_page_uri)
183
210
  yield from (cls(**item) for item in page['items'])
@@ -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,7 @@ 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 cls._create(session=session, **req.model_dump())
46
46
 
47
47
  @property
48
48
  def card(self) -> Optional[Card]:
@@ -1,4 +1,4 @@
1
- from typing import ClassVar, List, Optional, cast
1
+ from typing import ClassVar, Optional, cast
2
2
 
3
3
  from cuenca_validations.types import (
4
4
  CardErrorType,
@@ -19,19 +19,19 @@ class CardTransaction(Transaction):
19
19
 
20
20
  type: CardTransactionType
21
21
  network: CardNetwork
22
- related_card_transaction_uris: List[str]
22
+ related_card_transaction_uris: list[str]
23
23
  card_uri: str
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
- def related_card_transactions(self) -> Optional[List['CardTransaction']]:
30
+ def related_card_transactions(self) -> Optional[list['CardTransaction']]:
31
31
  if not self.related_card_transaction_uris:
32
32
  return []
33
33
  return cast(
34
- List['CardTransaction'],
34
+ list['CardTransaction'],
35
35
  retrieve_uris(self.related_card_transaction_uris),
36
36
  )
37
37
 
@@ -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
@@ -51,9 +51,7 @@ class CardValidation(Creatable):
51
51
  pin_block=pin_block,
52
52
  pin_attempts_exceeded=pin_attempts_exceeded,
53
53
  )
54
- return cast(
55
- 'CardValidation', cls._create(session=session, **req.dict())
56
- )
54
+ return cls._create(session=session, **req.model_dump())
57
55
 
58
56
  @property
59
57
  def card(self) -> Card:
@@ -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 cls._create(session=session, **req.model_dump())
85
85
 
86
86
  @classmethod
87
87
  def update(
@@ -106,7 +106,7 @@ 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
+ return cls._update(card_id, session=session, **req.model_dump())
110
110
 
111
111
  @classmethod
112
112
  def deactivate(
@@ -7,7 +7,8 @@ from cuenca_validations.types import (
7
7
  Gender,
8
8
  State,
9
9
  )
10
- from cuenca_validations.types.identities import CurpField
10
+ from cuenca_validations.types.identities import Curp
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,42 @@ 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[Curp] = Field(
40
+ None, description='curp provided in request'
41
+ )
42
+ calculated_curp: Curp = Field(
43
+ description='Calculated CURP based on request data'
44
+ )
45
+ validated_curp: Optional[Curp] = 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
+ description='True if all fields provided match the response from '
53
+ 'RENAPO. Accents in names are ignored',
54
+ )
55
+ model_config = ConfigDict(
56
+ json_schema_extra={
58
57
  'example': {
59
58
  'id': 'CVNEUInh69SuKXXmK95sROwQ',
60
59
  'created_at': '2019-08-24T14:15:22Z',
@@ -72,7 +71,8 @@ class CurpValidation(Creatable, Retrievable):
72
71
  'renapo_curp_match': True,
73
72
  'renapo_full_match': True,
74
73
  }
75
- }
74
+ },
75
+ )
76
76
 
77
77
  @classmethod
78
78
  def create(
@@ -84,7 +84,7 @@ class CurpValidation(Creatable, Retrievable):
84
84
  state_of_birth: Optional[State] = None,
85
85
  gender: Optional[Gender] = None,
86
86
  second_surname: Optional[str] = None,
87
- manual_curp: Optional[CurpField] = None,
87
+ manual_curp: Optional[Curp] = None,
88
88
  *,
89
89
  session: Session = global_session,
90
90
  ) -> 'CurpValidation':
@@ -98,4 +98,4 @@ class CurpValidation(Creatable, Retrievable):
98
98
  gender=gender,
99
99
  manual_curp=manual_curp,
100
100
  )
101
- return cls._create(session=session, **req.dict())
101
+ return cls._create(session=session, **req.model_dump())
@@ -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:
@@ -1,11 +1,11 @@
1
- from typing import ClassVar, List, Optional
1
+ from typing import ClassVar, Optional
2
2
 
3
3
  from cuenca_validations.types.enums import WebhookEvent
4
4
  from cuenca_validations.types.requests import (
5
5
  EndpointRequest,
6
6
  EndpointUpdateRequest,
7
7
  )
8
- from pydantic import HttpUrl
8
+ from pydantic import ConfigDict, Field, HttpUrl
9
9
 
10
10
  from ..http import Session, session as global_session
11
11
  from .base import Creatable, Deactivable, Queryable, Retrievable, Updateable
@@ -14,28 +14,21 @@ from .base import Creatable, Deactivable, Queryable, Retrievable, Updateable
14
14
  class Endpoint(Creatable, Deactivable, Retrievable, Queryable, Updateable):
15
15
  _resource: ClassVar = 'endpoints'
16
16
 
17
- url: HttpUrl
18
- secret: str
19
- is_enable: bool
20
- events: List[WebhookEvent]
21
-
22
- class Config:
23
- fields = {
24
- 'url': {'description': 'HTTPS url to send webhooks'},
25
- 'secret': {
26
- 'description': 'token to verify the webhook is sent by Cuenca '
27
- 'using HMAC algorithm'
28
- },
29
- 'is_enable': {
30
- 'description': 'Allows user to turn-off the endpoint '
31
- 'without the need of deleting it'
32
- },
33
- 'events': {
34
- 'description': 'list of enabled events. If None, '
35
- 'all events will be enabled for this Endpoint'
36
- },
37
- }
38
- schema_extra = {
17
+ url: HttpUrl = Field(description='HTTPS url to send webhooks')
18
+ secret: str = Field(
19
+ description='token to verify the webhook is sent by Cuenca '
20
+ 'using HMAC algorithm',
21
+ )
22
+ is_enable: bool = Field(
23
+ description='Allows user to turn-off the endpoint without the '
24
+ 'need of deleting it',
25
+ )
26
+ events: list[WebhookEvent] = Field(
27
+ description='list of enabled events. If None, all events will '
28
+ 'be enabled for this Endpoint',
29
+ )
30
+ model_config = ConfigDict(
31
+ json_schema_extra={
39
32
  'example': {
40
33
  '_id': 'ENxxne2Z5VSTKZm_w8Hzffcw',
41
34
  'platform_id': 'PTZoPrrPT6Ts-9myamq5h1bA',
@@ -52,13 +45,14 @@ class Endpoint(Creatable, Deactivable, Retrievable, Queryable, Updateable):
52
45
  ],
53
46
  'is_enable': True,
54
47
  }
55
- }
48
+ },
49
+ )
56
50
 
57
51
  @classmethod
58
52
  def create(
59
53
  cls,
60
54
  url: HttpUrl,
61
- events: Optional[List[WebhookEvent]] = None,
55
+ events: Optional[list[WebhookEvent]] = None,
62
56
  *,
63
57
  session: Session = global_session,
64
58
  ) -> 'Endpoint':
@@ -72,14 +66,14 @@ class Endpoint(Creatable, Deactivable, Retrievable, Queryable, Updateable):
72
66
  :return: New active endpoint
73
67
  """
74
68
  req = EndpointRequest(url=url, events=events)
75
- return cls._create(session=session, **req.dict())
69
+ return cls._create(session=session, **req.model_dump())
76
70
 
77
71
  @classmethod
78
72
  def update(
79
73
  cls,
80
74
  endpoint_id: str,
81
75
  url: Optional[HttpUrl] = None,
82
- events: Optional[List[WebhookEvent]] = None,
76
+ events: Optional[list[WebhookEvent]] = None,
83
77
  is_enable: Optional[bool] = None,
84
78
  *,
85
79
  session: Session = global_session,
@@ -89,6 +83,7 @@ class Endpoint(Creatable, Deactivable, Retrievable, Queryable, Updateable):
89
83
  like url and is_active.
90
84
  :param endpoint_id: existing endpoint_id
91
85
  :param url
86
+ :param events: Optional list of enabled events to update
92
87
  :param is_enable
93
88
  :param session
94
89
  :return: Updated endpoint object
@@ -96,4 +91,4 @@ class Endpoint(Creatable, Deactivable, Retrievable, Queryable, Updateable):
96
91
  req = EndpointUpdateRequest(
97
92
  url=url, is_enable=is_enable, events=events
98
93
  )
99
- return cls._update(endpoint_id, session=session, **req.dict())
94
+ return cls._update(endpoint_id, session=session, **req.model_dump())
@@ -0,0 +1,32 @@
1
+ from typing import ClassVar
2
+
3
+ from cuenca_validations.types import (
4
+ BatchFileMetadata,
5
+ FileBatchUploadRequest,
6
+ FileRequest,
7
+ )
8
+
9
+ from ..http import Session, session as global_session
10
+ from .base import Creatable, Queryable
11
+
12
+
13
+ class FileBatch(Creatable, Queryable):
14
+ _resource: ClassVar = 'file_batches'
15
+
16
+ received_files: list[BatchFileMetadata]
17
+ uploaded_files: list[BatchFileMetadata]
18
+ user_id: str
19
+
20
+ @classmethod
21
+ def create(
22
+ cls,
23
+ files: list[dict],
24
+ user_id: str,
25
+ *,
26
+ session: Session = global_session,
27
+ ) -> 'FileBatch':
28
+ req = FileBatchUploadRequest(
29
+ files=[FileRequest(**f) for f in files],
30
+ user_id=user_id,
31
+ )
32
+ return cls._create(session=session, **req.model_dump())
@@ -44,7 +44,7 @@ class File(Downloadable, Queryable, Uploadable):
44
44
  is_back=is_back,
45
45
  user_id=user_id,
46
46
  )
47
- return cls._upload(session=session, **req.dict())
47
+ return cls._upload(session=session, **req.model_dump())
48
48
 
49
49
  @property
50
50
  def file(self) -> bytes: