Created
January 31, 2012 15:37
-
-
Save vestel/1711115 to your computer and use it in GitHub Desktop.
Inheritance and MRO
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import generators | |
class A(object): | |
""" Normal class """ | |
def su(self): | |
self.su_result = [] | |
self.su_result.append("A:Start") | |
mro = list(self.__class__.__mro__)[:-1] | |
mro.reverse() | |
for i in mro: | |
try: | |
i._su(self) | |
except Exception: | |
self.su_result.append(i._exception(self)) | |
break | |
self.su_result.append("A:End") | |
def _su(self): | |
pass | |
def td(self): | |
self.result = [] | |
self.result.append("A:Start") | |
mro = list(self.__class__.__mro__)[:-1] | |
for i in mro: | |
try: | |
i._td(self) | |
except Exception: | |
self.result.append(i._exception(self)) | |
self.result.append("A:End") | |
def _td(self): | |
pass | |
def _exception(self): | |
return "A:Exception" | |
class B(A): | |
""" Normal child class """ | |
def _su(self): | |
self.su_result.append("B:Start") | |
def _td(self): | |
self.result.append("B:End") | |
def _exception(self): | |
return "B:Exception" | |
class BA(A): | |
""" Normal child class """ | |
def _su(self): | |
self.su_result.append("B:Start") | |
def _td(self): | |
self.result.append("B:End") | |
class C(B): | |
""" Normal leaf class """ | |
def _su(self): | |
self.su_result.append("C:Inside") | |
def _td(self): | |
self.result.append("C") | |
def _exception(self): | |
return "C:Exception" | |
class NE(BA): | |
""" Normal leaf class """ | |
def _su(self): | |
raise Exception("SU") | |
def _td(self): | |
raise Exception("TD") | |
class D(A): | |
""" Defective child class """ | |
def _su(self): | |
raise Exception("SU") | |
def _td(self): | |
raise Exception("TD") | |
def _exception(self): | |
return "D:Exception" | |
class E(B): | |
""" Errorious leaf class """ | |
def _su(self): | |
raise Exception("SU") | |
def _td(self): | |
raise Exception("TD") | |
def _exception(self): | |
return "E:Exception" | |
class X(D): | |
""" Defective inheritant """ | |
def _su(self): | |
self.su_result.append("X:Inside") | |
def _td(self): | |
self.result.append("X") | |
def _exception(self): | |
return "X:Exception" | |
class Z(D): | |
""" Totally broken """ | |
def _su(self): | |
raise Exception("SU") | |
def _td(self): | |
raise Exception("TD") | |
def _exception(self): | |
return "Z:Exception" | |
import unittest | |
class TestEverything(unittest.TestCase): | |
def test_su_called(self): | |
a = A() | |
a.su() | |
self.assertEquals(a.su_result, ["A:Start","A:End"]) | |
def test_td_called(self): | |
a = A() | |
a.td() | |
self.assertEquals(a.result, ["A:Start","A:End"]) | |
def test_child_su_called(self): | |
b = B() | |
b.su() | |
self.assertEquals(b.su_result, ["A:Start","B:Start","A:End"]) | |
def test_child_td_called(self): | |
b = B() | |
b.td() | |
self.assertEquals(b.result, ["A:Start","B:End","A:End"]) | |
def test_exception_su_leaf(self): | |
e = E() | |
e.su() | |
self.assertEquals(e.su_result, ["A:Start","B:Start","E:Exception","A:End"]) | |
def test_exception_td_leaf(self): | |
e = E() | |
e.td() | |
self.assertEquals(e.result, ["A:Start","E:Exception","B:End","A:End"]) | |
def test_exception_su_defect(self): | |
d = D() | |
d.su() | |
self.assertEquals(d.su_result, ["A:Start","D:Exception","A:End"]) | |
def test_exception_td_defect(self): | |
d = D() | |
d.td() | |
self.assertEquals(d.result, ["A:Start","D:Exception","A:End"]) | |
def test_exception_su_passthro(self): | |
x = X() | |
x.su() | |
self.assertEquals(x.su_result, ["A:Start","D:Exception","A:End"]) | |
def test_exception_td_passthro(self): | |
x = X() | |
x.td() | |
self.assertEquals(x.result, ["A:Start","X","D:Exception","A:End"]) | |
def test_exception_su_total(self): | |
z = Z() | |
z.su() | |
self.assertEquals(z.su_result, ["A:Start","D:Exception","A:End"]) | |
def test_exception_td_total(self): | |
z = Z() | |
z.td() | |
self.assertEquals(z.result, ["A:Start","Z:Exception","D:Exception","A:End"]) | |
def test_grand_child_td_called(self): | |
c = C() | |
c.td() | |
self.assertEquals(c.result, ["A:Start","C","B:End","A:End"]) | |
def test_grand_child_su_called(self): | |
c = C() | |
c.su() | |
self.assertEquals(c.su_result, ["A:Start","B:Start", "C:Inside","A:End"]) | |
def test_grand_child_noex_su_called(self): | |
c = NE() | |
c.su() | |
self.assertEquals(c.su_result, ["A:Start","B:Start","A:Exception","A:End"]) | |
def test_grand_child_noex_td_called(self): | |
c = NE() | |
c.td() | |
self.assertEquals(c.result, ["A:Start","A:Exception","B:End","A:End"]) | |
if __name__ == '__main__': | |
import nose | |
nose.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment