[Python-checkins] r86170 - in python/branches/py3k: Doc/library/stdtypes.rst Lib/test/test_unicode.py Misc/NEWS Objects/stringlib/string_format.h Objects/unicodeobject.c

Ezio Melotti ezio.melotti at gmail.com
Sat Nov 6 06:16:48 CET 2010


Hi,

On 04/11/2010 19.06, eric.smith wrote:
> Author: eric.smith
> Date: Thu Nov  4 18:06:58 2010
> New Revision: 86170
>
> Log:
> Issue #6081: Add str.format_map. str.format_map(mapping) is similar to str.format(**mapping), except mapping does not get converted to a dict.
>
> Modified:
>     python/branches/py3k/Doc/library/stdtypes.rst
>     python/branches/py3k/Lib/test/test_unicode.py
>     python/branches/py3k/Misc/NEWS
>     python/branches/py3k/Objects/stringlib/string_format.h
>     python/branches/py3k/Objects/unicodeobject.c
>
> Modified: python/branches/py3k/Doc/library/stdtypes.rst
> ==============================================================================
> --- python/branches/py3k/Doc/library/stdtypes.rst	(original)
> +++ python/branches/py3k/Doc/library/stdtypes.rst	Thu Nov  4 18:06:58 2010
> @@ -1038,6 +1038,14 @@
>      that can be specified in format strings.
>
>
> +.. method:: str.format_map(mapping)
> +
> +   Similar to ``str.forrmat(**mapping)``, except that ``mapping`` is
> +   used directly and not copied to a :class:`dict` .  This is useful
> +   if for example ``mapping`` is a dict subclass.


Including the "__missing__" example might be better. From the 
description, it's not clear why str.format(**dict_subclass) wouldn't 
work and that the previous line refers to the fact that ** converts the 
mapping in a plain dict, thus making __missing__ and other things unusable.


> +
> +    .. versionadded:: 3.2
> +
>   .. method:: str.index(sub[, start[, end]])
>
>      Like :meth:`find`, but raise :exc:`ValueError` when the substring is not found.
>
> Modified: python/branches/py3k/Lib/test/test_unicode.py
> ==============================================================================
> --- python/branches/py3k/Lib/test/test_unicode.py	(original)
> +++ python/branches/py3k/Lib/test/test_unicode.py	Thu Nov  4 18:06:58 2010
> @@ -695,6 +695,84 @@
>           self.assertRaises(ValueError, format, '', '#')
>           self.assertRaises(ValueError, format, '', '#20')
>
> +    def test_format_map(self):
> +        self.assertEqual(''.format_map({}), '')
> +        self.assertEqual('a'.format_map({}), 'a')
> +        self.assertEqual('ab'.format_map({}), 'ab')
> +        self.assertEqual('a{{'.format_map({}), 'a{')
> +        self.assertEqual('a}}'.format_map({}), 'a}')
> +        self.assertEqual('{{b'.format_map({}), '{b')
> +        self.assertEqual('}}b'.format_map({}), '}b')
> +        self.assertEqual('a{{b'.format_map({}), 'a{b')
> +
> +        # using mappings
> +        class Mapping(dict):
> +            def __missing__(self, key):
> +                return key
> +        self.assertEqual('{hello}'.format_map(Mapping()), 'hello')
> +        self.assertEqual('{a} {world}'.format_map(Mapping(a='hello')), 'hello world')
> +
> +        class InternalMapping:
> +            def __init__(self):
> +                self.mapping = {'a': 'hello'}
> +            def __getitem__(self, key):
> +                return self.mapping[key]
> +        self.assertEqual('{a}'.format_map(InternalMapping()), 'hello')
> +
> +
> +        # classes we'll use for testing
> +        class C:
> +            def __init__(self, x=100):
> +                self._x = x
> +            def __format__(self, spec):
> +                return spec
> +
> +        class D:
> +            def __init__(self, x):
> +                self.x = x
> +            def __format__(self, spec):
> +                return str(self.x)
> +
> +        # class with __str__, but no __format__
> +        class E:
> +            def __init__(self, x):
> +                self.x = x
> +            def __str__(self):
> +                return 'E(' + self.x + ')'
> +
> +        # class with __repr__, but no __format__ or __str__
> +        class F:
> +            def __init__(self, x):
> +                self.x = x
> +            def __repr__(self):
> +                return 'F(' + self.x + ')'
> +
> +        # class with __format__ that forwards to string, for some format_spec's
> +        class G:
> +            def __init__(self, x):
> +                self.x = x
> +            def __str__(self):
> +                return "string is " + self.x
> +            def __format__(self, format_spec):
> +                if format_spec == 'd':
> +                    return 'G(' + self.x + ')'
> +                return object.__format__(self, format_spec)
> +
> +        # class that returns a bad type from __format__
> +        class H:
> +            def __format__(self, format_spec):
> +                return 1.0
> +
> +        self.assertEqual('{foo._x}'.format_map({'foo': C(20)}), '20')
> +


