diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 5568dd5e279..10820ab712e 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1557,6 +1557,8 @@ order (MRO) for bases """ self.assertEqual(key, "hi") return 4 def swallow(*args): pass + def format_impl(self, spec): + return "hello" # It would be nice to have every special method tested here, but I'm # only listing the ones I can remember outside of typeobject.c, since it @@ -1575,6 +1577,7 @@ order (MRO) for bases """ ("__enter__", run_context, iden, set(), {"__exit__" : swallow}), ("__exit__", run_context, swallow, set(), {"__enter__" : iden}), ("__complex__", complex, complex_num, set(), {}), + ("__format__", format, format_impl, set(), {}), ] class Checker(object): diff --git a/Objects/abstract.c b/Objects/abstract.c index 5a904b44d12..1b6c2b42796 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -693,48 +693,36 @@ PyBuffer_Release(Py_buffer *view) PyObject * PyObject_Format(PyObject *obj, PyObject *format_spec) { - static PyObject * str__format__ = NULL; PyObject *meth; PyObject *empty = NULL; PyObject *result = NULL; - - /* Initialize cached value */ - if (str__format__ == NULL) { - /* Initialize static variable needed by _PyType_Lookup */ - str__format__ = PyUnicode_FromString("__format__"); - if (str__format__ == NULL) - goto done; - } + static PyObject *format_cache = NULL; /* If no format_spec is provided, use an empty string */ if (format_spec == NULL) { - empty = PyUnicode_FromUnicode(NULL, 0); - format_spec = empty; + empty = PyUnicode_FromUnicode(NULL, 0); + format_spec = empty; } - /* Make sure the type is initialized. float gets initialized late */ - if (Py_TYPE(obj)->tp_dict == NULL) - if (PyType_Ready(Py_TYPE(obj)) < 0) - goto done; - /* Find the (unbound!) __format__ method (a borrowed reference) */ - meth = _PyType_Lookup(Py_TYPE(obj), str__format__); + meth = _PyObject_LookupSpecial(obj, "__format__", &format_cache); if (meth == NULL) { - PyErr_Format(PyExc_TypeError, - "Type %.100s doesn't define __format__", - Py_TYPE(obj)->tp_name); + if (!PyErr_Occurred()) + PyErr_Format(PyExc_TypeError, + "Type %.100s doesn't define __format__", + Py_TYPE(obj)->tp_name); goto done; } - /* And call it, binding it to the value */ - result = PyObject_CallFunctionObjArgs(meth, obj, format_spec, NULL); + /* And call it. */ + result = PyObject_CallFunctionObjArgs(meth, format_spec, NULL); if (result && !PyUnicode_Check(result)) { - PyErr_SetString(PyExc_TypeError, - "__format__ method did not return string"); - Py_DECREF(result); - result = NULL; - goto done; + PyErr_SetString(PyExc_TypeError, + "__format__ method did not return string"); + Py_DECREF(result); + result = NULL; + goto done; } done: