Holger Brunn
9 years ago
3 changed files with 97 additions and 32 deletions
-
1mail_follower_custom_notification/models/__init__.py
-
92mail_follower_custom_notification/models/base_patch_models_mixin.py
-
36mail_follower_custom_notification/models/mail_thread.py
@ -0,0 +1,92 @@ |
|||
# -*- 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) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue