Skip to content

Commit

Permalink
Merge branch 'release/1.14.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
angelomelonas committed Aug 20, 2020
2 parents 2ba6b48 + 41357ad commit 78390d2
Show file tree
Hide file tree
Showing 40 changed files with 1,500 additions and 1,055 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
[//]: # (If there is a traceback please share it in a quote! You can do this by pasting the traceback text, highlighting it and pressing the quote button.)

## SDK version and environment
- Tested on [0.12.4](https://github.com/bunq/sdk_python/releases/tag/0.12.4)
- Tested on [1.14.1](https://github.com/bunq/sdk_python/releases/tag/1.14.1)
- [ ] Sandbox
- [ ] Production

Expand Down
2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

## This PR closes/fixes the following issues:
[//]: # (If for some reason your pull request does not require a test case you can just mark this box as checked and explain why it does not require a test case.)
- Closes bunq/sdk_php#
- Closes bunq/sdk_python#
- [ ] Tested
40 changes: 38 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,41 @@
# Changelog

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

[Full Changelog](https://github.com/bunq/sdk_python/compare/1.14.0...HEAD)

**Implemented enhancements:**

- Add a test for oauth\_authorization\_uri [\#145](https://github.com/bunq/sdk_python/issues/145)
- Update tests with Type Hints \(and other small Type Hint improvements\) [\#139](https://github.com/bunq/sdk_python/issues/139)
- Complete OAuth/PSD2 implementation [\#136](https://github.com/bunq/sdk_python/issues/136)
- Allow for a looser range of runtime dependency versions in conformance with semver backward compatibility guarantees [\#107](https://github.com/bunq/sdk_python/issues/107)
- Updated dependencies, and made them more flexible [\#146](https://github.com/bunq/sdk_python/pull/146) ([angelomelonas](https://github.com/angelomelonas))
- Added type hints for tests [\#141](https://github.com/bunq/sdk_python/pull/141) ([angelomelonas](https://github.com/angelomelonas))

**Fixed bugs:**

- Add missing \_user\_payment\_service\_provider variable with the value None to session\_server [\#135](https://github.com/bunq/sdk_python/pull/135) ([siccovansas](https://github.com/siccovansas))

**Closed issues:**

- Breaking changes since v1.13.0 [\#142](https://github.com/bunq/sdk_python/issues/142)
- Is this repository even maintained? [\#140](https://github.com/bunq/sdk_python/issues/140)
- AttributeError: 'SessionServer' object has no attribute '\_user\_payment\_service\_provider' [\#134](https://github.com/bunq/sdk_python/issues/134)
- cannot import name 'ApiContext' from 'bunq.sdk.context' [\#132](https://github.com/bunq/sdk_python/issues/132)
- The CHANGELOG is out of date [\#131](https://github.com/bunq/sdk_python/issues/131)
- Error in class conversion since BillingInvoice does not exist [\#124](https://github.com/bunq/sdk_python/issues/124)

**Merged pull requests:**

- Update CHANGELOG with breaking changes [\#143](https://github.com/bunq/sdk_python/pull/143) ([angelomelonas](https://github.com/angelomelonas))
- sdk\_python\#136 complete Oauth/PSD2 implementation [\#138](https://github.com/bunq/sdk_python/pull/138) ([angelomelonas](https://github.com/angelomelonas))
- update setup.py: only python 3.7 is supported. [\#133](https://github.com/bunq/sdk_python/pull/133) ([csdenboer](https://github.com/csdenboer))

## [1.14.0](https://github.com/bunq/sdk_python/tree/1.14.0) (2020-08-04)

[Full Changelog](https://github.com/bunq/sdk_python/compare/1.13.1...1.14.0)

## [1.13.1](https://github.com/bunq/sdk_python/tree/1.13.1) (2020-02-21)

[Full Changelog](https://github.com/bunq/sdk_python/compare/1.13.0...1.13.1)
Expand Down Expand Up @@ -267,10 +303,10 @@
- Add proxy support to Python SDK [\#16](https://github.com/bunq/sdk_python/issues/16)
- Break the SDK's dependence on the bunq.conf file [\#11](https://github.com/bunq/sdk_python/issues/11)
- Response is missing response headers and pagination [\#9](https://github.com/bunq/sdk_python/issues/9)
- cleanup tests \[\#18\] [\#19](https://github.com/bunq/sdk_python/pull/19) ([dnl-blkv](https://github.com/dnl-blkv))
- Changed test class name [\#14](https://github.com/bunq/sdk_python/pull/14) ([OGKevin](https://github.com/OGKevin))
- Load and Save an ApiContext from and to JSON Data [\#13](https://github.com/bunq/sdk_python/pull/13) ([PJUllrich](https://github.com/PJUllrich))
- \#9 Introduce BunqResponse [\#10](https://github.com/bunq/sdk_python/pull/10) ([dnl-blkv](https://github.com/dnl-blkv))
- Readme for tests [\#5](https://github.com/bunq/sdk_python/pull/5) ([OGKevin](https://github.com/OGKevin))

**Closed issues:**

Expand All @@ -287,7 +323,7 @@
**Implemented enhancements:**

- Submit this as package to PyPi [\#2](https://github.com/bunq/sdk_python/issues/2)
- cleanup tests \[\#18\] [\#19](https://github.com/bunq/sdk_python/pull/19) ([dnl-blkv](https://github.com/dnl-blkv))
- Readme for tests [\#5](https://github.com/bunq/sdk_python/pull/5) ([OGKevin](https://github.com/OGKevin))
- Uploaded to PyPi [\#4](https://github.com/bunq/sdk_python/pull/4) ([OGKevin](https://github.com/OGKevin))
- Add first series of unit-tests [\#1](https://github.com/bunq/sdk_python/pull/1) ([OGKevin](https://github.com/OGKevin))

Expand Down
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
### How to contribute to the bunq Python SDK 😎

#### Want to add a new amazing feature to our SDK? 🚀
- First let’s discuss the feature that you would like to add. [Open a new issue](https://github.com/bunq/bunq-Python/issues/new), describe the feature and explain why you think it should be added.
- First let’s discuss the feature that you would like to add. [Open a new issue](https://github.com/bunq/sdk_python/issues/new), describe the feature and explain why you think it should be added.
- Once we agree on the new feature, open a new GitHub pull request and include all the relevant information to get your code approved!

#### Did you find a bug? 🐛
- Before opening a new issue check if the bug hasn't already been reported by searching on GitHub under [issues](https://github.com/bunq/bunq-Python/issues).
- If it hasn't already been reported you can [open a new issue](https://github.com/bunq/bunq-Python/issues/new). Make sure you include a title and clear description, as much relevant information as possible, and a code sample or an executable test case demonstrating the expected behaviour that is not occurring.
- Before opening a new issue check if the bug hasn't already been reported by searching on GitHub under [issues](https://github.com/bunq/sdk_python/issues).
- If it hasn't already been reported you can [open a new issue](https://github.com/bunq/sdk_python/issues/new). Make sure you include a title and clear description, as much relevant information as possible, and a code sample or an executable test case demonstrating the expected behaviour that is not occurring.
- If you wrote a patch that fixes a bug, open a new GitHub pull request and make sure to clearly describe the problem and your awesome solution.

#### Do you have questions about the source code?
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.14.0
1.14.1
6 changes: 3 additions & 3 deletions bunq/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Type, Any
from typing import Type

from bunq.sdk.context.api_environment_type import ApiEnvironmentType
from bunq.sdk.context.installation_context import InstallationContext
Expand Down Expand Up @@ -42,11 +42,11 @@ def initialize_converter() -> None:
converter.register_adapter(datetime.datetime, DateTimeAdapter)
converter.register_adapter(Pagination, PaginationAdapter)

def register_anchor_adapter(class_to_register: Type[Any]) -> None:
def register_anchor_adapter(class_to_register: Type[T]) -> None:
if issubclass(class_to_register, AnchorObjectInterface):
converter.register_adapter(class_to_register, AnchorObjectAdapter)

def get_class(class_string_to_get: str) -> Type[Any]:
def get_class(class_string_to_get: str) -> Type[T]:
if hasattr(object_, class_string_to_get):
return getattr(object_, class_string_to_get)

Expand Down
3 changes: 2 additions & 1 deletion bunq/sdk/context/api_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ def create_for_psd2(cls,
service_provider_credential = api_context.__initialize_psd2_credential(
certificate,
private_key,
all_chain_certificate)
all_chain_certificate
)

api_context._api_key = service_provider_credential.token_value

Expand Down
64 changes: 64 additions & 0 deletions bunq/sdk/http/anonymous_api_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from typing import Dict

import requests

from bunq.sdk.context.api_context import ApiContext
from bunq.sdk.http.api_client import ApiClient
from bunq.sdk.http.bunq_response_raw import BunqResponseRaw
from bunq.sdk.security import security


class AnonymousApiClient(ApiClient):

def __init__(self, api_context: ApiContext) -> None:
super().__init__(api_context)

def post(self,
uri_relative: str,
request_bytes: bytes,
custom_headers: Dict[str, str]) -> BunqResponseRaw:
return self._request(
self.METHOD_POST,
uri_relative,
request_bytes,
{},
custom_headers
)

def _request(self,
method: str,
uri_relative: str,
request_bytes: bytes,
params: Dict[str, str],
custom_headers: Dict[str, str]) -> BunqResponseRaw:
from bunq.sdk.context.bunq_context import BunqContext

uri_relative_with_params = self._append_params_to_uri(uri_relative, params)
if uri_relative not in self._URIS_NOT_REQUIRING_ACTIVE_SESSION:
if self._api_context.ensure_session_active():
BunqContext.update_api_context(self._api_context)

all_headers = self._get_all_headers(
request_bytes,
custom_headers
)

response = requests.request(
method,
uri_relative_with_params,
data=request_bytes,
headers=all_headers,
proxies={self.FIELD_PROXY_HTTPS: self._api_context.proxy_url},
)

self._assert_response_success(response)

if self._api_context.installation_context is not None:
security.validate_response(
self._api_context.installation_context.public_key_server,
response.status_code,
response.content,
response.headers
)

return BunqResponseRaw(response.content, response.headers)
2 changes: 1 addition & 1 deletion bunq/sdk/http/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class ApiClient:
HEADER_RESPONSE_ID_LOWER_CASED = 'x-bunq-client-response-id'

# Default header values
USER_AGENT_BUNQ = 'bunq-sdk-python/1.14.0'
USER_AGENT_BUNQ = 'bunq-sdk-python/1.14.1'
GEOLOCATION_ZERO = '0 0 0 0 NL'
LANGUAGE_EN_US = 'en_US'
REGION_NL_NL = 'nl_NL'
Expand Down
15 changes: 15 additions & 0 deletions bunq/sdk/http/http_util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from typing import Dict


class HttpUtil:
QUERY_FORMAT = '{}={}'
QUERY_DELIMITER = '&'

@classmethod
def create_query_string(cls, all_parameter: Dict[str, str]):
encoded_parameters = []

for parameter, value in all_parameter.items():
encoded_parameters.append(cls.QUERY_FORMAT.format(parameter, value))

return cls.QUERY_DELIMITER.join(encoded_parameters)
48 changes: 19 additions & 29 deletions bunq/sdk/json/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import typing
import warnings
from types import ModuleType
from typing import Type, Optional, Callable, Generator, Any, Dict, Match, List, Union, Generic
from typing import Type, Optional, Callable, Generator, Dict, Match, List, Union, Generic

from bunq.sdk.exception.bunq_exception import BunqException
from bunq.sdk.util.type_alias import T, JsonValue
Expand Down Expand Up @@ -74,14 +74,14 @@ def register_custom_adapter(cls,
cls._custom_deserializers[class_name] = adapter

@classmethod
def _get_serializer(cls, cls_for: Type[Any]) -> type:
def _get_serializer(cls, cls_for: Type[T]) -> type:
if cls_for.__name__ in cls._custom_serializers:
return cls._custom_serializers[cls_for.__name__]

return JsonAdapter

@classmethod
def _get_deserializer(cls, cls_for: Type[Any]) -> Type[JsonAdapter]:
def _get_deserializer(cls, cls_for: Type[T]) -> Type[JsonAdapter]:
if cls_for.__name__ in cls._custom_deserializers:
return cls._custom_deserializers[cls_for.__name__]

Expand Down Expand Up @@ -121,7 +121,7 @@ def _deserialize_default(cls,
@classmethod
def _is_deserialized(cls,
cls_target: Type[T],
obj: Any) -> bool:
obj: T) -> bool:
if cls_target is None:
return True

Expand Down Expand Up @@ -151,7 +151,7 @@ def _deserialize_dict(cls,

@classmethod
def _deserialize_dict_attributes(cls,
cls_context: Type[Any],
cls_context: Type[T],
dict_: Dict) -> Dict:
dict_deserialized = {}

Expand Down Expand Up @@ -243,7 +243,7 @@ def _str_to_type(cls,
@classmethod
def _str_to_type_from_member_module(cls,
module_: ModuleType,
string: str) -> Type[Any]:
string: str) -> Type[T]:
"""
:raise: BunqException when could not find the class for the string.
Expand Down Expand Up @@ -307,7 +307,7 @@ def can_serialize(cls) -> bool:
return True

@classmethod
def serialize(cls, obj: Any) -> JsonValue:
def serialize(cls, obj: T) -> JsonValue:
cls._initialize()
serializer = cls._get_serializer(type(obj))

Expand All @@ -317,7 +317,7 @@ def serialize(cls, obj: Any) -> JsonValue:
return serializer.serialize(obj)

@classmethod
def _serialize_default(cls, obj: Any) -> JsonValue:
def _serialize_default(cls, obj: T) -> JsonValue:
if obj is None or cls._is_primitive(obj):
return obj
elif cls._is_bytes(obj):
Expand All @@ -330,19 +330,19 @@ def _serialize_default(cls, obj: Any) -> JsonValue:
return cls._serialize_dict(dict_)

@classmethod
def _is_primitive(cls, obj: Any) -> bool:
def _is_primitive(cls, obj: T) -> bool:
return cls._is_type_primitive(type(obj))

@classmethod
def _is_type_primitive(cls, type_: Type[Any]) -> bool:
def _is_type_primitive(cls, type_: Type[T]) -> bool:
return type_ in {int, str, bool, float}

@classmethod
def _is_bytes(cls, obj: Any) -> bool:
def _is_bytes(cls, obj: T) -> bool:
return cls._is_bytes_type(type(obj))

@classmethod
def _is_bytes_type(cls, type_: Type[Any]) -> bool:
def _is_bytes_type(cls, type_: Type[T]) -> bool:
return type_.__name__ in cls._TYPE_NAMES_BYTES

@classmethod
Expand All @@ -356,7 +356,7 @@ def _serialize_list(cls, list_: List) -> List:
return list_serialized

@classmethod
def _get_obj_raw(cls, obj: Any) -> Dict:
def _get_obj_raw(cls, obj: T) -> Dict:
return obj if type(obj) == dict else obj.__dict__

@classmethod
Expand All @@ -375,32 +375,22 @@ def _serialize_dict(cls, dict_: Dict) -> Dict:


class ValueTypes:
"""
:type _main: type|None
:type _sub: type|None
"""

def __init__(self,
main: Type[Any] = None,
sub: Type[Any] = None) -> None:
main: Type[T] = None,
sub: Type[T] = None) -> None:
self._main = main
self._sub = sub

@property
def main(self) -> Type[Any]:
def main(self) -> Type[T]:
return self._main

@property
def sub(self) -> Type[Any]:
def sub(self) -> Type[T]:
return self._sub


class ValueSpecs:
"""
:type _name: str|None
:type _types: ValueTypes|None
"""

def __init__(self,
name: str = None,
types: ValueTypes = None) -> None:
Expand Down Expand Up @@ -444,11 +434,11 @@ def deserialize(cls: Type[T], obj_raw: JsonValue) -> T:
return JsonAdapter.deserialize(cls, obj_raw)


def class_to_json(obj: Any) -> JsonValue:
def class_to_json(obj: T) -> JsonValue:
obj_raw = serialize(obj)

return json.dumps(obj_raw, indent=_JSON_INDENT, sort_keys=True)


def serialize(obj_cls: Any) -> JsonValue:
def serialize(obj_cls: T) -> JsonValue:
return JsonAdapter.serialize(obj_cls)
1 change: 1 addition & 0 deletions bunq/sdk/json/session_server_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def deserialize(cls,
),
cls._ATTRIBUTE_USER_COMPANY: None,
cls._ATTRIBUTE_USER_PERSON: None,
cls._ATTRIBUTE_USER_PAYMENT_SERVER_PROVIDER: None,
}

user_dict_wrapped = array[cls._INDEX_USER]
Expand Down
Loading

0 comments on commit 78390d2

Please sign in to comment.