|
2 | 2 |
|
3 | 3 | import datetime |
4 | 4 |
|
5 | | -from decorator import decorator |
| 5 | +from decorator import decorator, decorate |
6 | 6 |
|
7 | 7 | from django.conf import settings |
8 | 8 | from django.contrib.auth import login |
@@ -74,3 +74,29 @@ def err(code, text): |
74 | 74 | PersonApiKeyEvent.objects.create(person=person, type='apikey_login', key=key, desc="Logged in with key ID %s, endpoint %s" % (key.id, key.endpoint)) |
75 | 75 | # Execute decorated function |
76 | 76 | return f(request, *args, **kwargs) |
| 77 | + |
| 78 | + |
| 79 | +def _memoize(func, self, *args, **kwargs): |
| 80 | + ''''Memoize wrapper for instance methouds. Use @lru_cache for functions.''' |
| 81 | + if kwargs: # frozenset is used to ensure hashability |
| 82 | + key = args, frozenset(kwargs.items()) |
| 83 | + else: |
| 84 | + key = args |
| 85 | + # instance method, set up cache if needed |
| 86 | + if not hasattr(self, '_cache'): |
| 87 | + self._cache = {} |
| 88 | + if not func in self._cache: |
| 89 | + self._cache[func] = {} |
| 90 | + # |
| 91 | + cache = self._cache[func] |
| 92 | + if key not in cache: |
| 93 | + cache[key] = func(self, *args, **kwargs) |
| 94 | + return cache[key] |
| 95 | +def memoize(func): |
| 96 | + if not hasattr(func, '__class__'): |
| 97 | + raise NotImplementedError("Use @lru_cache instead of memoize() for funcitons.") |
| 98 | + # For methods, we want the cache on the object, not on the class, in order |
| 99 | + # to not having to think about cache bloat and content becoming stale, so |
| 100 | + # we cannot set up the cache here. |
| 101 | + return decorate(func, _memoize) |
| 102 | + |
0 commit comments