4
4
"""
5
5
import os
6
6
import sys
7
+ import pathlib
7
8
import platform
8
9
import re
9
10
import gc
19
20
import sysconfig
20
21
import concurrent .futures
21
22
import threading
23
+ import importlib .metadata
22
24
23
25
import numpy as np
24
26
from numpy ._core import (
25
27
intp , float32 , empty , arange , array_repr , ndarray , isnat , array )
26
28
from numpy import isfinite , isnan , isinf
27
29
import numpy .linalg ._umath_linalg
28
30
from numpy ._utils import _rename_parameter
31
+ from numpy ._core .tests ._natype import pd_NA
29
32
30
33
from io import StringIO
31
34
35
+
32
36
__all__ = [
33
37
'assert_equal' , 'assert_almost_equal' , 'assert_approx_equal' ,
34
38
'assert_array_equal' , 'assert_array_less' , 'assert_string_equal' ,
42
46
'HAS_REFCOUNT' , "IS_WASM" , 'suppress_warnings' , 'assert_array_compare' ,
43
47
'assert_no_gc_cycles' , 'break_cycles' , 'HAS_LAPACK64' , 'IS_PYSTON' ,
44
48
'IS_MUSL' , 'check_support_sve' , 'NOGIL_BUILD' ,
45
- 'IS_EDITABLE' , 'run_threaded' ,
49
+ 'IS_EDITABLE' , 'IS_INSTALLED' , 'NUMPY_ROOT' , ' run_threaded' ,
46
50
]
47
51
48
52
@@ -54,10 +58,40 @@ class KnownFailureException(Exception):
54
58
KnownFailureTest = KnownFailureException # backwards compat
55
59
verbose = 0
56
60
61
+ NUMPY_ROOT = pathlib .Path (np .__file__ ).parent
62
+
63
+ try :
64
+ np_dist = importlib .metadata .distribution ('numpy' )
65
+ except importlib .metadata .PackageNotFoundError :
66
+ IS_INSTALLED = IS_EDITABLE = False
67
+ else :
68
+ IS_INSTALLED = True
69
+ try :
70
+ if sys .version_info >= (3 , 13 ):
71
+ IS_EDITABLE = np_dist .origin .dir_info .editable
72
+ else :
73
+ # Backport importlib.metadata.Distribution.origin
74
+ import json , types # noqa: E401
75
+ origin = json .loads (
76
+ np_dist .read_text ('direct_url.json' ) or '{}' ,
77
+ object_hook = lambda data : types .SimpleNamespace (** data ),
78
+ )
79
+ IS_EDITABLE = origin .dir_info .editable
80
+ except AttributeError :
81
+ IS_EDITABLE = False
82
+
83
10000
+ # spin installs numpy directly via meson, instead of using meson-python, and
84
+ # runs the module by setting PYTHONPATH. This is problematic because the
85
+ # resulting installation lacks the Python metadata (.dist-info), and numpy
86
+ # might already be installed on the environment, causing us to find its
87
+ # metadata, even though we are not actually loading that package.
88
+ # Work around this issue by checking if the numpy root matches.
89
+ if not IS_EDITABLE and np_dist .locate_file ('numpy' ) != NUMPY_ROOT :
90
+ IS_INSTALLED = False
91
+
57
92
IS_WASM = platform .machine () in ["wasm32" , "wasm64" ]
58
93
IS_PYPY = sys .implementation .name == 'pypy'
59
94
IS_PYSTON = hasattr (sys , "pyston_version_info" )
60
- IS_EDITABLE = not bool (np .__path__ ) or 'editable' in np .__path__ [0 ]
61
95
HAS_REFCOUNT = getattr (sys , 'getrefcount' , None ) is not None and not IS_PYSTON
62
96
HAS_LAPACK64 = numpy .linalg ._umath_linalg ._ilp64
63
97
@@ -101,14 +135,15 @@ def GetPerformanceAttributes(object, counter, instance=None,
101
135
# thread's CPU usage is either 0 or 100). To read counters like this,
102
136
# you should copy this function, but keep the counter open, and call
103
137
# CollectQueryData() each time you need to know.
104
- # See http://msdn.microsoft.com/library/en-us/dnperfmo/html/perfmonpt2.asp (dead link)
138
+ # See http://msdn.microsoft.com/library/en-us/dnperfmo/html/perfmonpt2.asp
139
+ #(dead link)
105
140
# My older explanation for this was that the "AddCounter" process
106
141
# forced the CPU to 100%, but the above makes more sense :)
107
142
import win32pdh
108
143
if format is None :
109
144
format = win32pdh .PDH_FMT_LONG
110
- path = win32pdh .MakeCounterPath ( (machine , object , instance , None ,
111
- inum , counter ))
145
+ path = win32pdh .MakeCounterPath ((machine , object , instance , None ,
146
+ inum , counter ))
112
147
hq = win32pdh .OpenQuery ()
113
148
try :
114
149
hc = win32pdh .AddCounter (hq , path )
@@ -166,7 +201,7 @@ def jiffies(_proc_pid_stat=f'/proc/{os.getpid()}/stat', _load_time=[]):
166
201
l = f .readline ().split (' ' )
167
202
return int (l [13 ])
168
203
except Exception :
169
- return int (100 * (time .time ()- _load_time [0 ]))
204
+ return int (100 * (time .time () - _load_time [0 ]))
170
205
else :
171
206
# os.getpid is not in all platforms available.
172
207
# Using time is safe but inaccurate, especially when process
@@ -182,15 +217,15 @@ def jiffies(_load_time=[]):
182
217
import time
183
218
if not _load_time :
184
219
_load_time .append (time .time ())
185
- return int (100 * (time .time ()- _load_time [0 ]))
220
+ return int (100 * (time .time () - _load_time [0 ]))
186
221
187
222
188
223
def build_err_msg (arrays , err_msg , header = 'Items are not equal:' ,
189
224
verbose = True , names = ('ACTUAL' , 'DESIRED' ), precision = 8 ):
190
225
msg = ['\n ' + header ]
191
226
err_msg = str (err_msg )
192
227
if err_msg :
193
- if err_msg .find ('\n ' ) == - 1 and len (err_msg ) < 79 - len (header ):
228
+ if err_msg .find ('\n ' ) == - 1 and len (err_msg ) < 79 - len (header ):
194
229
msg = [msg [0 ] + ' ' + err_msg ]
195
230
else :
196
231
msg .append (err_msg )
@@ -659,14 +694,14 @@ def assert_approx_equal(actual, desired, significant=7, err_msg='',
659
694
# Normalized the numbers to be in range (-10.0,10.0)
660
695
# scale = float(pow(10,math.floor(math.log10(0.5*(abs(desired)+abs(actual))))))
661
696
with np .errstate (invalid = 'ignore' ):
662
- scale = 0.5 * (np .abs (desired ) + np .abs (actual ))
697
+ scale = 0.5 * (np .abs (desired ) + np .abs (actual ))
663
698
scale = np .power (10 , np .floor (np .log10 (scale )))
664
699
try :
665
- sc_desired = desired / scale
700
+ sc_desired = desired / scale
666
701
except ZeroDivisionError :
667
702
sc_desired = 0.0
668
703
try :
669
- sc_actual = actual / scale
704
+ sc_actual = actual / scale
670
705
except ZeroDivisionError :
671
706
sc_actual = 0.0
672
707
msg = build_err_msg (
@@ -687,7 +722,7 @@ def assert_approx_equal(actual, desired, significant=7, err_msg='',
687
722
return
688
723
except (TypeError , NotImplementedError ):
689
724
pass
690
- if np .abs (sc_desired - sc_actual ) >= np .power (10. , - (significant - 1 )):
725
+ if np .abs (sc_desired - sc_actual ) >= np .power (10. , - (significant - 1 )):
691
726
raise AssertionError (msg )
692
727
693
728
@@ -1379,10 +1414,10 @@ def check_support_sve(__cache=[]):
1379
1414
"""
1380
1415
gh-22982
1381
1416
"""
1382
-
1417
+
1383
1418
if __cache :
1384
1419
return __cache [0 ]
1385
-
1420
+
1386
1421
import subprocess
1387
1422
cmd = 'lscpu'
1388
1423
try :
@@ -1543,7 +1578,7 @@ def measure(code_str, times=1, label=None):
1543
1578
i += 1
1544
1579
exec (code , globs , locs )
1545
1580
elapsed = jiffies () - elapsed
1546
- return 0.01 * elapsed
1581
+ return 0.01 * elapsed
1547
1582
1548
1583
1549
1584
def _assert_valid_refcount (op ):
@@ -1557,7 +1592,7 @@ def _assert_valid_refcount(op):
1557
1592
import gc
1558
1593
import numpy as np
1559
1594
1560
- b = np .arange (100 * 100 ).reshape (100 , 100 )
1595
+ b = np .arange (100 * 100 ).reshape (100 , 100 )
1561
1596
c = b
1562
1597
i = 1
1563
1598
@@ -1735,7 +1770,7 @@ def assert_array_almost_equal_nulp(x, y, nulp=1):
1735
1770
ax = np .abs (x )
1736
1771
ay = np .abs (y )
1737
1772
ref = nulp * np .spacing (np .where (ax > ay , ax , ay ))
1738
- if not np .all (np .abs (x - y ) <= ref ):
1773
+ if not np .all (np .abs (x - y ) <= ref ):
1739
1774
if np .iscomplexobj (x ) or np .iscomplexobj (y ):
1740
1775
msg = f"Arrays are not equal to { nulp } ULP"
1741
1776
else :
@@ -1851,7 +1886,7 @@ def nulp_diff(x, y, dtype=None):
1851
1886
(x .shape , y .shape ))
1852
1887
1853
1888
def _diff (rx , ry , vdt ):
1854
- diff = np .asarray (rx - ry , dtype = vdt )
1889
+ diff = np .asarray (rx - ry , dtype = vdt )
1855
1890
return np .abs (diff )
1856
1891
1857
1892
rx = integer_repr (x )
@@ -2596,7 +2631,7 @@ def check_free_memory(free_bytes):
2596
2631
except ValueError as exc :
2597
2632
raise ValueError (f'Invalid environment variable { env_var } : { exc } ' )
2598
2633
2599
- msg = (f'{ free_bytes / 1e9 } GB memory required, but environment variable '
2634
+ msg = (f'{ free_bytes / 1e9 } GB memory required, but environment variable '
2600
2635
f'NPY_AVAILABLE_MEM={ env_value } set' )
2601
2636
else :
2602
2637
mem_free = _get_mem_available ()
@@ -2607,7 +2642,9 @@ def check_free_memory(free_bytes):
2607
2642
"the test." )
2608
2643
mem_free = - 1
2609
2644
else :
2610
- msg = f'{ free_bytes / 1e9 } GB memory required, but { mem_free / 1e9 } GB available'
2645
+ free_bytes_gb = free_bytes / 1e9
2646
+ mem_free_gb = mem_free / 1e9
2647
+ msg = f'{ free_bytes_gb } GB memory required, but { mem_free_gb } GB available'
2611
2648
2612
2649
return msg if mem_free < free_bytes else None
2613
2650
0 commit comments