Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 4 additions & 4 deletions cuenca/jwt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
import binascii
import datetime as dt
import json
from dataclasses import dataclass
from typing import TYPE_CHECKING

from pydantic import BaseModel

from .exc import MalformedJwtToken

if TYPE_CHECKING:
from .http import Session


@dataclass
class Jwt:
class Jwt(BaseModel):
expires_at: dt.datetime
token: str

Expand Down Expand Up @@ -45,4 +45,4 @@ def create(cls, session: 'Session') -> 'Jwt':
session.session.headers.pop('X-Cuenca-Token', None)
token = session.post('/token', dict())['token']
expires_at = Jwt.get_expiration_date(token)
return cls(expires_at, token)
return cls(expires_at=expires_at, token=token)
2 changes: 0 additions & 2 deletions cuenca/resources/accounts.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
from typing import ClassVar

from cuenca_validations.types import AccountQuery
from pydantic.dataclasses import dataclass

from .base import Queryable, Retrievable


@dataclass
class Account(Retrievable, Queryable):
_resource: ClassVar = 'accounts'
_query_params: ClassVar = AccountQuery
Expand Down
14 changes: 12 additions & 2 deletions cuenca/resources/api_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@
from typing import ClassVar, Optional, cast

from cuenca_validations.types import ApiKeyQuery, ApiKeyUpdateRequest
from pydantic.dataclasses import dataclass

from ..http import Session, session as global_session
from .base import Creatable, Queryable, Retrievable, Updateable


@dataclass
class ApiKey(Creatable, Queryable, Retrievable, Updateable):
_resource: ClassVar = 'api_keys'
_query_params: ClassVar = ApiKeyQuery
Expand All @@ -17,6 +15,18 @@ class ApiKey(Creatable, Queryable, Retrievable, Updateable):
deactivated_at: Optional[dt.datetime]
user_id: Optional[str]

class Config:
schema_extra = {
'example': {
'id': 'AKNEUInh69SuKXXmK95sROwQ',
'updated_at': '2021-08-24T14:15:22Z',
'created_at': '2021-08-24T14:15:22Z',
'secret': 'super-secret-random-string',
'deactivated_at': None,
'user_id': 'USWqY5cvkISJOxHyEKjAKf8w',
}
}

@property
def active(self) -> bool:
return (
Expand Down
2 changes: 0 additions & 2 deletions cuenca/resources/arpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@
from typing import ClassVar, Optional, cast

from cuenca_validations.types.requests import ARPCRequest
from pydantic.dataclasses import dataclass

from ..http import Session, session as global_session
from .base import Creatable


@dataclass
class Arpc(Creatable):
"""
An ARPC (Authorisation Response Cryptogram) is generated by the issuer
Expand Down
2 changes: 0 additions & 2 deletions cuenca/resources/balance_entries.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from typing import ClassVar, TypeVar, cast

from cuenca_validations.types import BalanceEntryQuery, EntryType
from pydantic.dataclasses import dataclass

from .accounts import Account
from .base import Queryable, Retrievable, Transaction
Expand All @@ -14,7 +13,6 @@
)


@dataclass
class BalanceEntry(Retrievable, Queryable):
_resource: ClassVar = 'balance_entries'
_query_params: ClassVar = BalanceEntryQuery
Expand Down
22 changes: 6 additions & 16 deletions cuenca/resources/base.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import base64
import datetime as dt
import json
from dataclasses import asdict, dataclass, fields
from io import BytesIO
from typing import ClassVar, Dict, Generator, Optional, Union
from urllib.parse import urlencode
Expand All @@ -13,21 +12,17 @@
TransactionQuery,
TransactionStatus,
)
from pydantic import BaseModel

from ..exc import MultipleResultsFound, NoResultFound
from ..http import Session, session as global_session


@dataclass
class Resource:
class Resource(BaseModel):
_resource: ClassVar[str]

id: str

# purely for MyPy
def __init__(self, **_): # pragma: no cover
...

@classmethod
def _from_dict(cls, obj_dict: Dict[str, Union[str, int]]) -> 'Resource':
cls._filter_excess_fields(obj_dict)
Expand All @@ -40,12 +35,14 @@ def _filter_excess_fields(cls, obj_dict):
method allows the API to add fields in the response body without
breaking the client
"""
excess = set(obj_dict.keys()) - {f.name for f in fields(cls)}
excess = set(obj_dict.keys()) - set(
cls.schema().get("properties").keys()
)
for f in excess:
del obj_dict[f]

def to_dict(self):
return asdict(self, dict_factory=SantizedDict)
return SantizedDict(self.dict())


class Retrievable(Resource):
Expand All @@ -69,7 +66,6 @@ def _create(cls, *, session: Session = global_session, **data) -> Resource:
return cls._from_dict(resp)


@dataclass
class Updateable(Resource):

updated_at: dt.datetime
Expand All @@ -82,7 +78,6 @@ def _update(
return cls._from_dict(resp)


@dataclass
class Deactivable(Resource):
deactivated_at: Optional[dt.datetime]

Expand All @@ -98,7 +93,6 @@ def is_active(self):
return not self.deactivated_at


@dataclass
class Downloadable(Resource):
@classmethod
def download(
Expand All @@ -124,7 +118,6 @@ def xml(self) -> bytes:
return self.download(self, file_format=FileFormat.xml).read()


@dataclass
class Uploadable(Resource):
@classmethod
def _upload(
Expand All @@ -148,7 +141,6 @@ def _upload(
return cls._from_dict(json.loads(resp))


@dataclass
class Queryable(Resource):
_query_params: ClassVar = QueryParams

Expand Down Expand Up @@ -203,7 +195,6 @@ def all(
next_page_uri = page['next_page_uri']


@dataclass
class Transaction(Retrievable, Queryable):
_query_params: ClassVar = TransactionQuery

Expand All @@ -213,7 +204,6 @@ class Transaction(Retrievable, Queryable):
descriptor: str # how it appears for the customer


@dataclass
class Wallet(Creatable, Deactivable, Retrievable, Queryable):
user_id: str
balance: int
Expand Down
2 changes: 0 additions & 2 deletions cuenca/resources/bill_payments.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
from typing import ClassVar, cast

from cuenca_validations.types import BillPaymentQuery
from pydantic.dataclasses import dataclass

from .base import Transaction
from .resources import retrieve_uri
from .service_providers import ServiceProvider


@dataclass
class BillPayment(Transaction):
_resource: ClassVar = 'bill_payments'
_query_params: ClassVar = BillPaymentQuery
Expand Down
2 changes: 0 additions & 2 deletions cuenca/resources/card_activations.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import datetime as dt
from dataclasses import dataclass
from typing import ClassVar, Optional, cast

from cuenca_validations.types.requests import CardActivationRequest
Expand All @@ -10,7 +9,6 @@
from .resources import retrieve_uri


@dataclass
class CardActivation(Creatable):
_resource: ClassVar = 'card_activations'

Expand Down
2 changes: 0 additions & 2 deletions cuenca/resources/card_transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@
CardTransactionType,
CardType,
)
from pydantic.dataclasses import dataclass

from .base import Transaction
from .cards import Card
from .resources import retrieve_uri, retrieve_uris


@dataclass
class CardTransaction(Transaction):
_resource: ClassVar = 'card_transactions'
_query_params: ClassVar = CardTransactionQuery
Expand Down
2 changes: 0 additions & 2 deletions cuenca/resources/card_validations.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@

from cuenca_validations.types import CardStatus, CardType
from cuenca_validations.types.requests import CardValidationRequest
from pydantic.dataclasses import dataclass

from ..http import Session, session as global_session
from .base import Creatable
from .cards import Card
from .resources import retrieve_uri


@dataclass
class CardValidation(Creatable):
_resource: ClassVar = 'card_validations'

Expand Down
2 changes: 0 additions & 2 deletions cuenca/resources/cards.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
)
from cuenca_validations.types.queries import CardQuery
from cuenca_validations.types.requests import CardRequest, CardUpdateRequest
from pydantic.dataclasses import dataclass

from cuenca.resources.base import Creatable, Queryable, Retrievable, Updateable

Expand All @@ -17,7 +16,6 @@
MAX_PIN_ATTEMPTS = 3


@dataclass
class Card(Retrievable, Queryable, Creatable, Updateable):
_resource: ClassVar = 'cards'
_query_params: ClassVar = CardQuery
Expand Down
2 changes: 0 additions & 2 deletions cuenca/resources/commissions.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
from typing import ClassVar, cast

from cuenca_validations.types import CommissionType, EntryType
from pydantic.dataclasses import dataclass

from .base import Transaction
from .resources import retrieve_uri

mapper = {CommissionType.cash_deposit: EntryType.credit}


@dataclass
class Commission(Transaction):
_resource: ClassVar = 'commissions'

Expand Down
65 changes: 53 additions & 12 deletions cuenca/resources/curp_validations.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,72 @@
State,
)
from cuenca_validations.types.identities import CurpField
from pydantic.dataclasses import dataclass

from ..http import Session, session as global_session
from .base import Creatable, Retrievable


@dataclass
class CurpValidation(Creatable, Retrievable):
_resource: ClassVar = 'curp_validations'

created_at: dt.datetime
names: Optional[str]
first_surname: Optional[str]
second_surname: Optional[str]
date_of_birth: Optional[dt.date]
country_of_birth: Optional[Country]
state_of_birth: Optional[State]
gender: Optional[Gender]
nationality: Optional[Country]
manual_curp: Optional[CurpField]
names: Optional[str] = None
first_surname: Optional[str] = None
second_surname: Optional[str] = None
date_of_birth: Optional[dt.date] = None
country_of_birth: Optional[Country] = None
state_of_birth: Optional[State] = None
gender: Optional[Gender] = None
nationality: Optional[Country] = None
manual_curp: Optional[CurpField] = None
calculated_curp: CurpField
validated_curp: Optional[CurpField]
validated_curp: Optional[CurpField] = None
renapo_curp_match: bool
renapo_full_match: bool

class Config:
fields = {
'names': {'description': 'Official name from Renapo'},
'first_surname': {'description': 'Official surname from Renapo'},
'second_surname': {'description': 'Official surname from Renapo'},
'country_of_birth': {'description': 'In format ISO 3166 Alpha-2'},
'state_of_birth': {'description': 'In format ISO 3166 Alpha-2'},
'nationality': {'description': 'In format ISO 3166 Alpha-2'},
'manual_curp': {'description': 'curp provided in request'},
'calculated_curp': {
'description': 'Calculated CURP based on request data'
},
'validated_curp': {
'description': 'CURP validated in Renapo, null if not exists'
},
'renapo_curp_match': {
'description': 'True if CURP exists and is valid'
},
'renapo_full_match': {
'description': 'True if all fields provided match the response'
' from RENAPO. Accents in names are ignored'
},
}
schema_extra = {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

usar un solo tipo de comillas

Copy link
Copy Markdown
Member Author

@rogelioLpz rogelioLpz Jun 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

El json de los example lo puse con comillas dobles porque es el formato de json. Se puede poner comillas simples pero me parecio mejor ponerlo así para que si alguien guste lo queda tomar de ahi y usarlo en otro lado tenga el standar de json y no tenga que estar editandolo.
No se que opines @Felipaoo ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aunque quieras usarlo como json tendrian que cambiar None por null y True por true. Mejor ser uniformes con la convención que usamos

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arre 👍

'example': {
'id': 'CVNEUInh69SuKXXmK95sROwQ',
'created_at': '2019-08-24T14:15:22Z',
'names': 'Guillermo',
'first_surname': 'Gonzales',
'second_surname': 'Camarena',
'date_of_birth': '1965-04-18',
'country_of_birth': 'MX',
'state_of_birth': 'VZ',
'gender': 'male',
'nationality': 'MX',
'manual_curp': None,
'calculated_curp': 'GOCG650418HVZNML08',
'validated_curp': 'GOCG650418HVZNML08',
'renapo_curp_match': True,
'renapo_full_match': True,
}
}

@classmethod
def create(
cls,
Expand Down
2 changes: 0 additions & 2 deletions cuenca/resources/deposits.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
from typing import ClassVar, Optional, cast

from cuenca_validations.types import DepositNetwork, DepositQuery
from pydantic.dataclasses import dataclass

from .accounts import Account
from .base import Transaction
from .resources import retrieve_uri


@dataclass
class Deposit(Transaction):
_resource: ClassVar = 'deposits'
_query_params: ClassVar = DepositQuery
Expand Down
Loading