1import sys
2
3import unittest
4from test import support
5from test.test_grammar import (VALID_UNDERSCORE_LITERALS,
6                               INVALID_UNDERSCORE_LITERALS)
7
8L = [
9        ('0', 0),
10        ('1', 1),
11        ('9', 9),
12        ('10', 10),
13        ('99', 99),
14        ('100', 100),
15        ('314', 314),
16        (' 314', 314),
17        ('314 ', 314),
18        ('  \t\t  314  \t\t  ', 314),
19        (repr(sys.maxsize), sys.maxsize),
20        ('  1x', ValueError),
21        ('  1  ', 1),
22        ('  1\02  ', ValueError),
23        ('', ValueError),
24        (' ', ValueError),
25        ('  \t\t  ', ValueError),
26        ("\u0200", ValueError)
27]
28
29class IntSubclass(int):
30    pass
31
32class IntTestCases(unittest.TestCase):
33
34    def test_basic(self):
35        self.assertEqual(int(314), 314)
36        self.assertEqual(int(3.14), 3)
37        # Check that conversion from float truncates towards zero
38        self.assertEqual(int(-3.14), -3)
39        self.assertEqual(int(3.9), 3)
40        self.assertEqual(int(-3.9), -3)
41        self.assertEqual(int(3.5), 3)
42        self.assertEqual(int(-3.5), -3)
43        self.assertEqual(int("-3"), -3)
44        self.assertEqual(int(" -3 "), -3)
45        self.assertEqual(int("\N{EM SPACE}-3\N{EN SPACE}"), -3)
46        # Different base:
47        self.assertEqual(int("10",16), 16)
48        # Test conversion from strings and various anomalies
49        for s, v in L:
50            for sign in "", "+", "-":
51                for prefix in "", " ", "\t", "  \t\t  ":
52                    ss = prefix + sign + s
53                    vv = v
54                    if sign == "-" and v is not ValueError:
55                        vv = -v
56                    try:
57                        self.assertEqual(int(ss), vv)
58                    except ValueError:
59                        pass
60
61        s = repr(-1-sys.maxsize)
62        x = int(s)
63        self.assertEqual(x+1, -sys.maxsize)
64        self.assertIsInstance(x, int)
65        # should return int
66        self.assertEqual(int(s[1:]), sys.maxsize+1)
67
68        # should return int
69        x = int(1e100)
70        self.assertIsInstance(x, int)
71        x = int(-1e100)
72        self.assertIsInstance(x, int)
73
74
75        # SF bug 434186:  0x80000000/2 != 0x80000000>>1.
76        # Worked by accident in Windows release build, but failed in debug build.
77        # Failed in all Linux builds.
78        x = -1-sys.maxsize
79        self.assertEqual(x >> 1, x//2)
80
81        x = int('1' * 600)
82        self.assertIsInstance(x, int)
83
84
85        self.assertRaises(TypeError, int, 1, 12)
86
87        self.assertEqual(int('0o123', 0), 83)
88        self.assertEqual(int('0x123', 16), 291)
89
90        # Bug 1679: "0x" is not a valid hex literal
91        self.assertRaises(ValueError, int, "0x", 16)
92        self.assertRaises(ValueError, int, "0x", 0)
93
94        self.assertRaises(ValueError, int, "0o", 8)
95        self.assertRaises(ValueError, int, "0o", 0)
96
97        self.assertRaises(ValueError, int, "0b", 2)
98        self.assertRaises(ValueError, int, "0b", 0)
99
100        # SF bug 1334662: int(string, base) wrong answers
101        # Various representations of 2**32 evaluated to 0
102        # rather than 2**32 in previous versions
103
104        self.assertEqual(int('100000000000000000000000000000000', 2), 4294967296)
105        self.assertEqual(int('102002022201221111211', 3), 4294967296)
106        self.assertEqual(int('10000000000000000', 4), 4294967296)
107        self.assertEqual(int('32244002423141', 5), 4294967296)
108        self.assertEqual(int('1550104015504', 6), 4294967296)
109        self.assertEqual(int('211301422354', 7), 4294967296)
110        self.assertEqual(int('40000000000', 8), 4294967296)
111        self.assertEqual(int('12068657454', 9), 4294967296)
112        self.assertEqual(int('4294967296', 10), 4294967296)
113        self.assertEqual(int('1904440554', 11), 4294967296)
114        self.assertEqual(int('9ba461594', 12), 4294967296)
115        self.assertEqual(int('535a79889', 13), 4294967296)
116        self.assertEqual(int('2ca5b7464', 14), 4294967296)
117        self.assertEqual(int('1a20dcd81', 15), 4294967296)
118        self.assertEqual(int('100000000', 16), 4294967296)
119        self.assertEqual(int('a7ffda91', 17), 4294967296)
120        self.assertEqual(int('704he7g4', 18), 4294967296)
121        self.assertEqual(int('4f5aff66', 19), 4294967296)
122        self.assertEqual(int('3723ai4g', 20), 4294967296)
123        self.assertEqual(int('281d55i4', 21), 4294967296)
124        self.assertEqual(int('1fj8b184', 22), 4294967296)
125        self.assertEqual(int('1606k7ic', 23), 4294967296)
126        self.assertEqual(int('mb994ag', 24), 4294967296)
127        self.assertEqual(int('hek2mgl', 25), 4294967296)
128        self.assertEqual(int('dnchbnm', 26), 4294967296)
129        self.assertEqual(int('b28jpdm', 27), 4294967296)
130        self.assertEqual(int('8pfgih4', 28), 4294967296)
131        self.assertEqual(int('76beigg', 29), 4294967296)
132        self.assertEqual(int('5qmcpqg', 30), 4294967296)
133        self.assertEqual(int('4q0jto4', 31), 4294967296)
134        self.assertEqual(int('4000000', 32), 4294967296)
135        self.assertEqual(int('3aokq94', 33), 4294967296)
136        self.assertEqual(int('2qhxjli', 34), 4294967296)
137        self.assertEqual(int('2br45qb', 35), 4294967296)
138        self.assertEqual(int('1z141z4', 36), 4294967296)
139
140        # tests with base 0
141        # this fails on 3.0, but in 2.x the old octal syntax is allowed
142        self.assertEqual(int(' 0o123  ', 0), 83)
143        self.assertEqual(int(' 0o123  ', 0), 83)
144        self.assertEqual(int('000', 0), 0)
145        self.assertEqual(int('0o123', 0), 83)
146        self.assertEqual(int('0x123', 0), 291)
147        self.assertEqual(int('0b100', 0), 4)
148        self.assertEqual(int(' 0O123   ', 0), 83)
149        self.assertEqual(int(' 0X123  ', 0), 291)
150        self.assertEqual(int(' 0B100 ', 0), 4)
151
152        # without base still base 10
153        self.assertEqual(int('0123'), 123)
154        self.assertEqual(int('0123', 10), 123)
155
156        # tests with prefix and base != 0
157        self.assertEqual(int('0x123', 16), 291)
158        self.assertEqual(int('0o123', 8), 83)
159        self.assertEqual(int('0b100', 2), 4)
160        self.assertEqual(int('0X123', 16), 291)
161        self.assertEqual(int('0O123', 8), 83)
162        self.assertEqual(int('0B100', 2), 4)
163
164        # the code has special checks for the first character after the
165        #  type prefix
166        self.assertRaises(ValueError, int, '0b2', 2)
167        self.assertRaises(ValueError, int, '0b02', 2)
168        self.assertRaises(ValueError, int, '0B2', 2)
169        self.assertRaises(ValueError, int, '0B02', 2)
170        self.assertRaises(ValueError, int, '0o8', 8)
171        self.assertRaises(ValueError, int, '0o08', 8)
172        self.assertRaises(ValueError, int, '0O8', 8)
173        self.assertRaises(ValueError, int, '0O08', 8)
174        self.assertRaises(ValueError, int, '0xg', 16)
175        self.assertRaises(ValueError, int, '0x0g', 16)
176        self.assertRaises(ValueError, int, '0Xg', 16)
177        self.assertRaises(ValueError, int, '0X0g', 16)
178
179        # SF bug 1334662: int(string, base) wrong answers
180        # Checks for proper evaluation of 2**32 + 1
181        self.assertEqual(int('100000000000000000000000000000001', 2), 4294967297)
182        self.assertEqual(int('102002022201221111212', 3), 4294967297)
183        self.assertEqual(int('10000000000000001', 4), 4294967297)
184        self.assertEqual(int('32244002423142', 5), 4294967297)
185        self.assertEqual(int('1550104015505', 6), 4294967297)
186        self.assertEqual(int('211301422355', 7), 4294967297)
187        self.assertEqual(int('40000000001', 8), 4294967297)
188        self.assertEqual(int('12068657455', 9), 4294967297)
189        self.assertEqual(int('4294967297', 10), 4294967297)
190        self.assertEqual(int('1904440555', 11), 4294967297)
191        self.assertEqual(int('9ba461595', 12), 4294967297)
192        self.assertEqual(int('535a7988a', 13), 4294967297)
193        self.assertEqual(int('2ca5b7465', 14), 4294967297)
194        self.assertEqual(int('1a20dcd82', 15), 4294967297)
195        self.assertEqual(int('100000001', 16), 4294967297)
196        self.assertEqual(int('a7ffda92', 17), 4294967297)
197        self.assertEqual(int('704he7g5', 18), 4294967297)
198        self.assertEqual(int('4f5aff67', 19), 4294967297)
199        self.assertEqual(int('3723ai4h', 20), 4294967297)
200        self.assertEqual(int('281d55i5', 21), 4294967297)
201        self.assertEqual(int('1fj8b185', 22), 4294967297)
202        self.assertEqual(int('1606k7id', 23), 4294967297)
203        self.assertEqual(int('mb994ah', 24), 4294967297)
204        self.assertEqual(int('hek2mgm', 25), 4294967297)
205        self.assertEqual(int('dnchbnn', 26), 4294967297)
206        self.assertEqual(int('b28jpdn', 27), 4294967297)
207        self.assertEqual(int('8pfgih5', 28), 4294967297)
208        self.assertEqual(int('76beigh', 29), 4294967297)
209        self.assertEqual(int('5qmcpqh', 30), 4294967297)
210        self.assertEqual(int('4q0jto5', 31), 4294967297)
211        self.assertEqual(int('4000001', 32), 4294967297)
212        self.assertEqual(int('3aokq95', 33), 4294967297)
213        self.assertEqual(int('2qhxjlj', 34), 4294967297)
214        self.assertEqual(int('2br45qc', 35), 4294967297)
215        self.assertEqual(int('1z141z5', 36), 4294967297)
216
217    def test_underscores(self):
218        for lit in VALID_UNDERSCORE_LITERALS:
219            if any(ch in lit for ch in '.eEjJ'):
220                continue
221            self.assertEqual(int(lit, 0), eval(lit))
222            self.assertEqual(int(lit, 0), int(lit.replace('_', ''), 0))
223        for lit in INVALID_UNDERSCORE_LITERALS:
224            if any(ch in lit for ch in '.eEjJ'):
225                continue
226            self.assertRaises(ValueError, int, lit, 0)
227        # Additional test cases with bases != 0, only for the constructor:
228        self.assertEqual(int("1_00", 3), 9)
229        self.assertEqual(int("0_100"), 100)  # not valid as a literal!
230        self.assertEqual(int(b"1_00"), 100)  # byte underscore
231        self.assertRaises(ValueError, int, "_100")
232        self.assertRaises(ValueError, int, "+_100")
233        self.assertRaises(ValueError, int, "1__00")
234        self.assertRaises(ValueError, int, "100_")
235
236    @support.cpython_only
237    def test_small_ints(self):
238        # Bug #3236: Return small longs from PyLong_FromString
239        self.assertIs(int('10'), 10)
240        self.assertIs(int('-1'), -1)
241        self.assertIs(int(b'10'), 10)
242        self.assertIs(int(b'-1'), -1)
243
244    def test_no_args(self):
245        self.assertEqual(int(), 0)
246
247    def test_keyword_args(self):
248        # Test invoking int() using keyword arguments.
249        self.assertEqual(int('100', base=2), 4)
250        with self.assertRaisesRegex(TypeError, 'keyword argument'):
251            int(x=1.2)
252        with self.assertRaisesRegex(TypeError, 'keyword argument'):
253            int(x='100', base=2)
254        self.assertRaises(TypeError, int, base=10)
255        self.assertRaises(TypeError, int, base=0)
256
257    def test_int_base_limits(self):
258        """Testing the supported limits of the int() base parameter."""
259        self.assertEqual(int('0', 5), 0)
260        with self.assertRaises(ValueError):
261            int('0', 1)
262        with self.assertRaises(ValueError):
263            int('0', 37)
264        with self.assertRaises(ValueError):
265            int('0', -909)  # An old magic value base from Python 2.
266        with self.assertRaises(ValueError):
267            int('0', base=0-(2**234))
268        with self.assertRaises(ValueError):
269            int('0', base=2**234)
270        # Bases 2 through 36 are supported.
271        for base in range(2,37):
272            self.assertEqual(int('0', base=base), 0)
273
274    def test_int_base_bad_types(self):
275        """Not integer types are not valid bases; issue16772."""
276        with self.assertRaises(TypeError):
277            int('0', 5.5)
278        with self.assertRaises(TypeError):
279            int('0', 5.0)
280
281    def test_int_base_indexable(self):
282        class MyIndexable(object):
283            def __init__(self, value):
284                self.value = value
285            def __index__(self):
286                return self.value
287
288        # Check out of range bases.
289        for base in 2**100, -2**100, 1, 37:
290            with self.assertRaises(ValueError):
291                int('43', base)
292
293        # Check in-range bases.
294        self.assertEqual(int('101', base=MyIndexable(2)), 5)
295        self.assertEqual(int('101', base=MyIndexable(10)), 101)
296        self.assertEqual(int('101', base=MyIndexable(36)), 1 + 36**2)
297
298    def test_non_numeric_input_types(self):
299        # Test possible non-numeric types for the argument x, including
300        # subclasses of the explicitly documented accepted types.
301        class CustomStr(str): pass
302        class CustomBytes(bytes): pass
303        class CustomByteArray(bytearray): pass
304
305        factories = [
306            bytes,
307            bytearray,
308            lambda b: CustomStr(b.decode()),
309            CustomBytes,
310            CustomByteArray,
311            memoryview,
312        ]
313        try:
314            from array import array
315        except ImportError:
316            pass
317        else:
318            factories.append(lambda b: array('B', b))
319
320        for f in factories:
321            x = f(b'100')
322            with self.subTest(type(x)):
323                self.assertEqual(int(x), 100)
324                if isinstance(x, (str, bytes, bytearray)):
325                    self.assertEqual(int(x, 2), 4)
326                else:
327                    msg = "can't convert non-string"
328                    with self.assertRaisesRegex(TypeError, msg):
329                        int(x, 2)
330                with self.assertRaisesRegex(ValueError, 'invalid literal'):
331                    int(f(b'A' * 0x10))
332
333    def test_int_memoryview(self):
334        self.assertEqual(int(memoryview(b'123')[1:3]), 23)
335        self.assertEqual(int(memoryview(b'123\x00')[1:3]), 23)
336        self.assertEqual(int(memoryview(b'123 ')[1:3]), 23)
337        self.assertEqual(int(memoryview(b'123A')[1:3]), 23)
338        self.assertEqual(int(memoryview(b'1234')[1:3]), 23)
339
340    def test_string_float(self):
341        self.assertRaises(ValueError, int, '1.2')
342
343    def test_intconversion(self):
344        # Test __int__()
345        class ClassicMissingMethods:
346            pass
347        self.assertRaises(TypeError, int, ClassicMissingMethods())
348
349        class MissingMethods(object):
350            pass
351        self.assertRaises(TypeError, int, MissingMethods())
352
353        class Foo0:
354            def __int__(self):
355                return 42
356
357        self.assertEqual(int(Foo0()), 42)
358
359        class Classic:
360            pass
361        for base in (object, Classic):
362            class IntOverridesTrunc(base):
363                def __int__(self):
364                    return 42
365                def __trunc__(self):
366                    return -12
367            self.assertEqual(int(IntOverridesTrunc()), 42)
368
369            class JustTrunc(base):
370                def __trunc__(self):
371                    return 42
372            self.assertEqual(int(JustTrunc()), 42)
373
374            class ExceptionalTrunc(base):
375                def __trunc__(self):
376                    1 / 0
377            with self.assertRaises(ZeroDivisionError):
378                int(ExceptionalTrunc())
379
380            for trunc_result_base in (object, Classic):
381                class Index(trunc_result_base):
382                    def __index__(self):
383                        return 42
384
385                class TruncReturnsNonInt(base):
386                    def __trunc__(self):
387                        return Index()
388                self.assertEqual(int(TruncReturnsNonInt()), 42)
389
390                class Intable(trunc_result_base):
391                    def __int__(self):
392                        return 42
393
394                class TruncReturnsNonIndex(base):
395                    def __trunc__(self):
396                        return Intable()
397                self.assertEqual(int(TruncReturnsNonInt()), 42)
398
399                class NonIntegral(trunc_result_base):
400                    def __trunc__(self):
401                        # Check that we avoid infinite recursion.
402                        return NonIntegral()
403
404                class TruncReturnsNonIntegral(base):
405                    def __trunc__(self):
406                        return NonIntegral()
407                try:
408                    int(TruncReturnsNonIntegral())
409                except TypeError as e:
410                    self.assertEqual(str(e),
411                                      "__trunc__ returned non-Integral"
412                                      " (type NonIntegral)")
413                else:
414                    self.fail("Failed to raise TypeError with %s" %
415                              ((base, trunc_result_base),))
416
417                # Regression test for bugs.python.org/issue16060.
418                class BadInt(trunc_result_base):
419                    def __int__(self):
420                        return 42.0
421
422                class TruncReturnsBadInt(base):
423                    def __trunc__(self):
424                        return BadInt()
425
426                with self.assertRaises(TypeError):
427                    int(TruncReturnsBadInt())
428
429    def test_int_subclass_with_index(self):
430        class MyIndex(int):
431            def __index__(self):
432                return 42
433
434        class BadIndex(int):
435            def __index__(self):
436                return 42.0
437
438        my_int = MyIndex(7)
439        self.assertEqual(my_int, 7)
440        self.assertEqual(int(my_int), 7)
441
442        self.assertEqual(int(BadIndex()), 0)
443
444    def test_int_subclass_with_int(self):
445        class MyInt(int):
446            def __int__(self):
447                return 42
448
449        class BadInt(int):
450            def __int__(self):
451                return 42.0
452
453        my_int = MyInt(7)
454        self.assertEqual(my_int, 7)
455        self.assertEqual(int(my_int), 42)
456
457        my_int = BadInt(7)
458        self.assertEqual(my_int, 7)
459        self.assertRaises(TypeError, int, my_int)
460
461    def test_int_returns_int_subclass(self):
462        class BadIndex:
463            def __index__(self):
464                return True
465
466        class BadIndex2(int):
467            def __index__(self):
468                return True
469
470        class BadInt:
471            def __int__(self):
472                return True
473
474        class BadInt2(int):
475            def __int__(self):
476                return True
477
478        class TruncReturnsBadIndex:
479            def __trunc__(self):
480                return BadIndex()
481
482        class TruncReturnsBadInt:
483            def __trunc__(self):
484                return BadInt()
485
486        class TruncReturnsIntSubclass:
487            def __trunc__(self):
488                return True
489
490        bad_int = BadIndex()
491        with self.assertWarns(DeprecationWarning):
492            n = int(bad_int)
493        self.assertEqual(n, 1)
494        self.assertIs(type(n), int)
495
496        bad_int = BadIndex2()
497        n = int(bad_int)
498        self.assertEqual(n, 0)
499        self.assertIs(type(n), int)
500
501        bad_int = BadInt()
502        with self.assertWarns(DeprecationWarning):
503            n = int(bad_int)
504        self.assertEqual(n, 1)
505        self.assertIs(type(n), int)
506
507        bad_int = BadInt2()
508        with self.assertWarns(DeprecationWarning):
509            n = int(bad_int)
510        self.assertEqual(n, 1)
511        self.assertIs(type(n), int)
512
513        bad_int = TruncReturnsBadIndex()
514        with self.assertWarns(DeprecationWarning):
515            n = int(bad_int)
516        self.assertEqual(n, 1)
517        self.assertIs(type(n), int)
518
519        bad_int = TruncReturnsBadInt()
520        with self.assertWarns(DeprecationWarning):
521            n = int(bad_int)
522        self.assertEqual(n, 1)
523        self.assertIs(type(n), int)
524
525        good_int = TruncReturnsIntSubclass()
526        n = int(good_int)
527        self.assertEqual(n, 1)
528        self.assertIs(type(n), int)
529        n = IntSubclass(good_int)
530        self.assertEqual(n, 1)
531        self.assertIs(type(n), IntSubclass)
532
533    def test_error_message(self):
534        def check(s, base=None):
535            with self.assertRaises(ValueError,
536                                   msg="int(%r, %r)" % (s, base)) as cm:
537                if base is None:
538                    int(s)
539                else:
540                    int(s, base)
541            self.assertEqual(cm.exception.args[0],
542                "invalid literal for int() with base %d: %r" %
543                (10 if base is None else base, s))
544
545        check('\xbd')
546        check('123\xbd')
547        check('  123 456  ')
548
549        check('123\x00')
550        # SF bug 1545497: embedded NULs were not detected with explicit base
551        check('123\x00', 10)
552        check('123\x00 245', 20)
553        check('123\x00 245', 16)
554        check('123\x00245', 20)
555        check('123\x00245', 16)
556        # byte string with embedded NUL
557        check(b'123\x00')
558        check(b'123\x00', 10)
559        # non-UTF-8 byte string
560        check(b'123\xbd')
561        check(b'123\xbd', 10)
562        # lone surrogate in Unicode string
563        check('123\ud800')
564        check('123\ud800', 10)
565
566    def test_issue31619(self):
567        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),
568                         0b1010101010101010101010101010101)
569        self.assertEqual(int('1_2_3_4_5_6_7_0_1_2_3', 8), 0o12345670123)
570        self.assertEqual(int('1_2_3_4_5_6_7_8_9', 16), 0x123456789)
571        self.assertEqual(int('1_2_3_4_5_6_7', 32), 1144132807)
572
573
574if __name__ == "__main__":
575    unittest.main()
576