Skip to content

Commit a42283c

Browse files
gmorales96gabino
andauthored
Update/pydantic v2 (#411)
* Update Python version and dependencies in Makefile and requirements files * Update Python version requirement and dependencies in setup.py * Update GitHub Actions workflows to use Python 3.13 * update syntax for Pydantic v2 compatibility * re-record card activation with valid card number * Remove unused test for valid card creation in test_cards.py * Refactor type checks in tests to use isinstance * Fix endpoint URL assertion and clean up session test assertions * Update error message in test_invalid_params to reflect new validation response * Update test_user_beneficiaries_update.yaml to correct phone number format in response body * Resolve linting errors * Replace built-in type hints (Dict, List) with dict and list * Update pydantic-extra-types version to 2.10.2 in requirements.txt * Update version to 2.0.0 in version.py * Add mypy configuration for Pydantic plugin * Refactor Card model to use string for card number instead of PaymentCardNumber type * Update cuenca-validations version to 2.0.0 in requirements.txt * Refactor CURP handling across multiple resources to use the updated Curp type instead of CurpField * Refactor optional parameters in resource classes * Update version to 2.0.0.dev7 in version.py for development release --------- Co-authored-by: gabino <gabino@cuenca.com>
1 parent b308816 commit a42283c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+393
-412
lines changed

.github/workflows/release.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@ jobs:
66
publish-pypi:
77
runs-on: ubuntu-latest
88
steps:
9-
- uses: actions/checkout@v2.4.0
10-
- name: Set up Python 3.8
11-
uses: actions/setup-python@v2.3.1
9+
- uses: actions/checkout@v4
10+
- name: Set up Python 3.13
11+
uses: actions/setup-python@v5
1212
with:
13-
python-version: 3.8
13+
python-version: 3.13
1414
- name: Install dependencies
1515
run: pip install -qU setuptools wheel twine
1616
- name: Generating distribution archives
1717
run: python setup.py sdist bdist_wheel
1818
- name: Publish distribution 📦 to PyPI
1919
if: startsWith(github.event.ref, 'refs/tags')
20-
uses: pypa/gh-action-pypi-publish@master
20+
uses: pypa/gh-action-pypi-publish@release/v1
2121
with:
2222
user: __token__
2323
password: ${{ secrets.pypi_password }}

.github/workflows/test.yml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ jobs:
77
runs-on: ubuntu-latest
88
steps:
99
- uses: actions/checkout@v4
10-
- name: Set up Python
11-
uses: actions/setup-python@v5.1.0
10+
- name: Set up Python 13
11+
uses: actions/setup-python@v5
1212
with:
13-
python-version: 3.8
13+
python-version: 3.13
1414
- name: Install dependencies
1515
run: make install-test
1616
- name: Lint
@@ -20,11 +20,11 @@ jobs:
2020
runs-on: ubuntu-latest
2121
strategy:
2222
matrix:
23-
python-version: ['3.8', '3.9', '3.10']
23+
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
2424
steps:
2525
- uses: actions/checkout@v4
2626
- name: Set up Python ${{ matrix.python-version }}
27-
uses: actions/setup-python@v5.1.0
27+
uses: actions/setup-python@v5
2828
with:
2929
python-version: ${{ matrix.python-version }}
3030
- name: Install dependencies
@@ -36,16 +36,16 @@ jobs:
3636
runs-on: ubuntu-latest
3737
steps:
3838
- uses: actions/checkout@v4
39-
- name: Setup Python
40-
uses: actions/setup-python@v5.1.0
39+
- name: Setup Python 13
40+
uses: actions/setup-python@v5
4141
with:
42-
python-version: 3.8
42+
python-version: 3.13
4343
- name: Install dependencies
4444
run: make install-test
4545
- name: Generate coverage report
4646
run: pytest --cov-report=xml
4747
- name: Upload coverage to Codecov
48-
uses: codecov/codecov-action@v4.1.1
48+
uses: codecov/codecov-action@v5
4949
with:
5050
file: ./coverage.xml
5151
flags: unittests

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
SHELL := bash
22
PATH := ./venv/bin:${PATH}
3-
PYTHON = python3.8
3+
PYTHON = python3.13
44
PROJECT = cuenca
55
isort = isort $(PROJECT) tests setup.py examples
6-
black = black -S -l 79 --target-version py38 $(PROJECT) tests setup.py examples
6+
black = black -S -l 79 --target-version py313 $(PROJECT) tests setup.py examples
77

88

99
all: test

cuenca/resources/api_keys.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from typing import ClassVar, Optional
33

44
from cuenca_validations.types import ApiKeyQuery, ApiKeyUpdateRequest
5+
from pydantic import ConfigDict
56

67
from ..http import Session, session as global_session
78
from .base import Creatable, Queryable, Retrievable, Updateable
@@ -12,11 +13,10 @@ class ApiKey(Creatable, Queryable, Retrievable, Updateable):
1213
_query_params: ClassVar = ApiKeyQuery
1314

1415
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={
2020
'example': {
2121
'id': 'AKNEUInh69SuKXXmK95sROwQ',
2222
'updated_at': '2021-08-24T14:15:22Z',
@@ -26,6 +26,7 @@ class Config:
2626
'user_id': 'USWqY5cvkISJOxHyEKjAKf8w',
2727
}
2828
}
29+
)
2930

