trytond-patches/issue10433002_60001.diff

228 lines
7.8 KiB
Diff

Index: trytond/backend/database.py
===================================================================
--- a/trytond/trytond/backend/database.py
+++ b/trytond/trytond/backend/database.py
@@ -1,6 +1,7 @@
#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
from trytond.const import MODEL_CACHE_SIZE
+from collections import defaultdict
DatabaseIntegrityError = None
DatabaseOperationalError = None
@@ -109,15 +110,18 @@
def __init__(self):
self.cache = {}
+ from trytond.cache import LRUDict
+ self.cache = defaultdict(
+ lambda: LRUDict(MODEL_CACHE_SIZE))
def get_cache(self):
- from trytond.cache import LRUDict
from trytond.transaction import Transaction
- user = Transaction().user
- context = Transaction().context
+ transaction = Transaction()
+ user = transaction.user
+ context = transaction.context
keys = tuple(((key, context[key]) for key in sorted(self.cache_keys)
if key in context))
- return self.cache.setdefault((user, keys), LRUDict(MODEL_CACHE_SIZE))
+ return self.cache[(user, keys)]
def execute(self, sql, params=None):
'''
Index: trytond/cache.py
===================================================================
--- a/trytond/trytond/cache.py
+++ b/trytond/trytond/cache.py
@@ -127,9 +127,12 @@
Dictionary with a size limit.
If size limit is reached, it will remove the first added items.
"""
+ __slots__ = ('size_limit', 'counter')
+
def __init__(self, size_limit, *args, **kwargs):
assert size_limit > 0
self.size_limit = size_limit
+ self.counter = Transaction().counter
super(LRUDict, self).__init__(*args, **kwargs)
self._check_size_limit()
@@ -146,6 +149,14 @@
self._check_size_limit()
return default
+ def clear(self):
+ super(LRUDict, self).clear()
+ self.counter = Transaction().counter
+
+ def refresh(self):
+ if self.counter != Transaction().counter:
+ self.clear()
+
def _check_size_limit(self):
while len(self) > self.size_limit:
self.popitem(last=False)
Index: trytond/model/fields/field.py
===================================================================
--- a/trytond/trytond/model/fields/field.py
+++ b/trytond/trytond/model/fields/field.py
@@ -210,6 +210,8 @@
if inst is None:
return self
assert self.name is not None
+ if self.name == 'id':
+ return inst._id
return inst.__getattr__(self.name)
def __set__(self, inst, value):
Index: trytond/model/model.py
===================================================================
--- a/trytond/trytond/model/model.py
+++ b/trytond/trytond/model/model.py
@@ -413,36 +413,30 @@
super(Model, self).__init__()
if id is not None:
id = int(id)
- self.__dict__['id'] = id
+ self._id = id
self._values = None
- parent_values = {}
- for name, value in kwargs.iteritems():
- if not name.startswith('_parent_'):
- setattr(self, name, value)
- else:
- parent_values[name] = value
- for name, value in parent_values.iteritems():
- parent_name, field = name.split('.', 1)
- parent_name = parent_name[8:] # Strip '_parent_'
- parent = getattr(self, parent_name, None)
- if parent is not None:
- setattr(parent, field, value)
- else:
- setattr(self, parent_name, {field: value})
+ if kwargs:
+ parent_values = {}
+ for name, value in kwargs.iteritems():
+ if not name.startswith('_parent_'):
+ setattr(self, name, value)
+ else:
+ parent_values[name] = value
+ for name, value in parent_values.iteritems():
+ parent_name, field = name.split('.', 1)
+ parent_name = parent_name[8:] # Strip '_parent_'
+ parent = getattr(self, parent_name, None)
+ if parent is not None:
+ setattr(parent, field, value)
+ else:
+ setattr(self, parent_name, {field: value})
def __getattr__(self, name):
- if name == 'id':
- return self.__dict__['id']
- elif self._values and name in self._values:
- return self._values.get(name)
- raise AttributeError("'%s' Model has no attribute '%s': %s"
- % (self.__name__, name, self._values))
-
- def __setattr__(self, name, value):
- if name == 'id':
- self.__dict__['id'] = value
- return
- super(Model, self).__setattr__(name, value)
+ try:
+ return self._values[name]
+ except (KeyError, TypeError):
+ raise AttributeError("'%s' Model has no attribute '%s': %s"
+ % (self.__name__, name, self._values))
def __getitem__(self, name):
warnings.warn('Use __getattr__ instead of __getitem__',
Index: trytond/model/modelstorage.py
===================================================================
--- a/trytond/trytond/model/modelstorage.py
+++ b/trytond/trytond/model/modelstorage.py
@@ -443,9 +443,14 @@
'''
Return a list of instance for the ids
'''
+ transaction = Transaction()
ids = map(int, ids)
local_cache = LRUDict(RECORD_CACHE_SIZE)
- return [cls(int(x), _ids=ids, _local_cache=local_cache) for x in ids]
+ cursor_cache = transaction.cursor.get_cache()
+ return [cls(x, _ids=ids,
+ _local_cache=local_cache,
+ _cursor_cache=cursor_cache,
+ _transaction=transaction) for x in ids]
@staticmethod
def __export_row(record, fields_names):
@@ -1144,9 +1149,13 @@
def __init__(self, id=None, **kwargs):
_ids = kwargs.pop('_ids', None)
_local_cache = kwargs.pop('_local_cache', None)
- self._cursor = Transaction().cursor
- self._user = Transaction().user
- self._context = Transaction().context
+ _cursor_cache = kwargs.pop('_cursor_cache', None)
+ transaction = kwargs.pop('_transaction', None)
+ if transaction is None:
+ transaction = Transaction()
+ self._cursor = transaction.cursor
+ self._user = transaction.user
+ self._context = transaction.context
if id is not None:
id = int(id)
if _ids is not None:
@@ -1155,13 +1164,15 @@
else:
self._ids = [id]
- self._cursor_cache = self._cursor.get_cache()
+ if _cursor_cache is not None:
+ self._cursor_cache = _cursor_cache
+ else:
+ self._cursor_cache = self._cursor.get_cache()
if _local_cache is not None:
self._local_cache = _local_cache
else:
self._local_cache = LRUDict(RECORD_CACHE_SIZE)
- self._local_cache.counter = Transaction().counter
super(ModelStorage, self).__init__(id, **kwargs)
@@ -1180,9 +1191,7 @@
raise
counter = Transaction().counter
- if self._local_cache.counter != counter:
- self._local_cache.clear()
- self._local_cache.counter = counter
+ self._local_cache.refresh()
# fetch the definition of the field
try:
@@ -1413,7 +1422,7 @@
if self.id < 0:
self._ids.remove(self.id)
try:
- self.id = self.create([save_values])[0].id
+ self._id = self.create([save_values])[0].id
finally:
self._ids.append(self.id)
else: