+++ /dev/null
-"Test the functionality of Python classes implementing operators."\r
-\r
-import unittest\r
-\r
-from test import test_support\r
-\r
-testmeths = [\r
-\r
-# Binary operations\r
- "add",\r
- "radd",\r
- "sub",\r
- "rsub",\r
- "mul",\r
- "rmul",\r
- "div",\r
- "rdiv",\r
- "mod",\r
- "rmod",\r
- "divmod",\r
- "rdivmod",\r
- "pow",\r
- "rpow",\r
- "rshift",\r
- "rrshift",\r
- "lshift",\r
- "rlshift",\r
- "and",\r
- "rand",\r
- "or",\r
- "ror",\r
- "xor",\r
- "rxor",\r
-\r
-# List/dict operations\r
- "contains",\r
- "getitem",\r
- "getslice",\r
- "setitem",\r
- "setslice",\r
- "delitem",\r
- "delslice",\r
-\r
-# Unary operations\r
- "neg",\r
- "pos",\r
- "abs",\r
-\r
-# generic operations\r
- "init",\r
- ]\r
-\r
-# These need to return something other than None\r
-# "coerce",\r
-# "hash",\r
-# "str",\r
-# "repr",\r
-# "int",\r
-# "long",\r
-# "float",\r
-# "oct",\r
-# "hex",\r
-\r
-# These are separate because they can influence the test of other methods.\r
-# "getattr",\r
-# "setattr",\r
-# "delattr",\r
-\r
-callLst = []\r
-def trackCall(f):\r
- def track(*args, **kwargs):\r
- callLst.append((f.__name__, args))\r
- return f(*args, **kwargs)\r
- return track\r
-\r
-class AllTests:\r
- trackCall = trackCall\r
-\r
- @trackCall\r
- def __coerce__(self, *args):\r
- return (self,) + args\r
-\r
- @trackCall\r
- def __hash__(self, *args):\r
- return hash(id(self))\r
-\r
- @trackCall\r
- def __str__(self, *args):\r
- return "AllTests"\r
-\r
- @trackCall\r
- def __repr__(self, *args):\r
- return "AllTests"\r
-\r
- @trackCall\r
- def __int__(self, *args):\r
- return 1\r
-\r
- @trackCall\r
- def __float__(self, *args):\r
- return 1.0\r
-\r
- @trackCall\r
- def __long__(self, *args):\r
- return 1L\r
-\r
- @trackCall\r
- def __oct__(self, *args):\r
- return '01'\r
-\r
- @trackCall\r
- def __hex__(self, *args):\r
- return '0x1'\r
-\r
- @trackCall\r
- def __cmp__(self, *args):\r
- return 0\r
-\r
-# Synthesize all the other AllTests methods from the names in testmeths.\r
-\r
-method_template = """\\r
-@trackCall\r
-def __%(method)s__(self, *args):\r
- pass\r
-"""\r
-\r
-for method in testmeths:\r
- exec method_template % locals() in AllTests.__dict__\r
-\r
-del method, method_template\r
-\r
-class ClassTests(unittest.TestCase):\r
- def setUp(self):\r
- callLst[:] = []\r
-\r
- def assertCallStack(self, expected_calls):\r
- actualCallList = callLst[:] # need to copy because the comparison below will add\r
- # additional calls to callLst\r
- if expected_calls != actualCallList:\r
- self.fail("Expected call list:\n %s\ndoes not match actual call list\n %s" %\r
- (expected_calls, actualCallList))\r
-\r
- def testInit(self):\r
- foo = AllTests()\r
- self.assertCallStack([("__init__", (foo,))])\r
-\r
- def testBinaryOps(self):\r
- testme = AllTests()\r
- # Binary operations\r
-\r
- callLst[:] = []\r
- testme + 1\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__add__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- 1 + testme\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__radd__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- testme - 1\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__sub__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- 1 - testme\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__rsub__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- testme * 1\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__mul__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- 1 * testme\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__rmul__", (testme, 1))])\r
-\r
- if 1/2 == 0:\r
- callLst[:] = []\r
- testme / 1\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__div__", (testme, 1))])\r
-\r
-\r
- callLst[:] = []\r
- 1 / testme\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__rdiv__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- testme % 1\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__mod__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- 1 % testme\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__rmod__", (testme, 1))])\r
-\r
-\r
- callLst[:] = []\r
- divmod(testme,1)\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__divmod__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- divmod(1, testme)\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__rdivmod__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- testme ** 1\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__pow__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- 1 ** testme\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__rpow__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- testme >> 1\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__rshift__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- 1 >> testme\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__rrshift__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- testme << 1\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__lshift__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- 1 << testme\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__rlshift__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- testme & 1\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__and__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- 1 & testme\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__rand__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- testme | 1\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__or__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- 1 | testme\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__ror__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- testme ^ 1\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__xor__", (testme, 1))])\r
-\r
- callLst[:] = []\r
- 1 ^ testme\r
- self.assertCallStack([("__coerce__", (testme, 1)), ("__rxor__", (testme, 1))])\r
-\r
- def testListAndDictOps(self):\r
- testme = AllTests()\r
-\r
- # List/dict operations\r
-\r
- class Empty: pass\r
-\r
- try:\r
- 1 in Empty()\r
- self.fail('failed, should have raised TypeError')\r
- except TypeError:\r
- pass\r
-\r
- callLst[:] = []\r
- 1 in testme\r
- self.assertCallStack([('__contains__', (testme, 1))])\r
-\r
- callLst[:] = []\r
- testme[1]\r
- self.assertCallStack([('__getitem__', (testme, 1))])\r
-\r
- callLst[:] = []\r
- testme[1] = 1\r
- self.assertCallStack([('__setitem__', (testme, 1, 1))])\r
-\r
- callLst[:] = []\r
- del testme[1]\r
- self.assertCallStack([('__delitem__', (testme, 1))])\r
-\r
- callLst[:] = []\r
- testme[:42]\r
- self.assertCallStack([('__getslice__', (testme, 0, 42))])\r
-\r
- callLst[:] = []\r
- testme[:42] = "The Answer"\r
- self.assertCallStack([('__setslice__', (testme, 0, 42, "The Answer"))])\r
-\r
- callLst[:] = []\r
- del testme[:42]\r
- self.assertCallStack([('__delslice__', (testme, 0, 42))])\r
-\r
- callLst[:] = []\r
- testme[2:1024:10]\r
- self.assertCallStack([('__getitem__', (testme, slice(2, 1024, 10)))])\r
-\r
- callLst[:] = []\r
- testme[2:1024:10] = "A lot"\r
- self.assertCallStack([('__setitem__', (testme, slice(2, 1024, 10),\r
- "A lot"))])\r
- callLst[:] = []\r
- del testme[2:1024:10]\r
- self.assertCallStack([('__delitem__', (testme, slice(2, 1024, 10)))])\r
-\r
- callLst[:] = []\r
- testme[:42, ..., :24:, 24, 100]\r
- self.assertCallStack([('__getitem__', (testme, (slice(None, 42, None),\r
- Ellipsis,\r
- slice(None, 24, None),\r
- 24, 100)))])\r
- callLst[:] = []\r
- testme[:42, ..., :24:, 24, 100] = "Strange"\r
- self.assertCallStack([('__setitem__', (testme, (slice(None, 42, None),\r
- Ellipsis,\r
- slice(None, 24, None),\r
- 24, 100), "Strange"))])\r
- callLst[:] = []\r
- del testme[:42, ..., :24:, 24, 100]\r
- self.assertCallStack([('__delitem__', (testme, (slice(None, 42, None),\r
- Ellipsis,\r
- slice(None, 24, None),\r
- 24, 100)))])\r
-\r
- # Now remove the slice hooks to see if converting normal slices to\r
- # slice object works.\r
-\r
- getslice = AllTests.__getslice__\r
- del AllTests.__getslice__\r
- setslice = AllTests.__setslice__\r
- del AllTests.__setslice__\r
- delslice = AllTests.__delslice__\r
- del AllTests.__delslice__\r
-\r
- # XXX when using new-style classes the slice testme[:42] produces\r
- # slice(None, 42, None) instead of slice(0, 42, None). py3k will have\r
- # to change this test.\r
- callLst[:] = []\r
- testme[:42]\r
- self.assertCallStack([('__getitem__', (testme, slice(0, 42, None)))])\r
-\r
- callLst[:] = []\r
- testme[:42] = "The Answer"\r
- self.assertCallStack([('__setitem__', (testme, slice(0, 42, None),\r
- "The Answer"))])\r
- callLst[:] = []\r
- del testme[:42]\r
- self.assertCallStack([('__delitem__', (testme, slice(0, 42, None)))])\r
-\r
- # Restore the slice methods, or the tests will fail with regrtest -R.\r
- AllTests.__getslice__ = getslice\r
- AllTests.__setslice__ = setslice\r
- AllTests.__delslice__ = delslice\r
-\r
-\r
- def testUnaryOps(self):\r
- testme = AllTests()\r
-\r
- callLst[:] = []\r
- -testme\r
- self.assertCallStack([('__neg__', (testme,))])\r
- callLst[:] = []\r
- +testme\r
- self.assertCallStack([('__pos__', (testme,))])\r
- callLst[:] = []\r
- abs(testme)\r
- self.assertCallStack([('__abs__', (testme,))])\r
- callLst[:] = []\r
- int(testme)\r
- self.assertCallStack([('__int__', (testme,))])\r
- callLst[:] = []\r
- long(testme)\r
- self.assertCallStack([('__long__', (testme,))])\r
- callLst[:] = []\r
- float(testme)\r
- self.assertCallStack([('__float__', (testme,))])\r
- callLst[:] = []\r
- oct(testme)\r
- self.assertCallStack([('__oct__', (testme,))])\r
- callLst[:] = []\r
- hex(testme)\r
- self.assertCallStack([('__hex__', (testme,))])\r
-\r
-\r
- def testMisc(self):\r
- testme = AllTests()\r
-\r
- callLst[:] = []\r
- hash(testme)\r
- self.assertCallStack([('__hash__', (testme,))])\r
-\r
- callLst[:] = []\r
- repr(testme)\r
- self.assertCallStack([('__repr__', (testme,))])\r
-\r
- callLst[:] = []\r
- str(testme)\r
- self.assertCallStack([('__str__', (testme,))])\r
-\r
- callLst[:] = []\r
- testme == 1\r
- self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])\r
-\r
- callLst[:] = []\r
- testme < 1\r
- self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])\r
-\r
- callLst[:] = []\r
- testme > 1\r
- self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])\r
-\r
- callLst[:] = []\r
- eval('testme <> 1') # XXX kill this in py3k\r
- self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])\r
-\r
- callLst[:] = []\r
- testme != 1\r
- self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])\r
-\r
- callLst[:] = []\r
- 1 == testme\r
- self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])\r
-\r
- callLst[:] = []\r
- 1 < testme\r
- self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])\r
-\r
- callLst[:] = []\r
- 1 > testme\r
- self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])\r
-\r
- callLst[:] = []\r
- eval('1 <> testme')\r
- self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])\r
-\r
- callLst[:] = []\r
- 1 != testme\r
- self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])\r
-\r
-\r
- def testGetSetAndDel(self):\r
- # Interfering tests\r
- class ExtraTests(AllTests):\r
- @trackCall\r
- def __getattr__(self, *args):\r
- return "SomeVal"\r
-\r
- @trackCall\r
- def __setattr__(self, *args):\r
- pass\r
-\r
- @trackCall\r
- def __delattr__(self, *args):\r
- pass\r
-\r
- testme = ExtraTests()\r
-\r
- callLst[:] = []\r
- testme.spam\r
- self.assertCallStack([('__getattr__', (testme, "spam"))])\r
-\r
- callLst[:] = []\r
- testme.eggs = "spam, spam, spam and ham"\r
- self.assertCallStack([('__setattr__', (testme, "eggs",\r
- "spam, spam, spam and ham"))])\r
-\r
- callLst[:] = []\r
- del testme.cardinal\r
- self.assertCallStack([('__delattr__', (testme, "cardinal"))])\r
-\r
- def testDel(self):\r
- x = []\r
-\r
- class DelTest:\r
- def __del__(self):\r
- x.append("crab people, crab people")\r
- testme = DelTest()\r
- del testme\r
- import gc\r
- gc.collect()\r
- self.assertEqual(["crab people, crab people"], x)\r
-\r
- def testBadTypeReturned(self):\r
- # return values of some method are type-checked\r
- class BadTypeClass:\r
- def __int__(self):\r
- return None\r
- __float__ = __int__\r
- __long__ = __int__\r
- __str__ = __int__\r
- __repr__ = __int__\r
- __oct__ = __int__\r
- __hex__ = __int__\r
-\r
- for f in [int, float, long, str, repr, oct, hex]:\r
- self.assertRaises(TypeError, f, BadTypeClass())\r
-\r
- def testMixIntsAndLongs(self):\r
- # mixing up ints and longs is okay\r
- class IntLongMixClass:\r
- @trackCall\r
- def __int__(self):\r
- return 42L\r
-\r
- @trackCall\r
- def __long__(self):\r
- return 64\r
-\r
- mixIntAndLong = IntLongMixClass()\r
-\r
- callLst[:] = []\r
- as_int = int(mixIntAndLong)\r
- self.assertEqual(type(as_int), long)\r
- self.assertEqual(as_int, 42L)\r
- self.assertCallStack([('__int__', (mixIntAndLong,))])\r
-\r
- callLst[:] = []\r
- as_long = long(mixIntAndLong)\r
- self.assertEqual(type(as_long), long)\r
- self.assertEqual(as_long, 64)\r
- self.assertCallStack([('__long__', (mixIntAndLong,))])\r
-\r
- def testHashStuff(self):\r
- # Test correct errors from hash() on objects with comparisons but\r
- # no __hash__\r
-\r
- class C0:\r
- pass\r
-\r
- hash(C0()) # This should work; the next two should raise TypeError\r
-\r
- class C1:\r
- def __cmp__(self, other): return 0\r
-\r
- self.assertRaises(TypeError, hash, C1())\r
-\r
- class C2:\r
- def __eq__(self, other): return 1\r
-\r
- self.assertRaises(TypeError, hash, C2())\r
-\r
-\r
- def testSFBug532646(self):\r
- # Test for SF bug 532646\r
-\r
- class A:\r
- pass\r
- A.__call__ = A()\r
- a = A()\r
-\r
- try:\r
- a() # This should not segfault\r
- except RuntimeError:\r
- pass\r
- else:\r
- self.fail("Failed to raise RuntimeError")\r
-\r
- def testForExceptionsRaisedInInstanceGetattr2(self):\r
- # Tests for exceptions raised in instance_getattr2().\r
-\r
- def booh(self):\r
- raise AttributeError("booh")\r
-\r
- class A:\r
- a = property(booh)\r
- try:\r
- A().a # Raised AttributeError: A instance has no attribute 'a'\r
- except AttributeError, x:\r
- if str(x) != "booh":\r
- self.fail("attribute error for A().a got masked: %s" % x)\r
-\r
- class E:\r
- __eq__ = property(booh)\r
- E() == E() # In debug mode, caused a C-level assert() to fail\r
-\r
- class I:\r
- __init__ = property(booh)\r
- try:\r
- # In debug mode, printed XXX undetected error and\r
- # raises AttributeError\r
- I()\r
- except AttributeError, x:\r
- pass\r
- else:\r
- self.fail("attribute error for I.__init__ got masked")\r
-\r
- def testHashComparisonOfMethods(self):\r
- # Test comparison and hash of methods\r
- class A:\r
- def __init__(self, x):\r
- self.x = x\r
- def f(self):\r
- pass\r
- def g(self):\r
- pass\r
- def __eq__(self, other):\r
- return self.x == other.x\r
- def __hash__(self):\r
- return self.x\r
- class B(A):\r
- pass\r
-\r
- a1 = A(1)\r
- a2 = A(2)\r
- self.assertEqual(a1.f, a1.f)\r
- self.assertNotEqual(a1.f, a2.f)\r
- self.assertNotEqual(a1.f, a1.g)\r
- self.assertEqual(a1.f, A(1).f)\r
- self.assertEqual(hash(a1.f), hash(a1.f))\r
- self.assertEqual(hash(a1.f), hash(A(1).f))\r
-\r
- self.assertNotEqual(A.f, a1.f)\r
- self.assertNotEqual(A.f, A.g)\r
- self.assertEqual(B.f, A.f)\r
- self.assertEqual(hash(B.f), hash(A.f))\r
-\r
- # the following triggers a SystemError in 2.4\r
- a = A(hash(A.f.im_func)^(-1))\r
- hash(a.f)\r
-\r
-def test_main():\r
- with test_support.check_py3k_warnings(\r
- (".+__(get|set|del)slice__ has been removed", DeprecationWarning),\r
- ("classic int division", DeprecationWarning),\r
- ("<> not supported", DeprecationWarning)):\r
- test_support.run_unittest(ClassTests)\r
-\r
-if __name__=='__main__':\r
- test_main()\r