From 8f9f4b40cdcad855cec449f9364a449a22cfad67 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 7 Feb 2024 07:21:16 +0100 Subject: [PATCH] Update model to new sqlalchemy version --- freqtrade/persistence/custom_data.py | 29 ++++++++++--------- .../persistence/custom_data_middleware.py | 10 ++++--- freqtrade/persistence/trade_model.py | 3 +- freqtrade/rpc/telegram.py | 8 ++--- 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/freqtrade/persistence/custom_data.py b/freqtrade/persistence/custom_data.py index 1f85467dd..beae8c478 100644 --- a/freqtrade/persistence/custom_data.py +++ b/freqtrade/persistence/custom_data.py @@ -1,14 +1,15 @@ from datetime import datetime -from typing import Optional +from typing import ClassVar, Optional -from sqlalchemy import Column, DateTime, ForeignKey, Integer, String, Text, UniqueConstraint -from sqlalchemy.orm import Query, relationship +from sqlalchemy import DateTime, ForeignKey, Integer, String, Text, UniqueConstraint, select +from sqlalchemy.orm import Mapped, Query, mapped_column, relationship from freqtrade.constants import DATETIME_PRINT_FORMAT -from freqtrade.persistence.base import _DECL_BASE +from freqtrade.persistence.base import ModelBase, SessionType +from freqtrade.util import dt_now -class CustomData(_DECL_BASE): +class CustomData(ModelBase): """ CustomData database model Keeps records of metadata as key/value store @@ -18,20 +19,22 @@ class CustomData(_DECL_BASE): - One metadata entry can only be associated with one Trade """ __tablename__ = 'trade_custom_data' + session: ClassVar[SessionType] + # Uniqueness should be ensured over pair, order_id # its likely that order_id is unique per Pair on some exchanges. __table_args__ = (UniqueConstraint('ft_trade_id', 'cd_key', name="_trade_id_cd_key"),) - id = Column(Integer, primary_key=True) - ft_trade_id = Column(Integer, ForeignKey('trades.id'), index=True, default=0) + id = mapped_column(Integer, primary_key=True) + ft_trade_id = mapped_column(Integer, ForeignKey('trades.id'), index=True, default=0) trade = relationship("Trade", back_populates="custom_data") - cd_key = Column(String(255), nullable=False) - cd_type = Column(String(25), nullable=False) - cd_value = Column(Text, nullable=False) - created_at = Column(DateTime, nullable=False, default=datetime.utcnow) - updated_at = Column(DateTime, nullable=True) + cd_key: Mapped[str] = mapped_column(String(255), nullable=False) + cd_type: Mapped[str] = mapped_column(String(25), nullable=False) + cd_value: Mapped[str] = mapped_column(Text, nullable=False) + created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=dt_now) + updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True) def __repr__(self): create_time = (self.created_at.strftime(DATETIME_PRINT_FORMAT) @@ -54,4 +57,4 @@ class CustomData(_DECL_BASE): if key is not None: filters.append(CustomData.cd_key.ilike(key)) - return CustomData.query.filter(*filters) + return CustomData.session.scalars(select(CustomData)) diff --git a/freqtrade/persistence/custom_data_middleware.py b/freqtrade/persistence/custom_data_middleware.py index 64e8a47fd..cf7b83abc 100644 --- a/freqtrade/persistence/custom_data_middleware.py +++ b/freqtrade/persistence/custom_data_middleware.py @@ -3,6 +3,8 @@ import logging from datetime import datetime from typing import Any, List, Optional +from sqlalchemy import select + from freqtrade.persistence.custom_data import CustomData @@ -86,8 +88,8 @@ class CustomDataWrapper: if CustomDataWrapper.use_db and value_db is not None: data_entry.cd_value = value_db - CustomData.query.session.add(data_entry) - CustomData.query.session.commit() + CustomData.session.add(data_entry) + CustomData.session.commit() elif not CustomDataWrapper.use_db: cd_index = -1 for index, data_entry in enumerate(CustomDataWrapper.custom_data): @@ -97,7 +99,7 @@ class CustomDataWrapper: if cd_index >= 0: data_entry.cd_type = value_type - data_entry.value = value + data_entry.cd_value = value data_entry.updated_at = datetime.utcnow() CustomDataWrapper.custom_data[cd_index] = data_entry @@ -108,6 +110,6 @@ class CustomDataWrapper: def get_all_custom_data() -> List[CustomData]: if CustomDataWrapper.use_db: - return CustomData.query.all() + return CustomData.session.scalars(select(CustomData)).all() else: return CustomDataWrapper.custom_data diff --git a/freqtrade/persistence/trade_model.py b/freqtrade/persistence/trade_model.py index a3f71ee4f..d96378bf2 100644 --- a/freqtrade/persistence/trade_model.py +++ b/freqtrade/persistence/trade_model.py @@ -1467,7 +1467,8 @@ class Trade(ModelBase, LocalTrade): orders: Mapped[List[Order]] = relationship( "Order", order_by="Order.id", cascade="all, delete-orphan", lazy="selectin", innerjoin=True) # type: ignore - custom_data = relationship("CustomData", order_by="CustomData.id", cascade="all, delete-orphan") + custom_data: Mapped[List[CustomData]] = relationship( + "CustomData", order_by="CustomData.id", cascade="all, delete-orphan") # type: ignore exchange: Mapped[str] = mapped_column(String(25), nullable=False) # type: ignore pair: Mapped[str] = mapped_column(String(25), nullable=False, index=True) # type: ignore diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 4bdb09f01..4d91d1bdb 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -1770,7 +1770,7 @@ class Telegram(RPCHandler): ) @authorized_only - def _list_custom_data(self, update: Update, context: CallbackContext) -> None: + async def _list_custom_data(self, update: Update, context: CallbackContext) -> None: """ Handler for /list_custom_data . List custom_data for specified trade (and key if supplied). @@ -1807,14 +1807,14 @@ class Telegram(RPCHandler): msg = "Message dropped because length exceeds " msg += f"maximum allowed characters: {MAX_MESSAGE_LENGTH}" logger.warning(msg) - self._send_msg(msg) + await self._send_msg(msg) else: message = f"Didn't find any custom-data entries for Trade ID: `{trade_id}`" message += f" and Key: `{key}`." if key is not None else "" - self._send_msg(message) + await self._send_msg(message) except RPCException as e: - self._send_msg(str(e)) + await self._send_msg(str(e)) async def _update_msg(self, query: CallbackQuery, msg: str, callback_path: str = "", reload_able: bool = False, parse_mode: str = ParseMode.MARKDOWN) -> None: