summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/stdtypes.rst8
-rw-r--r--Doc/whatsnew/3.8.rst4
-rw-r--r--Lib/test/test_doctest.py3
-rw-r--r--Lib/test/test_long.py32
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2018-08-12-16-03-58.bpo-33073.XWu1Jh.rst1
-rw-r--r--Objects/clinic/longobject.c.h30
-rw-r--r--Objects/longobject.c31
8 files changed, 108 insertions, 2 deletions
diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst
index fd59a51..5a133e3 100644
--- a/Doc/library/stdtypes.rst
+++ b/Doc/library/stdtypes.rst
@@ -537,6 +537,14 @@ class`. In addition, it provides a few more methods:
.. versionadded:: 3.2
+.. method:: int.as_integer_ratio()
+
+ Return a pair of integers whose ratio is exactly equal to the original
+ integer and with a positive denominator. The integer ratio of integers
+ (whole numbers) is always the integer as the numerator and ``1`` as the
+ denominator.
+
+ .. versionadded:: 3.8
Additional Methods on Float
---------------------------
diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst
index b2475c7..38b8623 100644
--- a/Doc/whatsnew/3.8.rst
+++ b/Doc/whatsnew/3.8.rst
@@ -91,6 +91,10 @@ Other Language Changes
was lifted.
(Contributed by Serhiy Storchaka in :issue:`32489`.)
+* The ``int`` type now has a new ``as_integer_ratio`` method compatible
+ with the existing ``float.as_integer_ratio`` method.
+ (Contributed by Lisa Roach in :issue:`33073`.)
+
* Added support of ``\N{name}`` escapes in :mod:`regular expressions <re>`.
(Contributed by Jonathan Eunice and Serhiy Storchaka in :issue:`30688`.)
diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py
index 83941c1..797bdb8 100644
--- a/Lib/test/test_doctest.py
+++ b/Lib/test/test_doctest.py
@@ -665,7 +665,7 @@ plain ol' Python and is guaranteed to be available.
True
>>> real_tests = [t for t in tests if len(t.examples) > 0]
>>> len(real_tests) # objects that actually have doctests
- 8
+ 9
>>> for t in real_tests:
... print('{} {}'.format(len(t.examples), t.name))
...
@@ -675,6 +675,7 @@ plain ol' Python and is guaranteed to be available.
2 builtins.float.hex
1 builtins.hex
1 builtins.int
+ 3 builtins.int.as_integer_ratio
2 builtins.int.bit_length
1 builtins.oct
diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py
index 8472889..7c883ba 100644
--- a/Lib/test/test_long.py
+++ b/Lib/test/test_long.py
@@ -3,6 +3,7 @@ from test import support
import sys
+import enum
import random
import math
import array
@@ -1349,6 +1350,37 @@ class LongTest(unittest.TestCase):
self.assertEqual(type(value << shift), int)
self.assertEqual(type(value >> shift), int)
+ def test_as_integer_ratio(self):
+ tests = [10, 0, -10, 1]
+ for value in tests:
+ numerator, denominator = value.as_integer_ratio()
+ self.assertEqual((numerator, denominator), (value, 1))
+ self.assertIsInstance(numerator, int)
+ self.assertIsInstance(denominator, int)
+
+ def test_as_integer_ratio_maxint(self):
+ x = sys.maxsize + 1
+ self.assertEqual(x.as_integer_ratio()[0], x)
+
+ def test_as_integer_ratio_bool(self):
+ self.assertEqual(True.as_integer_ratio(), (1, 1))
+ self.assertEqual(False.as_integer_ratio(), (0, 1))
+ self.assertEqual(type(True.as_integer_ratio()[0]), int)
+ self.assertEqual(type(False.as_integer_ratio()[0]), int)
+
+ def test_as_integer_ratio_int_enum(self):
+ class Foo(enum.IntEnum):
+ X = 42
+ self.assertEqual(Foo.X.as_integer_ratio(), (42, 1))
+ self.assertEqual(type(Foo.X.as_integer_ratio()[0]), int)
+
+ def test_as_integer_ratio_int_flag(self):
+ class Foo(enum.IntFlag):
+ R = 1 << 2
+ self.assertEqual(Foo.R.as_integer_ratio(), (4, 1))
+ self.assertEqual(type(Foo.R.as_integer_ratio()[0]), int)
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/Misc/ACKS b/Misc/ACKS
index 9698535..a29ff60 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1350,6 +1350,7 @@ Juan M. Bello Rivas
Mohd Sanad Zaki Rizvi
Davide Rizzo
Anthony Roach
+Lisa Roach
Carl Robben
Ben Roberts
Mark Roberts
diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-08-12-16-03-58.bpo-33073.XWu1Jh.rst b/Misc/NEWS.d/next/Core and Builtins/2018-08-12-16-03-58.bpo-33073.XWu1Jh.rst
new file mode 100644
index 0000000..ce9b612
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2018-08-12-16-03-58.bpo-33073.XWu1Jh.rst
@@ -0,0 +1 @@
+Added as_integer_ratio to ints to make them more interoperable with floats.
diff --git a/Objects/clinic/longobject.c.h b/Objects/clinic/longobject.c.h
index 14f5515..0e70fe5 100644
--- a/Objects/clinic/longobject.c.h
+++ b/Objects/clinic/longobject.c.h
@@ -118,6 +118,34 @@ int_bit_length(PyObject *self, PyObject *Py_UNUSED(ignored))
return int_bit_length_impl(self);
}
+PyDoc_STRVAR(int_as_integer_ratio__doc__,
+"as_integer_ratio($self, /)\n"
+"--\n"
+"\n"
+"Return integer ratio.\n"
+"\n"
+"Return a pair of integers, whose ratio is exactly equal to the original int\n"
+"and with a positive denominator.\n"
+"\n"
+">>> (10).as_integer_ratio()\n"
+"(10, 1)\n"
+">>> (-10).as_integer_ratio()\n"
+"(-10, 1)\n"
+">>> (0).as_integer_ratio()\n"
+"(0, 1)");
+
+#define INT_AS_INTEGER_RATIO_METHODDEF \
+ {"as_integer_ratio", (PyCFunction)int_as_integer_ratio, METH_NOARGS, int_as_integer_ratio__doc__},
+
+static PyObject *
+int_as_integer_ratio_impl(PyObject *self);
+
+static PyObject *
+int_as_integer_ratio(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ return int_as_integer_ratio_impl(self);
+}
+
PyDoc_STRVAR(int_to_bytes__doc__,
"to_bytes($self, /, length, byteorder, *, signed=False)\n"
"--\n"
@@ -211,4 +239,4 @@ int_from_bytes(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs, PyOb
exit:
return return_value;
}
-/*[clinic end generated code: output=fd64beb83bd16df3 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=6d5e92d7dc803751 input=a9049054013a1b77]*/
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 399d354..98ff9a8 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -5261,6 +5261,36 @@ long_is_finite(PyObject *v)
#endif
/*[clinic input]
+int.as_integer_ratio
+
+Return integer ratio.
+
+Return a pair of integers, whose ratio is exactly equal to the original int
+and with a positive denominator.
+
+>>> (10).as_integer_ratio()
+(10, 1)
+>>> (-10).as_integer_ratio()
+(-10, 1)
+>>> (0).as_integer_ratio()
+(0, 1)
+[clinic start generated code]*/
+
+static PyObject *
+int_as_integer_ratio_impl(PyObject *self)
+/*[clinic end generated code: output=e60803ae1cc8621a input=55ce3058e15de393]*/
+{
+ if PyLong_CheckExact(self) {
+ return PyTuple_Pack(2, self, _PyLong_One);
+ } else {
+ PyObject *numerator = _PyLong_Copy(self);
+ PyObject *ratio_tuple = PyTuple_Pack(2, numerator, _PyLong_One);
+ Py_DECREF(numerator);
+ return ratio_tuple;
+ }
+}
+
+/*[clinic input]
int.to_bytes
length: Py_ssize_t
@@ -5392,6 +5422,7 @@ static PyMethodDef long_methods[] = {
#endif
INT_TO_BYTES_METHODDEF
INT_FROM_BYTES_METHODDEF
+ INT_AS_INTEGER_RATIO_METHODDEF
{"__trunc__", long_long_meth, METH_NOARGS,
"Truncating an Integral returns itself."},
{"__floor__", long_long_meth, METH_NOARGS,