This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: decimal.py: more format issues
Type: behavior Stage: resolved
Components: Versions: Python 3.11
process
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: eric.smith Nosy List: eric.smith, iritkatriel, mark.dickinson, skrah
Priority: normal Keywords:

Created on 2009-09-09 16:07 by skrah, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (20)
msg92453 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2009-09-09 16:07
Hi,

I've two more issues where format behavior should probably be identical:

1: (version 2.6 vs. 3.1):

Version 2.6:
>>> format(Decimal("NaN"), "+08.4")
'+0000NaN'
>>> format(float("NaN"), "+08.4")
'+00.0nan'

Version 3.1:
>>> format(Decimal("NaN"), "+08.4")
'+NaN    '
>>> format(float("NaN"), "+08.4")
'+0000nan'


2: (float vs. decimal):

>>> format(float(123), "00")
'123.0'
>>> format(Decimal(123), "00")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.1/decimal.py", line 3611, in __format__
    spec = _parse_format_specifier(specifier, _localeconv=_localeconv)
  File "/usr/lib/python3.1/decimal.py", line 5563, in
_parse_format_specifier
    raise ValueError("Invalid format specifier: " + format_spec)
ValueError: Invalid format specifier: 00
msg92455 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2009-09-09 17:04
For #1 for floats, 2.6 is in error. This has been fixed in 2.7 (trunk).

For #2, I think float is correct. The PEP says the specifier is:
[[fill]align][sign][#][0][minimumwidth][.precision][type]
so '00' is parsed as minimumwidth=0 with zero-padding specified.
msg92456 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2009-09-09 18:18
Also, see issue 4482 for a discussion of float formatting for nan and inf.
msg92461 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2009-09-09 19:25
Issue #1: In both trunk and py3k I get:

>>> from decimal import Decimal
>>> format(Decimal('nan'), '+08.4')
'    +NaN'
>>> format(float('nan'), '+08.4')
'+0000nan'
>>> format(Decimal('inf'), '+012.4')
'   +Infinity'
>>> format(float('inf'), '+012.4')
'+00000000inf'

Two potential issues here:  first is the zero padding; to me, a zero-
padded nan or inf just looks ugly, but if people think that's the 
correct output (and I suppose that I have to admit that it probably is) 
then I'll add the zeros in for the Decimal type.

The second issue is the difference in spelling; ('nan' versus 'NaN', 
'inf' versus 'Infinity');  I'm not really bothered by this difference, 
and it would be quite awkward to change.  The output format for Decimal 
is mandated by the standard, while changing the spelling for floats 
seems both unnecessary and likely to break code.

Issue #2: This is a bit odd.  If a minimumwidth of 0 is permissible, 
then the format '0' is ambiguous.  Assuming that '0' continues to mean 
zero-padded, this leaves '00' as the *only* way to specify a minimum 
width of 0.  It seems cleaner just to assume that minimumwidth always 
has to be strictly positive, making '00' invalid.  At least, I think 
that's what I was thinking when I wrote the Decimal formatting code.
But I agree that float and Decimal should be consistent here.
msg92467 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2009-09-09 21:06
Issue 1:

I would definitely keep the spelling in decimal, my concern was only the
padding.

The C standard agrees with Mark's view:

"Leading zeros (following any indication of sign or base) are used to
pad to the field width rather than performing space padding, except when
converting an infinity or NaN."

If this could be agreed on, issue 1 should be handled by changing float
and decimal 2.6.


Issue 2:

I can't find it quickly in the C standard, but gcc warns in this situation:

   warning: repeated '0' flag in format

This would support the behavior of decimal and float should be changed.


I would like to add two new issues.

Issue 3:

Regarding padding, the C standard further says:

"If the 0 and - flags both appear, the 0 flag is ignored"

This is quite sensible, since signless 0 padding looks a bit awkward.
(But this is a minor issue). 


Issue 4:

>>> format(Decimal('1e88'), '0<20')
'1E+88000000000000000'

>>> format(float('1e88'), '0<20')
'0000000000000001e+88'

I think right-padding with digits is dangerous, since it changes the
numerical value. I'm not sure what float does, it doesn't look correct
(but protects the user).
msg92474 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2009-09-10 08:05
Issue 3 is nonsense, '-' means left-justified in C. Sorry.
msg92578 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2009-09-13 18:32
I think issue #4 is a bug in float formatting:  I don't think it makes 
sense to change alignment just because the fill character happens to be 
'0'.
msg92579 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2009-09-13 18:33
From the current trunk:

>>> format(float('1e88'), '1<20')
'1e+88111111111111111'
[64734 refs]
>>> format(float('1e88'), '0<20')
'0000000000000001e+88'
[64734 refs]
msg92585 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2009-09-13 23:29
The '0' fill character is forcing '=' alignment (per the PEP). This
looks like a bug to me, since it should use the specified alignment.

This is not a float-only problem, it applies to the other built-in types
as well:
>>> format(2, '0<20')
'00000000000000000002'
>>> format(2, '1<20')
'21111111111111111111'

There are too many distinct issues combined here, I'll create a new
issue just for this bug.
msg92587 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2009-09-13 23:38
Created issue 6902 to handle #4.

The others will need to be broken out into their own issues if we want
to fix them. I can't keep track of multiple issues in one bug report.
msg99828 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2010-02-22 20:49
I think there are no remaining issues here that don't have their own issue. I'm going to close this unless one of you think otherwise.
msg99839 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2010-02-22 21:32
I couldn't find other issues where #1 and #2 are addressed. This
is from py3k:


#1:

>>> format(float('nan'), '+08.4')
'+0000nan'
[70141 refs]
>>> format(Decimal('nan'), '+08.4')
'    +NaN'


#2:>>> format(float(123), "00")
'123.0'
[70141 refs]
>>> format(Decimal(123), "00")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/stefan/svn/py3k/Lib/decimal.py", line 3633, in __format__
    spec = _parse_format_specifier(specifier, _localeconv=_localeconv)
  File "/home/stefan/svn/py3k/Lib/decimal.py", line 5915, in _parse_format_specifier
    raise ValueError("Invalid format specifier: " + format_spec)
ValueError: Invalid format specifier: 00
[70141 refs]
msg99841 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2010-02-22 21:41
[The tracker apparently set the status to 'open' without my intervention.]

To sum up what I said earlier about #1 and #2, I think that the C standard
and gcc's warning behavior support the way of Decimal.
msg99845 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2010-02-22 21:47
[If the status is pending, any comment turns it back to open, by design.]

I'd rather float.__format__ agree with %-formatting for floats than with anything else.

>>> '%+08.4f' % float('nan')
'+0000nan'
>>> "%00f" % float('123')
'123.000000'

(Not sure about the precision being displayed on that last one, I'll have to think about it.)
msg190058 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2013-05-26 03:51
If I'm reading this correctly only issue 2 is outstanding.  Opinions please gentlemen.
msg396109 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) Date: 2021-06-18 23:31
Issue #2 still exists in 3.11:

>>> format(float(123), "00")
'123.0'
>>> format(Decimal(123), "00")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid format string
msg396122 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2021-06-19 09:23
Eric: any thoughts on this?

It's looking like a "won't fix" to me. Regardless of what we think the "right" thing to do is, making the float behaviour stricter would be a backwards compatibility break, and relaxing the Decimal behaviour involves either diverging from the upstream libmpdec (and then having to maintain that divergence if we update to newer versions of libmpdec) or pushing changes back upstream. Both of those options seem like more effort than it's worth for something that apparently hasn't actually bothered anyone for several years.
msg396130 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2021-06-19 12:33
I tend to agree with Mark: any change would be disruptive, and it doesn't seem to be causing any real problem.

Irit: did you come across this because it's causing a problem somewhere?
msg396132 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) Date: 2021-06-19 13:10
No just trying to sort out the backlog.
msg396136 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2021-06-19 15:26
Thanks, Irit.

I'm closing this as "won't fix".
History
Date User Action Args
2022-04-11 14:56:52adminsetgithub: 51120
2021-06-19 15:26:00eric.smithsetstatus: open -> closed
resolution: out of date -> wont fix
messages: + msg396136

stage: resolved
2021-06-19 13:10:01iritkatrielsetmessages: + msg396132
2021-06-19 12:33:09eric.smithsetmessages: + msg396130
2021-06-19 09:23:14mark.dickinsonsetmessages: + msg396122
2021-06-18 23:31:21iritkatrielsetnosy: + iritkatriel

messages: + msg396109
versions: + Python 3.11
2014-02-03 17:12:55BreamoreBoysetnosy: - BreamoreBoy
2013-05-26 03:51:41BreamoreBoysetnosy: + BreamoreBoy
messages: + msg190058
2010-02-24 17:50:34eric.smithsetpriority: normal
2010-02-22 21:47:17eric.smithsetmessages: + msg99845
2010-02-22 21:41:37skrahsetmessages: + msg99841
2010-02-22 21:32:22skrahsetstatus: pending -> open

messages: + msg99839
2010-02-22 20:49:50eric.smithsetstatus: open -> pending
type: behavior
messages: + msg99828

assignee: eric.smith
resolution: out of date
2009-09-13 23:38:27eric.smithsetmessages: + msg92587
2009-09-13 23:29:55eric.smithsetmessages: + msg92585
2009-09-13 18:33:46mark.dickinsonsetmessages: + msg92579
2009-09-13 18:32:43mark.dickinsonsetmessages: + msg92578
2009-09-10 08:05:48skrahsetmessages: + msg92474
2009-09-09 21:06:24skrahsetmessages: + msg92467
2009-09-09 19:25:19mark.dickinsonsetmessages: + msg92461
2009-09-09 18:18:37eric.smithsetmessages: + msg92456
2009-09-09 17:04:04eric.smithsetnosy: + eric.smith
messages: + msg92455
2009-09-09 16:07:20skrahcreate