mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Close SF bug 563740. complex() now finds __complex__() in new style classes.
Made conversion failure error messages consistent between types. Added related unittests.
This commit is contained in:
parent
56f46f8d8c
commit
478d47a168
3 changed files with 36 additions and 28 deletions
|
@ -101,6 +101,17 @@ print 'compile'
|
||||||
compile('print 1\n', '', 'exec')
|
compile('print 1\n', '', 'exec')
|
||||||
|
|
||||||
print 'complex'
|
print 'complex'
|
||||||
|
class OS:
|
||||||
|
def __complex__(self): return 1+10j
|
||||||
|
class NS(object):
|
||||||
|
def __complex__(self): return 1+10j
|
||||||
|
if complex(OS()) != 1+10j: raise TestFailed, '__complex__ in old style class'
|
||||||
|
if complex(NS()) != 1+10j: raise TestFailed, '__complex__ in new style class'
|
||||||
|
if complex("1+10j") != 1+10j: raise TestFailed, 'complex("1+10j")'
|
||||||
|
if complex(10) != 10+0j: raise TestFailed, 'complex(10)'
|
||||||
|
if complex(10.0) != 10+0j: raise TestFailed, 'complex(10.0)'
|
||||||
|
if complex(10L) != 10+0j: raise TestFailed, 'complex(10L)'
|
||||||
|
if complex(10+0j) != 10+0j: raise TestFailed, 'complex(10+0j)'
|
||||||
if complex(1,10) != 1+10j: raise TestFailed, 'complex(1,10)'
|
if complex(1,10) != 1+10j: raise TestFailed, 'complex(1,10)'
|
||||||
if complex(1,10L) != 1+10j: raise TestFailed, 'complex(1,10L)'
|
if complex(1,10L) != 1+10j: raise TestFailed, 'complex(1,10L)'
|
||||||
if complex(1,10.0) != 1+10j: raise TestFailed, 'complex(1,10.0)'
|
if complex(1,10.0) != 1+10j: raise TestFailed, 'complex(1,10.0)'
|
||||||
|
|
|
@ -903,7 +903,7 @@ PyNumber_Int(PyObject *o)
|
||||||
if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
|
if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
|
||||||
return int_from_string((char*)buffer, buffer_len);
|
return int_from_string((char*)buffer, buffer_len);
|
||||||
|
|
||||||
return type_error("object can't be converted to int");
|
return type_error("int() argument must be a string or a number");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add a check for embedded NULL-bytes in the argument. */
|
/* Add a check for embedded NULL-bytes in the argument. */
|
||||||
|
@ -960,7 +960,7 @@ PyNumber_Long(PyObject *o)
|
||||||
if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
|
if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
|
||||||
return long_from_string(buffer, buffer_len);
|
return long_from_string(buffer, buffer_len);
|
||||||
|
|
||||||
return type_error("object can't be converted to long");
|
return type_error("long() argument must be a string or a number");
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
|
|
|
@ -811,10 +811,11 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
PyObject *r, *i, *tmp;
|
PyObject *r, *i, *tmp, *f;
|
||||||
PyNumberMethods *nbr, *nbi = NULL;
|
PyNumberMethods *nbr, *nbi = NULL;
|
||||||
Py_complex cr, ci;
|
Py_complex cr, ci;
|
||||||
int own_r = 0;
|
int own_r = 0;
|
||||||
|
static PyObject *complexstr;
|
||||||
static char *kwlist[] = {"real", "imag", 0};
|
static char *kwlist[] = {"real", "imag", 0};
|
||||||
|
|
||||||
r = Py_False;
|
r = Py_False;
|
||||||
|
@ -837,39 +838,35 @@ complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* XXX Hack to support classes with __complex__ method */
|
||||||
|
if (complexstr == NULL) {
|
||||||
|
complexstr = PyString_InternFromString("__complex__");
|
||||||
|
if (complexstr == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
f = PyObject_GetAttr(r, complexstr);
|
||||||
|
if (f == NULL)
|
||||||
|
PyErr_Clear();
|
||||||
|
else {
|
||||||
|
PyObject *args = Py_BuildValue("()");
|
||||||
|
if (args == NULL)
|
||||||
|
return NULL;
|
||||||
|
r = PyEval_CallObject(f, args);
|
||||||
|
Py_DECREF(args);
|
||||||
|
Py_DECREF(f);
|
||||||
|
if (r == NULL)
|
||||||
|
return NULL;
|
||||||
|
own_r = 1;
|
||||||
|
}
|
||||||
nbr = r->ob_type->tp_as_number;
|
nbr = r->ob_type->tp_as_number;
|
||||||
if (i != NULL)
|
if (i != NULL)
|
||||||
nbi = i->ob_type->tp_as_number;
|
nbi = i->ob_type->tp_as_number;
|
||||||
if (nbr == NULL || nbr->nb_float == NULL ||
|
if (nbr == NULL || nbr->nb_float == NULL ||
|
||||||
((i != NULL) && (nbi == NULL || nbi->nb_float == NULL))) {
|
((i != NULL) && (nbi == NULL || nbi->nb_float == NULL))) {
|
||||||
PyErr_SetString(PyExc_TypeError,
|
PyErr_SetString(PyExc_TypeError,
|
||||||
"complex() arg can't be converted to complex");
|
"complex() argument must be a string or a number");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* XXX Hack to support classes with __complex__ method */
|
|
||||||
if (PyInstance_Check(r)) {
|
|
||||||
static PyObject *complexstr;
|
|
||||||
PyObject *f;
|
|
||||||
if (complexstr == NULL) {
|
|
||||||
complexstr = PyString_InternFromString("__complex__");
|
|
||||||
if (complexstr == NULL)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
f = PyObject_GetAttr(r, complexstr);
|
|
||||||
if (f == NULL)
|
|
||||||
PyErr_Clear();
|
|
||||||
else {
|
|
||||||
PyObject *args = Py_BuildValue("()");
|
|
||||||
if (args == NULL)
|
|
||||||
return NULL;
|
|
||||||
r = PyEval_CallObject(f, args);
|
|
||||||
Py_DECREF(args);
|
|
||||||
Py_DECREF(f);
|
|
||||||
if (r == NULL)
|
|
||||||
return NULL;
|
|
||||||
own_r = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (PyComplex_Check(r)) {
|
if (PyComplex_Check(r)) {
|
||||||
/* Note that if r is of a complex subtype, we're only
|
/* Note that if r is of a complex subtype, we're only
|
||||||
retaining its real & imag parts here, and the return
|
retaining its real & imag parts here, and the return
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue