From c4ab8339e9a966d9d8e601531489a5436d197f47 Mon Sep 17 00:00:00 2001 From: Eric Smith Date: Sun, 29 Nov 2009 17:40:57 +0000 Subject: [PATCH] Issue #3382: Make '%F' and float.__format__('F') convert results to upper case. Much of the patch came from Mark Dickinson. --- Lib/test/formatfloat_testcases.txt | 24 ++++++++++++++++++++++++ Lib/test/test_complex.py | 19 +++++++++++++++++++ Lib/test/test_float.py | 14 ++++++++++++-- Misc/NEWS | 4 ++++ Objects/stringlib/formatter.h | 14 -------------- Objects/stringobject.c | 2 -- Objects/unicodeobject.c | 2 -- 7 files changed, 59 insertions(+), 20 deletions(-) diff --git a/Lib/test/formatfloat_testcases.txt b/Lib/test/formatfloat_testcases.txt index 4cf20aa8c9b..43ef0409543 100644 --- a/Lib/test/formatfloat_testcases.txt +++ b/Lib/test/formatfloat_testcases.txt @@ -81,6 +81,14 @@ %f 0.0000005001 -> 0.000001 %f 0.0000004999 -> 0.000000 +-- nans and infinities +%f nan -> nan +%f inf -> inf +%f -infinity -> -inf +%F nan -> NAN +%F infinity -> INF +%F -inf -> -INF + -- 'e' code formatting with explicit precision (>= 0). Output should -- always have exactly the number of places after the point that were -- requested. @@ -202,6 +210,14 @@ %#.1e 123.4 -> 1.2e+02 %#.2e 0.0001357 -> 1.36e-04 +-- nans and infinities +%e nan -> nan +%e inf -> inf +%e -infinity -> -inf +%E nan -> NAN +%E infinity -> INF +%E -inf -> -INF + -- 'g' code formatting. -- zeros @@ -314,6 +330,14 @@ %#.5g 234.56 -> 234.56 %#.6g 234.56 -> 234.560 +-- nans and infinities +%g nan -> nan +%g inf -> inf +%g -infinity -> -inf +%G nan -> NAN +%G infinity -> INF +%G -inf -> -INF + -- for repr formatting see the separate test_short_repr test in -- test_float.py. Not all platforms use short repr for floats. diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py index a192ec45ac4..a2f4ed505a6 100644 --- a/Lib/test/test_complex.py +++ b/Lib/test/test_complex.py @@ -539,6 +539,25 @@ class ComplexTest(unittest.TestCase): # make sure everything works in ''.format() self.assertEqual('*{0:.3f}*'.format(3.14159+2.71828j), '*3.142+2.718j*') + # issue 3382: 'f' and 'F' with inf's and nan's + self.assertEqual('{0:f}'.format(INF+0j), 'inf+0.000000j') + self.assertEqual('{0:F}'.format(INF+0j), 'INF+0.000000j') + self.assertEqual('{0:f}'.format(-INF+0j), '-inf+0.000000j') + self.assertEqual('{0:F}'.format(-INF+0j), '-INF+0.000000j') + self.assertEqual('{0:f}'.format(complex(INF, INF)), 'inf+infj') + self.assertEqual('{0:F}'.format(complex(INF, INF)), 'INF+INFj') + self.assertEqual('{0:f}'.format(complex(INF, -INF)), 'inf-infj') + self.assertEqual('{0:F}'.format(complex(INF, -INF)), 'INF-INFj') + self.assertEqual('{0:f}'.format(complex(-INF, INF)), '-inf+infj') + self.assertEqual('{0:F}'.format(complex(-INF, INF)), '-INF+INFj') + self.assertEqual('{0:f}'.format(complex(-INF, -INF)), '-inf-infj') + self.assertEqual('{0:F}'.format(complex(-INF, -INF)), '-INF-INFj') + + self.assertEqual('{0:f}'.format(complex(NAN, 0)), 'nan+0.000000j') + self.assertEqual('{0:F}'.format(complex(NAN, 0)), 'NAN+0.000000j') + self.assertEqual('{0:f}'.format(complex(NAN, NAN)), 'nan+nanj') + self.assertEqual('{0:F}'.format(complex(NAN, NAN)), 'NAN+NANj') + def test_main(): test_support.run_unittest(ComplexTest) diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index 4e918fbb2ff..3ad14028819 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -309,6 +309,14 @@ class IEEEFormatTestCase(unittest.TestCase): self.assertRaises(ValueError, format, 1e-100, format_spec) self.assertRaises(ValueError, format, -1e-100, format_spec) + # issue 3382: 'f' and 'F' with inf's and nan's + self.assertEqual('{0:f}'.format(INF), 'inf') + self.assertEqual('{0:F}'.format(INF), 'INF') + self.assertEqual('{0:f}'.format(-INF), '-inf') + self.assertEqual('{0:F}'.format(-INF), '-INF') + self.assertEqual('{0:f}'.format(NAN), 'nan') + self.assertEqual('{0:F}'.format(NAN), 'NAN') + @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"), "test requires IEEE 754 doubles") def test_format_testfile(self): @@ -321,8 +329,10 @@ class IEEEFormatTestCase(unittest.TestCase): lhs, rhs = map(str.strip, line.split('->')) fmt, arg = lhs.split() - self.assertEqual(fmt % float(arg), rhs) - self.assertEqual(fmt % -float(arg), '-' + rhs) + arg = float(arg) + self.assertEqual(fmt % arg, rhs) + if not math.isnan(arg) and copysign(1.0, arg) > 0.0: + self.assertEqual(fmt % -arg, '-' + rhs) def test_issue5864(self): self.assertEquals(format(123.456, '.4'), '123.5') diff --git a/Misc/NEWS b/Misc/NEWS index 2d6b7f0b022..e5c86267773 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,10 @@ What's New in Python 2.7 alpha 1 Core and Builtins ----------------- +- Issue #3382: 'F' formatting for float and complex now convert the + result to upper case. This only affects 'inf' and 'nan', since 'f' + no longer converts to 'g' for large values. + - Remove switch from "%f" formatting to "%g" formatting for floats larger than 1e50 in absolute value. diff --git a/Objects/stringlib/formatter.h b/Objects/stringlib/formatter.h index f09578fa13d..f4a3ea3d581 100644 --- a/Objects/stringlib/formatter.h +++ b/Objects/stringlib/formatter.h @@ -937,13 +937,6 @@ format_float_internal(PyObject *value, format the result. We take care of that later. */ type = 'g'; -#if PY_VERSION_HEX < 0x0301000 - /* 'F' is the same as 'f', per the PEP */ - /* This is no longer the case in 3.x */ - if (type == 'F') - type = 'f'; -#endif - val = PyFloat_AsDouble(value); if (val == -1.0 && PyErr_Occurred()) goto done; @@ -1128,13 +1121,6 @@ format_complex_internal(PyObject *value, format the result. We take care of that later. */ type = 'g'; -#if PY_VERSION_HEX < 0x03010000 - /* This is no longer the case in 3.x */ - /* 'F' is the same as 'f', per the PEP */ - if (type == 'F') - type = 'f'; -#endif - if (precision < 0) precision = default_precision; diff --git a/Objects/stringobject.c b/Objects/stringobject.c index 6636b9af6d8..02aabf2e429 100644 --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -4966,8 +4966,6 @@ PyString_Format(PyObject *format, PyObject *args) case 'F': case 'g': case 'G': - if (c == 'F') - c = 'f'; temp = formatfloat(v, flags, prec, c); if (temp == NULL) goto error; diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 2fa004eae13..e85b20fa031 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -8809,8 +8809,6 @@ PyObject *PyUnicode_Format(PyObject *format, case 'F': case 'g': case 'G': - if (c == 'F') - c = 'f'; temp = formatfloat(v, flags, prec, c); if (temp == NULL) goto onError;