summaryrefslogtreecommitdiff
path: root/bin/tools/misc.py
diff options
context:
space:
mode:
Diffstat (limited to 'bin/tools/misc.py')
-rw-r--r--bin/tools/misc.py167
1 files changed, 94 insertions, 73 deletions
diff --git a/bin/tools/misc.py b/bin/tools/misc.py
index a9157541a99..6b366eec67f 100644
--- a/bin/tools/misc.py
+++ b/bin/tools/misc.py
@@ -2,7 +2,7 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
+# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
# This program is free software: you can redistribute it and/or modify
@@ -549,26 +549,74 @@ class cache(object):
self.multi = multi
self.lasttime = time.time()
self.cache = {}
-
+ self.fun = None
cache.__caches.append(self)
- @classmethod
- def clean_cache_for_db(cls, dbname):
- def get_dbname_from_key(key):
- for e in key:
- if e[0] == 'dbname':
- return e[1]
- return None
-
- for cache in cls.__caches:
- keys_to_del = [key for key in cache.cache if get_dbname_from_key(key) == dbname]
- for key in keys_to_del:
- del cache.cache[key]
+
+ def _generate_keys(self, dbname, kwargs2):
+ """
+ Generate keys depending of the arguments and the self.mutli value
+ """
+
+ def to_tuple(d):
+ i = d.items()
+ i.sort()
+ return tuple(i)
+
+ if not self.multi:
+ key = (('dbname', dbname),) + to_tuple(kwargs2)
+ yield key, None
+ else:
+ multis = kwargs2[self.multi][:]
+ for id in multis:
+ kwargs2[self.multi] = [id]
+ key = (('dbname', dbname),) + to_tuple(kwargs2)
+ yield key, id
+
+ def _unify_args(self, *args, **kwargs):
+ # Update named arguments with positional argument values (without self and cr)
+ kwargs2 = self.fun_default_values.copy()
+ kwargs2.update(kwargs)
+ kwargs2.update(dict(zip(self.fun_arg_names, args[self.skiparg-2:])))
+ for k in kwargs2:
+ if isinstance(kwargs2[k], (list, dict, set)):
+ kwargs2[k] = tuple(kwargs2[k])
+ elif not is_hashable(kwargs2[k]):
+ kwargs2[k] = repr(kwargs2[k])
+
+ return kwargs2
+
+ def clear(self, dbname, *args, **kwargs):
+ """clear the cache for database dbname
+ if *args and **kwargs are both empty, clear all the keys related to this database
+ """
+ if not args and not kwargs:
+ keys_to_del = [key for key in self.cache if key[0][1] == dbname]
+ else:
+ kwargs2 = self._unify_args(*args, **kwargs)
+ keys_to_del = [key for key, _ in self._generate_keys(dbname, kwargs2) if key in self.cache]
+
+ for key in keys_to_del:
+ del self.cache[key]
+
+ @classmethod
+ def clean_caches_for_db(cls, dbname):
+ for c in cls.__caches:
+ c.clear(dbname)
def __call__(self, fn):
- arg_names = inspect.getargspec(fn)[0][self.skiparg:]
-
- def cached_result(self2, cr=None, *args, **kwargs):
+ if self.fun is not None:
+ raise Exception("Can not use a cache instance on more than one function")
+ self.fun = fn
+
+ argspec = inspect.getargspec(fn)
+ self.fun_arg_names = argspec[0][self.skiparg:]
+ self.fun_default_values = {}
+ if argspec[3]:
+ self.fun_default_values = dict(zip(self.fun_arg_names[-len(argspec[3]):], argspec[3]))
+ debug(self.fun_default_values)
+
+ def cached_result(self2, cr, *args, **kwargs):
if time.time()-self.timeout > self.lasttime:
self.lasttime = time.time()
t = time.time()-self.timeout
@@ -576,64 +624,36 @@ class cache(object):
if self.cache[key][1]<t:
del self.cache[key]
- if cr is None:
- self.cache = {}
- return True
- if ('clear_keys' in kwargs):
- if (kwargs['clear_keys'] in self.cache):
- del self.cache[kwargs['clear_keys']]
- return True
-
- # Update named arguments with positional argument values (without self and cr)
- kwargs2 = kwargs.copy()
- kwargs2.update(dict(zip(arg_names, args[self.skiparg-2:])))
- for k in kwargs2:
- if isinstance(kwargs2[k], (list, dict, set)):
- kwargs2[k] = tuple(kwargs2[k])
- elif not is_hashable(kwargs2[k]):
- kwargs2[k] = repr(kwargs2[k])
-
- if self.multi:
- kwargs3 = kwargs2.copy()
- notincache = []
- result = {}
- for id in kwargs3[self.multi]:
- kwargs2[self.multi] = [id]
- kwargs4 = kwargs2.items()
- kwargs4.sort()
-
- # Work out key as a tuple of ('argname', value) pairs
- key = (('dbname', cr.dbname),) + tuple(kwargs4)
- if key in self.cache:
- result[id] = self.cache[key][0]
- else:
- notincache.append(id)
-
-
-
- if notincache:
- kwargs2[self.multi] = notincache
- result2 = fn(self2, cr, *args[2:self.skip], **kwargs3)
- for id in result2:
- kwargs2[self.multi] = [id]
- kwargs4 = kwargs2.items()
- kwargs4.sort()
- key = (('dbname', cr.dbname),) + tuple(kwargs4)
- self.cache[key] = result2[id]
- result.updat(result2)
- return result
-
- kwargs2 = kwargs2.items()
- kwargs2.sort()
-
- key = (('dbname', cr.dbname),) + tuple(kwargs2)
- if key in self.cache:
- return self.cache[key][0]
+ kwargs2 = self._unify_args(*args, **kwargs)
- result = fn(self2, cr, *args, **kwargs)
-
- self.cache[key] = (result, time.time())
+ result = {}
+ notincache = {}
+ for key, id in self._generate_keys(cr.dbname, kwargs2):
+ if key in self.cache:
+ result[id] = self.cache[key][0]
+ else:
+ notincache[id] = key
+
+ if notincache:
+ if self.multi:
+ kwargs2[self.multi] = notincache.keys()
+
+ result2 = fn(self2, cr, *args[2:self.skiparg], **kwargs2)
+ if not self.multi:
+ key = notincache[None]
+ self.cache[key] = (result2, time.time())
+ result[None] = result2
+ else:
+ for id in result2:
+ key = notincache[id]
+ self.cache[key] = (result2[id], time.time())
+ result.update(result2)
+
+ if not self.multi:
+ return result[None]
return result
+
+ cached_result.clear_cache = self.clear
return cached_result
def to_xml(s):
@@ -688,6 +708,7 @@ def get_languages():
languages={
'ar_AR': u'Arabic / الْعَرَبيّة',
'bg_BG': u'Bulgarian / български',
+ 'bs_BS': u'Bosnian / bosanski jezik',
'ca_ES': u'Catalan / Català',
'cs_CZ': u'Czech / Čeština',
'de_DE': u'German / Deutsch',