Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Doc/deprecations/pending-removal-in-3.20.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,8 @@ Pending removal in Python 3.20
- :mod:`zlib`

(Contributed by Hugo van Kemenade and Stan Ulbrych in :gh:`76007`.)

* The ``__getformat__()`` class method of the :class:`float` is deprecated
and will be removed in Python 3.20.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should document the deprecation in What's New in Python 3.15.

What is the migration path for projects currently relying on __getformat__()? Do they have to copy/paste the big _have_ieee_doubles() function?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the migration path for projects currently relying on getformat()? Do they have to copy/paste the big _have_ieee_doubles() function?

Primary goal is using the CPython's test suite. No changes needed.

But for the rest - yes.


(Contributed by Sergey B Kirpichev in :gh:`145633`.)
5 changes: 5 additions & 0 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1621,6 +1621,11 @@ New deprecations
* Deprecated :func:`!typing.no_type_check_decorator` has been removed.
(Contributed by Nikita Sobolev in :gh:`133601`.)

* The ``__getformat__()`` class method of the :class:`float` is deprecated
and will be removed in Python 3.20.

(Contributed by Sergey B Kirpichev in :gh:`145633`.)

* ``__version__``

* The ``__version__``, ``version`` and ``VERSION`` attributes have been
Expand Down
6 changes: 0 additions & 6 deletions Lib/test/pythoninfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,6 @@ def collect_locale(info_add):
info_add('locale.getencoding', locale.getencoding())


def collect_builtins(info_add):
info_add('builtins.float.float_format', float.__getformat__("float"))
info_add('builtins.float.double_format', float.__getformat__("double"))


def collect_urandom(info_add):
import os

Expand Down Expand Up @@ -1050,7 +1045,6 @@ def collect_info(info):
# its state.
collect_urandom,

collect_builtins,
collect_cc,
collect_curses,
collect_datetime,
Expand Down
34 changes: 33 additions & 1 deletion Lib/test/support/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -518,9 +518,41 @@ def dec(*args, **kwargs):
# for a discussion of this number.
SOCK_MAX_SIZE = 16 * 1024 * 1024 + 1

def _have_ieee_doubles():
import math
import struct
# Check parameters for encoding of floats; a quick exit
# if they aren't same as for IEC 60559 doubles. Check
# also that subnormals are present.
if (struct.calcsize('d') != 8
or sys.float_info.radix != 2
or sys.float_info.mant_dig != 53
or sys.float_info.dig != 15
or sys.float_info.min_exp != -1021
or sys.float_info.min_10_exp != -307
or sys.float_info.max_exp != 1024
or sys.float_info.max_10_exp != 308
or not math.issubnormal(math.nextafter(0, 1))):
return False
try:
import ctypes
except ImportError:
return True
# We attempt to determine if this machine is using IEC
# floating-point formats by peering at the bits of some
# carefully chosen value. Assume that integer and
# floating-point types have same endianness.
d = 9006104071832581.0
be_d = int.from_bytes(b"\x43\x3f\xff\x01\x02\x03\x04\x05")
dp = ctypes.pointer(ctypes.c_double(d))
lp = ctypes.cast(dp, ctypes.POINTER(ctypes.c_uint64))
return lp[0] == be_d

HAVE_IEEE_754 = _have_ieee_doubles()

# decorator for skipping tests on non-IEEE 754 platforms
requires_IEEE_754 = unittest.skipUnless(
float.__getformat__("double").startswith("IEEE"),
HAVE_IEEE_754,
"test requires IEEE 754 doubles")

def requires_zlib(reason='requires zlib'):
Expand Down
11 changes: 5 additions & 6 deletions Lib/test/test_capi/test_float.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from test.test_capi.test_getargs import (Float, FloatSubclass, FloatSubclass2,
BadIndex2, BadFloat2, Index, BadIndex,
BadFloat)
from test import support
from test.support import import_helper

_testcapi = import_helper.import_module('_testcapi')
Expand All @@ -23,7 +24,6 @@
8: 2.0 ** -53, # binary64
}

HAVE_IEEE_754 = float.__getformat__("double").startswith("IEEE")
INF = float("inf")
NAN = float("nan")

