summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2007-03-17 16:08:45 (GMT)
committerGeorg Brandl <georg@python.org>2007-03-17 16:08:45 (GMT)
commit2b869943fa284be9f3b9572df10b334f12962aa6 (patch)
tree4b14375b0251356b2399d78107c2cb3d4f7fc111 /Objects
parent6f187743ffbce522c9d686ae5393272c1eb85dcc (diff)
downloadcpython-2b869943fa284be9f3b9572df10b334f12962aa6.zip
cpython-2b869943fa284be9f3b9572df10b334f12962aa6.tar.gz
cpython-2b869943fa284be9f3b9572df10b334f12962aa6.tar.bz2
Patch #1675423: PyComplex_AsCComplex() now tries to convert an object
to complex using its __complex__() method before falling back to the __float__() method. Therefore, the functions in the cmath module now can operate on objects that define a __complex__() method. (backport)
Diffstat (limited to 'Objects')
-rw-r--r--Objects/complexobject.c49
1 files changed, 48 insertions, 1 deletions
diff --git a/Objects/complexobject.c b/Objects/complexobject.c
index 54ad075..a8a2188 100644
--- a/Objects/complexobject.c
+++ b/Objects/complexobject.c
@@ -252,12 +252,59 @@ 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 */
if (PyComplex_Check(op)) {
return ((PyComplexObject *)op)->cval;
}
+ /* If not, use op's __complex__ method, if it exists */
+
+ /* return -1 on failure */
+ cv.real = -1.;
+ cv.imag = 0.;
+
+ if (PyInstance_Check(op)) {
+ /* this can go away in python 3000 */
+ if (PyObject_HasAttrString(op, "__complex__")) {
+ newop = PyObject_CallMethod(op, "__complex__", NULL);
+ if (!newop)
+ return cv;
+ }
+ /* else try __float__ */
+ } else {
+ PyObject *complexfunc;
+ if (!complex_str) {
+ if (!(complex_str = PyString_FromString("__complex__")))
+ return cv;
+ }
+ 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;
+ }
+ }
+
+ if (newop) {
+ if (!PyComplex_Check(newop)) {
+ PyErr_SetString(PyExc_TypeError,
+ "__complex__ should return a complex object");
+ Py_DECREF(newop);
+ return cv;
+ }
+ cv = ((PyComplexObject *)newop)->cval;
+ Py_DECREF(newop);
+ 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 {
+ /* PyFloat_AsDouble will return -1 on failure */
cv.real = PyFloat_AsDouble(op);
- cv.imag = 0.;
return cv;
}
}