The classes D-H seem unused, did you forget to add some tests or am I 
missing something?


> +        # test various errors
> +        self.assertRaises(TypeError, '{'.format_map)
> +        self.assertRaises(TypeError, '}'.format_map)
> +        self.assertRaises(TypeError, 'a{'.format_map)
> +        self.assertRaises(TypeError, 'a}'.format_map)
> +        self.assertRaises(TypeError, '{a'.format_map)
> +        self.assertRaises(TypeError, '}a'.format_map)
> +
>       def test_format_auto_numbering(self):
>           class C:
>               def __init__(self, x=100):
>
> Modified: python/branches/py3k/Misc/NEWS
> ==============================================================================
> --- python/branches/py3k/Misc/NEWS	(original)
> +++ python/branches/py3k/Misc/NEWS	Thu Nov  4 18:06:58 2010
> @@ -10,6 +10,8 @@
>   Core and Builtins
>   -----------------
>
> +- Issue #6081: Add str.format_map, similar to str.format(**mapping).
> +
>   - If FileIO.__init__ fails, close the file descriptor.
>
>   - Issue #10221: dict.pop(k) now has a key error message that includes the
>
> Modified: python/branches/py3k/Objects/stringlib/string_format.h
> ==============================================================================
> --- python/branches/py3k/Objects/stringlib/string_format.h	(original)
> +++ python/branches/py3k/Objects/stringlib/string_format.h	Thu Nov  4 18:06:58 2010
> @@ -499,7 +499,11 @@
>           PyObject *key = SubString_new_object(&first);
>           if (key == NULL)
>               goto error;
> -        if ((kwargs == NULL) || (obj = PyDict_GetItem(kwargs, key)) == NULL) {
> +
> +        /* Use PyObject_GetItem instead of PyDict_GetItem because this
> +           code is no longer just used with kwargs. It might be passed
> +           a non-dict when called through format_map. */
> +        if ((kwargs == NULL) || (obj = PyObject_GetItem(kwargs, key)) == NULL) {
>               PyErr_SetObject(PyExc_KeyError, key);
>               Py_DECREF(key);
>               goto error;
> @@ -1039,6 +1043,11 @@
>       return build_string(&input, args, kwargs, recursion_depth,&auto_number);
>   }
>
> +static PyObject *
> +do_string_format_map(PyObject *self, PyObject *obj)
> +{
> +    return do_string_format(self, NULL, obj);
> +}
>
>
>   /************************************************************************/
>
> Modified: python/branches/py3k/Objects/unicodeobject.c
> ==============================================================================
> --- python/branches/py3k/Objects/unicodeobject.c	(original)
> +++ python/branches/py3k/Objects/unicodeobject.c	Thu Nov  4 18:06:58 2010
> @@ -9028,6 +9028,11 @@
>   \n\
>   ");
>
> +PyDoc_STRVAR(format_map__doc__,
> +             "S.format_map(mapping) ->  str\n\
> +\n\
> +");
> +


Wouldn't a more verbose docstring be better? (str.format seems to lack 
one too)


>   static PyObject *
>   unicode__format__(PyObject* self, PyObject* args)
>   {
> @@ -9109,6 +9114,7 @@
>       {"isprintable", (PyCFunction) unicode_isprintable, METH_NOARGS, isprintable__doc__},
>       {"zfill", (PyCFunction) unicode_zfill, METH_VARARGS, zfill__doc__},
>       {"format", (PyCFunction) do_string_format, METH_VARARGS | METH_KEYWORDS, format__doc__},
> +    {"format_map", (PyCFunction) do_string_format_map, METH_O, format_map__doc__},
>       {"__format__", (PyCFunction) unicode__format__, METH_VARARGS, p_format__doc__},
>       {"maketrans", (PyCFunction) unicode_maketrans,
>        METH_VARARGS | METH_STATIC, maketrans__doc__},
> _______________________________________________
> Python-checkins mailing list
> Python-checkins at python.org
> http://mail.python.org/mailman/listinfo/python-checkins
>

Best Regards,
Ezio Melotti


More information about the Python-checkins mailing list