python-future/tests/test_future/test_magicsuper.py

136 lines
4.3 KiB
Python

"""
Tests for the super() function.
Based on Ryan Kelly's magicsuper.tests
"""
from __future__ import absolute_import, division, print_function, unicode_literals
import future.builtins.newsuper
from future.builtins import super
from future.tests.base import unittest
from future import utils
class TestMagicSuper(unittest.TestCase):
def test_basic_diamond(self):
class Base(object):
def calc(self,value):
return 2 * value
class Sub1(Base):
def calc(self,value):
return 7 + super().calc(value)
class Sub2(Base):
def calc(self,value):
return super().calc(value) - 1
class Diamond(Sub1,Sub2):
def calc(self,value):
return 3 * super().calc(value)
b = Base()
s1 = Sub1()
s2 = Sub2()
d = Diamond()
for x in range(10):
self.assertEqual(b.calc(x),2*x)
self.assertEqual(s1.calc(x),7+(2*x))
self.assertEqual(s2.calc(x),(2*x)-1)
self.assertEqual(d.calc(x),3*(7+((2*x)-1)))
def test_with_unrelated_methods(self):
class Base(object):
def hello(self):
return "world"
class Sub(Base):
def hello(self):
return "hello " + super().hello()
def other(self):
pass
class SubSub(Sub):
def other(self):
return super().other()
ss = SubSub()
self.assertEqual(ss.hello(),"hello world")
@unittest.skipIf(utils.PY3, "this test isn't relevant on Py3")
def test_fails_for_oldstyle_class(self):
class OldStyle:
def testme(self):
return super().testme()
o = OldStyle()
self.assertRaises(RuntimeError,o.testme)
def test_fails_for_raw_functions(self):
def not_a_method():
super().not_a_method()
self.assertRaises(RuntimeError,not_a_method)
def not_a_method(self):
super().not_a_method()
if utils.PY2:
self.assertRaises(RuntimeError,not_a_method,self)
else:
self.assertRaises(AttributeError,not_a_method,self)
def assertSuperEquals(self,sobj1,sobj2):
assert sobj1.__self__ is sobj2.__self__
assert sobj1.__self_class__ is sobj2.__self_class__
assert sobj1.__thisclass__ is sobj2.__thisclass__
def test_call_with_args_does_nothing(self):
if utils.PY2:
from __builtin__ import super as builtin_super
else:
from builtins import super as builtin_super
class Base(object):
def calc(self,value):
return 2 * value
class Sub1(Base):
def calc(self,value):
return 7 + super().calc(value)
class Sub2(Base):
def calc(self,value):
return super().calc(value) - 1
class Diamond(Sub1,Sub2):
def calc(self,value):
return 3 * super().calc(value)
for cls in (Base,Sub1,Sub2,Diamond,):
obj = cls()
self.assertSuperEquals(builtin_super(cls), super(cls))
self.assertSuperEquals(builtin_super(cls,obj), super(cls,obj))
@unittest.skipIf(utils.PY3, "this test isn't relevant for Py3's super()")
def test_superm(self):
class Base(object):
def getit(self):
return 2
class Sub(Base):
def getit(self):
return 10 * future.builtins.newsuper.superm()
s = Sub()
self.assertEqual(s.getit(),20)
def test_use_inside_dunder_new(self):
class Terminal(str):
def __new__(cls, value, token_type):
self = super().__new__(cls, value)
self.token_type = token_type
return self
DOT = Terminal(".", "dit")
self.assertTrue(isinstance(DOT, str))
self.assertTrue(isinstance(DOT, Terminal))
def test_use_inside_classmethod(self):
class Base(object):
@classmethod
def getit(cls):
return 42
class Singleton(Base):
@classmethod
def getit(cls):
print(super())
return super().getit() + 1
self.assertEqual(Singleton.getit(), 43)
if __name__ == '__main__':
unittest.main()