]>
git.ipfire.org Git - thirdparty/Python/cpython.git/blob - Lib/test/test_class.py
4c1814142736e3a019d7206fd53dfbc18c46a8cd
1 "Test the functionality of Python classes implementing operators."
37 # List/dict operations
52 # These need to return something other than None
59 # These are separate because they can influence the test of other methods.
66 def track(*args
, **kwargs
):
67 callLst
.append((f
.__name
__, args
))
68 return f(*args
, **kwargs
)
73 def __hash__(self, *args):
77 def __str__(self, *args):
81 def __repr__(self, *args):
85 def __int__(self, *args):
89 def __index__(self, *args):
93 def __float__(self, *args):
97 def __eq__(self, *args):
101 def __ne__(self, *args):
105 def __lt__(self, *args):
109 def __le__(self, *args):
113 def __gt__(self, *args):
117 def __ge__(self, *args):
121 # Synthesize all the other AllTests methods from the names in testmeths.
123 method_template
= """\
125 def __%s__(self, *args):
130 exec(statictests
, globals(), d
)
131 for method
in testmeths
:
132 exec(method_template
% method
, globals(), d
)
133 AllTests
= type("AllTests", (object,), d
)
134 del d
, statictests
, method
, method_template
136 class ClassTests(unittest
.TestCase
):
140 def assertCallStack(self
, expected_calls
):
141 actualCallList
= callLst
[:] # need to copy because the comparison below will add
142 # additional calls to callLst
143 if expected_calls
!= actualCallList
:
144 self
.fail("Expected call list:\n %s\ndoes not match actual call list\n %s" %
145 (expected_calls
, actualCallList
))
149 self
.assertCallStack([("__init__", (foo
,))])
151 def testBinaryOps(self
):
157 self
.assertCallStack([("__add__", (testme
, 1))])
161 self
.assertCallStack([("__radd__", (testme
, 1))])
165 self
.assertCallStack([("__sub__", (testme
, 1))])
169 self
.assertCallStack([("__rsub__", (testme
, 1))])
173 self
.assertCallStack([("__mul__", (testme
, 1))])
177 self
.assertCallStack([("__rmul__", (testme
, 1))])
181 self
.assertCallStack([("__matmul__", (testme
, 1))])
185 self
.assertCallStack([("__rmatmul__", (testme
, 1))])
189 self
.assertCallStack([("__truediv__", (testme
, 1))])
194 self
.assertCallStack([("__rtruediv__", (testme
, 1))])
198 self
.assertCallStack([("__floordiv__", (testme
, 1))])
203 self
.assertCallStack([("__rfloordiv__", (testme
, 1))])
207 self
.assertCallStack([("__mod__", (testme
, 1))])
211 self
.assertCallStack([("__rmod__", (testme
, 1))])
216 self
.assertCallStack([("__divmod__", (testme
, 1))])
220 self
.assertCallStack([("__rdivmod__", (testme
, 1))])
224 self
.assertCallStack([("__pow__", (testme
, 1))])
228 self
.assertCallStack([("__rpow__", (testme
, 1))])
232 self
.assertCallStack([("__rshift__", (testme
, 1))])
236 self
.assertCallStack([("__rrshift__", (testme
, 1))])
240 self
.assertCallStack([("__lshift__", (testme
, 1))])
244 self
.assertCallStack([("__rlshift__", (testme
, 1))])
248 self
.assertCallStack([("__and__", (testme
, 1))])
252 self
.assertCallStack([("__rand__", (testme
, 1))])
256 self
.assertCallStack([("__or__", (testme
, 1))])
260 self
.assertCallStack([("__ror__", (testme
, 1))])
264 self
.assertCallStack([("__xor__", (testme
, 1))])
268 self
.assertCallStack([("__rxor__", (testme
, 1))])
270 def testListAndDictOps(self
):
273 # List/dict operations
279 self
.fail('failed, should have raised TypeError')
285 self
.assertCallStack([('__contains__', (testme
, 1))])
289 self
.assertCallStack([('__getitem__', (testme
, 1))])
293 self
.assertCallStack([('__setitem__', (testme
, 1, 1))])
297 self
.assertCallStack([('__delitem__', (testme
, 1))])
301 self
.assertCallStack([('__getitem__', (testme
, slice(None, 42)))])
304 testme
[:42] = "The Answer"
305 self
.assertCallStack([('__setitem__', (testme
, slice(None, 42),
310 self
.assertCallStack([('__delitem__', (testme
, slice(None, 42)))])
314 self
.assertCallStack([('__getitem__', (testme
, slice(2, 1024, 10)))])
317 testme
[2:1024:10] = "A lot"
318 self
.assertCallStack([('__setitem__', (testme
, slice(2, 1024, 10),
321 del testme
[2:1024:10]
322 self
.assertCallStack([('__delitem__', (testme
, slice(2, 1024, 10)))])
325 testme
[:42, ..., :24:, 24, 100]
326 self
.assertCallStack([('__getitem__', (testme
, (slice(None, 42, None),
328 slice(None, 24, None),
331 testme
[:42, ..., :24:, 24, 100] = "Strange"
332 self
.assertCallStack([('__setitem__', (testme
, (slice(None, 42, None),
334 slice(None, 24, None),
335 24, 100), "Strange"))])
337 del testme
[:42, ..., :24:, 24, 100]
338 self
.assertCallStack([('__delitem__', (testme
, (slice(None, 42, None),
340 slice(None, 24, None),
343 def testUnaryOps(self
):
348 self
.assertCallStack([('__neg__', (testme
,))])
351 self
.assertCallStack([('__pos__', (testme
,))])
354 self
.assertCallStack([('__abs__', (testme
,))])
357 self
.assertCallStack([('__int__', (testme
,))])
360 self
.assertCallStack([('__float__', (testme
,))])
363 self
.assertCallStack([('__index__', (testme
,))])
366 self
.assertCallStack([('__index__', (testme
,))])
374 self
.assertCallStack([('__hash__', (testme
,))])
378 self
.assertCallStack([('__repr__', (testme
,))])
382 self
.assertCallStack([('__str__', (testme
,))])
386 self
.assertCallStack([('__eq__', (testme
, 1))])
390 self
.assertCallStack([('__lt__', (testme
, 1))])
394 self
.assertCallStack([('__gt__', (testme
, 1))])
398 self
.assertCallStack([('__ne__', (testme
, 1))])
402 self
.assertCallStack([('__eq__', (1, testme
))])
406 self
.assertCallStack([('__gt__', (1, testme
))])
410 self
.assertCallStack([('__lt__', (1, testme
))])
414 self
.assertCallStack([('__ne__', (1, testme
))])
417 def testGetSetAndDel(self
):
419 class ExtraTests(AllTests
):
421 def __getattr__(self
, *args
):
425 def __setattr__(self
, *args
):
429 def __delattr__(self
, *args
):
432 testme
= ExtraTests()
436 self
.assertCallStack([('__getattr__', (testme
, "spam"))])
439 testme
.eggs
= "spam, spam, spam and ham"
440 self
.assertCallStack([('__setattr__', (testme
, "eggs",
441 "spam, spam, spam and ham"))])
445 self
.assertCallStack([('__delattr__', (testme
, "cardinal"))])
447 def testHasAttrString(self
):
449 from test
.support
import import_helper
450 _testlimitedcapi
= import_helper
.import_module('_testlimitedcapi')
457 self
.assertEqual(_testlimitedcapi
.object_hasattrstring(a
, b
"attr"), 1)
458 self
.assertEqual(_testlimitedcapi
.object_hasattrstring(a
, b
"noattr"), 0)
459 self
.assertIsNone(sys
.exception())
466 x
.append("crab people, crab people")
471 self
.assertEqual(["crab people, crab people"], x
)
473 def testBadTypeReturned(self
):
474 # return values of some method are type-checked
479 __complex__
= __int__
488 for f
in [float, complex, str, repr, bytes
, bin
, oct, hex, bool, index
]:
489 self
.assertRaises(TypeError, f
, BadTypeClass())
491 def testHashStuff(self
):
492 # Test correct errors from hash() on objects with comparisons but
498 hash(C0()) # This should work; the next two should raise TypeError
501 def __eq__(self
, other
): return 1
503 self
.assertRaises(TypeError, hash, C2())
506 def testSFBug532646(self
):
507 # Test for SF bug 532646
515 a() # This should not segfault
516 except RecursionError
:
519 self
.fail("Failed to raise RecursionError")
521 def testForExceptionsRaisedInInstanceGetattr2(self
):
522 # Tests for exceptions raised in instance_getattr2().
525 raise AttributeError("booh")
530 A().a
# Raised AttributeError: A instance has no attribute 'a'
531 except AttributeError as x
:
533 self
.fail("attribute error for A().a got masked: %s" % x
)
536 __eq__
= property(booh
)
537 E() == E() # In debug mode, caused a C-level assert() to fail
540 __init__
= property(booh
)
542 # In debug mode, printed XXX undetected error and
543 # raises AttributeError
545 except AttributeError:
548 self
.fail("attribute error for I.__init__ got masked")
550 def assertNotOrderable(self
, a
, b
):
551 with self
.assertRaises(TypeError):
553 with self
.assertRaises(TypeError):
555 with self
.assertRaises(TypeError):
557 with self
.assertRaises(TypeError):
560 def testHashComparisonOfMethods(self
):
561 # Test comparison and hash of methods
563 def __init__(self
, x
):
569 def __eq__(self
, other
):
578 self
.assertTrue(a1
.f
== a1
.f
)
579 self
.assertFalse(a1
.f
!= a1
.f
)
580 self
.assertFalse(a1
.f
== a2
.f
)
581 self
.assertTrue(a1
.f
!= a2
.f
)
582 self
.assertFalse(a1
.f
== a1
.g
)
583 self
.assertTrue(a1
.f
!= a1
.g
)
584 self
.assertNotOrderable(a1
.f
, a1
.f
)
585 self
.assertEqual(hash(a1
.f
), hash(a1
.f
))
587 self
.assertFalse(A
.f
== a1
.f
)
588 self
.assertTrue(A
.f
!= a1
.f
)
589 self
.assertFalse(A
.f
== A
.g
)
590 self
.assertTrue(A
.f
!= A
.g
)
591 self
.assertTrue(B
.f
== A
.f
)
592 self
.assertFalse(B
.f
!= A
.f
)
593 self
.assertNotOrderable(A
.f
, A
.f
)
594 self
.assertEqual(hash(B
.f
), hash(A
.f
))
596 # the following triggers a SystemError in 2.4
597 a
= A(hash(A
.f
)^
(-1))
600 def testSetattrWrapperNameIntern(self
):
601 # Issue #25794: __setattr__ should intern the attribute name
605 def add(self
, other
):
608 name
= str(b
'__add__', 'ascii') # shouldn't be optimized
609 self
.assertIsNot(name
, '__add__') # not interned
610 type.__setattr
__(A
, name
, add
)
611 self
.assertEqual(A() + 1, 'summa')
613 name2
= str(b
'__add__', 'ascii')
614 self
.assertIsNot(name2
, '__add__')
615 self
.assertIsNot(name2
, name
)
616 type.__delattr
__(A
, name2
)
617 with self
.assertRaises(TypeError):
620 def testSetattrNonStringName(self
):
624 with self
.assertRaises(TypeError):
625 type.__setattr
__(A
, b
'x', None)
627 def testTypeAttributeAccessErrorMessages(self
):
631 error_msg
= "type object 'A' has no attribute 'x'"
632 with self
.assertRaisesRegex(AttributeError, error_msg
):
634 with self
.assertRaisesRegex(AttributeError, error_msg
):
637 def testObjectAttributeAccessErrorMessages(self
):
646 def __setattr__(self
, name
, value
) -> None:
648 super().__setattr
__("y", 1)
650 super().__setattr
__(name
, value
)
652 error_msg
= "'A' object has no attribute 'x'"
653 with self
.assertRaisesRegex(AttributeError, error_msg
):
655 with self
.assertRaisesRegex(AttributeError, error_msg
):
658 error_msg
= "'B' object has no attribute 'x'"
659 with self
.assertRaisesRegex(AttributeError, error_msg
):
661 with self
.assertRaisesRegex(AttributeError, error_msg
):
663 with self
.assertRaisesRegex(
665 "'B' object has no attribute 'x' and no __dict__ for setting new attributes"
668 with self
.assertRaisesRegex(
670 "'C' object has no attribute 'x'"
674 error_msg
= "'B' object attribute 'y' is read-only"
675 with self
.assertRaisesRegex(AttributeError, error_msg
):
677 with self
.assertRaisesRegex(AttributeError, error_msg
):
681 with self
.assertRaisesRegex(AttributeError, error_msg
):
683 with self
.assertRaisesRegex(AttributeError, error_msg
):
686 def testConstructorErrorMessages(self
):
687 # bpo-31506: Improves the error message logic for object_new & object_init
689 # Class without any method overrides
693 error_msg
= r
'C.__init__\(\) takes exactly one argument \(the instance to initialize\)'
695 with self
.assertRaisesRegex(TypeError, r
'C\(\) takes no arguments'):
698 with self
.assertRaisesRegex(TypeError, r
'C\(\) takes no arguments'):
701 with self
.assertRaisesRegex(TypeError, error_msg
):
704 with self
.assertRaisesRegex(TypeError, r
'C\(\) takes no arguments'):
705 object.__new
__(C
, 42)
707 with self
.assertRaisesRegex(TypeError, error_msg
):
708 object.__init
__(C(), 42)
710 # Class with both `__init__` & `__new__` method overridden
712 def __new__(cls
, *args
, **kwargs
):
713 super().__new
__(cls
, *args
, **kwargs
)
714 def __init__(self
, *args
, **kwargs
):
715 super().__init
__(*args
, **kwargs
)
717 error_msg
= r
'object.__new__\(\) takes exactly one argument \(the type to instantiate\)'
719 with self
.assertRaisesRegex(TypeError, error_msg
):
722 with self
.assertRaisesRegex(TypeError, error_msg
):
725 with self
.assertRaisesRegex(TypeError, error_msg
):
726 object.__new
__(D
, 42)
728 # Class that only overrides __init__
730 def __init__(self
, *args
, **kwargs
):
731 super().__init
__(*args
, **kwargs
)
733 error_msg
= r
'object.__init__\(\) takes exactly one argument \(the instance to initialize\)'
735 with self
.assertRaisesRegex(TypeError, error_msg
):
738 with self
.assertRaisesRegex(TypeError, error_msg
):
739 object.__init
__(E(), 42)
741 def testClassWithExtCall(self
):
743 def __init__(*args
, **kwargs
):
746 def __new__(cls
, name
, bases
, attrs
, **kwargs
):
749 d
= {'metaclass': Meta
}
752 self
.assertEqual(A
, ((), {}))
753 class A(0, 1, 2, 3, 4, 5, 6, 7, **d
): pass
754 self
.assertEqual(A
, (tuple(range(8)), {}))
755 class A(0, *range(1, 8), **d
, foo
='bar'): pass
756 self
.assertEqual(A
, (tuple(range(8)), {'foo': 'bar'}))
758 def testClassCallRecursionLimit(self
):
763 with self
.assertRaises(RecursionError
):
767 #Each call to C() consumes 2 levels, so offset by 1.
770 with self
.assertRaises(RecursionError
):
773 def testMetaclassCallOptimization(self
):
776 class TypeMetaclass(type):
777 def __call__(cls
, *args
, **kwargs
):
780 return type.__call
__(cls
, *args
, **kwargs
)
782 class Type(metaclass
=TypeMetaclass
):
783 def __init__(self
, obj
):
788 self
.assertEqual(calls
, 100)
791 from _testinternalcapi
import has_inline_values
793 Py_TPFLAGS_MANAGED_DICT
= (1 << 2)
808 class TestInlineValues(unittest
.TestCase
):
810 def test_flags(self
):
811 self
.assertEqual(Plain
.__flags
__ & Py_TPFLAGS_MANAGED_DICT
, Py_TPFLAGS_MANAGED_DICT
)
812 self
.assertEqual(WithAttrs
.__flags
__ & Py_TPFLAGS_MANAGED_DICT
, Py_TPFLAGS_MANAGED_DICT
)
814 def test_has_inline_values(self
):
816 self
.assertTrue(has_inline_values(c
))
818 self
.assertFalse(has_inline_values(c
))
820 def test_instances(self
):
821 self
.assertTrue(has_inline_values(Plain()))
822 self
.assertTrue(has_inline_values(WithAttrs()))
824 def test_inspect_dict(self
):
825 for cls
in (Plain
, WithAttrs
):
828 self
.assertTrue(has_inline_values(c
))
830 def test_update_dict(self
):
831 d
= { "e": 5, "f": 6 }
832 for cls
in (Plain
, WithAttrs
):
835 self
.assertTrue(has_inline_values(c
))
840 setattr(obj
, f
"a{i}", i
)
842 def check_100(self
, obj
):
844 self
.assertEqual(getattr(obj
, f
"a{i}"), i
)
846 def test_many_attributes(self
):
849 self
.assertTrue(has_inline_values(c
))
851 self
.assertFalse(has_inline_values(c
))
854 self
.assertTrue(has_inline_values(c
))
856 def test_many_attributes_with_dict(self
):
860 self
.assertTrue(has_inline_values(c
))
862 self
.assertFalse(has_inline_values(c
))
867 if __name__
== '__main__':