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

belm0
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 marked this pull request as draft December 11, 2021 13:24
@belm0 belm0 marked this pull request as ready for review December 14, 2021 13:23
Comment on lines 3252 to 3263
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

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

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.

@github-actions
Copy link

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

@github-actions github-actions bot added the stale Stale PR or inactive for long period of time. label Jan 18, 2022
@mdickinson mdickinson removed the stale Stale PR or inactive for long period of time. label Jan 22, 2022
@mdickinson
Copy link
Member

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

@mdickinson
Copy link
Member

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

Choose a reason for hiding this comment

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

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

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

@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

Choose a reason for hiding this comment

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

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
Comment on lines +3360 to +3363
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

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

Choose a reason for hiding this comment

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

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 belm0 requested a review from mdickinson April 7, 2022 12:52
Copy link
Member

@mdickinson mdickinson left a comment

Choose a reason for hiding this comment

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

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

Choose a reason for hiding this comment

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

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

@cpython-cla-bot
Copy link

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

@belm0
Copy link
Contributor Author

belm0 commented Apr 11, 2022

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

@ericvsmith
Copy link
Member

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

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
mdickinson added a commit to mdickinson/peps that referenced this pull request Apr 11, 2022
The implementation of PEP 682 was completed in python/cpython#30049.
@belm0 belm0 deleted the format_negative_zero branch April 11, 2022 14:40
JelleZijlstra pushed a commit to python/peps that referenced this pull request 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.

5 participants