Issue 3382: Make '%F' and float.__format__('F') convert results to upper case.

This commit is contained in:
Eric Smith 2008-07-17 17:48:39 +00:00
parent 4347c44f18
commit 454816d8bd
8 changed files with 53 additions and 23 deletions

View file

@ -1296,9 +1296,9 @@ The conversion types are:
+------------+-----------------------------------------------------+-------+ +------------+-----------------------------------------------------+-------+
| ``'E'`` | Floating point exponential format (uppercase). | \(3) | | ``'E'`` | Floating point exponential format (uppercase). | \(3) |
+------------+-----------------------------------------------------+-------+ +------------+-----------------------------------------------------+-------+
| ``'f'`` | Floating point decimal format. | \(3) | | ``'f'`` | Floating point decimal format (lowercase). | \(3) |
+------------+-----------------------------------------------------+-------+ +------------+-----------------------------------------------------+-------+
| ``'F'`` | Floating point decimal format. | \(3) | | ``'F'`` | Floating point decimal format (uppercase). | \(3) |
+------------+-----------------------------------------------------+-------+ +------------+-----------------------------------------------------+-------+
| ``'g'`` | Floating point format. Uses lowercase exponential | \(4) | | ``'g'`` | Floating point format. Uses lowercase exponential | \(4) |
| | format if exponent is less than -4 or not less than | | | | format if exponent is less than -4 or not less than | |

View file

@ -429,13 +429,14 @@ The available presentation types for floating point and decimal values are:
| ``'e'`` | Exponent notation. Prints the number in scientific | | ``'e'`` | Exponent notation. Prints the number in scientific |
| | notation using the letter 'e' to indicate the exponent. | | | notation using the letter 'e' to indicate the exponent. |
+---------+----------------------------------------------------------+ +---------+----------------------------------------------------------+
| ``'E'`` | Exponent notation. Same as ``'e'`` except it uses an | | ``'E'`` | Exponent notation. Same as ``'e'`` except it converts |
| | upper case 'E' as the separator character. | | | the number to upper case. |
+---------+----------------------------------------------------------+ +---------+----------------------------------------------------------+
| ``'f'`` | Fixed point. Displays the number as a fixed-point | | ``'f'`` | Fixed point. Displays the number as a fixed-point |
| | number. | | | number. |
+---------+----------------------------------------------------------+ +---------+----------------------------------------------------------+
| ``'F'`` | Fixed point. Same as ``'f'``. | | ``'F'`` | Fixed point. Same as ``'f'`` except it converts the |
| | number to upper case. |
+---------+----------------------------------------------------------+ +---------+----------------------------------------------------------+
| ``'g'`` | General format. This prints the number as a fixed-point | | ``'g'`` | General format. This prints the number as a fixed-point |
| | number, unless the number is too large, in which case | | | number, unless the number is too large, in which case |

View file

@ -88,6 +88,18 @@ class FormatTest(unittest.TestCase):
testboth("%#.*F", (110, -1.e+100/3.)) testboth("%#.*F", (110, -1.e+100/3.))
overflowrequired = 0 overflowrequired = 0
# check for %f and %F
testboth("%f", (1.0,), "1.000000")
testboth("%F", (1.0,), "1.000000")
testboth("%f", (1e100,), "1e+100")
testboth("%F", (1e100,), "1E+100")
testboth("%f", (1e100,), "1e+100")
testboth("%F", (1e100,), "1E+100")
testboth("%f", (float('nan'),), "nan")
testboth("%F", (float('nan'),), "NAN")
testboth("%f", (float('inf'),), "inf")
testboth("%F", (float('inf'),), "INF")
# Formatting of long integers. Overflow is not ok # Formatting of long integers. Overflow is not ok
overflowok = 0 overflowok = 0
testboth("%x", 10L, "a") testboth("%x", 10L, "a")

View file

@ -587,9 +587,17 @@ class TypesTests(unittest.TestCase):
test( 1.0, '+f', '+1.000000') test( 1.0, '+f', '+1.000000')
test(-1.0, '+f', '-1.000000') test(-1.0, '+f', '-1.000000')
test(1.1234e90, 'f', '1.1234e+90') test(1.1234e90, 'f', '1.1234e+90')
test(1.1234e90, 'F', '1.1234e+90') test(1.1234e90, 'F', '1.1234E+90')
test(1.1234e200, 'f', '1.1234e+200') test(1.1234e200, 'f', '1.1234e+200')
test(1.1234e200, 'F', '1.1234e+200') test(1.1234e200, 'F', '1.1234E+200')
test(1e100, 'x<20f', '1e+100xxxxxxxxxxxxxx')
test(1e100, 'x<20F', '1E+100xxxxxxxxxxxxxx')
test(float('nan'), 'f', 'nan')
test(float('nan'), 'F', 'NAN')
test(float('inf'), 'f', 'inf')
test(float('inf'), 'F', 'INF')
test(float('-inf'), 'f', '-inf')
test(float('-inf'), 'F', '-INF')
test( 1.0, 'e', '1.000000e+00') test( 1.0, 'e', '1.000000e+00')
test(-1.0, 'e', '-1.000000e+00') test(-1.0, 'e', '-1.000000e+00')

View file

@ -10,6 +10,9 @@ What's New in Python 2.6 beta 2?
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #3382: Make '%F' and float.__format__('F') convert results
to uppercase.
- Issue #3156: Fix inconsistent behavior of the bytearray type: all - Issue #3156: Fix inconsistent behavior of the bytearray type: all
its methods now allow for items objects that can be converted to its methods now allow for items objects that can be converted to
an integer using operator.index(). an integer using operator.index().

View file

@ -741,10 +741,6 @@ format_float_internal(PyObject *value,
/* first, do the conversion as 8-bit chars, using the platform's /* first, do the conversion as 8-bit chars, using the platform's
snprintf. then, if needed, convert to unicode. */ snprintf. then, if needed, convert to unicode. */
/* 'F' is the same as 'f', per the PEP */
if (type == 'F')
type = 'f';
x = PyFloat_AsDouble(value); x = PyFloat_AsDouble(value);
if (x == -1.0 && PyErr_Occurred()) if (x == -1.0 && PyErr_Occurred())
@ -758,8 +754,12 @@ format_float_internal(PyObject *value,
if (precision < 0) if (precision < 0)
precision = 6; precision = 6;
if (type == 'f' && (fabs(x) / 1e25) >= 1e25) if ((type == 'f' || type == 'F') && (fabs(x) / 1e25) >= 1e25) {
type = 'g'; if (type == 'f')
type = 'g';
else
type = 'G';
}
/* cast "type", because if we're in unicode we need to pass a /* cast "type", because if we're in unicode we need to pass a
8-bit char. this is safe, because we've restricted what "type" 8-bit char. this is safe, because we've restricted what "type"

View file

@ -4320,8 +4320,12 @@ formatfloat(char *buf, size_t buflen, int flags,
} }
if (prec < 0) if (prec < 0)
prec = 6; prec = 6;
if (type == 'f' && fabs(x)/1e25 >= 1e25) if ((type == 'f' || type == 'F') && (fabs(x) / 1e25) >= 1e25) {
type = 'g'; if (type == 'f')
type = 'g';
else
type = 'G';
}
/* Worst case length calc to ensure no buffer overrun: /* Worst case length calc to ensure no buffer overrun:
'g' formats: 'g' formats:
@ -4340,7 +4344,8 @@ formatfloat(char *buf, size_t buflen, int flags,
*/ */
if (((type == 'g' || type == 'G') && if (((type == 'g' || type == 'G') &&
buflen <= (size_t)10 + (size_t)prec) || buflen <= (size_t)10 + (size_t)prec) ||
(type == 'f' && buflen <= (size_t)53 + (size_t)prec)) { ((type == 'f' || type == 'F') &&
buflen <= (size_t)53 + (size_t)prec)) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"formatted float is too long (precision too large?)"); "formatted float is too long (precision too large?)");
return -1; return -1;
@ -4910,8 +4915,6 @@ PyString_Format(PyObject *format, PyObject *args)
case 'F': case 'F':
case 'g': case 'g':
case 'G': case 'G':
if (c == 'F')
c = 'f';
pbuf = formatbuf; pbuf = formatbuf;
len = formatfloat(pbuf, sizeof(formatbuf), len = formatfloat(pbuf, sizeof(formatbuf),
flags, prec, c, v); flags, prec, c, v);

View file

@ -8191,8 +8191,12 @@ formatfloat(Py_UNICODE *buf,
return -1; return -1;
if (prec < 0) if (prec < 0)
prec = 6; prec = 6;
if (type == 'f' && (fabs(x) / 1e25) >= 1e25) if ((type == 'f' || type == 'F') && (fabs(x) / 1e25) >= 1e25) {
type = 'g'; if (type == 'f')
type = 'g';
else
type = 'G';
}
/* Worst case length calc to ensure no buffer overrun: /* Worst case length calc to ensure no buffer overrun:
'g' formats: 'g' formats:
@ -8211,7 +8215,8 @@ formatfloat(Py_UNICODE *buf,
*/ */
if (((type == 'g' || type == 'G') && if (((type == 'g' || type == 'G') &&
buflen <= (size_t)10 + (size_t)prec) || buflen <= (size_t)10 + (size_t)prec) ||
(type == 'f' && buflen <= (size_t)53 + (size_t)prec)) { ((type == 'f' || type == 'F') &&
buflen <= (size_t)53 + (size_t)prec)) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"formatted float is too long (precision too large?)"); "formatted float is too long (precision too large?)");
return -1; return -1;
@ -8704,8 +8709,6 @@ PyObject *PyUnicode_Format(PyObject *format,
case 'F': case 'F':
case 'g': case 'g':
case 'G': case 'G':
if (c == 'F')
c = 'f';
pbuf = formatbuf; pbuf = formatbuf;
len = formatfloat(pbuf, sizeof(formatbuf)/sizeof(Py_UNICODE), len = formatfloat(pbuf, sizeof(formatbuf)/sizeof(Py_UNICODE),
flags, prec, c, v); flags, prec, c, v);