Improve fidelity to pylint's standard rules.

This commit is contained in:
Davide Casale
2023-10-26 05:09:10 +02:00
parent ac50f8f884
commit 8e915e42eb
10 changed files with 49 additions and 43 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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 \

View File

@@ -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 })

View File

@@ -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]

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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)