-
-
Notifications
You must be signed in to change notification settings - Fork 34.3k
gh-145633: deprecate float.__getformat__() class method #146400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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(): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand well the purpose of this function. Python now requires IEEE 754 as a build dependency: https://docs.python.org/dev/using/configure.html#build-requirements. Is this test to actually check if it's the case?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is only for alternative Python implementations, using the CPython test suite. |
||
| 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 | ||
skirpichev marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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'): | ||
|
|
||
| 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. |
There was a problem hiding this comment.
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?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Primary goal is using the CPython's test suite. No changes needed.
But for the rest - yes.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can simplify helper? I.e. no ctypes.
In float_info docs the C99, section 5.2.4.2.2 was referenced for "details":
The model is same as in IEEE specification (modulo different summation limits) and we can check that implementation has same set of values for finite numbers, including subnormals and two zeros. And check that there are two infinities and a nan. I.e. slightly extended "if" statement. (
The C11 standard has additionallyEdit: it's obsoleted in C23.)DBL_HAS_SUBNORMmacro. I think we could update float_info with this macro, it will be helpful in such check.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still don't understand how to update code using
__getformat__()? Should code now assume that Python always support IEEE 754 and so what only matters is the endian? In that case, you should point tosys.byteorder.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
__getformat__()now is actual only for alternative implementations. They can override this and skip some parts of the CPython test suite (not all in fact related just to specific format of floating-point numbers, but some also expect certain runtime behavior from arithmetic operations).The
_have_ieee_doubles()use some heuristics to check that some unknown alternative Python implementation actually uses IEEE doubles for the float type, at least can encode all stuff. Old__getformat__()just checked one finite number (like we do now with the ctypes codepath in helper). But instead we also could check parameters for floating-point type, presence of infinities/nans/subnormals. I'm not sure which heuristics is better nowadays, but the ctypes module is missing on some platforms.