Skip to content

Commit c579282

Browse files
authored
Merge pull request #24255 from charris/backport-24248
BUG: Factor out slow `getenv` call used for memory policy warning
2 parents 39435de + 7ca0270 commit c579282

File tree

5 files changed

+49
-13
lines changed

5 files changed

+49
-13
lines changed

doc/source/reference/global_state.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,6 @@ release (NumPy 2.0) by setting an environment before importing NumPy:
9696

9797
By default this will also activate the :ref:`NEP 50 <NEP50>` related setting
9898
``NPY_PROMOTION_STATE`` (please see the NEP for details on this).
99+
100+
.. versionchanged:: 1.25.2
101+
This variable is only checked on the first import.

numpy/core/src/multiarray/arrayobject.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ maintainer email: oliphant.travis@ieee.org
6262
#include "binop_override.h"
6363
#include "array_coercion.h"
6464

65+
66+
NPY_NO_EXPORT npy_bool numpy_warn_if_no_mem_policy = 0;
67+
6568
/*NUMPY_API
6669
Compute the size of an array (in number of items)
6770
*/
@@ -460,9 +463,8 @@ array_dealloc(PyArrayObject *self)
460463
}
461464
}
462465
if (fa->mem_handler == NULL) {
463-
char *env = getenv("NUMPY_WARN_IF_NO_MEM_POLICY");
464-
if ((env != NULL) && (strncmp(env, "1", 1) == 0)) {
465-
char const * msg = "Trying to dealloc data, but a memory policy "
466+
if (numpy_warn_if_no_mem_policy) {
467+
char const *msg = "Trying to dealloc data, but a memory policy "
466468
"is not set. If you take ownership of the data, you must "
467469
"set a base owning the data (e.g. a PyCapsule).";
468470
WARN_IN_DEALLOC(PyExc_RuntimeWarning, msg);

numpy/core/src/multiarray/arrayobject.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#ifndef NUMPY_CORE_SRC_MULTIARRAY_ARRAYOBJECT_H_
66
#define NUMPY_CORE_SRC_MULTIARRAY_ARRAYOBJECT_H_
77

8+
extern NPY_NO_EXPORT npy_bool numpy_warn_if_no_mem_policy;
9+
810
NPY_NO_EXPORT PyObject *
911
_strings_richcompare(PyArrayObject *self, PyArrayObject *other, int cmp_op,
1012
int rstrip);

numpy/core/src/multiarray/multiarraymodule.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4475,6 +4475,24 @@ normalize_axis_index(PyObject *NPY_UNUSED(self),
44754475
}
44764476

44774477

4478+
static PyObject *
4479+
_set_numpy_warn_if_no_mem_policy(PyObject *NPY_UNUSED(self), PyObject *arg)
4480+
{
4481+
int res = PyObject_IsTrue(arg);
4482+
if (res < 0) {
4483+
return NULL;
4484+
}
4485+
int old_value = numpy_warn_if_no_mem_policy;
4486+
numpy_warn_if_no_mem_policy = res;
4487+
if (old_value) {
4488+
Py_RETURN_TRUE;
4489+
}
4490+
else {
4491+
Py_RETURN_FALSE;
4492+
}
4493+
}
4494+
4495+
44784496
static PyObject *
44794497
_reload_guard(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args)) {
44804498
static int initialized = 0;
@@ -4733,6 +4751,9 @@ static struct PyMethodDef array_module_methods[] = {
47334751
METH_O, "Set the NEP 50 promotion state. This is not thread-safe.\n"
47344752
"The optional warnings can be safely silenced using the \n"
47354753
"`np._no_nep50_warning()` context manager."},
4754+
{"_set_numpy_warn_if_no_mem_policy",
4755+
(PyCFunction)_set_numpy_warn_if_no_mem_policy,
4756+
METH_O, "Change the warn if no mem policy flag for testing."},
47364757
{"_add_newdoc_ufunc", (PyCFunction)add_newdoc_ufunc,
47374758
METH_VARARGS, NULL},
47384759
{"_get_sfloat_dtype",
@@ -5029,6 +5050,14 @@ initialize_static_globals(void)
50295050
npy_numpy2_behavior = NPY_TRUE;
50305051
}
50315052

5053+
env = getenv("NUMPY_WARN_IF_NO_MEM_POLICY");
5054+
if ((env != NULL) && (strncmp(env, "1", 1) == 0)) {
5055+
numpy_warn_if_no_mem_policy = 1;
5056+
}
5057+
else {
5058+
numpy_warn_if_no_mem_policy = 0;
5059+
}
5060+
50325061
return 0;
50335062
}
50345063

numpy/core/tests/test_mem_policy.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -395,16 +395,19 @@ def test_switch_owner(get_module, policy):
395395
a = get_module.get_array()
396396
assert np.core.multiarray.get_handler_name(a) is None
397397
get_module.set_own(a)
398-
oldval = os.environ.get('NUMPY_WARN_IF_NO_MEM_POLICY', None)
398+
399399
if policy is None:
400-
if 'NUMPY_WARN_IF_NO_MEM_POLICY' in os.environ:
401-
os.environ.pop('NUMPY_WARN_IF_NO_MEM_POLICY')
400+
# See what we expect to be set based on the env variable
401+
policy = os.getenv("NUMPY_WARN_IF_NO_MEM_POLICY", "0") == "1"
402+
oldval = None
402403
else:
403-
os.environ['NUMPY_WARN_IF_NO_MEM_POLICY'] = policy
404+
policy = policy == "1"
405+
oldval = np.core._multiarray_umath._set_numpy_warn_if_no_mem_policy(
406+
policy)
404407
try:
405408
# The policy should be NULL, so we have to assume we can call
406409
# "free". A warning is given if the policy == "1"
407-
if policy == "1":
410+
if policy:
408411
with assert_warns(RuntimeWarning) as w:
409412
del a
410413
gc.collect()
@@ -413,11 +416,8 @@ def test_switch_owner(get_module, policy):
413416
gc.collect()
414417

415418
finally:
416-
if oldval is None:
417-
if 'NUMPY_WARN_IF_NO_MEM_POLICY' in os.environ:
418-
os.environ.pop('NUMPY_WARN_IF_NO_MEM_POLICY')
419-
else:
420-
os.environ['NUMPY_WARN_IF_NO_MEM_POLICY'] = oldval
419+
if oldval is not None:
420+
np.core._multiarray_umath._set_numpy_warn_if_no_mem_policy(oldval)
421421

422422
def test_owner_is_base(get_module):
423423
a = get_module.get_array_with_base()

0 commit comments

Comments
 (0)