From a4eaa86e440c9c5cf7ce4b3c84d98b33f70122ff Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Fri, 10 Jul 2015 11:19:27 +0200 Subject: [PATCH] [IMP] fields: split attribute `_attrs` into `args` and `_attrs` Make an explicit distinction between both semantics of `_attrs`: - the parameters given to `__init__` in `args` - the non-slot attributes (memory optimization) in `_attrs` --- openerp/addons/base/ir/ir_model.py | 2 +- openerp/fields.py | 48 ++++++++++++++++-------------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/openerp/addons/base/ir/ir_model.py b/openerp/addons/base/ir/ir_model.py index f7fea3a28fd..b0d7dee0173 100644 --- a/openerp/addons/base/ir/ir_model.py +++ b/openerp/addons/base/ir/ir_model.py @@ -491,7 +491,7 @@ class ir_model_fields(osv.osv): for field_name, field_patches in model_patches.iteritems(): # update field properties, and adapt corresponding column field = obj._fields[field_name] - attrs = dict(field._attrs, **field_patches) + attrs = dict(field.args, **field_patches) obj._add_field(field_name, field.new(**attrs)) # update database schema diff --git a/openerp/fields.py b/openerp/fields.py index 0a6f858d5c4..a00d0c19b46 100644 --- a/openerp/fields.py +++ b/openerp/fields.py @@ -256,9 +256,8 @@ class Field(object): relational = False # whether the field is a relational one _slots = { - '_attrs': EMPTY_DICT, # dictionary of field attributes; it contains: - # - all attributes after __init__() - # - free attributes only after set_class_name() + 'args': EMPTY_DICT, # the parameters given to __init__() + '_attrs': EMPTY_DICT, # the field's non-slot attributes 'automatic': False, # whether the field is automatically created ("magic" field) 'inherited': False, # whether the field is inherited (_inherits) @@ -302,8 +301,8 @@ class Field(object): def __init__(self, string=None, **kwargs): kwargs['string'] = string - attrs = {key: val for key, val in kwargs.iteritems() if val is not None} - self._attrs = attrs or EMPTY_DICT + args = {key: val for key, val in kwargs.iteritems() if val is not None} + self.args = args or EMPTY_DICT def __getattr__(self, name): """ Access non-slot field attribute. """ @@ -322,6 +321,15 @@ class Field(object): else: self._attrs = {name: value} # replace EMPTY_DICT + def set_all_attrs(self, attrs): + """ Set all field attributes at once (with slot defaults). """ + # optimization: we assign slots only + assign = object.__setattr__ + for key, val in self._slots.iteritems(): + assign(self, key, attrs.pop(key, val)) + if attrs: + assign(self, '_attrs', attrs) + def __delattr__(self, name): """ Remove non-slot field attribute. """ try: @@ -335,21 +343,18 @@ class Field(object): def set_class_name(self, cls, name): """ Assign the model class and field name of ``self``. """ - self_attrs = self._attrs - for attr, value in self._slots.iteritems(): - setattr(self, attr, value) - - self.model_name = cls._name - self.name = name - # determine all inherited field attributes attrs = {} for field in resolve_all_mro(cls, name, reverse=True): if isinstance(field, type(self)): - attrs.update(field._attrs) + attrs.update(field.args) else: attrs.clear() - attrs.update(self_attrs) # necessary in case self is not in cls + attrs.update(self.args) # necessary in case self is not in cls + + attrs['args'] = self.args + attrs['model_name'] = cls._name + attrs['name'] = name # initialize ``self`` with ``attrs`` if attrs.get('compute'): @@ -366,8 +371,7 @@ class Field(object): if not isinstance(attrs.get('origin'), (NoneType, fields.function)): attrs.pop('store', None) - for attr, value in attrs.iteritems(): - setattr(self, attr, value) + self.set_all_attrs(attrs) if not self.string and not self.related: # related fields get their string from their parent field @@ -391,9 +395,9 @@ class Field(object): # klass contains another value overridden by self return - if 'default' in field._attrs: + if 'default' in field.args: # take the default in field, and adapt it for cls._defaults - value = field._attrs['default'] + value = field.args['default'] if callable(value): from openerp import api self.default = value @@ -1412,11 +1416,11 @@ class Selection(Field): if isinstance(field, type(self)): # We cannot use field.selection or field.selection_add here # because those attributes are overridden by ``set_class_name``. - if 'selection' in field._attrs: - self.selection = field._attrs['selection'] - if 'selection_add' in field._attrs: + if 'selection' in field.args: + self.selection = field.args['selection'] + if 'selection_add' in field.args: # use an OrderedDict to update existing values - selection_add = field._attrs['selection_add'] + selection_add = field.args['selection_add'] self.selection = OrderedDict(self.selection + selection_add).items() else: self.selection = None