Skip to content
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

bpo-45995: add "z" format specifer to coerce negative 0 to zero #30049

Merged
merged 25 commits into from Apr 11, 2022

Conversation

Copy link
Contributor

@belm0 belm0 commented Dec 11, 2021

This option coerces negative zero into zero after rounding to the format precision.
Covers formatting of standard fraction types (float, Decimal, complex) via str.format(), built-in format(), and f-strings. Old-style string interpolation
is not supported.

https://www.python.org/dev/peps/pep-0682/

https://bugs.python.org/issue45995

@belm0 belm0 requested a review from isidentical as a code owner Dec 11, 2021
@belm0 belm0 marked this pull request as draft Dec 11, 2021
@belm0 belm0 marked this pull request as ready for review Dec 14, 2021
@belm0 belm0 requested a review from rhettinger as a code owner Dec 14, 2021
char *z_start = strchr(fmt, 'z');
if (z_start != NULL) {
no_neg_0 = 1;
size_t z_index = z_start - fmt;
if (fmt_copy == NULL) {
fmt = fmt_copy = dec_strdup(fmt, size);
if (fmt_copy == NULL) {
return NULL;
}
}
memmove(fmt_copy + z_index, fmt_copy + z_index + 1, size - z_index);
size -= 1;
Copy link
Contributor Author

@belm0 belm0 Dec 18, 2021

Choose a reason for hiding this comment

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

if PR #29438 lands, then detection of the "z" option can be incorporated into our forked mpd_parse_fmt_str_ex(), rather than this preprocessing of the format string

Copy link
Member

@ericvsmith ericvsmith Mar 15, 2022

Choose a reason for hiding this comment

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

I think it's the case that one way or the other, the format spec is going to need to be completely parsed to figure out if a given 'z' is used for no_neg_0.

Lib/_pydecimal.py Show resolved Hide resolved
@github-actions
Copy link

@github-actions github-actions bot commented Jan 18, 2022

This PR is stale because it has been open for 30 days with no activity.

@github-actions github-actions bot added the stale label Jan 18, 2022
@taleinat taleinat requested a review from mdickinson Jan 18, 2022
@mdickinson mdickinson removed the stale label Jan 22, 2022
@mdickinson
Copy link
Member

@mdickinson mdickinson commented Jan 22, 2022

Removing the stale label; discussion is ongoing on the bug tracker.

@mdickinson
Copy link
Member

@mdickinson mdickinson commented Mar 6, 2022

Update: the PEP has been accepted - https://discuss.python.org/t/accepting-pep-682-format-specifier-for-signed-zero/14088

We should aim to get this reviewed and in by the next (and final) alpha release of 3.11, due April 5th.

Copy link
Member

@mdickinson mdickinson left a comment

Hi @belm0. Here's a first-pass review; apologies for taking so long to get to this.

Most of the comments are nitpick-level. The big exception is the Decimal code, where I think there's still significant work to do.

Doc/library/string.rst Outdated Show resolved Hide resolved
Doc/library/string.rst Outdated Show resolved Hide resolved
Lib/_pydecimal.py Show resolved Hide resolved
Lib/pydoc_data/topics.py Outdated Show resolved Hide resolved
Lib/test/test_decimal.py Show resolved Hide resolved
Modules/_decimal/_decimal.c Show resolved Hide resolved
Modules/_decimal/_decimal.c Show resolved Hide resolved
Modules/_decimal/_decimal.c Outdated Show resolved Hide resolved
Objects/bytesobject.c Outdated Show resolved Hide resolved
Python/pystrtod.c Show resolved Hide resolved
@bedevere-bot
Copy link

@bedevere-bot bedevere-bot commented Mar 13, 2022

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@mdickinson
Copy link
Member

@mdickinson mdickinson commented Mar 13, 2022

@ericvsmith: if you have any bandwidth to look over the code at some point before the first 3.11 beta, I'd appreciate your input.

Copy link
Contributor Author

@belm0 belm0 left a comment

Thank you for the thorough review!

I'm bogged down a bit and it may take a week or so to reconcile the comments.

Hoping to get this merged for the next (final) alpha.

3.11.0 alpha 7: Tuesday, 2022-04-05
3.11.0 beta 1: Friday, 2022-05-06

Lib/test/test_float.py Outdated Show resolved Hide resolved
@bedevere-bot
Copy link

@bedevere-bot bedevere-bot commented Mar 23, 2022

Thanks for making the requested changes!

@mdickinson: please review the changes made to this pull request.

@bedevere-bot bedevere-bot requested a review from mdickinson Mar 23, 2022
if (no_neg_0 && mpd_isnegative(mpd) && !mpd_isspecial(mpd)) {
/* Round into a temporary (carefully mirroring the rounding
of mpd_qformat_spec()), and check if the result is negative zero.
If so, clear the sign and format the resulting positive zero. */
Copy link
Contributor Author

@belm0 belm0 Mar 23, 2022

Choose a reason for hiding this comment

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

An insight I had recently was that, once negative zero is confirmed somehow, producing the correct output is only a matter of formatting positive zero (which cannot be affected by directed rounding, etc.).

As for how to detect negative zero, the options are: 1) round independently of the format function, or 2) analyze the string result of the format function (as Mark suggested). I found the former easier to manage, since it's a matter of duplicating a small amount of proven mpd library code, and is relatively straightforward to test. In contrast, analyzing the format output involves writing a new and perfectly-correct regex or parser, and imagining all the format spec edge cases to test it with.

