Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update/pydantic v2 #410

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
6abe75c
Update dependencies to support Pydantic v2
Dec 22, 2024
12a8556
Refactor type hints and casting in resource files
Dec 22, 2024
ff94458
Remove Python 3.10 from GitHub Actions workflow matrix for test
Dec 22, 2024
e96cfb6
Update version to 2.0.0.dev1 in version.py
Dec 22, 2024
19c5838
Update dependencies and GitHub Actions workflow
Dec 30, 2024
622e6cf
Fix VCRHTTPResponse version_string AttributeError in tests
Dec 30, 2024
9c10590
Removed temporary patch for VCRHTTPResponse version_string from conft…
Dec 30, 2024
aeca28d
Update Python version to 3.13, adjust dependencies
Dec 31, 2024
63823a5
Update version to 2.0.0.dev2
Dec 31, 2024
11bb963
Update cuenca-validations dependency to version 2.0.0.dev9 in setup.py
Jan 2, 2025
8bf739a
Increment version to 2.0.0.dev3 in version.py
Jan 2, 2025
4bc3a54
Refactor CuencaResponseException to use dataclass and update fieldnam…
Jan 6, 2025
ceb1d41
Refactor URL fields in endpoints and sessions to use annotated types …
Jan 6, 2025
3c0f14f
Refactor retrieve_uris function to use a simple for loop instead of T…
Jan 6, 2025
53add20
Update test and main dependencies to latest versions
Jan 8, 2025
e0d54d3
Refactor API resource methods to use model_dump() instead of dict()
Jan 8, 2025
6a41ff9
Update card activation test values and cassette data
Jan 8, 2025
f7c54f8
style: fix formatting according to lint rules
Jan 8, 2025
e5070d4
refactor: change card number type to PaymentCardNumber for improved v…
Jan 8, 2025
7ea8e3d
refactor: replace type checks with isinstance
Jan 8, 2025
304c405
chore: update GitHub Actions workflows to use latest versions of setu…
Jan 8, 2025
42d9677
refactor: remove unnecessary constructor in CardTransaction class
Jan 8, 2025
5e2c585
refactor: update type hints to use built-in `list` and `dict`
Jan 9, 2025
2c6ce31
refactor: replace HttpUrl and AnyUrl with cuenca_validations.types
Jan 9, 2025
19081ee
chore: update types-requests dependency version
Jan 9, 2025
1712d33
refactor: update type hints to use built-in `list`
Jan 9, 2025
f295c73
refactor: simplify success_url and failure_url type hints in Session …
Jan 9, 2025
ebe078b
chore: update cuenca-validations dependency to version 2.0.0.dev12
Jan 9, 2025
f81c8bf
chore: bump version to 2.0.0.dev4
Jan 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/[email protected]
- name: Set up Python 3.8
uses: actions/setup-python@v2.3.1
- name: Set up Python 3.13
uses: actions/setup-python@v5.1.0
with:
python-version: 3.8
python-version: 3.13
- name: Install dependencies
run: pip install -qU setuptools wheel twine
- name: Generating distribution archives
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
- name: Set up Python
uses: actions/[email protected]
with:
python-version: 3.8
python-version: 3.13
- name: Install dependencies
run: make install-test
- name: Lint
Expand All @@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10']
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -39,13 +39,13 @@ jobs:
- name: Setup Python
uses: actions/[email protected]
with:
python-version: 3.8
python-version: 3.13
- name: Install dependencies
run: make install-test
- name: Generate coverage report
run: pytest --cov-report=xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4.1.1
uses: codecov/codecov-action@v5
with:
file: ./coverage.xml
flags: unittests
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
SHELL := bash
PATH := ./venv/bin:${PATH}
PYTHON = python3.8
PYTHON = python3.13
PROJECT = cuenca
isort = isort $(PROJECT) tests setup.py examples
black = black -S -l 79 --target-version py38 $(PROJECT) tests setup.py examples
black = black -S -l 79 --target-version py313 $(PROJECT) tests setup.py examples
gmorales96 marked this conversation as resolved.
Show resolved Hide resolved


all: test
Expand Down
13 changes: 7 additions & 6 deletions cuenca/resources/api_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import ClassVar, Optional, cast

from cuenca_validations.types import ApiKeyQuery, ApiKeyUpdateRequest
from pydantic import ConfigDict

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

secret: str
deactivated_at: Optional[dt.datetime]
user_id: Optional[str]

class Config:
schema_extra = {
deactivated_at: Optional[dt.datetime] = None
user_id: Optional[str] = None
model_config = ConfigDict(
json_schema_extra={
'example': {
'id': 'AKNEUInh69SuKXXmK95sROwQ',
'updated_at': '2021-08-24T14:15:22Z',
Expand All @@ -26,6 +26,7 @@ class Config:
'user_id': 'USWqY5cvkISJOxHyEKjAKf8w',
}
}
)

@property
def active(self) -> bool:
Expand Down Expand Up @@ -74,5 +75,5 @@ def update(
req = ApiKeyUpdateRequest(
metadata=metadata, user_id=user_id, platform_id=platform_id
)
resp = cls._update(api_key_id, **req.dict(), session=session)
resp = cls._update(api_key_id, **req.model_dump(), session=session)
return cast('ApiKey', resp)
9 changes: 5 additions & 4 deletions cuenca/resources/arpc.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import datetime as dt
from typing import ClassVar, Optional, cast

from cuenca_validations.types.enums import TrackDataMethod
from cuenca_validations.types.requests import ARPCRequest

from ..http import Session, session as global_session
Expand All @@ -23,8 +24,8 @@ class Arpc(Creatable):

created_at: dt.datetime
card_uri: str
is_valid_arqc: Optional[bool]
arpc: Optional[str]
is_valid_arqc: Optional[bool] = None
arpc: Optional[str] = None

@classmethod
def create(
Expand All @@ -50,6 +51,6 @@ def create(
transaction_counter=transaction_counter,
pan_sequence=pan_sequence,
unique_number=unique_number,
track_data_method=track_data_method,
track_data_method=cast(TrackDataMethod, track_data_method),
)
return cast('Arpc', cls._create(session=session, **req.dict()))
return cast('Arpc', cls._create(session=session, **req.model_dump()))
6 changes: 2 additions & 4 deletions cuenca/resources/balance_entries.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import ClassVar, TypeVar, cast
from typing import ClassVar, Union, cast

from cuenca_validations.types import BalanceEntryQuery, EntryType

Expand All @@ -8,9 +8,7 @@
from .resources import retrieve_uri
from .service_providers import ServiceProvider

FundingInstrument = TypeVar(
'FundingInstrument', Account, ServiceProvider, Card
)
FundingInstrument = Union[Account, ServiceProvider, Card]


class BalanceEntry(Retrievable, Queryable):
Expand Down
16 changes: 8 additions & 8 deletions cuenca/resources/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import datetime as dt
import json
from io import BytesIO
from typing import ClassVar, Dict, Generator, Optional, Union
from typing import Any, ClassVar, Generator, Optional
from urllib.parse import urlencode

from cuenca_validations.types import (
Expand All @@ -24,7 +24,7 @@ class Resource(BaseModel):
id: str

@classmethod
def _from_dict(cls, obj_dict: Dict[str, Union[str, int]]) -> 'Resource':
def _from_dict(cls, obj_dict: dict[str, Any]) -> 'Resource':
cls._filter_excess_fields(obj_dict)
return cls(**obj_dict)

Expand All @@ -42,7 +42,7 @@ def _filter_excess_fields(cls, obj_dict):
del obj_dict[f]

def to_dict(self):
return SantizedDict(self.dict())
return SantizedDict(self.model_dump())
gmorales96 marked this conversation as resolved.
Show resolved Hide resolved


class Retrievable(Resource):
Expand Down Expand Up @@ -79,7 +79,7 @@ def _update(


class Deactivable(Resource):
deactivated_at: Optional[dt.datetime]
deactivated_at: Optional[dt.datetime] = None

@classmethod
def deactivate(
Expand Down Expand Up @@ -151,7 +151,7 @@ def one(
cls, *, session: Session = global_session, **query_params
) -> Resource:
q = cls._query_params(limit=2, **query_params)
resp = session.get(cls._resource, q.dict())
resp = session.get(cls._resource, q.model_dump())
items = resp['items']
len_items = len(items)
if not len_items:
Expand All @@ -165,7 +165,7 @@ def first(
cls, *, session: Session = global_session, **query_params
) -> Optional[Resource]:
q = cls._query_params(limit=1, **query_params)
resp = session.get(cls._resource, q.dict())
resp = session.get(cls._resource, q.model_dump())
try:
item = resp['items'][0]
except IndexError:
Expand All @@ -179,7 +179,7 @@ def count(
cls, *, session: Session = global_session, **query_params
) -> int:
q = cls._query_params(count=True, **query_params)
resp = session.get(cls._resource, q.dict())
resp = session.get(cls._resource, q.model_dump())
return resp['count']

@classmethod
Expand All @@ -188,7 +188,7 @@ def all(
) -> Generator[Resource, None, None]:
session = session or global_session
q = cls._query_params(**query_params)
next_page_uri = f'{cls._resource}?{urlencode(q.dict())}'
next_page_uri = f'{cls._resource}?{urlencode(q.model_dump())}'
while next_page_uri:
page = session.get(next_page_uri)
yield from (cls._from_dict(item) for item in page['items'])
Expand Down
7 changes: 4 additions & 3 deletions cuenca/resources/card_activations.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import ClassVar, Optional, cast

from cuenca_validations.types.requests import CardActivationRequest
from pydantic_extra_types.payment import PaymentCardNumber

from ..http import Session, session as global_session
from .base import Creatable
Expand All @@ -15,13 +16,13 @@ class CardActivation(Creatable):
created_at: dt.datetime
user_id: str
ip_address: str
card_uri: Optional[str]
card_uri: Optional[str] = None
success: bool

@classmethod
def create(
cls,
number: str,
number: PaymentCardNumber,
exp_month: int,
exp_year: int,
cvv2: str,
Expand All @@ -43,7 +44,7 @@ def create(
cvv2=cvv2,
)
return cast(
'CardActivation', cls._create(session=session, **req.dict())
'CardActivation', cls._create(session=session, **req.model_dump())
)

@property
Expand Down
11 changes: 6 additions & 5 deletions cuenca/resources/card_transactions.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import ClassVar, List, Optional, cast
from typing import ClassVar, Optional, cast

from cuenca_validations.types import (
CardErrorType,
Expand All @@ -14,24 +14,25 @@


class CardTransaction(Transaction):

_resource: ClassVar = 'card_transactions'
_query_params: ClassVar = CardTransactionQuery

type: CardTransactionType
network: CardNetwork
related_card_transaction_uris: List[str]
related_card_transaction_uris: list[str]
card_uri: str
card_last4: str
card_type: CardType
metadata: dict
error_type: Optional[CardErrorType]
error_type: Optional[CardErrorType] = None

@property # type: ignore
def related_card_transactions(self) -> Optional[List['CardTransaction']]:
def related_card_transactions(self) -> Optional[list['CardTransaction']]:
if not self.related_card_transaction_uris:
return []
return cast(
List['CardTransaction'],
list['CardTransaction'],
retrieve_uris(self.related_card_transaction_uris),
)

Expand Down
14 changes: 7 additions & 7 deletions cuenca/resources/card_validations.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ class CardValidation(Creatable):
user_id: str
card_status: CardStatus
card_type: CardType
is_valid_cvv: Optional[bool]
is_valid_cvv2: Optional[bool]
is_valid_icvv: Optional[bool]
is_valid_pin_block: Optional[bool]
is_valid_exp_date: Optional[bool]
is_valid_cvv: Optional[bool] = None
is_valid_cvv2: Optional[bool] = None
is_valid_icvv: Optional[bool] = None
is_valid_pin_block: Optional[bool] = None
is_valid_exp_date: Optional[bool] = None
is_pin_attempts_exceeded: bool
is_expired: bool
platform_id: Optional[str] = None
Expand All @@ -37,7 +37,7 @@ def create(
exp_month: Optional[int] = None,
exp_year: Optional[int] = None,
pin_block: Optional[str] = None,
pin_attempts_exceeded: Optional[str] = None,
pin_attempts_exceeded: Optional[bool] = None,
*,
session: Session = global_session,
) -> 'CardValidation':
Expand All @@ -52,7 +52,7 @@ def create(
pin_attempts_exceeded=pin_attempts_exceeded,
)
return cast(
'CardValidation', cls._create(session=session, **req.dict())
'CardValidation', cls._create(session=session, **req.model_dump())
)

@property
Expand Down
8 changes: 4 additions & 4 deletions cuenca/resources/cards.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ class Card(Retrievable, Queryable, Creatable, Updateable):
_resource: ClassVar = 'cards'
_query_params: ClassVar = CardQuery

user_id: Optional[str]
user_id: Optional[str] = None
number: str
exp_month: int
exp_year: int
cvv2: str
pin: Optional[str]
pin: Optional[str] = None
type: CardType
status: CardStatus
issuer: CardIssuer
Expand Down Expand Up @@ -81,7 +81,7 @@ def create(
card_holder_user_id=card_holder_user_id,
is_dynamic_cvv=is_dynamic_cvv,
)
return cast('Card', cls._create(session=session, **req.dict()))
return cast('Card', cls._create(session=session, **req.model_dump()))

@classmethod
def update(
Expand All @@ -106,7 +106,7 @@ def update(
req = CardUpdateRequest(
status=status, pin_block=pin_block, is_dynamic_cvv=is_dynamic_cvv
)
resp = cls._update(card_id, session=session, **req.dict())
resp = cls._update(card_id, session=session, **req.model_dump())
return cast('Card', resp)

@classmethod
Expand Down
Loading
Loading