| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent c1d98d6 commit 984bb58
9 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -350,9 +350,18 @@ following: | |||
| 350 | 350 | | | positive numbers, and a minus sign on negative numbers. | | |
| 351 | 351 | +---------+----------------------------------------------------------+ | |
| 352 | 352 | ||
| 353 | - The ``'#'`` option is only valid for integers, and only for binary, octal, or | ||
| 354 | - hexadecimal output. If present, it specifies that the output will be prefixed | ||
| 355 | - by ``'0b'``, ``'0o'``, or ``'0x'``, respectively. | ||
| 353 | + | ||
| 354 | + The ``'#'`` option causes the "alternate form" to be used for the | ||
| 355 | + conversion. The alternate form is defined differently for different | ||
| 356 | + types. This option is only valid for integer, float, complex and | ||
| 357 | + Decimal types. For integers, when binary, octal, or hexadecimal output | ||
| 358 | + is used, this option adds the prefix respective ``'0b'``, ``'0o'``, or | ||
| 359 | + ``'0x'`` to the output value. For floats, complex and Decimal the | ||
| 360 | + alternate form causes the result of the conversion to always contain a | ||
| 361 | + decimal-point character, even if no digits follow it. Normally, a | ||
| 362 | + decimal-point character appears in the result of these conversions | ||
| 363 | + only if a digit follows it. In addition, for ``'g'`` and ``'G'`` | ||
| 364 | + conversions, trailing zeros are not removed from the result. | ||
| 356 | 365 | ||
| 357 | 366 | The ``','`` option signals the use of a comma for a thousands separator. | |
| 358 | 367 | For a locale aware separator, use the ``'n'`` integer presentation type | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5991,14 +5991,15 @@ def _convert_for_comparison(self, other, equality_op=False): | |||
| 5991 | 5991 | # | |
| 5992 | 5992 | # A format specifier for Decimal looks like: | |
| 5993 | 5993 | # | |
| 5994 | - # [[fill]align][sign][0][minimumwidth][,][.precision][type] | ||
| 5994 | + # [[fill]align][sign][#][0][minimumwidth][,][.precision][type] | ||
| 5995 | 5995 | ||
| 5996 | 5996 | _parse_format_specifier_regex = re.compile(r"""\A | |
| 5997 | 5997 | (?: | |
| 5998 | 5998 | (?P<fill>.)? | |
| 5999 | 5999 | (?P<align>[<>=^]) | |
| 6000 | 6000 | )? | |
| 6001 | 6001 | (?P<sign>[-+ ])? | |
| 6002 | + (?P<alt>\#)? | ||
| 6002 | 6003 | (?P<zeropad>0)? | |
| 6003 | 6004 | (?P<minimumwidth>(?!0)\d+)? | |
| 6004 | 6005 | (?P<thousands_sep>,)? | |
@@ -6214,7 +6215,7 @@ def _format_number(is_negative, intpart, fracpart, exp, spec): | |||
| 6214 | 6215 | ||
| 6215 | 6216 | sign = _format_sign(is_negative, spec) | |
| 6216 | 6217 | ||
| 6217 | - if fracpart: | ||
| 6218 | + if fracpart or spec['alt']: | ||
| 6218 | 6219 | fracpart = spec['decimal_point'] + fracpart | |
| 6219 | 6220 | ||
| 6220 | 6221 | if exp != 0 or spec['type'] in 'eE': | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -555,8 +555,28 @@ def test_format(self): | |||
| 555 | 555 | self.assertEqual(format(1.5e21+3j, '^40,.2f'), ' 1,500,000,000,000,000,000,000.00+3.00j ') | |
| 556 | 556 | self.assertEqual(format(1.5e21+3000j, ',.2f'), '1,500,000,000,000,000,000,000.00+3,000.00j') | |
| 557 | 557 | ||
| 558 | - # alternate is invalid | ||
| 559 | - self.assertRaises(ValueError, (1.5+0.5j).__format__, '#f') | ||
| 558 | + # Issue 7094: Alternate formatting (specified by #) | ||
| 559 | + self.assertEqual(format(1+1j, '.0e'), '1e+00+1e+00j') | ||
| 560 | + self.assertEqual(format(1+1j, '#.0e'), '1.e+00+1.e+00j') | ||
| 561 | + self.assertEqual(format(1+1j, '.0f'), '1+1j') | ||
| 562 | + self.assertEqual(format(1+1j, '#.0f'), '1.+1.j') | ||
| 563 | + self.assertEqual(format(1.1+1.1j, 'g'), '1.1+1.1j') | ||
| 564 | + self.assertEqual(format(1.1+1.1j, '#g'), '1.10000+1.10000j') | ||
| 565 | + | ||
| 566 | + # Alternate doesn't make a difference for these, they format the same with or without it | ||
| 567 | + self.assertEqual(format(1+1j, '.1e'), '1.0e+00+1.0e+00j') | ||
| 568 | + self.assertEqual(format(1+1j, '#.1e'), '1.0e+00+1.0e+00j') | ||
| 569 | + self.assertEqual(format(1+1j, '.1f'), '1.0+1.0j') | ||
| 570 | + self.assertEqual(format(1+1j, '#.1f'), '1.0+1.0j') | ||
| 571 | + | ||
| 572 | + # Misc. other alternate tests | ||
| 573 | + self.assertEqual(format((-1.5+0.5j), '#f'), '-1.500000+0.500000j') | ||
| 574 | + self.assertEqual(format((-1.5+0.5j), '#.0f'), '-2.+0.j') | ||
| 575 | + self.assertEqual(format((-1.5+0.5j), '#e'), '-1.500000e+00+5.000000e-01j') | ||
| 576 | + self.assertEqual(format((-1.5+0.5j), '#.0e'), '-2.e+00+5.e-01j') | ||
| 577 | + self.assertEqual(format((-1.5+0.5j), '#g'), '-1.50000+0.500000j') | ||
| 578 | + self.assertEqual(format((-1.5+0.5j), '.0g'), '-2+0.5j') | ||
| 579 | + self.assertEqual(format((-1.5+0.5j), '#.0g'), '-2.+0.5j') | ||
| 560 | 580 | ||
| 561 | 581 | # zero padding is invalid | |
| 562 | 582 | self.assertRaises(ValueError, (1.5+0.5j).__format__, '010f') | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -818,6 +818,18 @@ def test_formatting(self): | |||
| 818 | 818 | ||
| 819 | 819 | # issue 6850 | |
| 820 | 820 | ('a=-7.0', '0.12345', 'aaaa0.1'), | |
| 821 | + | ||
| 822 | + # Issue 7094: Alternate formatting (specified by #) | ||
| 823 | + ('.0e', '1.0', '1e+0'), | ||
| 824 | + ('#.0e', '1.0', '1.e+0'), | ||
| 825 | + ('.0f', '1.0', '1'), | ||
| 826 | + ('#.0f', '1.0', '1.'), | ||
| 827 | + ('g', '1.1', '1.1'), | ||
| 828 | + ('#g', '1.1', '1.1'), | ||
| 829 | + ('.0g', '1', '1'), | ||
| 830 | + ('#.0g', '1', '1.'), | ||
| 831 | + ('.0%', '1.0', '100%'), | ||
| 832 | + ('#.0%', '1.0', '100.%'), | ||
| 821 | 833 | ] | |
| 822 | 834 | for fmt, d, result in test_values: | |
| 823 | 835 | self.assertEqual(format(Decimal(d), fmt), result) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -706,11 +706,8 @@ def test_format_specials(self): | |||
| 706 | 706 | def test(fmt, value, expected): | |
| 707 | 707 | # Test with both % and format(). | |
| 708 | 708 | self.assertEqual(fmt % value, expected, fmt) | |
| 709 | - if not '#' in fmt: | ||
| 710 | - # Until issue 7094 is implemented, format() for floats doesn't | ||
| 711 | - # support '#' formatting | ||
| 712 | - fmt = fmt[1:] # strip off the % | ||
| 713 | - self.assertEqual(format(value, fmt), expected, fmt) | ||
| 709 | + fmt = fmt[1:] # strip off the % | ||
| 710 | + self.assertEqual(format(value, fmt), expected, fmt) | ||
| 714 | 711 | ||
| 715 | 712 | for fmt in ['%e', '%f', '%g', '%.0e', '%.6f', '%.20g', | |
| 716 | 713 | '%#e', '%#f', '%#g', '%#.20e', '%#.15f', '%#.3g']: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -396,13 +396,9 @@ def test_int__format__locale(self): | |||
| 396 | 396 | self.assertEqual(len(format(0, cfmt)), len(format(x, cfmt))) | |
| 397 | 397 | ||
| 398 | 398 | def test_float__format__(self): | |
| 399 | - # these should be rewritten to use both format(x, spec) and | ||
| 400 | - # x.__format__(spec) | ||
| 401 | - | ||
| 402 | 399 | def test(f, format_spec, result): | |
| 403 | - assert type(f) == float | ||
| 404 | - assert type(format_spec) == str | ||
| 405 | 400 | self.assertEqual(f.__format__(format_spec), result) | |
| 401 | + self.assertEqual(format(f, format_spec), result) | ||
| 406 | 402 | ||
| 407 | 403 | test(0.0, 'f', '0.000000') | |
| 408 | 404 | ||
@@ -516,9 +512,27 @@ def test(f, format_spec, result): | |||
| 516 | 512 | self.assertRaises(ValueError, format, 1e-100, format_spec) | |
| 517 | 513 | self.assertRaises(ValueError, format, -1e-100, format_spec) | |
| 518 | 514 | ||
| 519 | - # Alternate formatting is not supported | ||
| 520 | - self.assertRaises(ValueError, format, 0.0, '#') | ||
| 521 | - self.assertRaises(ValueError, format, 0.0, '#20f') | ||
| 515 | + # Alternate float formatting | ||
| 516 | + test(1.0, '.0e', '1e+00') | ||
| 517 | + test(1.0, '#.0e', '1.e+00') | ||
| 518 | + test(1.0, '.0f', '1') | ||
| 519 | + test(1.0, '#.0f', '1.') | ||
| 520 | + test(1.1, 'g', '1.1') | ||
| 521 | + test(1.1, '#g', '1.10000') | ||
| 522 | + test(1.0, '.0%', '100%') | ||
| 523 | + test(1.0, '#.0%', '100.%') | ||
| 524 | + | ||
| 525 | + # Issue 7094: Alternate formatting (specified by #) | ||
| 526 | + test(1.0, '0e', '1.000000e+00') | ||
| 527 | + test(1.0, '#0e', '1.000000e+00') | ||
| 528 | + test(1.0, '0f', '1.000000' ) | ||
| 529 | + test(1.0, '#0f', '1.000000') | ||
| 530 | + test(1.0, '.1e', '1.0e+00') | ||
| 531 | + test(1.0, '#.1e', '1.0e+00') | ||
| 532 | + test(1.0, '.1f', '1.0') | ||
| 533 | + test(1.0, '#.1f', '1.0') | ||
| 534 | + test(1.0, '.1%', '100.0%') | ||
| 535 | + test(1.0, '#.1%', '100.0%') | ||
| 522 | 536 | ||
| 523 | 537 | # Issue 6902 | |
| 524 | 538 | test(12345.6, "0<20", '12345.60000000000000') | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -318,6 +318,7 @@ David Goodger | |||
| 318 | 318 | Hans de Graaff | |
| 319 | 319 | Eddy De Greef | |
| 320 | 320 | Duncan Grisby | |
| 321 | + Eric Groo | ||
| 321 | 322 | Dag Gruneau | |
| 322 | 323 | Michael Guravage | |
| 323 | 324 | Lars Gustäbel | |
@@ -457,6 +458,7 @@ Lenny Kneler | |||
| 457 | 458 | Pat Knight | |
| 458 | 459 | Greg Kochanski | |
| 459 | 460 | Damon Kohler | |
| 461 | + Vlad Korolev | ||
| 460 | 462 | Joseph Koshy | |
| 461 | 463 | Maksim Kozyarchuk | |
| 462 | 464 | Stefan Krah | |
@@ -536,6 +538,7 @@ David Marek | |||
| 536 | 538 | Doug Marien | |
| 537 | 539 | Alex Martelli | |
| 538 | 540 | Anthony Martin | |
| 541 | + Owen Martin | ||
| 539 | 542 | Sébastien Martini | |
| 540 | 543 | Roger Masse | |
| 541 | 544 | Nick Mathewson | |
@@ -733,6 +736,7 @@ Michael Scharf | |||
| 733 | 736 | Andreas Schawo | |
| 734 | 737 | Neil Schemenauer | |
| 735 | 738 | David Scherer | |
| 739 | + Bob Schmertz | ||
| 736 | 740 | Gregor Schmid | |
| 737 | 741 | Ralf Schmitt | |
| 738 | 742 | Michael Schneider | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -15,6 +15,10 @@ Core and Builtins | |||
| 15 | 15 | - Issue #10027. st_nlink was not being set on Windows calls to os.stat or | |
| 16 | 16 | os.lstat. Patch by Hirokazu Yamamoto. | |
| 17 | 17 | ||
| 18 | + - Issue #7094: Added alternate formatting (specified by '#') to | ||
| 19 | + __format__ method of float, complex, and Decimal. This allows more | ||
| 20 | + precise control over when decimal points are displayed. | ||
| 21 | + | ||
| 18 | 22 | - Issue #10474: range().count() should return integers. | |
| 19 | 23 | ||
| 20 | 24 | - Issue #10255: Fix reference leak in Py_InitializeEx(). Patch by Neil | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -941,13 +941,8 @@ format_float_internal(PyObject *value, | |||
| 941 | 941 | from a hard-code pseudo-locale */ | |
| 942 | 942 | LocaleInfo locale; | |
| 943 | 943 | ||
| 944 | - /* Alternate is not allowed on floats. */ | ||
| 945 | - if (format->alternate) { | ||
| 946 | - PyErr_SetString(PyExc_ValueError, | ||
| 947 | - "Alternate form (#) not allowed in float format " | ||
| 948 | - "specifier"); | ||
| 949 | - goto done; | ||
| 950 | - } | ||
| 944 | + if (format->alternate) | ||
| 945 | + flags |= Py_DTSF_ALT; | ||
| 951 | 946 | ||
| 952 | 947 | if (type == '\0') { | |
| 953 | 948 | /* Omitted type specifier. Behaves in the same way as repr(x) | |
@@ -1104,15 +1099,7 @@ format_complex_internal(PyObject *value, | |||
| 1104 | 1099 | from a hard-code pseudo-locale */ | |
| 1105 | 1100 | LocaleInfo locale; | |
| 1106 | 1101 | ||
| 1107 | - /* Alternate is not allowed on complex. */ | ||
| 1108 | - if (format->alternate) { | ||
| 1109 | - PyErr_SetString(PyExc_ValueError, | ||
| 1110 | - "Alternate form (#) not allowed in complex format " | ||
| 1111 | - "specifier"); | ||
| 1112 | - goto done; | ||
| 1113 | - } | ||
| 1114 | - | ||
| 1115 | - /* Neither is zero pading. */ | ||
| 1102 | + /* Zero padding is not allowed. */ | ||
| 1116 | 1103 | if (format->fill_char == '0') { | |
| 1117 | 1104 | PyErr_SetString(PyExc_ValueError, | |
| 1118 | 1105 | "Zero padding is not allowed in complex format " | |
@@ -1135,6 +1122,9 @@ format_complex_internal(PyObject *value, | |||
| 1135 | 1122 | if (im == -1.0 && PyErr_Occurred()) | |
| 1136 | 1123 | goto done; | |
| 1137 | 1124 | ||
| 1125 | + if (format->alternate) | ||
| 1126 | + flags |= Py_DTSF_ALT; | ||
| 1127 | + | ||
| 1138 | 1128 | if (type == '\0') { | |
| 1139 | 1129 | /* Omitted type specifier. Should be like str(self). */ | |
| 1140 | 1130 | type = 'r'; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments