[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:
parent
9d7b6aa67f
commit
071152216f
|
@ -68,7 +68,7 @@ from pprint import pformat
|
||||||
from weakref import WeakSet
|
from weakref import WeakSet
|
||||||
from werkzeug.local import Local, release_local
|
from werkzeug.local import Local, release_local
|
||||||
|
|
||||||
from openerp.tools import frozendict
|
from openerp.tools import frozendict, classproperty
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -674,6 +674,10 @@ class Environment(object):
|
||||||
"""
|
"""
|
||||||
_local = Local()
|
_local = Local()
|
||||||
|
|
||||||
|
@classproperty
|
||||||
|
def envs(cls):
|
||||||
|
return cls._local.environments
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def manage(cls):
|
def manage(cls):
|
||||||
|
@ -699,7 +703,7 @@ class Environment(object):
|
||||||
args = (cr, uid, context)
|
args = (cr, uid, context)
|
||||||
|
|
||||||
# if env already exists, return it
|
# if env already exists, return it
|
||||||
env, envs = None, cls._local.environments
|
env, envs = None, cls.envs
|
||||||
for env in envs:
|
for env in envs:
|
||||||
if env.args == args:
|
if env.args == args:
|
||||||
return env
|
return env
|
||||||
|
|
|
@ -1054,8 +1054,10 @@ class Float(Field):
|
||||||
@property
|
@property
|
||||||
def digits(self):
|
def digits(self):
|
||||||
if callable(self._digits):
|
if callable(self._digits):
|
||||||
with registry().cursor() as cr:
|
# retrieve a cursor from any environment
|
||||||
return self._digits(cr)
|
from openerp.api import Environment
|
||||||
|
cr = next(iter(Environment.envs)).cr
|
||||||
|
return self._digits(cr)
|
||||||
else:
|
else:
|
||||||
return self._digits
|
return self._digits
|
||||||
|
|
||||||
|
|
|
@ -388,8 +388,10 @@ class float(_column):
|
||||||
@property
|
@property
|
||||||
def digits(self):
|
def digits(self):
|
||||||
if self._digits_compute:
|
if self._digits_compute:
|
||||||
with registry().cursor() as cr:
|
# retrieve a cursor from any environment
|
||||||
return self._digits_compute(cr)
|
from openerp.api import Environment
|
||||||
|
cr = next(iter(Environment.envs)).cr
|
||||||
|
return self._digits_compute(cr)
|
||||||
else:
|
else:
|
||||||
return self._digits
|
return self._digits
|
||||||
|
|
||||||
|
@ -1309,8 +1311,10 @@ class function(_column):
|
||||||
@property
|
@property
|
||||||
def digits(self):
|
def digits(self):
|
||||||
if self._digits_compute:
|
if self._digits_compute:
|
||||||
with registry().cursor() as cr:
|
# retrieve a cursor from any environment
|
||||||
return self._digits_compute(cr)
|
from openerp.api import Environment
|
||||||
|
cr = next(iter(Environment.envs)).cr
|
||||||
|
return self._digits_compute(cr)
|
||||||
else:
|
else:
|
||||||
return self._digits
|
return self._digits
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue