8000 MAINT: Remove any promotion-state switching logic (#27156) · numpy/numpy@b3ddf2f · GitHub
[go: up one dir, main page]

Skip to content

Commit b3ddf2f

Browse files
authored
MAINT: Remove any promotion-state switching logic (#27156)
This is the first level, no following code simplifications, just straight up deletions of any branching. I kept a UserWarning, in case someone had the bad idea to permanently set the environment variable and think they can rely on it. Although would be happy to just delete that as well. * DOC: Add release note for promotion state removal I think we can just do that, but maybe it's prudent to just point it out anyway... * DOC: Mention semi-private removed functions and tweak docs * Adress Marten's last comment
1 parent cfeed27 commit b3ddf2f

27 files changed

+132
-894
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
NEP 50 promotion state option removed
2+
-------------------------------------
3+
The NEP 50 promotion state settings are now removed. They were always
4+
meant as temporary means for testing.
5+
A warning will be given if the environment variable is set to anything
6+
but ``NPY_PROMOTION_STATE=weak`` wile ``_set_promotion_state``
7+
and ``_get_promotion_state`` are removed.
8+
In case code used ``_no_nep50_warning``, a ``contextlib.nullcontext``
9+
could be used to replace it when not available.

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

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,14 +1089,13 @@ Converting data types
10891089
returned when the value will not overflow or be truncated to
10901090
an integer when converting to a smaller type.
10911091
1092-
This is almost the same as the result of
1093-
PyArray_CanCastTypeTo(PyArray_MinScalarType(arr), totype, casting),
1094-
but it also handles a special case arising because the set
1095-
of uint values is not a subset of the int values for types with the
1096-
same number of bits.
1097-
10981092
.. c:function:: PyArray_Descr* PyArray_MinScalarType(PyArrayObject* arr)
10991093
1094+
.. note::
1095+
With the adoption of NEP 50 in NumPy 2, this function is not used
1096+
internally. It is currently provided for backwards compatibility,
1097+
but expected to be eventually deprecated.
1098+
11001099
.. versionadded:: 1.6
11011100
11021101
If *arr* is an array, returns its data type descriptor, but if
@@ -1134,8 +1133,7 @@ Converting data types
11341133
11351134
.. c:function:: int PyArray_ObjectType(PyObject* op, int mintype)
11361135
1137-
This function is superseded by :c:func:`PyArray_MinScalarType` and/or
1138-
:c:func:`PyArray_ResultType`.
1136+
This function is superseded by :c:func:`PyArray_ResultType`.
11391137
11401138
This function is useful for determining a common type that two or
11411139
more arrays can be converted to. It only works for non-flexible
@@ -3250,30 +3248,18 @@ Array scalars
32503248
.. c:function:: NPY_SCALARKIND PyArray_ScalarKind( \
32513249
int typenum, PyArrayObject** arr)
32523250
3253-
See the function :c:func:`PyArray_MinScalarType` for an alternative
3254-
mechanism introduced in NumPy 1.6.0.
3251+
Legacy way to query special promotion for scalar values. This is not
3252+
used in NumPy itself anymore and is expected to be deprecated eventually.
32553253
3256-
Return the kind of scalar represented by *typenum* and the array
3257-
in *\*arr* (if *arr* is not ``NULL`` ). The array is assumed to be
3258-
rank-0 and only used if *typenum* represents a signed integer. If
3259-
*arr* is not ``NULL`` and the first element is negative then
3260-
:c:data:`NPY_INTNEG_SCALAR` is returned, otherwise
3261-
:c:data:`NPY_INTPOS_SCALAR` is returned. The possible return values
3262-
are the enumerated values in :c:type:`NPY_SCALARKIND`.
3254+
New DTypes can define promotion rules specific to Python scalars.
32633255
32643256
.. c:function:: int PyArray_CanCoerceScalar( \
32653257
char thistype, char neededtype, NPY_SCALARKIND scalar)
32663258
3267-
See the function :c:func:`PyArray_ResultType` for details of
3268-
NumPy type promotion, updated in NumPy 1.6.0.
3259+
Legacy way to query special promotion for scalar values. This is not
3260+
used in NumPy itself anymore and is expected to be deprecated eventually.
32693261
3270-
Implements the rules for scalar coercion. Scalars are only
3271-
silently coerced from thistype to neededtype if this function
3272-
returns nonzero. If scalar is :c:data:`NPY_NOSCALAR`, then this
3273-
function is equivalent to :c:func:`PyArray_CanCastSafely`. The rule is
3274-
that scalars of the same KIND can be coerced into arrays of the
3275-
same KIND. This rule means that high-precision scalars will never
3276-
cause low-precision arrays of the same KIND to be upcast.
3262+
Use ``PyArray_ResultType`` for similar purposes.
32773263
32783264
32793265
Data-type descriptors

numpy/__init__.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@
120120

121121
from . import _core
122122
from ._core import (
123-
False_, ScalarType, True_, _get_promotion_state, _no_nep50_warning,
124-
_set_promotion_state, abs, absolute, acos, acosh, add, all, allclose,
123+
False_, ScalarType, True_,
124+
abs, absolute, acos, acosh, add, all, allclose,
125125
amax, amin, any, arange, arccos, arccosh, arcsin, arcsinh,
126126
arctan, arctan2, arctanh, argmax, argmin, argpartition, argsort,
127127
argwhere, around, array, array2string, array_equal, array_equiv,
@@ -531,8 +531,11 @@ def hugepage_setup():
531531
_core.multiarray._multiarray_umath._reload_guard()
532532

533533
# TODO: Remove the environment variable entirely now that it is "weak"
534-
_core._set_promotion_state(
535-
os.environ.get("NPY_PROMOTION_STATE", "weak"))
534+
if (os.environ.get("NPY_PROMOTION_STATE", "weak") != "weak"):
535+
warnings.warn(
536+
"NPY_PROMOTION_STATE was a temporary feature for NumPy 2.0 "
537+
"transition and is ignored after NumPy 2.2.",
538+
UserWarning, stacklevel=2)
536539

537540
# Tell PyInstaller where to find hook-numpy.py
538541
def _pyinstaller_hooks_dir():

numpy/__init__.pyi

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3891,11 +3891,6 @@ class errstate:
38913891
) -> None: ...
38923892
def __call__(self, func: _CallType) -> _CallType: ...
38933893

3894-
@contextmanager
3895-
def _no_nep50_warning() -> Generator[None, None, None]: ...
3896-
def _get_promotion_state() -> str: ...
3897-
def _set_promotion_state(state: str, /) -> None: ...
3898-
38993894
_ScalarType_co = TypeVar("_ScalarType_co", bound=generic, covariant=True)
39003895

39013896
class ndenumerate(Generic[_ScalarType_co]):

numpy/_core/_methods.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
from numpy._core.multiarray import asanyarray
1515
from numpy._core import numerictypes as nt
1616
from numpy._core import _exceptions
17-
from numpy._core._ufunc_config import _no_nep50_warning
1817
from numpy._globals import _NoValue
1918

2019
# save those O(100) nanoseconds!
@@ -135,9 +134,8 @@ def _mean(a, axis=None, dtype=None, out=None, keepdims=False, *, where=True):
135134

136135
ret = umr_sum(arr, axis, dtype, out, keepdims, where=where)
137136
if isinstance(ret, mu.ndarray):
138-
with _no_nep50_warning():
139-
ret = um.true_divide(
140-
ret, rcount, out=ret, casting='unsafe', subok=False)
137+
ret = um.true_divide(
138+
ret, rcount, out=ret, casting='unsafe', subok=False)
141139
if is_float16_result and out is None:
142140
ret = arr.dtype.type(ret)
143141
elif hasattr(ret, 'dtype'):
@@ -180,9 +178,8 @@ def _var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False, *,
180178
# matching rcount to arrmean when where is specified as array
181179
div = rcount.reshape(arrmean.shape)
182180
if isinstance(arrmean, mu.ndarray):
183-
with _no_nep50_warning():
184-
arrmean = um.true_divide(arrmean, div, out=arrmean,
185-
casting='unsafe', subok=False)
181+
arrmean = um.true_divide(arrmean, div, out=arrmean,
182+
casting='unsafe', subok=False)
186183
elif hasattr(arrmean, "dtype"):
187184
arrmean = arrmean.dtype.type(arrmean / rcount)
188185
else:
@@ -212,9 +209,8 @@ def _var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False, *,
212209

213210
# divide by degrees of freedom
214211
if isinstance(ret, mu.ndarray):
215-
with _no_nep50_warning():
216-
ret = um.true_divide(
217-
ret, rcount, out=ret, casting='unsafe', subok=False)
212+
ret = um.true_divide(
213+
ret, rcount, out=ret, casting='unsafe', subok=False)
218214
elif hasattr(ret, 'dtype'):
219215
ret = ret.dtype.type(ret / rcount)
220216
else:

numpy/_core/_ufunc_config.py

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
__all__ = [
1515
"seterr", "geterr", "setbufsize", "getbufsize", "seterrcall", "geterrcall",
16-
"errstate", '_no_nep50_warning'
16+
"errstate"
1717
]
1818

1919

@@ -481,22 +481,3 @@ def inner(*args, **kwargs):
481481
_extobj_contextvar.reset(_token)
482482

483483
return inner
484-
485-
486-
NO_NEP50_WARNING = contextvars.ContextVar("_no_nep50_warning", default=False)
487-
488-
@set_module('numpy')
489-
@contextlib.contextmanager
490-
def _no_nep50_warning():
491-
"""
492-
Context manager to disable NEP 50 warnings. This context manager is
493-
only relevant if the NEP 50 warnings are enabled globally (which is not
494-
thread/context safe).
495-
496-
This warning context manager itself is fully safe, however.
497-
"""
498-
token = NO_NEP50_WARNING.set(True)
499-
try:
500-
yield
501-
finally:
502-
NO_NEP50_WARNING.reset(token)

numpy/_core/multiarray.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
_flagdict, from_dlpack, _place, _reconstruct,
1818
_vec_string, _ARRAY_API, _monotonicity, _get_ndarray_c_version,
1919
_get_madvise_hugepage, _set_madvise_hugepage,
20-
_get_promotion_state, _set_promotion_state
2120
)
2221

2322
__all__ = [
@@ -40,8 +39,7 @@
4039
'normalize_axis_index', 'packbits', 'promote_types', 'putmask',
4140
'ravel_multi_index', 'result_type', 'scalar', 'set_datetimeparse_function',
4241
'set_typeDict', 'shares_memory', 'typeinfo',
43-
'unpackbits', 'unravel_index', 'vdot', 'where', 'zeros',
44-
'_get_promotion_state', '_set_promotion_state']
42+
'unpackbits', 'unravel_index', 'vdot', 'where', 'zeros']
4543

4644
# For backward compatibility, make sure pickle imports
4745
# these functions from here
@@ -67,8 +65,6 @@
6765
nested_iters.__module__ = 'numpy'
6866
promote_types.__module__ = 'numpy'
6967
zeros.__module__ = 'numpy'
70-
_get_promotion_state.__module__ = 'numpy'
71-
_set_promotion_state.__module__ = 'numpy'
7268
normalize_axis_index.__module__ = 'numpy.lib.array_utils'
7369

7470

numpy/_core/numeric.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@
1717
empty, empty_like, flatiter, frombuffer, from_dlpack, fromfile, fromiter,
1818
fromstring, inner, lexsort, matmul, may_share_memory, min_scalar_type,
1919
ndarray, nditer, nested_iters, promote_types, putmask, result_type,
20-
shares_memory, vdot, where, zeros, normalize_axis_index,
21-
_get_promotion_state, _set_promotion_state, vecdot
20+
shares_memory, vdot, where, zeros, normalize_axis_index, vecdot
2221
)
2322

2423
from . import overrides
@@ -28,7 +27,7 @@
2827
from .umath import (multiply, invert, sin, PINF, NAN)
2928
from . import numerictypes
3029
from ..exceptions import AxisError
31-
from ._ufunc_config import errstate, _no_nep50_warning
30+
from ._ufunc_config import errstate
3231

3332
bitwise_not = invert
3433
ufunc = type(sin)
@@ -53,7 +52,7 @@
5352
'identity', 'allclose', 'putmask',
5453
'flatnonzero', 'inf', 'nan', 'False_', 'True_', 'bitwise_not',
5554
'full', 'full_like', 'matmul', 'vecdot', 'shares_memory',
56-
'may_share_memory', '_get_promotion_state', '_set_promotion_state']
55+
'may_share_memory']
5756

5857

5958
def _zeros_like_dispatcher(
@@ -2457,7 +2456,7 @@ def isclose(a, b, rtol=1.e-5, atol=1.e-8, equal_nan=False):
24572456
elif isinstance(y, int):
24582457
y = float(y)
24592458

2460-
with errstate(invalid='ignore'), _no_nep50_warning():
2459+
with errstate(invalid='ignore'):
24612460
result = (less_equal(abs(x-y), atol + rtol * abs(y))
24622461
& isfinite(y)
24632462
| (x == y))

numpy/_core/src/multiarray/arraytypes.c.src

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -275,41 +275,10 @@ static int
275275
#endif
276276
) {
277277
PyArray_Descr *descr = PyArray_DescrFromType(NPY_@TYPE@);
278-
int promotion_state = get_npy_promotion_state();
279-
if (promotion_state == NPY_USE_LEGACY_PROMOTION || (
280-
promotion_state == NPY_USE_WEAK_PROMOTION_AND_WARN
281-
&& !npy_give_promotion_warnings())) {
282-
/*
283-
* This path will be taken both for the "promotion" case such as
284-
* `uint8_arr + 123` as well as the assignment case.
285-
* The "legacy" path should only ever be taken for assignment
286-
* (legacy promotion will prevent overflows by promoting up)
287-
* so a normal deprecation makes sense.
288-
* When weak promotion is active, we use "future" behavior unless
289-
* warnings were explicitly opt-in.
290-
*/
291-
if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
292-
"NumPy will stop allowing conversion of out-of-bound "
293-
"Python integers to integer arrays. The conversion "
294-
"of %.100R to %S will fail in the future.\n"
295-
"For the old behavior, usually:\n"
296-
" np.array(value).astype(dtype)\n"
297-
"will give the desired result (the cast overflows).",
298-
obj, descr) < 0) {
299-
Py_DECREF(descr);
300-
return -1;
301-
}
302-
Py_DECREF(descr);
303-
return 0;
304-
}
305-
else {
306-
/* Live in the future, outright error: */
307-
PyErr_Format(PyExc_OverflowError,
308-
"Python integer %R out of bounds for %S", obj, descr);
309-
Py_DECREF(descr);
310-
return -1;
311-
}
312-
assert(0);
278+
PyErr_Format(PyExc_OverflowError,
279+
"Python integer %R out of bounds for %S", obj, descr);
280+
Py_DECREF(descr);
281+
return -1;
313282
}
314283
return 0;
315284
}

0 commit comments

Comments
 (0)
0