[FIX] fields: when computing digits, use an existing cursor instead of a new one

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.
This commit is contained in:
Raphael Collet 2015-05-05 12:01:22 +02:00
parent 9d7b6aa67f
commit 071152216f
3 changed files with 18 additions and 8 deletions

View File

@ -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

View File

@ -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

View File

@ -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