changeset 392e44a1e0b8 in trytond:default
details: https://hg.tryton.org/trytond?cmd=changeset;node=392e44a1e0b8
description:
        Replace memoize with functools.lru_cache

        issue9081
        review286781002
diffstat:

 CHANGELOG                     |   1 +
 trytond/model/modelstorage.py |  24 ++++++++--------
 trytond/tools/__init__.py     |   4 +-
 trytond/tools/misc.py         |  63 -------------------------------------------
 4 files changed, 15 insertions(+), 77 deletions(-)

diffs (202 lines):

diff -r 87b102b5b4ab -r 392e44a1e0b8 CHANGELOG
--- a/CHANGELOG Tue Mar 24 10:02:58 2020 +0100
+++ b/CHANGELOG Wed Mar 25 17:34:35 2020 +0100
@@ -1,3 +1,4 @@
+* Replace memoize with functools.lru_cache
 * Add support for Python 3.8
 * Set all fields readonly for inactive record
 * Enable check_access context when checking wizard access (issue9108)
diff -r 87b102b5b4ab -r 392e44a1e0b8 trytond/model/modelstorage.py
--- a/trytond/model/modelstorage.py     Tue Mar 24 10:02:58 2020 +0100
+++ b/trytond/model/modelstorage.py     Wed Mar 25 17:34:35 2020 +0100
@@ -7,15 +7,14 @@
 
 from decimal import Decimal
 from itertools import islice, chain
-from functools import wraps
+from functools import lru_cache, wraps
 from operator import itemgetter
 from collections import defaultdict
 
 from trytond.exceptions import UserError
 from trytond.model import Model
 from trytond.model import fields
-from trytond.tools import reduce_domain, memoize, is_instance_method, \
-    grouped_slice
+from trytond.tools import reduce_domain, is_instance_method, grouped_slice
 from trytond.tools.domain_inversion import (
     domain_inversion, parse as domain_parse)
 from trytond.pyson import PYSONEncoder, PYSONDecoder, PYSON
