-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Migration: deprecate borderless-accounts endpoint, and provide accoun…
…t-detail and balance-statement endpoints. (#25)
- Loading branch information
1 parent
dccfe9f
commit 9f8b2cd
Showing
8 changed files
with
293 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
from typing import Any | ||
|
||
from apiron import JsonEndpoint | ||
from munch import munchify | ||
|
||
from pywisetransfer import Client | ||
from pywisetransfer.base import Base | ||
|
||
|
||
class AccountDetailsService(Base): | ||
list = JsonEndpoint(path="/v1/profiles/{profile_id}/account-details") | ||
|
||
|
||
class AccountDetails: | ||
def __init__(self, client: Client): | ||
self.service = AccountDetailsService(client=client) | ||
|
||
def list(self, profile_id: str) -> list[Any]: | ||
return munchify(self.service.list(profile_id=profile_id)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
from typing import Any | ||
|
||
from munch import munchify | ||
|
||
from pywisetransfer import Client | ||
from pywisetransfer.base import Base | ||
from pywisetransfer.endpoint import JsonEndpointWithSCA | ||
|
||
|
||
class BalanceStatementsService(Base): | ||
statement = JsonEndpointWithSCA( | ||
path="/v1/profiles/{profile_id}/balance-statements/{balance_id}/statement.json", | ||
required_params=["currency", "intervalStart", "intervalEnd"], | ||
) | ||
|
||
|
||
class BalanceStatements: | ||
def __init__(self, client: Client): | ||
self.service = BalanceStatementsService(client=client) | ||
|
||
def statement( | ||
self, | ||
profile_id: str, | ||
balance_id: str, | ||
currency: str, | ||
interval_start: str, | ||
interval_end: str, | ||
type: str = "COMPACT", | ||
) -> Any: | ||
valid_types = ["COMPACT", "FLAT"] | ||
if type not in valid_types: | ||
raise ValueError(f"Invalid type '{type}'; value values are: {valid_types}") | ||
|
||
return munchify( | ||
self.service.statement( | ||
profile_id=profile_id, | ||
balance_id=balance_id, | ||
params={ | ||
"currency": currency, | ||
"intervalStart": interval_start, | ||
"intervalEnd": interval_end, | ||
"type": type, | ||
}, | ||
) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from typing import Any | ||
|
||
from apiron import JsonEndpoint | ||
from munch import munchify | ||
|
||
from pywisetransfer import Client | ||
from pywisetransfer.base import Base | ||
|
||
|
||
class BalancesService(Base): | ||
list = JsonEndpoint(path="/v4/profiles/{profile_id}/balances", required_params=["types"]) | ||
get = JsonEndpoint(path="/v4/profiles/{profile_id}/balances/{balance_id}") | ||
|
||
|
||
class Balances: | ||
def __init__(self, client: Client): | ||
self.service = BalancesService(client=client) | ||
|
||
def list(self, profile_id: str, types: str | list[str] = "STANDARD") -> Any: | ||
if not isinstance(types, list): | ||
assert isinstance(types, str) | ||
types = [types] | ||
|
||
valid_types = ["STANDARD", "SAVINGS"] | ||
for value in types: | ||
assert isinstance(value, str) | ||
if value not in valid_types: | ||
raise ValueError(f"Invalid type '{type}'; value values are: {valid_types}") | ||
|
||
params = {"types": ",".join(types)} | ||
return munchify(self.service.list(profile_id=profile_id, params=params)) | ||
|
||
def get(self, profile_id: str, balance_id: str) -> Any: | ||
return munchify(self.service.get(profile_id=profile_id, balance_id=balance_id)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
from __future__ import annotations | ||
|
||
import warnings | ||
|
||
|
||
class deprecated: | ||
"""Decorator to indicate that a method is deprecated, with an optional | ||
message to emit in the warning. | ||
Written following guidance from: | ||
https://blog.miguelgrinberg.com/post/the-ultimate-guide-to-python-decorators-part-iii-decorators-with-arguments | ||
""" | ||
|
||
def __init__(self, *args, **kwargs): | ||
if len(args) == 1 and callable(args[0]): | ||
self.f = args[0] | ||
message = args[1] if len(args) > 1 else None | ||
else: | ||
self.f = None | ||
message = args[0] if len(args) == 1 else None | ||
self.message = kwargs.get("message", message) | ||
|
||
def __call__(self, *args, **kwargs): | ||
if self.f is None and len(args) == 1 and callable(args[0]): | ||
self.f = args[0] | ||
return self | ||
|
||
warnings.warn(self.message, DeprecationWarning, stacklevel=2) | ||
return self.f(*args, **kwargs) | ||
|
||
def __repr__(self): | ||
return f"<deprecated {repr(self.f)}>" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
from warnings import catch_warnings | ||
|
||
import pytest | ||
|
||
from pywisetransfer.deprecation import deprecated | ||
|
||
record_warnings = lambda: catch_warnings(record=True) | ||
|
||
|
||
def undecorated(): | ||
return 1 | ||
|
||
|
||
@deprecated | ||
def bare_decorator(): | ||
return 1 | ||
|
||
|
||
@deprecated() | ||
def zero_args_decorator(): | ||
return 1 | ||
|
||
|
||
@deprecated("positional") | ||
def posarg_decorator(): | ||
return 1 | ||
|
||
|
||
@deprecated(message="keyword") | ||
def kwarg_decorator(): | ||
return 1 | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"func, name, deprecated, message", | ||
[ | ||
(undecorated, "undecorated", False, None), | ||
(bare_decorator, "bare_decorator", True, None), | ||
(zero_args_decorator, "zero_args_decorator", True, None), | ||
(posarg_decorator, "posarg_decorator", True, "positional"), | ||
(kwarg_decorator, "kwarg_decorator", True, "keyword"), | ||
], | ||
) | ||
def test_no_decorator(func, name, deprecated, message): | ||
actual_repr = repr(func) | ||
with record_warnings() as ws: | ||
result = func() | ||
|
||
# Check the Python repr of the function | ||
assert name in actual_repr | ||
actual_deprecated = "deprecated" in actual_repr | ||
assert deprecated == actual_deprecated | ||
|
||
# Check the behaviour of the function | ||
assert result == 1 | ||
|
||
# Check the warnings emitted by the function | ||
assert ws if deprecated else not ws | ||
assert any([message in str(w.message) for w in ws] if message else [True]) |
Oops, something went wrong.