
Campbell Barton wrote:
Hrvoje Niksic wrote:
double PyNumber_AsDouble(PyObject * value) { if (PyFloat_Check(value) || PyInt_Check(value)) { return PyFloat_AsDouble(value); } else { PyObject *pyfloat; double d;
pyfloat = PyNumber_Float(value); d = PyNumber_AsDouble(pyfloat);
I assume this should be PyFloat_AsDouble?
Py_XDECREF(pyfloat); return d;
} }
What happens if PyNumber_Float raises an exception? As far as I can tell, PyNumber_AsDouble will result in a "bad argument" exception being raised and will return -1, losing track of the original exception in the process.
Come to think of it, error checking problems could very well be the reason why the API doesn't provide a PyNumber_AsDouble.
It is a problem but I dont think thats a good enough reason not to have some way to do this since its such a common operation.
PyFloat_AsDouble cant return an error value, so enforcing that the pyobject is checked with PyNumber_Check seems reasonable to me.
To follow up on this issue, Iv added the function below to a branch of the Blender/Py API so Numbers that aren't pythons Ints of Floats work.
double EXPP_PyNumber_AsDouble(PyObject * value) { if (PyFloat_Check(value) || PyInt_Check(value)) { return PyFloat_AS_DOUBLE(value); } else { PyObject *pyfloat; double d;
pyfloat = PyNumber_Float(value);
d = PyFloat_AsDouble(pyfloat);
Py_XDECREF(pyfloat);
return d; /* will be -1 and set an error if its PyNumber_Float failed */
}
}
from looking at pythons source there are 2 ways to make sure this function succeeds.
I was under the impression the only way to do error checking for this was to do....
float f; if (!PyFloat_Check(pyob)) { PyErr_SetString(PyExc_TypeError, "float argument required"); return -1; } f = PyFloat_AS_DOUBLE(pyob)
But another way to do it is.... (used in python 2.5.1's stringobject.c:4150)
float f = PyFloat_Check(pyob); if (f == -1.0 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "float argument required"); return -1; }
Which would work with EXPP_PyNumber_AsDouble to do error checking as well. so I think error checking is ok with that function. (and would like to see PyNumber_AsDouble in the C/Python API hint, hint)
However Im wondering if this is advisable, with PyErr_Occurred() its possible that some other part of the API (even a totaly separate API) sets the error string but dosnt return an error value. - Any suggestions?