Coverage for app/delivery_fee/utility_meta_classes.py: 82%

22 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2024-11-27 09:26 +0000

1from threading import Lock 

2 

3 

4class ThreadSafeSingletonMeta(type): 

5 """ 

6 This is a thread-safe implementation of Singleton. 

7 Source: https://refactoring.guru/design-patterns/singleton/python/example#example-1 

8 """ 

9 

10 _instances = {} 

11 

12 _lock: Lock = Lock() 

13 """ 

14 We now have a lock object that will be used to synchronize threads during 

15 first access to the Singleton. 

16 """ 

17 

18 def __call__(cls, *args, **kwargs): 

19 """ 

20 Possible changes to the value of the `__init__` argument do not affect 

21 the returned instance. 

22 """ 

23 # Now, imagine that the program has just been launched. Since there's no 

24 # Singleton instance yet, multiple threads can simultaneously pass the 

25 # previous conditional and reach this point almost at the same time. The 

26 # first of them will acquire lock and will proceed further, while the 

27 # rest will wait here. 

28 with cls._lock: 

29 # The first thread to acquire the lock, reaches this conditional, 

30 # goes inside and creates the Singleton instance. Once it leaves the 

31 # lock block, a thread that might have been waiting for the lock 

32 # release may then enter this section. But since the Singleton field 

33 # is already initialized, the thread won't create a new object. 

34 if cls not in cls._instances: 

35 instance = super().__call__(*args, **kwargs) 

36 cls._instances[cls] = instance 

37 return cls._instances[cls] 

38 

39 def clear_singleton_instance(cls): 

40 """ 

41 This method is used for testing purposes only. 

42 """ 

43 with cls._lock: 

44 if cls in cls._instances: 

45 cls._instances.pop(cls) 

46 

47 

48class SingletonMeta(type): 

49 """ 

50 The Singleton class can be implemented in different ways in Python. Some 

51 possible methods include: base class, decorator, metaclass. We will use the 

52 metaclass because it is best suited for this purpose. 

53 Source: https://refactoring.guru/design-patterns/singleton/python/example#example-0 

54 """ 

55 

56 _instances = {} 

57 

58 def __call__(cls, *args, **kwargs): 

59 """ 

60 Possible changes to the value of the `__init__` argument do not affect 

61 the returned instance. 

62 """ 

63 if cls not in cls._instances: 

64 instance = super().__call__(*args, **kwargs) 

65 cls._instances[cls] = instance 

66 return cls._instances[cls]