Skip to content

Commit f6202e4

Browse files
committed
Merge branch 'release/1.14.18'
2 parents 78390d2 + 269aed4 commit f6202e4

24 files changed

+263
-258
lines changed

CHANGELOG.md

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,25 @@
22

33
## [Unreleased](https://github.com/bunq/sdk_python/tree/HEAD)
44

5-
[Full Changelog](https://github.com/bunq/sdk_python/compare/1.14.0...HEAD)
5+
[Full Changelog](https://github.com/bunq/sdk_python/compare/1.14.1...HEAD)
6+
7+
**Implemented enhancements:**
8+
9+
- Replace /sandbox-user with /sandbox-user-person and /sandbox-user-company [\#151](https://github.com/bunq/sdk_python/issues/151)
10+
11+
**Fixed bugs:**
12+
13+
- Remove \_\_get\_user\_object call immediately after UserContext creation \(reduce rate-limit hits\) [\#149](https://github.com/bunq/sdk_python/issues/149)
14+
- Feature/sdk python\#149 save/restore User in SessionContext from file [\#153](https://github.com/bunq/sdk_python/pull/153) ([angelomelonas](https://github.com/angelomelonas))
15+
16+
**Merged pull requests:**
17+
18+
- feature/sdk\_python\#151 Deprecated SandboxUser and replaced it with SandboxUserPerson/Company [\#152](https://github.com/bunq/sdk_python/pull/152) ([angelomelonas](https://github.com/angelomelonas))
19+
- feature/sdk\_python\#149 Remove get\_user\_object call directly after UserContext creation [\#150](https://github.com/bunq/sdk_python/pull/150) ([angelomelonas](https://github.com/angelomelonas))
20+
21+
## [1.14.1](https://github.com/bunq/sdk_python/tree/1.14.1) (2020-08-20)
22+
23+
[Full Changelog](https://github.com/bunq/sdk_python/compare/1.14.0...1.14.1)
624

725
**Implemented enhancements:**
826

@@ -126,32 +144,18 @@
126144

127145
**Implemented enhancements:**
128146

129-
- \[python\] Update examples in readme [\#87](https://github.com/bunq/sdk_python/issues/87)
130-
- It is not possible to refresh userContext data [\#79](https://github.com/bunq/sdk_python/issues/79)
131-
- Optimise test framework [\#78](https://github.com/bunq/sdk_python/issues/78)
132-
- Add more example scripts [\#68](https://github.com/bunq/sdk_python/issues/68)
133-
- Auto save the session after automatic session reset has been executed  [\#65](https://github.com/bunq/sdk_python/issues/65)
134-
- Add optional parameters to constructor  [\#55](https://github.com/bunq/sdk_python/issues/55)
135-
- Monetary account joint cannot be retrieved. [\#52](https://github.com/bunq/sdk_python/issues/52)
136-
- Endpoint HTTP methods should not be static [\#41](https://github.com/bunq/sdk_python/issues/41)
137-
- Name field for pointer counterparty [\#29](https://github.com/bunq/sdk_python/issues/29)
138147
- Added method to refresh user context data. \(bunq/sdk\_python\#79\) [\#80](https://github.com/bunq/sdk_python/pull/80) ([OGKevin](https://github.com/OGKevin))
139148

140-
**Fixed bugs:**
141-
142-
- bunq-sdk 0.12.4 package on PyPI contains code from 0.13.0 [\#88](https://github.com/bunq/sdk_python/issues/88)
143-
- Can not construct a BunqMeTabEntry to create a BunqMeTab [\#77](https://github.com/bunq/sdk_python/issues/77)
144-
- ImportError: cannot import name 'JSONDecodeError' [\#72](https://github.com/bunq/sdk_python/issues/72)
145-
146149
**Closed issues:**
147150

151+
- Add oath support. [\#102](https://github.com/bunq/sdk_python/issues/102)
148152
- Update Sandbox API key procedure [\#100](https://github.com/bunq/sdk_python/issues/100)
149-
- Python 3.4.2: ImportError: cannot import name 'context' \(cyclic import?\) [\#73](https://github.com/bunq/sdk_python/issues/73)
150153

151154
**Merged pull requests:**
152155

153156
- Oauth bunq/sdk\_python\#102 [\#103](https://github.com/bunq/sdk_python/pull/103) ([OGKevin](https://github.com/OGKevin))
154157
- Update Sandbox API key procedure. \(bunq/sdk\_python\#100\) [\#101](https://github.com/bunq/sdk_python/pull/101) ([sandervdo](https://github.com/sandervdo))
158+
- Move to new sandbox bunq/sdk\_python\#98 [\#99](https://github.com/bunq/sdk_python/pull/99) ([OGKevin](https://github.com/OGKevin))
155159
- Updated readme to point to tinker for examples. \(bunq/sdk\_python\#87\) [\#95](https://github.com/bunq/sdk_python/pull/95) ([OGKevin](https://github.com/OGKevin))
156160
- Fix monetary account joint retrieval bunq/sdk\_python\#52 [\#94](https://github.com/bunq/sdk_python/pull/94) ([OGKevin](https://github.com/OGKevin))
157161
- Fix supperfouls fields error bunq/sdk\_python\#77 [\#91](https://github.com/bunq/sdk_python/pull/91) ([OGKevin](https://github.com/OGKevin))
@@ -165,19 +169,33 @@
165169

166170
[Full Changelog](https://github.com/bunq/sdk_python/compare/0.13.0...0.13.1)
167171

172+
**Implemented enhancements:**
173+
174+
- \[python\] Update examples in readme [\#87](https://github.com/bunq/sdk_python/issues/87)
175+
- It is not possible to refresh userContext data [\#79](https://github.com/bunq/sdk_python/issues/79)
176+
- Optimise test framework [\#78](https://github.com/bunq/sdk_python/issues/78)
177+
- Add more example scripts [\#68](https://github.com/bunq/sdk_python/issues/68)
178+
- Auto save the session after automatic session reset has been executed  [\#65](https://github.com/bunq/sdk_python/issues/65)
179+
- Add optional parameters to constructor  [\#55](https://github.com/bunq/sdk_python/issues/55)
180+
- Monetary account joint cannot be retrieved. [\#52](https://github.com/bunq/sdk_python/issues/52)
181+
- Endpoint HTTP methods should not be static [\#41](https://github.com/bunq/sdk_python/issues/41)
182+
- Name field for pointer counterparty [\#29](https://github.com/bunq/sdk_python/issues/29)
183+
184+
**Fixed bugs:**
185+
186+
- bunq-sdk 0.12.4 package on PyPI contains code from 0.13.0 [\#88](https://github.com/bunq/sdk_python/issues/88)
187+
- Can not construct a BunqMeTabEntry to create a BunqMeTab [\#77](https://github.com/bunq/sdk_python/issues/77)
188+
- ImportError: cannot import name 'JSONDecodeError' [\#72](https://github.com/bunq/sdk_python/issues/72)
189+
168190
**Closed issues:**
169191

192+
- Move to new sandbox env. [\#98](https://github.com/bunq/sdk_python/issues/98)
170193
- Bunq sdk release request [\#97](https://github.com/bunq/sdk_python/issues/97)
171194
- reopening of question \#12 generated.Payment.FIELD\_COUNTERPARTY\_ALIAS not working with IBAN [\#96](https://github.com/bunq/sdk_python/issues/96)
172195
- Update samples and readme [\#93](https://github.com/bunq/sdk_python/issues/93)
173196
- bunq.sdk.exception.BunqException: ApiContext has not been loaded. Please load ApiContext in BunqContext [\#92](https://github.com/bunq/sdk_python/issues/92)
174197
- Sample for reading/using shared accounts [\#90](https://github.com/bunq/sdk_python/issues/90)
175-
- Add oath support. [\#102](https://github.com/bunq/sdk_python/issues/102)
176-
- Move to new sandbox env. [\#98](https://github.com/bunq/sdk_python/issues/98)
177-
178-
**Merged pull requests:**
179-
180-
- Move to new sandbox bunq/sdk\_python\#98 [\#99](https://github.com/bunq/sdk_python/pull/99) ([OGKevin](https://github.com/OGKevin))
198+
- Python 3.4.2: ImportError: cannot import name 'context' \(cyclic import?\) [\#73](https://github.com/bunq/sdk_python/issues/73)
181199

182200
## [0.13.0](https://github.com/bunq/sdk_python/tree/0.13.0) (2018-03-20)
183201

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ Creating objects through the API requires an `ApiContext`, a `requestMap` and id
8282
dependencies (such as User ID required for accessing a Monetary Account). Optionally, custom headers
8383
can be passed to requests.
8484

85-
payment_id = endpoint.Payment.create(
85+
payment_id = Payment.create(
8686
amount=Amount(amount_string, self._CURRENCY_EURL),
8787
counterparty_alias=Pointer(self._POINTER_TYPE_EMAIL, recipient),
8888
description=description
@@ -109,7 +109,7 @@ See [`tinker/list_all_payment`](https://github.com/bunq/tinker_python/blob/2182b
109109
Updating objects through the API goes the same way as creating objects, except that also the object to update identifier
110110
(ID or UUID) is needed.
111111

112-
endpoint.Card.update(
112+
Card.update(
113113
card_id=int(card_id),
114114
monetary_account_current_id=int(account_id)
115115
)
@@ -130,7 +130,7 @@ passed to requests.
130130
Listing objects through the API requires an `ApiContext` and identifiers of all dependencies (such as User ID required
131131
for accessing a Monetary Account). Optionally, custom headers can be passed to requests.
132132

133-
users = endpoint.User.list(api_context)
133+
users = User.list(api_context)
134134

135135
##### Example
136136
See [`UserListExample.py`](./examples/user_list_example.py)

bunq/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from bunq.sdk.http.pagination import Pagination
66
from bunq.sdk.json import converter
77
from bunq.sdk.model.core.anchor_object_interface import AnchorObjectInterface
8+
from bunq.sdk.model.generated.object_ import Geolocation, ShareDetail, MonetaryAccountReference
89
from bunq.sdk.util.type_alias import T
910

1011

@@ -36,9 +37,9 @@ def initialize_converter() -> None:
3637
converter.register_adapter(InstallationContext, InstallationContextAdapter)
3738
converter.register_adapter(ApiEnvironmentType, ApiEnvironmentTypeAdapter)
3839
converter.register_adapter(float, FloatAdapter)
39-
converter.register_adapter(object_.Geolocation, GeolocationAdapter)
40-
converter.register_adapter(object_.MonetaryAccountReference, MonetaryAccountReferenceAdapter)
41-
converter.register_adapter(object_.ShareDetail, ShareDetailAdapter)
40+
converter.register_adapter(Geolocation, GeolocationAdapter)
41+
converter.register_adapter(MonetaryAccountReference, MonetaryAccountReferenceAdapter)
42+
converter.register_adapter(ShareDetail, ShareDetailAdapter)
4243
converter.register_adapter(datetime.datetime, DateTimeAdapter)
4344
converter.register_adapter(Pagination, PaginationAdapter)
4445

bunq/sdk/context/api_context.py

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
from bunq.sdk.exception.bunq_exception import BunqException
1313
from bunq.sdk.json import converter
1414
from bunq.sdk.model.core.payment_service_provider_credential_internal import PaymentServiceProviderCredentialInternal
15-
from bunq.sdk.model.generated import endpoint
16-
from bunq.sdk.model.generated.endpoint import UserCredentialPasswordIp, UserPaymentServiceProvider
15+
from bunq.sdk.model.generated.endpoint import UserCredentialPasswordIp, Session
1716
from bunq.sdk.security import security
1817

1918
if typing.TYPE_CHECKING:
@@ -90,7 +89,7 @@ def create_for_psd2(cls,
9089
api_context._api_key = service_provider_credential.token_value
9190

9291
api_context.__register_device(description, all_permitted_ip)
93-
api_context.__initialize_session_for_psd2(service_provider_credential)
92+
api_context.__initialize_session()
9493

9594
return api_context
9695

@@ -104,8 +103,7 @@ def __initialize_installation(self) -> None:
104103
security.public_key_to_string(private_key_client.publickey())
105104
).value
106105
token = installation.token.token
107-
public_key_server_string = \
108-
installation.server_public_key.server_public_key
106+
public_key_server_string = installation.server_public_key.server_public_key
109107
public_key_server = RSA.import_key(public_key_server_string)
110108

111109
self._installation_context = InstallationContext(
@@ -117,7 +115,7 @@ def __initialize_installation(self) -> None:
117115
def __initialize_psd2_credential(self,
118116
certificate: str,
119117
private_key: str,
120-
all_chain_certificate: List[str], ) -> UserCredentialPasswordIp:
118+
all_chain_certificate: List[str]) -> UserCredentialPasswordIp:
121119
session_token = self.installation_context.token
122120
client_key_pair = self.installation_context.private_key_client
123121

@@ -147,24 +145,13 @@ def __register_device(self,
147145

148146
def __initialize_session(self) -> None:
149147
from bunq.sdk.model.core.session_server import SessionServer
150-
151-
session_server = SessionServer.create(self).value
152-
token = session_server.token.token
153-
expiry_time = self._get_expiry_timestamp(session_server)
154-
user_id = session_server.get_referenced_user().id_
155-
156-
self._session_context = SessionContext(token, expiry_time, user_id)
157-
158-
def __initialize_session_for_psd2(self, user_payment_service_provider: UserPaymentServiceProvider) -> None:
159-
from bunq.sdk.model.core.session_server import SessionServer
160-
161148
session_server = SessionServer.create(self).value
162149

163-
token = session_server.token.token
150+
token = session_server.token
164151
expiry_time = self._get_expiry_timestamp(session_server)
165-
user_id = session_server.get_referenced_user().id_
152+
user = session_server.get_user_reference()
166153

167-
self._session_context = SessionContext(token, expiry_time, user_id)
154+
self._session_context = SessionContext(token, expiry_time, user)
168155

169156
@classmethod
170157
def _get_expiry_timestamp(cls, session_server: SessionServer) -> datetime.datetime:
@@ -237,7 +224,7 @@ def close_session(self) -> None:
237224
self._drop_session_context()
238225

239226
def _delete_session(self) -> None:
240-
endpoint.Session.delete(self._SESSION_ID_DUMMY)
227+
Session.delete(self._SESSION_ID_DUMMY)
241228

242229
@property
243230
def environment_type(self) -> ApiEnvironmentType:

bunq/sdk/context/bunq_context.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ def __init__(self) -> None:
1717
@classmethod
1818
def load_api_context(cls, api_context: ApiContext) -> None:
1919
cls._api_context = api_context
20-
cls._user_context = UserContext(api_context.session_context.user_id)
20+
cls._user_context = UserContext(
21+
api_context.session_context.user_id,
22+
api_context.session_context.get_user_reference()
23+
)
2124
cls._user_context.init_main_monetary_account()
2225

2326
@classmethod

bunq/sdk/context/session_context.py

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
1+
from __future__ import annotations
2+
13
import datetime
4+
from typing import Optional
5+
6+
from bunq.sdk.exception.bunq_exception import BunqException
7+
from bunq.sdk.model.core.bunq_model import BunqModel
8+
from bunq.sdk.model.core.session_token import SessionToken
9+
from bunq.sdk.model.generated.endpoint import UserPerson, UserCompany, UserApiKey, UserPaymentServiceProvider
210

311

412
class SessionContext:
513
"""
614
:type _token: str
715
:type _expiry_time: datetime.datetime
816
:type _user_id: int
17+
:type _user_person: UserPerson|None
18+
:type _user_company: UserCompany|None
19+
:type _user_api_key: UserApiKey|None
20+
:type _user_payment_service_provider: UserPaymentServiceProvider|None
921
"""
1022

11-
def __init__(self,
12-
token: str,
13-
expiry_time: datetime.datetime,
14-
user_id: int) -> None:
15-
self._token = token
16-
self._expiry_time = expiry_time
17-
self._user_id = user_id
23+
# Error constants
24+
_ERROR_ALL_FIELD_IS_NULL = 'All fields are null'
25+
_ERROR_UNEXPECTED_USER_INSTANCE = '"{}" is unexpected user instance.'
1826

1927
@property
2028
def token(self) -> str:
@@ -27,3 +35,68 @@ def expiry_time(self) -> datetime.datetime:
2735
@property
2836
def user_id(self) -> int:
2937
return self._user_id
38+
39+
@property
40+
def user_person(self) -> Optional[UserPerson]:
41+
return self._user_person
42+
43+
@property
44+
def user_company(self) -> Optional[UserCompany]:
45+
return self._user_company
46+
47+
@property
48+
def user_api_key(self) -> Optional[UserApiKey]:
49+
return self._user_api_key
50+
51+
@property
52+
def user_payment_service_provider(self) -> Optional[UserPaymentServiceProvider]:
53+
return self._user_payment_service_provider
54+
55+
def __init__(self, token: SessionToken, expiry_time: datetime.datetime, user: BunqModel) -> None:
56+
self._user_person = None
57+
self._user_company = None
58+
self._user_api_key = None
59+
self._user_payment_service_provider = None
60+
self._token = token.token
61+
self._expiry_time = expiry_time
62+
self._user_id = self.__get_user_id(user)
63+
self.__set_user(user)
64+
65+
def __get_user_id(self, user: BunqModel) -> int:
66+
if isinstance(user, UserPerson):
67+
return user.id_
68+
69+
if isinstance(user, UserCompany):
70+
return user.id_
71+
72+
if isinstance(user, UserApiKey):
73+
return user.id_
74+
75+
if isinstance(user, UserPaymentServiceProvider):
76+
return user.id_
77+
78+
raise BunqException(self._ERROR_UNEXPECTED_USER_INSTANCE)
79+
80+
def __set_user(self, user: BunqModel):
81+
if isinstance(user, UserPerson):
82+
self._user_person = user
83+
elif isinstance(user, UserCompany):
84+
self._user_company = user
85+
elif isinstance(user, UserApiKey):
86+
self._user_api_key = user
87+
elif isinstance(user, UserPaymentServiceProvider):
88+
self._user_payment_service_provider = user
89+
else:
90+
raise BunqException(self._ERROR_UNEXPECTED_USER_INSTANCE)
91+
92+
def get_user_reference(self) -> BunqModel:
93+
if self.user_person is not None:
94+
return self.user_person
95+
elif self.user_company is not None:
96+
return self.user_company
97+
elif self.user_api_key is not None:
98+
return self.user_api_key
99+
elif self.user_payment_service_provider is not None:
100+
return self.user_payment_service_provider
101+
else:
102+
raise BunqException(self._ERROR_ALL_FIELD_IS_NULL)

bunq/sdk/context/user_context.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,39 @@
11
from bunq.sdk.exception.bunq_exception import BunqException
22
from bunq.sdk.model.core.bunq_model import BunqModel
3-
from bunq.sdk.model.generated import endpoint
4-
from bunq.sdk.model.generated.endpoint import UserPerson, UserCompany, UserApiKey, MonetaryAccountBank
3+
from bunq.sdk.model.generated.endpoint import UserPerson, UserCompany, UserApiKey, MonetaryAccountBank, User, \
4+
UserPaymentServiceProvider
55

66

77
class UserContext:
88
_ERROR_UNEXPECTED_USER_INSTANCE = '"{}" is unexpected user instance.'
99
_ERROR_NO_ACTIVE_MONETARY_ACCOUNT_FOUND = 'No active monetary account found.'
1010
_STATUS_ACTIVE = 'ACTIVE'
1111

12-
def __init__(self, user_id: int) -> None:
12+
def __init__(self, user_id: int, user: BunqModel) -> None:
1313
self._user_id = user_id
1414
self._user_person = None
1515
self._user_company = None
1616
self._user_api_key = None
1717
self._user_payment_service_provider = None
1818
self._primary_monetary_account = None
1919

20-
self._set_user(self.__get_user_object())
20+
self._set_user(user)
2121

2222
@staticmethod
2323
def __get_user_object() -> BunqModel:
24-
return endpoint.User.list().value[0].get_referenced_object()
24+
return User.list().value[0].get_referenced_object()
2525

2626
def _set_user(self, user: BunqModel) -> None:
27-
if isinstance(user, endpoint.UserPerson):
27+
if isinstance(user, UserPerson):
2828
self._user_person = user
2929

30-
elif isinstance(user, endpoint.UserCompany):
30+
elif isinstance(user, UserCompany):
3131
self._user_company = user
3232

33-
elif isinstance(user, endpoint.UserApiKey):
33+
elif isinstance(user, UserApiKey):
3434
self._user_api_key = user
3535

36-
elif isinstance(user, endpoint.UserPaymentServiceProvider):
36+
elif isinstance(user, UserPaymentServiceProvider):
3737
self._user_payment_service_provider = user
3838

3939
else:
@@ -44,7 +44,7 @@ def init_main_monetary_account(self) -> None:
4444
if self._user_payment_service_provider is not None:
4545
return
4646

47-
all_monetary_account = endpoint.MonetaryAccountBank.list().value
47+
all_monetary_account = MonetaryAccountBank.list().value
4848

4949
for account in all_monetary_account:
5050
if account.status == self._STATUS_ACTIVE:

0 commit comments

Comments
 (0)