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