diff --git a/freqtrade/rpc/fiat_convert.py b/freqtrade/rpc/fiat_convert.py index 16d64dd50..4ae5842d5 100644 --- a/freqtrade/rpc/fiat_convert.py +++ b/freqtrade/rpc/fiat_convert.py @@ -5,7 +5,6 @@ e.g BTC to USD import logging from datetime import datetime -from typing import Any from requests.exceptions import RequestException @@ -13,6 +12,7 @@ from freqtrade.constants import SUPPORTED_FIAT, Config from freqtrade.mixins.logging_mixin import LoggingMixin from freqtrade.util import FtTTLCache from freqtrade.util.coin_gecko import FtCoinGeckoApi +from freqtrade.util.singleton import SingletonMeta logger = logging.getLogger(__name__) @@ -32,26 +32,16 @@ coingecko_mapping = { } -class CryptoToFiatConverter(LoggingMixin): +class CryptoToFiatConverter(LoggingMixin, metaclass=SingletonMeta): """ Main class to initiate Crypto to FIAT. This object contains a list of pair Crypto, FIAT This object is also a Singleton """ - __instance = None - _coinlistings: list[dict] = [] _backoff: float = 0.0 - def __new__(cls, *args: Any, **kwargs: Any) -> Any: - """ - Singleton pattern to ensure only one instance is created. - """ - if not cls.__instance: - cls.__instance = super().__new__(cls) - return cls.__instance - def __init__(self, config: Config) -> None: # Timeout: 6h self._pair_price: FtTTLCache = FtTTLCache(maxsize=500, ttl=6 * 60 * 60) diff --git a/freqtrade/util/singleton.py b/freqtrade/util/singleton.py new file mode 100644 index 000000000..91841cdec --- /dev/null +++ b/freqtrade/util/singleton.py @@ -0,0 +1,16 @@ +from typing import Any + + +class SingletonMeta(type): + """ + A thread-safe implementation of Singleton. + Use as metaclass to create singleton classes. + """ + + _instances: dict = {} + + def __call__(cls, *args: Any, **kwargs: Any) -> Any: + if cls not in cls._instances: + instance = super().__call__(*args, **kwargs) + cls._instances[cls] = instance + return cls._instances[cls] diff --git a/tests/rpc/test_fiat_convert.py b/tests/rpc/test_fiat_convert.py index 4ae7441c8..a67ff9b33 100644 --- a/tests/rpc/test_fiat_convert.py +++ b/tests/rpc/test_fiat_convert.py @@ -12,6 +12,12 @@ from freqtrade.util.coin_gecko import FtCoinGeckoApi from tests.conftest import log_has, log_has_re +@pytest.fixture(autouse=True) +def reset_singleton_instance(): + # Reset the singleton instance before each test + CryptoToFiatConverter._instances = {} + + def test_fiat_convert_is_singleton(): fiat_convert = CryptoToFiatConverter({"a": 22}) fiat_convert2 = CryptoToFiatConverter({})