Expand Down Expand Up @@ -170,14 +170,13 @@ def test_unpack(self):
self.assertEqual(unpack(b'\x00\x00\x00\x00\x00\x00\xf8?', LITTLE_ENDIAN),
1.5)

@support.requires_IEEE_754
def test_pack_unpack_roundtrip(self):
pack = _testcapi.float_pack
unpack = _testcapi.float_unpack

large = 2.0 ** 100
values = [1.0, 1.5, large, 1.0/7, math.pi]
if HAVE_IEEE_754:
values.extend((INF, NAN))
values = [1.0, 1.5, large, 1.0/7, math.pi, INF, NAN]
for value in values:
for size in (2, 4, 8,):
if size == 2 and value == large:
Expand All @@ -196,7 +195,7 @@ def test_pack_unpack_roundtrip(self):
else:
self.assertEqual(value2, value)

@unittest.skipUnless(HAVE_IEEE_754, "requires IEEE 754")
@support.requires_IEEE_754
def test_pack_unpack_roundtrip_for_nans(self):
pack = _testcapi.float_pack
unpack = _testcapi.float_unpack
Expand Down Expand Up @@ -228,7 +227,7 @@ def test_pack_unpack_roundtrip_for_nans(self):
self.assertTrue(math.isnan(value))
self.assertEqual(data1, data2)

@unittest.skipUnless(HAVE_IEEE_754, "requires IEEE 754")
@support.requires_IEEE_754
@unittest.skipUnless(sys.maxsize != 2147483647, "requires 64-bit mode")
def test_pack_unpack_nans_for_different_formats(self):
pack = _testcapi.float_pack
Expand Down
11 changes: 0 additions & 11 deletions Lib/test/test_float.py
Original file line number Diff line number Diff line change
Expand Up @@ -670,17 +670,6 @@ def __neg__(self):
self.assertFalse(f >= i)


@unittest.skipUnless(hasattr(float, "__getformat__"), "requires __getformat__")
class FormatFunctionsTestCase(unittest.TestCase):
def test_getformat(self):
self.assertIn(float.__getformat__('double'),
['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
self.assertIn(float.__getformat__('float'),
['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
self.assertRaises(ValueError, float.__getformat__, 'chicken')
self.assertRaises(TypeError, float.__getformat__, 1)


BE_DOUBLE_INF = b'\x7f\xf0\x00\x00\x00\x00\x00\x00'
LE_DOUBLE_INF = bytes(reversed(BE_DOUBLE_INF))
BE_DOUBLE_NAN = b'\x7f\xf8\x00\x00\x00\x00\x00\x00'
Expand Down
3 changes: 0 additions & 3 deletions Lib/test/test_funcattrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -486,8 +486,6 @@ def test_builtin__qualname__(self):

# builtin classmethod:
self.assertEqual(dict.fromkeys.__qualname__, 'dict.fromkeys')
self.assertEqual(float.__getformat__.__qualname__,
'float.__getformat__')

# builtin staticmethod:
self.assertEqual(str.maketrans.__qualname__, 'str.maketrans')
Expand All @@ -509,7 +507,6 @@ def test_builtin__self__(self):

# builtin classmethod:
self.assertIs(dict.fromkeys.__self__, dict)
self.assertIs(float.__getformat__.__self__, float)

# builtin staticmethod:
self.assertIsNone(str.maketrans.__self__)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
The ``__getformat__()`` class method of the :class:`float` is deprecated.
Patch by Sergey B Kirpichev.
5 changes: 5 additions & 0 deletions Objects/floatobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1696,6 +1696,11 @@ static PyObject *
float___getformat___impl(PyTypeObject *type, const char *typestr)
/*[clinic end generated code: output=2bfb987228cc9628 input=0ae1ba35d192f704]*/
{
if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
"float.__getformat__() is deprecated"))
{
return NULL;
}
if (strcmp(typestr, "double") != 0 && strcmp(typestr, "float") != 0) {
PyErr_SetString(PyExc_ValueError,
"__getformat__() argument 1 must be "
Expand Down
Loading