]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | # -*- coding: utf-8 -*- |
2 | """ | |
3 | This is a minimal implementation of lru_cache function. | |
4 | ||
5 | Based on Python 3 functools and backports.functools_lru_cache. | |
6 | """ | |
11fdf7f2 | 7 | |
11fdf7f2 | 8 | from collections import OrderedDict |
f67539c2 | 9 | from functools import wraps |
11fdf7f2 TL |
10 | from threading import RLock |
11 | ||
12 | ||
13 | def lru_cache(maxsize=128, typed=False): | |
14 | if typed is not False: | |
15 | raise NotImplementedError("typed caching not supported") | |
16 | ||
17 | def decorating_function(function): | |
18 | cache = OrderedDict() | |
19 | stats = [0, 0] | |
20 | rlock = RLock() | |
9f95a23c TL |
21 | setattr(function, 'cache_info', lambda: |
22 | "hits={}, misses={}, maxsize={}, currsize={}".format( | |
23 | stats[0], stats[1], maxsize, len(cache))) | |
11fdf7f2 TL |
24 | |
25 | @wraps(function) | |
26 | def wrapper(*args, **kwargs): | |
27 | key = args + tuple(kwargs.items()) | |
28 | with rlock: | |
29 | if key in cache: | |
30 | ret = cache[key] | |
31 | del cache[key] | |
32 | cache[key] = ret | |
33 | stats[0] += 1 | |
34 | else: | |
35 | ret = function(*args, **kwargs) | |
36 | if len(cache) == maxsize: | |
37 | cache.popitem(last=False) | |
38 | cache[key] = ret | |
39 | stats[1] += 1 | |
40 | return ret | |
41 | ||
42 | return wrapper | |
43 | return decorating_function |