functional.py 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. from __future__ import absolute_import
  2. from __future__ import with_statement
  3. from functools import wraps
  4. from threading import Lock
  5. try:
  6. from collections import Sequence
  7. except ImportError:
  8. # <= Py2.5
  9. Sequence = (list, tuple) # noqa
  10. from celery.datastructures import LRUCache
  11. KEYWORD_MARK = object()
  12. def maybe_list(l):
  13. if isinstance(l, Sequence):
  14. return l
  15. return [l]
  16. def memoize(maxsize=None, Cache=LRUCache):
  17. def _memoize(fun):
  18. mutex = Lock()
  19. cache = Cache(limit=maxsize)
  20. @wraps(fun)
  21. def _M(*args, **kwargs):
  22. key = args + (KEYWORD_MARK, ) + tuple(sorted(kwargs.iteritems()))
  23. try:
  24. with mutex:
  25. value = cache[key]
  26. except KeyError:
  27. value = fun(*args, **kwargs)
  28. _M.misses += 1
  29. with mutex:
  30. cache[key] = value
  31. else:
  32. _M.hits += 1
  33. return value
  34. def clear():
  35. """Clear the cache and reset cache statistics."""
  36. cache.clear()
  37. _M.hits = _M.misses = 0
  38. _M.hits = _M.misses = 0
  39. _M.clear = clear
  40. _M.original_func = fun
  41. return _M
  42. return _memoize