[IMP] fields: optimize setup_base() for regular (non-related) fields
Split the methods `_setup_regular` and `_setup_related` in `base` and `full` parts, such that the `base` part is done in `setup_base()`, and the `full` part is done in `setup_full()`. This optimizes the setup of models during the installation of modules: regular fields are not set up again from scratch. Only related fields (which are less common) are always set up from scratch.
This commit is contained in:
+42
-32
@@ -330,6 +330,7 @@ class Field(object):
|
||||
kwargs['string'] = string
|
||||
args = {key: val for key, val in kwargs.iteritems() if val is not None}
|
||||
self.args = args or EMPTY_DICT
|
||||
self.setup_full_done = False
|
||||
|
||||
def new(self, **kwargs):
|
||||
""" Return a field of the same type as ``self``, with its own parameters. """
|
||||
@@ -381,7 +382,17 @@ class Field(object):
|
||||
|
||||
def setup_base(self, model, name):
|
||||
""" Base setup: things that do not depend on other models/fields. """
|
||||
self._setup_attrs(model, name)
|
||||
if self.setup_full_done and not self.related:
|
||||
# optimization for regular fields: keep the base setup
|
||||
self.setup_full_done = False
|
||||
self.inverse_fields = ()
|
||||
self.computed_fields = ()
|
||||
self._triggers = ()
|
||||
else:
|
||||
# do the base setup from scratch
|
||||
self._setup_attrs(model, name)
|
||||
if not self.related:
|
||||
self._setup_regular_base(model)
|
||||
|
||||
#
|
||||
# Setup field parameter attributes
|
||||
@@ -463,16 +474,16 @@ class Field(object):
|
||||
""" Full setup: everything else, except recomputation triggers. """
|
||||
if not self.setup_full_done:
|
||||
if not self.related:
|
||||
self._setup_regular(model)
|
||||
self._setup_regular_full(model)
|
||||
else:
|
||||
self._setup_related(model)
|
||||
self._setup_related_full(model)
|
||||
self.setup_full_done = True
|
||||
|
||||
#
|
||||
# Setup of non-related fields
|
||||
#
|
||||
|
||||
def _setup_regular(self, model):
|
||||
def _setup_regular_base(self, model):
|
||||
""" Setup the attributes of a non-related field. """
|
||||
def make_depends(deps):
|
||||
return tuple(deps(model) if callable(deps) else deps)
|
||||
@@ -493,11 +504,15 @@ class Field(object):
|
||||
if isinstance(self.search, basestring):
|
||||
self.search = getattr(type(model), self.search)
|
||||
|
||||
def _setup_regular_full(self, model):
|
||||
""" Setup the inverse field(s) of ``self``. """
|
||||
pass
|
||||
|
||||
#
|
||||
# Setup of related fields
|
||||
#
|
||||
|
||||
def _setup_related(self, model):
|
||||
def _setup_related_full(self, model):
|
||||
""" Setup the attributes of a related field. """
|
||||
# fix the type of self.related if necessary
|
||||
if isinstance(self.related, basestring):
|
||||
@@ -569,7 +584,7 @@ class Field(object):
|
||||
""" Determine the domain to search on field ``self``. """
|
||||
return [('.'.join(self.related), operator, value)]
|
||||
|
||||
# properties used by _setup_related() to copy values from related field
|
||||
# properties used by _setup_related_full() to copy values from related field
|
||||
_related_comodel_name = property(attrgetter('comodel_name'))
|
||||
_related_string = property(attrgetter('string'))
|
||||
_related_help = property(attrgetter('help'))
|
||||
@@ -1074,14 +1089,6 @@ class Float(Field):
|
||||
else:
|
||||
return self._digits
|
||||
|
||||
def _setup_digits(self, model):
|
||||
""" Setup the digits for ``self`` and its corresponding column """
|
||||
pass
|
||||
|
||||
def _setup_regular(self, model):
|
||||
super(Float, self)._setup_regular(model)
|
||||
self._setup_digits(model)
|
||||
|
||||
_related__digits = property(attrgetter('_digits'))
|
||||
_related_group_operator = property(attrgetter('group_operator'))
|
||||
|
||||
@@ -1121,10 +1128,13 @@ class Monetary(Field):
|
||||
_related_currency_field = property(attrgetter('currency_field'))
|
||||
_description_currency_field = property(attrgetter('currency_field'))
|
||||
|
||||
def _setup_regular(self, model):
|
||||
super(Monetary, self)._setup_regular(model)
|
||||
def _setup_regular_base(self, model):
|
||||
super(Monetary, self)._setup_regular_base(model)
|
||||
if not self.currency_field:
|
||||
self.currency_field = 'currency_id'
|
||||
|
||||
def _setup_regular_full(self, model):
|
||||
super(Monetary, self)._setup_regular_full(model)
|
||||
assert self.currency_field in model._fields, \
|
||||
"Field %s with unknown currency_field %r" % (self, self.currency_field)
|
||||
|
||||
@@ -1213,8 +1223,8 @@ class Char(_String):
|
||||
_related_size = property(attrgetter('size'))
|
||||
_description_size = property(attrgetter('size'))
|
||||
|
||||
def _setup_regular(self, model):
|
||||
super(Char, self)._setup_regular(model)
|
||||
def _setup_regular_base(self, model):
|
||||
super(Char, self)._setup_regular_base(model)
|
||||
assert isinstance(self.size, (NoneType, int)), \
|
||||
"Char field %s with non-integer size %r" % (self, self.size)
|
||||
|
||||
@@ -1422,12 +1432,12 @@ class Selection(Field):
|
||||
selection = api.expected(api.model, selection)
|
||||
super(Selection, self).__init__(selection=selection, string=string, **kwargs)
|
||||
|
||||
def _setup_regular(self, model):
|
||||
super(Selection, self)._setup_regular(model)
|
||||
def _setup_regular_base(self, model):
|
||||
super(Selection, self)._setup_regular_base(model)
|
||||
assert self.selection is not None, "Field %s without selection" % self
|
||||
|
||||
def _setup_related(self, model):
|
||||
super(Selection, self)._setup_related(model)
|
||||
def _setup_related_full(self, model):
|
||||
super(Selection, self)._setup_related_full(model)
|
||||
# selection must be computed on related field
|
||||
field = self.related_field
|
||||
self.selection = lambda model: field._description_selection(model.env)
|
||||
@@ -1512,8 +1522,8 @@ class Reference(Selection):
|
||||
_related_size = property(attrgetter('size'))
|
||||
_column_size = property(attrgetter('size'))
|
||||
|
||||
def _setup_regular(self, model):
|
||||
super(Reference, self)._setup_regular(model)
|
||||
def _setup_regular_base(self, model):
|
||||
super(Reference, self)._setup_regular_base(model)
|
||||
assert isinstance(self.size, (NoneType, int)), \
|
||||
"Reference field %s with non-integer size %r" % (self, self.size)
|
||||
|
||||
@@ -1547,8 +1557,8 @@ class _Relational(Field):
|
||||
'context': {}, # context for searching values
|
||||
}
|
||||
|
||||
def _setup_regular(self, model):
|
||||
super(_Relational, self)._setup_regular(model)
|
||||
def _setup_regular_base(self, model):
|
||||
super(_Relational, self)._setup_regular_base(model)
|
||||
if self.comodel_name not in model.pool:
|
||||
_logger.warning("Field %s with unknown comodel_name %r", self, self.comodel_name)
|
||||
self.comodel_name = '_unknown'
|
||||
@@ -1830,9 +1840,8 @@ class One2many(_RelationalMulti):
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def _setup_regular(self, model):
|
||||
super(One2many, self)._setup_regular(model)
|
||||
|
||||
def _setup_regular_full(self, model):
|
||||
super(One2many, self)._setup_regular_full(model)
|
||||
if self.inverse_name:
|
||||
# link self to its inverse field and vice-versa
|
||||
comodel = model.env[self.comodel_name]
|
||||
@@ -1900,15 +1909,16 @@ class Many2many(_RelationalMulti):
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def _setup_regular(self, model):
|
||||
super(Many2many, self)._setup_regular(model)
|
||||
|
||||
def _setup_regular_base(self, model):
|
||||
super(Many2many, self)._setup_regular_base(model)
|
||||
if not self.relation and self.store:
|
||||
# retrieve self.relation from the corresponding column
|
||||
column = self.to_column()
|
||||
if isinstance(column, fields.many2many):
|
||||
self.relation, self.column1, self.column2 = column._sql_names(model)
|
||||
|
||||
def _setup_regular_full(self, model):
|
||||
super(Many2many, self)._setup_regular_full(model)
|
||||
if self.relation:
|
||||
m2m = model.pool._m2m
|
||||
# if inverse field has already been setup, it is present in m2m
|
||||
|
||||
Reference in New Issue
Block a user