From: Benjamin Peterson Date: Sat, 5 Jun 2010 00:32:50 +0000 (+0000) Subject: properly lookup the __format__ special method X-Git-Tag: v2.7rc1~29 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2aa6c38237535cbcfbf7ab079c960322c9a7f2c3;p=python properly lookup the __format__ special method --- diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index d450eed585..2fdd62fc4f 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1697,6 +1697,8 @@ order (MRO) for bases """ def some_number(self_, key): self.assertEqual(key, "hi") return 4 + 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 @@ -1715,6 +1717,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 761e035da3..898becd245 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -723,7 +723,6 @@ PyBuffer_Release(Py_buffer *view) PyObject * PyObject_Format(PyObject* obj, PyObject *format_spec) { - static PyObject * str__format__ = NULL; PyObject *empty = NULL; PyObject *result = NULL; #ifdef Py_USING_UNICODE @@ -731,14 +730,6 @@ PyObject_Format(PyObject* obj, PyObject *format_spec) int result_is_unicode; #endif - /* Initialize cached value */ - if (str__format__ == NULL) { - /* Initialize static variable needed by _PyType_Lookup */ - str__format__ = PyString_InternFromString("__format__"); - if (str__format__ == NULL) - goto done; - } - /* If no format_spec is provided, use an empty string */ if (format_spec == NULL) { empty = PyString_FromStringAndSize(NULL, 0); @@ -769,8 +760,7 @@ PyObject_Format(PyObject* obj, PyObject *format_spec) /* Check for a __format__ method and call it. */ if (PyInstance_Check(obj)) { /* We're an instance of a classic class */ - PyObject *bound_method = PyObject_GetAttr(obj, - str__format__); + PyObject *bound_method = PyObject_GetAttrString(obj, "__format__"); if (bound_method != NULL) { result = PyObject_CallFunctionObjArgs(bound_method, format_spec, @@ -820,8 +810,7 @@ PyObject_Format(PyObject* obj, PyObject *format_spec) } /* Then call str.__format__ on that result */ - format_method = PyObject_GetAttr(self_as_str, - str__format__); + format_method = PyObject_GetAttrString(self_as_str, "__format__"); if (format_method == NULL) { goto done1; } @@ -837,20 +826,21 @@ done1: } else { /* Not an instance of a classic class, use the code from py3k */ + static PyObject *format_cache; /* Find the (unbound!) __format__ method (a borrowed reference) */ - PyObject *method = _PyType_Lookup(Py_TYPE(obj), - str__format__); + PyObject *method = _PyObject_LookupSpecial(obj, "__format__", + &format_cache); if (method == 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(method, obj, - format_spec, NULL); + /* And call it. */ + result = PyObject_CallFunctionObjArgs(method, format_spec, NULL); } if (result == NULL)