NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

memoize.py (3433B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\caching\memoize.py
      2 import numbers, time
      3 try:
      4     from locks import Lock
      5 except ImportError:
      6     Lock = None
      7 
      8 CACHE_FOREVER = 108000
      9 
     10 def Memoize(minutes):
     11     cache_seconds = CACHE_FOREVER
     12 
     13     def deco(fn):
     14         _cache = _MemoizeCache(cache_seconds)
     15 
     16         def inner_deco(*args, **kwargs):
     17             key = _cache.make_key(*args, **kwargs)
     18             try:
     19                 value = _cache.get_value_if_key_is_present_and_not_expired(key)
     20             except KeyError:
     21                 value = fn(*args, **kwargs)
     22                 _cache.store(key, value)
     23 
     24             return value
     25 
     26         inner_deco.clear_memoized = _cache.clear_cache
     27         return inner_deco
     28 
     29     if callable(minutes):
     30         return deco(minutes)
     31     if isinstance(minutes, numbers.Number):
     32         cache_seconds = minutes * 60
     33         return deco
     34     raise ValueError("Wrong usage of 'Memoized' decorator. Either use no arguments or specify a number of minutes.")
     35 
     36 
     37 def MemoizeWithLock(minutes):
     38     if Lock is None:
     39         raise RuntimeError('MemoizeWithLock requires a Stackless execution environment')
     40     cache_seconds = CACHE_FOREVER
     41 
     42     def deco(fn):
     43         _cache = _MemoizeCache(cache_seconds)
     44         _lock = Lock('MemoizeWithLock._lock %s' % fn)
     45 
     46         def inner_deco_with_lock(*args, **kwargs):
     47             key = _cache.make_key(*args, **kwargs)
     48             try:
     49                 value = _cache.get_value_if_key_is_present_and_not_expired(key)
     50             except KeyError:
     51                 with _lock:
     52                     try:
     53                         value = _cache.get_value_if_key_is_present_and_not_expired(key)
     54                     except KeyError:
     55                         value = fn(*args, **kwargs)
     56                         _cache.store(key, value)
     57 
     58             return value
     59 
     60         inner_deco_with_lock.clear_memoized = _cache.clear_cache
     61         return inner_deco_with_lock
     62 
     63     if callable(minutes):
     64         return deco(minutes)
     65     if isinstance(minutes, numbers.Number):
     66         cache_seconds = minutes * 60
     67         return deco
     68     raise ValueError("Wrong usage of 'MemoizeWithLock' decorator. Either use no arguments or specify a number of minutes.")
     69 
     70 
     71 class _MemoizeCache(object):
     72 
     73     def __init__(self, cache_seconds):
     74         self._cache = {}
     75         self._cache_seconds = cache_seconds
     76 
     77     @staticmethod
     78     def make_key(*args, **kwargs):
     79         hargs = []
     80         for a in args:
     81             if getattr(a, '__hash__', None):
     82                 hargs.append(a)
     83             elif hasattr(a, 'iteritems'):
     84                 hargs.append(frozenset(a.iteritems()))
     85             else:
     86                 hargs.append(tuple(a) if hasattr(a, '__iter__') else repr(a))
     87 
     88         return (tuple(hargs) if hargs else None, frozenset(kwargs.iteritems()) if kwargs else None)
     89 
     90     def get_value_if_key_is_present_and_not_expired(self, key):
     91         value, saved_time = self._cache[key]
     92         if saved_time + self._cache_seconds < time.time():
     93             raise KeyError
     94         return value
     95 
     96     def store(self, key, value):
     97         saved_time = time.time()
     98         self._cache[key] = (value, saved_time)
     99 
    100     def clear_cache(self, *args, **kwargs):
    101         if not args and not kwargs:
    102             self._cache.clear()
    103         else:
    104             try:
    105                 del self._cache[self.make_key(*args, **kwargs)]
    106             except KeyError:
    107                 pass