[Python-checkins] r78280 - in python/trunk: Doc/reference/datamodel.rst Lib/test/test_complex.py Misc/NEWS Objects/complexobject.c

mark.dickinson python-checkins at python.org
Sun Feb 21 13:57:35 CET 2010


Author: mark.dickinson
Date: Sun Feb 21 13:57:35 2010
New Revision: 78280
Log:
Fix complex type to avoid implicit calls to complex.__coerce__.
Modified:
 python/trunk/Doc/reference/datamodel.rst
 python/trunk/Lib/test/test_complex.py
 python/trunk/Misc/NEWS
 python/trunk/Objects/complexobject.c
Modified: python/trunk/Doc/reference/datamodel.rst
==============================================================================
--- python/trunk/Doc/reference/datamodel.rst	(original)
+++ python/trunk/Doc/reference/datamodel.rst	Sun Feb 21 13:57:35 2010
@@ -2271,13 +2271,15 @@
 *
 
 In the current implementation, the built-in numeric types :class:`int`,
- :class:`long` and :class:`float` do not use coercion; the type :class:`complex`
- however does use coercion for binary operators and rich comparisons, despite
- the above rules. The difference can become apparent when subclassing these
- types. Over time, the type :class:`complex` may be fixed to avoid coercion.
+ :class:`long`, :class:`float`, and :class:`complex` do not use coercion.
 All these types implement a :meth:`__coerce__` method, for use by the built-in
 :func:`coerce` function.
 
+ .. versionchanged:: 2.7
+
+ The complex type no longer makes implicit calls to the :meth:`__coerce__`
+ method for mixed-type binary arithmetic operations.
+
 
 .. _context-managers:
 
Modified: python/trunk/Lib/test/test_complex.py
==============================================================================
--- python/trunk/Lib/test/test_complex.py	(original)
+++ python/trunk/Lib/test/test_complex.py	Sun Feb 21 13:57:35 2010
@@ -358,6 +358,61 @@
 self.assertAlmostEqual(complex(complex1(1j)), 2j)
 self.assertRaises(TypeError, complex, complex2(1j))
 
+ def test_subclass(self):
+ class xcomplex(complex):
+ def __add__(self,other):
+ return xcomplex(complex(self) + other)
+ __radd__ = __add__
+
+ def __sub__(self,other):
+ return xcomplex(complex(self) + other)
+ __rsub__ = __sub__
+
+ def __mul__(self,other):
+ return xcomplex(complex(self) * other)
+ __rmul__ = __mul__
+
+ def __div__(self,other):
+ return xcomplex(complex(self) / other)
+
+ def __rdiv__(self,other):
+ return xcomplex(other / complex(self))
+
+ __truediv__ = __div__
+ __rtruediv__ = __rdiv__
+
+ def __floordiv__(self,other):
+ return xcomplex(complex(self) // other)
+
+ def __rfloordiv__(self,other):
+ return xcomplex(other // complex(self))
+
+ def __pow__(self,other):
+ return xcomplex(complex(self) ** other)
+
+ def __rpow__(self,other):
+ return xcomplex(other ** complex(self) )
+
+ def __mod__(self,other):
+ return xcomplex(complex(self) % other)
+
+ def __rmod__(self,other):
+ return xcomplex(other % complex(self))
+
+ infix_binops = ('+', '-', '*', '**', '%', '//', '/')
+ xcomplex_values = (xcomplex(1), xcomplex(123.0),
+ xcomplex(-10+2j), xcomplex(3+187j),
+ xcomplex(3-78j))
+ test_values = (1, 123.0, 10-19j, xcomplex(1+2j),
+ xcomplex(1+87j), xcomplex(10+90j))
+
+ for op in infix_binops:
+ for x in xcomplex_values:
+ for y in test_values:
+ a = 'x %s y' % op
+ b = 'y %s x' % op
+ self.assertTrue(type(eval(a)) is type(eval(b)) is xcomplex)
+
 def test_hash(self):
 for x in xrange(-30, 30):
 self.assertEqual(hash(x), hash(complex(x, 0)))
Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Sun Feb 21 13:57:35 2010
@@ -12,6 +12,9 @@
 Core and Builtins
 -----------------
 
+- Issue #5211: the complex type no longer uses implicit coercion in
+ mixed-type binary arithmetic operations.
+
 Library
 -------
 
Modified: python/trunk/Objects/complexobject.c
==============================================================================
--- python/trunk/Objects/complexobject.c	(original)
+++ python/trunk/Objects/complexobject.c	Sun Feb 21 13:57:35 2010
@@ -513,43 +513,54 @@
 		
 
 static PyObject *
-complex_add(PyComplexObject *v, PyComplexObject *w)
+complex_add(PyObject *v, PyObject *w)
 {
 	Py_complex result;
+	Py_complex a, b;
+	TO_COMPLEX(v, a);
+	TO_COMPLEX(w, b);
 	PyFPE_START_PROTECT("complex_add", return 0)
-	result = c_sum(v->cval,w->cval);
+	result = c_sum(a, b);
 	PyFPE_END_PROTECT(result)
 	return PyComplex_FromCComplex(result);
 }
 
 static PyObject *
-complex_sub(PyComplexObject *v, PyComplexObject *w)
+complex_sub(PyObject *v, PyObject *w)
 {
-	Py_complex result;
+ Py_complex result;
+	Py_complex a, b;
+	TO_COMPLEX(v, a);
+	TO_COMPLEX(w, b);;
 	PyFPE_START_PROTECT("complex_sub", return 0)
-	result = c_diff(v->cval,w->cval);
+	result = c_diff(a, b);
 	PyFPE_END_PROTECT(result)
 	return PyComplex_FromCComplex(result);
 }
 
 static PyObject *
-complex_mul(PyComplexObject *v, PyComplexObject *w)
+complex_mul(PyObject *v, PyObject *w)
 {
 	Py_complex result;
+	Py_complex a, b;
+	TO_COMPLEX(v, a);
+	TO_COMPLEX(w, b);
 	PyFPE_START_PROTECT("complex_mul", return 0)
-	result = c_prod(v->cval,w->cval);
+	result = c_prod(a, b);
 	PyFPE_END_PROTECT(result)
 	return PyComplex_FromCComplex(result);
 }
 
 static PyObject *
-complex_div(PyComplexObject *v, PyComplexObject *w)
+complex_div(PyObject *v, PyObject *w)
 {
 	Py_complex quot;
-
+	Py_complex a, b;
+	TO_COMPLEX(v, a);
+	TO_COMPLEX(w, b);
 	PyFPE_START_PROTECT("complex_div", return 0)
 	errno = 0;
-	quot = c_quot(v->cval,w->cval);
+	quot = c_quot(a, b);
 	PyFPE_END_PROTECT(quot)
 	if (errno == EDOM) {
 		PyErr_SetString(PyExc_ZeroDivisionError, "complex division");
@@ -559,10 +570,12 @@
 }
 
 static PyObject *
-complex_classic_div(PyComplexObject *v, PyComplexObject *w)
+complex_classic_div(PyObject *v, PyObject *w)
 {
 	Py_complex quot;
-
+	Py_complex a, b;
+	TO_COMPLEX(v, a);
+	TO_COMPLEX(w, b);
 	if (Py_DivisionWarningFlag >= 2 &&
 	 PyErr_Warn(PyExc_DeprecationWarning,
 		 "classic complex division") < 0)
@@ -570,7 +583,7 @@
 
 	PyFPE_START_PROTECT("complex_classic_div", return 0)
 	errno = 0;
-	quot = c_quot(v->cval,w->cval);
+	quot = c_quot(a, b);
 	PyFPE_END_PROTECT(quot)
 	if (errno == EDOM) {
 		PyErr_SetString(PyExc_ZeroDivisionError, "complex division");
@@ -580,47 +593,51 @@
 }
 
 static PyObject *
-complex_remainder(PyComplexObject *v, PyComplexObject *w)
+complex_remainder(PyObject *v, PyObject *w)
 {
 	Py_complex div, mod;
-
+	Py_complex a, b;
+	TO_COMPLEX(v, a);
+	TO_COMPLEX(w, b);
 	if (PyErr_Warn(PyExc_DeprecationWarning,
 		 "complex divmod(), // and % are deprecated") < 0)
 		return NULL;
 
 	errno = 0;
-	div = c_quot(v->cval,w->cval); /* The raw divisor value. */
+	div = c_quot(a, b); /* The raw divisor value. */
 	if (errno == EDOM) {
 		PyErr_SetString(PyExc_ZeroDivisionError, "complex remainder");
 		return NULL;
 	}
 	div.real = floor(div.real); /* Use the floor of the real part. */
 	div.imag = 0.0;
-	mod = c_diff(v->cval, c_prod(w->cval, div));
+	mod = c_diff(a, c_prod(b, div));
 
 	return PyComplex_FromCComplex(mod);
 }
 
 
 static PyObject *
-complex_divmod(PyComplexObject *v, PyComplexObject *w)
+complex_divmod(PyObject *v, PyObject *w)
 {
 	Py_complex div, mod;
 	PyObject *d, *m, *z;
-
+	Py_complex a, b;
+	TO_COMPLEX(v, a);
+	TO_COMPLEX(w, b);
 	if (PyErr_Warn(PyExc_DeprecationWarning,
 		 "complex divmod(), // and % are deprecated") < 0)
 		return NULL;
 
 	errno = 0;
-	div = c_quot(v->cval,w->cval); /* The raw divisor value. */
+	div = c_quot(a, b); /* The raw divisor value. */
 	if (errno == EDOM) {
 		PyErr_SetString(PyExc_ZeroDivisionError, "complex divmod()");
 		return NULL;
 	}
 	div.real = floor(div.real); /* Use the floor of the real part. */
 	div.imag = 0.0;
-	mod = c_diff(v->cval, c_prod(w->cval, div));
+	mod = c_diff(a, c_prod(b, div));
 	d = PyComplex_FromCComplex(div);
 	m = PyComplex_FromCComplex(mod);
 	z = PyTuple_Pack(2, d, m);
@@ -638,8 +655,7 @@
 	Py_complex a, b;
 	TO_COMPLEX(v, a);
 	TO_COMPLEX(w, b);
-
- 	if (z!=Py_None) {
+	if (z!=Py_None) {
 		PyErr_SetString(PyExc_ValueError, "complex modulo");
 		return NULL;
 	}
@@ -668,10 +684,12 @@
 }
 
 static PyObject *
-complex_int_div(PyComplexObject *v, PyComplexObject *w)
+complex_int_div(PyObject *v, PyObject *w)
 {
 	PyObject *t, *r;
-	
+	Py_complex a, b;
+	TO_COMPLEX(v, a);
+	TO_COMPLEX(w, b);
 	if (PyErr_Warn(PyExc_DeprecationWarning,
 		 "complex divmod(), // and % are deprecated") < 0)
 		return NULL;
@@ -1282,7 +1300,8 @@
 	PyObject_GenericGetAttr,		/* tp_getattro */
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
+		Py_TPFLAGS_BASETYPE,		/* tp_flags */
 	complex_doc,				/* tp_doc */
 	0,					/* tp_traverse */
 	0,					/* tp_clear */


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /