diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 2d3e1ccd90b..e5957ae0d77 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -540,6 +540,7 @@ class BuiltinTest(unittest.TestCase): self.assertEqual(format(3.1415e-104, ""), str(3.1415e-104)) self.assertEqual(format(-3.1415e-104, ""), str(-3.1415e-104)) self.assertEqual(format(object, ""), str(object)) + self.assertEqual(format(None, ""), str(None)) # TypeError because self.__format__ returns the wrong type self.assertRaises(TypeError, format, H(), "") diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py index 4e15340f6c0..4ba825a3356 100644 --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -497,13 +497,25 @@ class LongTest(unittest.TestCase): self.assertEqual(format(123456789, 'd'), '123456789') self.assertEqual(format(123456789, 'd'), '123456789') + # sign and aligning are interdependent + self.assertEqual(format(1, "-"), '1') + self.assertEqual(format(-1, "-"), '-1') + self.assertEqual(format(1, "-3"), ' 1') + self.assertEqual(format(-1, "-3"), ' -1') + self.assertEqual(format(1, "+3"), ' +1') + self.assertEqual(format(-1, "+3"), ' -1') + self.assertEqual(format(1, " 3"), ' 1') + self.assertEqual(format(-1, " 3"), ' -1') + self.assertEqual(format(1, " "), ' 1') + self.assertEqual(format(-1, " "), '-1') + # hex self.assertEqual(format(3, "x"), "3") self.assertEqual(format(3, "X"), "3") self.assertEqual(format(1234, "x"), "4d2") self.assertEqual(format(-1234, "x"), "-4d2") self.assertEqual(format(1234, "8x"), " 4d2") -# XXX fix self.assertEqual(format(-1234, "8x"), " -4d2") + self.assertEqual(format(-1234, "8x"), " -4d2") self.assertEqual(format(1234, "x"), "4d2") self.assertEqual(format(-1234, "x"), "-4d2") self.assertEqual(format(-3, "x"), "-3") @@ -530,7 +542,6 @@ class LongTest(unittest.TestCase): # make sure these are errors self.assertRaises(ValueError, format, 3, "1.3") # precision disallowed - return self.assertRaises(ValueError, format, 3, "+c") # sign not allowed # with 'c' self.assertRaises(ValueError, format, 3, "R") # bogus format type diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py index 47d7236b701..444656a1ba3 100644 --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -379,8 +379,6 @@ class UnicodeTest( self.assertEqual("The year is {0.year}".format(d), "The year is 2007") - #"{0!r:20}".format("Hello") - # classes we'll use for testing class C: def __init__(self, x=100): @@ -428,6 +426,10 @@ class UnicodeTest( def __format__(self, format_spec): return self.strftime(format_spec) + class J(int): + def __format__(self, format_spec): + return int.__format__(self * 2, format_spec) + self.assertEqual(''.format(), '') self.assertEqual('abc'.format(), 'abc') @@ -465,12 +467,6 @@ class UnicodeTest( self.assertEqual('{0[1][0]}'.format(['abc', ['def']]), 'def') self.assertEqual('{0[1][0].x}'.format(['abc', [D('def')]]), 'def') - # I'm not sure if this should work, or if it's a problem if it does work - #'{0[_{foo}]}'.format({'_FOO': 'abc'}, foo='FOO') - #('{0[{foo}{bar}]}'.format({'FOOBAR': 'abc'}, foo='FOO', bar='BAR') - - # format specifiers for built in types - # strings self.assertEqual('{0:.3s}'.format('abc'), 'abc') self.assertEqual('{0:.3s}'.format('ab'), 'ab') @@ -524,6 +520,10 @@ class UnicodeTest( day=27)), "date: 2007-08-27") + # test deriving from a builtin type and overriding __format__ + self.assertEqual("{0}".format(J(10)), "20") + + # string format specifiers self.assertEqual('{0:}'.format('a'), 'a') diff --git a/Objects/stringlib/formatter.h b/Objects/stringlib/formatter.h index c40835024da..8e2b8ef0957 100644 --- a/Objects/stringlib/formatter.h +++ b/Objects/stringlib/formatter.h @@ -145,8 +145,7 @@ parse_internal_render_format_spec(PyObject *format_spec, } /* The special case for 0-padding (backwards compat) */ - if (format->fill_char == '\0' && - end-ptr >= 1 && ptr[0] == '0') { + if (format->fill_char == '\0' && end-ptr >= 1 && ptr[0] == '0') { format->fill_char = '0'; if (format->align == '\0') { format->align = '='; @@ -298,9 +297,10 @@ calc_number_widths(NumberFieldWidths *r, STRINGLIB_CHAR actual_sign, r->n_lpadding = padding / 2; r->n_rpadding = padding - r->n_lpadding; } - else - /* must be '=' */ + else if (format->align == '=') r->n_spadding = padding; + else + r->n_lpadding = padding; } } r->n_total = r->n_lpadding + r->n_lsign + r->n_spadding + @@ -603,7 +603,7 @@ strtounicode(Py_UNICODE *buffer, const char *charbuffer) register Py_ssize_t i; Py_ssize_t len = strlen(charbuffer); for (i = len - 1; i >= 0; i--) - buffer[i] = (Py_UNICODE) charbuffer[i]; + buffer[i] = (Py_UNICODE) charbuffer[i]; return len; } @@ -641,14 +641,14 @@ _format_float(STRINGLIB_CHAR type, PyObject *value, /* Worst case length calc to ensure no buffer overrun: 'g' formats: - fmt = %#.g - buf = '-' + [0-9]*prec + '.' + 'e+' + (longest exp - for any double rep.) - len = 1 + prec + 1 + 2 + 5 = 9 + prec + fmt = %#.g + buf = '-' + [0-9]*prec + '.' + 'e+' + (longest exp + for any double rep.) + len = 1 + prec + 1 + 2 + 5 = 9 + prec 'f' formats: - buf = '-' + [0-9]*x + '.' + [0-9]*prec (with x < 50) - len = 1 + 50 + 1 + prec = 52 + prec + buf = '-' + [0-9]*x + '.' + [0-9]*prec (with x < 50) + len = 1 + 50 + 1 + prec = 52 + prec If prec=0 the effective precision is 1 (the leading digit is always given), therefore increase the length by one. @@ -678,7 +678,7 @@ _format_float(STRINGLIB_CHAR type, PyObject *value, x = PyFloat_AsDouble(value); if (x == -1.0 && PyErr_Occurred()) - goto done; + goto done; if (type == '%') { type = 'f'; @@ -687,9 +687,9 @@ _format_float(STRINGLIB_CHAR type, PyObject *value, } if (precision < 0) - precision = 6; + precision = 6; if (type == 'f' && (fabs(x) / 1e25) >= 1e25) - type = 'g'; + type = 'g'; /* 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"