Skip to content

Instantly share code, notes, and snippets.

@cryzed
Last active May 23, 2021 21:47
Show Gist options
  • Save cryzed/83328b876bb92d5be1ed7f3cc77a5820 to your computer and use it in GitHub Desktop.
Save cryzed/83328b876bb92d5be1ed7f3cc77a5820 to your computer and use it in GitHub Desktop.
import collections
import dataclasses
import functools
import time
import typing as T
NumberType = T.Union[int, float]
X = T.TypeVar("X")
@dataclasses.dataclass
class _TimedCacheEntry(T.Generic[X]):
value: X
expires_at: float
def timed_cache(seconds: NumberType = 60) -> T.Callable[[T.Callable[..., X]], T.Callable[..., X]]:
def _timed_cache(function: T.Callable[..., X]) -> T.Callable[..., X]:
cache: collections.OrderedDict[T.Hashable, _TimedCacheEntry[X]] = collections.OrderedDict()
@functools.wraps(function)
def wrapped(*args: T.Hashable, **kwargs: T.Hashable) -> X:
now = time.monotonic()
for key, entry in tuple(cache.items()):
if entry.expires_at >= now:
break
del cache[key]
key = args, tuple(kwargs.items())
if key in cache:
return cache[key].value
result = function(*args, **kwargs)
cache[key] = _TimedCacheEntry(result, now + seconds)
return result
return wrapped
return _timed_cache
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment