Skip to content

Commit e60081b

Browse files
authored
Merge pull request #17 from bunq/16_proxy
Add proxy support [#16]
2 parents 1201ab2 + 40627c5 commit e60081b

File tree

4 files changed

+55
-18
lines changed

4 files changed

+55
-18
lines changed

bunq/sdk/client.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ class ApiClient(object):
1919
:type _api_context: context.ApiContext
2020
"""
2121

22+
# HTTPS type of proxy, the only used at bunq
23+
_FIELD_PROXY_HTTPS = 'https'
24+
2225
# Header constants
2326
HEADER_ATTACHMENT_DESCRIPTION = 'X-Bunq-Attachment-Description'
2427
HEADER_CONTENT_TYPE = 'Content-Type'
@@ -98,7 +101,8 @@ def _request(self, method, uri_relative, request_bytes, custom_headers):
98101
method,
99102
self._get_uri_full(uri_relative),
100103
data=request_bytes,
101-
headers=all_headers
104+
headers=all_headers,
105+
proxies={self._FIELD_PROXY_HTTPS: self._api_context.proxy_url}
102106
)
103107

104108
self._assert_response_success(response)

bunq/sdk/context.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class ApiContext(object):
4141
:type _api_key: str
4242
:type _session_context: SessionContext
4343
:type _installation_context: InstallationContext
44+
:type _proxy_url: str|None
4445
"""
4546

4647
# File mode for saving and restoring the context
@@ -57,12 +58,13 @@ class ApiContext(object):
5758
_PATH_API_CONTEXT_DEFAULT = 'bunq.conf'
5859

5960
def __init__(self, environment_type, api_key, device_description,
60-
permitted_ips=None):
61+
permitted_ips=None, proxy_url=None):
6162
"""
6263
:type environment_type: ApiEnvironmentType
6364
:type api_key: str
6465
:type device_description: str
6566
:type permitted_ips: list[str]|None
67+
:type proxy_url: str|None
6668
"""
6769

6870
if permitted_ips is None:
@@ -72,6 +74,7 @@ def __init__(self, environment_type, api_key, device_description,
7274
self._api_key = api_key
7375
self._installation_context = None
7476
self._session_context = None
77+
self._proxy_url = proxy_url
7578
self._initialize(device_description, permitted_ips)
7679

7780
def _initialize(self, device_description, permitted_ips):
@@ -254,6 +257,14 @@ def session_context(self):
254257

255258
return self._session_context
256259

260+
@property
261+
def proxy_url(self):
262+
"""
263+
:rtype: str
264+
"""
265+
266+
return self._proxy_url
267+
257268
def save(self, path=None):
258269
"""
259270
:type path: str

bunq/sdk/json/converter.py

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ class JsonAdapter(object):
2929
_PREFIX_KEY_PROTECTED = '_'
3030

3131
# Constants to fetch param types from the docstrings
32-
_PATTERN_PARAM_TYPES = ':type (_?{}): ([\w.]+)(?:\[([\w.]+)\])?'
32+
_TEMPLATE_PATTERN_PARAM_TYPES = ':type (_?{}): ([\w.]+)(?:\[([\w.]+)\])?'
33+
_PATTERN_PARAM_NAME_TYPED_ANY = ':type (\w+):'
3334
_SUBMATCH_INDEX_NAME = 1
3435
_SUBMATCH_INDEX_TYPE_MAIN = 2
3536
_SUBMATCH_INDEX_TYPE_SUB = 3
@@ -163,7 +164,9 @@ def _deserialize_dict(cls, cls_target, dict_):
163164
"""
164165

165166
instance = cls_target.__new__(cls_target, cls_target)
166-
instance.__dict__ = cls._deserialize_dict_attributes(cls_target, dict_)
167+
dict_deserialized = cls._deserialize_dict_attributes(cls_target, dict_)
168+
instance.__dict__ = cls._fill_default_values(cls_target,
169+
dict_deserialized)
167170

168171
return instance
169172

@@ -192,18 +195,6 @@ def _deserialize_dict_attributes(cls, cls_context, dict_):
192195

193196
return dict_deserialized
194197

195-
@classmethod
196-
def _warn_key_unknown(cls, cls_context, key):
197-
"""
198-
:type cls_context: type
199-
:type key: str
200-
201-
:rtype: None
202-
"""
203-
204-
context_name = cls_context.__name__
205-
warnings.warn(cls._WARNING_KEY_UNKNOWN.format(key, context_name))
206-
207198
@classmethod
208199
def _deserialize_key(cls, key):
209200
"""
@@ -240,7 +231,7 @@ def _fetch_attribute_specs_from_doc(cls, cls_in, attribute_name):
240231
:rtype: ValueSpecs
241232
"""
242233

243-
pattern = cls._PATTERN_PARAM_TYPES.format(attribute_name)
234+
pattern = cls._TEMPLATE_PATTERN_PARAM_TYPES.format(attribute_name)
244235
match = re.search(pattern, cls_in.__doc__)
245236

246237
if match is not None:
@@ -366,6 +357,37 @@ def _deserialize_list(cls, type_item, list_):
366357

367358
return list_deserialized
368359

360+
@classmethod
361+
def _warn_key_unknown(cls, cls_context, key):
362+
"""
363+
:type cls_context: type
364+
:type key: str
365+
366+
:rtype: None
367+
"""
368+
369+
context_name = cls_context.__name__
370+
warnings.warn(cls._WARNING_KEY_UNKNOWN.format(key, context_name))
371+
372+
@classmethod
373+
def _fill_default_values(cls, cls_context, dict_):
374+
"""
375+
:type cls_context: type
376+
:type dict_: dict
377+
378+
:rtype: dict
379+
"""
380+
381+
dict_with_default_values = dict(dict_)
382+
params = re.findall(cls._PATTERN_PARAM_NAME_TYPED_ANY,
383+
cls_context.__doc__)
384+
385+
for param in params:
386+
if param not in dict_with_default_values:
387+
dict_with_default_values[param] = None
388+
389+
return dict_with_default_values
390+
369391
@classmethod
370392
def can_serialize(cls):
371393
"""

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
aenum==2.0.8
22
chardet==3.0.4
33
pycryptodomex==3.4.6
4-
requests==2.18.1
4+
requests[socks]==2.18.1
55
simplejson==3.11.1
66
urllib3==1.21.1

0 commit comments

Comments
 (0)