fix(exchange): drop unused get_ft_has override plumbing

This commit is contained in:
matstedt
2026-01-23 17:07:51 +01:00
committed by Matthias
parent 06abc95b2e
commit 9ddf464c03
3 changed files with 3 additions and 95 deletions
+1 -17
View File
@@ -1,30 +1,15 @@
import logging import logging
from typing import Any
from freqtrade.constants import Config from freqtrade.constants import Config
from freqtrade.enums import RunMode from freqtrade.enums import RunMode
from freqtrade.exceptions import OperationalException from freqtrade.exceptions import OperationalException
from freqtrade.exchange import available_exchanges, is_exchange_known_ccxt, validate_exchange from freqtrade.exchange import available_exchanges, is_exchange_known_ccxt, validate_exchange
from freqtrade.exchange.common import MAP_EXCHANGE_CHILDCLASS, SUPPORTED_EXCHANGES from freqtrade.exchange.common import MAP_EXCHANGE_CHILDCLASS, SUPPORTED_EXCHANGES
from freqtrade.resolvers.exchange_resolver import ExchangeResolver
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def _get_ft_has_overrides(exchange_name: str) -> dict[str, Any] | None:
subclassed = {e["name"].lower(): e for e in ExchangeResolver.search_all_objects({}, False)}
mapped = MAP_EXCHANGE_CHILDCLASS.get(exchange_name.lower(), exchange_name.lower()).lower()
resolved = subclassed.get(mapped)
if not resolved:
return None
get_ft_has = getattr(resolved["class"], "get_ft_has", None)
if callable(get_ft_has):
return get_ft_has() or None
return None
def check_exchange(config: Config, check_for_bad: bool = True) -> bool: def check_exchange(config: Config, check_for_bad: bool = True) -> bool:
""" """
Check if the exchange name in the config file is supported by Freqtrade Check if the exchange name in the config file is supported by Freqtrade
@@ -62,8 +47,7 @@ def check_exchange(config: Config, check_for_bad: bool = True) -> bool:
f"{', '.join(available_exchanges())}" f"{', '.join(available_exchanges())}"
) )
ft_has_overrides = _get_ft_has_overrides(exchange) valid, reason, _, _ = validate_exchange(exchange)
valid, reason, _, _ = validate_exchange(exchange, ft_has_overrides)
if not valid: if not valid:
if check_for_bad: if check_for_bad:
raise OperationalException( raise OperationalException(
+1 -9
View File
@@ -70,7 +70,6 @@ def _exchange_has_helper(ex_has: dict[str, Any], required: dict[str, list[str]])
def validate_exchange( def validate_exchange(
exchange: str, exchange: str,
ft_has_overrides: dict[str, Any] | None = None,
) -> tuple[bool, str, str, ccxt.Exchange | None]: ) -> tuple[bool, str, str, ccxt.Exchange | None]:
""" """
returns: can_use, reason, exchange_object returns: can_use, reason, exchange_object
@@ -85,8 +84,6 @@ def validate_exchange(
return False, "", "", None return False, "", "", None
ex_has = dict(ex_mod.has or {}) ex_has = dict(ex_mod.has or {})
if ft_has_overrides:
ex_has.update(ft_has_overrides)
result = True result = True
reasons = [] reasons = []
@@ -120,13 +117,8 @@ def _build_exchange_list_entry(
mapped_exchange_name = MAP_EXCHANGE_CHILDCLASS.get(exchange_name, exchange_name).lower() mapped_exchange_name = MAP_EXCHANGE_CHILDCLASS.get(exchange_name, exchange_name).lower()
resolved = exchangeClasses.get(mapped_exchange_name) resolved = exchangeClasses.get(mapped_exchange_name)
ft_has_overrides = None
if resolved:
get_ft_has = getattr(resolved["class"], "get_ft_has", None)
if callable(get_ft_has):
ft_has_overrides = get_ft_has() or None
valid, comment, comment_fut, ex_mod = validate_exchange(exchange_name, ft_has_overrides) valid, comment, comment_fut, ex_mod = validate_exchange(exchange_name)
is_alias = getattr(ex_mod, "alias", False) is_alias = getattr(ex_mod, "alias", False)
result: ValidExchangesType = { result: ValidExchangesType = {
+1 -69
View File
@@ -3,7 +3,6 @@ from datetime import UTC, datetime, timedelta
from math import isnan, nan from math import isnan, nan
from unittest.mock import MagicMock from unittest.mock import MagicMock
import ccxt
import pytest import pytest
from ccxt import ( from ccxt import (
DECIMAL_PLACES, DECIMAL_PLACES,
@@ -15,7 +14,6 @@ from ccxt import (
TRUNCATE, TRUNCATE,
) )
import freqtrade.exchange.exchange_utils as exchange_utils_mod
from freqtrade.enums import RunMode from freqtrade.enums import RunMode
from freqtrade.exceptions import OperationalException from freqtrade.exceptions import OperationalException
from freqtrade.exchange import ( from freqtrade.exchange import (
@@ -30,13 +28,10 @@ from freqtrade.exchange import (
timeframe_to_resample_freq, timeframe_to_resample_freq,
timeframe_to_seconds, timeframe_to_seconds,
) )
from freqtrade.exchange.check_exchange import _get_ft_has_overrides, check_exchange from freqtrade.exchange.check_exchange import check_exchange
from freqtrade.exchange.exchange_utils import ( from freqtrade.exchange.exchange_utils import (
_build_exchange_list_entry,
_exchange_has_helper, _exchange_has_helper,
validate_exchange,
) )
from freqtrade.resolvers.exchange_resolver import ExchangeResolver
from tests.conftest import log_has_re from tests.conftest import log_has_re
@@ -433,66 +428,3 @@ def test_exchange__exchange_has_helper():
} }
missing = _exchange_has_helper(e_mod.has, required) missing = _exchange_has_helper(e_mod.has, required)
assert set(missing) == {"fetchOHLCV", "fetchMyTrades", "fetchOrder"} assert set(missing) == {"fetchOHLCV", "fetchMyTrades", "fetchOrder"}
def test_validate_exchange_uses_ft_has_overrides(monkeypatch):
class DummyExchange:
def __init__(self) -> None:
self.has = {
"fetchOrder": False,
"fetchL2OrderBook": False,
"fetchTicker": True,
"cancelOrder": True,
"createOrder": True,
"fetchBalance": True,
"fetchOHLCV": False,
}
monkeypatch.setattr(ccxt.pro, "dummy", DummyExchange, raising=False)
valid, _, _, _ = validate_exchange("dummy")
assert not valid
valid, _, _, _ = validate_exchange("dummy", {"fetchOrder": True, "fetchOHLCV": True})
assert valid
def test_build_exchange_list_entry_uses_ft_has_overrides(monkeypatch):
class DummyClass:
_supported_trading_mode_margin_pairs = []
@staticmethod
def get_ft_has():
return {"fetchOrder": True}
captured = {}
class DummyExchange:
name = "Dummy"
alias = False
dex = False
def fake_validate_exchange(exchange, ft_has_overrides=None):
captured["ft_has_overrides"] = ft_has_overrides
return True, "", "", DummyExchange()
monkeypatch.setattr(exchange_utils_mod, "validate_exchange", fake_validate_exchange)
res = _build_exchange_list_entry("dummy", {"dummy": {"class": DummyClass}})
assert captured["ft_has_overrides"] == {"fetchOrder": True}
assert res["classname"] == "dummy"
def test_get_ft_has_overrides_returns_override(monkeypatch):
class DummyClass:
@staticmethod
def get_ft_has():
return {"fetchOrder": True}
monkeypatch.setattr(
ExchangeResolver,
"search_all_objects",
lambda *args, **kwargs: [{"name": "dummy", "class": DummyClass}],
)
assert _get_ft_has_overrides("dummy") == {"fetchOrder": True}