diff options
author | Benjamin Peterson <benjamin@python.org> | 2010-06-05 00:32:50 (GMT) |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2010-06-05 00:32:50 (GMT) |
commit | 2aa6c38237535cbcfbf7ab079c960322c9a7f2c3 (patch) | |
tree | fc6764d3e2195dbd1ba6955d80351d292ec88bbb | |
parent | e7e505ba6e2ba1768ba81e9dde652b6aff34c386 (diff) | |
download | cpython-2aa6c38237535cbcfbf7ab079c960322c9a7f2c3.zip cpython-2aa6c38237535cbcfbf7ab079c960322c9a7f2c3.tar.gz cpython-2aa6c38237535cbcfbf7ab079c960322c9a7f2c3.tar.bz2 |
properly lookup the __format__ special method
-rw-r--r-- | Lib/test/test_descr.py | 3 | ||||
-rw-r--r-- | Objects/abstract.c | 32 |
2 files changed, 14 insertions, 21 deletions
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index d450eed..2fdd62f 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 761e035..898becd 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) |