Skip to content

Commit 4e0ce82

Browse files
authored
Revert "bpo-26680: Incorporate is_integer in all built-in and standard library numeric types (GH-6121)" (GH-22584)
This reverts commit 58a7da9.
1 parent 4f3c250 commit 4e0ce82

16 files changed

+24
-223
lines changed

Doc/library/decimal.rst

-14
Original file line numberDiff line numberDiff line change
@@ -621,13 +621,6 @@ Decimal objects
621621
Return :const:`True` if the argument is either positive or negative
622622
infinity and :const:`False` otherwise.
623623

624-
.. method:: is_integer()
625-
626-
Return :const:`True` if the argument is a finite integral value and
627-
:const:`False` otherwise.
628-
629-
.. versionadded:: 3.10
630-
631624
.. method:: is_nan()
632625

633626
Return :const:`True` if the argument is a (quiet or signaling) NaN and
@@ -1222,13 +1215,6 @@ In addition to the three supplied contexts, new contexts can be created with the
12221215
Returns ``True`` if *x* is infinite; otherwise returns ``False``.
12231216

12241217

1225-
.. method:: is_integer(x)
1226-
1227-
Returns ``True`` if *x* is finite and integral; otherwise
1228-
returns ``False``.
1229-
1230-
.. versionadded:: 3.10
1231-
12321218
.. method:: is_nan(x)
12331219

12341220
Returns ``True`` if *x* is a qNaN or sNaN; otherwise returns ``False``.

Doc/library/numbers.rst

+7-19
Original file line numberDiff line numberDiff line change
@@ -49,30 +49,19 @@ The numeric tower
4949
numbers.
5050

5151
In short, those are: a conversion to :class:`float`, :func:`math.trunc`,
52-
:func:`round`, :func:`math.floor`, :func:`math.ceil`, :func:`divmod`,
53-
:func:`~Real.is_integer`, ``//``, ``%``, ``<``, ``<=``, ``>``, and ``>=``.
52+
:func:`round`, :func:`math.floor`, :func:`math.ceil`, :func:`divmod`, ``//``,
53+
``%``, ``<``, ``<=``, ``>``, and ``>=``.
5454

5555
Real also provides defaults for :func:`complex`, :attr:`~Complex.real`,
5656
:attr:`~Complex.imag`, and :meth:`~Complex.conjugate`.
5757

58-
.. method:: is_integer()
59-
60-
Returns :const:`True` if this number has a finite and integral value,
61-
otherwise :const:`False`. This is a default implementation which
62-
relies on successful conversion to :class:`int`. It may be overridden
63-
in subclasses (such as it is in :class:`float`) for better performance,
64-
or to handle special values such as NaN which are not
65-
convertible to :class:`int`.
66-
67-
.. versionadded:: 3.10
68-
6958

7059
.. class:: Rational
7160

7261
Subtypes :class:`Real` and adds
7362
:attr:`~Rational.numerator` and :attr:`~Rational.denominator` properties, which
74-
should be in lowest terms. With these, it provides defaults for
75-
:func:`float` and :func:`~Real.is_integer`.
63+
should be in lowest terms. With these, it provides a default for
64+
:func:`float`.
7665

7766
.. attribute:: numerator
7867

@@ -86,10 +75,9 @@ The numeric tower
8675
.. class:: Integral
8776

8877
Subtypes :class:`Rational` and adds a conversion to :class:`int`. Provides
89-
defaults for :func:`float`, :attr:`~Rational.numerator`,
90-
:attr:`~Rational.denominator`, and :func:`~Real.is_integer`. Adds abstract
91-
methods for ``**`` and bit-string operations: ``<<``, ``>>``, ``&``, ``^``,
92-
``|``, ``~``.
78+
defaults for :func:`float`, :attr:`~Rational.numerator`, and
79+
:attr:`~Rational.denominator`. Adds abstract methods for ``**`` and
80+
bit-string operations: ``<<``, ``>>``, ``&``, ``^``, ``|``, ``~``.
9381

9482

9583
Notes for type implementors

Doc/library/stdtypes.rst

+10-4
Original file line numberDiff line numberDiff line change
@@ -310,10 +310,6 @@ the operations, see :ref:`operator-summary`):
310310
+---------------------+---------------------------------+---------+--------------------+
311311
| ``x ** y`` | *x* to the power *y* | \(5) | |
312312
+---------------------+---------------------------------+---------+--------------------+
313-
| ``x.is_integer()`` | ``True`` if *x* has a finite | | :func:`~numbers\ |
314-
| | and integral value, otherwise | | .Real.is_integer` |
315-
| | ``False``. | | |
316-
+---------------------+---------------------------------+---------+--------------------+
317313

318314
.. index::
319315
triple: operations on; numeric; types
@@ -587,6 +583,16 @@ class`. float also has the following additional methods.
587583
:exc:`OverflowError` on infinities and a :exc:`ValueError` on
588584
NaNs.
589585

586+
.. method:: float.is_integer()
587+
588+
Return ``True`` if the float instance is finite with integral
589+
value, and ``False`` otherwise::
590+
591+
>>> (-2.0).is_integer()
592+
True
593+
>>> (3.2).is_integer()
594+
False
595+
590596
Two methods support conversion to
591597
and from hexadecimal strings. Since Python's floats are stored
592598
internally as binary numbers, converting a float to or from a

Lib/_pydecimal.py

-25
Original file line numberDiff line numberDiff line change
@@ -3164,12 +3164,6 @@ def is_zero(self):
31643164
"""Return True if self is a zero; otherwise return False."""
31653165
return not self._is_special and self._int == '0'
31663166

3167-
def is_integer(self):
3168-
"""Return True is self is finite and integral; otherwise False."""
3169-
if self._is_special:
3170-
return False
3171-
return self.to_integral_value(rounding=ROUND_FLOOR) == self
3172-
31733167
def _ln_exp_bound(self):
31743168
"""Compute a lower bound for the adjusted exponent of self.ln().
31753169
In other words, compute r such that self.ln() >= 10**r. Assumes
@@ -4665,25 +4659,6 @@ def is_zero(self, a):
46654659
a = _convert_other(a, raiseit=True)
46664660
return a.is_zero()
46674661

4668-
def is_integer(self, a):
4669-
"""Return True if the operand is integral; otherwise return False.
4670-
4671-
>>> ExtendedContext.is_integer(Decimal('0'))
4672-
True
4673-
>>> ExtendedContext.is_integer(Decimal('2.50'))
4674-
False
4675-
>>> ExtendedContext.is_integer(Decimal('-0E+2'))
4676-
True
4677-
>>> ExtendedContext.is_integer(Decimal('-0.5'))
4678-
False
4679-
>>> ExtendedContext.is_integer(Decimal('NaN'))
4680-
False
4681-
>>> ExtendedContext.is_integer(10)
4682-
True
4683-
"""
4684-
a = _convert_other(a, raiseit=True)
4685-
return a.is_integer()
4686-
46874662
def ln(self, a):
46884663
"""Returns the natural (base e) logarithm of the operand.
46894664

Lib/numbers.py

+1-20
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ class Real(Complex):
148148
"""To Complex, Real adds the operations that work on real numbers.
149149
150150
In short, those are: a conversion to float, trunc(), divmod,
151-
is_integer, %, <, <=, >, and >=.
151+
%, <, <=, >, and >=.
152152
153153
Real also provides defaults for the derived operations.
154154
"""
@@ -242,17 +242,6 @@ def __le__(self, other):
242242
"""self <= other"""
243243
raise NotImplementedError
244244

245-
def is_integer(self):
246-
"""Return True if the Real is integral; otherwise return False.
247-
248-
This default implementation can be overridden in subclasses
249-
for performance reasons or to deal with values such as NaN,
250-
which would otherwise cause an exception to be raised.
251-
"""
252-
# Although __int__ is not defined at this level, the int
253-
# constructor falls back to __trunc__, which we do have.
254-
return self == int(self)
255-
256245
# Concrete implementations of Complex abstract methods.
257246
def __complex__(self):
258247
"""complex(self) == complex(float(self), 0)"""
@@ -301,10 +290,6 @@ def __float__(self):
301290
"""
302291
return self.numerator / self.denominator
303292

304-
def is_integer(self):
305-
"""Return True if the Rational is integral; otherwise return False."""
306-
return self.denominator == 1
307-
308293

309294
class Integral(Rational):
310295
"""Integral adds a conversion to int and the bit-string operations."""
@@ -401,8 +386,4 @@ def denominator(self):
401386
"""Integers have a denominator of 1."""
402387
return 1
403388

404-
def is_integer(self):
405-
"""Return True; all Integrals represent an integral value."""
406-
return True
407-
408389
Integral.register(int)

Lib/test/decimaltestdata/extra.decTest

-18
Original file line numberDiff line numberDiff line change
@@ -2346,24 +2346,6 @@ bool2096 iszero sNaN -> 0
23462346
bool2097 iszero -sNaN -> 0
23472347
bool2098 iszero sNaN123 -> 0
23482348
bool2099 iszero -sNaN123 -> 0
2349-
bool2100 is_integer -1.0 -> 1
2350-
bool2101 is_integer 0.0 -> 1
2351-
bool2102 is_integer 1.0 -> 1
2352-
bool2103 is_integer 42 -> 1
2353-
bool2104 is_integer 1e2 -> 1
2354-
bool2105 is_integer 1.5 -> 0
2355-
bool2106 is_integer 1e-2 -> 0
2356-
bool2107 is_integer NaN -> 0
2357-
bool2109 is_integer -NaN -> 0
2358-
bool2110 is_integer NaN123 -> 0
2359-
bool2111 is_integer -NaN123 -> 0
2360-
bool2112 is_integer sNaN -> 0
2361-
bool2113 is_integer -sNaN -> 0
2362-
bool2114 is_integer sNaN123 -> 0
2363-
bool2115 is_integer -sNaN123 -> 0
2364-
bool2116 is_integer Infinity -> 0
2365-
bool2117 is_integer -Infinity -> 0
2366-
23672349

23682350
------------------------------------------------------------------------
23692351
-- The following tests (pwmx0 through pwmx440) are for the --

Lib/test/test_bool.py

-5
Original file line numberDiff line numberDiff line change
@@ -354,11 +354,6 @@ def test_real_and_imag(self):
354354
self.assertIs(type(False.real), int)
355355
self.assertIs(type(False.imag), int)
356356

357-
def test_always_is_integer(self):
358-
# Issue #26680: Incorporating number.is_integer into bool
359-
self.assertTrue(all(b.is_integer() for b in (False, True)))
360-
361-
362357
def test_main():
363358
support.run_unittest(BoolTest)
364359

Lib/test/test_decimal.py

-24
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,6 @@ def setUp(self):
276276
'is_snan',
277277
'is_subnormal',
278278
'is_zero',
279-
'is_integer',
280279
'same_quantum')
281280

282281
def read_unlimited(self, v, context):
@@ -2727,7 +2726,6 @@ def test_named_parameters(self):
27272726
self.assertRaises(TypeError, D(1).is_snan, context=xc)
27282727
self.assertRaises(TypeError, D(1).is_signed, context=xc)
27292728
self.assertRaises(TypeError, D(1).is_zero, context=xc)
2730-
self.assertRaises(TypeError, D(1).is_integer, context=xc)
27312729

27322730
self.assertFalse(D("0.01").is_normal(context=xc))
27332731
self.assertTrue(D("0.01").is_subnormal(context=xc))
@@ -3199,15 +3197,6 @@ def test_is_zero(self):
31993197
self.assertEqual(c.is_zero(10), d)
32003198
self.assertRaises(TypeError, c.is_zero, '10')
32013199

3202-
def test_is_integer(self):
3203-
Decimal = self.decimal.Decimal
3204-
Context = self.decimal.Context
3205-
3206-
c = Context()
3207-
b = c.is_integer(Decimal(10))
3208-
self.assertEqual(c.is_integer(10), b)
3209-
self.assertRaises(TypeError, c.is_integer, '10')
3210-
32113200
def test_ln(self):
32123201
Decimal = self.decimal.Decimal
32133202
Context = self.decimal.Context
@@ -4371,19 +4360,6 @@ def test_implicit_context(self):
43714360
self.assertTrue(Decimal("-1").is_signed())
43724361
self.assertTrue(Decimal("0").is_zero())
43734362
self.assertTrue(Decimal("0").is_zero())
4374-
self.assertTrue(Decimal("-1").is_integer())
4375-
self.assertTrue(Decimal("0").is_integer())
4376-
self.assertTrue(Decimal("1").is_integer())
4377-
self.assertTrue(Decimal("42").is_integer())
4378-
self.assertTrue(Decimal("1e2").is_integer())
4379-
self.assertFalse(Decimal("1.5").is_integer())
4380-
self.assertFalse(Decimal("1e-2").is_integer())
4381-
self.assertFalse(Decimal("NaN").is_integer())
4382-
self.assertFalse(Decimal("-NaN").is_integer())
4383-
self.assertFalse(Decimal("sNaN").is_integer())
4384-
self.assertFalse(Decimal("-sNaN").is_integer())
4385-
self.assertFalse(Decimal("Inf").is_integer())
4386-
self.assertFalse(Decimal("-Inf").is_integer())
43874363

43884364
# Copy
43894365
with localcontext() as c:

Lib/test/test_fractions.py

-11
Original file line numberDiff line numberDiff line change
@@ -724,17 +724,6 @@ def denominator(self):
724724
self.assertEqual(type(f.numerator), myint)
725725
self.assertEqual(type(f.denominator), myint)
726726

727-
def test_is_integer(self):
728-
# Issue #26680: Incorporating number.is_integer into Fraction
729-
self.assertTrue(F(-1, 1).is_integer())
730-
self.assertTrue(F(0, 1).is_integer())
731-
self.assertTrue(F(1, 1).is_integer())
732-
self.assertTrue(F(42, 1).is_integer())
733-
self.assertTrue(F(2, 2).is_integer())
734-
self.assertTrue(F(8, 4).is_integer())
735-
self.assertFalse(F(1, 2).is_integer())
736-
self.assertFalse(F(1, 3).is_integer())
737-
self.assertFalse(F(2, 3).is_integer())
738727

739728
if __name__ == '__main__':
740729
unittest.main()

Lib/test/test_long.py

-4
Original file line numberDiff line numberDiff line change
@@ -1381,10 +1381,6 @@ class myint(int):
13811381
self.assertEqual(type(numerator), int)
13821382
self.assertEqual(type(denominator), int)
13831383

1384-
def test_int_always_is_integer(self):
1385-
# Issue #26680: Incorporating number.is_integer into int
1386-
self.assertTrue(all(x.is_integer() for x in (-1, 0, 1, 42)))
1387-
13881384

13891385
if __name__ == "__main__":
13901386
unittest.main()

Lib/test/test_numeric_tower.py

-31
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import sys
77
import operator
88

9-
from numbers import Real, Rational, Integral
109
from decimal import Decimal as D
1110
from fractions import Fraction as F
1211

@@ -199,35 +198,5 @@ def test_complex(self):
199198
self.assertRaises(TypeError, op, v, z)
200199

201200

202-
class IsIntegerTest(unittest.TestCase):
203-
204-
def test_real_is_integer(self):
205-
self.assertTrue(Real.is_integer(-1.0))
206-
self.assertTrue(Real.is_integer(0.0))
207-
self.assertTrue(Real.is_integer(1.0))
208-
self.assertTrue(Real.is_integer(42.0))
209-
210-
self.assertFalse(Real.is_integer(-0.5))
211-
self.assertFalse(Real.is_integer(4.2))
212-
213-
def test_rational_is_integer(self):
214-
self.assertTrue(Rational.is_integer(F(-1, 1)))
215-
self.assertTrue(Rational.is_integer(F(0, 1)))
216-
self.assertTrue(Rational.is_integer(F(1, 1)))
217-
self.assertTrue(Rational.is_integer(F(42, 1)))
218-
self.assertTrue(Rational.is_integer(F(2, 2)))
219-
self.assertTrue(Rational.is_integer(F(8, 4)))
220-
221-
self.assertFalse(Rational.is_integer(F(1, 2)))
222-
self.assertFalse(Rational.is_integer(F(1, 3)))
223-
self.assertFalse(Rational.is_integer(F(2, 3)))
224-
225-
def test_integral_is_integer(self):
226-
self.assertTrue(Integral.is_integer(-1))
227-
self.assertTrue(Integral.is_integer(0))
228-
self.assertTrue(Integral.is_integer(1))
229-
self.assertTrue(Integral.is_integer(1729))
230-
231-
232201
if __name__ == '__main__':
233202
unittest.main()

Misc/ACKS

-1
Original file line numberDiff line numberDiff line change
@@ -1613,7 +1613,6 @@ Roman Skurikhin
16131613
Ville Skyttä
16141614
Michael Sloan
16151615
Nick Sloan
1616-
Robert Smallshire
16171616
Václav Šmilauer
16181617
Allen W. Smith
16191618
Christopher Smith

Modules/_decimal/_decimal.c

+2-4
Original file line numberDiff line numberDiff line change
@@ -4138,7 +4138,6 @@ Dec_BoolFunc(mpd_isqnan)
41384138
Dec_BoolFunc(mpd_issnan)
41394139
Dec_BoolFunc(mpd_issigned)
41404140
Dec_BoolFunc(mpd_iszero)
4141-
Dec_BoolFunc(mpd_isinteger)
41424141

41434142
/* Boolean functions, optional context arg */
41444143
Dec_BoolFuncVA(mpd_isnormal)
@@ -4773,7 +4772,6 @@ static PyMethodDef dec_methods [] =
47734772
{ "is_snan", dec_mpd_issnan, METH_NOARGS, doc_is_snan },
47744773
{ "is_signed", dec_mpd_issigned, METH_NOARGS, doc_is_signed },
47754774
{ "is_zero", dec_mpd_iszero, METH_NOARGS, doc_is_zero },
4776-
{ "is_integer", dec_mpd_isinteger, METH_NOARGS, doc_is_integer},
47774775

47784776
/* Boolean functions, optional context arg */
47794777
{ "is_normal", (PyCFunction)(void(*)(void))dec_mpd_isnormal, METH_VARARGS|METH_KEYWORDS, doc_is_normal },
@@ -5185,7 +5183,6 @@ DecCtx_BoolFunc_NO_CTX(mpd_isqnan)
51855183
DecCtx_BoolFunc_NO_CTX(mpd_issigned)
51865184
DecCtx_BoolFunc_NO_CTX(mpd_issnan)
51875185
DecCtx_BoolFunc_NO_CTX(mpd_iszero)
5188-
DecCtx_BoolFunc_NO_CTX(mpd_isinteger)
51895186

51905187
static PyObject *
51915188
ctx_iscanonical(PyObject *context UNUSED, PyObject *v)
@@ -5467,7 +5464,6 @@ static PyMethodDef context_methods [] =
54675464
{ "is_snan", ctx_mpd_issnan, METH_O, doc_ctx_is_snan },
54685465
{ "is_subnormal", ctx_mpd_issubnormal, METH_O, doc_ctx_is_subnormal },
54695466
{ "is_zero", ctx_mpd_iszero, METH_O, doc_ctx_is_zero },
5470-
{ "is_integer", ctx_mpd_isinteger, METH_O, doc_ctx_is_integer },
54715467

54725468
/* Functions with a single decimal argument */
54735469
{ "_apply", PyDecContext_Apply, METH_O, NULL }, /* alias for apply */
@@ -6101,3 +6097,5 @@ PyInit__decimal(void)
61016097

61026098
return NULL; /* GCOV_NOT_REACHED */
61036099
}
6100+
6101+

0 commit comments

Comments
 (0)