diff -r 47288880cc9e Doc/library/string.rst --- a/Doc/library/string.rst Fri Feb 17 19:58:41 2012 -0500 +++ b/Doc/library/string.rst Sat Feb 18 12:51:49 2012 +0100 @@ -91,8 +91,8 @@ .. method:: format(format_string, *args, **kwargs) - :meth:`format` is the primary API method. It takes a format template - string, and an arbitrary set of positional and keyword argument. + :meth:`format` is the primary API method. It takes a format string and + an arbitrary set of positional and keyword arguments. :meth:`format` is just a wrapper that calls :meth:`vformat`. .. method:: vformat(format_string, args, kwargs) @@ -101,8 +101,8 @@ separate function for cases where you want to pass in a predefined dictionary of arguments, rather than unpacking and repacking the dictionary as individual arguments using the ``*args`` and ``**kwds`` - syntax. :meth:`vformat` does the work of breaking up the format template - string into character data and replacement fields. It calls the various + syntax. :meth:`vformat` does the work of breaking up the format string + into character data and replacement fields. It calls the various methods described below. In addition, the :class:`Formatter` defines a number of methods that are @@ -173,7 +173,8 @@ Converts the value (returned by :meth:`get_field`) given a conversion type (as in the tuple returned by the :meth:`parse` method). The default - version understands 'r' (repr) and 's' (str) conversion types. + version understands 's' (str), 'r' (repr) and 'a' (ascii) conversion + types. .. _formatstrings: @@ -202,9 +203,9 @@ conversion: "r" | "s" | "a" format_spec: -In less formal terms, the replacement field can start with a *field_name* that specifies -the object whose value is to be formatted and inserted -into the output instead of the replacement field. +In less formal terms, the replacement field can start with a *field_name* that +specifies the object whose value is to be formatted and inserted into the +output instead of the replacement field. The *field_name* is optionally followed by a *conversion* field, which is preceded by an exclamation point ``'!'``, and a *format_spec*, which is preceded by a colon ``':'``. These specify a non-default format for the replacement value. @@ -212,10 +213,10 @@ See also the :ref:`formatspec` section. The *field_name* itself begins with an *arg_name* that is either a number or a -keyword. If it's a number, it refers to a positional argument, and if it's a keyword, -it refers to a named keyword argument. If the numerical arg_names in a format string -are 0, 1, 2, ... in sequence, they can all be omitted (not just some) -and the numbers 0, 1, 2, ... will be automatically inserted in that order. +keyword. If it's a number, it refers to a positional argument, and if it's a +keyword, it refers to a named keyword argument. If the numerical arg_names in +a format string are 0, 1, 2, ... in sequence, they can all be omitted (not just +some) and the numbers 0, 1, 2, ... will be automatically inserted in that order. Because *arg_name* is not quote-delimited, it is not possible to specify arbitrary dictionary keys (e.g., the strings ``'10'`` or ``':-]'``) within a format string. The *arg_name* can be followed by any number of index or diff -r 47288880cc9e Lib/string.py --- a/Lib/string.py Fri Feb 17 19:58:41 2012 -0500 +++ b/Lib/string.py Sat Feb 18 12:51:49 2012 +0100 @@ -195,7 +195,7 @@ # expand the format spec, if needed format_spec = self._vformat(format_spec, args, kwargs, - used_args, recursion_depth-1) + used_args, recursion_depth - 1) # format the object and append to the result result.append(self.format_field(obj, format_spec)) @@ -220,12 +220,14 @@ def convert_field(self, value, conversion): # do any conversion on the resulting object - if conversion == 'r': - return repr(value) + if conversion is None: + return value elif conversion == 's': return str(value) - elif conversion is None: - return value + elif conversion == 'r': + return repr(value) + elif conversion == 'a': + return ascii(value) raise ValueError("Unknown conversion specifier {0!s}".format(conversion)) diff -r 47288880cc9e Lib/test/test_string.py --- a/Lib/test/test_string.py Fri Feb 17 19:58:41 2012 -0500 +++ b/Lib/test/test_string.py Sat Feb 18 12:51:49 2012 +0100 @@ -38,6 +38,9 @@ self.assertEqual(fmt.format("{0!s}", 'test'), 'test') self.assertRaises(ValueError, fmt.format, "{0!h}", 'test') + # issue13579 + self.assertEqual(fmt.format("{0!a}", 42), '42') + def test_name_lookup(self): fmt = string.Formatter() class AnyAttr: diff -r 47288880cc9e Misc/NEWS --- a/Misc/NEWS Fri Feb 17 19:58:41 2012 -0500 +++ b/Misc/NEWS Sat Feb 18 12:51:49 2012 +0100 @@ -7067,6 +7067,8 @@ Library ------- +- Issue #13579: string.Formatter now understands the !a conversion specifier. + - Issue #7071: byte-compilation in Distutils is now done with respect to sys.dont_write_bytecode. @@ -7555,6 +7557,7 @@ - Windows locale mapping updated to Vista. + Tools/Demos -----------