diff --git a/Doc/library/string.rst b/Doc/library/string.rst --- a/Doc/library/string.rst +++ b/Doc/library/string.rst @@ -114,8 +114,8 @@ to do complex variable substitutions and value formatting via the :meth:`str.format` method described in :pep:`3101`. The :class:`Formatter` class in the :mod:`string` module allows you to create and customize your own -string formatting behaviors using the same implementation as the built-in -:meth:`format` method. +string formatting behaviors using an implementation very similar to that of +the built-in :meth:`format` method. .. class:: Formatter @@ -123,9 +123,27 @@ .. method:: format(format_string, *args, **kwargs) - :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`. + :meth:`Formatter.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`. + + The :meth:`format() ` method can return both 8-bit + strings and Unicode objects when *format_string* is Unicode. Some + examples:: + + >>> f = Formatter() + >>> f.format(u'') + '' + >>> f.format(u'{0}', 'é') + '\xc3\xa9' + >>> f.format(u'H{0}', 'i') + u'Hi' + >>> f.format(u'H{0}', 'é') + Traceback (most recent call last): + ... + UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in \ + position 0: ordinal not in range(128) .. method:: vformat(format_string, args, kwargs) diff --git a/Lib/test/test_string.py b/Lib/test/test_string.py --- a/Lib/test/test_string.py +++ b/Lib/test/test_string.py @@ -110,8 +110,23 @@ self.assertEqual(string.capwords('\taBc\tDeF\t', '\t'), '\tAbc\tDef\t') def test_formatter(self): + def assert_type_equal(a, b): + # Assert that a == b and that their types are equal. + self.assertEqual(a, b) + self.assertEqual(type(a), type(b)) + fmt = string.Formatter() - self.assertEqual(fmt.format("foo"), "foo") + assert_type_equal(fmt.format("foo"), "foo") + # PEP 3101 says that format() should return unicode if the format + # string is unicode, though this is not followed in all cases (e.g. + # see the next example). + assert_type_equal(fmt.format(u"foo"), u"foo") + + # Make sure that passing a non-ascii byte as an argument with a + # Unicode format string doesn't raise an exception (e.g. + # UnicodeDecodeError). Also see issue #15951. In this example, + # "\xc3\xa9" is a UTF-8 encoded "e-acute". + assert_type_equal(fmt.format(u"{0}", "\xc3\xa9"), "\xc3\xa9") self.assertEqual(fmt.format("foo{0}", "bar"), "foobar") self.assertEqual(fmt.format("foo{1}{0}-{1}", "bar", 6), "foo6bar-6")