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: format_dict
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.1, Python 3.2, Python 2.7, Python 2.6
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: mark.dickinson Nosy List: eric.smith, mark.dickinson, skrah
Priority: normal Keywords:

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

Messages (6)
msg92337 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2009-09-06 21:34
Hi,

it looks like format_dict['type'] is not always initialized:

>>> from decimal import *
>>> format(Decimal("0.12345"), "a=-7.0")
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 5595, in
_parse_format_specifier
    if format_dict['type'] in 'gG' or format_dict['type'] is None:
TypeError: 'in <string>' requires string as left operand, not NoneType


Inserting these two lines somewhere in _parse_format_specifier fixes the
problem. (float() uses 'g' as the default, but I got the impression that
decimal.py uses uppercase as the default.) 

if format_dict['type'] is None:
    format_dict['type'] = 'G'
msg92365 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2009-09-07 13:42
The test as written will always give an error for None. I think the
better fix is to change it to be:

if format_dict['type'] is None or format_dict['type'] in 'gG':

That "fixes" this particular exception, but since the format specifier
is invalid, it produces nonsense. I think Decimal's format parser needs
to detect this as an error.
msg92367 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2009-09-07 15:21
Eric Smith <report@bugs.python.org> wrote:
> The test as written will always give an error for None. I think the
> better fix is to change it to be:
> 
> if format_dict['type'] is None or format_dict['type'] in 'gG':
> 
> That "fixes" this particular exception, but since the format specifier
> is invalid, it produces nonsense. I think Decimal's format parser needs
> to detect this as an error.

Do you mean that zero significant digits are invalid or that the conversion
specifier cannot be omitted? If I look at the following, the intentions are
not quite clear to me:

'0.1    '

'0.1    '

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 5595, in _parse_format_specifier
    if format_dict['type'] in 'gG' or format_dict['type'] is None:
TypeError: 'in <string>' requires string as left operand, not NoneType

'    0.1'

1. Conversion specifier can be omitted if significant digits != 0.

2. Significant digits can be zero if conversion specifier is present.

3. Exception

4. float() accepts the format.

I would be in favour of making the conversion specifier mandatory - and
perhaps disallow zero significant digits in the case of 'g'.  If the
intention is to mimic the C Standard, zero significant digits should
probably be silently promoted to one.

In any case, float() and Decimal() should preferably behave identically.

P.S.:

Unrelated, but I just see that float() has the wrong default alignment.
msg92369 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2009-09-07 15:31
The format string is valid. Sorry for the noise. The fill character of
'a' threw me off.

With my suggested change to decimal.py, line 5595, in py3k:
>>> from decimal import *
>>> format(Decimal("0.12345"), "a=-7.0")
'aaaa0.1'
>>> format(0.12345, "a=-7.0")
'aaaa0.1'
>>> 

If float has the wrong alignment, could you open another issue with an
example?
msg92371 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2009-09-07 15:47
Yes, I'll do that.  -  The tracker has eaten my examples, so hopefully
this goes through:

1. format(Decimal("0.12345"), "7.1")   ->  '0.1    '

2. format(Decimal("0.12345"), "7.0g")  ->  '0.1    '

3. format(Decimal("0.12345"), "7.0")
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 5595, in
_parse_format_specifier
    if format_dict['type'] in 'gG' or format_dict['type'] is None:
TypeError: 'in <string>' requires string as left operand, not NoneType

4. format(float("0.12345"), "7.0")     -> '    0.1'


But I've opened a separate issue now.
msg92372 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2009-09-07 16:23
Thanks for the report.  I've fixed the order of the checks as Eric 
suggested in r74704 (trunk), r74705 (release26-maint), r74706 (py3k) and 
r74707 (release31-maint).
History
Date User Action Args
2022-04-11 14:56:52adminsetgithub: 51099
2009-09-07 16:23:34mark.dickinsonsetstatus: open -> closed
versions: + Python 3.2, - Python 3.0
messages: + msg92372

resolution: fixed
stage: resolved
2009-09-07 15:47:59skrahsetmessages: + msg92371
2009-09-07 15:31:39eric.smithsetmessages: + msg92369
2009-09-07 15:21:05skrahsetmessages: + msg92367
title: decimal.py: format_dict['type'] not initialized -> decimal.py: format_dict
2009-09-07 13:44:39eric.smithsetnosy: mark.dickinson, eric.smith, skrah
type: behavior
components: + Library (Lib)
2009-09-07 13:42:15eric.smithsetmessages: + msg92365
2009-09-07 13:37:32eric.smithsetnosy: + eric.smith
2009-09-06 23:13:22benjamin.petersonsetassignee: mark.dickinson

nosy: + mark.dickinson
2009-09-06 21:34:26skrahcreate