summaryrefslogtreecommitdiffstats
path: root/Objects/abstract.c
diff options
context:
space:
mode:
authorBrett Cannon <bcannon@gmail.com>2005-04-26 03:45:26 (GMT)
committerBrett Cannon <bcannon@gmail.com>2005-04-26 03:45:26 (GMT)
commitc3647ac93e2a38762de8a23b1d94a6380e9ad468 (patch)
treea7e00a7e8f70ee226fdeb3d229b9734d5b17a344 /Objects/abstract.c
parentd7c795e72966f7c72b94b919f3539be66495e6c3 (diff)
downloadcpython-c3647ac93e2a38762de8a23b1d94a6380e9ad468.zip
cpython-c3647ac93e2a38762de8a23b1d94a6380e9ad468.tar.gz
cpython-c3647ac93e2a38762de8a23b1d94a6380e9ad468.tar.bz2
Make subclasses of int, long, complex, float, and unicode perform type
conversion using the proper magic slot (e.g., __int__()). Also move conversion code out of PyNumber_*() functions in the C API into the nb_* function. Applied patch #1109424. Thanks Walter Doewald.
Diffstat (limited to 'Objects/abstract.c')
-rw-r--r--Objects/abstract.c84
1 files changed, 37 insertions, 47 deletions
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 875c880..d28006a 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -951,7 +951,19 @@ PyNumber_Int(PyObject *o)
Py_INCREF(o);
return o;
}
- if (PyInt_Check(o)) {
+ m = o->ob_type->tp_as_number;
+ if (m && m->nb_int) { /* This should include subclasses of int */
+ PyObject *res = m->nb_int(o);
+ if (res && (!PyInt_Check(res) && !PyLong_Check(res))) {
+ PyErr_Format(PyExc_TypeError,
+ "__int__ returned non-int (type %.200s)",
+ res->ob_type->tp_name);
+ Py_DECREF(res);
+ return NULL;
+ }
+ return res;
+ }
+ if (PyInt_Check(o)) { /* A int subclass without nb_int */
PyIntObject *io = (PyIntObject*)o;
return PyInt_FromLong(io->ob_ival);
}
@@ -964,18 +976,6 @@ PyNumber_Int(PyObject *o)
PyUnicode_GET_SIZE(o),
10);
#endif
- m = o->ob_type->tp_as_number;
- if (m && m->nb_int) {
- PyObject *res = m->nb_int(o);
- if (res && (!PyInt_Check(res) && !PyLong_Check(res))) {
- PyErr_Format(PyExc_TypeError,
- "__int__ returned non-int (type %.200s)",
- res->ob_type->tp_name);
- Py_DECREF(res);
- return NULL;
- }
- return res;
- }
if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
return int_from_string((char*)buffer, buffer_len);
@@ -1010,11 +1010,19 @@ PyNumber_Long(PyObject *o)
if (o == NULL)
return null_error();
- if (PyLong_CheckExact(o)) {
- Py_INCREF(o);
- return o;
+ m = o->ob_type->tp_as_number;
+ if (m && m->nb_long) { /* This should include subclasses of long */
+ PyObject *res = m->nb_long(o);
+ if (res && (!PyInt_Check(res) && !PyLong_Check(res))) {
+ PyErr_Format(PyExc_TypeError,
+ "__long__ returned non-long (type %.200s)",
+ res->ob_type->tp_name);
+ Py_DECREF(res);
+ return NULL;
+ }
+ return res;
}
- if (PyLong_Check(o))
+ if (PyLong_Check(o)) /* A long subclass without nb_long */
return _PyLong_Copy((PyLongObject *)o);
if (PyString_Check(o))
/* need to do extra error checking that PyLong_FromString()
@@ -1030,18 +1038,6 @@ PyNumber_Long(PyObject *o)
PyUnicode_GET_SIZE(o),
10);
#endif
- m = o->ob_type->tp_as_number;
- if (m && m->nb_long) {
- PyObject *res = m->nb_long(o);
- if (res && (!PyInt_Check(res) && !PyLong_Check(res))) {
- PyErr_Format(PyExc_TypeError,
- "__long__ returned non-long (type %.200s)",
- res->ob_type->tp_name);
- Py_DECREF(res);
- return NULL;
- }
- return res;
- }
if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
return long_from_string(buffer, buffer_len);
@@ -1055,28 +1051,22 @@ PyNumber_Float(PyObject *o)
if (o == NULL)
return null_error();
- if (PyFloat_CheckExact(o)) {
- Py_INCREF(o);
- return o;
+ m = o->ob_type->tp_as_number;
+ if (m && m->nb_float) { /* This should include subclasses of float */
+ PyObject *res = m->nb_float(o);
+ if (res && !PyFloat_Check(res)) {
+ PyErr_Format(PyExc_TypeError,
+ "__float__ returned non-float (type %.200s)",
+ res->ob_type->tp_name);
+ Py_DECREF(res);
+ return NULL;
+ }
+ return res;
}
- if (PyFloat_Check(o)) {
+ if (PyFloat_Check(o)) { /* A float subclass with nb_float == NULL */
PyFloatObject *po = (PyFloatObject *)o;
return PyFloat_FromDouble(po->ob_fval);
}
- if (!PyString_Check(o)) {
- m = o->ob_type->tp_as_number;
- if (m && m->nb_float) {
- PyObject *res = m->nb_float(o);
- if (res && !PyFloat_Check(res)) {
- PyErr_Format(PyExc_TypeError,
- "__float__ returned non-float (type %.200s)",
- res->ob_type->tp_name);
- Py_DECREF(res);
- return NULL;
- }
- return res;
- }
- }
return PyFloat_FromString(o, NULL);
}