summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--numpy/core/src/multiarray/methods.c5
-rw-r--r--numpy/core/src/multiarray/strfuncs.c27
-rw-r--r--numpy/core/src/multiarray/strfuncs.h3
-rw-r--r--numpy/core/tests/test_multiarray.py31
4 files changed, 66 insertions, 0 deletions
diff --git a/numpy/core/src/multiarray/methods.c b/numpy/core/src/multiarray/methods.c
index a908e648d..6a121574b 100644
--- a/numpy/core/src/multiarray/methods.c
+++ b/numpy/core/src/multiarray/methods.c
@@ -20,6 +20,7 @@
#include "item_selection.h"
#include "conversion_utils.h"
#include "shape.h"
+#include "strfuncs.h"
#include "methods.h"
#include "alloc.h"
@@ -2533,6 +2534,10 @@ NPY_NO_EXPORT PyMethodDef array_methods[] = {
(PyCFunction) array_complex,
METH_VARARGS, NULL},
+ {"__format__",
+ (PyCFunction) array_format,
+ METH_VARARGS, NULL},
+
#ifndef NPY_PY3K
/*
* While we could put these in `tp_sequence`, its' easier to define them
diff --git a/numpy/core/src/multiarray/strfuncs.c b/numpy/core/src/multiarray/strfuncs.c
index f7980ffe0..624c551ce 100644
--- a/numpy/core/src/multiarray/strfuncs.c
+++ b/numpy/core/src/multiarray/strfuncs.c
@@ -197,3 +197,30 @@ array_str(PyArrayObject *self)
}
return s;
}
+
+NPY_NO_EXPORT PyObject *
+array_format(PyArrayObject *self, PyObject *args)
+{
+ PyObject *format;
+ if (!PyArg_ParseTuple(args, "O:__format__", &format))
+ return NULL;
+
+ /* 0d arrays - forward to the scalar type */
+ if (PyArray_NDIM(self) == 0) {
+ PyObject *item = PyArray_ToScalar(PyArray_DATA(self), self);
+ PyObject *res;
+ if (item == NULL) {
+ return NULL;
+ }
+ res = PyObject_Format(item, format);
+ Py_DECREF(item);
+ return res;
+ }
+ /* Everything else - use the builtin */
+ else {
+ return PyObject_CallMethod(
+ (PyObject *)&PyBaseObject_Type, "__format__", "OO",
+ (PyObject *)self, format
+ );
+ }
+}
diff --git a/numpy/core/src/multiarray/strfuncs.h b/numpy/core/src/multiarray/strfuncs.h
index 8e80897c2..5dd661a20 100644
--- a/numpy/core/src/multiarray/strfuncs.h
+++ b/numpy/core/src/multiarray/strfuncs.h
@@ -10,4 +10,7 @@ array_repr(PyArrayObject *self);
NPY_NO_EXPORT PyObject *
array_str(PyArrayObject *self);
+NPY_NO_EXPORT PyObject *
+array_format(PyArrayObject *self, PyObject *args);
+
#endif
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index 92fc21b83..b1a6fbe44 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -7013,6 +7013,37 @@ class TestUnicodeArrayNonzero(object):
assert_(a)
+class TestFormat(object):
+
+ def test_0d(self):
+ a = np.array(np.pi)
+ assert_equal('{:0.3g}'.format(a), '3.14')
+ assert_equal('{:0.3g}'.format(a[()]), '3.14')
+
+ def test_1d_no_format(self):
+ a = np.array([np.pi])
+ assert_equal('{}'.format(a), str(a))
+
+ def test_1d_format(self):
+ # until gh-5543, ensure that the behaviour matches what it used to be
+ a = np.array([np.pi])
+
+ def ret_and_exc(f, *args, **kwargs):
+ try:
+ return f(*args, **kwargs), None
+ except Exception as e:
+ # exceptions don't compare equal, so return type and args
+ # which do
+ return None, (type(e), e.args)
+
+ # Could switch on python version here, but all we care about is
+ # that the behaviour hasn't changed
+ assert_equal(
+ ret_and_exc(object.__format__, a, '30'),
+ ret_and_exc('{:30}'.format, a)
+ )
+
+
class TestCTypes(object):
def test_ctypes_is_available(self):