(root)/
Python-3.12.0/
Lib/
test/
test_class.py
       1  "Test the functionality of Python classes implementing operators."
       2  
       3  import unittest
       4  
       5  
       6  testmeths = [
       7  
       8  # Binary operations
       9      "add",
      10      "radd",
      11      "sub",
      12      "rsub",
      13      "mul",
      14      "rmul",
      15      "matmul",
      16      "rmatmul",
      17      "truediv",
      18      "rtruediv",
      19      "floordiv",
      20      "rfloordiv",
      21      "mod",
      22      "rmod",
      23      "divmod",
      24      "rdivmod",
      25      "pow",
      26      "rpow",
      27      "rshift",
      28      "rrshift",
      29      "lshift",
      30      "rlshift",
      31      "and",
      32      "rand",
      33      "or",
      34      "ror",
      35      "xor",
      36      "rxor",
      37  
      38  # List/dict operations
      39      "contains",
      40      "getitem",
      41      "setitem",
      42      "delitem",
      43  
      44  # Unary operations
      45      "neg",
      46      "pos",
      47      "abs",
      48  
      49  # generic operations
      50      "init",
      51      ]
      52  
      53  # These need to return something other than None
      54  #    "hash",
      55  #    "str",
      56  #    "repr",
      57  #    "int",
      58  #    "float",
      59  
      60  # These are separate because they can influence the test of other methods.
      61  #    "getattr",
      62  #    "setattr",
      63  #    "delattr",
      64  
      65  callLst = []
      66  def trackCall(f):
      67      def track(*args, **kwargs):
      68          callLst.append((f.__name__, args))
      69          return f(*args, **kwargs)
      70      return track
      71  
      72  statictests = """
      73  @trackCall
      74  def __hash__(self, *args):
      75      return hash(id(self))
      76  
      77  @trackCall
      78  def __str__(self, *args):
      79      return "AllTests"
      80  
      81  @trackCall
      82  def __repr__(self, *args):
      83      return "AllTests"
      84  
      85  @trackCall
      86  def __int__(self, *args):
      87      return 1
      88  
      89  @trackCall
      90  def __index__(self, *args):
      91      return 1
      92  
      93  @trackCall
      94  def __float__(self, *args):
      95      return 1.0
      96  
      97  @trackCall
      98  def __eq__(self, *args):
      99      return True
     100  
     101  @trackCall
     102  def __ne__(self, *args):
     103      return False
     104  
     105  @trackCall
     106  def __lt__(self, *args):
     107      return False
     108  
     109  @trackCall
     110  def __le__(self, *args):
     111      return True
     112  
     113  @trackCall
     114  def __gt__(self, *args):
     115      return False
     116  
     117  @trackCall
     118  def __ge__(self, *args):
     119      return True
     120  """
     121  
     122  # Synthesize all the other AllTests methods from the names in testmeths.
     123  
     124  method_template = """\
     125  @trackCall
     126  def __%s__(self, *args):
     127      pass
     128  """
     129  
     130  d = {}
     131  exec(statictests, globals(), d)
     132  for method in testmeths:
     133      exec(method_template % method, globals(), d)
     134  AllTests = type("AllTests", (object,), d)
     135  del d, statictests, method, method_template
     136  
     137  class ESC[4;38;5;81mClassTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     138      def setUp(self):
     139          callLst[:] = []
     140  
     141      def assertCallStack(self, expected_calls):
     142          actualCallList = callLst[:]  # need to copy because the comparison below will add
     143                                       # additional calls to callLst
     144          if expected_calls != actualCallList:
     145              self.fail("Expected call list:\n  %s\ndoes not match actual call list\n  %s" %
     146                        (expected_calls, actualCallList))
     147  
     148      def testInit(self):
     149          foo = AllTests()
     150          self.assertCallStack([("__init__", (foo,))])
     151  
     152      def testBinaryOps(self):
     153          testme = AllTests()
     154          # Binary operations
     155  
     156          callLst[:] = []
     157          testme + 1
     158          self.assertCallStack([("__add__", (testme, 1))])
     159  
     160          callLst[:] = []
     161          1 + testme
     162          self.assertCallStack([("__radd__", (testme, 1))])
     163  
     164          callLst[:] = []
     165          testme - 1
     166          self.assertCallStack([("__sub__", (testme, 1))])
     167  
     168          callLst[:] = []
     169          1 - testme
     170          self.assertCallStack([("__rsub__", (testme, 1))])
     171  
     172          callLst[:] = []
     173          testme * 1
     174          self.assertCallStack([("__mul__", (testme, 1))])
     175  
     176          callLst[:] = []
     177          1 * testme
     178          self.assertCallStack([("__rmul__", (testme, 1))])
     179  
     180          callLst[:] = []
     181          testme @ 1
     182          self.assertCallStack([("__matmul__", (testme, 1))])
     183  
     184          callLst[:] = []
     185          1 @ testme
     186          self.assertCallStack([("__rmatmul__", (testme, 1))])
     187  
     188          callLst[:] = []
     189          testme / 1
     190          self.assertCallStack([("__truediv__", (testme, 1))])
     191  
     192  
     193          callLst[:] = []
     194          1 / testme
     195          self.assertCallStack([("__rtruediv__", (testme, 1))])
     196  
     197          callLst[:] = []
     198          testme // 1
     199          self.assertCallStack([("__floordiv__", (testme, 1))])
     200  
     201  
     202          callLst[:] = []
     203          1 // testme
     204          self.assertCallStack([("__rfloordiv__", (testme, 1))])
     205  
     206          callLst[:] = []
     207          testme % 1
     208          self.assertCallStack([("__mod__", (testme, 1))])
     209  
     210          callLst[:] = []
     211          1 % testme
     212          self.assertCallStack([("__rmod__", (testme, 1))])
     213  
     214  
     215          callLst[:] = []
     216          divmod(testme,1)
     217          self.assertCallStack([("__divmod__", (testme, 1))])
     218  
     219          callLst[:] = []
     220          divmod(1, testme)
     221          self.assertCallStack([("__rdivmod__", (testme, 1))])
     222  
     223          callLst[:] = []
     224          testme ** 1
     225          self.assertCallStack([("__pow__", (testme, 1))])
     226  
     227          callLst[:] = []
     228          1 ** testme
     229          self.assertCallStack([("__rpow__", (testme, 1))])
     230  
     231          callLst[:] = []
     232          testme >> 1
     233          self.assertCallStack([("__rshift__", (testme, 1))])
     234  
     235          callLst[:] = []
     236          1 >> testme
     237          self.assertCallStack([("__rrshift__", (testme, 1))])
     238  
     239          callLst[:] = []
     240          testme << 1
     241          self.assertCallStack([("__lshift__", (testme, 1))])
     242  
     243          callLst[:] = []
     244          1 << testme
     245          self.assertCallStack([("__rlshift__", (testme, 1))])
     246  
     247          callLst[:] = []
     248          testme & 1
     249          self.assertCallStack([("__and__", (testme, 1))])
     250  
     251          callLst[:] = []
     252          1 & testme
     253          self.assertCallStack([("__rand__", (testme, 1))])
     254  
     255          callLst[:] = []
     256          testme | 1
     257          self.assertCallStack([("__or__", (testme, 1))])
     258  
     259          callLst[:] = []
     260          1 | testme
     261          self.assertCallStack([("__ror__", (testme, 1))])
     262  
     263          callLst[:] = []
     264          testme ^ 1
     265          self.assertCallStack([("__xor__", (testme, 1))])
     266  
     267          callLst[:] = []
     268          1 ^ testme
     269          self.assertCallStack([("__rxor__", (testme, 1))])
     270  
     271      def testListAndDictOps(self):
     272          testme = AllTests()
     273  
     274          # List/dict operations
     275  
     276          class ESC[4;38;5;81mEmpty: pass
     277  
     278          try:
     279              1 in Empty()
     280              self.fail('failed, should have raised TypeError')
     281          except TypeError:
     282              pass
     283  
     284          callLst[:] = []
     285          1 in testme
     286          self.assertCallStack([('__contains__', (testme, 1))])
     287  
     288          callLst[:] = []
     289          testme[1]
     290          self.assertCallStack([('__getitem__', (testme, 1))])
     291  
     292          callLst[:] = []
     293          testme[1] = 1
     294          self.assertCallStack([('__setitem__', (testme, 1, 1))])
     295  
     296          callLst[:] = []
     297          del testme[1]
     298          self.assertCallStack([('__delitem__', (testme, 1))])
     299  
     300          callLst[:] = []
     301          testme[:42]
     302          self.assertCallStack([('__getitem__', (testme, slice(None, 42)))])
     303  
     304          callLst[:] = []
     305          testme[:42] = "The Answer"
     306          self.assertCallStack([('__setitem__', (testme, slice(None, 42),
     307                                                 "The Answer"))])
     308  
     309          callLst[:] = []
     310          del testme[:42]
     311          self.assertCallStack([('__delitem__', (testme, slice(None, 42)))])
     312  
     313          callLst[:] = []
     314          testme[2:1024:10]
     315          self.assertCallStack([('__getitem__', (testme, slice(2, 1024, 10)))])
     316  
     317          callLst[:] = []
     318          testme[2:1024:10] = "A lot"
     319          self.assertCallStack([('__setitem__', (testme, slice(2, 1024, 10),
     320                                                                      "A lot"))])
     321          callLst[:] = []
     322          del testme[2:1024:10]
     323          self.assertCallStack([('__delitem__', (testme, slice(2, 1024, 10)))])
     324  
     325          callLst[:] = []
     326          testme[:42, ..., :24:, 24, 100]
     327          self.assertCallStack([('__getitem__', (testme, (slice(None, 42, None),
     328                                                          Ellipsis,
     329                                                          slice(None, 24, None),
     330                                                          24, 100)))])
     331          callLst[:] = []
     332          testme[:42, ..., :24:, 24, 100] = "Strange"
     333          self.assertCallStack([('__setitem__', (testme, (slice(None, 42, None),
     334                                                          Ellipsis,
     335                                                          slice(None, 24, None),
     336                                                          24, 100), "Strange"))])
     337          callLst[:] = []
     338          del testme[:42, ..., :24:, 24, 100]
     339          self.assertCallStack([('__delitem__', (testme, (slice(None, 42, None),
     340                                                          Ellipsis,
     341                                                          slice(None, 24, None),
     342                                                          24, 100)))])
     343  
     344      def testUnaryOps(self):
     345          testme = AllTests()
     346  
     347          callLst[:] = []
     348          -testme
     349          self.assertCallStack([('__neg__', (testme,))])
     350          callLst[:] = []
     351          +testme
     352          self.assertCallStack([('__pos__', (testme,))])
     353          callLst[:] = []
     354          abs(testme)
     355          self.assertCallStack([('__abs__', (testme,))])
     356          callLst[:] = []
     357          int(testme)
     358          self.assertCallStack([('__int__', (testme,))])
     359          callLst[:] = []
     360          float(testme)
     361          self.assertCallStack([('__float__', (testme,))])
     362          callLst[:] = []
     363          oct(testme)
     364          self.assertCallStack([('__index__', (testme,))])
     365          callLst[:] = []
     366          hex(testme)
     367          self.assertCallStack([('__index__', (testme,))])
     368  
     369  
     370      def testMisc(self):
     371          testme = AllTests()
     372  
     373          callLst[:] = []
     374          hash(testme)
     375          self.assertCallStack([('__hash__', (testme,))])
     376  
     377          callLst[:] = []
     378          repr(testme)
     379          self.assertCallStack([('__repr__', (testme,))])
     380  
     381          callLst[:] = []
     382          str(testme)
     383          self.assertCallStack([('__str__', (testme,))])
     384  
     385          callLst[:] = []
     386          testme == 1
     387          self.assertCallStack([('__eq__', (testme, 1))])
     388  
     389          callLst[:] = []
     390          testme < 1
     391          self.assertCallStack([('__lt__', (testme, 1))])
     392  
     393          callLst[:] = []
     394          testme > 1
     395          self.assertCallStack([('__gt__', (testme, 1))])
     396  
     397          callLst[:] = []
     398          testme != 1
     399          self.assertCallStack([('__ne__', (testme, 1))])
     400  
     401          callLst[:] = []
     402          1 == testme
     403          self.assertCallStack([('__eq__', (1, testme))])
     404  
     405          callLst[:] = []
     406          1 < testme
     407          self.assertCallStack([('__gt__', (1, testme))])
     408  
     409          callLst[:] = []
     410          1 > testme
     411          self.assertCallStack([('__lt__', (1, testme))])
     412  
     413          callLst[:] = []
     414          1 != testme
     415          self.assertCallStack([('__ne__', (1, testme))])
     416  
     417  
     418      def testGetSetAndDel(self):
     419          # Interfering tests
     420          class ESC[4;38;5;81mExtraTests(ESC[4;38;5;149mAllTests):
     421              @trackCall
     422              def __getattr__(self, *args):
     423                  return "SomeVal"
     424  
     425              @trackCall
     426              def __setattr__(self, *args):
     427                  pass
     428  
     429              @trackCall
     430              def __delattr__(self, *args):
     431                  pass
     432  
     433          testme = ExtraTests()
     434  
     435          callLst[:] = []
     436          testme.spam
     437          self.assertCallStack([('__getattr__', (testme, "spam"))])
     438  
     439          callLst[:] = []
     440          testme.eggs = "spam, spam, spam and ham"
     441          self.assertCallStack([('__setattr__', (testme, "eggs",
     442                                                 "spam, spam, spam and ham"))])
     443  
     444          callLst[:] = []
     445          del testme.cardinal
     446          self.assertCallStack([('__delattr__', (testme, "cardinal"))])
     447  
     448      def testHasAttrString(self):
     449          import sys
     450          from test.support import import_helper
     451          _testcapi = import_helper.import_module('_testcapi')
     452  
     453          class ESC[4;38;5;81mA:
     454              def __init__(self):
     455                  self.attr = 1
     456  
     457          a = A()
     458          self.assertEqual(_testcapi.object_hasattrstring(a, b"attr"), 1)
     459          self.assertEqual(_testcapi.object_hasattrstring(a, b"noattr"), 0)
     460          self.assertIsNone(sys.exception())
     461  
     462      def testDel(self):
     463          x = []
     464  
     465          class ESC[4;38;5;81mDelTest:
     466              def __del__(self):
     467                  x.append("crab people, crab people")
     468          testme = DelTest()
     469          del testme
     470          import gc
     471          gc.collect()
     472          self.assertEqual(["crab people, crab people"], x)
     473  
     474      def testBadTypeReturned(self):
     475          # return values of some method are type-checked
     476          class ESC[4;38;5;81mBadTypeClass:
     477              def __int__(self):
     478                  return None
     479              __float__ = __int__
     480              __complex__ = __int__
     481              __str__ = __int__
     482              __repr__ = __int__
     483              __bytes__ = __int__
     484              __bool__ = __int__
     485              __index__ = __int__
     486          def index(x):
     487              return [][x]
     488  
     489          for f in [float, complex, str, repr, bytes, bin, oct, hex, bool, index]:
     490              self.assertRaises(TypeError, f, BadTypeClass())
     491  
     492      def testHashStuff(self):
     493          # Test correct errors from hash() on objects with comparisons but
     494          #  no __hash__
     495  
     496          class ESC[4;38;5;81mC0:
     497              pass
     498  
     499          hash(C0()) # This should work; the next two should raise TypeError
     500  
     501          class ESC[4;38;5;81mC2:
     502              def __eq__(self, other): return 1
     503  
     504          self.assertRaises(TypeError, hash, C2())
     505  
     506  
     507      def testSFBug532646(self):
     508          # Test for SF bug 532646
     509  
     510          class ESC[4;38;5;81mA:
     511              pass
     512          A.__call__ = A()
     513          a = A()
     514  
     515          try:
     516              a() # This should not segfault
     517          except RecursionError:
     518              pass
     519          else:
     520              self.fail("Failed to raise RecursionError")
     521  
     522      def testForExceptionsRaisedInInstanceGetattr2(self):
     523          # Tests for exceptions raised in instance_getattr2().
     524  
     525          def booh(self):
     526              raise AttributeError("booh")
     527  
     528          class ESC[4;38;5;81mA:
     529              a = property(booh)
     530          try:
     531              A().a # Raised AttributeError: A instance has no attribute 'a'
     532          except AttributeError as x:
     533              if str(x) != "booh":
     534                  self.fail("attribute error for A().a got masked: %s" % x)
     535  
     536          class ESC[4;38;5;81mE:
     537              __eq__ = property(booh)
     538          E() == E() # In debug mode, caused a C-level assert() to fail
     539  
     540          class ESC[4;38;5;81mI:
     541              __init__ = property(booh)
     542          try:
     543              # In debug mode, printed XXX undetected error and
     544              #  raises AttributeError
     545              I()
     546          except AttributeError:
     547              pass
     548          else:
     549              self.fail("attribute error for I.__init__ got masked")
     550  
     551      def assertNotOrderable(self, a, b):
     552          with self.assertRaises(TypeError):
     553              a < b
     554          with self.assertRaises(TypeError):
     555              a > b
     556          with self.assertRaises(TypeError):
     557              a <= b
     558          with self.assertRaises(TypeError):
     559              a >= b
     560  
     561      def testHashComparisonOfMethods(self):
     562          # Test comparison and hash of methods
     563          class ESC[4;38;5;81mA:
     564              def __init__(self, x):
     565                  self.x = x
     566              def f(self):
     567                  pass
     568              def g(self):
     569                  pass
     570              def __eq__(self, other):
     571                  return True
     572              def __hash__(self):
     573                  raise TypeError
     574          class ESC[4;38;5;81mB(ESC[4;38;5;149mA):
     575              pass
     576  
     577          a1 = A(1)
     578          a2 = A(1)
     579          self.assertTrue(a1.f == a1.f)
     580          self.assertFalse(a1.f != a1.f)
     581          self.assertFalse(a1.f == a2.f)
     582          self.assertTrue(a1.f != a2.f)
     583          self.assertFalse(a1.f == a1.g)
     584          self.assertTrue(a1.f != a1.g)
     585          self.assertNotOrderable(a1.f, a1.f)
     586          self.assertEqual(hash(a1.f), hash(a1.f))
     587  
     588          self.assertFalse(A.f == a1.f)
     589          self.assertTrue(A.f != a1.f)
     590          self.assertFalse(A.f == A.g)
     591          self.assertTrue(A.f != A.g)
     592          self.assertTrue(B.f == A.f)
     593          self.assertFalse(B.f != A.f)
     594          self.assertNotOrderable(A.f, A.f)
     595          self.assertEqual(hash(B.f), hash(A.f))
     596  
     597          # the following triggers a SystemError in 2.4
     598          a = A(hash(A.f)^(-1))
     599          hash(a.f)
     600  
     601      def testSetattrWrapperNameIntern(self):
     602          # Issue #25794: __setattr__ should intern the attribute name
     603          class ESC[4;38;5;81mA:
     604              pass
     605  
     606          def add(self, other):
     607              return 'summa'
     608  
     609          name = str(b'__add__', 'ascii')  # shouldn't be optimized
     610          self.assertIsNot(name, '__add__')  # not interned
     611          type.__setattr__(A, name, add)
     612          self.assertEqual(A() + 1, 'summa')
     613  
     614          name2 = str(b'__add__', 'ascii')
     615          self.assertIsNot(name2, '__add__')
     616          self.assertIsNot(name2, name)
     617          type.__delattr__(A, name2)
     618          with self.assertRaises(TypeError):
     619              A() + 1
     620  
     621      def testSetattrNonStringName(self):
     622          class ESC[4;38;5;81mA:
     623              pass
     624  
     625          with self.assertRaises(TypeError):
     626              type.__setattr__(A, b'x', None)
     627  
     628      def testTypeAttributeAccessErrorMessages(self):
     629          class ESC[4;38;5;81mA:
     630              pass
     631  
     632          error_msg = "type object 'A' has no attribute 'x'"
     633          with self.assertRaisesRegex(AttributeError, error_msg):
     634              A.x
     635          with self.assertRaisesRegex(AttributeError, error_msg):
     636              del A.x
     637  
     638      def testObjectAttributeAccessErrorMessages(self):
     639          class ESC[4;38;5;81mA:
     640              pass
     641          class ESC[4;38;5;81mB:
     642              y = 0
     643              __slots__ = ('z',)
     644  
     645          error_msg = "'A' object has no attribute 'x'"
     646          with self.assertRaisesRegex(AttributeError, error_msg):
     647              A().x
     648          with self.assertRaisesRegex(AttributeError, error_msg):
     649              del A().x
     650  
     651          error_msg = "'B' object has no attribute 'x'"
     652          with self.assertRaisesRegex(AttributeError, error_msg):
     653              B().x
     654          with self.assertRaisesRegex(AttributeError, error_msg):
     655              del B().x
     656          with self.assertRaisesRegex(AttributeError, error_msg):
     657              B().x = 0
     658  
     659          error_msg = "'B' object attribute 'y' is read-only"
     660          with self.assertRaisesRegex(AttributeError, error_msg):
     661              del B().y
     662          with self.assertRaisesRegex(AttributeError, error_msg):
     663              B().y = 0
     664  
     665          error_msg = 'z'
     666          with self.assertRaisesRegex(AttributeError, error_msg):
     667              B().z
     668          with self.assertRaisesRegex(AttributeError, error_msg):
     669              del B().z
     670  
     671      def testConstructorErrorMessages(self):
     672          # bpo-31506: Improves the error message logic for object_new & object_init
     673  
     674          # Class without any method overrides
     675          class ESC[4;38;5;81mC:
     676              pass
     677  
     678          error_msg = r'C.__init__\(\) takes exactly one argument \(the instance to initialize\)'
     679  
     680          with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'):
     681              C(42)
     682  
     683          with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'):
     684              C.__new__(C, 42)
     685  
     686          with self.assertRaisesRegex(TypeError, error_msg):
     687              C().__init__(42)
     688  
     689          with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'):
     690              object.__new__(C, 42)
     691  
     692          with self.assertRaisesRegex(TypeError, error_msg):
     693              object.__init__(C(), 42)
     694  
     695          # Class with both `__init__` & `__new__` method overridden
     696          class ESC[4;38;5;81mD:
     697              def __new__(cls, *args, **kwargs):
     698                  super().__new__(cls, *args, **kwargs)
     699              def __init__(self, *args, **kwargs):
     700                  super().__init__(*args, **kwargs)
     701  
     702          error_msg =  r'object.__new__\(\) takes exactly one argument \(the type to instantiate\)'
     703  
     704          with self.assertRaisesRegex(TypeError, error_msg):
     705              D(42)
     706  
     707          with self.assertRaisesRegex(TypeError, error_msg):
     708              D.__new__(D, 42)
     709  
     710          with self.assertRaisesRegex(TypeError, error_msg):
     711              object.__new__(D, 42)
     712  
     713          # Class that only overrides __init__
     714          class ESC[4;38;5;81mE:
     715              def __init__(self, *args, **kwargs):
     716                  super().__init__(*args, **kwargs)
     717  
     718          error_msg = r'object.__init__\(\) takes exactly one argument \(the instance to initialize\)'
     719  
     720          with self.assertRaisesRegex(TypeError, error_msg):
     721              E().__init__(42)
     722  
     723          with self.assertRaisesRegex(TypeError, error_msg):
     724              object.__init__(E(), 42)
     725  
     726      def testClassWithExtCall(self):
     727          class ESC[4;38;5;81mMeta(ESC[4;38;5;149mint):
     728              def __init__(*args, **kwargs):
     729                  pass
     730  
     731              def __new__(cls, name, bases, attrs, **kwargs):
     732                  return bases, kwargs
     733  
     734          d = {'metaclass': Meta}
     735  
     736          class ESC[4;38;5;81mA(**ESC[4;38;5;149md): pass
     737          self.assertEqual(A, ((), {}))
     738          class ESC[4;38;5;81mA(0, 1, 2, 3, 4, 5, 6, 7, **ESC[4;38;5;149md): pass
     739          self.assertEqual(A, (tuple(range(8)), {}))
     740          class ESC[4;38;5;81mA(0, *ESC[4;38;5;149mrange(1, 8), **ESC[4;38;5;149md, foo='bar'): pass
     741          self.assertEqual(A, (tuple(range(8)), {'foo': 'bar'}))
     742  
     743  
     744  if __name__ == '__main__':
     745      unittest.main()