mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 21:51:50 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			412 lines
		
	
	
	
		
			7.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			412 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",
 | |
|     "div",
 | |
|     "rdiv",
 | |
|     "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
 | |
| #    "coerce",
 | |
| #    "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 __coerce__(self, *args):
 | |
|         print "__coerce__:", args
 | |
|         return (self,) + args
 | |
| 
 | |
|     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 __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
 | |
| """
 | |
| 
 | |
| for method in testmeths:
 | |
|     exec method_template % locals() in AllTests.__dict__
 | |
| 
 | |
| 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.
 | |
| 
 | |
| 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
 | |
| 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
 | |
| 
 | |
| 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)
 | 
