mirror of
https://github.com/aljazceru/bitfinex-api-py.git
synced 2025-12-18 22:34:21 +01:00
Improve fidelity to pylint's standard rules.
This commit is contained in:
16
.pylintrc
16
.pylintrc
@@ -3,28 +3,20 @@ py-version=3.8.0
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
disable=
|
||||
multiple-imports,
|
||||
missing-docstring,
|
||||
logging-not-lazy,
|
||||
logging-fstring-interpolation,
|
||||
multiple-imports,
|
||||
too-few-public-methods,
|
||||
too-many-public-methods,
|
||||
too-many-instance-attributes,
|
||||
dangerous-default-value,
|
||||
inconsistent-return-statements,
|
||||
|
||||
[SIMILARITIES]
|
||||
min-similarity-lines=6
|
||||
too-many-instance-attributes
|
||||
|
||||
[VARIABLES]
|
||||
allowed-redefined-builtins=type,dir,id,all,format,len
|
||||
allowed-redefined-builtins=all,dir,format,id,len,type
|
||||
|
||||
[FORMAT]
|
||||
max-line-length=120
|
||||
expected-line-ending-format=LF
|
||||
|
||||
[BASIC]
|
||||
good-names=t,f,id,ip,on,pl,tf,to,A,B,C,D,E,F
|
||||
good-names=f,t,id,ip,on,pl,tf,to,A,B,C,D,E,F
|
||||
|
||||
[TYPECHECK]
|
||||
generated-members=websockets
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from typing import \
|
||||
TYPE_CHECKING, List, Literal, Optional
|
||||
TYPE_CHECKING, List, Optional
|
||||
|
||||
from bfxapi._utils.logging import ColorLogger
|
||||
|
||||
@@ -23,8 +23,7 @@ class Client:
|
||||
wss_host: str = WSS_HOST,
|
||||
filters: Optional[List[str]] = None,
|
||||
timeout: Optional[int] = 60 * 15,
|
||||
log_filename: Optional[str] = None,
|
||||
log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] = "INFO"
|
||||
log_filename: Optional[str] = None
|
||||
) -> None:
|
||||
credentials: Optional["_Credentials"] = None
|
||||
|
||||
@@ -40,7 +39,7 @@ class Client:
|
||||
|
||||
self.rest = BfxRestInterface(rest_host, api_key, api_secret)
|
||||
|
||||
logger = ColorLogger("bfxapi", level=log_level)
|
||||
logger = ColorLogger("bfxapi", level="INFO")
|
||||
|
||||
if log_filename:
|
||||
logger.register(filename=log_filename)
|
||||
|
||||
@@ -22,6 +22,7 @@ from ...types import serializers
|
||||
|
||||
from ...types.serializers import _Notification
|
||||
|
||||
#pylint: disable-next=too-many-public-methods
|
||||
class RestAuthEndpoints(Middleware):
|
||||
def get_user_info(self) -> UserInfo:
|
||||
return serializers.UserInfo \
|
||||
|
||||
@@ -148,6 +148,7 @@ class RestMerchantEndpoints(Middleware):
|
||||
def get_merchant_settings(self, key: MerchantSettingsKey) -> Any:
|
||||
return self._post("auth/r/ext/pay/settings/get", body={ "key": key })
|
||||
|
||||
#pylint: disable-next=dangerous-default-value
|
||||
def list_merchant_settings(self, keys: List[MerchantSettingsKey] = []) -> Dict[MerchantSettingsKey, Any]:
|
||||
return self._post("auth/r/ext/pay/settings/list", body={ "keys": keys })
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ from ...types import \
|
||||
|
||||
from ...types import serializers
|
||||
|
||||
#pylint: disable-next=too-many-public-methods
|
||||
class RestPublicEndpoints(Middleware):
|
||||
def conf(self, config: Config) -> Any:
|
||||
return self._get(f"conf/{config}")[0]
|
||||
|
||||
@@ -34,8 +34,8 @@ class _Type:
|
||||
|
||||
class _Serializer(Generic[T]):
|
||||
def __init__(self, name: str, klass: Type[_Type], labels: List[str],
|
||||
*, flat: bool = False, ignore: List[str] = [ "_PLACEHOLDER" ]):
|
||||
self.name, self.klass, self.__labels, self.__flat, self.__ignore = name, klass, labels, flat, ignore
|
||||
*, flat: bool = False):
|
||||
self.name, self.klass, self.__labels, self.__flat = name, klass, labels, flat
|
||||
|
||||
def _serialize(self, *args: Any) -> Iterable[Tuple[str, Any]]:
|
||||
if self.__flat:
|
||||
@@ -46,14 +46,14 @@ class _Serializer(Generic[T]):
|
||||
"arguments should contain the same amount of elements.")
|
||||
|
||||
for index, label in enumerate(self.__labels):
|
||||
if label not in self.__ignore:
|
||||
if label != "_PLACEHOLDER":
|
||||
yield label, args[index]
|
||||
|
||||
def parse(self, *values: Any) -> T:
|
||||
return cast(T, self.klass(**dict(self._serialize(*values))))
|
||||
|
||||
def get_labels(self) -> List[str]:
|
||||
return [ label for label in self.__labels if label not in self.__ignore ]
|
||||
return [ label for label in self.__labels if label != "_PLACEHOLDER" ]
|
||||
|
||||
@classmethod
|
||||
def __flatten(cls, array: List[Any]) -> List[Any]:
|
||||
@@ -68,8 +68,8 @@ class _Serializer(Generic[T]):
|
||||
class _RecursiveSerializer(_Serializer, Generic[T]):
|
||||
def __init__(self, name: str, klass: Type[_Type], labels: List[str],
|
||||
*, serializers: Dict[str, _Serializer[Any]],
|
||||
flat: bool = False, ignore: List[str] = [ "_PLACEHOLDER" ]):
|
||||
super().__init__(name, klass, labels, flat=flat, ignore=ignore)
|
||||
flat: bool = False):
|
||||
super().__init__(name, klass, labels, flat=flat)
|
||||
|
||||
self.serializers = serializers
|
||||
|
||||
@@ -83,14 +83,14 @@ class _RecursiveSerializer(_Serializer, Generic[T]):
|
||||
return cast(T, self.klass(**serialization))
|
||||
|
||||
def generate_labeler_serializer(name: str, klass: Type[T], labels: List[str],
|
||||
*, flat: bool = False, ignore: List[str] = [ "_PLACEHOLDER" ]
|
||||
*, flat: bool = False
|
||||
) -> _Serializer[T]:
|
||||
return _Serializer[T](name, klass, labels, \
|
||||
flat=flat, ignore=ignore)
|
||||
flat=flat)
|
||||
|
||||
def generate_recursive_serializer(name: str, klass: Type[T], labels: List[str],
|
||||
*, serializers: Dict[str, _Serializer[Any]],
|
||||
flat: bool = False, ignore: List[str] = [ "_PLACEHOLDER" ]
|
||||
flat: bool = False
|
||||
) -> _RecursiveSerializer[T]:
|
||||
return _RecursiveSerializer[T](name, klass, labels, \
|
||||
serializers=serializers, flat=flat, ignore=ignore)
|
||||
serializers=serializers, flat=flat)
|
||||
|
||||
@@ -18,7 +18,7 @@ class _Notification(_Serializer, Generic[T]):
|
||||
__LABELS = [ "mts", "type", "message_id", "_PLACEHOLDER", "data", "code", "status", "text" ]
|
||||
|
||||
def __init__(self, serializer: Optional[_Serializer] = None, is_iterable: bool = False):
|
||||
super().__init__("Notification", Notification, _Notification.__LABELS, ignore = [ "_PLACEHOLDER" ])
|
||||
super().__init__("Notification", Notification, _Notification.__LABELS)
|
||||
|
||||
self.serializer, self.is_iterable = serializer, is_iterable
|
||||
|
||||
|
||||
@@ -3,9 +3,9 @@ from typing import \
|
||||
Optional, Any
|
||||
|
||||
from logging import Logger
|
||||
|
||||
from datetime import datetime
|
||||
from socket import gaierror
|
||||
|
||||
from asyncio import Task
|
||||
|
||||
import \
|
||||
@@ -68,6 +68,7 @@ class _Delay:
|
||||
def reset(self) -> None:
|
||||
self.__backoff_delay = _Delay.__BACKOFF_MIN
|
||||
|
||||
#pylint: disable-next=too-many-instance-attributes
|
||||
class BfxWebSocketClient(Connection):
|
||||
def __init__(self,
|
||||
host: str,
|
||||
@@ -101,6 +102,7 @@ class BfxWebSocketClient(Connection):
|
||||
stack_trace = traceback.format_exception( \
|
||||
type(exception), exception, exception.__traceback__)
|
||||
|
||||
#pylint: disable-next=logging-not-lazy
|
||||
self.__logger.critical(header + "\n" + \
|
||||
str().join(stack_trace)[:-1])
|
||||
|
||||
@@ -158,12 +160,11 @@ class BfxWebSocketClient(Connection):
|
||||
|
||||
if isinstance(error, ConnectionClosedError) and error.code in (1006, 1012):
|
||||
if error.code == 1006:
|
||||
self.__logger.error("Connection lost: no close frame " \
|
||||
"received or sent (1006). Trying to reconnect...")
|
||||
self.__logger.error("Connection lost: trying to reconnect...")
|
||||
|
||||
if error.code == 1012:
|
||||
self.__logger.info("WSS server is about to restart, clients need " \
|
||||
"to reconnect (server sent 20051). Reconnection attempt in progress...")
|
||||
self.__logger.warning("WSS server is restarting: all " \
|
||||
"clients need to reconnect (server sent 20051).")
|
||||
|
||||
if self.__timeout:
|
||||
asyncio.get_event_loop().call_later(
|
||||
@@ -177,10 +178,14 @@ class BfxWebSocketClient(Connection):
|
||||
_delay.reset()
|
||||
elif ((isinstance(error, InvalidStatusCode) and error.status_code == 408) or \
|
||||
isinstance(error, gaierror)) and self.__reconnection:
|
||||
self.__logger.warning(
|
||||
f"_Reconnection attempt was unsuccessful (no.{self.__reconnection['attempts']}). " \
|
||||
f"Next reconnection attempt in {int(_delay.peek())}.0 seconds. (at the moment " \
|
||||
f"the client has been offline for {datetime.now() - self.__reconnection['timestamp']})")
|
||||
#pylint: disable-next=logging-fstring-interpolation
|
||||
self.__logger.warning("Reconnection attempt unsuccessful (no." \
|
||||
f"{self.__reconnection['attempts']}): next attempt in " \
|
||||
f"~{int(_delay.peek())}.0s.")
|
||||
|
||||
#pylint: disable-next=logging-fstring-interpolation
|
||||
self.__logger.info(f"The client has been offline for " \
|
||||
f"{datetime.now() - self.__reconnection['timestamp']}.")
|
||||
|
||||
self.__reconnection["attempts"] += 1
|
||||
else:
|
||||
@@ -196,9 +201,10 @@ class BfxWebSocketClient(Connection):
|
||||
async def __connect(self) -> None:
|
||||
async with websockets.client.connect(self._host) as websocket:
|
||||
if self.__reconnection:
|
||||
self.__logger.info(f"_Reconnection attempt successful (no.{self.__reconnection['attempts']}): The " \
|
||||
f"client has been offline for a total of {datetime.now() - self.__reconnection['timestamp']} " \
|
||||
f"(connection lost on: {self.__reconnection['timestamp']:%d-%m-%Y at %H:%M:%S}).")
|
||||
#pylint: disable-next=logging-fstring-interpolation
|
||||
self.__logger.warning("Reconnection attempt successful (no." \
|
||||
f"{self.__reconnection['attempts']}): recovering " \
|
||||
"connection state...")
|
||||
|
||||
self.__reconnection = None
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ class AuthEventsHandler:
|
||||
|
||||
def handle(self, abbrevation: str, stream: Any) -> None:
|
||||
if abbrevation == "n":
|
||||
return self.__notification(stream)
|
||||
self.__notification(stream)
|
||||
|
||||
for abbrevations, serializer in AuthEventsHandler.__SERIALIZERS.items():
|
||||
if abbrevation in abbrevations:
|
||||
@@ -45,12 +45,11 @@ class AuthEventsHandler:
|
||||
|
||||
if all(isinstance(sub_stream, list) for sub_stream in stream):
|
||||
data = [ serializer.parse(*sub_stream) for sub_stream in stream ]
|
||||
else: data = serializer.parse(*stream)
|
||||
else:
|
||||
data = serializer.parse(*stream)
|
||||
|
||||
self.__event_emitter.emit(event, data)
|
||||
|
||||
break
|
||||
|
||||
def __notification(self, stream: Any) -> None:
|
||||
event: str = "notification"
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ class PublicChannelsHandler:
|
||||
elif subscription["channel"] == "status":
|
||||
self.__status_channel_handler(cast(Status, subscription), stream)
|
||||
|
||||
#pylint: disable-next=inconsistent-return-statements
|
||||
def __ticker_channel_handler(self, subscription: Ticker, stream: List[Any]):
|
||||
if subscription["symbol"].startswith("t"):
|
||||
return self.__event_emitter.emit("t_ticker_update", subscription, \
|
||||
@@ -44,6 +45,7 @@ class PublicChannelsHandler:
|
||||
return self.__event_emitter.emit("f_ticker_update", subscription, \
|
||||
serializers.FundingCurrencyTicker.parse(*stream[0]))
|
||||
|
||||
#pylint: disable-next=inconsistent-return-statements
|
||||
def __trades_channel_handler(self, subscription: Trades, stream: List[Any]):
|
||||
if (event := stream[0]) and event in [ "te", "tu", "fte", "ftu" ]:
|
||||
events = { "te": "t_trade_execution", "tu": "t_trade_execution_update", \
|
||||
@@ -67,6 +69,7 @@ class PublicChannelsHandler:
|
||||
[ serializers.FundingCurrencyTrade.parse(*sub_stream) \
|
||||
for sub_stream in stream[0] ])
|
||||
|
||||
#pylint: disable-next=inconsistent-return-statements
|
||||
def __book_channel_handler(self, subscription: Book, stream: List[Any]):
|
||||
if subscription["symbol"].startswith("t"):
|
||||
if all(isinstance(sub_stream, list) for sub_stream in stream[0]):
|
||||
@@ -86,6 +89,7 @@ class PublicChannelsHandler:
|
||||
return self.__event_emitter.emit("f_book_update", subscription, \
|
||||
serializers.FundingCurrencyBook.parse(*stream[0]))
|
||||
|
||||
#pylint: disable-next=inconsistent-return-statements
|
||||
def __raw_book_channel_handler(self, subscription: Book, stream: List[Any]):
|
||||
if subscription["symbol"].startswith("t"):
|
||||
if all(isinstance(sub_stream, list) for sub_stream in stream[0]):
|
||||
@@ -105,6 +109,7 @@ class PublicChannelsHandler:
|
||||
return self.__event_emitter.emit("f_raw_book_update", subscription, \
|
||||
serializers.FundingCurrencyRawBook.parse(*stream[0]))
|
||||
|
||||
#pylint: disable-next=inconsistent-return-statements
|
||||
def __candles_channel_handler(self, subscription: Candles, stream: List[Any]):
|
||||
if all(isinstance(sub_stream, list) for sub_stream in stream[0]):
|
||||
return self.__event_emitter.emit("candles_snapshot", subscription, \
|
||||
@@ -114,6 +119,7 @@ class PublicChannelsHandler:
|
||||
return self.__event_emitter.emit("candles_update", subscription, \
|
||||
serializers.Candle.parse(*stream[0]))
|
||||
|
||||
#pylint: disable-next=inconsistent-return-statements
|
||||
def __status_channel_handler(self, subscription: Status, stream: List[Any]):
|
||||
if subscription["key"].startswith("deriv:"):
|
||||
return self.__event_emitter.emit("derivatives_status_update", subscription, \
|
||||
@@ -123,6 +129,7 @@ class PublicChannelsHandler:
|
||||
return self.__event_emitter.emit("liquidation_feed_update", subscription, \
|
||||
serializers.Liquidation.parse(*stream[0][0]))
|
||||
|
||||
#pylint: disable-next=inconsistent-return-statements
|
||||
def __checksum_handler(self, subscription: Book, value: int):
|
||||
return self.__event_emitter.emit( \
|
||||
"checksum", subscription, value & 0xFFFFFFFF)
|
||||
|
||||
Reference in New Issue
Block a user