2022-08-29 19:41:15 +00:00
|
|
|
import logging
|
|
|
|
from abc import ABC, abstractmethod
|
2024-10-04 05:06:27 +00:00
|
|
|
from typing import Any, Union
|
2022-08-29 19:41:15 +00:00
|
|
|
|
2022-09-02 06:05:36 +00:00
|
|
|
import orjson
|
2022-09-02 05:15:03 +00:00
|
|
|
import rapidjson
|
|
|
|
from pandas import DataFrame
|
2022-08-29 19:41:15 +00:00
|
|
|
|
2022-09-02 05:15:03 +00:00
|
|
|
from freqtrade.misc import dataframe_to_json, json_to_dataframe
|
2022-08-29 19:41:15 +00:00
|
|
|
from freqtrade.rpc.api_server.ws.proxy import WebSocketProxy
|
2022-11-15 03:27:45 +00:00
|
|
|
from freqtrade.rpc.api_server.ws_schemas import WSMessageSchemaType
|
2022-08-29 19:41:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
class WebSocketSerializer(ABC):
|
|
|
|
def __init__(self, websocket: WebSocketProxy):
|
|
|
|
self._websocket: WebSocketProxy = websocket
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def _serialize(self, data):
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def _deserialize(self, data):
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
2024-10-04 05:06:27 +00:00
|
|
|
async def send(self, data: Union[WSMessageSchemaType, dict[str, Any]]):
|
2022-08-29 19:41:15 +00:00
|
|
|
await self._websocket.send(self._serialize(data))
|
|
|
|
|
|
|
|
async def recv(self) -> bytes:
|
|
|
|
data = await self._websocket.recv()
|
|
|
|
return self._deserialize(data)
|
|
|
|
|
|
|
|
|
2022-09-02 06:05:36 +00:00
|
|
|
class HybridJSONWebSocketSerializer(WebSocketSerializer):
|
2022-09-06 05:25:25 +00:00
|
|
|
def _serialize(self, data) -> str:
|
|
|
|
return str(orjson.dumps(data, default=_json_default), "utf-8")
|
2022-09-02 06:05:36 +00:00
|
|
|
|
2022-09-06 05:25:25 +00:00
|
|
|
def _deserialize(self, data: str):
|
2022-09-05 19:47:17 +00:00
|
|
|
# RapidJSON expects strings
|
2022-09-02 06:05:36 +00:00
|
|
|
return rapidjson.loads(data, object_hook=_json_object_hook)
|
|
|
|
|
|
|
|
|
2022-09-02 05:15:03 +00:00
|
|
|
# Support serializing pandas DataFrames
|
|
|
|
def _json_default(z):
|
|
|
|
if isinstance(z, DataFrame):
|
2024-05-12 14:51:11 +00:00
|
|
|
return {"__type__": "dataframe", "__value__": dataframe_to_json(z)}
|
2022-09-02 05:15:03 +00:00
|
|
|
raise TypeError
|
|
|
|
|
|
|
|
|
|
|
|
# Support deserializing JSON to pandas DataFrames
|
|
|
|
def _json_object_hook(z):
|
2024-05-12 14:51:11 +00:00
|
|
|
if z.get("__type__") == "dataframe":
|
|
|
|
return json_to_dataframe(z.get("__value__"))
|
2022-09-02 05:15:03 +00:00
|
|
|
return z
|