Index: Objects/complexobject.c =================================================================== --- Objects/complexobject.c (revision 54183) +++ Objects/complexobject.c (working copy) @@ -252,9 +252,44 @@ PyComplex_AsCComplex(PyObject *op) { Py_complex cv; + PyObject *f, *r, *args; + + /* If op is already of type PyComplex_Type, return its value */ if (PyComplex_Check(op)) { return ((PyComplexObject *)op)->cval; } + /* If not, use op's __complex__ method, if it exists */ + if (PyObject_HasAttrString(op, "__complex__")) { + /* return value of -1 on failure */ + cv.real = -1.; + cv.imag = 0.; + + f = PyObject_GetAttrString(op, "__complex__"); + if (f == NULL) + return cv; + args = PyTuple_New(0); + if (args == NULL) { + Py_DECREF(f); + return cv; + } + r = PyEval_CallObject(f, args); + Py_DECREF(args); + Py_DECREF(f); + if (r == NULL) { + return cv; + } + if (!PyComplex_Check(r)) { + PyErr_SetString(PyExc_TypeError, + "__complex__ should return a complex object"); + Py_DECREF(r); + return cv; + } + cv = ((PyComplexObject *)r)->cval; + Py_DECREF(r); + 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 { cv.real = PyFloat_AsDouble(op); cv.imag = 0.; Index: Doc/api/concrete.tex =================================================================== --- Doc/api/concrete.tex (revision 54183) +++ Doc/api/concrete.tex (working copy) @@ -443,7 +443,9 @@ \begin{cfuncdesc}{double}{PyFloat_AsDouble}{PyObject *pyfloat} Return a C \ctype{double} representation of the contents of - \var{pyfloat}. + \var{pyfloat}. If \var{pyfloat} is not a Python floating point + object but has a \method{__float__} method, this method will first + be called to convert \var{pyfloat} into a float. \end{cfuncdesc} \begin{cfuncdesc}{double}{PyFloat_AS_DOUBLE}{PyObject *pyfloat} @@ -558,8 +560,10 @@ \end{cfuncdesc} \begin{cfuncdesc}{Py_complex}{PyComplex_AsCComplex}{PyObject *op} - Return the \ctype{Py_complex} value of the complex number - \var{op}. + Return the \ctype{Py_complex} value of the complex number \var{op}. + If \var{op} is not a Python complex number object but has a + \method{__complex__} method, this method will first be called to + convert op to a Python complex number object. \end{cfuncdesc}