]>
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 | """ | |
7 | from __future__ import absolute_import | |
8 | ||
9 | from functools import wraps | |
10 | from collections import OrderedDict | |
11 | from threading import RLock | |
12 | ||
13 | ||
14 | def lru_cache(maxsize=128, typed=False): | |
15 | if typed is not False: | |
16 | raise NotImplementedError("typed caching not supported") | |
17 | ||
18 | def decorating_function(function): | |
19 | cache = OrderedDict() | |
20 | stats = [0, 0] | |
21 | rlock = RLock() | |
22 | setattr( | |
23 | function, | |
24 | 'cache_info', | |
25 | lambda: | |
26 | "hits={}, misses={}, maxsize={}, currsize={}".format( | |
27 | stats[0], stats[1], maxsize, len(cache))) | |
28 | ||
29 | @wraps(function) | |
30 | def wrapper(*args, **kwargs): | |
31 | key = args + tuple(kwargs.items()) | |
32 | with rlock: | |
33 | if key in cache: | |
34 | ret = cache[key] | |
35 | del cache[key] | |
36 | cache[key] = ret | |
37 | stats[0] += 1 | |
38 | else: | |
39 | ret = function(*args, **kwargs) | |
40 | if len(cache) == maxsize: | |
41 | cache.popitem(last=False) | |
42 | cache[key] = ret | |
43 | stats[1] += 1 | |
44 | return ret | |
45 | ||
46 | return wrapper | |
47 | return decorating_function |