summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2001-08-31 17:40:15 (GMT)
committerGuido van Rossum <guido@python.org>2001-08-31 17:40:15 (GMT)
commit393661d15fa76ec46e9f7b71e97bf2ed38470620 (patch)
tree99af5c4d5a19a77fb12428d6ef40ce3896d9e2fd /Objects
parent29d55a38ce15062bcabf78a52faa828002b5bbd4 (diff)
downloadcpython-393661d15fa76ec46e9f7b71e97bf2ed38470620.zip
cpython-393661d15fa76ec46e9f7b71e97bf2ed38470620.tar.gz
cpython-393661d15fa76ec46e9f7b71e97bf2ed38470620.tar.bz2
Add warning mode for classic division, almost exactly as specified in
PEP 238. Changes: - add a new flag variable Py_DivisionWarningFlag, declared in pydebug.h, defined in object.c, set in main.c, and used in {int,long,float,complex}object.c. When this flag is set, the classic division operator issues a DeprecationWarning message. - add a new API PyRun_SimpleStringFlags() to match PyRun_SimpleString(). The main() function calls this so that commands run with -c can also benefit from -Dnew. - While I was at it, I changed the usage message in main() somewhat: alphabetized the options, split it in *four* parts to fit in under 512 bytes (not that I still believe this is necessary -- doc strings elsewhere are much longer), and perhaps most visibly, don't display the full list of options on each command line error. Instead, the full list is only displayed when -h is used, and otherwise a brief reminder of -h is displayed. When -h is used, write to stdout so that you can do `python -h | more'. Notes: - I don't want to use the -W option to control whether the classic division warning is issued or not, because the machinery to decide whether to display the warning or not is very expensive (it involves calling into the warnings.py module). You can use -Werror to turn the warnings into exceptions though. - The -Dnew option doesn't select future division for all of the program -- only for the __main__ module. I don't know if I'll ever change this -- it would require changes to the .pyc file magic number to do it right, and a more global notion of compiler flags. - You can usefully combine -Dwarn and -Dnew: this gives the __main__ module new division, and warns about classic division everywhere else.
Diffstat (limited to 'Objects')
-rw-r--r--Objects/complexobject.c23
-rw-r--r--Objects/floatobject.c21
-rw-r--r--Objects/intobject.c25
-rw-r--r--Objects/longobject.c22
-rw-r--r--Objects/object.c2
5 files changed, 88 insertions, 5 deletions
diff --git a/Objects/complexobject.c b/Objects/complexobject.c
index cb081aa..281de13 100644
--- a/Objects/complexobject.c
+++ b/Objects/complexobject.c
@@ -373,6 +373,27 @@ complex_div(PyComplexObject *v, PyComplexObject *w)
}
static PyObject *
+complex_classic_div(PyComplexObject *v, PyComplexObject *w)
+{
+ Py_complex quot;
+
+ if (Py_DivisionWarningFlag &&
+ PyErr_Warn(PyExc_DeprecationWarning,
+ "classic complex division") < 0)
+ return NULL;
+
+ PyFPE_START_PROTECT("complex_classic_div", return 0)
+ errno = 0;
+ quot = c_quot(v->cval,w->cval);
+ PyFPE_END_PROTECT(quot)
+ if (errno == EDOM) {
+ PyErr_SetString(PyExc_ZeroDivisionError, "complex division");
+ return NULL;
+ }
+ return PyComplex_FromCComplex(quot);
+}
+
+static PyObject *
complex_remainder(PyComplexObject *v, PyComplexObject *w)
{
Py_complex div, mod;
@@ -854,7 +875,7 @@ static PyNumberMethods complex_as_number = {
(binaryfunc)complex_add, /* nb_add */
(binaryfunc)complex_sub, /* nb_subtract */
(binaryfunc)complex_mul, /* nb_multiply */
- (binaryfunc)complex_div, /* nb_divide */
+ (binaryfunc)complex_classic_div, /* nb_divide */
(binaryfunc)complex_remainder, /* nb_remainder */
(binaryfunc)complex_divmod, /* nb_divmod */
(ternaryfunc)complex_pow, /* nb_power */
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 7eb2777..39eba8e 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -414,6 +414,25 @@ float_div(PyObject *v, PyObject *w)
}
static PyObject *
+float_classic_div(PyObject *v, PyObject *w)
+{
+ double a,b;
+ CONVERT_TO_DOUBLE(v, a);
+ CONVERT_TO_DOUBLE(w, b);
+ if (Py_DivisionWarningFlag &&
+ PyErr_Warn(PyExc_DeprecationWarning, "classic float division") < 0)
+ return NULL;
+ if (b == 0.0) {
+ PyErr_SetString(PyExc_ZeroDivisionError, "float division");
+ return NULL;
+ }
+ PyFPE_START_PROTECT("divide", return 0)
+ a = a / b;
+ PyFPE_END_PROTECT(a)
+ return PyFloat_FromDouble(a);
+}
+
+static PyObject *
float_rem(PyObject *v, PyObject *w)
{
double vx, wx;
@@ -677,7 +696,7 @@ static PyNumberMethods float_as_number = {
(binaryfunc)float_add, /*nb_add*/
(binaryfunc)float_sub, /*nb_subtract*/
(binaryfunc)float_mul, /*nb_multiply*/
- (binaryfunc)float_div, /*nb_divide*/
+ (binaryfunc)float_classic_div, /*nb_divide*/
(binaryfunc)float_rem, /*nb_remainder*/
(binaryfunc)float_divmod, /*nb_divmod*/
(ternaryfunc)float_pow, /*nb_power*/
diff --git a/Objects/intobject.c b/Objects/intobject.c
index d1f241d..108e658 100644
--- a/Objects/intobject.c
+++ b/Objects/intobject.c
@@ -512,6 +512,27 @@ int_div(PyIntObject *x, PyIntObject *y)
}
static PyObject *
+int_classic_div(PyIntObject *x, PyIntObject *y)
+{
+ long xi, yi;
+ long d, m;
+ CONVERT_TO_LONG(x, xi);
+ CONVERT_TO_LONG(y, yi);
+ if (Py_DivisionWarningFlag &&
+ PyErr_Warn(PyExc_DeprecationWarning, "classic int division") < 0)
+ return NULL;
+ switch (i_divmod(xi, yi, &d, &m)) {
+ case DIVMOD_OK:
+ return PyInt_FromLong(d);
+ case DIVMOD_OVERFLOW:
+ return PyLong_Type.tp_as_number->nb_divide((PyObject *)x,
+ (PyObject *)y);
+ default:
+ return NULL;
+ }
+}
+
+static PyObject *
int_mod(PyIntObject *x, PyIntObject *y)
{
long xi, yi;
@@ -744,7 +765,7 @@ int_or(PyIntObject *v, PyIntObject *w)
static PyObject *
int_true_divide(PyObject *v, PyObject *w)
{
- return PyFloat_Type.tp_as_number->nb_divide(v, w);
+ return PyFloat_Type.tp_as_number->nb_true_divide(v, w);
}
static PyObject *
@@ -855,7 +876,7 @@ static PyNumberMethods int_as_number = {
(binaryfunc)int_add, /*nb_add*/
(binaryfunc)int_sub, /*nb_subtract*/
(binaryfunc)int_mul, /*nb_multiply*/
- (binaryfunc)int_div, /*nb_divide*/
+ (binaryfunc)int_classic_div, /*nb_divide*/
(binaryfunc)int_mod, /*nb_remainder*/
(binaryfunc)int_divmod, /*nb_divmod*/
(ternaryfunc)int_pow, /*nb_power*/
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 25d0377..4209419 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -1509,6 +1509,26 @@ long_div(PyObject *v, PyObject *w)
}
static PyObject *
+long_classic_div(PyObject *v, PyObject *w)
+{
+ PyLongObject *a, *b, *div, *mod;
+
+ CONVERT_BINOP(v, w, &a, &b);
+
+ if (Py_DivisionWarningFlag &&
+ PyErr_Warn(PyExc_DeprecationWarning, "classic long division") < 0)
+ div = NULL;
+ else if (l_divmod(a, b, &div, &mod) < 0)
+ div = NULL;
+ else
+ Py_DECREF(mod);
+
+ Py_DECREF(a);
+ Py_DECREF(b);
+ return (PyObject *)div;
+}
+
+static PyObject *
long_mod(PyObject *v, PyObject *w)
{
PyLongObject *a, *b, *div, *mod;
@@ -2115,7 +2135,7 @@ static PyNumberMethods long_as_number = {
(binaryfunc) long_add, /*nb_add*/
(binaryfunc) long_sub, /*nb_subtract*/
(binaryfunc) long_mul, /*nb_multiply*/
- (binaryfunc) long_div, /*nb_divide*/
+ (binaryfunc) long_classic_div, /*nb_divide*/
(binaryfunc) long_mod, /*nb_remainder*/
(binaryfunc) long_divmod, /*nb_divmod*/
(ternaryfunc) long_pow, /*nb_power*/
diff --git a/Objects/object.c b/Objects/object.c
index 7b9e280..66b4eae 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -16,6 +16,8 @@
DL_IMPORT(long) _Py_RefTotal;
#endif
+DL_IMPORT(int) Py_DivisionWarningFlag;
+
/* Object allocation routines used by NEWOBJ and NEWVAROBJ macros.
These are used by the individual routines for object creation.
Do not call them otherwise, they do not initialize the object! */