Copy link
Member

@mdickinson mdickinson left a comment

Here's a second-pass review. We're getting there, but there are still a couple of bugs to resolve.

Lib/test/test_float.py Show resolved Hide resolved
Python/formatter_unicode.c Outdated Show resolved Hide resolved
Modules/_decimal/_decimal.c Outdated Show resolved Hide resolved
Modules/_decimal/_decimal.c Show resolved Hide resolved
Modules/_decimal/_decimal.c Show resolved Hide resolved
belm0 and others added 3 commits Apr 7, 2022
@belm0 belm0 requested a review from mdickinson Apr 7, 2022
Copy link
Member

@mdickinson mdickinson left a comment

Thank you for the updates! This looks ready to merge to me. I've been running some automated tests that cover a wide variety of combinations, and haven't yet managed to break this. :-)

A bit off-topic: I do think we're introducing some DRY-type technical debt into _decimal.c, though for this PR I don't see an easy alternative. For the future, there's scope for some cleanup after lifting the formatting machinery from libmpdec to _decimal.c. That's for another day, though.

Copy link
Member

@ericvsmith ericvsmith left a comment

Other than possibly adding a credit in the blurb, this looks good to me.

@cpython-cla-bot
Copy link

@cpython-cla-bot cpython-cla-bot bot commented Apr 11, 2022

Commit authors are required to sign the Contributor License Agreement.
CLA not signed

@belm0
Copy link
Contributor Author

@belm0 belm0 commented Apr 11, 2022

using file edit from the github UI appears to have angered CLA bot and bedevere

@ericvsmith
Copy link
Member

@ericvsmith ericvsmith commented Apr 11, 2022

using file edit from the github UI appears to have angered CLA bot and bedevere

I think it's related to the bpo to github issues migration. I'll see what I can figure out.

@mdickinson
Copy link
Member

@mdickinson mdickinson commented Apr 11, 2022

The "CLA Signing" check doesn't seem to be required for merging. Given that we know that CLA signing has occurred, I think we should be okay to merge. I've reported the failure to @ambv.

@mdickinson mdickinson merged commit b0b836b into python:main Apr 11, 2022
12 of 13 checks passed
mdickinson added a commit to mdickinson/peps that referenced this issue Apr 11, 2022
The implementation of PEP 682 was completed in python/cpython#30049.
@belm0 belm0 deleted the format_negative_zero branch Apr 11, 2022
JelleZijlstra pushed a commit to python/peps that referenced this issue Apr 11, 2022
The implementation of PEP 682 was completed in python/cpython#30049.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants