python (3.11.7)

(root)/
lib/
python3.11/
test/
test_int.py
       1  import sys
       2  import time
       3  
       4  import unittest
       5  from test import support
       6  from test.test_grammar import (VALID_UNDERSCORE_LITERALS,
       7                                 INVALID_UNDERSCORE_LITERALS)
       8  
       9  L = [
      10          ('0', 0),
      11          ('1', 1),
      12          ('9', 9),
      13          ('10', 10),
      14          ('99', 99),
      15          ('100', 100),
      16          ('314', 314),
      17          (' 314', 314),
      18          ('314 ', 314),
      19          ('  \t\t  314  \t\t  ', 314),
      20          (repr(sys.maxsize), sys.maxsize),
      21          ('  1x', ValueError),
      22          ('  1  ', 1),
      23          ('  1\02  ', ValueError),
      24          ('', ValueError),
      25          (' ', ValueError),
      26          ('  \t\t  ', ValueError),
      27          ("\u0200", ValueError)
      28  ]
      29  
      30  class ESC[4;38;5;81mIntSubclass(ESC[4;38;5;149mint):
      31      pass
      32  
      33  class ESC[4;38;5;81mIntTestCases(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      34  
      35      def test_basic(self):
      36          self.assertEqual(int(314), 314)
      37          self.assertEqual(int(3.14), 3)
      38          # Check that conversion from float truncates towards zero
      39          self.assertEqual(int(-3.14), -3)
      40          self.assertEqual(int(3.9), 3)
      41          self.assertEqual(int(-3.9), -3)
      42          self.assertEqual(int(3.5), 3)
      43          self.assertEqual(int(-3.5), -3)
      44          self.assertEqual(int("-3"), -3)
      45          self.assertEqual(int(" -3 "), -3)
      46          self.assertEqual(int("\N{EM SPACE}-3\N{EN SPACE}"), -3)
      47          # Different base:
      48          self.assertEqual(int("10",16), 16)
      49          # Test conversion from strings and various anomalies
      50          for s, v in L:
      51              for sign in "", "+", "-":
      52                  for prefix in "", " ", "\t", "  \t\t  ":
      53                      ss = prefix + sign + s
      54                      vv = v
      55                      if sign == "-" and v is not ValueError:
      56                          vv = -v
      57                      try:
      58                          self.assertEqual(int(ss), vv)
      59                      except ValueError:
      60                          pass
      61  
      62          s = repr(-1-sys.maxsize)
      63          x = int(s)
      64          self.assertEqual(x+1, -sys.maxsize)
      65          self.assertIsInstance(x, int)
      66          # should return int
      67          self.assertEqual(int(s[1:]), sys.maxsize+1)
      68  
      69          # should return int
      70          x = int(1e100)
      71          self.assertIsInstance(x, int)
      72          x = int(-1e100)
      73          self.assertIsInstance(x, int)
      74  
      75  
      76          # SF bug 434186:  0x80000000/2 != 0x80000000>>1.
      77          # Worked by accident in Windows release build, but failed in debug build.
      78          # Failed in all Linux builds.
      79          x = -1-sys.maxsize
      80          self.assertEqual(x >> 1, x//2)
      81  
      82          x = int('1' * 600)
      83          self.assertIsInstance(x, int)
      84  
      85  
      86          self.assertRaises(TypeError, int, 1, 12)
      87  
      88          self.assertEqual(int('0o123', 0), 83)
      89          self.assertEqual(int('0x123', 16), 291)
      90  
      91          # Bug 1679: "0x" is not a valid hex literal
      92          self.assertRaises(ValueError, int, "0x", 16)
      93          self.assertRaises(ValueError, int, "0x", 0)
      94  
      95          self.assertRaises(ValueError, int, "0o", 8)
      96          self.assertRaises(ValueError, int, "0o", 0)
      97  
      98          self.assertRaises(ValueError, int, "0b", 2)
      99          self.assertRaises(ValueError, int, "0b", 0)
     100  
     101          # SF bug 1334662: int(string, base) wrong answers
     102          # Various representations of 2**32 evaluated to 0
     103          # rather than 2**32 in previous versions
     104  
     105          self.assertEqual(int('100000000000000000000000000000000', 2), 4294967296)
     106          self.assertEqual(int('102002022201221111211', 3), 4294967296)
     107          self.assertEqual(int('10000000000000000', 4), 4294967296)
     108          self.assertEqual(int('32244002423141', 5), 4294967296)
     109          self.assertEqual(int('1550104015504', 6), 4294967296)
     110          self.assertEqual(int('211301422354', 7), 4294967296)
     111          self.assertEqual(int('40000000000', 8), 4294967296)
     112          self.assertEqual(int('12068657454', 9), 4294967296)
     113          self.assertEqual(int('4294967296', 10), 4294967296)
     114          self.assertEqual(int('1904440554', 11), 4294967296)
     115          self.assertEqual(int('9ba461594', 12), 4294967296)
     116          self.assertEqual(int('535a79889', 13), 4294967296)
     117          self.assertEqual(int('2ca5b7464', 14), 4294967296)
     118          self.assertEqual(int('1a20dcd81', 15), 4294967296)
     119          self.assertEqual(int('100000000', 16), 4294967296)
     120          self.assertEqual(int('a7ffda91', 17), 4294967296)
     121          self.assertEqual(int('704he7g4', 18), 4294967296)
     122          self.assertEqual(int('4f5aff66', 19), 4294967296)
     123          self.assertEqual(int('3723ai4g', 20), 4294967296)
     124          self.assertEqual(int('281d55i4', 21), 4294967296)
     125          self.assertEqual(int('1fj8b184', 22), 4294967296)
     126          self.assertEqual(int('1606k7ic', 23), 4294967296)
     127          self.assertEqual(int('mb994ag', 24), 4294967296)
     128          self.assertEqual(int('hek2mgl', 25), 4294967296)
     129          self.assertEqual(int('dnchbnm', 26), 4294967296)
     130          self.assertEqual(int('b28jpdm', 27), 4294967296)
     131          self.assertEqual(int('8pfgih4', 28), 4294967296)
     132          self.assertEqual(int('76beigg', 29), 4294967296)
     133          self.assertEqual(int('5qmcpqg', 30), 4294967296)
     134          self.assertEqual(int('4q0jto4', 31), 4294967296)
     135          self.assertEqual(int('4000000', 32), 4294967296)
     136          self.assertEqual(int('3aokq94', 33), 4294967296)
     137          self.assertEqual(int('2qhxjli', 34), 4294967296)
     138          self.assertEqual(int('2br45qb', 35), 4294967296)
     139          self.assertEqual(int('1z141z4', 36), 4294967296)
     140  
     141          # tests with base 0
     142          # this fails on 3.0, but in 2.x the old octal syntax is allowed
     143          self.assertEqual(int(' 0o123  ', 0), 83)
     144          self.assertEqual(int(' 0o123  ', 0), 83)
     145          self.assertEqual(int('000', 0), 0)
     146          self.assertEqual(int('0o123', 0), 83)
     147          self.assertEqual(int('0x123', 0), 291)
     148          self.assertEqual(int('0b100', 0), 4)
     149          self.assertEqual(int(' 0O123   ', 0), 83)
     150          self.assertEqual(int(' 0X123  ', 0), 291)
     151          self.assertEqual(int(' 0B100 ', 0), 4)
     152          with self.assertRaises(ValueError):
     153              int('010', 0)
     154  
     155          # without base still base 10
     156          self.assertEqual(int('0123'), 123)
     157          self.assertEqual(int('0123', 10), 123)
     158  
     159          # tests with prefix and base != 0
     160          self.assertEqual(int('0x123', 16), 291)
     161          self.assertEqual(int('0o123', 8), 83)
     162          self.assertEqual(int('0b100', 2), 4)
     163          self.assertEqual(int('0X123', 16), 291)
     164          self.assertEqual(int('0O123', 8), 83)
     165          self.assertEqual(int('0B100', 2), 4)
     166  
     167          # the code has special checks for the first character after the
     168          #  type prefix
     169          self.assertRaises(ValueError, int, '0b2', 2)
     170          self.assertRaises(ValueError, int, '0b02', 2)
     171          self.assertRaises(ValueError, int, '0B2', 2)
     172          self.assertRaises(ValueError, int, '0B02', 2)
     173          self.assertRaises(ValueError, int, '0o8', 8)
     174          self.assertRaises(ValueError, int, '0o08', 8)
     175          self.assertRaises(ValueError, int, '0O8', 8)
     176          self.assertRaises(ValueError, int, '0O08', 8)
     177          self.assertRaises(ValueError, int, '0xg', 16)
     178          self.assertRaises(ValueError, int, '0x0g', 16)
     179          self.assertRaises(ValueError, int, '0Xg', 16)
     180          self.assertRaises(ValueError, int, '0X0g', 16)
     181  
     182          # SF bug 1334662: int(string, base) wrong answers
     183          # Checks for proper evaluation of 2**32 + 1
     184          self.assertEqual(int('100000000000000000000000000000001', 2), 4294967297)
     185          self.assertEqual(int('102002022201221111212', 3), 4294967297)
     186          self.assertEqual(int('10000000000000001', 4), 4294967297)
     187          self.assertEqual(int('32244002423142', 5), 4294967297)
     188          self.assertEqual(int('1550104015505', 6), 4294967297)
     189          self.assertEqual(int('211301422355', 7), 4294967297)
     190          self.assertEqual(int('40000000001', 8), 4294967297)
     191          self.assertEqual(int('12068657455', 9), 4294967297)
     192          self.assertEqual(int('4294967297', 10), 4294967297)
     193          self.assertEqual(int('1904440555', 11), 4294967297)
     194          self.assertEqual(int('9ba461595', 12), 4294967297)
     195          self.assertEqual(int('535a7988a', 13), 4294967297)
     196          self.assertEqual(int('2ca5b7465', 14), 4294967297)
     197          self.assertEqual(int('1a20dcd82', 15), 4294967297)
     198          self.assertEqual(int('100000001', 16), 4294967297)
     199          self.assertEqual(int('a7ffda92', 17), 4294967297)
     200          self.assertEqual(int('704he7g5', 18), 4294967297)
     201          self.assertEqual(int('4f5aff67', 19), 4294967297)
     202          self.assertEqual(int('3723ai4h', 20), 4294967297)
     203          self.assertEqual(int('281d55i5', 21), 4294967297)
     204          self.assertEqual(int('1fj8b185', 22), 4294967297)
     205          self.assertEqual(int('1606k7id', 23), 4294967297)
     206          self.assertEqual(int('mb994ah', 24), 4294967297)
     207          self.assertEqual(int('hek2mgm', 25), 4294967297)
     208          self.assertEqual(int('dnchbnn', 26), 4294967297)
     209          self.assertEqual(int('b28jpdn', 27), 4294967297)
     210          self.assertEqual(int('8pfgih5', 28), 4294967297)
     211          self.assertEqual(int('76beigh', 29), 4294967297)
     212          self.assertEqual(int('5qmcpqh', 30), 4294967297)
     213          self.assertEqual(int('4q0jto5', 31), 4294967297)
     214          self.assertEqual(int('4000001', 32), 4294967297)
     215          self.assertEqual(int('3aokq95', 33), 4294967297)
     216          self.assertEqual(int('2qhxjlj', 34), 4294967297)
     217          self.assertEqual(int('2br45qc', 35), 4294967297)
     218          self.assertEqual(int('1z141z5', 36), 4294967297)
     219  
     220      def test_invalid_signs(self):
     221          with self.assertRaises(ValueError):
     222              int('+')
     223          with self.assertRaises(ValueError):
     224              int('-')
     225          with self.assertRaises(ValueError):
     226              int('- 1')
     227          with self.assertRaises(ValueError):
     228              int('+ 1')
     229          with self.assertRaises(ValueError):
     230              int(' + 1 ')
     231  
     232      def test_unicode(self):
     233          self.assertEqual(int("१२३४५६७८९०1234567890"), 12345678901234567890)
     234          self.assertEqual(int('١٢٣٤٥٦٧٨٩٠'), 1234567890)
     235          self.assertEqual(int("१२३४५६७८९०1234567890", 0), 12345678901234567890)
     236          self.assertEqual(int('١٢٣٤٥٦٧٨٩٠', 0), 1234567890)
     237  
     238      def test_underscores(self):
     239          for lit in VALID_UNDERSCORE_LITERALS:
     240              if any(ch in lit for ch in '.eEjJ'):
     241                  continue
     242              self.assertEqual(int(lit, 0), eval(lit))
     243              self.assertEqual(int(lit, 0), int(lit.replace('_', ''), 0))
     244          for lit in INVALID_UNDERSCORE_LITERALS:
     245              if any(ch in lit for ch in '.eEjJ'):
     246                  continue
     247              self.assertRaises(ValueError, int, lit, 0)
     248          # Additional test cases with bases != 0, only for the constructor:
     249          self.assertEqual(int("1_00", 3), 9)
     250          self.assertEqual(int("0_100"), 100)  # not valid as a literal!
     251          self.assertEqual(int(b"1_00"), 100)  # byte underscore
     252          self.assertRaises(ValueError, int, "_100")
     253          self.assertRaises(ValueError, int, "+_100")
     254          self.assertRaises(ValueError, int, "1__00")
     255          self.assertRaises(ValueError, int, "100_")
     256  
     257      @support.cpython_only
     258      def test_small_ints(self):
     259          # Bug #3236: Return small longs from PyLong_FromString
     260          self.assertIs(int('10'), 10)
     261          self.assertIs(int('-1'), -1)
     262          self.assertIs(int(b'10'), 10)
     263          self.assertIs(int(b'-1'), -1)
     264  
     265      def test_no_args(self):
     266          self.assertEqual(int(), 0)
     267  
     268      def test_keyword_args(self):
     269          # Test invoking int() using keyword arguments.
     270          self.assertEqual(int('100', base=2), 4)
     271          with self.assertRaisesRegex(TypeError, 'keyword argument'):
     272              int(x=1.2)
     273          with self.assertRaisesRegex(TypeError, 'keyword argument'):
     274              int(x='100', base=2)
     275          self.assertRaises(TypeError, int, base=10)
     276          self.assertRaises(TypeError, int, base=0)
     277  
     278      def test_int_base_limits(self):
     279          """Testing the supported limits of the int() base parameter."""
     280          self.assertEqual(int('0', 5), 0)
     281          with self.assertRaises(ValueError):
     282              int('0', 1)
     283          with self.assertRaises(ValueError):
     284              int('0', 37)
     285          with self.assertRaises(ValueError):
     286              int('0', -909)  # An old magic value base from Python 2.
     287          with self.assertRaises(ValueError):
     288              int('0', base=0-(2**234))
     289          with self.assertRaises(ValueError):
     290              int('0', base=2**234)
     291          # Bases 2 through 36 are supported.
     292          for base in range(2,37):
     293              self.assertEqual(int('0', base=base), 0)
     294  
     295      def test_int_base_bad_types(self):
     296          """Not integer types are not valid bases; issue16772."""
     297          with self.assertRaises(TypeError):
     298              int('0', 5.5)
     299          with self.assertRaises(TypeError):
     300              int('0', 5.0)
     301  
     302      def test_int_base_indexable(self):
     303          class ESC[4;38;5;81mMyIndexable(ESC[4;38;5;149mobject):
     304              def __init__(self, value):
     305                  self.value = value
     306              def __index__(self):
     307                  return self.value
     308  
     309          # Check out of range bases.
     310          for base in 2**100, -2**100, 1, 37:
     311              with self.assertRaises(ValueError):
     312                  int('43', base)
     313  
     314          # Check in-range bases.
     315          self.assertEqual(int('101', base=MyIndexable(2)), 5)
     316          self.assertEqual(int('101', base=MyIndexable(10)), 101)
     317          self.assertEqual(int('101', base=MyIndexable(36)), 1 + 36**2)
     318  
     319      def test_non_numeric_input_types(self):
     320          # Test possible non-numeric types for the argument x, including
     321          # subclasses of the explicitly documented accepted types.
     322          class ESC[4;38;5;81mCustomStr(ESC[4;38;5;149mstr): pass
     323          class ESC[4;38;5;81mCustomBytes(ESC[4;38;5;149mbytes): pass
     324          class ESC[4;38;5;81mCustomByteArray(ESC[4;38;5;149mbytearray): pass
     325  
     326          factories = [
     327              bytes,
     328              bytearray,
     329              lambda b: CustomStr(b.decode()),
     330              CustomBytes,
     331              CustomByteArray,
     332              memoryview,
     333          ]
     334          try:
     335              from array import array
     336          except ImportError:
     337              pass
     338          else:
     339              factories.append(lambda b: array('B', b))
     340  
     341          for f in factories:
     342              x = f(b'100')
     343              with self.subTest(type(x)):
     344                  self.assertEqual(int(x), 100)
     345                  if isinstance(x, (str, bytes, bytearray)):
     346                      self.assertEqual(int(x, 2), 4)
     347                  else:
     348                      msg = "can't convert non-string"
     349                      with self.assertRaisesRegex(TypeError, msg):
     350                          int(x, 2)
     351                  with self.assertRaisesRegex(ValueError, 'invalid literal'):
     352                      int(f(b'A' * 0x10))
     353  
     354      def test_int_memoryview(self):
     355          self.assertEqual(int(memoryview(b'123')[1:3]), 23)
     356          self.assertEqual(int(memoryview(b'123\x00')[1:3]), 23)
     357          self.assertEqual(int(memoryview(b'123 ')[1:3]), 23)
     358          self.assertEqual(int(memoryview(b'123A')[1:3]), 23)
     359          self.assertEqual(int(memoryview(b'1234')[1:3]), 23)
     360  
     361      def test_string_float(self):
     362          self.assertRaises(ValueError, int, '1.2')
     363  
     364      def test_intconversion(self):
     365          # Test __int__()
     366          class ESC[4;38;5;81mClassicMissingMethods:
     367              pass
     368          self.assertRaises(TypeError, int, ClassicMissingMethods())
     369  
     370          class ESC[4;38;5;81mMissingMethods(ESC[4;38;5;149mobject):
     371              pass
     372          self.assertRaises(TypeError, int, MissingMethods())
     373  
     374          class ESC[4;38;5;81mFoo0:
     375              def __int__(self):
     376                  return 42
     377  
     378          self.assertEqual(int(Foo0()), 42)
     379  
     380          class ESC[4;38;5;81mClassic:
     381              pass
     382          for base in (object, Classic):
     383              class ESC[4;38;5;81mIntOverridesTrunc(ESC[4;38;5;149mbase):
     384                  def __int__(self):
     385                      return 42
     386                  def __trunc__(self):
     387                      return -12
     388              self.assertEqual(int(IntOverridesTrunc()), 42)
     389  
     390              class ESC[4;38;5;81mJustTrunc(ESC[4;38;5;149mbase):
     391                  def __trunc__(self):
     392                      return 42
     393              with self.assertWarns(DeprecationWarning):
     394                  self.assertEqual(int(JustTrunc()), 42)
     395  
     396              class ESC[4;38;5;81mExceptionalTrunc(ESC[4;38;5;149mbase):
     397                  def __trunc__(self):
     398                      1 / 0
     399              with self.assertRaises(ZeroDivisionError), \
     400                   self.assertWarns(DeprecationWarning):
     401                  int(ExceptionalTrunc())
     402  
     403              for trunc_result_base in (object, Classic):
     404                  class ESC[4;38;5;81mIndex(ESC[4;38;5;149mtrunc_result_base):
     405                      def __index__(self):
     406                          return 42
     407  
     408                  class ESC[4;38;5;81mTruncReturnsNonInt(ESC[4;38;5;149mbase):
     409                      def __trunc__(self):
     410                          return Index()
     411                  with self.assertWarns(DeprecationWarning):
     412                      self.assertEqual(int(TruncReturnsNonInt()), 42)
     413  
     414                  class ESC[4;38;5;81mIntable(ESC[4;38;5;149mtrunc_result_base):
     415                      def __int__(self):
     416                          return 42
     417  
     418                  class ESC[4;38;5;81mTruncReturnsNonIndex(ESC[4;38;5;149mbase):
     419                      def __trunc__(self):
     420                          return Intable()
     421                  with self.assertWarns(DeprecationWarning):
     422                      self.assertEqual(int(TruncReturnsNonInt()), 42)
     423  
     424                  class ESC[4;38;5;81mNonIntegral(ESC[4;38;5;149mtrunc_result_base):
     425                      def __trunc__(self):
     426                          # Check that we avoid infinite recursion.
     427                          return NonIntegral()
     428  
     429                  class ESC[4;38;5;81mTruncReturnsNonIntegral(ESC[4;38;5;149mbase):
     430                      def __trunc__(self):
     431                          return NonIntegral()
     432                  try:
     433                      with self.assertWarns(DeprecationWarning):
     434                          int(TruncReturnsNonIntegral())
     435                  except TypeError as e:
     436                      self.assertEqual(str(e),
     437                                        "__trunc__ returned non-Integral"
     438                                        " (type NonIntegral)")
     439                  else:
     440                      self.fail("Failed to raise TypeError with %s" %
     441                                ((base, trunc_result_base),))
     442  
     443                  # Regression test for bugs.python.org/issue16060.
     444                  class ESC[4;38;5;81mBadInt(ESC[4;38;5;149mtrunc_result_base):
     445                      def __int__(self):
     446                          return 42.0
     447  
     448                  class ESC[4;38;5;81mTruncReturnsBadInt(ESC[4;38;5;149mbase):
     449                      def __trunc__(self):
     450                          return BadInt()
     451  
     452                  with self.assertRaises(TypeError), \
     453                       self.assertWarns(DeprecationWarning):
     454                      int(TruncReturnsBadInt())
     455  
     456      def test_int_subclass_with_index(self):
     457          class ESC[4;38;5;81mMyIndex(ESC[4;38;5;149mint):
     458              def __index__(self):
     459                  return 42
     460  
     461          class ESC[4;38;5;81mBadIndex(ESC[4;38;5;149mint):
     462              def __index__(self):
     463                  return 42.0
     464  
     465          my_int = MyIndex(7)
     466          self.assertEqual(my_int, 7)
     467          self.assertEqual(int(my_int), 7)
     468  
     469          self.assertEqual(int(BadIndex()), 0)
     470  
     471      def test_int_subclass_with_int(self):
     472          class ESC[4;38;5;81mMyInt(ESC[4;38;5;149mint):
     473              def __int__(self):
     474                  return 42
     475  
     476          class ESC[4;38;5;81mBadInt(ESC[4;38;5;149mint):
     477              def __int__(self):
     478                  return 42.0
     479  
     480          my_int = MyInt(7)
     481          self.assertEqual(my_int, 7)
     482          self.assertEqual(int(my_int), 42)
     483  
     484          my_int = BadInt(7)
     485          self.assertEqual(my_int, 7)
     486          self.assertRaises(TypeError, int, my_int)
     487  
     488      def test_int_returns_int_subclass(self):
     489          class ESC[4;38;5;81mBadIndex:
     490              def __index__(self):
     491                  return True
     492  
     493          class ESC[4;38;5;81mBadIndex2(ESC[4;38;5;149mint):
     494              def __index__(self):
     495                  return True
     496  
     497          class ESC[4;38;5;81mBadInt:
     498              def __int__(self):
     499                  return True
     500  
     501          class ESC[4;38;5;81mBadInt2(ESC[4;38;5;149mint):
     502              def __int__(self):
     503                  return True
     504  
     505          class ESC[4;38;5;81mTruncReturnsBadIndex:
     506              def __trunc__(self):
     507                  return BadIndex()
     508  
     509          class ESC[4;38;5;81mTruncReturnsBadInt:
     510              def __trunc__(self):
     511                  return BadInt()
     512  
     513          class ESC[4;38;5;81mTruncReturnsIntSubclass:
     514              def __trunc__(self):
     515                  return True
     516  
     517          bad_int = BadIndex()
     518          with self.assertWarns(DeprecationWarning):
     519              n = int(bad_int)
     520          self.assertEqual(n, 1)
     521          self.assertIs(type(n), int)
     522  
     523          bad_int = BadIndex2()
     524          n = int(bad_int)
     525          self.assertEqual(n, 0)
     526          self.assertIs(type(n), int)
     527  
     528          bad_int = BadInt()
     529          with self.assertWarns(DeprecationWarning):
     530              n = int(bad_int)
     531          self.assertEqual(n, 1)
     532          self.assertIs(type(n), int)
     533  
     534          bad_int = BadInt2()
     535          with self.assertWarns(DeprecationWarning):
     536              n = int(bad_int)
     537          self.assertEqual(n, 1)
     538          self.assertIs(type(n), int)
     539  
     540          bad_int = TruncReturnsBadIndex()
     541          with self.assertWarns(DeprecationWarning):
     542              n = int(bad_int)
     543          self.assertEqual(n, 1)
     544          self.assertIs(type(n), int)
     545  
     546          bad_int = TruncReturnsBadInt()
     547          with self.assertWarns(DeprecationWarning):
     548              self.assertRaises(TypeError, int, bad_int)
     549  
     550          good_int = TruncReturnsIntSubclass()
     551          with self.assertWarns(DeprecationWarning):
     552              n = int(good_int)
     553          self.assertEqual(n, 1)
     554          self.assertIs(type(n), int)
     555          with self.assertWarns(DeprecationWarning):
     556              n = IntSubclass(good_int)
     557          self.assertEqual(n, 1)
     558          self.assertIs(type(n), IntSubclass)
     559  
     560      def test_error_message(self):
     561          def check(s, base=None):
     562              with self.assertRaises(ValueError,
     563                                     msg="int(%r, %r)" % (s, base)) as cm:
     564                  if base is None:
     565                      int(s)
     566                  else:
     567                      int(s, base)
     568              self.assertEqual(cm.exception.args[0],
     569                  "invalid literal for int() with base %d: %r" %
     570                  (10 if base is None else base, s))
     571  
     572          check('\xbd')
     573          check('123\xbd')
     574          check('  123 456  ')
     575  
     576          check('123\x00')
     577          # SF bug 1545497: embedded NULs were not detected with explicit base
     578          check('123\x00', 10)
     579          check('123\x00 245', 20)
     580          check('123\x00 245', 16)
     581          check('123\x00245', 20)
     582          check('123\x00245', 16)
     583          # byte string with embedded NUL
     584          check(b'123\x00')
     585          check(b'123\x00', 10)
     586          # non-UTF-8 byte string
     587          check(b'123\xbd')
     588          check(b'123\xbd', 10)
     589          # lone surrogate in Unicode string
     590          check('123\ud800')
     591          check('123\ud800', 10)
     592  
     593      def test_issue31619(self):
     594          self.assertEqual(int('1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1', 2),
     595                           0b1010101010101010101010101010101)
     596          self.assertEqual(int('1_2_3_4_5_6_7_0_1_2_3', 8), 0o12345670123)
     597          self.assertEqual(int('1_2_3_4_5_6_7_8_9', 16), 0x123456789)
     598          self.assertEqual(int('1_2_3_4_5_6_7', 32), 1144132807)
     599  
     600  
     601  class ESC[4;38;5;81mIntStrDigitLimitsTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     602  
     603      int_class = int  # Override this in subclasses to reuse the suite.
     604  
     605      def setUp(self):
     606          super().setUp()
     607          self._previous_limit = sys.get_int_max_str_digits()
     608          sys.set_int_max_str_digits(2048)
     609  
     610      def tearDown(self):
     611          sys.set_int_max_str_digits(self._previous_limit)
     612          super().tearDown()
     613  
     614      def test_disabled_limit(self):
     615          self.assertGreater(sys.get_int_max_str_digits(), 0)
     616          self.assertLess(sys.get_int_max_str_digits(), 20_000)
     617          with support.adjust_int_max_str_digits(0):
     618              self.assertEqual(sys.get_int_max_str_digits(), 0)
     619              i = self.int_class('1' * 20_000)
     620              str(i)
     621          self.assertGreater(sys.get_int_max_str_digits(), 0)
     622  
     623      def test_max_str_digits_edge_cases(self):
     624          """Ignore the +/- sign and space padding."""
     625          int_class = self.int_class
     626          maxdigits = sys.get_int_max_str_digits()
     627  
     628          int_class('1' * maxdigits)
     629          int_class(' ' + '1' * maxdigits)
     630          int_class('1' * maxdigits + ' ')
     631          int_class('+' + '1' * maxdigits)
     632          int_class('-' + '1' * maxdigits)
     633          self.assertEqual(len(str(10 ** (maxdigits - 1))), maxdigits)
     634  
     635      def check(self, i, base=None):
     636          with self.assertRaises(ValueError):
     637              if base is None:
     638                  self.int_class(i)
     639              else:
     640                  self.int_class(i, base)
     641  
     642      def test_max_str_digits(self):
     643          maxdigits = sys.get_int_max_str_digits()
     644  
     645          self.check('1' * (maxdigits + 1))
     646          self.check(' ' + '1' * (maxdigits + 1))
     647          self.check('1' * (maxdigits + 1) + ' ')
     648          self.check('+' + '1' * (maxdigits + 1))
     649          self.check('-' + '1' * (maxdigits + 1))
     650          self.check('1' * (maxdigits + 1))
     651  
     652          i = 10 ** maxdigits
     653          with self.assertRaises(ValueError):
     654              str(i)
     655  
     656      def test_denial_of_service_prevented_int_to_str(self):
     657          """Regression test: ensure we fail before performing O(N**2) work."""
     658          maxdigits = sys.get_int_max_str_digits()
     659          assert maxdigits < 50_000, maxdigits  # A test prerequisite.
     660          get_time = time.process_time
     661          if get_time() <= 0:  # some platforms like WASM lack process_time()
     662              get_time = time.monotonic
     663  
     664          huge_int = int(f'0x{"c"*65_000}', base=16)  # 78268 decimal digits.
     665          digits = 78_268
     666          with support.adjust_int_max_str_digits(digits):
     667              start = get_time()
     668              huge_decimal = str(huge_int)
     669          seconds_to_convert = get_time() - start
     670          self.assertEqual(len(huge_decimal), digits)
     671          # Ensuring that we chose a slow enough conversion to measure.
     672          # It takes 0.1 seconds on a Zen based cloud VM in an opt build.
     673          # Some OSes have a low res 1/64s timer, skip if hard to measure.
     674          if seconds_to_convert < 1/64:
     675              raise unittest.SkipTest('"slow" conversion took only '
     676                                      f'{seconds_to_convert} seconds.')
     677  
     678          # We test with the limit almost at the size needed to check performance.
     679          # The performant limit check is slightly fuzzy, give it a some room.
     680          with support.adjust_int_max_str_digits(int(.995 * digits)):
     681              with self.assertRaises(ValueError) as err:
     682                  start = get_time()
     683                  str(huge_int)
     684              seconds_to_fail_huge = get_time() - start
     685          self.assertIn('conversion', str(err.exception))
     686          self.assertLessEqual(seconds_to_fail_huge, seconds_to_convert/2)
     687  
     688          # Now we test that a conversion that would take 30x as long also fails
     689          # in a similarly fast fashion.
     690          extra_huge_int = int(f'0x{"c"*500_000}', base=16)  # 602060 digits.
     691          with self.assertRaises(ValueError) as err:
     692              start = get_time()
     693              # If not limited, 8 seconds said Zen based cloud VM.
     694              str(extra_huge_int)
     695          seconds_to_fail_extra_huge = get_time() - start
     696          self.assertIn('conversion', str(err.exception))
     697          self.assertLess(seconds_to_fail_extra_huge, seconds_to_convert/2)
     698  
     699      def test_denial_of_service_prevented_str_to_int(self):
     700          """Regression test: ensure we fail before performing O(N**2) work."""
     701          maxdigits = sys.get_int_max_str_digits()
     702          assert maxdigits < 100_000, maxdigits  # A test prerequisite.
     703          get_time = time.process_time
     704          if get_time() <= 0:  # some platforms like WASM lack process_time()
     705              get_time = time.monotonic
     706  
     707          digits = 133700
     708          huge = '8'*digits
     709          with support.adjust_int_max_str_digits(digits):
     710              start = get_time()
     711              int(huge)
     712          seconds_to_convert = get_time() - start
     713          # Ensuring that we chose a slow enough conversion to measure.
     714          # It takes 0.1 seconds on a Zen based cloud VM in an opt build.
     715          # Some OSes have a low res 1/64s timer, skip if hard to measure.
     716          if seconds_to_convert < 1/64:
     717              raise unittest.SkipTest('"slow" conversion took only '
     718                                      f'{seconds_to_convert} seconds.')
     719  
     720          with support.adjust_int_max_str_digits(digits - 1):
     721              with self.assertRaises(ValueError) as err:
     722                  start = get_time()
     723                  int(huge)
     724              seconds_to_fail_huge = get_time() - start
     725          self.assertIn('conversion', str(err.exception))
     726          self.assertLessEqual(seconds_to_fail_huge, seconds_to_convert/2)
     727  
     728          # Now we test that a conversion that would take 30x as long also fails
     729          # in a similarly fast fashion.
     730          extra_huge = '7'*1_200_000
     731          with self.assertRaises(ValueError) as err:
     732              start = get_time()
     733              # If not limited, 8 seconds in the Zen based cloud VM.
     734              int(extra_huge)
     735          seconds_to_fail_extra_huge = get_time() - start
     736          self.assertIn('conversion', str(err.exception))
     737          self.assertLessEqual(seconds_to_fail_extra_huge, seconds_to_convert/2)
     738  
     739      def test_power_of_two_bases_unlimited(self):
     740          """The limit does not apply to power of 2 bases."""
     741          maxdigits = sys.get_int_max_str_digits()
     742  
     743          for base in (2, 4, 8, 16, 32):
     744              with self.subTest(base=base):
     745                  self.int_class('1' * (maxdigits + 1), base)
     746                  assert maxdigits < 100_000
     747                  self.int_class('1' * 100_000, base)
     748  
     749      def test_underscores_ignored(self):
     750          maxdigits = sys.get_int_max_str_digits()
     751  
     752          triples = maxdigits // 3
     753          s = '111' * triples
     754          s_ = '1_11' * triples
     755          self.int_class(s)  # succeeds
     756          self.int_class(s_)  # succeeds
     757          self.check(f'{s}111')
     758          self.check(f'{s_}_111')
     759  
     760      def test_sign_not_counted(self):
     761          int_class = self.int_class
     762          max_digits = sys.get_int_max_str_digits()
     763          s = '5' * max_digits
     764          i = int_class(s)
     765          pos_i = int_class(f'+{s}')
     766          assert i == pos_i
     767          neg_i = int_class(f'-{s}')
     768          assert -pos_i == neg_i
     769          str(pos_i)
     770          str(neg_i)
     771  
     772      def _other_base_helper(self, base):
     773          int_class = self.int_class
     774          max_digits = sys.get_int_max_str_digits()
     775          s = '2' * max_digits
     776          i = int_class(s, base)
     777          if base > 10:
     778              with self.assertRaises(ValueError):
     779                  str(i)
     780          elif base < 10:
     781              str(i)
     782          with self.assertRaises(ValueError) as err:
     783              int_class(f'{s}1', base)
     784  
     785      def test_int_from_other_bases(self):
     786          base = 3
     787          with self.subTest(base=base):
     788              self._other_base_helper(base)
     789          base = 36
     790          with self.subTest(base=base):
     791              self._other_base_helper(base)
     792  
     793  
     794  class ESC[4;38;5;81mIntSubclassStrDigitLimitsTests(ESC[4;38;5;149mIntStrDigitLimitsTests):
     795      int_class = IntSubclass
     796  
     797  
     798  if __name__ == "__main__":
     799      unittest.main()