From 071152216fe44039f75e821b0cbf31344b66d174 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 5 May 2015 12:01:22 +0200 Subject: [PATCH] [FIX] fields: when computing digits, use an existing cursor instead of a new one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The computation of property `digits` was creating a new cursor to call the function that determines digits. This technique is fragile because the current cursor may have pending updates that the new cursor will not see. The issue was discovered by Cécile Tonglet (cto). She observed an infinite loop during a database migration, and a traceback inside the loop showed the presence of the `digits` property. This change fixes the infinite loop issue. --- openerp/api.py | 8 ++++++-- openerp/fields.py | 6 ++++-- openerp/osv/fields.py | 12 ++++++++---- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/openerp/api.py b/openerp/api.py index 4ab512be6a9..b377076cf55 100644 --- a/openerp/api.py +++ b/openerp/api.py @@ -68,7 +68,7 @@ from pprint import pformat from weakref import WeakSet from werkzeug.local import Local, release_local -from openerp.tools import frozendict +from openerp.tools import frozendict, classproperty _logger = logging.getLogger(__name__) @@ -674,6 +674,10 @@ class Environment(object): """ _local = Local() + @classproperty + def envs(cls): + return cls._local.environments + @classmethod @contextmanager def manage(cls): @@ -699,7 +703,7 @@ class Environment(object): args = (cr, uid, context) # if env already exists, return it - env, envs = None, cls._local.environments + env, envs = None, cls.envs for env in envs: if env.args == args: return env diff --git a/openerp/fields.py b/openerp/fields.py index 036b5af82b9..1613b69cf98 100644 --- a/openerp/fields.py +++ b/openerp/fields.py @@ -1054,8 +1054,10 @@ class Float(Field): @property def digits(self): if callable(self._digits): - with registry().cursor() as cr: - return self._digits(cr) + # retrieve a cursor from any environment + from openerp.api import Environment + cr = next(iter(Environment.envs)).cr + return self._digits(cr) else: return self._digits diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index e9c2c38f97c..7bcb8606e64 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -388,8 +388,10 @@ class float(_column): @property def digits(self): if self._digits_compute: - with registry().cursor() as cr: - return self._digits_compute(cr) + # retrieve a cursor from any environment + from openerp.api import Environment + cr = next(iter(Environment.envs)).cr + return self._digits_compute(cr) else: return self._digits @@ -1309,8 +1311,10 @@ class function(_column): @property def digits(self): if self._digits_compute: - with registry().cursor() as cr: - return self._digits_compute(cr) + # retrieve a cursor from any environment + from openerp.api import Environment + cr = next(iter(Environment.envs)).cr + return self._digits_compute(cr) else: return self._digits