Skip to content

Commit 098522e

Browse files
author
Ricardo
authored
Customized session in each request (#103)
* Upgrade cuenca-validations * Add card to init * Add session as optional parameter * Add test for session * Version * Add missing cassette * default_session => global_session * Using global_session as default parameter * Using positional argumens * Fix versions * Use kwargs * Another missing cases
1 parent c523e1a commit 098522e

File tree

7 files changed

+112
-17
lines changed

7 files changed

+112
-17
lines changed

cuenca/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
'Account',
55
'BalanceEntry',
66
'BillPayment',
7+
'Card',
78
'CardTransaction',
89
'Commission',
910
'Deposit',
@@ -20,6 +21,7 @@
2021
ApiKey,
2122
BalanceEntry,
2223
BillPayment,
24+
Card,
2325
CardTransaction,
2426
Commission,
2527
Deposit,

cuenca/resources/base.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
)
1212

1313
from ..exc import MultipleResultsFound, NoResultFound
14-
from ..http import session
14+
from ..http import Session, session as global_session
1515

1616

1717
@dataclass
@@ -46,19 +46,21 @@ def to_dict(self):
4646

4747
class Retrievable(Resource):
4848
@classmethod
49-
def retrieve(cls, id: str) -> Resource:
49+
def retrieve(
50+
cls, id: str, *, session: Session = global_session
51+
) -> Resource:
5052
resp = session.get(f'/{cls._resource}/{id}')
5153
return cls._from_dict(resp)
5254

53-
def refresh(self):
54-
new = self.retrieve(self.id)
55+
def refresh(self, *, session: Session = global_session):
56+
new = self.retrieve(self.id, session=session)
5557
for attr, value in new.__dict__.items():
5658
setattr(self, attr, value)
5759

5860

5961
class Creatable(Resource):
6062
@classmethod
61-
def _create(cls, **data) -> Resource:
63+
def _create(cls, *, session: Session = global_session, **data) -> Resource:
6264
resp = session.post(cls._resource, data)
6365
return cls._from_dict(resp)
6466

@@ -68,7 +70,9 @@ class Updateable(Resource):
6870
updated_at: dt.datetime
6971

7072
@classmethod
71-
def _update(cls, id: str, **data) -> Resource:
73+
def _update(
74+
cls, id: str, *, session: Session = global_session, **data
75+
) -> Resource:
7276
resp = session.patch(f'/{cls._resource}/{id}', data)
7377
return cls._from_dict(resp)
7478

@@ -80,7 +84,9 @@ class Queryable(Resource):
8084
created_at: dt.datetime
8185

8286
@classmethod
83-
def one(cls, **query_params) -> Resource:
87+
def one(
88+
cls, *, session: Session = global_session, **query_params
89+
) -> Resource:
8490
q = cls._query_params(limit=2, **query_params)
8591
resp = session.get(cls._resource, q.dict())
8692
items = resp['items']
@@ -92,7 +98,9 @@ def one(cls, **query_params) -> Resource:
9298
return cls._from_dict(items[0])
9399

94100
@classmethod
95-
def first(cls, **query_params) -> Optional[Resource]:
101+
def first(
102+
cls, *, session: Session = global_session, **query_params
103+
) -> Optional[Resource]:
96104
q = cls._query_params(limit=1, **query_params)
97105
resp = session.get(cls._resource, q.dict())
98106
try:
@@ -104,13 +112,18 @@ def first(cls, **query_params) -> Optional[Resource]:
104112
return rv
105113

106114
@classmethod
107-
def count(cls, **query_params) -> int:
115+
def count(
116+
cls, *, session: Session = global_session, **query_params
117+
) -> int:
108118
q = cls._query_params(count=True, **query_params)
109119
resp = session.get(cls._resource, q.dict())
110120
return resp['count']
111121

112122
@classmethod
113-
def all(cls, **query_params) -> Generator[Resource, None, None]:
123+
def all(
124+
cls, *, session: Session = global_session, **query_params
125+
) -> Generator[Resource, None, None]:
126+
session = session or global_session
114127
q = cls._query_params(**query_params)
115128
next_page_uri = f'{cls._resource}?{urlencode(q.dict())}'
116129
while next_page_uri:

cuenca/resources/cards.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

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

10-
from ..http import session
10+
from ..http import Session, session as global_session
1111

1212

1313
@dataclass
@@ -25,7 +25,13 @@ class Card(Retrievable, Queryable, Creatable, Updateable):
2525
status: CardStatus
2626

2727
@classmethod
28-
def create(cls, ledger_account_id: str, user_id: str) -> 'Card':
28+
def create(
29+
cls,
30+
ledger_account_id: str,
31+
user_id: str,
32+
*,
33+
session: Session = global_session,
34+
) -> 'Card':
2935
"""
3036
Assigns user_id and ledger_account_id to a existing card
3137
@@ -34,7 +40,7 @@ def create(cls, ledger_account_id: str, user_id: str) -> 'Card':
3440
:return: New assigned card
3541
"""
3642
req = CardRequest(ledger_account_id=ledger_account_id, user_id=user_id)
37-
return cast('Card', cls._create(**req.dict()))
43+
return cast('Card', cls._create(session=session, **req.dict()))
3844

3945
@classmethod
4046
def update(
@@ -43,6 +49,8 @@ def update(
4349
user_id: Optional[str] = None,
4450
ledger_account_id: Optional[str] = None,
4551
status: Optional[CardStatus] = None,
52+
*,
53+
session: Session = global_session,
4654
):
4755
"""
4856
Updates card properties that are not sensitive or fixed data. It allows
@@ -57,11 +65,15 @@ def update(
5765
req = CardUpdateRequest(
5866
user_id=user_id, ledger_account_id=ledger_account_id, status=status
5967
)
60-
resp = cls._update(card_id, **req.dict(exclude_none=True))
68+
resp = cls._update(
69+
card_id, session=session, **req.dict(exclude_none=True)
70+
)
6171
return cast('Card', resp)
6272

6373
@classmethod
64-
def deactivate(cls, card_id: str) -> 'Card':
74+
def deactivate(
75+
cls, card_id: str, *, session: Session = global_session
76+
) -> 'Card':
6577
"""
6678
Deactivates a card
6779
"""

cuenca/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
__version__ = '0.4.1'
1+
__version__ = '0.4.2'
22
CLIENT_VERSION = __version__
33
API_VERSION = '2020-03-19'

tests/http/test_client.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
from unittest.mock import MagicMock, patch
2+
13
import pytest
24

35
from cuenca.exc import CuencaResponseException
46
from cuenca.http.client import Session
7+
from cuenca.resources import Card
58

69

710
@pytest.mark.vcr
@@ -56,3 +59,18 @@ def test_overrides_aws_creds():
5659
assert session.auth.aws_secret_access_key == 'new_aws_secret'
5760
assert session.auth.aws_access_key == 'new_aws_key'
5861
assert session.auth.aws_region == 'us-east-2'
62+
63+
64+
@patch('cuenca.http.client.requests.Session.request')
65+
def test_overrides_session(mock_request):
66+
magic_mock = MagicMock()
67+
magic_mock.json.return_value = dict(items=[])
68+
mock_request.return_value = magic_mock
69+
session = Session()
70+
session.configure(
71+
api_key='USER_API_KEY', api_secret='USER_SECRET', sandbox=True
72+
)
73+
Card.first(user_id='USER_ID', session=session)
74+
mock_request.assert_called_once()
75+
_, kwargs = mock_request.call_args_list[0]
76+
assert kwargs['auth'] == session.auth
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
interactions:
2+
- request:
3+
body: null
4+
headers:
5+
Accept:
6+
- '*/*'
7+
Accept-Encoding:
8+
- gzip, deflate
9+
Authorization:
10+
- DUMMY
11+
Connection:
12+
- keep-alive
13+
User-Agent:
14+
- cuenca-python/0.4.3.dev1
15+
X-Cuenca-Api-Version:
16+
- '2020-03-19'
17+
method: GET
18+
uri: https://sandbox.cuenca.com/cards?user_id=US1237
19+
response:
20+
body:
21+
string: '{"items":[{"id":"CACs_Itr72QfaS6NSPhwanNA","created_at":"2020-09-18T22:05:53.233000","updated_at":"2020-09-18T22:05:53.394000","user_id":"US1237","ledger_account_id":"LAnbstynwl3","number":"4231450000000012","exp_month":9,"exp_year":2025,"cvv2":"123","type":"virtual","status":"active","batch":null,"manufacturer":null,"cvv":null,"icvv":null,"pin":null}],"next_page_uri":null}'
22+
headers:
23+
Connection:
24+
- keep-alive
25+
Content-Length:
26+
- '394'
27+
Content-Type:
28+
- application/json
29+
Date:
30+
- Wed, 06 Jan 2021 22:19:47 GMT
31+
X-Amzn-Trace-Id:
32+
- Root=1-5ff63783-637d9bf30645c2f614f3cd99;Sampled=0
33+
x-amz-apigw-id:
34+
- Yv2cgGttCYcFuSw=
35+
x-amzn-Remapped-Connection:
36+
- keep-alive
37+
x-amzn-Remapped-Content-Length:
38+
- '394'
39+
x-amzn-Remapped-Date:
40+
- Wed, 06 Jan 2021 22:19:47 GMT
41+
x-amzn-Remapped-Server:
42+
- nginx/1.18.0
43+
x-amzn-Remapped-x-amzn-RequestId:
44+
- c3a609d7-4e21-4221-a088-0339e5eb2b1b
45+
x-amzn-RequestId:
46+
- 37f91dcf-3e56-4039-8401-5f693c9915af
47+
status:
48+
code: 200
49+
message: OK
50+
version: 1

tests/resources/test_cards.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def test_card_one_errors():
5959
@pytest.mark.vcr
6060
def test_card_all():
6161
cards = Card.all(user_id=user_id)
62-
assert len([cards]) == 1
62+
assert len(list(cards)) == 1
6363

6464

6565
@pytest.mark.vcr

0 commit comments

Comments
 (0)