summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/src/multiarray/scalartypes.c.src37
-rw-r--r--numpy/core/tests/test_scalarprint.py17
2 files changed, 54 insertions, 0 deletions
diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src
index ee83206de..3e17ec040 100644
--- a/numpy/core/src/multiarray/scalartypes.c.src
+++ b/numpy/core/src/multiarray/scalartypes.c.src
@@ -4169,6 +4169,37 @@ initialize_casting_tables(void)
}
}
+#ifndef NPY_PY3K
+/*
+ * In python2, the `float` and `complex` types still implement the obsolete
+ * "tp_print" method, which uses CPython's float-printing routines to print the
+ * float. Numpy's float_/cfloat inherit from Python float/complex, but
+ * override its tp_repr and tp_str methods. In order to avoid an inconsistency
+ * with the inherited tp_print, we need to override it too.
+ *
+ * In python3 the tp_print method is reserved/unused.
+ */
+static int
+doubletype_print(PyObject *o, FILE *fp, int flags)
+{
+ int ret;
+ PyObject *to_print;
+ if (flags & Py_PRINT_RAW) {
+ to_print = PyObject_Str(o);
+ }
+ else {
+ to_print = PyObject_Repr(o);
+ }
+
+ if (to_print == NULL) {
+ return -1;
+ }
+
+ ret = PyObject_Print(to_print, fp, flags);
+ Py_DECREF(to_print);
+ return ret;
+}
+#endif
static PyNumberMethods longdoubletype_as_number;
static PyNumberMethods clongdoubletype_as_number;
@@ -4221,6 +4252,12 @@ initialize_numeric_types(void)
/**end repeat**/
+#ifndef NPY_PY3K
+ PyDoubleArrType_Type.tp_print = &doubletype_print;
+ PyCDoubleArrType_Type.tp_print = &doubletype_print;
+#endif
+
+
PyBoolArrType_Type.tp_as_number->nb_index = (unaryfunc)bool_index;
PyStringArrType_Type.tp_alloc = NULL;
diff --git a/numpy/core/tests/test_scalarprint.py b/numpy/core/tests/test_scalarprint.py
index d57f1a890..47cd2a40a 100644
--- a/numpy/core/tests/test_scalarprint.py
+++ b/numpy/core/tests/test_scalarprint.py
@@ -6,6 +6,7 @@ from __future__ import division, absolute_import, print_function
import numpy as np
from numpy.testing import assert_, assert_equal, run_module_suite
+import sys, tempfile
class TestRealScalars(object):
@@ -45,6 +46,22 @@ class TestRealScalars(object):
check(1e15)
check(1e16)
+ def test_py2_float_print(self):
+ # gh-10753
+ # In python2, the python float type implements an obsolte method
+ # tp_print, which overrides tp_repr and tp_str when using "print" to
+ # output to a "real file" (ie, not a StringIO). Make sure we don't
+ # inherit it.
+ x = np.double(0.1999999999999)
+ with tempfile.TemporaryFile('r+t') as f:
+ print(x, file=f)
+ f.seek(0)
+ output = f.read()
+ assert_equal(output, str(x) + '\n')
+ # In python2 the value float('0.1999999999999') prints with reduced
+ # precision as '0.2', but we want numpy's np.double('0.1999999999999')
+ # to print the unique value, '0.1999999999999'.
+
def test_dragon4(self):
# these tests are adapted from Ryan Juckett's dragon4 implementation,
# see dragon4.c for details.