Skip to content

Commit 0d7127b

Browse files
committed
refactor: use metaclass for Singleton in FiatConverter
1 parent cfd048e commit 0d7127b

File tree

3 files changed

+24
-12
lines changed

3 files changed

+24
-12
lines changed

freqtrade/rpc/fiat_convert.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55

66
import logging
77
from datetime import datetime
8-
from typing import Any
98

109
from requests.exceptions import RequestException
1110

1211
from freqtrade.constants import SUPPORTED_FIAT, Config
1312
from freqtrade.mixins.logging_mixin import LoggingMixin
1413
from freqtrade.util import FtTTLCache
1514
from freqtrade.util.coin_gecko import FtCoinGeckoApi
15+
from freqtrade.util.singleton import SingletonMeta
1616

1717

1818
logger = logging.getLogger(__name__)
@@ -32,26 +32,16 @@
3232
}
3333

3434

35-
class CryptoToFiatConverter(LoggingMixin):
35+
class CryptoToFiatConverter(LoggingMixin, metaclass=SingletonMeta):
3636
"""
3737
Main class to initiate Crypto to FIAT.
3838
This object contains a list of pair Crypto, FIAT
3939
This object is also a Singleton
4040
"""
4141

42-
__instance = None
43-
4442
_coinlistings: list[dict] = []
4543
_backoff: float = 0.0
4644

47-
def __new__(cls, *args: Any, **kwargs: Any) -> Any:
48-
"""
49-
Singleton pattern to ensure only one instance is created.
50-
"""
51-
if not cls.__instance:
52-
cls.__instance = super().__new__(cls)
53-
return cls.__instance
54-
5545
def __init__(self, config: Config) -> None:
5646
# Timeout: 6h
5747
self._pair_price: FtTTLCache = FtTTLCache(maxsize=500, ttl=6 * 60 * 60)

freqtrade/util/singleton.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from typing import Any
2+
3+
4+
class SingletonMeta(type):
5+
"""
6+
A thread-safe implementation of Singleton.
7+
Use as metaclass to create singleton classes.
8+
"""
9+
10+
_instances: dict = {}
11+
12+
def __call__(cls, *args: Any, **kwargs: Any) -> Any:
13+
if cls not in cls._instances:
14+
instance = super().__call__(*args, **kwargs)
15+
cls._instances[cls] = instance
16+
return cls._instances[cls]

tests/rpc/test_fiat_convert.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
from tests.conftest import log_has, log_has_re
1313

1414

15+
@pytest.fixture(autouse=True)
16+
def reset_singleton_instance():
17+
# Reset the singleton instance before each test
18+
CryptoToFiatConverter._instances = {}
19+
20+
1521
def test_fiat_convert_is_singleton():
1622
fiat_convert = CryptoToFiatConverter({"a": 22})
1723
fiat_convert2 = CryptoToFiatConverter({})

0 commit comments

Comments
 (0)