diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index c436eb64180..8e45bcf18a4 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1542,6 +1542,8 @@ order (MRO) for bases """ return [] def zero(self): return 0 + def complex_num(self): + return 1j def stop(self): raise StopIteration def return_true(self, thing=None): @@ -1575,6 +1577,7 @@ order (MRO) for bases """ set(("__bases__",)), {}), ("__enter__", run_context, iden, set(), {"__exit__" : swallow}), ("__exit__", run_context, swallow, set(), {"__enter__" : iden}), + ("__complex__", complex, complex_num, set(), {}), ] class Checker(object): diff --git a/Misc/NEWS b/Misc/NEWS index 815e3922b9c..1f29728aefb 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,9 @@ What's New in Python 3.2 Alpha 1? Core and Builtins ----------------- +- The __complex__ method is now looked up on the class of instances to make it + consistent with other special methods. + - Issue #7462: Implement the stringlib fast search algorithm for the `rfind`, `rindex`, `rsplit` and `rpartition` methods. Patch by Florent Xicluna. diff --git a/Objects/complexobject.c b/Objects/complexobject.c index 562e41f6f98..73183676a65 100644 --- a/Objects/complexobject.c +++ b/Objects/complexobject.c @@ -262,12 +262,25 @@ PyComplex_ImagAsDouble(PyObject *op) } } +static PyObject * +try_complex_special_method(PyObject *op) { + PyObject *f; + static PyObject *complexstr; + + f = _PyObject_LookupSpecial(op, "__complex__", &complexstr); + if (f) { + PyObject *res = PyObject_CallFunctionObjArgs(f, NULL); + Py_DECREF(f); + return res; + } + return NULL; +} + Py_complex PyComplex_AsCComplex(PyObject *op) { Py_complex cv; PyObject *newop = NULL; - static PyObject *complex_str = NULL; assert(op); /* If op is already of type PyComplex_Type, return its value */ @@ -280,21 +293,7 @@ PyComplex_AsCComplex(PyObject *op) cv.real = -1.; cv.imag = 0.; - if (complex_str == NULL) { - if (!(complex_str = PyUnicode_FromString("__complex__"))) - return cv; - } - - { - PyObject *complexfunc; - complexfunc = _PyType_Lookup(op->ob_type, complex_str); - /* complexfunc is a borrowed reference */ - if (complexfunc) { - newop = PyObject_CallFunctionObjArgs(complexfunc, op, NULL); - if (!newop) - return cv; - } - } + newop = try_complex_special_method(op); if (newop) { if (!PyComplex_Check(newop)) { @@ -307,6 +306,9 @@ PyComplex_AsCComplex(PyObject *op) Py_DECREF(newop); return cv; } + else if (PyErr_Occurred()) { + return cv; + } /* If neither of the above works, interpret op as a float giving the real part of the result, and fill in the imaginary part as 0. */ else { @@ -880,13 +882,12 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v) static PyObject * complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyObject *r, *i, *tmp, *f; + PyObject *r, *i, *tmp; PyNumberMethods *nbr, *nbi = NULL; Py_complex cr, ci; int own_r = 0; int cr_is_complex = 0; int ci_is_complex = 0; - static PyObject *complexstr; static char *kwlist[] = {"real", "imag", 0}; r = Py_False; @@ -921,26 +922,15 @@ complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } - /* XXX Hack to support classes with __complex__ method */ - if (complexstr == NULL) { - complexstr = PyUnicode_InternFromString("__complex__"); - if (complexstr == NULL) - return NULL; - } - f = PyObject_GetAttr(r, complexstr); - if (f == NULL) - PyErr_Clear(); - else { - PyObject *args = PyTuple_New(0); - if (args == NULL) - return NULL; - r = PyEval_CallObject(f, args); - Py_DECREF(args); - Py_DECREF(f); - if (r == NULL) - return NULL; + tmp = try_complex_special_method(r); + if (tmp) { + r = tmp; own_r = 1; } + else if (PyErr_Occurred()) { + return NULL; + } + nbr = r->ob_type->tp_as_number; if (i != NULL) nbi = i->ob_type->tp_as_number;