]>
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 | ||
11fdf7f2 | 9 | from collections import OrderedDict |
f67539c2 | 10 | from functools import wraps |
11fdf7f2 TL |
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() | |
9f95a23c TL |
22 | setattr(function, 'cache_info', lambda: |
23 | "hits={}, misses={}, maxsize={}, currsize={}".format( | |
24 | stats[0], stats[1], maxsize, len(cache))) | |
11fdf7f2 TL |
25 | |
26 | @wraps(function) | |
27 | def wrapper(*args, **kwargs): | |
28 | key = args + tuple(kwargs.items()) | |
29 | with rlock: | |
30 | if key in cache: | |
31 | ret = cache[key] | |
32 | del cache[key] | |
33 | cache[key] = ret | |
34 | stats[0] += 1 | |
35 | else: | |
36 | ret = function(*args, **kwargs) | |
37 | if len(cache) == maxsize: | |
38 | cache.popitem(last=False) | |
39 | cache[key] = ret | |
40 | stats[1] += 1 | |
41 | return ret | |
42 | ||
43 | return wrapper | |
44 | return decorating_function |