3031
@property
3132
def active(self) -> bool:
@@ -74,4 +75,4 @@ def update(
7475
req = ApiKeyUpdateRequest(
7576
metadata=metadata, user_id=user_id, platform_id=platform_id
7677
)
77-
return cls._update(api_key_id, **req.dict(), session=session)
78+
return cls._update(api_key_id, **req.model_dump(), session=session)

cuenca/resources/arpc.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ class Arpc(Creatable):
2323

2424
created_at: dt.datetime
2525
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
2828

2929
@classmethod
3030
def create(
@@ -52,4 +52,4 @@ def create(
5252
unique_number=unique_number,
5353
track_data_method=track_data_method,
5454
)
55-
return cls._create(session=session, **req.dict())
55+
return cls._create(session=session, **req.model_dump())

cuenca/resources/balance_entries.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import ClassVar, TypeVar, cast
1+
from typing import ClassVar, Union, cast
22

33
from cuenca_validations.types import BalanceEntryQuery, EntryType
44

@@ -8,9 +8,7 @@
88
from .resources import retrieve_uri
99
from .service_providers import ServiceProvider
1010

11-
FundingInstrument = TypeVar(
12-
'FundingInstrument', Account, ServiceProvider, Card
13-
)
11+
FundingInstrument = Union[Account, ServiceProvider, Card]
1412

1513

1614
class BalanceEntry(Retrievable, Queryable):

cuenca/resources/base.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
TransactionQuery,
1313
TransactionStatus,
1414
)
15-
from pydantic import BaseModel, Extra
15+
from pydantic import BaseModel, ConfigDict
1616

1717
from ..exc import MultipleResultsFound, NoResultFound
1818
from ..http import Session, session as global_session
@@ -25,11 +25,12 @@ class Resource(BaseModel):
2525

2626
id: str
2727

28-
class Config:
29-
extra = Extra.ignore
28+
model_config = ConfigDict(
29+
extra="ignore",
30+
)
3031

3132
def to_dict(self):
32-
return SantizedDict(self.dict())
33+
return SantizedDict(self.model_dump())
3334

3435

3536
class Retrievable(Resource):
@@ -78,7 +79,7 @@ def _update(
7879

7980

8081
class Deactivable(Resource):
81-
deactivated_at: Optional[dt.datetime]
82+
deactivated_at: Optional[dt.datetime] = None
8283

8384
@classmethod
8485
def deactivate(
@@ -157,7 +158,7 @@ def one(
157158
**query_params: Any,
158159
) -> R_co:
159160
q = cast(Queryable, cls)._query_params(limit=2, **query_params)
160-
resp = session.get(cls._resource, q.dict())
161+
resp = session.get(cls._resource, q.model_dump())
161162
items = resp['items']
162163
len_items = len(items)
163164
if not len_items:
@@ -174,7 +175,7 @@ def first(
174175
**query_params: Any,
175176
) -> Optional[R_co]:
176177
q = cast(Queryable, cls)._query_params(limit=1, **query_params)
177-
resp = session.get(cls._resource, q.dict())
178+
resp = session.get(cls._resource, q.model_dump())
178179
try:
179180
item = resp['items'][0]
180181
except IndexError:
@@ -191,7 +192,7 @@ def count(
191192
**query_params: Any,
192193
) -> int:
193194
q = cast(Queryable, cls)._query_params(count=True, **query_params)
194-
resp = session.get(cls._resource, q.dict())
195+
resp = session.get(cls._resource, q.model_dump())
195196
return resp['count']
196197

197198
@classmethod
@@ -203,7 +204,7 @@ def all(
203204
) -> Generator[R_co, None, None]:
204205
session = session or global_session
205206
q = cast(Queryable, cls)._query_params(**query_params)
206-
next_page_uri = f'{cls._resource}?{urlencode(q.dict())}'
207+
next_page_uri = f'{cls._resource}?{urlencode(q.model_dump())}'
207208
while next_page_uri:
208209
page = session.get(next_page_uri)
209210
yield from (cls(**item) for item in page['items'])

cuenca/resources/card_activations.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class CardActivation(Creatable):
1515
created_at: dt.datetime
1616
user_id: str
1717
ip_address: str
18-
card_uri: Optional[str]
18+
card_uri: Optional[str] = None
1919
success: bool
2020

2121
@classmethod
@@ -42,7 +42,7 @@ def create(
4242
exp_year=exp_year,
4343
cvv2=cvv2,
4444
)
45-
return cls._create(session=session, **req.dict())
45+
return cls._create(session=session, **req.model_dump())
4646

4747
@property
4848
def card(self) -> Optional[Card]:

cuenca/resources/card_transactions.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import ClassVar, List, Optional, cast
1+
from typing import ClassVar, Optional, cast
22

33
from cuenca_validations.types import (
44
CardErrorType,
@@ -19,19 +19,19 @@ class CardTransaction(Transaction):
1919

2020
type: CardTransactionType
2121
network: CardNetwork
22-
related_card_transaction_uris: List[str]
22+
related_card_transaction_uris: list[str]
2323
card_uri: str
2424
card_last4: str
2525
card_type: CardType
2626
metadata: dict
27-
error_type: Optional[CardErrorType]
27+
error_type: Optional[CardErrorType] = None
2828

2929
@property # type: ignore
30-
def related_card_transactions(self) -> Optional[List['CardTransaction']]:
30+
def related_card_transactions(self) -> Optional[list['CardTransaction']]:
3131
if not self.related_card_transaction_uris:
3232
return []
3333
return cast(
34-
List['CardTransaction'],
34+
list['CardTransaction'],
3535
retrieve_uris(self.related_card_transaction_uris),
3636
)
3737

cuenca/resources/card_validations.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ class CardValidation(Creatable):
1818
user_id: str
1919
card_status: CardStatus
2020
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
2626
is_pin_attempts_exceeded: bool
2727
is_expired: bool
2828
platform_id: Optional[str] = None
@@ -51,7 +51,7 @@ def create(
5151
pin_block=pin_block,
5252
pin_attempts_exceeded=pin_attempts_exceeded,
5353
)
54-
return cls._create(session=session, **req.dict())
54+
return cls._create(session=session, **req.model_dump())
5555

5656
@property
5757
def card(self) -> Card:

0 commit comments

Comments
 (0)