8000 Merge pull request #9883 from eric-wieser/0d-format · numpy/numpy@e657629 · GitHub
[go: up one dir, main page]

Skip to content

Commit e657629

Browse files
authored
Merge pull request #9883 from eric-wieser/0d-format
ENH: Implement ndarray.__format__ for 0d arrays
2 parents c0b2aba + 86a7ac6 commit e657629

File tree

4 files changed

+67
-0
lines changed

4 files changed

+67
-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: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,31 @@ 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+
213+
if (item == NULL) {
214+
return NULL;
215+
}
216+
res = PyObject_Format(item, format);
217+
Py_DECREF(item);
218+
return res;
219+
}
220+
/* Everything else - use the builtin */
221+
else {
222+
return PyObject_CallMethod(
223+
(PyObject *)&PyBaseObject_Type, "__format__", "OO",
224+
(PyObject *)self, format
225+
);
226+
}
227+
}

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