summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrandt Bucher <brandt@python.org>2022-01-16 16:06:37 (GMT)
committerGitHub <noreply@github.com>2022-01-16 16:06:37 (GMT)
commit5cd9a162cd02a3d0f1b0a182d80feeb17439e84f (patch)
tree3a80de2f3551e23f85f4c63200e5ecd844dfa374
parent09087b8519316608b85131ee7455b664c00c38d2 (diff)
downloadcpython-5cd9a162cd02a3d0f1b0a182d80feeb17439e84f.zip
cpython-5cd9a162cd02a3d0f1b0a182d80feeb17439e84f.tar.gz
cpython-5cd9a162cd02a3d0f1b0a182d80feeb17439e84f.tar.bz2
bpo-46361: Fix "small" `int` caching (GH-30583)
-rw-r--r--Lib/test/test_decimal.py7
-rw-r--r--Lib/test/test_long.py7
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2022-01-12-17-15-17.bpo-46361.mgI_j_.rst2
-rw-r--r--Modules/_decimal/_decimal.c7
-rw-r--r--Objects/longobject.c2
5 files changed, 24 insertions, 1 deletions
diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py
index b6173a5..9ced801 100644
--- a/Lib/test/test_decimal.py
+++ b/Lib/test/test_decimal.py
@@ -2552,6 +2552,13 @@ class PythonAPItests(unittest.TestCase):
self.assertRaises(OverflowError, int, Decimal('inf'))
self.assertRaises(OverflowError, int, Decimal('-inf'))
+ @cpython_only
+ def test_small_ints(self):
+ Decimal = self.decimal.Decimal
+ # bpo-46361
+ for x in range(-5, 257):
+ self.assertIs(int(Decimal(x)), x)
+
def test_trunc(self):
Decimal = self.decimal.Decimal
diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py
index f2a622b..c7dd0b2 100644
--- a/Lib/test/test_long.py
+++ b/Lib/test/test_long.py
@@ -1471,6 +1471,13 @@ class LongTest(unittest.TestCase):
self.assertEqual(i, 1)
self.assertEqual(getattr(i, 'foo', 'none'), 'bar')
+ @support.cpython_only
+ def test_from_bytes_small(self):
+ # bpo-46361
+ for i in range(-5, 257):
+ b = i.to_bytes(2, signed=True)
+ self.assertIs(int.from_bytes(b, signed=True), i)
+
def test_access_to_nonexistent_digit_0(self):
# http://bugs.python.org/issue14630: A bug in _PyLong_Copy meant that
# ob_digit[0] was being incorrectly accessed for instances of a
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-01-12-17-15-17.bpo-46361.mgI_j_.rst b/Misc/NEWS.d/next/Core and Builtins/2022-01-12-17-15-17.bpo-46361.mgI_j_.rst
new file mode 100644
index 0000000..eef877d
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-01-12-17-15-17.bpo-46361.mgI_j_.rst
@@ -0,0 +1,2 @@
+Ensure that "small" integers created by :meth:`int.from_bytes` and
+:class:`decimal.Decimal` are properly cached.
diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c
index 7fc7315..35a1156 100644
--- a/Modules/_decimal/_decimal.c
+++ b/Modules/_decimal/_decimal.c
@@ -3394,6 +3394,13 @@ dec_as_long(PyObject *dec, PyObject *context, int round)
return NULL;
}
+ if (n == 1) {
+ sdigit val = mpd_arith_sign(x) * ob_digit[0];
+ mpd_free(ob_digit);
+ mpd_del(x);
+ return PyLong_FromLong(val);
+ }
+
assert(n > 0);
pylong = _PyLong_New(n);
if (pylong == NULL) {
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 5d181aa..1b2d126 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -911,7 +911,7 @@ _PyLong_FromByteArray(const unsigned char* bytes, size_t n,
}
Py_SET_SIZE(v, is_signed ? -idigit : idigit);
- return (PyObject *)long_normalize(v);
+ return (PyObject *)maybe_small_long(long_normalize(v));
}
int