diff options
author | Brandt Bucher <brandt@python.org> | 2022-01-16 16:06:37 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-16 16:06:37 (GMT) |
commit | 5cd9a162cd02a3d0f1b0a182d80feeb17439e84f (patch) | |
tree | 3a80de2f3551e23f85f4c63200e5ecd844dfa374 | |
parent | 09087b8519316608b85131ee7455b664c00c38d2 (diff) | |
download | cpython-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.py | 7 | ||||
-rw-r--r-- | Lib/test/test_long.py | 7 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2022-01-12-17-15-17.bpo-46361.mgI_j_.rst | 2 | ||||
-rw-r--r-- | Modules/_decimal/_decimal.c | 7 | ||||
-rw-r--r-- | Objects/longobject.c | 2 |
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 |