Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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.

(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