mirror of
https://github.com/aljazceru/bitfinex-api-py.git
synced 2025-12-19 23:04:21 +01:00
Add tests subpackage. Add TestRestSerializersAndTypes and TestWebsocketSerializersAndTypes unit tests. Fix consistency bugs between serializers and types.
This commit is contained in:
@@ -28,6 +28,9 @@ class _Serializer(Generic[T]):
|
|||||||
def parse(self, *values: Any, skip: Optional[List[str]] = None) -> T:
|
def parse(self, *values: Any, skip: Optional[List[str]] = None) -> T:
|
||||||
return cast(T, self.klass(**dict(self._serialize(*values, skip=skip))))
|
return cast(T, self.klass(**dict(self._serialize(*values, skip=skip))))
|
||||||
|
|
||||||
|
def get_labels(self) -> List[str]:
|
||||||
|
return [ label for label in self.__labels if label not in self.__IGNORE ]
|
||||||
|
|
||||||
class _RecursiveSerializer(_Serializer, Generic[T]):
|
class _RecursiveSerializer(_Serializer, Generic[T]):
|
||||||
def __init__(self, name: str, klass: Type[_Type], labels: List[str], serializers: Dict[str, _Serializer[Any]], IGNORE: List[str] = ["_PLACEHOLDER"]):
|
def __init__(self, name: str, klass: Type[_Type], labels: List[str], serializers: Dict[str, _Serializer[Any]], IGNORE: List[str] = ["_PLACEHOLDER"]):
|
||||||
super().__init__(name, klass, labels, IGNORE)
|
super().__init__(name, klass, labels, IGNORE)
|
||||||
|
|||||||
@@ -4,6 +4,26 @@ from .. labeler import generate_labeler_serializer, generate_recursive_serialize
|
|||||||
|
|
||||||
from .. notification import _Notification
|
from .. notification import _Notification
|
||||||
|
|
||||||
|
__serializers__ = [
|
||||||
|
"PlatformStatus", "TradingPairTicker", "FundingCurrencyTicker",
|
||||||
|
"TickersHistory", "TradingPairTrade", "FundingCurrencyTrade",
|
||||||
|
"TradingPairBook", "FundingCurrencyBook", "TradingPairRawBook",
|
||||||
|
"FundingCurrencyRawBook", "Statistic", "Candle",
|
||||||
|
"DerivativesStatus", "Liquidation", "Leaderboard",
|
||||||
|
"FundingStatistic", "PulseProfile", "PulseMessage",
|
||||||
|
"TradingMarketAveragePrice", "FundingMarketAveragePrice", "FxRate",
|
||||||
|
|
||||||
|
"Order", "Position", "Trade",
|
||||||
|
"FundingTrade", "OrderTrade", "Ledger",
|
||||||
|
"FundingOffer", "FundingCredit", "FundingLoan",
|
||||||
|
"FundingAutoRenew", "FundingInfo", "Wallet",
|
||||||
|
"Transfer", "Withdrawal", "DepositAddress",
|
||||||
|
"Invoice", "Movement", "SymbolMarginInfo",
|
||||||
|
"BaseMarginInfo", "Claim", "IncreaseInfo",
|
||||||
|
"Increase", "PositionHistory", "PositionSnapshot",
|
||||||
|
"PositionAudit", "DerivativePositionCollateral", "DerivativePositionCollateralLimits",
|
||||||
|
]
|
||||||
|
|
||||||
#region Serializers definition for Rest Public Endpoints
|
#region Serializers definition for Rest Public Endpoints
|
||||||
|
|
||||||
PlatformStatus = generate_labeler_serializer("PlatformStatus", klass=types.PlatformStatus, labels=[
|
PlatformStatus = generate_labeler_serializer("PlatformStatus", klass=types.PlatformStatus, labels=[
|
||||||
@@ -308,7 +328,7 @@ Position = generate_labeler_serializer("Position", klass=types.Position, labels=
|
|||||||
|
|
||||||
Trade = generate_labeler_serializer("Trade", klass=types.Trade, labels=[
|
Trade = generate_labeler_serializer("Trade", klass=types.Trade, labels=[
|
||||||
"id",
|
"id",
|
||||||
"pair",
|
"symbol",
|
||||||
"mts_create",
|
"mts_create",
|
||||||
"order_id",
|
"order_id",
|
||||||
"exec_amount",
|
"exec_amount",
|
||||||
@@ -333,7 +353,7 @@ FundingTrade = generate_labeler_serializer("FundingTrade", klass=types.FundingTr
|
|||||||
|
|
||||||
OrderTrade = generate_labeler_serializer("OrderTrade", klass=types.OrderTrade, labels=[
|
OrderTrade = generate_labeler_serializer("OrderTrade", klass=types.OrderTrade, labels=[
|
||||||
"id",
|
"id",
|
||||||
"pair",
|
"symbol",
|
||||||
"mts_create",
|
"mts_create",
|
||||||
"order_id",
|
"order_id",
|
||||||
"exec_amount",
|
"exec_amount",
|
||||||
|
|||||||
@@ -6,12 +6,32 @@ from .. labeler import _Type
|
|||||||
from .. notification import Notification
|
from .. notification import Notification
|
||||||
from .. utils.encoder import JSON
|
from .. utils.encoder import JSON
|
||||||
|
|
||||||
|
__types__ = [
|
||||||
|
"PlatformStatus", "TradingPairTicker", "FundingCurrencyTicker",
|
||||||
|
"TickersHistory", "TradingPairTrade", "FundingCurrencyTrade",
|
||||||
|
"TradingPairBook", "FundingCurrencyBook", "TradingPairRawBook",
|
||||||
|
"FundingCurrencyRawBook", "Statistic", "Candle",
|
||||||
|
"DerivativesStatus", "Liquidation", "Leaderboard",
|
||||||
|
"FundingStatistic", "PulseProfile", "PulseMessage",
|
||||||
|
"TradingMarketAveragePrice", "FundingMarketAveragePrice", "FxRate",
|
||||||
|
|
||||||
|
"Order", "Position", "Trade",
|
||||||
|
"FundingTrade", "OrderTrade", "Ledger",
|
||||||
|
"FundingOffer", "FundingCredit", "FundingLoan",
|
||||||
|
"FundingAutoRenew", "FundingInfo", "Wallet",
|
||||||
|
"Transfer", "Withdrawal", "DepositAddress",
|
||||||
|
"Invoice", "Movement", "SymbolMarginInfo",
|
||||||
|
"BaseMarginInfo", "Claim", "IncreaseInfo",
|
||||||
|
"Increase", "PositionHistory", "PositionSnapshot",
|
||||||
|
"PositionAudit", "DerivativePositionCollateral", "DerivativePositionCollateralLimits",
|
||||||
|
]
|
||||||
|
|
||||||
#region Type hinting for Rest Public Endpoints
|
#region Type hinting for Rest Public Endpoints
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class PlatformStatus(_Type):
|
class PlatformStatus(_Type):
|
||||||
status: int
|
status: int
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class TradingPairTicker(_Type):
|
class TradingPairTicker(_Type):
|
||||||
symbol: Optional[str]
|
symbol: Optional[str]
|
||||||
|
|||||||
8
bfxapi/tests/__init__.py
Normal file
8
bfxapi/tests/__init__.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import unittest
|
||||||
|
from .test_rest_serializers_and_types import TestRestSerializersAndTypes
|
||||||
|
from .test_websocket_serializers_and_types import TestWebsocketSerializersAndTypes
|
||||||
|
|
||||||
|
NAME = "tests"
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
23
bfxapi/tests/test_rest_serializers_and_types.py
Normal file
23
bfxapi/tests/test_rest_serializers_and_types.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from ..rest import serializers, types
|
||||||
|
|
||||||
|
class TestRestSerializersAndTypes(unittest.TestCase):
|
||||||
|
def test_consistency(self):
|
||||||
|
__types__ = list(map(types.__dict__.get, types.__types__))
|
||||||
|
|
||||||
|
for serializer in map(serializers.__dict__.get, serializers.__serializers__):
|
||||||
|
type = types.__dict__.get(serializer.name)
|
||||||
|
|
||||||
|
__types__.remove(type)
|
||||||
|
self.assertIsNotNone(type, f"_Serializer <{serializer.name}>: no respective _Type found in bfxapi.rest.types.")
|
||||||
|
self.assertEqual(serializer.klass, type, f"_Serializer <{serializer.name}>.klass: field does not match with respective _Type in bfxapi.rest.types.")
|
||||||
|
|
||||||
|
self.assertListEqual(serializer.get_labels(), list(type.__annotations__),
|
||||||
|
f"_Serializer <{serializer.name}> and _Type <{type.__name__}> must have matching labels and fields.")
|
||||||
|
|
||||||
|
for type in __types__:
|
||||||
|
self.fail(f"_Type <{type.__name__}>: no respective _Serializer found in bfxapi.rest.serializers.")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
23
bfxapi/tests/test_websocket_serializers_and_types.py
Normal file
23
bfxapi/tests/test_websocket_serializers_and_types.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from ..websocket import serializers, types
|
||||||
|
|
||||||
|
class TestWebsocketSerializersAndTypes(unittest.TestCase):
|
||||||
|
def test_consistency(self):
|
||||||
|
__types__ = list(map(types.__dict__.get, types.__types__))
|
||||||
|
|
||||||
|
for serializer in map(serializers.__dict__.get, serializers.__serializers__):
|
||||||
|
type = types.__dict__.get(serializer.name)
|
||||||
|
|
||||||
|
__types__.remove(type)
|
||||||
|
self.assertIsNotNone(type, f"_Serializer <{serializer.name}>: no respective _Type found in bfxapi.websocket.types.")
|
||||||
|
self.assertEqual(serializer.klass, type, f"_Serializer <{serializer.name}>.klass: field does not match with respective _Type in bfxapi.websocket.types.")
|
||||||
|
|
||||||
|
self.assertListEqual(serializer.get_labels(), list(type.__annotations__),
|
||||||
|
f"_Serializer <{serializer.name}> and _Type <{type.__name__}> must have matching labels and fields.")
|
||||||
|
|
||||||
|
for type in __types__:
|
||||||
|
self.fail(f"_Type <{type.__name__}>: no respective _Serializer found in bfxapi.websocket.serializers.")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
@@ -4,6 +4,17 @@ from .. labeler import generate_labeler_serializer
|
|||||||
|
|
||||||
from .. notification import _Notification
|
from .. notification import _Notification
|
||||||
|
|
||||||
|
__serializers__ = [
|
||||||
|
"TradingPairTicker", "FundingCurrencyTicker", "TradingPairTrade",
|
||||||
|
"FundingCurrencyTrade", "TradingPairBook", "FundingCurrencyBook",
|
||||||
|
"TradingPairRawBook", "FundingCurrencyRawBook", "Candle",
|
||||||
|
"DerivativesStatus",
|
||||||
|
|
||||||
|
"Order", "Position", "Trade",
|
||||||
|
"FundingOffer", "FundingCredit", "FundingLoan",
|
||||||
|
"Wallet", "Balance",
|
||||||
|
]
|
||||||
|
|
||||||
#region Serializers definition for Websocket Public Channels
|
#region Serializers definition for Websocket Public Channels
|
||||||
|
|
||||||
TradingPairTicker = generate_labeler_serializer("TradingPairTicker", klass=types.TradingPairTicker, labels=[
|
TradingPairTicker = generate_labeler_serializer("TradingPairTicker", klass=types.TradingPairTicker, labels=[
|
||||||
@@ -32,7 +43,7 @@ FundingCurrencyTicker = generate_labeler_serializer("FundingCurrencyTicker", kla
|
|||||||
"last_price",
|
"last_price",
|
||||||
"volume",
|
"volume",
|
||||||
"high",
|
"high",
|
||||||
"low"
|
"low",
|
||||||
"_PLACEHOLDER",
|
"_PLACEHOLDER",
|
||||||
"_PLACEHOLDER",
|
"_PLACEHOLDER",
|
||||||
"frr_amount_available"
|
"frr_amount_available"
|
||||||
@@ -100,7 +111,7 @@ DerivativesStatus = generate_labeler_serializer("DerivativesStatus", klass=types
|
|||||||
"next_funding_accrued",
|
"next_funding_accrued",
|
||||||
"next_funding_step",
|
"next_funding_step",
|
||||||
"_PLACEHOLDER",
|
"_PLACEHOLDER",
|
||||||
"current_funding"
|
"current_funding",
|
||||||
"_PLACEHOLDER",
|
"_PLACEHOLDER",
|
||||||
"_PLACEHOLDER",
|
"_PLACEHOLDER",
|
||||||
"mark_price",
|
"mark_price",
|
||||||
|
|||||||
@@ -6,6 +6,17 @@ from ..labeler import _Type
|
|||||||
from ..notification import Notification
|
from ..notification import Notification
|
||||||
from .. utils.encoder import JSON
|
from .. utils.encoder import JSON
|
||||||
|
|
||||||
|
__types__ = [
|
||||||
|
"TradingPairTicker", "FundingCurrencyTicker", "TradingPairTrade",
|
||||||
|
"FundingCurrencyTrade", "TradingPairBook", "FundingCurrencyBook",
|
||||||
|
"TradingPairRawBook", "FundingCurrencyRawBook", "Candle",
|
||||||
|
"DerivativesStatus",
|
||||||
|
|
||||||
|
"Order", "Position", "Trade",
|
||||||
|
"FundingOffer", "FundingCredit", "FundingLoan",
|
||||||
|
"Wallet", "Balance",
|
||||||
|
]
|
||||||
|
|
||||||
#region Type hinting for Websocket Public Channels
|
#region Type hinting for Websocket Public Channels
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -143,6 +154,7 @@ class Position(_Type):
|
|||||||
pl_perc: float
|
pl_perc: float
|
||||||
price_liq: float
|
price_liq: float
|
||||||
leverage: float
|
leverage: float
|
||||||
|
flag: int
|
||||||
position_id: int
|
position_id: int
|
||||||
mts_create: int
|
mts_create: int
|
||||||
mts_update: int
|
mts_update: int
|
||||||
|
|||||||
Reference in New Issue
Block a user