codekingpro/portable-devtools
114k
1"""Key functions for memoizing decorators."""2 3__all__ = ("hashkey", "methodkey", "typedkey")4 5 6class _HashedTuple(tuple):7 """A tuple that ensures that hash() will be called no more than once8 per element, since cache decorators will hash the key multiple9 times on a cache miss. See also _HashedSeq in the standard10 library functools implementation.11 12 """13 14 __hashvalue = None15 16 def __hash__(self, hash=tuple.__hash__):17 hashvalue = self.__hashvalue18 if hashvalue is None:19 self.__hashvalue = hashvalue = hash(self)20 return hashvalue21 22 def __add__(self, other, add=tuple.__add__):23 return _HashedTuple(add(self, other))24 25 def __radd__(self, other, add=tuple.__add__):26 return _HashedTuple(add(other, self))27 28 def __getstate__(self):29 return {}30 31 32# used for separating keyword arguments; we do not use an object33# instance here so identity is preserved when pickling/unpickling34_kwmark = (_HashedTuple,)35 36 37def hashkey(*args, **kwargs):38 """Return a cache key for the specified hashable arguments."""39 40 if kwargs:41 return _HashedTuple(args + sum(sorted(kwargs.items()), _kwmark))42 else:43 return _HashedTuple(args)44 45 46def methodkey(self, *args, **kwargs):47 """Return a cache key for use with cached methods."""48 return hashkey(*args, **kwargs)49 50 51def typedkey(*args, **kwargs):52 """Return a typed cache key for the specified hashable arguments."""53 54 key = hashkey(*args, **kwargs)55 key += tuple(type(v) for v in args)56 key += tuple(type(v) for _, v in sorted(kwargs.items()))57 return key58 