diff options
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/test/output/test_class | 101 | ||||
-rw-r--r-- | Lib/test/test_class.py | 783 |
2 files changed, 497 insertions, 387 deletions
diff --git a/Lib/test/output/test_class b/Lib/test/output/test_class deleted file mode 100644 index 93827f1..0000000 --- a/Lib/test/output/test_class +++ /dev/null @@ -1,101 +0,0 @@ -test_class -__init__: () -__coerce__: (1,) -__add__: (1,) -__coerce__: (1,) -__radd__: (1,) -__coerce__: (1,) -__sub__: (1,) -__coerce__: (1,) -__rsub__: (1,) -__coerce__: (1,) -__mul__: (1,) -__coerce__: (1,) -__rmul__: (1,) -__coerce__: (1,) -__div__: (1,) -__coerce__: (1,) -__rdiv__: (1,) -__coerce__: (1,) -__mod__: (1,) -__coerce__: (1,) -__rmod__: (1,) -__coerce__: (1,) -__divmod__: (1,) -__coerce__: (1,) -__rdivmod__: (1,) -__coerce__: (1,) -__pow__: (1,) -__coerce__: (1,) -__rpow__: (1,) -__coerce__: (1,) -__rshift__: (1,) -__coerce__: (1,) -__rrshift__: (1,) -__coerce__: (1,) -__lshift__: (1,) -__coerce__: (1,) -__rlshift__: (1,) -__coerce__: (1,) -__and__: (1,) -__coerce__: (1,) -__rand__: (1,) -__coerce__: (1,) -__or__: (1,) -__coerce__: (1,) -__ror__: (1,) -__coerce__: (1,) -__xor__: (1,) -__coerce__: (1,) -__rxor__: (1,) -__contains__: (1,) -__getitem__: (1,) -__setitem__: (1, 1) -__delitem__: (1,) -__getslice__: (0, 42) -__setslice__: (0, 42, 'The Answer') -__delslice__: (0, 42) -__getitem__: (slice(2, 1024, 10),) -__setitem__: (slice(2, 1024, 10), 'A lot') -__delitem__: (slice(2, 1024, 10),) -__getitem__: ((slice(None, 42, None), Ellipsis, slice(None, 24, None), 24, 100),) -__setitem__: ((slice(None, 42, None), Ellipsis, slice(None, 24, None), 24, 100), 'Strange') -__delitem__: ((slice(None, 42, None), Ellipsis, slice(None, 24, None), 24, 100),) -__getitem__: (slice(0, 42, None),) -__setitem__: (slice(0, 42, None), 'The Answer') -__delitem__: (slice(0, 42, None),) -__neg__: () -__pos__: () -__abs__: () -__int__: () -__long__: () -__float__: () -__oct__: () -__hex__: () -__hash__: () -__repr__: () -__str__: () -__coerce__: (1,) -__cmp__: (1,) -__coerce__: (1,) -__cmp__: (1,) -__coerce__: (1,) -__cmp__: (1,) -__coerce__: (1,) -__cmp__: (1,) -__coerce__: (1,) -__cmp__: (1,) -__coerce__: (1,) -__cmp__: (1,) -__coerce__: (1,) -__cmp__: (1,) -__coerce__: (1,) -__cmp__: (1,) -__coerce__: (1,) -__cmp__: (1,) -__coerce__: (1,) -__cmp__: (1,) -__del__: () -__getattr__: ('spam',) -__setattr__: ('eggs', 'spam, spam, spam and ham') -__delattr__: ('cardinal',) diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py index 26b8e7a..9cf3331 100644 --- a/Lib/test/test_class.py +++ b/Lib/test/test_class.py @@ -1,6 +1,9 @@ "Test the functionality of Python classes implementing operators." -from test.test_support import TestFailed +import unittest +import sys + +from test import test_support testmeths = [ @@ -64,55 +67,62 @@ testmeths = [ # "setattr", # "delattr", +callLst = [] +def trackCall(f): + def track(*args, **kwargs): + callLst.append((f.__name__, args)) + return f(*args, **kwargs) + return track + class AllTests: + trackCall = trackCall + + @trackCall def __coerce__(self, *args): - print "__coerce__:", args return (self,) + args + @trackCall def __hash__(self, *args): - print "__hash__:", args return hash(id(self)) + @trackCall def __str__(self, *args): - print "__str__:", args return "AllTests" + @trackCall def __repr__(self, *args): - print "__repr__:", args return "AllTests" + @trackCall def __int__(self, *args): - print "__int__:", args return 1 + @trackCall def __float__(self, *args): - print "__float__:", args return 1.0 + @trackCall def __long__(self, *args): - print "__long__:", args return 1L + @trackCall def __oct__(self, *args): - print "__oct__:", args return '01' + @trackCall def __hex__(self, *args): - print "__hex__:", args return '0x1' + @trackCall def __cmp__(self, *args): - print "__cmp__:", args return 0 - def __del__(self, *args): - print "__del__:", args - -# Synthesize AllTests methods from the names in testmeths. +# Synthesize all the other AllTests methods from the names in testmeths. method_template = """\ +@trackCall def __%(method)s__(self, *args): - print "__%(method)s__:", args + pass """ for method in testmeths: @@ -120,293 +130,494 @@ for method in testmeths: del method, method_template -# this also tests __init__ of course. -testme = AllTests() - -# Binary operations - -testme + 1 -1 + testme - -testme - 1 -1 - testme - -testme * 1 -1 * testme - -if 1/2 == 0: - testme / 1 - 1 / testme -else: - # True division is in effect, so "/" doesn't map to __div__ etc; but - # the canned expected-output file requires that __div__ etc get called. - testme.__coerce__(1) - testme.__div__(1) - testme.__coerce__(1) - testme.__rdiv__(1) - -testme % 1 -1 % testme - -divmod(testme,1) -divmod(1, testme) - -testme ** 1 -1 ** testme - -testme >> 1 -1 >> testme - -testme << 1 -1 << testme - -testme & 1 -1 & testme - -testme | 1 -1 | testme - -testme ^ 1 -1 ^ testme - - -# List/dict operations - -class Empty: pass - -try: - 1 in Empty() - print 'failed, should have raised TypeError' -except TypeError: - pass - -1 in testme - -testme[1] -testme[1] = 1 -del testme[1] - -testme[:42] -testme[:42] = "The Answer" -del testme[:42] - -testme[2:1024:10] -testme[2:1024:10] = "A lot" -del testme[2:1024:10] - -testme[:42, ..., :24:, 24, 100] -testme[:42, ..., :24:, 24, 100] = "Strange" -del testme[:42, ..., :24:, 24, 100] - - -# Now remove the slice hooks to see if converting normal slices to slice -# object works. +class ClassTests(unittest.TestCase): + def setUp(self): + callLst[:] = [] -del AllTests.__getslice__ -del AllTests.__setslice__ -del AllTests.__delslice__ + def assertCallStack(self, expected_calls): + actualCallList = callLst[:] # need to copy because the comparison below will add + # additional calls to callLst + if expected_calls != actualCallList: + self.fail("Expected call list:\n %s\ndoes not match actual call list\n %s" % + (expected_calls, actualCallList)) -import sys -if sys.platform[:4] != 'java': - testme[:42] - testme[:42] = "The Answer" - del testme[:42] -else: - # This works under Jython, but the actual slice values are - # different. - print "__getitem__: (slice(0, 42, None),)" - print "__setitem__: (slice(0, 42, None), 'The Answer')" - print "__delitem__: (slice(0, 42, None),)" + def testInit(self): + foo = AllTests() + self.assertCallStack([("__init__", (foo,))]) -# Unary operations + def testBinaryOps(self): + testme = AllTests() + # Binary operations --testme -+testme -abs(testme) -int(testme) -long(testme) -float(testme) -oct(testme) -hex(testme) - -# And the rest... - -hash(testme) -repr(testme) -str(testme) - -testme == 1 -testme < 1 -testme > 1 -testme <> 1 -testme != 1 -1 == testme -1 < testme -1 > testme -1 <> testme -1 != testme - -# This test has to be last (duh.) - -del testme -if sys.platform[:4] == 'java': - import java - java.lang.System.gc() - -# Interfering tests - -class ExtraTests: - def __getattr__(self, *args): - print "__getattr__:", args - return "SomeVal" - - def __setattr__(self, *args): - print "__setattr__:", args - - def __delattr__(self, *args): - print "__delattr__:", args - -testme = ExtraTests() -testme.spam -testme.eggs = "spam, spam, spam and ham" -del testme.cardinal - - -# return values of some method are type-checked -class BadTypeClass: - def __int__(self): - return None - __float__ = __int__ - __long__ = __int__ - __str__ = __int__ - __repr__ = __int__ - __oct__ = __int__ - __hex__ = __int__ - -def check_exc(stmt, exception): - """Raise TestFailed if executing 'stmt' does not raise 'exception' - """ - try: - exec stmt - except exception: - pass - else: - raise TestFailed, "%s should raise %s" % (stmt, exception) - -check_exc("int(BadTypeClass())", TypeError) -check_exc("float(BadTypeClass())", TypeError) -check_exc("long(BadTypeClass())", TypeError) -check_exc("str(BadTypeClass())", TypeError) -check_exc("repr(BadTypeClass())", TypeError) -check_exc("oct(BadTypeClass())", TypeError) -check_exc("hex(BadTypeClass())", TypeError) - -# mixing up ints and longs is okay -class IntLongMixClass: - def __int__(self): - return 0L - - def __long__(self): - return 0 + callLst[:] = [] + testme + 1 + self.assertCallStack([("__coerce__", (testme, 1)), ("__add__", (testme, 1))]) -try: - int(IntLongMixClass()) -except TypeError: - raise TestFailed, "TypeError should not be raised" + callLst[:] = [] + 1 + testme + self.assertCallStack([("__coerce__", (testme, 1)), ("__radd__", (testme, 1))]) -try: - long(IntLongMixClass()) -except TypeError: - raise TestFailed, "TypeError should not be raised" + callLst[:] = [] + testme - 1 + self.assertCallStack([("__coerce__", (testme, 1)), ("__sub__", (testme, 1))]) + callLst[:] = [] + 1 - testme + self.assertCallStack([("__coerce__", (testme, 1)), ("__rsub__", (testme, 1))]) -# Test correct errors from hash() on objects with comparisons but no __hash__ + callLst[:] = [] + testme * 1 + self.assertCallStack([("__coerce__", (testme, 1)), ("__mul__", (testme, 1))]) -class C0: - pass + callLst[:] = [] + 1 * testme + self.assertCallStack([("__coerce__", (testme, 1)), ("__rmul__", (testme, 1))]) -hash(C0()) # This should work; the next two should raise TypeError + if 1/2 == 0: + callLst[:] = [] + testme / 1 + self.assertCallStack([("__coerce__", (testme, 1)), ("__div__", (testme, 1))]) -class C1: - def __cmp__(self, other): return 0 -check_exc("hash(C1())", TypeError) + callLst[:] = [] + 1 / testme + self.assertCallStack([("__coerce__", (testme, 1)), ("__rdiv__", (testme, 1))]) -class C2: - def __eq__(self, other): return 1 + callLst[:] = [] + testme % 1 + self.assertCallStack([("__coerce__", (testme, 1)), ("__mod__", (testme, 1))]) -check_exc("hash(C2())", TypeError) + callLst[:] = [] + 1 % testme + self.assertCallStack([("__coerce__", (testme, 1)), ("__rmod__", (testme, 1))]) -# Test for SF bug 532646 -class A: - pass -A.__call__ = A() -a = A() -try: - a() # This should not segfault -except RuntimeError: - pass -else: - raise TestFailed, "how could this not have overflowed the stack?" + callLst[:] = [] + divmod(testme,1) + self.assertCallStack([("__coerce__", (testme, 1)), ("__divmod__", (testme, 1))]) + callLst[:] = [] + divmod(1, testme) + self.assertCallStack([("__coerce__", (testme, 1)), ("__rdivmod__", (testme, 1))]) -# Tests for exceptions raised in instance_getattr2(). + callLst[:] = [] + testme ** 1 + self.assertCallStack([("__coerce__", (testme, 1)), ("__pow__", (testme, 1))]) -def booh(self): - raise AttributeError, "booh" - -class A: - a = property(booh) -try: - A().a # Raised AttributeError: A instance has no attribute 'a' -except AttributeError, x: - if str(x) != "booh": - print "attribute error for A().a got masked:", str(x) - -class E: - __eq__ = property(booh) -E() == E() # In debug mode, caused a C-level assert() to fail - -class I: - __init__ = property(booh) -try: - I() # In debug mode, printed XXX undetected error and raises AttributeError -except AttributeError, x: - pass -else: - print "attribute error for I.__init__ got masked" - - -# Test comparison and hash of methods -class A: - def __init__(self, x): - self.x = x - def f(self): - pass - def g(self): - pass - def __eq__(self, other): - return self.x == other.x - def __hash__(self): - return self.x -class B(A): - pass + callLst[:] = [] + 1 ** testme + self.assertCallStack([("__coerce__", (testme, 1)), ("__rpow__", (testme, 1))]) -a1 = A(1) -a2 = A(2) -assert a1.f == a1.f -assert a1.f != a2.f -assert a1.f != a1.g -assert a1.f == A(1).f -assert hash(a1.f) == hash(a1.f) -assert hash(a1.f) == hash(A(1).f) - -assert A.f != a1.f -assert A.f != A.g -assert B.f == A.f -assert hash(B.f) == hash(A.f) - -# the following triggers a SystemError in 2.4 -a = A(hash(A.f.im_func)^(-1)) -hash(a.f) + callLst[:] = [] + testme >> 1 + self.assertCallStack([("__coerce__", (testme, 1)), ("__rshift__", (testme, 1))]) + + callLst[:] = [] + 1 >> testme + self.assertCallStack([("__coerce__", (testme, 1)), ("__rrshift__", (testme, 1))]) + + callLst[:] = [] + testme << 1 + self.assertCallStack([("__coerce__", (testme, 1)), ("__lshift__", (testme, 1))]) + + callLst[:] = [] + 1 << testme + self.assertCallStack([("__coerce__", (testme, 1)), ("__rlshift__", (testme, 1))]) + + callLst[:] = [] + testme & 1 + self.assertCallStack([("__coerce__", (testme, 1)), ("__and__", (testme, 1))]) + + callLst[:] = [] + 1 & testme + self.assertCallStack([("__coerce__", (testme, 1)), ("__rand__", (testme, 1))]) + + callLst[:] = [] + testme | 1 + self.assertCallStack([("__coerce__", (testme, 1)), ("__or__", (testme, 1))]) + + callLst[:] = [] + 1 | testme + self.assertCallStack([("__coerce__", (testme, 1)), ("__ror__", (testme, 1))]) + + callLst[:] = [] + testme ^ 1 + self.assertCallStack([("__coerce__", (testme, 1)), ("__xor__", (testme, 1))]) + + callLst[:] = [] + 1 ^ testme + self.assertCallStack([("__coerce__", (testme, 1)), ("__rxor__", (testme, 1))]) + + def testListAndDictOps(self): + testme = AllTests() + + # List/dict operations + + class Empty: pass + + try: + 1 in Empty() + self.fail('failed, should have raised TypeError') + except TypeError: + pass + + callLst[:] = [] + 1 in testme + self.assertCallStack([('__contains__', (testme, 1))]) + + callLst[:] = [] + testme[1] + self.assertCallStack([('__getitem__', (testme, 1))]) + + callLst[:] = [] + testme[1] = 1 + self.assertCallStack([('__setitem__', (testme, 1, 1))]) + + callLst[:] = [] + del testme[1] + self.assertCallStack([('__delitem__', (testme, 1))]) + + callLst[:] = [] + testme[:42] + self.assertCallStack([('__getslice__', (testme, 0, 42))]) + + callLst[:] = [] + testme[:42] = "The Answer" + self.assertCallStack([('__setslice__', (testme, 0, 42, "The Answer"))]) + + callLst[:] = [] + del testme[:42] + self.assertCallStack([('__delslice__', (testme, 0, 42))]) + + callLst[:] = [] + testme[2:1024:10] + self.assertCallStack([('__getitem__', (testme, slice(2, 1024, 10)))]) + + callLst[:] = [] + testme[2:1024:10] = "A lot" + self.assertCallStack([('__setitem__', (testme, slice(2, 1024, 10), + "A lot"))]) + callLst[:] = [] + del testme[2:1024:10] + self.assertCallStack([('__delitem__', (testme, slice(2, 1024, 10)))]) + + callLst[:] = [] + testme[:42, ..., :24:, 24, 100] + self.assertCallStack([('__getitem__', (testme, (slice(None, 42, None), + Ellipsis, + slice(None, 24, None), + 24, 100)))]) + callLst[:] = [] + testme[:42, ..., :24:, 24, 100] = "Strange" + self.assertCallStack([('__setitem__', (testme, (slice(None, 42, None), + Ellipsis, + slice(None, 24, None), + 24, 100), "Strange"))]) + callLst[:] = [] + del testme[:42, ..., :24:, 24, 100] + self.assertCallStack([('__delitem__', (testme, (slice(None, 42, None), + Ellipsis, + slice(None, 24, None), + 24, 100)))]) + + # Now remove the slice hooks to see if converting normal slices to + # slice object works. + + getslice = AllTests.__getslice__ + del AllTests.__getslice__ + setslice = AllTests.__setslice__ + del AllTests.__setslice__ + delslice = AllTests.__delslice__ + del AllTests.__delslice__ + + # XXX when using new-style classes the slice testme[:42] produces + # slice(None, 42, None) instead of slice(0, 42, None). py3k will have + # to change this test. + callLst[:] = [] + testme[:42] + self.assertCallStack([('__getitem__', (testme, slice(0, 42, None)))]) + + callLst[:] = [] + testme[:42] = "The Answer" + self.assertCallStack([('__setitem__', (testme, slice(0, 42, None), + "The Answer"))]) + callLst[:] = [] + del testme[:42] + self.assertCallStack([('__delitem__', (testme, slice(0, 42, None)))]) + + # Restore the slice methods, or the tests will fail with regrtest -R. + AllTests.__getslice__ = getslice + AllTests.__setslice__ = setslice + AllTests.__delslice__ = delslice + + + def testUnaryOps(self): + testme = AllTests() + + callLst[:] = [] + -testme + self.assertCallStack([('__neg__', (testme,))]) + callLst[:] = [] + +testme + self.assertCallStack([('__pos__', (testme,))]) + callLst[:] = [] + abs(testme) + self.assertCallStack([('__abs__', (testme,))]) + callLst[:] = [] + int(testme) + self.assertCallStack([('__int__', (testme,))]) + callLst[:] = [] + long(testme) + self.assertCallStack([('__long__', (testme,))]) + callLst[:] = [] + float(testme) + self.assertCallStack([('__float__', (testme,))]) + callLst[:] = [] + oct(testme) + self.assertCallStack([('__oct__', (testme,))]) + callLst[:] = [] + hex(testme) + self.assertCallStack([('__hex__', (testme,))]) + + + def testMisc(self): + testme = AllTests() + + callLst[:] = [] + hash(testme) + self.assertCallStack([('__hash__', (testme,))]) + + callLst[:] = [] + repr(testme) + self.assertCallStack([('__repr__', (testme,))]) + + callLst[:] = [] + str(testme) + self.assertCallStack([('__str__', (testme,))]) + + callLst[:] = [] + testme == 1 + self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))]) + + callLst[:] = [] + testme < 1 + self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))]) + + callLst[:] = [] + testme > 1 + self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))]) + + callLst[:] = [] + testme <> 1 # XXX kill this in py3k + self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))]) + + callLst[:] = [] + testme != 1 + self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))]) + + callLst[:] = [] + 1 == testme + self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))]) + + callLst[:] = [] + 1 < testme + self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))]) + + callLst[:] = [] + 1 > testme + self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))]) + + callLst[:] = [] + 1 <> testme + self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))]) + + callLst[:] = [] + 1 != testme + self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))]) + + + def testGetSetAndDel(self): + # Interfering tests + class ExtraTests(AllTests): + @trackCall + def __getattr__(self, *args): + return "SomeVal" + + @trackCall + def __setattr__(self, *args): + pass + + @trackCall + def __delattr__(self, *args): + pass + + testme = ExtraTests() + + callLst[:] = [] + testme.spam + self.assertCallStack([('__getattr__', (testme, "spam"))]) + + callLst[:] = [] + testme.eggs = "spam, spam, spam and ham" + self.assertCallStack([('__setattr__', (testme, "eggs", + "spam, spam, spam and ham"))]) + + callLst[:] = [] + del testme.cardinal + self.assertCallStack([('__delattr__', (testme, "cardinal"))]) + + def testDel(self): + x = [] + + class DelTest: + def __del__(self): + x.append("crab people, crab people") + testme = DelTest() + del testme + import gc + gc.collect() + self.assertEquals(["crab people, crab people"], x) + + def testBadTypeReturned(self): + # return values of some method are type-checked + class BadTypeClass: + def __int__(self): + return None + __float__ = __int__ + __long__ = __int__ + __str__ = __int__ + __repr__ = __int__ + __oct__ = __int__ + __hex__ = __int__ + + for f in [int, float, long, str, repr, oct, hex]: + self.assertRaises(TypeError, f, BadTypeClass()) + + def testMixIntsAndLongs(self): + # mixing up ints and longs is okay + class IntLongMixClass: + @trackCall + def __int__(self): + return 42L + + @trackCall + def __long__(self): + return 64 + + mixIntAndLong = IntLongMixClass() + + callLst[:] = [] + as_int = int(mixIntAndLong) + self.assertEquals(type(as_int), long) + self.assertEquals(as_int, 42L) + self.assertCallStack([('__int__', (mixIntAndLong,))]) + + callLst[:] = [] + as_long = long(mixIntAndLong) + self.assertEquals(type(as_long), int) + self.assertEquals(as_long, 64) + self.assertCallStack([('__long__', (mixIntAndLong,))]) + + def testHashStuff(self): + # Test correct errors from hash() on objects with comparisons but + # no __hash__ + + class C0: + pass + + hash(C0()) # This should work; the next two should raise TypeError + + class C1: + def __cmp__(self, other): return 0 + + self.assertRaises(TypeError, hash, C1()) + + class C2: + def __eq__(self, other): return 1 + + self.assertRaises(TypeError, hash, C2()) + + + def testSFBug532646(self): + # Test for SF bug 532646 + + class A: + pass + A.__call__ = A() + a = A() + + try: + a() # This should not segfault + except RuntimeError: + pass + else: + self.fail("Failed to raise RuntimeError") + + def testForExceptionsRaisedInInstanceGetattr2(self): + # Tests for exceptions raised in instance_getattr2(). + + def booh(self): + raise AttributeError("booh") + + class A: + a = property(booh) + try: + A().a # Raised AttributeError: A instance has no attribute 'a' + except AttributeError, x: + if str(x) != "booh": + self.fail("attribute error for A().a got masked: %s" % x) + + class E: + __eq__ = property(booh) + E() == E() # In debug mode, caused a C-level assert() to fail + + class I: + __init__ = property(booh) + try: + # In debug mode, printed XXX undetected error and + # raises AttributeError + I() + except AttributeError, x: + pass + else: + self.fail("attribute error for I.__init__ got masked") + + def testHashComparisonOfMethods(self): + # Test comparison and hash of methods + class A: + def __init__(self, x): + self.x = x + def f(self): + pass + def g(self): + pass + def __eq__(self, other): + return self.x == other.x + def __hash__(self): + return self.x + class B(A): + pass + + a1 = A(1) + a2 = A(2) + self.assertEquals(a1.f, a1.f) + self.assertNotEquals(a1.f, a2.f) + self.assertNotEquals(a1.f, a1.g) + self.assertEquals(a1.f, A(1).f) + self.assertEquals(hash(a1.f), hash(a1.f)) + self.assertEquals(hash(a1.f), hash(A(1).f)) + + self.assertNotEquals(A.f, a1.f) + self.assertNotEquals(A.f, A.g) + self.assertEquals(B.f, A.f) + self.assertEquals(hash(B.f), hash(A.f)) + + # the following triggers a SystemError in 2.4 + a = A(hash(A.f.im_func)^(-1)) + hash(a.f) + +def test_main(): + test_support.run_unittest(ClassTests) + +if __name__=='__main__': + test_main() |