[IMP] Make wizard work
[odoo/odoo.git] / openerp / tools / cache.py
1 import lru
2
3 class ormcache(object):
4     """ LRU cache decorator for orm methods,
5     """
6
7     def __init__(self, skiparg=2, size=8192, multi=None, timeout=None):
8         self.skiparg = skiparg
9         self.size = size
10         self.method = None
11         self.stat_miss = 0
12         self.stat_hit = 0
13         self.stat_err = 0
14
15     def __call__(self,m):
16         self.method = m
17         def lookup(self2, cr, *args):
18             r = self.lookup(self2, cr, *args)
19             return r
20         lookup.clear_cache = self.clear
21         return lookup
22
23     def stat(self):
24         return "lookup-stats hit=%s miss=%s err=%s ratio=%.1f" % (self.stat_hit,self.stat_miss,self.stat_err, (100*float(self.stat_hit))/(self.stat_miss+self.stat_hit) )
25
26     def lru(self, self2):
27         try:
28             ormcache = getattr(self2, '_ormcache')
29         except AttributeError:
30             ormcache = self2._ormcache = {}
31         try:
32             d = ormcache[self.method]
33         except KeyError:
34             d = ormcache[self.method] = lru.LRU(self.size)
35         return d
36
37     def lookup(self, self2, cr, *args):
38         d = self.lru(self2)
39         key = args[self.skiparg-2:]
40         try:
41            r = d[key]
42            self.stat_hit += 1
43            return r
44         except KeyError:
45            self.stat_miss += 1
46            value = d[key] = self.method(self2, cr, *args)
47            return value
48         except TypeError:
49            self.stat_err += 1
50            return self.method(self2, cr, *args)
51
52     def clear(self, self2, *args):
53         """ Remove *args entry from the cache or all keys if *args is undefined 
54         """
55         d = self.lru(self2)
56         if args:
57             try:
58                 key = args[self.skiparg-2:]
59                 del d[key]
60                 self2.pool._any_cache_cleared = True
61             except KeyError:
62                 pass
63         else:
64             d.clear()
65             self2.pool._any_cache_cleared = True
66
67 class ormcache_multi(ormcache):
68     def __init__(self, skiparg=2, size=8192, multi=3):
69         super(ormcache_multi,self).__init__(skiparg,size)
70         self.multi = multi - 2
71
72     def lookup(self, self2, cr, *args):
73         d = self.lru(self2)
74         args = list(args)
75         multi = self.multi
76         ids = args[multi]
77         r = {}
78         miss = []
79
80         for i in ids:
81             args[multi] = i
82             key = tuple(args[self.skiparg-2:])
83             try:
84                r[i] = d[key]
85                self.stat_hit += 1
86             except Exception:
87                self.stat_miss += 1
88                miss.append(i)
89
90         if miss:
91             args[multi] = miss
92             r.update(self.method(self2, cr, *args))
93
94         for i in miss:
95             args[multi] = i
96             key = tuple(args[self.skiparg-2:])
97             d[key] = r[i]
98
99         return r
100
101 class dummy_cache(object):
102     """ Cache decorator replacement to actually do no caching.
103     """
104     def __init__(self, *l, **kw):
105         pass
106     def __call__(self, fn):
107         fn.clear_cache = self.clear
108         return fn
109     def clear(self, *l, **kw):
110         pass
111
112 if __name__ == '__main__':
113
114     class A():
115         @ormcache()
116         def m(self,a,b):
117             print  "A::m(", self,a,b
118             return 1
119
120         @ormcache_multi(multi=3)
121         def n(self,cr,uid,ids):
122             print  "m", self,cr,uid,ids
123             return dict([(i,i) for i in ids])
124
125     a=A()
126     r=a.m(1,2)
127     r=a.m(1,2)
128     r=a.n("cr",1,[1,2,3,4])
129     r=a.n("cr",1,[1,2])
130     print r
131     for i in a._ormcache:
132         print a._ormcache[i].d
133     a.n.clear_cache(a,1,1)
134     r=a.n("cr",1,[1,2])
135     print r
136     r=a.n("cr",1,[1,2])
137
138 # For backward compatibility
139 cache = ormcache
140
141 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: