cpython/Lib/test/test_class.py

417 lines
7.4 KiB
Python

"Test the functionality of Python classes implementing operators."
from test.test_support import TestFailed
testmeths = [
# Binary operations
"add",
"radd",
"sub",
"rsub",
"mul",
"rmul",
"truediv",
"rtruediv",
"mod",
"rmod",
"divmod",
"rdivmod",
"pow",
"rpow",
"rshift",
"rrshift",
"lshift",
"rlshift",
"and",
"rand",
"or",
"ror",
"xor",
"rxor",
# List/dict operations
"contains",
"getitem",
"getslice",
"setitem",
"setslice",
"delitem",
"delslice",
# Unary operations
"neg",
"pos",
"abs",
# generic operations
"init",
]
# These need to return something other than None
# "hash",
# "str",
# "repr",
# "int",
# "long",
# "float",
# "oct",
# "hex",
# These are separate because they can influence the test of other methods.
# "getattr",
# "setattr",
# "delattr",
class AllTests:
def __hash__(self, *args):
print "__hash__:", args
return hash(id(self))
def __str__(self, *args):
print "__str__:", args
return "AllTests"
def __repr__(self, *args):
print "__repr__:", args
return "AllTests"
def __int__(self, *args):
print "__int__:", args
return 1
def __float__(self, *args):
print "__float__:", args
return 1.0
def __long__(self, *args):
print "__long__:", args
return 1L
def __oct__(self, *args):
print "__oct__:", args
return '01'
def __hex__(self, *args):
print "__hex__:", args
return '0x1'
def __cmp__(self, *args):
print "__cmp__:", args
return 0
def __eq__(self, *args):
print "__eq__:", args
return True
def __ne__(self, *args):
print "__ne__:", args
return False
def __lt__(self, *args):
print "__lt__:", args
return False
def __le__(self, *args):
print "__le__:", args
return True
def __gt__(self, *args):
print "__gt__:", args
return False
def __ge__(self, *args):
print "__ge__:", args
return True
def __del__(self, *args):
print "__del__:", args
# Synthesize AllTests methods from the names in testmeths.
method_template = """\
def __%(method)s__(self, *args):
print "__%(method)s__:", args
"""
d = {}
for method in testmeths:
exec(method_template % locals(), d)
for k in d:
setattr(AllTests, k, d[k])
del d, k
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
testme / 1
1 / testme
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
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.
del AllTests.__getslice__
del AllTests.__setslice__
del AllTests.__delslice__
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),)"
# Unary 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
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
try:
int(IntLongMixClass())
except TypeError:
raise TestFailed, "TypeError should not be raised"
try:
long(IntLongMixClass())
except TypeError:
raise TestFailed, "TypeError should not be raised"
# 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
check_exc("hash(C1())", TypeError)
class C2:
def __eq__(self, other): return 1
check_exc("hash(C2())", TypeError)
# 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?"
# 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":
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
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)