You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
92 lines
3.6 KiB
92 lines
3.6 KiB
# -*- coding: utf-8 -*-
|
|
# © 2016 Therp BV <http://therp.nl>
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|
import logging
|
|
from openerp import SUPERUSER_ID, models
|
|
|
|
|
|
_logger = logging.getLogger(__file__)
|
|
|
|
|
|
# TODO: this should be a helper module to cetralize the point of failure
|
|
# in case this introduces tacit bugs
|
|
class BasePatchModelsMixin(models.AbstractModel):
|
|
"""
|
|
This is a mixin class meant to simplify working with patches
|
|
on BaseModel or on abstract models like mail.thread.
|
|
If you just change them, models created earlier will lack the
|
|
attributes you add. Just inherit from this mixin, it will check
|
|
which existing models need your changes and apply them.
|
|
|
|
In your module, do something like
|
|
|
|
class MailThread(models.AbstractModel):
|
|
_name = 'mail.thread'
|
|
_inherit = ['base.patch.models.mixin', 'mail.thread']
|
|
|
|
in case you need to patch BaseModel, say
|
|
|
|
class BaseModel(models.BaseModel):
|
|
_name = 'my.unique.model.name'
|
|
_inherit = 'base.patch.models.mixin'
|
|
|
|
Your code will behave as if it was an inherited class of the class you pass
|
|
in the second parameter to _base_patch_models.
|
|
"""
|
|
_name = 'base.patch.models.mixin'
|
|
|
|
def _base_patch_models(self, cr, our_class=None, parent_class=None):
|
|
"""iterate through existing models to apply our changes there if
|
|
necessary"""
|
|
if self._name == BasePatchModelsMixin._name:
|
|
return
|
|
my_bases = self.__class__.__bases__
|
|
for i in range(max(len(my_bases) - 1, 0)):
|
|
if my_bases[i]._name == BasePatchModelsMixin._name:
|
|
our_class = my_bases[i - 1]
|
|
parent_class = my_bases[i + 1]
|
|
inherit = [self._inherit]\
|
|
if isinstance(self._inherit, basestring) else self._inherit
|
|
for i in range(len(my_bases) - 1, 0, -1):
|
|
# this can be different from the above if our mixin is used
|
|
# multiple times on the same model
|
|
if my_bases[i]._name in inherit:
|
|
parent_class = my_bases[i]
|
|
break
|
|
if self.__class__.__bases__[-1] == BasePatchModelsMixin\
|
|
and not our_class or not parent_class:
|
|
our_class = self.__class__.__bases__[-2]
|
|
parent_class = models.BaseModel
|
|
if not our_class or not parent_class:
|
|
_logger.info(
|
|
'Failed to autodetect own class or parent class for %s, '
|
|
'ignoring', self._name)
|
|
return
|
|
|
|
for model_name, model_object in self.pool.models.iteritems():
|
|
if not isinstance(model_object, parent_class):
|
|
continue
|
|
if isinstance(model_object, our_class):
|
|
continue
|
|
if not isinstance(model_object, models.Model):
|
|
continue
|
|
bases = list(model_object.__class__.__bases__)
|
|
position = 1
|
|
if parent_class == models.BaseModel:
|
|
position = len(bases)
|
|
else:
|
|
for i in range(len(bases) - 1, position, -1):
|
|
if bases[i]._name in inherit:
|
|
position = i
|
|
break
|
|
bases.insert(position, our_class)
|
|
model_object.__class__.__bases__ = tuple(bases)
|
|
|
|
def _register_hook(self, cr):
|
|
self._base_patch_models(cr)
|
|
for base in self.__class__.__bases__:
|
|
if not hasattr(super(base, self), '_register_hook'):
|
|
return
|
|
if super(base, self)._register_hook != self._register_hook:
|
|
return super(base, self)._register_hook.__func__(
|
|
super(base, self), cr)
|