Skip to content

Commit 3853b32

Browse files
author
Kevin Hellemun
committed
Merge branch 'release/0.12.4'
2 parents a1dd162 + 522538d commit 3853b32

File tree

12 files changed

+6888
-1382
lines changed

12 files changed

+6888
-1382
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,4 @@ config.json
9292
connectQr.png
9393
.DS_Store
9494
bunq_sdk.egg-info
95+
.idea/codeStyles/

CHANGELOG.md

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# Change Log
2+
3+
## [0.12.4](https://github.com/bunq/sdk_python/tree/0.12.4) (2017-12-21)
4+
[Full Changelog](https://github.com/bunq/sdk_python/compare/0.12.3...0.12.4)
5+
6+
**Implemented enhancements:**
7+
8+
- Make sure received signatures headers are correctly cased [\#51](https://github.com/bunq/sdk_python/issues/51)
9+
- Introduce from\_json method  [\#50](https://github.com/bunq/sdk_python/issues/50)
10+
- Return base class from createFromJsonString [\#49](https://github.com/bunq/sdk_python/issues/49)
11+
- CHANGELOG.md is empty [\#46](https://github.com/bunq/sdk_python/issues/46)
12+
- Improve decoder to recognise child object [\#42](https://github.com/bunq/sdk_python/issues/42)
13+
14+
**Closed issues:**
15+
16+
- Python doesn't want CamelCase [\#45](https://github.com/bunq/sdk_python/issues/45)
17+
18+
**Merged pull requests:**
19+
20+
- Feature/make sure headers are correctly cased bunq/sdk python\#51 [\#57](https://github.com/bunq/sdk_python/pull/57) ([OGKevin](https://github.com/OGKevin))
21+
- Feature/improve decoder bunq/sdk python\#42 [\#56](https://github.com/bunq/sdk_python/pull/56) ([OGKevin](https://github.com/OGKevin))
22+
- Renamed camelCase methods. \(bunq/sdk\_python\#45\) [\#48](https://github.com/bunq/sdk_python/pull/48) ([OGKevin](https://github.com/OGKevin))
23+
- Generated CHANGELOG.md :clap:. \(bunq/sdk\_python\#46\) [\#47](https://github.com/bunq/sdk_python/pull/47) ([OGKevin](https://github.com/OGKevin))
24+
25+
## [0.12.3](https://github.com/bunq/sdk_python/tree/0.12.3) (2017-11-15)
26+
[Full Changelog](https://github.com/bunq/sdk_python/compare/0.12.2...0.12.3)
27+
28+
**Implemented enhancements:**
29+
30+
- Callback models for holding callback data [\#40](https://github.com/bunq/sdk_python/issues/40)
31+
- Feature/callback models bunq/sdk python\#40 [\#43](https://github.com/bunq/sdk_python/pull/43) ([OGKevin](https://github.com/OGKevin))
32+
33+
**Fixed bugs:**
34+
35+
- ScheduledPayment causes decode error due to Typo [\#44](https://github.com/bunq/sdk_python/issues/44)
36+
37+
## [0.12.2](https://github.com/bunq/sdk_python/tree/0.12.2) (2017-11-08)
38+
[Full Changelog](https://github.com/bunq/sdk_python/compare/0.12.0...0.12.2)
39+
40+
**Implemented enhancements:**
41+
42+
- Add missing fields for cvc endpoint [\#37](https://github.com/bunq/sdk_python/issues/37)
43+
- Missing CARD GENERATED CVC2 endpoint [\#33](https://github.com/bunq/sdk_python/issues/33)
44+
- More flexibility for sessionContext handling [\#31](https://github.com/bunq/sdk_python/issues/31)
45+
- Added cvc\_endpoint. \#33 [\#34](https://github.com/bunq/sdk_python/pull/34) ([OGKevin](https://github.com/OGKevin))
46+
- Added isSessionExpired\(\) method \#31. [\#32](https://github.com/bunq/sdk_python/pull/32) ([OGKevin](https://github.com/OGKevin))
47+
48+
**Fixed bugs:**
49+
50+
- DraftPayment object field causes converter error [\#36](https://github.com/bunq/sdk_python/issues/36)
51+
52+
**Merged pull requests:**
53+
54+
- Feature/fix draft payment object \#36 [\#39](https://github.com/bunq/sdk_python/pull/39) ([OGKevin](https://github.com/OGKevin))
55+
- Feature/add missing cvc fields \#37 [\#38](https://github.com/bunq/sdk_python/pull/38) ([OGKevin](https://github.com/OGKevin))
56+
57+
## [0.12.0](https://github.com/bunq/sdk_python/tree/0.12.0) (2017-10-11)
58+
[Full Changelog](https://github.com/bunq/sdk_python/compare/0.11.0...0.12.0)
59+
60+
**Implemented enhancements:**
61+
62+
- Add strictly typed BunqResponses [\#27](https://github.com/bunq/sdk_python/issues/27)
63+
- Better error handling [\#25](https://github.com/bunq/sdk_python/issues/25)
64+
- Add Pagination [\#20](https://github.com/bunq/sdk_python/issues/20)
65+
- Marked all files in generated dir as generated code. [\#24](https://github.com/bunq/sdk_python/pull/24) ([OGKevin](https://github.com/OGKevin))
66+
67+
**Merged pull requests:**
68+
69+
- cleanup after 27-strictly-typed-response [\#30](https://github.com/bunq/sdk_python/pull/30) ([dnl-blkv](https://github.com/dnl-blkv))
70+
- Add strictly typed responses; fix circular dependencies; improve namespaces [\#28](https://github.com/bunq/sdk_python/pull/28) ([dnl-blkv](https://github.com/dnl-blkv))
71+
- Feature/exception handler [\#26](https://github.com/bunq/sdk_python/pull/26) ([OGKevin](https://github.com/OGKevin))
72+
73+
## [0.11.0](https://github.com/bunq/sdk_python/tree/0.11.0) (2017-09-06)
74+
[Full Changelog](https://github.com/bunq/sdk_python/compare/0.10.0...0.11.0)
75+
76+
**Implemented enhancements:**
77+
78+
- Ignore generated code for reviews [\#22](https://github.com/bunq/sdk_python/issues/22)
79+
- Feature/git attributes [\#23](https://github.com/bunq/sdk_python/pull/23) ([OGKevin](https://github.com/OGKevin))
80+
- Add pagination [\#21](https://github.com/bunq/sdk_python/pull/21) ([dnl-blkv](https://github.com/dnl-blkv))
81+
82+
## [0.10.0](https://github.com/bunq/sdk_python/tree/0.10.0) (2017-08-22)
83+
[Full Changelog](https://github.com/bunq/sdk_python/compare/0.9.1...0.10.0)
84+
85+
**Implemented enhancements:**
86+
87+
- Add proxy support to Python SDK [\#16](https://github.com/bunq/sdk_python/issues/16)
88+
- Break the SDK's dependence on the bunq.conf file [\#11](https://github.com/bunq/sdk_python/issues/11)
89+
- Response is missing response headers and pagination [\#9](https://github.com/bunq/sdk_python/issues/9)
90+
- cleanup tests \[\#18\] [\#19](https://github.com/bunq/sdk_python/pull/19) ([dnl-blkv](https://github.com/dnl-blkv))
91+
- Changed test class name [\#14](https://github.com/bunq/sdk_python/pull/14) ([OGKevin](https://github.com/OGKevin))
92+
- Load and Save an ApiContext from and to JSON Data [\#13](https://github.com/bunq/sdk_python/pull/13) ([PJUllrich](https://github.com/PJUllrich))
93+
- \#9 Introduce BunqResponse [\#10](https://github.com/bunq/sdk_python/pull/10) ([dnl-blkv](https://github.com/dnl-blkv))
94+
95+
**Closed issues:**
96+
97+
- Tests need a minor cleanup [\#18](https://github.com/bunq/sdk_python/issues/18)
98+
99+
**Merged pull requests:**
100+
101+
- Add proxy support \[\#16\] [\#17](https://github.com/bunq/sdk_python/pull/17) ([dnl-blkv](https://github.com/dnl-blkv))
102+
103+
## [0.9.1](https://github.com/bunq/sdk_python/tree/0.9.1) (2017-08-07)
104+
**Implemented enhancements:**
105+
106+
- Submit this as package to PyPi [\#2](https://github.com/bunq/sdk_python/issues/2)
107+
- Readme for tests [\#5](https://github.com/bunq/sdk_python/pull/5) ([OGKevin](https://github.com/OGKevin))
108+
- Uploaded to PyPi [\#4](https://github.com/bunq/sdk_python/pull/4) ([OGKevin](https://github.com/OGKevin))
109+
- Add first series of unit-tests [\#1](https://github.com/bunq/sdk_python/pull/1) ([OGKevin](https://github.com/OGKevin))
110+
111+
**Fixed bugs:**
112+
113+
- Add Threadsafety for x-bunq-server-signature [\#7](https://github.com/bunq/sdk_python/issues/7)
114+
115+
116+
117+
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.12.3
1+
0.12.4

bunq/__init__.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ def initialize_converter():
77
"""
88

99
import datetime
10+
import inspect
1011

1112
from bunq.sdk import client
1213
from bunq.sdk import context
1314
from bunq.sdk.model import core
1415
from bunq.sdk.json import adapters
1516
from bunq.sdk.json import converter
1617
from bunq.sdk.model.generated import object_
18+
from bunq.sdk.model.generated import endpoint
1719

1820
converter.register_adapter(core.Installation, adapters.InstallationAdapter)
1921
converter.register_adapter(
@@ -38,5 +40,27 @@ def initialize_converter():
3840
converter.register_adapter(datetime.datetime, adapters.DateTimeAdapter)
3941
converter.register_adapter(client.Pagination, adapters.PaginationAdapter)
4042

43+
def register_anchor_adapter(class_to_regsiter):
44+
if issubclass(class_to_regsiter, core.AnchoredObjectInterface):
45+
converter.register_adapter(
46+
class_to_regsiter,
47+
adapters.AnchoredObjectModelAdapter
48+
)
49+
50+
def get_class(class_string_to_get):
51+
if hasattr(object_, class_string_to_get):
52+
return getattr(object_, class_string_to_get)
53+
54+
if hasattr(endpoint, class_string_to_get):
55+
return getattr(endpoint, class_string_to_get)
56+
57+
for class_string in list(dir(object_) + dir(endpoint)):
58+
class_ = get_class(class_string)
59+
60+
if not inspect.isclass(class_):
61+
continue
62+
63+
register_anchor_adapter(class_)
64+
4165

4266
converter.set_initializer_function(initialize_converter)

bunq/sdk/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class ApiClient(object):
4141
HEADER_AUTHENTICATION = 'X-Bunq-Client-Authentication'
4242

4343
# Default header values
44-
_USER_AGENT_BUNQ = 'bunq-sdk-python/0.12.3'
44+
_USER_AGENT_BUNQ = 'bunq-sdk-python/0.12.4'
4545
_GEOLOCATION_ZERO = '0 0 0 0 NL'
4646
_LANGUAGE_EN_US = 'en_US'
4747
_REGION_NL_NL = 'nl_NL'

bunq/sdk/json/adapters.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,71 @@
88
from bunq.sdk.model import core
99
from bunq.sdk.model.generated import endpoint
1010
from bunq.sdk.model.generated import object_
11+
from bunq.sdk.exception import BunqException
12+
13+
14+
class AnchoredObjectModelAdapter(converter.JsonAdapter):
15+
16+
_ERROR_MODEL_NOT_FOUND = '{} is not in endpoint nor object.'
17+
18+
_override_field_map = {
19+
'ScheduledPayment': 'SchedulePayment',
20+
'ScheduledInstance': 'ScheduleInstance',
21+
}
22+
23+
@classmethod
24+
def deserialize(cls, cls_target, obj_raw):
25+
"""
26+
:type cls_target: core.BunqModel
27+
:type obj_raw: int|str|bool|float|list|dict|None
28+
29+
:rtype: T
30+
"""
31+
32+
model_ = super()._deserialize_default(cls_target, obj_raw)
33+
34+
if isinstance(model_, core.AnchoredObjectInterface) and model_.is_all_field_none():
35+
for field in model_.__dict__:
36+
field_ = None
37+
if field in cls._override_field_map:
38+
field_ = cls._override_field_map[field]
39+
40+
if field_ is None:
41+
object_class = cls._get_object_class(field)
42+
else:
43+
object_class = cls._get_object_class(field_)
44+
45+
contents = super()._deserialize_default(object_class, obj_raw)
46+
47+
if contents.is_all_field_none():
48+
setattr(model_, field, None)
49+
else:
50+
setattr(model_, field, contents)
51+
52+
return model_
53+
54+
@classmethod
55+
def can_serialize(cls):
56+
return False
57+
58+
@classmethod
59+
def _get_object_class(cls, class_name):
60+
"""
61+
:type class_name: str
62+
:rtype: core.BunqModel
63+
"""
64+
65+
try:
66+
return getattr(endpoint, class_name)
67+
except AttributeError:
68+
pass
69+
70+
try:
71+
return getattr(object_, class_name)
72+
except AttributeError:
73+
pass
74+
75+
raise BunqException(cls._ERROR_MODEL_NOT_FOUND.format(class_name))
1176

1277

1378
class InstallationAdapter(converter.JsonAdapter):

bunq/sdk/model/core.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
from bunq.sdk.json import converter
33

44

5+
class AnchoredObjectInterface:
6+
pass
7+
8+
59
class BunqModel(object):
610
# Field constants
711
_FIELD_RESPONSE = 'Response'
@@ -12,13 +16,20 @@ class BunqModel(object):
1216
# The very first index of an array
1317
_INDEX_FIRST = 0
1418

19+
def is_all_field_none(self):
20+
raise NotImplementedError
21+
1522
def to_json(self):
1623
"""
1724
:rtype: str
1825
"""
1926

2027
return converter.class_to_json(self)
2128

29+
@staticmethod
30+
def from_json(json_str):
31+
raise NotImplementedError
32+
2233
@classmethod
2334
def _from_json_array_nested(cls, response_raw):
2435
"""
@@ -141,6 +152,13 @@ def id_(self):
141152

142153
return self._id_
143154

155+
def is_all_field_none(self):
156+
if self.id_ is not None:
157+
return False
158+
159+
return True
160+
161+
144162

145163
class Uuid(BunqModel):
146164
"""
@@ -158,6 +176,11 @@ def uuid(self):
158176

159177
return self._uuid
160178

179+
def is_all_field_none(self):
180+
if self.uuid is not None:
181+
return False
182+
183+
return True
161184

162185
class SessionToken(BunqModel):
163186
"""
@@ -205,6 +228,21 @@ def token(self):
205228

206229
return self._token
207230

231+
def is_all_field_none(self):
232+
if self.id_ is not None:
233+
return False
234+
235+
if self.created is not None:
236+
return False
237+
238+
if self.updated is not None:
239+
return False
240+
241+
if self.token is not None:
242+
return False
243+
244+
return True
245+
208246

209247
class PublicKeyServer(BunqModel):
210248
"""
@@ -222,6 +260,12 @@ def server_public_key(self):
222260

223261
return self._server_public_key
224262

263+
def is_all_field_none(self):
264+
if self.server_public_key is not None:
265+
return False
266+
267+
return True
268+
225269

226270
class Installation(BunqModel):
227271
"""
@@ -296,6 +340,17 @@ def generate_request_body_bytes(cls, public_key_string):
296340
}
297341
).encode()
298342

343+
def is_all_field_none(self):
344+
if self.id_ is not None:
345+
return False
346+
347+
if self.token is not None:
348+
return False
349+
350+
if self.server_public_key is not None:
351+
return False
352+
353+
return True
299354

300355
class SessionServer(BunqModel):
301356
"""
@@ -373,4 +428,17 @@ def generate_request_body_bytes(cls, secret):
373428

374429
return converter.class_to_json({cls.FIELD_SECRET: secret}).encode()
375430

431+
def is_all_field_none(self):
432+
if self.id_ is not None:
433+
return False
434+
435+
if self.token is not None:
436+
return False
437+
438+
if self.user_person is not None:
439+
return False
440+
441+
if self.user_company is not None:
442+
return False
376443

444+
return True

0 commit comments

Comments
 (0)