Rename BfxWebsocketClient, BfxWebsocketBucket and BfxWebsocketInputs to BfxWebSocketClient, BfxWebSocketBucket and BfxWebSocketInputs.

This commit is contained in:
Davide Casale
2023-04-20 01:36:09 +02:00
parent 99783c1a5a
commit d80b8b8721
11 changed files with 48 additions and 48 deletions

View File

@@ -1,7 +1,7 @@
from typing import List, Literal, Optional from typing import List, Literal, Optional
from .rest import BfxRestInterface from .rest import BfxRestInterface
from .websocket import BfxWebsocketClient from .websocket import BfxWebSocketClient
from .urls import REST_HOST, WSS_HOST from .urls import REST_HOST, WSS_HOST
class Client: class Client:
@@ -27,7 +27,7 @@ class Client:
credentials=credentials credentials=credentials
) )
self.wss = BfxWebsocketClient( self.wss = BfxWebSocketClient(
host=wss_host, host=wss_host,
credentials=credentials, credentials=credentials,
wss_timeout=wss_timeout, wss_timeout=wss_timeout,

View File

@@ -1,14 +1,14 @@
import unittest import unittest
from .test_rest_serializers import TestRestSerializers from .test_rest_serializers import TestRestSerializers
from .test_websocket_serializers import TestWebsocketSerializers from .test_websocket_serializers import TestWebSocketSerializers
from .test_labeler import TestLabeler from .test_labeler import TestLabeler
from .test_notification import TestNotification from .test_notification import TestNotification
def suite(): def suite():
return unittest.TestSuite([ return unittest.TestSuite([
unittest.makeSuite(TestRestSerializers), unittest.makeSuite(TestRestSerializers),
unittest.makeSuite(TestWebsocketSerializers), unittest.makeSuite(TestWebSocketSerializers),
unittest.makeSuite(TestLabeler), unittest.makeSuite(TestLabeler),
unittest.makeSuite(TestNotification), unittest.makeSuite(TestNotification),
]) ])

View File

@@ -6,7 +6,7 @@ from ..labeler import _Type
from ..websocket import serializers from ..websocket import serializers
class TestWebsocketSerializers(unittest.TestCase): class TestWebSocketSerializers(unittest.TestCase):
def test_websocket_serializers(self): def test_websocket_serializers(self):
for serializer in map(serializers.__dict__.get, serializers.__serializers__): for serializer in map(serializers.__dict__.get, serializers.__serializers__):
self.assertTrue(issubclass(serializer.klass, _Type), self.assertTrue(issubclass(serializer.klass, _Type),

View File

@@ -1 +1 @@
from .client import BfxWebsocketClient, BfxWebsocketBucket, BfxWebsocketInputs from .client import BfxWebSocketClient, BfxWebSocketBucket, BfxWebSocketInputs

View File

@@ -1,3 +1,3 @@
from .bfx_websocket_client import BfxWebsocketClient from .bfx_websocket_client import BfxWebSocketClient
from .bfx_websocket_bucket import BfxWebsocketBucket from .bfx_websocket_bucket import BfxWebSocketBucket
from .bfx_websocket_inputs import BfxWebsocketInputs from .bfx_websocket_inputs import BfxWebSocketInputs

View File

@@ -19,7 +19,7 @@ def _require_websocket_connection(function: F) -> F:
return cast(F, wrapper) return cast(F, wrapper)
class BfxWebsocketBucket: class BfxWebSocketBucket:
VERSION = 2 VERSION = 2
MAXIMUM_SUBSCRIPTIONS_AMOUNT = 25 MAXIMUM_SUBSCRIPTIONS_AMOUNT = 25
@@ -81,7 +81,7 @@ class BfxWebsocketBucket:
@_require_websocket_connection @_require_websocket_connection
async def subscribe(self, channel, sub_id=None, **kwargs): async def subscribe(self, channel, sub_id=None, **kwargs):
if len(self.subscriptions) + len(self.pendings) == BfxWebsocketBucket.MAXIMUM_SUBSCRIPTIONS_AMOUNT: if len(self.subscriptions) + len(self.pendings) == BfxWebSocketBucket.MAXIMUM_SUBSCRIPTIONS_AMOUNT:
raise TooManySubscriptions("The client has reached the maximum number of subscriptions.") raise TooManySubscriptions("The client has reached the maximum number of subscriptions.")
subscription = { subscription = {

View File

@@ -8,11 +8,11 @@ import traceback, json, asyncio, hmac, hashlib, time, socket, random, websockets
from pyee.asyncio import AsyncIOEventEmitter from pyee.asyncio import AsyncIOEventEmitter
from .bfx_websocket_bucket import _HEARTBEAT, F, _require_websocket_connection, BfxWebsocketBucket from .bfx_websocket_bucket import _HEARTBEAT, F, _require_websocket_connection, BfxWebSocketBucket
from .bfx_websocket_inputs import BfxWebsocketInputs from .bfx_websocket_inputs import BfxWebSocketInputs
from ..handlers import PublicChannelsHandler, AuthenticatedEventsHandler from ..handlers import PublicChannelsHandler, AuthenticatedEventsHandler
from ..exceptions import WebsocketAuthenticationRequired, InvalidAuthenticationCredentials, EventNotSupported, \ from ..exceptions import WebSocketAuthenticationRequired, InvalidAuthenticationCredentials, EventNotSupported, \
ZeroConnectionsError, ReconnectionTimeoutError, OutdatedClientVersion ZeroConnectionsError, ReconnectionTimeoutError, OutdatedClientVersion
from ...utils.json_encoder import JSONEncoder from ...utils.json_encoder import JSONEncoder
@@ -22,7 +22,7 @@ from ...utils.logger import ColorLogger, FileLogger
def _require_websocket_authentication(function: F) -> F: def _require_websocket_authentication(function: F) -> F:
async def wrapper(self, *args, **kwargs): async def wrapper(self, *args, **kwargs):
if hasattr(self, "authentication") and not self.authentication: if hasattr(self, "authentication") and not self.authentication:
raise WebsocketAuthenticationRequired("To perform this action you need to " \ raise WebSocketAuthenticationRequired("To perform this action you need to " \
"authenticate using your API_KEY and API_SECRET.") "authenticate using your API_KEY and API_SECRET.")
await _require_websocket_connection(function)(self, *args, **kwargs) await _require_websocket_connection(function)(self, *args, **kwargs)
@@ -50,8 +50,8 @@ class _Delay:
return (self.__backoff_delay == _Delay.BACKOFF_MIN) \ return (self.__backoff_delay == _Delay.BACKOFF_MIN) \
and self.__initial_delay or self.__backoff_delay and self.__initial_delay or self.__backoff_delay
class BfxWebsocketClient: class BfxWebSocketClient:
VERSION = BfxWebsocketBucket.VERSION VERSION = BfxWebSocketBucket.VERSION
MAXIMUM_CONNECTIONS_AMOUNT = 20 MAXIMUM_CONNECTIONS_AMOUNT = 20
@@ -78,11 +78,11 @@ class BfxWebsocketClient:
self.handler = AuthenticatedEventsHandler(event_emitter=self.event_emitter) self.handler = AuthenticatedEventsHandler(event_emitter=self.event_emitter)
self.inputs = BfxWebsocketInputs(handle_websocket_input=self.__handle_websocket_input) self.inputs = BfxWebSocketInputs(handle_websocket_input=self.__handle_websocket_input)
if log_filename is None: if log_filename is None:
self.logger = ColorLogger("BfxWebsocketClient", level=log_level) self.logger = ColorLogger("BfxWebSocketClient", level=log_level)
else: self.logger = FileLogger("BfxWebsocketClient", level=log_level, filename=log_filename) else: self.logger = FileLogger("BfxWebSocketClient", level=log_level, filename=log_filename)
self.event_emitter.add_listener("error", self.event_emitter.add_listener("error",
lambda exception: self.logger.error(f"{type(exception).__name__}: {str(exception)}" + "\n" + lambda exception: self.logger.error(f"{type(exception).__name__}: {str(exception)}" + "\n" +
@@ -97,13 +97,13 @@ class BfxWebsocketClient:
self.logger.info("With connections set to 0 it will not be possible to subscribe to any public channel. " \ self.logger.info("With connections set to 0 it will not be possible to subscribe to any public channel. " \
"Attempting a subscription will cause a ZeroConnectionsError to be thrown.") "Attempting a subscription will cause a ZeroConnectionsError to be thrown.")
if connections > BfxWebsocketClient.MAXIMUM_CONNECTIONS_AMOUNT: if connections > BfxWebSocketClient.MAXIMUM_CONNECTIONS_AMOUNT:
self.logger.warning(f"It is not safe to use more than {BfxWebsocketClient.MAXIMUM_CONNECTIONS_AMOUNT} " \ self.logger.warning(f"It is not safe to use more than {BfxWebSocketClient.MAXIMUM_CONNECTIONS_AMOUNT} " \
f"buckets from the same connection ({connections} in use), the server could momentarily " \ f"buckets from the same connection ({connections} in use), the server could momentarily " \
"block the client with <429 Too Many Requests>.") "block the client with <429 Too Many Requests>.")
for _ in range(connections): for _ in range(connections):
self.buckets += [BfxWebsocketBucket(self.host, self.event_emitter, self.events_per_subscription)] self.buckets += [BfxWebSocketBucket(self.host, self.event_emitter, self.events_per_subscription)]
await self.__connect() await self.__connect()
@@ -134,7 +134,7 @@ class BfxWebsocketClient:
self.websocket = websocket self.websocket = websocket
coroutines = [ BfxWebsocketBucket.connect(bucket) for bucket in self.buckets ] coroutines = [ BfxWebSocketBucket.connect(bucket) for bucket in self.buckets ]
tasks = [ asyncio.create_task(coroutine) for coroutine in coroutines ] tasks = [ asyncio.create_task(coroutine) for coroutine in coroutines ]
@@ -150,13 +150,13 @@ class BfxWebsocketClient:
if isinstance(message, dict): if isinstance(message, dict):
if message["event"] == "info" and "version" in message: if message["event"] == "info" and "version" in message:
if BfxWebsocketClient.VERSION != message["version"]: if BfxWebSocketClient.VERSION != message["version"]:
raise OutdatedClientVersion("Mismatch between the client version and the server " \ raise OutdatedClientVersion("Mismatch between the client version and the server " \
"version. Update the library to the latest version to continue (client version: " \ "version. Update the library to the latest version to continue (client version: " \
f"{BfxWebsocketClient.VERSION}, server version: {message['version']}).") f"{BfxWebSocketClient.VERSION}, server version: {message['version']}).")
elif message["event"] == "info" and message["code"] == 20051: elif message["event"] == "info" and message["code"] == 20051:
rcvd = websockets.frames.Close(code=1012, rcvd = websockets.frames.Close(code=1012,
reason="Stop/Restart Websocket Server (please reconnect).") reason="Stop/Restart WebSocket Server (please reconnect).")
raise websockets.exceptions.ConnectionClosedError(rcvd=rcvd, sent=None) raise websockets.exceptions.ConnectionClosedError(rcvd=rcvd, sent=None)
elif message["event"] == "auth": elif message["event"] == "auth":
@@ -267,12 +267,12 @@ class BfxWebsocketClient:
def on(self, *events, callback = None): def on(self, *events, callback = None):
for event in events: for event in events:
if event not in BfxWebsocketClient.EVENTS: if event not in BfxWebSocketClient.EVENTS:
raise EventNotSupported(f"Event <{event}> is not supported. To get a list " \ raise EventNotSupported(f"Event <{event}> is not supported. To get a list " \
"of available events print BfxWebsocketClient.EVENTS") "of available events print BfxWebSocketClient.EVENTS")
def _register_event(event, function): def _register_event(event, function):
if event in BfxWebsocketClient.ONCE_EVENTS: if event in BfxWebSocketClient.ONCE_EVENTS:
self.event_emitter.once(event, function) self.event_emitter.once(event, function)
else: self.event_emitter.on(event, function) else: self.event_emitter.on(event, function)

View File

@@ -5,7 +5,7 @@ from typing import Union, Optional, List, Tuple
from .. enums import OrderType, FundingOfferType from .. enums import OrderType, FundingOfferType
from ...utils.json_encoder import JSON from ...utils.json_encoder import JSON
class BfxWebsocketInputs: class BfxWebSocketInputs:
def __init__(self, handle_websocket_input): def __init__(self, handle_websocket_input):
self.__handle_websocket_input = handle_websocket_input self.__handle_websocket_input = handle_websocket_input

View File

@@ -1,66 +1,66 @@
from .. exceptions import BfxBaseException from .. exceptions import BfxBaseException
__all__ = [ __all__ = [
"BfxWebsocketException", "BfxWebSocketException",
"ConnectionNotOpen", "ConnectionNotOpen",
"TooManySubscriptions", "TooManySubscriptions",
"ZeroConnectionsError", "ZeroConnectionsError",
"ReconnectionTimeoutError", "ReconnectionTimeoutError",
"WebsocketAuthenticationRequired", "WebSocketAuthenticationRequired",
"InvalidAuthenticationCredentials", "InvalidAuthenticationCredentials",
"EventNotSupported", "EventNotSupported",
"HandlerNotFound", "HandlerNotFound",
"OutdatedClientVersion" "OutdatedClientVersion"
] ]
class BfxWebsocketException(BfxBaseException): class BfxWebSocketException(BfxBaseException):
""" """
Base class for all custom exceptions in bfxapi/websocket/exceptions.py. Base class for all custom exceptions in bfxapi/websocket/exceptions.py.
""" """
class ConnectionNotOpen(BfxWebsocketException): class ConnectionNotOpen(BfxWebSocketException):
""" """
This error indicates an attempt to communicate via websocket before starting the connection with the servers. This error indicates an attempt to communicate via websocket before starting the connection with the servers.
""" """
class TooManySubscriptions(BfxWebsocketException): class TooManySubscriptions(BfxWebSocketException):
""" """
This error indicates a subscription attempt after reaching the limit of simultaneous connections. This error indicates a subscription attempt after reaching the limit of simultaneous connections.
""" """
class ZeroConnectionsError(BfxWebsocketException): class ZeroConnectionsError(BfxWebSocketException):
""" """
This error indicates an attempt to subscribe to a public channel while the number of connections is 0. This error indicates an attempt to subscribe to a public channel while the number of connections is 0.
""" """
class ReconnectionTimeoutError(BfxWebsocketException): class ReconnectionTimeoutError(BfxWebSocketException):
""" """
This error indicates that the connection has been offline for too long without being able to reconnect. This error indicates that the connection has been offline for too long without being able to reconnect.
""" """
class WebsocketAuthenticationRequired(BfxWebsocketException): class WebSocketAuthenticationRequired(BfxWebSocketException):
""" """
This error indicates an attempt to access a protected resource without logging in first. This error indicates an attempt to access a protected resource without logging in first.
""" """
class InvalidAuthenticationCredentials(BfxWebsocketException): class InvalidAuthenticationCredentials(BfxWebSocketException):
""" """
This error indicates that the user has provided incorrect credentials (API-KEY and API-SECRET) for authentication. This error indicates that the user has provided incorrect credentials (API-KEY and API-SECRET) for authentication.
""" """
class EventNotSupported(BfxWebsocketException): class EventNotSupported(BfxWebSocketException):
""" """
This error indicates a failed attempt to subscribe to an event not supported by the BfxWebsocketClient. This error indicates a failed attempt to subscribe to an event not supported by the BfxWebSocketClient.
""" """
class HandlerNotFound(BfxWebsocketException): class HandlerNotFound(BfxWebSocketException):
""" """
This error indicates that a handler was not found for an incoming message. This error indicates that a handler was not found for an incoming message.
""" """
class OutdatedClientVersion(BfxWebsocketException): class OutdatedClientVersion(BfxWebSocketException):
""" """
This error indicates a mismatch between the client version and the server WSS version. This error indicates a mismatch between the client version and the server WSS version.
""" """

View File

@@ -18,7 +18,7 @@ __serializers__ = [
"Wallet", "Balance", "Wallet", "Balance",
] ]
#region Serializers definition for Websocket Public Channels #region Serializers definition for WebSocket Public Channels
TradingPairTicker = generate_labeler_serializer( TradingPairTicker = generate_labeler_serializer(
name="TradingPairTicker", name="TradingPairTicker",
@@ -170,7 +170,7 @@ DerivativesStatus = generate_labeler_serializer(
#endregion #endregion
#region Serializers definition for Websocket Authenticated Channels #region Serializers definition for WebSocket Authenticated Channels
Order = generate_labeler_serializer( Order = generate_labeler_serializer(
name="Order", name="Order",

View File

@@ -12,7 +12,7 @@ from .. notification import Notification
from ..utils.json_encoder import JSON from ..utils.json_encoder import JSON
#region Type hinting for Websocket Public Channels #region Type hinting for WebSocket Public Channels
@dataclass @dataclass
class TradingPairTicker(_Type): class TradingPairTicker(_Type):
@@ -111,7 +111,7 @@ class DerivativesStatus(_Type):
#endregion #endregion
#region Type hinting for Websocket Authenticated Channels #region Type hinting for WebSocket Authenticated Channels
@dataclass @dataclass
class Order(_Type): class Order(_Type):
id: int id: int