Skip to content

Commit 5cd9a16

Browse files
authored
bpo-46361: Fix "small" int caching (GH-30583)
1 parent 09087b8 commit 5cd9a16

File tree

5 files changed

+24
-1
lines changed

5 files changed

+24
-1
lines changed

Lib/test/test_decimal.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2552,6 +2552,13 @@ def test_int(self):
25522552
self.assertRaises(OverflowError, int, Decimal('inf'))
25532553
self.assertRaises(OverflowError, int, Decimal('-inf'))
25542554

2555+
@cpython_only
2556+
def test_small_ints(self):
2557+
Decimal = self.decimal.Decimal
2558+
# bpo-46361
2559+
for x in range(-5, 257):
2560+
self.assertIs(int(Decimal(x)), x)
2561+
25552562
def test_trunc(self):
25562563
Decimal = self.decimal.Decimal
25572564

Lib/test/test_long.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1471,6 +1471,13 @@ def __init__(self, value):
14711471
self.assertEqual(i, 1)
14721472
self.assertEqual(getattr(i, 'foo', 'none'), 'bar')
14731473

1474+
@support.cpython_only
1475+
def test_from_bytes_small(self):
1476+
# bpo-46361
1477+
for i in range(-5, 257):
1478+
b = i.to_bytes(2, signed=True)
1479+
self.assertIs(int.from_bytes(b, signed=True), i)
1480+
14741481
def test_access_to_nonexistent_digit_0(self):
14751482
# http://bugs.python.org/issue14630: A bug in _PyLong_Copy meant that
14761483
# ob_digit[0] was being incorrectly accessed for instances of a
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Ensure that "small" integers created by :meth:`int.from_bytes` and
2+
:class:`decimal.Decimal` are properly cached.

Modules/_decimal/_decimal.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3394,6 +3394,13 @@ dec_as_long(PyObject *dec, PyObject *context, int round)
33943394
return NULL;
33953395
}
33963396

3397+
if (n == 1) {
3398+
sdigit val = mpd_arith_sign(x) * ob_digit[0];
3399+
mpd_free(ob_digit);
3400+
mpd_del(x);
3401+
return PyLong_FromLong(val);
3402+
}
3403+
33973404
assert(n > 0);
33983405
pylong = _PyLong_New(n);
33993406
if (pylong == NULL) {

Objects/longobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -911,7 +911,7 @@ _PyLong_FromByteArray(const unsigned char* bytes, size_t n,
911911
}
912912

913913
Py_SET_SIZE(v, is_signed ? -idigit : idigit);
914-
return (PyObject *)long_normalize(v);
914+
return (PyObject *)maybe_small_long(long_normalize(v));
915915
}
916916

917917
int

0 commit comments

Comments
 (0)