10000 ENH: Implement ndarray.__format__ for 0d arrays · theodoregoetz/numpy@3f87c6e · GitHub
[go: up one dir, main page]

Skip to content

Commit 3f87c6e

Browse files
eric-wiesertheodoregoetz
authored andcommitted
ENH: Implement ndarray.__format__ for 0d arrays
This fixes numpygh-7978 The behavior for other sized arrays is left unchanged, pending discussion in numpygh-5543
1 parent 6999863 commit 3f87c6e

File tree

4 files changed

+66
-0
lines changed

4 files changed

+66
-0
lines changed

numpy/core/src/multiarray/methods.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "item_selection.h"
2121
#include "conversion_utils.h"
2222
#include "shape.h"
23+
#include "strfuncs.h"
2324

2425
#include "methods.h"
2526
#include "alloc.h"
@@ -2533,6 +2534,10 @@ NPY_NO_EXPORT PyMethodDef array_methods[] = {
25332534
(PyCFunction) array_complex,
25342535
METH_VARARGS, NULL},
25352536

2537+
{"__format__",
2538+
(PyCFunction) array_format,
2539+
METH_VARARGS, NULL},
2540+
25362541
#ifndef NPY_PY3K
25372542
/*
25382543
* While we could put these in `tp_sequence`, its' easier to define them

numpy/core/src/multiarray/strfuncs.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,30 @@ array_str(PyArrayObject *self)
197197
}
198198
return s;
199199
}
200+
201+
NPY_NO_EXPORT PyObject *
202+
array_format(PyArrayObject *self, PyObject *args)
203+
{
204+
PyObject *format;
205+
if (!PyArg_ParseTuple(args, "O:__format__", &format))
206+
return NULL;
207+
208+
/* 0d arrays - forward to the scalar type */
209+
if (PyArray_NDIM(self) == 0) {
210+
PyObject *item = PyArray_ToScalar(PyArray_DATA(self), self);
211+
PyObject *res;
212+
if (item == NULL) {
213+
return NULL;
214+
}
215+
res = PyObject_Format(item, format);
216+
Py_DECREF(item);
217+
return res;
218+
}
219+
/* Everything else - use the builtin */
220+
else {
221+
return PyObject_CallMethod(
222+
(PyObject *)&PyBaseObject_Type, "__format__", "OO",
223+
(PyObject *)self, format
224+
);
225+
}
226+
}

numpy/core/src/multiarray/strfuncs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,7 @@ array_repr(PyArrayObject *self);
1010
NPY_NO_EXPORT PyObject *
1111
array_str(PyArrayObject *self);
1212

13+
NPY_NO_EXPORT PyObject *
14+
array_format(PyArrayObject *self, PyObject *args);
15+
1316
#endif

numpy/core/tests/test_multiarray.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7013,6 +7013,37 @@ def test_null_inside_ustring_array_is_truthy(self):
70137013
assert_(a)
70147014

70157015

7016+
class TestFormat(object):
7017+
7018+
def test_0d(self):
7019+
a = np.array(np.pi)
7020+
assert_equal('{:0.3g}'.format(a), '3.14')
7021+
assert_equal('{:0.3g}'.format(a[()]), '3.14')
7022+
7023+
def test_1d_no_format(self):
7024+
a = np.array([np.pi])
7025+
assert_equal('{}'.format(a), str(a))
7026+
7027+
def test_1d_format(self):
7028+
# until gh-5543, ensure that the behaviour matches what it used to be
7029+
a = np.array([np.pi])
7030+
7031+
def ret_and_exc(f, *args, **kwargs):
7032+
try:
7033+
return f(*args, **kwargs), None
7034+
except Exception as e:
7035+
# exceptions don't compare equal, so return type and args
7036+
# which do
7037+
return None, (type(e), e.args)
7038+
7039+
# Could switch on python version here, but all we care about is
7040+
# that the behaviour hasn't changed
7041+
assert_equal(
7042+
ret_and_exc(object.__format__, a, '30'),
7043+
ret_and_exc('{:30}'.format, a)
7044+
)
7045+
7046+
70167047
class TestCTypes(object):
70177048

70187049
def test_ctypes_is_available(self):

0 commit comments

Comments
 (0)
0