diff --git a/addons/decimal_precision/decimal_precision.py b/addons/decimal_precision/decimal_precision.py index f169b698ebd..728fa9cc99b 100644 --- a/addons/decimal_precision/decimal_precision.py +++ b/addons/decimal_precision/decimal_precision.py @@ -48,11 +48,6 @@ class decimal_precision(orm.Model): def clear_cache(self, cr): """clear cache and update models. Notify other workers to restart their registry.""" self.precision_get.clear_cache(self) - env = openerp.api.Environment(cr, SUPERUSER_ID, {}) - for model in self.pool.values(): - for field in model._fields.values(): - if field.type == 'float': - field._setup_digits(env) RegistryManager.signal_registry_change(cr.dbname) def create(self, cr, uid, data, context=None): diff --git a/openerp/__init__.py b/openerp/__init__.py index 24a193bf759..691a7d27c1c 100644 --- a/openerp/__init__.py +++ b/openerp/__init__.py @@ -56,11 +56,15 @@ del time # The hard-coded super-user id (a.k.a. administrator, or root user). SUPERUSER_ID = 1 -def registry(database_name): +def registry(database_name=None): """ - Return the model registry for the given database. If the registry does not - exist yet, it is created on the fly. + Return the model registry for the given database, or the database mentioned + on the current thread. If the registry does not exist yet, it is created on + the fly. """ + if database_name is None: + import threading + database_name = threading.currentThread().dbname return modules.registry.RegistryManager.get(database_name) #---------------------------------------------------------- diff --git a/openerp/fields.py b/openerp/fields.py index da0ba4dc374..9aadca4b3cb 100644 --- a/openerp/fields.py +++ b/openerp/fields.py @@ -991,26 +991,28 @@ class Float(Field): """ type = 'float' _digits = None # digits argument passed to class initializer - digits = None # digits as computed by setup() group_operator = None # operator for aggregating values def __init__(self, string=None, digits=None, **kwargs): super(Float, self).__init__(string=string, _digits=digits, **kwargs) + @property + def digits(self): + if callable(self._digits): + with registry().cursor() as cr: + return self._digits(cr) + else: + return self._digits + def _setup_digits(self, env): """ Setup the digits for `self` and its corresponding column """ - self.digits = self._digits(env.cr) if callable(self._digits) else self._digits - if self.digits: - assert isinstance(self.digits, (tuple, list)) and len(self.digits) >= 2, \ - "Float field %s with digits %r, expecting (total, decimal)" % (self, self.digits) - if self.column: - self.column.digits_change(env.cr) + pass def _setup_regular(self, env): super(Float, self)._setup_regular(env) self._setup_digits(env) - _related_digits = property(attrgetter('digits')) + _related__digits = property(attrgetter('_digits')) _related_group_operator = property(attrgetter('group_operator')) _description_digits = property(attrgetter('digits')) @@ -1021,10 +1023,9 @@ class Float(Field): def convert_to_cache(self, value, record, validate=True): # apply rounding here, otherwise value in cache may be wrong! - if self.digits: - return float_round(float(value or 0.0), precision_digits=self.digits[1]) - else: - return float(value or 0.0) + value = float(value or 0.0) + digits = self.digits + return float_round(value, precision_digits=digits[1]) if digits else value class _String(Field): @@ -1790,7 +1791,7 @@ class Id(Field): raise TypeError("field 'id' cannot be assigned") # imported here to avoid dependency cycle issues -from openerp import SUPERUSER_ID +from openerp import SUPERUSER_ID, registry from .exceptions import Warning, AccessError, MissingError from .models import BaseModel, MAGIC_COLUMNS from .osv import fields diff --git a/openerp/models.py b/openerp/models.py index 76ad1e042bf..0846521888d 100644 --- a/openerp/models.py +++ b/openerp/models.py @@ -659,8 +659,6 @@ class BaseModel(object): # process store of low-level function fields for fname, column in cls._columns.iteritems(): - if hasattr(column, 'digits_change'): - column.digits_change(cr) # filter out existing store about this field pool._store_function[cls._name] = [ stored diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index cc11669ef33..239a55e394f 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -51,7 +51,7 @@ from openerp.tools.translate import _ from openerp.tools import float_round, float_repr from openerp.tools import html_sanitize import simplejson -from openerp import SUPERUSER_ID +from openerp import SUPERUSER_ID, registry _logger = logging.getLogger(__name__) @@ -334,36 +334,42 @@ class html(text): import __builtin__ +def _symbol_set_float(self, x): + result = __builtin__.float(x or 0.0) + digits = self.digits + if digits: + precision, scale = digits + result = float_repr(float_round(result, precision_digits=scale), precision_digits=scale) + return result + class float(_column): _type = 'float' _symbol_c = '%s' - _symbol_f = lambda x: __builtin__.float(x or 0.0) - _symbol_set = (_symbol_c, _symbol_f) _symbol_get = lambda self,x: x or 0.0 + @property + def digits(self): + if self._digits_compute: + with registry().cursor() as cr: + return self._digits_compute(cr) + else: + return self._digits + def __init__(self, string='unknown', digits=None, digits_compute=None, required=False, **args): _column.__init__(self, string=string, required=required, **args) - self.digits = digits # synopsis: digits_compute(cr) -> (precision, scale) - self.digits_compute = digits_compute - - def new(self, _computed_field=False, **args): - # float columns are database-dependent, so always recreate them - return type(self)(**args) + self._digits = digits + self._digits_compute = digits_compute + self._symbol_f = lambda x: _symbol_set_float(self, x) + self._symbol_set = (self._symbol_c, self._symbol_f) def to_field_args(self): args = super(float, self).to_field_args() - args['digits'] = self.digits_compute or self.digits + args['digits'] = self._digits_compute or self._digits return args def digits_change(self, cr): - if self.digits_compute: - self.digits = self.digits_compute(cr) - if self.digits: - precision, scale = self.digits - self._symbol_set = ('%s', lambda x: float_repr(float_round(__builtin__.float(x or 0.0), - precision_digits=scale), - precision_digits=scale)) + pass class date(_column): _type = 'date' @@ -1240,10 +1246,22 @@ class function(_column): # function fields are not copied by default copy = False + @property + def digits(self): + if self._digits_compute: + with registry().cursor() as cr: + return self._digits_compute(cr) + else: + return self._digits + # # multi: compute several fields in one call # def __init__(self, fnct, arg=None, fnct_inv=None, fnct_inv_arg=None, type='float', fnct_search=None, obj=None, store=False, multi=False, **args): + # pop attributes that should not be assigned to self + self._digits = args.pop('digits', (16,2)) + self._digits_compute = args.pop('digits_compute', None) + _column.__init__(self, **args) self._obj = obj self._fnct = fnct @@ -1253,8 +1271,6 @@ class function(_column): if 'relation' in args: self._obj = args['relation'] - self.digits = args.get('digits', (16,2)) - self.digits_compute = args.get('digits_compute', None) if callable(args.get('selection')): from openerp import api self.selection = api.expected(api.cr_uid_context, args['selection']) @@ -1283,6 +1299,10 @@ class function(_column): self._symbol_c = char._symbol_c self._symbol_f = lambda x: _symbol_set_char(self, x) self._symbol_set = (self._symbol_c, self._symbol_f) + elif type == 'float': + self._symbol_c = float._symbol_c + self._symbol_f = lambda x: _symbol_set_float(self, x) + self._symbol_set = (self._symbol_c, self._symbol_f) else: type_class = globals().get(type) if type_class is not None: @@ -1304,7 +1324,7 @@ class function(_column): args = super(function, self).to_field_args() args['store'] = bool(self.store) if self._type in ('float',): - args['digits'] = self.digits_compute or self.digits + args['digits'] = self._digits_compute or self._digits elif self._type in ('selection', 'reference'): args['selection'] = self.selection elif self._type in ('many2one', 'one2many', 'many2many'): @@ -1312,14 +1332,7 @@ class function(_column): return args def digits_change(self, cr): - if self._type == 'float': - if self.digits_compute: - self.digits = self.digits_compute(cr) - if self.digits: - precision, scale = self.digits - self._symbol_set = ('%s', lambda x: float_repr(float_round(__builtin__.float(x or 0.0), - precision_digits=scale), - precision_digits=scale)) + pass def search(self, cr, uid, obj, name, args, context=None): if not self._fnct_search: