8000 Merge pull request #26611 from mtsokol/remove-set_string_function · numpy/numpy@a4cddb6 · GitHub
[go: up one dir, main page]

Skip to content

Commit a4cddb6

Browse files
authored
Merge pull request #26611 from mtsokol/remove-set_string_function
MNT: Remove `set_string_function`
2 parents 056b558 + 6ff8609 commit a4cddb6

File tree

14 files changed

+43
-194
lines changed

14 files changed

+43
-194
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
* ``set_string_function`` internal function was removed and ``PyArray_SetStringFunction``
2+
was stubbed out.

doc/source/reference/c-api/array.rst

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4077,21 +4077,6 @@ extension with the lowest :c:data:`NPY_FEATURE_VERSION` as possible.
40774077
:c:data:`NPY_FEATURE_VERSION` changes whenever the API changes (e.g. a
40784078
function is added). A changed value does not always require a recompile.
40794079
4080-
Internal Flexibility
4081-
~~~~~~~~~~~~~~~~~~~~
4082-
4083-
.. c:function:: void PyArray_SetStringFunction(PyObject* op, int repr)
4084-
4085-
This function allows you to alter the tp_str and tp_repr methods
4086-
of the array object to any Python function. Thus you can alter
4087-
what happens for all arrays when str(arr) or repr(arr) is called
4088-
from Python. The function to be called is passed in as *op*. If
4089-
*repr* is non-zero, then this function will be called in response
4090-
to repr(arr), otherwise the function will be called in response to
4091-
str(arr). No check on whether or not *op* is callable is
4092-
performed. The callable passed in to *op* should expect an array
4093-
argument and should return a string to be printed.
4094-
40954080
40964081
Memory management
40974082
~~~~~~~~~~~~~~~~~

doc/source/reference/c-api/types-and-structures.rst

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -215,12 +215,11 @@ The :c:data:`PyArray_Type` can also be sub-typed.
215215

216216
.. tip::
217217

218-
The ``tp_as_number`` methods use a generic approach to call whatever
219-
function has been registered for handling the operation. When the
220-
``_multiarray_umath module`` is imported, it sets the numeric operations
221-
for all arrays to the corresponding ufuncs. This choice can be changed with
222-
:c:func:`PyUFunc_ReplaceLoopBySignature` The ``tp_str`` and ``tp_repr``
223-
methods can also be altered using :c:func:`PyArray_SetStringFunction`.
218+
The :c:member:`tp_as_number <PyTypeObject.tp_as_number>` methods use
219+
a generic approach to call whatever function has been registered for
220+
handling the operation. When the ``_multiarray_umath`` module is imported,
221+
it sets the numeric operations for all arrays to the corresponding ufuncs.
222+
This choice can be changed with :c:func:`PyUFunc_ReplaceLoopBySignature`.
224223

225224
PyGenericArrType_Type
226225
---------------------

numpy/__init__.cython-30.pxd

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,6 @@ cdef extern from "numpy/arrayobject.h":
608608
# more than is probably needed until it can be checked further.
609609
int PyArray_INCREF (ndarray) except * # uses PyArray_Item_INCREF...
610610
int PyArray_XDECREF (ndarray) except * # uses PyArray_Item_DECREF...
611-
void PyArray_SetStringFunction (object, int)
612611
dtype PyArray_DescrFromType (int)
613612
object PyArray_TypeObjectFromType (int)
614613
char * PyArray_Zero (ndarray)

numpy/__init__.pxd

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,6 @@ cdef extern from "numpy/arrayobject.h":
523523
# more than is probably needed until it can be checked further.
524524
int PyArray_INCREF (ndarray) except * # uses PyArray_Item_INCREF...
525525
int PyArray_XDECREF (ndarray) except * # uses PyArray_Item_DECREF...
526-
void PyArray_SetStringFunction (object, int)
527526
dtype PyArray_DescrFromType (int)
528527
object PyArray_TypeObjectFromType (int)
529528
char * PyArray_Zero (ndarray)

numpy/_core/_add_newdocs.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1846,15 +1846,6 @@
18461846
18471847
""")
18481848

1849-
1850-
add_newdoc('numpy._core.multiarray', 'set_string_function',
1851-
"""
1852-
set_string_function(f, repr=1)
1853-
1854-
Internal method to set a function to be used when pretty printing arrays.
1855-
1856-
""")
1857-
18581849
add_newdoc('numpy._core.multiarray', 'promote_types',
18591850
"""
18601851
promote_types(type1, type2)

numpy/_core/arrayprint.py

Lines changed: 17 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,14 @@
5959
'formatter': None,
6060
# Internally stored as an int to simplify comparisons; converted from/to
6161
# str/False on the way in/out.
62-
'legacy': sys.maxsize}
62+
'legacy': sys.maxsize,
63+
'override_repr': None,
64+
}
6365

6466
def _make_options_dict(precision=None, threshold=None, edgeitems=None,
6567
linewidth=None, suppress=None, nanstr=None, infstr=None,
66-
sign=None, formatter=None, floatmode=None, legacy=None):
68+
sign=None, formatter=None, floatmode=None, legacy=None,
69+
override_repr=None):
6770
"""
6871
Make a dictionary out of the non-None arguments, plus conversion of
6972
*legacy* and sanity checks.
@@ -119,7 +122,7 @@ def _make_options_dict(precision=None, threshold=None, edgeitems=None,
119122
def set_printoptions(precision=None, threshold=None, edgeitems=None,
120123
linewidth=None, suppress=None, nanstr=None,
121124
infstr=None, formatter=None, sign=None, floatmode=None,
122-
*, legacy=None):
125+
*, legacy=None, override_repr=None):
123126
"""
124127
Set printing options.
125128
@@ -224,6 +227,9 @@ def set_printoptions(precision=None, threshold=None, edgeitems=None,
224227
225228
.. versionadded:: 1.14.0
226229
.. versionchanged:: 1.22.0
230+
override_repr: callable, optional
231+
If set a passed function will be used for generating arrays' repr.
232+
Other options will be ignored.
227233
228234
See Also
229235
--------
@@ -285,9 +291,10 @@ def set_printoptions(precision=None, threshold=None, edgeitems=None,
285291
"""
286292
opt = _make_options_dict(precision, threshold, edgeitems, linewidth,
287293
suppress, nanstr, infstr, sign, formatter,
288-
floatmode, legacy)
289-
# formatter is always reset
294+
floatmode, legacy, override_repr)
295+
# formatter and override_repr are always reset
290296
opt['formatter'] = formatter
297+
opt['override_repr'] = override_repr
291298
_format_options.update(opt)
292299

293300
# set the C variable for legacy mode
@@ -333,7 +340,7 @@ def get_printoptions():
333340
--------
334341
335342
>>> np.get_printoptions()
336-
{'edgeitems': 3, 'threshold': 1000, ..., 'legacy': False}
343+
{'edgeitems': 3, 'threshold': 1000, ..., 'override_repr': None}
337344
338345
>>> np.get_printoptions()['linewidth']
339346
75
@@ -1552,6 +1559,10 @@ def _array_repr_implementation(
15521559
arr, max_line_width=None, precision=None, suppress_small=None,
15531560
array2string=array2string):
15541561
"""Internal version of array_repr() that allows overriding array2string."""
1562+
override_repr = _format_options["override_repr"]
1563+
if override_repr is not None:
1564+
return override_repr(arr)
1565+
15551566
if max_line_width is None:
15561567
max_line_width = _format_options['linewidth']
15571568

@@ -1727,78 +1738,3 @@ def array_str(a, max_line_width=None, precision=None, suppress_small=None):
17271738
array2string=_array2string_impl)
17281739
_default_array_repr = functools.partial(_array_repr_implementation,
17291740
array2string=_array2string_impl)
1730-
1731-
1732-
def set_string_function(f, repr=True):
1733-
"""
1734-
Set a Python function to be used when pretty printing arrays.
1735-
1736-
.. deprecated:: 2.0
1737-
Use `np.set_printoptions` instead with a formatter for custom
1738-
printing of NumPy objects.
1739-
1740-
Parameters
1741-
----------
1742-
f : function or None
1743-
Function to be used to pretty print arrays. The function should expect
1744-
a single array argument and return a string of the representation of
1745-
the array. If None, the function is reset to the default NumPy function
1746-
to print arrays.
1747-
repr : bool, optional
1748-
If True (default), the function for pretty printing (``__repr__``)
1749-
is set, if False the function that returns the default string
1750-
representation (``__str__``) is set.
1751-
1752-
See Also
1753-
--------
1754-
set_printoptions, get_printoptions
1755-
1756-
Examples
1757-
--------
1758-
>>> from numpy._core.arrayprint import set_string_function
1759-
>>> def pprint(arr):
1760-
... return 'HA! - What are you going to do now?'
1761-
...
1762-
>>> set_string_function(pprint)
1763-
>>> a = np.arange(10)
1764-
>>> a
1765-
HA! - What are you going to do now?
1766-
>>> _ = a
1767-
>>> # [0 1 2 3 4 5 6 7 8 9]
1768-
1769-
We can reset the function to the default:
1770-
1771-
>>> set_string_function(None)
1772-
>>> a
1773-
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
1774-
1775-
`repr` affects either pretty printing or normal string representation.
1776-
Note that ``__repr__`` is still affected by setting ``__str__``
1777-
because the width of each array element in the returned string becomes
1778-
equal to the length of the result of ``__str__()``.
1779-
1780-
>>> x = np.arange(4)
1781-
>>> set_string_function(lambda x:'random', repr=False)
1782-
>>> x.__str__()
1783-
'random'
1784-
>>> x.__repr__()
1785-
'array([0, 1, 2, 3])'
1786-
1787-
"""
1788-
1789-
# Deprecated in NumPy 2.0, 2023-07-11
1790-
warnings.warn(
1791-
"`set_string_function` is deprecated. Use `np.set_printoptions` "
1792-
"with a formatter for custom printing NumPy objects. "
1793-
"(deprecated in NumPy 2.0)",
1794-
DeprecationWarning,
1795-
stacklevel=2
1796-
)
1797-
1798-
if f is None:
1799-
if repr:
1800-
return multiarray.set_string_function(_default_array_repr, 1)
1801-
else:
1802-
return multiarray.set_string_function(_default_array_str, 0)
1803-
else:
1804-
return multiarray.set_string_function(f, repr)

numpy/_core/arrayprint.pyi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ def set_printoptions(
6363
sign: Literal[None, "-", "+", " "] = ...,
6464
floatmode: None | _FloatMode = ...,
6565
*,
66-
legacy: Literal[None, False, "1.13", "1.21"] = ...
66+
legacy: Literal[None, False, "1.13", "1.21"] = ...,
67+
override_repr: None | Callable[[NDArray[Any]], str] = ...,
6768
) -> None: ...
6869
def get_printoptions() -> _FormatOptions: ...
6970
def array2string(

numpy/_core/code_generators/numpy_api.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ def get_annotations():
116116
# Unused slot 41, was `PyArray_GetNumericOps`,
117117
'PyArray_INCREF': (42,),
118118
'PyArray_XDECREF': (43,),
119+
# `PyArray_SetStringFunction` was stubbed out
120+
# and should be removed in the future.
119121
'PyArray_SetStringFunction': (44,),
120122
'PyArray_DescrFromType': (45,),
121123
'PyArray_TypeObjectFromType': (46,),

numpy/_core/src/multiarray/multiarraymodule.c

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3176,31 +3176,6 @@ array__reconstruct(PyObject *NPY_UNUSED(dummy), PyObject *args)
31763176
return NULL;
31773177
}
31783178

3179-
static PyObject *
3180-
array_set_string_function(PyObject *NPY_UNUSED(self), PyObject *args,
3181-
PyObject *kwds)
3182-
{
3183-
PyObject *op = NULL;
3184-
int repr = 1;
3185-
static char *kwlist[] = {"f", "repr", NULL};
3186-
3187-
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:set_string_function", kwlist, &op, &repr)) {
3188-
return NULL;
3189-
}
3190-
/* reset the array_repr function to built-in */
3191-
if (op == Py_None) {
3192-
op = NULL;
3193-
}
3194-
if (op != NULL && !PyCallable_Check(op)) {
3195-
PyErr_SetString(PyExc_TypeError,
3196-
"Argument must be callable.");
3197-
return NULL;
3198-
}
3199-
PyArray_SetStringFunction(op, repr);
3200-
Py_RETURN_NONE;
3201-
}
3202-
3203-
32043179
static PyObject *
32053180
array_set_datetimeparse_function(PyObject *NPY_UNUSED(self),
32063181
PyObject *NPY_UNUSED(args), PyObject *NPY_UNUSED(kwds))
@@ -4417,9 +4392,6 @@ static struct PyMethodDef array_module_methods[] = {
44174392
{"_reconstruct",
44184393
(PyCFunction)array__reconstruct,
44194394
METH_VARARGS, NULL},
4420-
{"set_string_function",
4421-
(PyCFunction)array_set_string_function,
4422-
METH_VARARGS|METH_KEYWORDS, NULL},
44234395
{"set_datetimeparse_function",
44244396
(PyCFunction)array_set_datetimeparse_function,
44254397
METH_VARARGS|METH_KEYWORDS, NULL},

numpy/_core/src/multiarray/strfuncs.c

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@
99
#include "npy_import.h"
1010
#include "strfuncs.h"
1111

12-
static PyObject *PyArray_StrFunction = NULL;
13-
static PyObject *PyArray_ReprFunction = NULL;
14-
15-
1612
static void
1713
npy_PyErr_SetStringChained(PyObject *type, const char *message)
1814
{
@@ -30,34 +26,14 @@ npy_PyErr_SetStringChained(PyObject *type, const char *message)
3026
NPY_NO_EXPORT void
3127
PyArray_SetStringFunction(PyObject *op, int repr)
3228
{
33-
if (repr) {
34-
/* Dispose of previous callback */
35-
Py_XDECREF(PyArray_ReprFunction);
36-
/* Add a reference to new callback */
37-
Py_XINCREF(op);
38-
/* Remember new callback */
39-
PyArray_ReprFunction = op;
40-
}
41-
else {
42-
/* Dispose of previous callback */
43-
Py_XDECREF(PyArray_StrFunction);
44-
/* Add a reference to new callback */
45-
Py_XINCREF(op);
46-
/* Remember new callback */
47-
PyArray_StrFunction = op;
48-
}
29+
PyErr_SetString(PyExc_ValueError, "PyArray_SetStringFunction was removed");
4930
}
5031

5132

5233
NPY_NO_EXPORT PyObject *
5334
array_repr(PyArrayObject *self)
5435
{
5536
static PyObject *repr = NULL;
56-
57-
if (PyArray_ReprFunction != NULL) {
58-
return PyObject_CallFunctionObjArgs(PyArray_ReprFunction, self, NULL);
59-
}
60-
6137
/*
6238
* We need to do a delayed import here as initialization on module load
6339
* leads to circular import problems.
@@ -76,11 +52,6 @@ NPY_NO_EXPORT PyObject *
7652
array_str(PyArrayObject *self)
7753
{
7854
static PyObject *str = NULL;
79-
80-
if (PyArray_StrFunction != NULL) {
81-
return PyObject_CallFunctionObjArgs(PyArray_StrFunction, self, NULL);
82-
}
83-
8455
/*
8556
* We need to do a delayed import here as initialization on module load leads
8657
* to circular import problems.

numpy/_core/tests/test_arrayprint.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,17 @@ def test_formatter_reset(self):
667667
np.set_printoptions(formatter={'float_kind':None})
668668
assert_equal(repr(x), "array([0., 1., 2.])")
669669

670+
def test_override_repr(self):
671+
x = np.arange(3)
672+
np.set_printoptions(override_repr=lambda x: "FOO")
673+
assert_equal(repr(x), "FOO")
674+
np.set_printoptions(override_repr=None)
675+
assert_equal(repr(x), "array([0, 1, 2])")
676+
677+
with np.printoptions(override_repr=lambda x: "BAR"):
678+
assert_equal(repr(x), "BAR")
679+
assert_equal(repr(x), "array([0, 1, 2])")
680+
670681
def test_0d_arrays(self):
671682
assert_equal(str(np.array('café', '<U4')), 'café')
672683

numpy/_core/tests/test_multiarray.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -594,16 +594,16 @@ def assign(v):
594594
)
595595
def test_unicode_assignment(self):
596596
# gh-5049
597-
from numpy._core.arrayprint import set_string_function
597+
from numpy._core.arrayprint import set_printoptions
598598

599599
@contextmanager
600600
def inject_str(s):
601601
""" replace ndarray.__str__ temporarily """
602-
set_string_function(lambda x: s, repr=False)
602+
set_printoptions(formatter={"all": lambda x: s})
603603
try:
604604
yield
605605
finally:
606-
set_string_function(None, repr=False)
606+
set_printoptions()
607607

608608
a1d = np.array(['test'])
609609
a0d = np.array('done')

0 commit comments

Comments
 (0)
0