Commit b6b517ee authored by Xiaowu Zhang's avatar Xiaowu Zhang

portal_type_class: possible to overwrite methods or properties in mixin

Before this change, class hierarchy is like this when using mixin:
```
class MyClass(BaseClass, Mixin1....)
```
which is usually ok when classes don't override each other's

But if we want to overwrite BaseClass's method by using mixin to do more thing,

For example:
```
class BaseClass(object):
  def test(self):
    print 'base test'

class Mixin1(object):
  def test(self):
    super(Mixin,self).test()
    print 'mixin'
```
I want to display 'mixin base test' when call test, but it doesn't work

since priority of how methods are resolved is from left

to right: BaseClass----->Mixin1, it only display 'base test'

So the correct way to use mixin should be in reverse order:
```
class MyClass(Mixin1, BaseClass)
```

/reviewed-on nexedi/erp5!935
parent 0d996b48
...@@ -285,7 +285,7 @@ def generatePortalTypeClass(site, portal_type_name): ...@@ -285,7 +285,7 @@ def generatePortalTypeClass(site, portal_type_name):
mixin_class_list.append(mixin_class) mixin_class_list.append(mixin_class)
base_class_list = [klass] + accessor_holder_list + mixin_class_list + [ base_class_list = mixin_class_list + [klass] + accessor_holder_list + [
# _getAcquireLocalRoles is accessed by security machinery, so it needs to # _getAcquireLocalRoles is accessed by security machinery, so it needs to
# be fast: make it a ConstantGetter while we have access to portal_type # be fast: make it a ConstantGetter while we have access to portal_type
# configuration. # configuration.
......
...@@ -2559,15 +2559,18 @@ class TestZodbMixinComponent(TestZodbInterfaceComponent): ...@@ -2559,15 +2559,18 @@ class TestZodbMixinComponent(TestZodbInterfaceComponent):
""" """
Return 42 Return 42
""" """
def getTitle(self, **kw):
return "Test Mixin"
''' % class_name ''' % class_name
def testAssignToPortalTypeClass(self): def testAssignToPortalTypeClass(self):
""" """
Create a new Document Component inheriting from Person Document and try to Create a new Document Component inheriting from Person Document and try to
assign it to Person Portal Type, then create a new Person and check assign it to Person Portal Type, in this Component, define getTitle method,
whether it has been successfully added to its Portal Type class bases and then create a new Person and check whether it has been successfully added
that the newly-defined function on ZODB Component can be called as well as to its Portal Type class bases and that the newly-defined function
methods from Person Document on ZODB Component can be called as well as methods from Person Document,also
check getTitle method overwrite the original one
""" """
import erp5.portal_type import erp5.portal_type
person_type = self.portal.portal_types.Person person_type = self.portal.portal_types.Person
...@@ -2588,6 +2591,9 @@ class TestZodbMixinComponent(TestZodbInterfaceComponent): ...@@ -2588,6 +2591,9 @@ class TestZodbMixinComponent(TestZodbInterfaceComponent):
person_type_class_mro_list = person_type_class.__mro__ person_type_class_mro_list = person_type_class.__mro__
self.assertFalse(TestPortalTypeMixin in person_type_class_mro_list) self.assertFalse(TestPortalTypeMixin in person_type_class_mro_list)
person_original_mixin_type_list = list(person_type.getTypeMixinList()) person_original_mixin_type_list = list(person_type.getTypeMixinList())
person_module = self.portal.person_module
person = person_module.newContent(id='Mixin', portal_type='Person')
original_title = person.getTitle()
try: try:
person_type.setTypeMixinList(person_original_mixin_type_list + person_type.setTypeMixinList(person_original_mixin_type_list +
['TestPortalTypeMixin']) ['TestPortalTypeMixin'])
...@@ -2598,6 +2604,8 @@ class TestZodbMixinComponent(TestZodbInterfaceComponent): ...@@ -2598,6 +2604,8 @@ class TestZodbMixinComponent(TestZodbInterfaceComponent):
person_type_class_mro_list = person_type_class.__mro__ person_type_class_mro_list = person_type_class.__mro__
from erp5.component.mixin.TestPortalTypeMixin import TestPortalTypeMixin from erp5.component.mixin.TestPortalTypeMixin import TestPortalTypeMixin
self.assertTrue(TestPortalTypeMixin in person_type_class_mro_list) self.assertTrue(TestPortalTypeMixin in person_type_class_mro_list)
self.assertEqual('Test Mixin', person.getTitle())
self.assertNotEqual(original_title, person.getTitle())
finally: finally:
person_type.setTypeMixinList(person_original_mixin_type_list) person_type.setTypeMixinList(person_original_mixin_type_list)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment