Correct handling of zeropad and fill_char options

This commit is contained in:
Sergey B Kirpichev
2025-02-28 08:42:42 +03:00
parent 849e185ede
commit f4cef9c83e
2 changed files with 13 additions and 14 deletions
+6 -8
View File
@@ -1397,8 +1397,8 @@ _FLOAT_FORMAT_SPECIFICATION_MATCHER = re.compile(r"""
(?P<sign>[-+ ]?)
(?P<no_neg_0>z)?
(?P<alternate>\#)?
(?P<zeropad>0)?
(?P<width>0|[1-9][0-9]*)?
(?P<zeropad>0(?=0*[1-9]))?
(?P<width>[0-9]+)?
(?P<thousands_separators>[,_])?
(?:\.(?P<precision>[0-9]+))?
(?P<rounding>[UDYZN])?
@@ -1470,13 +1470,11 @@ def read_format_spec(format_spec):
if rounding_char is not None:
format_dict['rounding'] = _GMPY_ROUND_CHAR_DICT[rounding_char]
if match['zeropad'] and match['fill_char']:
raise ValueError('Cannot specify both 0-padding and a fill '
'character')
if match['zeropad']:
format_dict['align'] = '='
format_dict['fill_char'] = '0'
if not match['align']:
format_dict['align'] = '='
if not match['fill_char']:
format_dict['fill_char'] = '0'
if format_dict['precision'] < 0 and format_dict['type'].lower() not in ['', 'a', 'b']:
format_dict['precision'] = 6
+7 -6
View File
@@ -54,7 +54,9 @@ def fmt_str(draw, types='fFeE', for_complex=False):
skip_thousand_separators = True
# Width
res += draw(st.sampled_from(['']*7 + list(map(str, range(1, 40)))))
res += draw(st.sampled_from(['']*7 + list(map(str, range(1, 40)))
+ ([] if for_complex else ['0' + str(_)
for _ in range(40)])))
# grouping character (thousand_separators)
gchar = draw(st.sampled_from([''] + list(',_')))
@@ -470,6 +472,7 @@ def test_mpf_fmt_cpython():
allow_subnormal=True))
@example(fmt='.0g', x=9.995074823339339e-05) # issue 880
@example(fmt='.016f', x=0.1) # issue 915
@example(fmt='0030f', x=0.3)
def test_mpf_floats_bulk(fmt, x):
'''
These are additional random tests that check that mp.mpf and fp.mpf yield
@@ -479,6 +482,9 @@ def test_mpf_floats_bulk(fmt, x):
if not x and math.copysign(1, x) == -1:
return # skip negative zero
spec = read_format_spec(fmt)
if (spec['width'] > 0 and spec['fill_char'] == '0'
and spec['thousands_separators']):
return # issue 917
if not spec['type'] and spec['precision'] < 0 and math.isfinite(x):
# The mpmath could choose a different decimal
# representative (wrt CPython) for same binary
@@ -799,11 +805,6 @@ def test_errors():
with pytest.raises(ValueError, match="Invalid format specifier '12.3 E '"):
f"{mp.mpf('4'):12.3 E }"
with pytest.raises(ValueError, match="Cannot specify both 0-padding "
"and a fill character"):
f"{mp.mpf('4'):q<03f}"
@settings(max_examples=10000)
@given(st.floats(allow_nan=True, allow_infinity=True,