1from datetime import timedelta 2import weakref 3from collections import OrderedDict 4 5 6class _TzSingleton(type): 7 def __init__(cls, *args, **kwargs): 8 cls.__instance = None 9 super(_TzSingleton, cls).__init__(*args, **kwargs) 10 11 def __call__(cls): 12 if cls.__instance is None: 13 cls.__instance = super(_TzSingleton, cls).__call__() 14 return cls.__instance 15 16 17class _TzFactory(type): 18 def instance(cls, *args, **kwargs): 19 """Alternate constructor that returns a fresh instance""" 20 return type.__call__(cls, *args, **kwargs) 21 22 23class _TzOffsetFactory(_TzFactory): 24 def __init__(cls, *args, **kwargs): 25 cls.__instances = weakref.WeakValueDictionary() 26 cls.__strong_cache = OrderedDict() 27 cls.__strong_cache_size = 8 28 29 def __call__(cls, name, offset): 30 if isinstance(offset, timedelta): 31 key = (name, offset.total_seconds()) 32 else: 33 key = (name, offset) 34 35 instance = cls.__instances.get(key, None) 36 if instance is None: 37 instance = cls.__instances.setdefault(key, 38 cls.instance(name, offset)) 39 40 cls.__strong_cache[key] = cls.__strong_cache.pop(key, instance) 41 42 # Remove an item if the strong cache is overpopulated 43 # TODO: Maybe this should be under a lock? 44 if len(cls.__strong_cache) > cls.__strong_cache_size: 45 cls.__strong_cache.popitem(last=False) 46 47 return instance 48 49 50class _TzStrFactory(_TzFactory): 51 def __init__(cls, *args, **kwargs): 52 cls.__instances = weakref.WeakValueDictionary() 53 cls.__strong_cache = OrderedDict() 54 cls.__strong_cache_size = 8 55 56 def __call__(cls, s, posix_offset=False): 57 key = (s, posix_offset) 58 instance = cls.__instances.get(key, None) 59 60 if instance is None: 61 instance = cls.__instances.setdefault(key, 62 cls.instance(s, posix_offset)) 63 64 cls.__strong_cache[key] = cls.__strong_cache.pop(key, instance) 65 66 67 # Remove an item if the strong cache is overpopulated 68 # TODO: Maybe this should be under a lock? 69 if len(cls.__strong_cache) > cls.__strong_cache_size: 70 cls.__strong_cache.popitem(last=False) 71 72 return instance 73 74