Index: Objects/unicodeobject.c =================================================================== --- Objects/unicodeobject.c (wersja 79046) +++ Objects/unicodeobject.c (kopia robocza) @@ -8666,6 +8666,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_using_mapping", (PyCFunction) do_string_format_using_mapping, METH_O, format__doc__}, {"__format__", (PyCFunction) unicode__format__, METH_VARARGS, p_format__doc__}, {"_formatter_field_name_split", (PyCFunction) formatter_field_name_split, METH_NOARGS}, {"_formatter_parser", (PyCFunction) formatter_parser, METH_NOARGS}, Index: Objects/stringlib/string_format.h =================================================================== --- Objects/stringlib/string_format.h (wersja 79046) +++ Objects/stringlib/string_format.h (kopia robocza) @@ -496,9 +496,21 @@ if (key == NULL) goto error; if ((kwargs == NULL) || (obj = PyDict_GetItem(kwargs, key)) == NULL) { - PyErr_SetObject(PyExc_KeyError, key); - Py_DECREF(key); - goto error; + PyObject *missing; + static PyObject *missing_str = NULL; + missing = _PyObject_LookupSpecial((PyObject *) kwargs, + "__missing__", + &missing_str); + if (missing != NULL) { + obj = PyObject_CallFunctionObjArgs(missing, key, NULL); + Py_DECREF(missing); + } + else { + PyErr_SetObject(PyExc_KeyError, key); + Py_DECREF(missing); + Py_DECREF(key); + goto error; + } } Py_DECREF(key); Py_INCREF(obj); @@ -1035,6 +1047,11 @@ return build_string(&input, args, kwargs, recursion_depth, &auto_number); } +static PyObject * +do_string_format_using_mapping(PyObject *self, PyObject *obj) +{ + return do_string_format(self, NULL, obj); +} /************************************************************************/