@@ -696,7 +695,7 @@
         '''
         pool = Pool()
 
-        @memoize(1000)
+        @lru_cache(maxsize=1000)
         def get_many2one(relation, value):
             if not value:
                 return None
@@ -718,7 +717,7 @@
                 res = res[0].id
             return res
 
-        @memoize(1000)
+        @lru_cache(maxsize=1000)
         def get_many2many(relation, value):
             if not value:
                 return None
@@ -748,7 +747,7 @@
         def get_one2one(relation, value):
             return ('add', get_many2one(relation, value))
 
-        @memoize(1000)
+        @lru_cache(maxsize=1000)
         def get_reference(value, field):
             if not value:
                 return None
@@ -758,7 +757,7 @@
                 raise ImportDataError(
                     gettext('ir.msg_reference_syntax_error',
                         value=value,
-                        field='/'.join(field)))
+                        field=field))
             Relation = pool.get(relation)
             res = Relation.search([
                 ('rec_name', '=', value),
@@ -777,7 +776,7 @@
                 res = '%s,%s' % (relation, res[0].id)
             return res
 
-        @memoize(1000)
+        @lru_cache(maxsize=1000)
         def get_by_id(value, field, ftype):
             if not value:
                 return None
@@ -792,7 +791,7 @@
                     raise ImportDataError(
                         gettext('ir.msg_reference_syntax_error',
                             value=value,
-                            field='/'.join(field)))
+                            field=field))
                 value = [value]
             else:
                 value = [value]
@@ -804,7 +803,7 @@
                     raise ImportDataError(
                         gettext('ir.msg_xml_id_syntax_error',
                             value=word,
-                            field='/'.join(field)))
+                            field=field))
                 db_id = ModelData.get_id(module, xml_id)
                 res_ids.append(db_id)
             if ftype == 'many2many' and res_ids:
@@ -838,7 +837,8 @@
                 value = line[i]
                 if is_prefix_len and field[-1].endswith(':id'):
                     ftype = fields_def[field[-1][:-3]]['type']
-                    row[field[0][:-3]] = get_by_id(value, field, ftype)
+                    row[field[0][:-3]] = get_by_id(
+                        value, '/'.join(field), ftype)
                 elif is_prefix_len and ':lang=' in field[-1]:
                     field_name, lang = field[-1].split(':lang=')
                     translate.setdefault(lang, {})[field_name] = value or False
@@ -904,7 +904,7 @@
                     elif field_type == 'one2one':
                         res = get_one2one(this_field_def['relation'], value)
                     elif field_type == 'reference':
-                        res = get_reference(value, field)
+                        res = get_reference(value, '/'.join(field))
                     else:
                         res = value or None
                     row[field[-1]] = res
diff -r 87b102b5b4ab -r 392e44a1e0b8 trytond/tools/__init__.py
--- a/trytond/tools/__init__.py Tue Mar 24 10:02:58 2020 +0100
+++ b/trytond/tools/__init__.py Wed Mar 25 17:34:35 2020 +0100
@@ -2,12 +2,12 @@
 # this repository contains the full copyright notices and license terms.
 
 from .misc import (
-    file_open, get_smtp_server, memoize, reduce_ids, reduce_domain,
+    file_open, get_smtp_server, reduce_ids, reduce_domain,
     grouped_slice, is_instance_method, resolve, strip_wildcard,
     lstrip_wildcard, rstrip_wildcard, slugify)
 from .decimal_ import decistmt
 
-__all__ = ['file_open', 'get_smtp_server', 'memoize', 'reduce_ids',
+__all__ = ['file_open', 'get_smtp_server', 'reduce_ids',
     'reduce_domain', 'grouped_slice', 'is_instance_method', 'resolve',
     'strip_wildcard', 'lstrip_wildcard', 'rstrip_wildcard', 'slugify',
     'decistmt', 'ClassProperty', 'cursor_dict']
diff -r 87b102b5b4ab -r 392e44a1e0b8 trytond/tools/misc.py
--- a/trytond/tools/misc.py     Tue Mar 24 10:02:58 2020 +0100
+++ b/trytond/tools/misc.py     Wed Mar 25 17:34:35 2020 +0100
@@ -90,69 +90,6 @@
     return get_smtp_server()
 
 
-def memoize(maxsize):
-    """
-    Decorator to 'memoize' a function - caching its results with a
-    near LRU implementation.
-
-    The cache keeps a list of keys logicaly separated in 4 segment :
-
-    segment 1 | ...        | segment4
-    [k,k,k,k,k,k,k, .. ,k,k,k,k,k,k,k]
-
-    For each segment there is a pointer that loops on it.  When a key
-    is accessed from the cache it is promoted to the first segment (at
-    the pointer place of segment one), the key under the pointer is
-    moved to the next segment, the pointer is then incremented and so
-    on. A key that is removed from the last segment is removed from
-    the cache.
-
-    :param: maxsize the size of the cache (must be greater than or
-    equal to 4)
-    """
-    assert maxsize >= 4, "Memoize cannot work if maxsize is less than 4"
-
-    def wrap(fct):
-        cache = {}
-        keys = [None for i in range(maxsize)]
-        seg_size = maxsize // 4
-
-        pointers = [i * seg_size for i in range(4)]
-        max_pointers = [(i + 1) * seg_size for i in range(3)] + [maxsize]
-
-        def wrapper(*args):
-            key = repr(args)
-            res = cache.get(key)
-            if res:
-                pos, res = res
-                keys[pos] = None
-            else:
-                res = fct(*args)
-
-            value = res
-            for segment, pointer in enumerate(pointers):
-                newkey = keys[pointer]
-                keys[pointer] = key
-                cache[key] = (pointer, value)
-
-                pointers[segment] = pointer + 1
-                if pointers[segment] == max_pointers[segment]:
-                    pointers[segment] = segment * seg_size
-
-                if newkey is None:
-                    break
-                segment, value = cache.pop(newkey)
-                key = newkey
-
-            return res
-
-        wrapper.__doc__ = fct.__doc__
-        wrapper.__name__ = fct.__name__
-
-        return wrapper
-    return wrap
-
-
 def reduce_ids(field, ids):
     '''
     Return a small SQL expression for the list of ids and the sql column

Reply via email to