(?P<zeropad>0)?
(?P<minimumwidth>\d+)?
(?P<thousands_sep>[,_])?
-(?:\.(?P<precision>\d+))?
+(?:\.
+ (?=[\d,_]) # lookahead for digit or separator
+ (?P<precision>\d+)?
+ (?P<frac_separators>[,_])?
+)?
(?P<type>[eEfFgGn%])?
\z
""", re.VERBOSE|re.DOTALL)
format_dict['grouping'] = [3, 0]
format_dict['decimal_point'] = '.'
+ if format_dict['frac_separators'] is None:
+ format_dict['frac_separators'] = ''
+
return format_dict
def _format_align(sign, body, spec):
sign = _format_sign(is_negative, spec)
+ frac_sep = spec['frac_separators']
+ if fracpart and frac_sep:
+ fracpart = frac_sep.join(fracpart[pos:pos + 3]
+ for pos in range(0, len(fracpart), 3))
+
if fracpart or spec['alt']:
fracpart = spec['decimal_point'] + fracpart
('07_', '1234.56', '1_234.56'),
('_', '1.23456789', '1.23456789'),
('_%', '123.456789', '12_345.6789%'),
+ # and now for something completely different...
+ ('.,', '1.23456789', '1.234,567,89'),
+ ('._', '1.23456789', '1.234_567_89'),
+ ('.6_f', '12345.23456789', '12345.234_568'),
+ (',._%', '123.456789', '12,345.678_9%'),
+ (',._e', '123456', '1.234_56e+5'),
+ (',.4_e', '123456', '1.234_6e+5'),
+ (',.3_e', '123456', '1.235e+5'),
+ (',._E', '123456', '1.234_56E+5'),
# negative zero: default behavior
('.1f', '-0', '-0.0'),
# bytes format argument
self.assertRaises(TypeError, Decimal(1).__format__, b'-020')
+ # precision or fractional part separator should follow after dot
+ self.assertRaises(ValueError, format, Decimal(1), '.f')
+ self.assertRaises(ValueError, format, Decimal(1), '._6f')
+
def test_negative_zero_format_directed_rounding(self):
with self.decimal.localcontext() as ctx:
ctx.rounding = ROUND_CEILING