numexpr 2.10.0__tar.gz → 2.10.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {numexpr-2.10.0 → numexpr-2.10.2}/ANNOUNCE.rst +14 -15
- {numexpr-2.10.0 → numexpr-2.10.2}/MANIFEST.in +1 -1
- {numexpr-2.10.0 → numexpr-2.10.2}/PKG-INFO +13 -11
- {numexpr-2.10.0 → numexpr-2.10.2}/RELEASE_NOTES.rst +30 -0
- numexpr-2.10.2/VERSION +1 -0
- numexpr-2.10.2/bench/large_array_vs_numpy.py +152 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/__init__.py +0 -2
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/interpreter.cpp +6 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/necompiler.py +4 -6
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/tests/test_numexpr.py +88 -15
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/utils.py +85 -4
- numexpr-2.10.2/numexpr/version.py +5 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr.egg-info/PKG-INFO +13 -11
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr.egg-info/SOURCES.txt +2 -2
- numexpr-2.10.2/numexpr.egg-info/requires.txt +1 -0
- numexpr-2.10.2/pyproject.toml +50 -0
- numexpr-2.10.2/requirements.txt +1 -0
- numexpr-2.10.2/setup.cfg +4 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/setup.py +15 -6
- numexpr-2.10.0/numexpr/version.py +0 -4
- numexpr-2.10.0/numexpr.egg-info/not-zip-safe +0 -1
- numexpr-2.10.0/numexpr.egg-info/requires.txt +0 -1
- numexpr-2.10.0/pyproject.toml +0 -7
- numexpr-2.10.0/requirements.txt +0 -1
- numexpr-2.10.0/setup.cfg +0 -34
- {numexpr-2.10.0 → numexpr-2.10.2}/AUTHORS.txt +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/LICENSE.txt +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/README.rst +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/bench/boolean_timing.py +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/bench/issue-36.py +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/bench/issue-47.py +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/bench/multidim.py +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/bench/poly.py +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/bench/timing.py +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/bench/unaligned-simple.py +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/bench/varying-expr.py +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/bench/vml_timing.py +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/bench/vml_timing2.py +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/bench/vml_timing3.py +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/complex_functions.hpp +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/cpuinfo.py +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/expressions.py +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/functions.hpp +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/interp_body.cpp +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/interpreter.hpp +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/missing_posix_functions.hpp +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/module.cpp +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/module.hpp +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/msvc_function_stubs.hpp +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/numexpr_config.hpp +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/numexpr_object.cpp +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/numexpr_object.hpp +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/opcodes.hpp +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/str-two-way.hpp +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/tests/__init__.py +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/win32/pthread.c +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/win32/pthread.h +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr/win32/stdint.h +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr.egg-info/dependency_links.txt +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/numexpr.egg-info/top_level.txt +0 -0
- {numexpr-2.10.0 → numexpr-2.10.2}/site.cfg.example +0 -0
|
@@ -1,29 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
Announcing NumExpr 2.
|
|
3
|
-
|
|
1
|
+
=========================
|
|
2
|
+
Announcing NumExpr 2.10.2
|
|
3
|
+
=========================
|
|
4
4
|
|
|
5
5
|
Hi everyone,
|
|
6
6
|
|
|
7
|
-
NumExpr 2.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
NumExpr 2.10.2 provides wheels for Python 2.13 for first time.
|
|
8
|
+
Also, there is better support for CPUs that do not have a power
|
|
9
|
+
of 2 number of cores. Finally, numexpr is allowed to run with
|
|
10
|
+
the multithreading package in Python.
|
|
11
11
|
|
|
12
12
|
Project documentation is available at:
|
|
13
13
|
|
|
14
14
|
http://numexpr.readthedocs.io/
|
|
15
15
|
|
|
16
|
-
Changes from 2.
|
|
17
|
-
|
|
16
|
+
Changes from 2.10.1 to 2.10.2
|
|
17
|
+
-----------------------------
|
|
18
18
|
|
|
19
|
-
*
|
|
20
|
-
|
|
21
|
-
@27rabbitlt for most of the work and @mgorny and @mattip for
|
|
22
|
-
providing help and additional fixes. Fixes #463.
|
|
19
|
+
* Better support for CPUs that do not have a power of 2 number of
|
|
20
|
+
cores. See #479 and #490. Thanks to @avalentino.
|
|
23
21
|
|
|
24
|
-
*
|
|
22
|
+
* Allow numexpr to run with the multithreading package in Python.
|
|
23
|
+
See PR #496. Thanks to @emmaai
|
|
25
24
|
|
|
26
|
-
*
|
|
25
|
+
* Wheels for Python 3.13 are now provided.
|
|
27
26
|
|
|
28
27
|
What's Numexpr?
|
|
29
28
|
---------------
|
|
@@ -1,29 +1,31 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: numexpr
|
|
3
|
-
Version: 2.10.
|
|
3
|
+
Version: 2.10.2
|
|
4
4
|
Summary: Fast numerical expression evaluator for NumPy
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
Author-email: "David M. Cooke, Francesc Alted, and others" <blosc@blosc.org>
|
|
6
|
+
Maintainer-email: Blosc Development Team <blosc@blosc.org>
|
|
7
|
+
Project-URL: homepage, https://github.com/pydata/numexpr
|
|
8
|
+
Project-URL: documentation, https://numexpr.readthedocs.io
|
|
9
|
+
Project-URL: repository, https://github.com/pydata/numexpr
|
|
10
10
|
Classifier: Development Status :: 6 - Mature
|
|
11
|
-
Classifier: Intended Audience ::
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Information Technology
|
|
12
13
|
Classifier: Intended Audience :: Science/Research
|
|
13
14
|
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
18
|
+
Classifier: Operating System :: Unix
|
|
14
19
|
Classifier: Programming Language :: Python :: 3
|
|
15
20
|
Classifier: Programming Language :: Python :: 3.9
|
|
16
21
|
Classifier: Programming Language :: Python :: 3.10
|
|
17
22
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
23
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
-
Classifier: Operating System :: Microsoft :: Windows
|
|
20
|
-
Classifier: Operating System :: POSIX
|
|
21
|
-
Classifier: Operating System :: MacOS
|
|
22
24
|
Requires-Python: >=3.9
|
|
23
25
|
Description-Content-Type: text/x-rst
|
|
24
26
|
License-File: LICENSE.txt
|
|
25
27
|
License-File: AUTHORS.txt
|
|
26
|
-
Requires-Dist: numpy>=1.
|
|
28
|
+
Requires-Dist: numpy>=1.23.0
|
|
27
29
|
|
|
28
30
|
======================================================
|
|
29
31
|
NumExpr: Fast numerical expression evaluator for NumPy
|
|
@@ -2,6 +2,36 @@
|
|
|
2
2
|
Release notes for NumExpr 2.10 series
|
|
3
3
|
=====================================
|
|
4
4
|
|
|
5
|
+
Changes from 2.10.1 to 2.10.2
|
|
6
|
+
-----------------------------
|
|
7
|
+
|
|
8
|
+
* Better support for CPUs that do not have a power of 2 number of
|
|
9
|
+
cores. See #479 and #490. Thanks to @avalentino.
|
|
10
|
+
|
|
11
|
+
* Allow numexpr to run with the multithreading package in Python.
|
|
12
|
+
See PR #496. Thanks to @emmaai
|
|
13
|
+
|
|
14
|
+
* Wheels for Python 3.13 are now provided.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
Changes from 2.10.0 to 2.10.1
|
|
18
|
+
-----------------------------
|
|
19
|
+
|
|
20
|
+
* The default number of 'safe' threads has been upgraded to 16 (instead of
|
|
21
|
+
previous 8). That means that if your CPU has > 16 cores, the default is
|
|
22
|
+
to use 16. You can always override this with the "NUMEXPR_MAX_THREADS"
|
|
23
|
+
environment variable.
|
|
24
|
+
|
|
25
|
+
* NumPy 1.23 is now the minimum supported.
|
|
26
|
+
|
|
27
|
+
* Preliminary support for Python 3.13. Thanks to Karolina Surma.
|
|
28
|
+
|
|
29
|
+
* Fix tests on nthreads detection (closes: #479). Thanks to @avalentino.
|
|
30
|
+
|
|
31
|
+
* The build process has been modernized and now uses the `pyproject.toml`
|
|
32
|
+
file for more of the configuration options.
|
|
33
|
+
|
|
34
|
+
|
|
5
35
|
Changes from 2.9.0 to 2.10.0
|
|
6
36
|
----------------------------
|
|
7
37
|
|
numexpr-2.10.2/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.10.2
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
#################################################################################
|
|
2
|
+
# To mimic the scenario that computation is i/o bound and constrained by memory
|
|
3
|
+
#
|
|
4
|
+
# It's a much simplified version that the chunk is computed in a loop,
|
|
5
|
+
# and expression is evaluated in a sequence, which is not true in reality.
|
|
6
|
+
# Neverthless, numexpr outperforms numpy.
|
|
7
|
+
#################################################################################
|
|
8
|
+
"""
|
|
9
|
+
Benchmarking Expression 1:
|
|
10
|
+
NumPy time (threaded over 32 chunks with 2 threads): 4.612313 seconds
|
|
11
|
+
numexpr time (threaded with re_evaluate over 32 chunks with 2 threads): 0.951172 seconds
|
|
12
|
+
numexpr speedup: 4.85x
|
|
13
|
+
----------------------------------------
|
|
14
|
+
Benchmarking Expression 2:
|
|
15
|
+
NumPy time (threaded over 32 chunks with 2 threads): 23.862752 seconds
|
|
16
|
+
numexpr time (threaded with re_evaluate over 32 chunks with 2 threads): 2.182058 seconds
|
|
17
|
+
numexpr speedup: 10.94x
|
|
18
|
+
----------------------------------------
|
|
19
|
+
Benchmarking Expression 3:
|
|
20
|
+
NumPy time (threaded over 32 chunks with 2 threads): 20.594895 seconds
|
|
21
|
+
numexpr time (threaded with re_evaluate over 32 chunks with 2 threads): 2.927881 seconds
|
|
22
|
+
numexpr speedup: 7.03x
|
|
23
|
+
----------------------------------------
|
|
24
|
+
Benchmarking Expression 4:
|
|
25
|
+
NumPy time (threaded over 32 chunks with 2 threads): 12.834101 seconds
|
|
26
|
+
numexpr time (threaded with re_evaluate over 32 chunks with 2 threads): 5.392480 seconds
|
|
27
|
+
numexpr speedup: 2.38x
|
|
28
|
+
----------------------------------------
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
import os
|
|
32
|
+
|
|
33
|
+
os.environ["NUMEXPR_NUM_THREADS"] = "16"
|
|
34
|
+
import numpy as np
|
|
35
|
+
import numexpr as ne
|
|
36
|
+
import timeit
|
|
37
|
+
import threading
|
|
38
|
+
|
|
39
|
+
array_size = 10**8
|
|
40
|
+
num_runs = 10
|
|
41
|
+
num_chunks = 32 # Number of chunks
|
|
42
|
+
num_threads = 2 # Number of threads constrained by how many chunks memory can hold
|
|
43
|
+
|
|
44
|
+
a = np.random.rand(array_size).reshape(10**4, -1)
|
|
45
|
+
b = np.random.rand(array_size).reshape(10**4, -1)
|
|
46
|
+
c = np.random.rand(array_size).reshape(10**4, -1)
|
|
47
|
+
|
|
48
|
+
chunk_size = array_size // num_chunks
|
|
49
|
+
|
|
50
|
+
expressions_numpy = [
|
|
51
|
+
lambda a, b, c: a + b * c,
|
|
52
|
+
lambda a, b, c: a**2 + b**2 - 2 * a * b * np.cos(c),
|
|
53
|
+
lambda a, b, c: np.sin(a) + np.log(b) * np.sqrt(c),
|
|
54
|
+
lambda a, b, c: np.exp(a) + np.tan(b) - np.sinh(c),
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
expressions_numexpr = [
|
|
58
|
+
"a + b * c",
|
|
59
|
+
"a**2 + b**2 - 2 * a * b * cos(c)",
|
|
60
|
+
"sin(a) + log(b) * sqrt(c)",
|
|
61
|
+
"exp(a) + tan(b) - sinh(c)",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def benchmark_numpy_chunk(func, a, b, c, results, indices):
|
|
66
|
+
for index in indices:
|
|
67
|
+
start = index * chunk_size
|
|
68
|
+
end = (index + 1) * chunk_size
|
|
69
|
+
time_taken = timeit.timeit(
|
|
70
|
+
lambda: func(a[start:end], b[start:end], c[start:end]), number=num_runs
|
|
71
|
+
)
|
|
72
|
+
results.append(time_taken)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def benchmark_numexpr_re_evaluate(expr, a, b, c, results, indices):
|
|
76
|
+
for index in indices:
|
|
77
|
+
start = index * chunk_size
|
|
78
|
+
end = (index + 1) * chunk_size
|
|
79
|
+
if index == 0:
|
|
80
|
+
# Evaluate the first chunk with evaluate
|
|
81
|
+
time_taken = timeit.timeit(
|
|
82
|
+
lambda: ne.evaluate(
|
|
83
|
+
expr,
|
|
84
|
+
local_dict={
|
|
85
|
+
"a": a[start:end],
|
|
86
|
+
"b": b[start:end],
|
|
87
|
+
"c": c[start:end],
|
|
88
|
+
},
|
|
89
|
+
),
|
|
90
|
+
number=num_runs,
|
|
91
|
+
)
|
|
92
|
+
else:
|
|
93
|
+
# Re-evaluate subsequent chunks with re_evaluate
|
|
94
|
+
time_taken = timeit.timeit(
|
|
95
|
+
lambda: ne.re_evaluate(
|
|
96
|
+
local_dict={"a": a[start:end], "b": b[start:end], "c": c[start:end]}
|
|
97
|
+
),
|
|
98
|
+
number=num_runs,
|
|
99
|
+
)
|
|
100
|
+
results.append(time_taken)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def run_benchmark_threaded():
|
|
104
|
+
chunk_indices = list(range(num_chunks))
|
|
105
|
+
|
|
106
|
+
for i in range(len(expressions_numpy)):
|
|
107
|
+
print(f"Benchmarking Expression {i+1}:")
|
|
108
|
+
|
|
109
|
+
results_numpy = []
|
|
110
|
+
results_numexpr = []
|
|
111
|
+
|
|
112
|
+
threads_numpy = []
|
|
113
|
+
for j in range(num_threads):
|
|
114
|
+
indices = chunk_indices[j::num_threads] # Distribute chunks across threads
|
|
115
|
+
thread = threading.Thread(
|
|
116
|
+
target=benchmark_numpy_chunk,
|
|
117
|
+
args=(expressions_numpy[i], a, b, c, results_numpy, indices),
|
|
118
|
+
)
|
|
119
|
+
threads_numpy.append(thread)
|
|
120
|
+
thread.start()
|
|
121
|
+
|
|
122
|
+
for thread in threads_numpy:
|
|
123
|
+
thread.join()
|
|
124
|
+
|
|
125
|
+
numpy_time = sum(results_numpy)
|
|
126
|
+
print(
|
|
127
|
+
f"NumPy time (threaded over {num_chunks} chunks with {num_threads} threads): {numpy_time:.6f} seconds"
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
threads_numexpr = []
|
|
131
|
+
for j in range(num_threads):
|
|
132
|
+
indices = chunk_indices[j::num_threads] # Distribute chunks across threads
|
|
133
|
+
thread = threading.Thread(
|
|
134
|
+
target=benchmark_numexpr_re_evaluate,
|
|
135
|
+
args=(expressions_numexpr[i], a, b, c, results_numexpr, indices),
|
|
136
|
+
)
|
|
137
|
+
threads_numexpr.append(thread)
|
|
138
|
+
thread.start()
|
|
139
|
+
|
|
140
|
+
for thread in threads_numexpr:
|
|
141
|
+
thread.join()
|
|
142
|
+
|
|
143
|
+
numexpr_time = sum(results_numexpr)
|
|
144
|
+
print(
|
|
145
|
+
f"numexpr time (threaded with re_evaluate over {num_chunks} chunks with {num_threads} threads): {numexpr_time:.6f} seconds"
|
|
146
|
+
)
|
|
147
|
+
print(f"numexpr speedup: {numpy_time / numexpr_time:.2f}x")
|
|
148
|
+
print("-" * 40)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
if __name__ == "__main__":
|
|
152
|
+
run_benchmark_threaded()
|
|
@@ -28,8 +28,6 @@ is_cpu_amd_intel = False # DEPRECATION WARNING: WILL BE REMOVED IN FUTURE RELEAS
|
|
|
28
28
|
# cpuinfo imports were moved into the test submodule function that calls them
|
|
29
29
|
# to improve import times.
|
|
30
30
|
|
|
31
|
-
import os, os.path
|
|
32
|
-
import platform
|
|
33
31
|
from numexpr.expressions import E
|
|
34
32
|
from numexpr.necompiler import (NumExpr, disassemble, evaluate, re_evaluate,
|
|
35
33
|
validate)
|
|
@@ -47,6 +47,12 @@
|
|
|
47
47
|
#define AVAILABLE(Haystack, Haystack_Len, J, Needle_Len) \
|
|
48
48
|
((Haystack_Len) >= (J) + (Needle_Len))
|
|
49
49
|
|
|
50
|
+
// To allow building with NumPy<2 locally define the new NumPy macros:
|
|
51
|
+
#if NPY_ABI_VERSION < 0x02000000
|
|
52
|
+
#define PyDataType_ELSIZE(descr) ((descr)->elsize)
|
|
53
|
+
#define PyDataType_SET_ELSIZE(descr, size) (descr)->elsize = size
|
|
54
|
+
#endif
|
|
55
|
+
|
|
50
56
|
#include "str-two-way.hpp"
|
|
51
57
|
|
|
52
58
|
#ifdef DEBUG
|
|
@@ -19,7 +19,7 @@ import numpy
|
|
|
19
19
|
|
|
20
20
|
is_cpu_amd_intel = False # DEPRECATION WARNING: WILL BE REMOVED IN FUTURE RELEASE
|
|
21
21
|
from numexpr import interpreter, expressions, use_vml
|
|
22
|
-
from numexpr.utils import CacheDict
|
|
22
|
+
from numexpr.utils import CacheDict, ContextDict
|
|
23
23
|
|
|
24
24
|
# Declare a double type that does not exist in Python space
|
|
25
25
|
double = numpy.double
|
|
@@ -767,7 +767,7 @@ def getArguments(names, local_dict=None, global_dict=None, _frame_depth: int=2):
|
|
|
767
767
|
# If we generated local_dict via an explicit reference to f_locals,
|
|
768
768
|
# clear the dict to prevent creating extra ref counts in the caller's scope
|
|
769
769
|
# See https://github.com/pydata/numexpr/issues/310
|
|
770
|
-
if clear_local_dict:
|
|
770
|
+
if clear_local_dict and hasattr(local_dict, 'clear'):
|
|
771
771
|
local_dict.clear()
|
|
772
772
|
|
|
773
773
|
return arguments
|
|
@@ -776,11 +776,9 @@ def getArguments(names, local_dict=None, global_dict=None, _frame_depth: int=2):
|
|
|
776
776
|
# Dictionaries for caching variable names and compiled expressions
|
|
777
777
|
_names_cache = CacheDict(256)
|
|
778
778
|
_numexpr_cache = CacheDict(256)
|
|
779
|
-
_numexpr_last =
|
|
779
|
+
_numexpr_last = ContextDict()
|
|
780
780
|
evaluate_lock = threading.Lock()
|
|
781
781
|
|
|
782
|
-
# MAYBE: decorate this function to add attributes instead of having the
|
|
783
|
-
# _numexpr_last dictionary?
|
|
784
782
|
def validate(ex: str,
|
|
785
783
|
local_dict: Optional[Dict] = None,
|
|
786
784
|
global_dict: Optional[Dict] = None,
|
|
@@ -887,7 +885,7 @@ def validate(ex: str,
|
|
|
887
885
|
compiled_ex = _numexpr_cache[numexpr_key] = NumExpr(ex, signature, sanitize=sanitize, **context)
|
|
888
886
|
kwargs = {'out': out, 'order': order, 'casting': casting,
|
|
889
887
|
'ex_uses_vml': ex_uses_vml}
|
|
890
|
-
_numexpr_last
|
|
888
|
+
_numexpr_last.set(ex=compiled_ex, argnames=names, kwargs=kwargs)
|
|
891
889
|
except Exception as e:
|
|
892
890
|
return e
|
|
893
891
|
return None
|
|
@@ -41,6 +41,7 @@ TestCase = unittest.TestCase
|
|
|
41
41
|
|
|
42
42
|
double = np.double
|
|
43
43
|
long = int
|
|
44
|
+
MAX_THREADS = 16
|
|
44
45
|
|
|
45
46
|
|
|
46
47
|
class test_numexpr(TestCase):
|
|
@@ -1128,7 +1129,7 @@ class test_threading_config(TestCase):
|
|
|
1128
1129
|
"if 'NUMEXPR_MAX_THREADS' in os.environ: os.environ.pop('NUMEXPR_MAX_THREADS')",
|
|
1129
1130
|
"if 'OMP_NUM_THREADS' in os.environ: os.environ.pop('OMP_NUM_THREADS')",
|
|
1130
1131
|
"import numexpr",
|
|
1131
|
-
"assert(numexpr.nthreads <=
|
|
1132
|
+
f"assert(numexpr.nthreads <= {MAX_THREADS})",
|
|
1132
1133
|
"exit(0)"])
|
|
1133
1134
|
subprocess.check_call([sys.executable, '-c', script])
|
|
1134
1135
|
|
|
@@ -1164,14 +1165,14 @@ class test_threading_config(TestCase):
|
|
|
1164
1165
|
if 'sparc' in platform.machine():
|
|
1165
1166
|
self.assertEqual(1, numexpr._init_num_threads())
|
|
1166
1167
|
else:
|
|
1167
|
-
self.assertEqual(detect_number_of_cores(), numexpr._init_num_threads())
|
|
1168
|
+
self.assertEqual(min(detect_number_of_cores(), MAX_THREADS), numexpr._init_num_threads())
|
|
1168
1169
|
|
|
1169
1170
|
def test_numexpr_max_threads_empty_string(self):
|
|
1170
1171
|
with _environment('NUMEXPR_MAX_THREADS', ''):
|
|
1171
1172
|
if 'sparc' in platform.machine():
|
|
1172
1173
|
self.assertEqual(1, numexpr._init_num_threads())
|
|
1173
1174
|
else:
|
|
1174
|
-
self.assertEqual(detect_number_of_cores(), numexpr._init_num_threads())
|
|
1175
|
+
self.assertEqual(min(detect_number_of_cores(), MAX_THREADS), numexpr._init_num_threads())
|
|
1175
1176
|
|
|
1176
1177
|
def test_vml_threads_round_trip(self):
|
|
1177
1178
|
n_threads = 3
|
|
@@ -1200,6 +1201,7 @@ class test_threading(TestCase):
|
|
|
1200
1201
|
test.join()
|
|
1201
1202
|
|
|
1202
1203
|
def test_multithread(self):
|
|
1204
|
+
|
|
1203
1205
|
import threading
|
|
1204
1206
|
|
|
1205
1207
|
# Running evaluate() from multiple threads shouldn't crash
|
|
@@ -1217,6 +1219,77 @@ class test_threading(TestCase):
|
|
|
1217
1219
|
for t in threads:
|
|
1218
1220
|
t.join()
|
|
1219
1221
|
|
|
1222
|
+
def test_thread_safety(self):
|
|
1223
|
+
"""
|
|
1224
|
+
Expected output
|
|
1225
|
+
|
|
1226
|
+
When not safe (before the pr this test is commited)
|
|
1227
|
+
AssertionError: Thread-0 failed: result does not match expected
|
|
1228
|
+
|
|
1229
|
+
When safe (after the pr this test is commited)
|
|
1230
|
+
Should pass without failure
|
|
1231
|
+
"""
|
|
1232
|
+
import threading
|
|
1233
|
+
import time
|
|
1234
|
+
|
|
1235
|
+
barrier = threading.Barrier(4)
|
|
1236
|
+
|
|
1237
|
+
# Function that each thread will run with different expressions
|
|
1238
|
+
def thread_function(a_value, b_value, expression, expected_result, results, index):
|
|
1239
|
+
validate(expression, local_dict={"a": a_value, "b": b_value})
|
|
1240
|
+
# Wait for all threads to reach this point
|
|
1241
|
+
# such that they all set _numexpr_last
|
|
1242
|
+
barrier.wait()
|
|
1243
|
+
|
|
1244
|
+
# Simulate some work or a context switch delay
|
|
1245
|
+
time.sleep(0.1)
|
|
1246
|
+
|
|
1247
|
+
result = re_evaluate(local_dict={"a": a_value, "b": b_value})
|
|
1248
|
+
results[index] = np.array_equal(result, expected_result)
|
|
1249
|
+
|
|
1250
|
+
def test_thread_safety_with_numexpr():
|
|
1251
|
+
num_threads = 4
|
|
1252
|
+
array_size = 1000000
|
|
1253
|
+
|
|
1254
|
+
expressions = [
|
|
1255
|
+
"a + b",
|
|
1256
|
+
"a - b",
|
|
1257
|
+
"a * b",
|
|
1258
|
+
"a / b"
|
|
1259
|
+
]
|
|
1260
|
+
|
|
1261
|
+
a_value = [np.full(array_size, i + 1) for i in range(num_threads)]
|
|
1262
|
+
b_value = [np.full(array_size, (i + 1) * 2) for i in range(num_threads)]
|
|
1263
|
+
|
|
1264
|
+
expected_results = [
|
|
1265
|
+
a_value[i] + b_value[i] if expr == "a + b" else
|
|
1266
|
+
a_value[i] - b_value[i] if expr == "a - b" else
|
|
1267
|
+
a_value[i] * b_value[i] if expr == "a * b" else
|
|
1268
|
+
a_value[i] / b_value[i] if expr == "a / b" else None
|
|
1269
|
+
for i, expr in enumerate(expressions)
|
|
1270
|
+
]
|
|
1271
|
+
|
|
1272
|
+
results = [None] * num_threads
|
|
1273
|
+
threads = []
|
|
1274
|
+
|
|
1275
|
+
# Create and start threads with different expressions
|
|
1276
|
+
for i in range(num_threads):
|
|
1277
|
+
thread = threading.Thread(
|
|
1278
|
+
target=thread_function,
|
|
1279
|
+
args=(a_value[i], b_value[i], expressions[i], expected_results[i], results, i)
|
|
1280
|
+
)
|
|
1281
|
+
threads.append(thread)
|
|
1282
|
+
thread.start()
|
|
1283
|
+
|
|
1284
|
+
for thread in threads:
|
|
1285
|
+
thread.join()
|
|
1286
|
+
|
|
1287
|
+
for i in range(num_threads):
|
|
1288
|
+
if not results[i]:
|
|
1289
|
+
self.fail(f"Thread-{i} failed: result does not match expected")
|
|
1290
|
+
|
|
1291
|
+
test_thread_safety_with_numexpr()
|
|
1292
|
+
|
|
1220
1293
|
|
|
1221
1294
|
# The worker function for the subprocess (needs to be here because Windows
|
|
1222
1295
|
# has problems pickling nested functions with the multiprocess module :-/)
|
|
@@ -1315,28 +1388,28 @@ def suite():
|
|
|
1315
1388
|
add_method(func)
|
|
1316
1389
|
|
|
1317
1390
|
for n in range(niter):
|
|
1318
|
-
theSuite.addTest(unittest.
|
|
1391
|
+
theSuite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(test_numexpr))
|
|
1319
1392
|
if 'sparc' not in platform.machine():
|
|
1320
|
-
theSuite.addTest(unittest.
|
|
1321
|
-
theSuite.addTest(unittest.
|
|
1322
|
-
theSuite.addTest(unittest.
|
|
1323
|
-
theSuite.addTest(unittest.
|
|
1324
|
-
theSuite.addTest(unittest.
|
|
1325
|
-
theSuite.addTest(unittest.
|
|
1393
|
+
theSuite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(test_numexpr2))
|
|
1394
|
+
theSuite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(test_evaluate))
|
|
1395
|
+
theSuite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(TestExpressions))
|
|
1396
|
+
theSuite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(test_int32_int64))
|
|
1397
|
+
theSuite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(test_uint32_int64))
|
|
1398
|
+
theSuite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(test_strings))
|
|
1326
1399
|
theSuite.addTest(
|
|
1327
|
-
unittest.
|
|
1328
|
-
theSuite.addTest(unittest.
|
|
1329
|
-
theSuite.addTest(unittest.
|
|
1400
|
+
unittest.defaultTestLoader.loadTestsFromTestCase(test_irregular_stride))
|
|
1401
|
+
theSuite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(test_zerodim))
|
|
1402
|
+
theSuite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(test_threading_config))
|
|
1330
1403
|
|
|
1331
1404
|
# multiprocessing module is not supported on Hurd/kFreeBSD
|
|
1332
1405
|
if (pl.system().lower() not in ('gnu', 'gnu/kfreebsd')):
|
|
1333
|
-
theSuite.addTest(unittest.
|
|
1406
|
+
theSuite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(test_subprocess))
|
|
1334
1407
|
|
|
1335
1408
|
# I need to put this test after test_subprocess because
|
|
1336
1409
|
# if not, the test suite locks immediately before test_subproces.
|
|
1337
1410
|
# This only happens with Windows, so I suspect of a subtle bad
|
|
1338
1411
|
# interaction with threads and subprocess :-/
|
|
1339
|
-
theSuite.addTest(unittest.
|
|
1412
|
+
theSuite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(test_threading))
|
|
1340
1413
|
|
|
1341
1414
|
return theSuite
|
|
1342
1415
|
|
|
@@ -13,6 +13,7 @@ log = logging.getLogger(__name__)
|
|
|
13
13
|
|
|
14
14
|
import os
|
|
15
15
|
import subprocess
|
|
16
|
+
import contextvars
|
|
16
17
|
|
|
17
18
|
from numexpr.interpreter import _set_num_threads, _get_num_threads, MAX_THREADS
|
|
18
19
|
from numexpr import use_vml
|
|
@@ -143,10 +144,10 @@ def _init_num_threads():
|
|
|
143
144
|
# configured NumExpr as desired, so we emit info logs.
|
|
144
145
|
if n_cores > MAX_THREADS:
|
|
145
146
|
log.info('Note: detected %d virtual cores but NumExpr set to maximum of %d, check "NUMEXPR_MAX_THREADS" environment variable.'%(n_cores, MAX_THREADS))
|
|
146
|
-
if n_cores >
|
|
147
|
-
#
|
|
148
|
-
log.info('Note: NumExpr detected %d cores but "NUMEXPR_MAX_THREADS" not set, so enforcing safe limit of
|
|
149
|
-
n_cores =
|
|
147
|
+
if n_cores > 16:
|
|
148
|
+
# Back in 2019, 8 threads would be considered safe for performance. We are in 2024 now, so adjusting.
|
|
149
|
+
log.info('Note: NumExpr detected %d cores but "NUMEXPR_MAX_THREADS" not set, so enforcing safe limit of 16.'%n_cores)
|
|
150
|
+
n_cores = 16
|
|
150
151
|
|
|
151
152
|
# Now we check for 'NUMEXPR_NUM_THREADS' or 'OMP_NUM_THREADS' to set the
|
|
152
153
|
# actual number of threads used.
|
|
@@ -226,3 +227,83 @@ class CacheDict(dict):
|
|
|
226
227
|
super(CacheDict, self).__delitem__(k)
|
|
227
228
|
super(CacheDict, self).__setitem__(key, value)
|
|
228
229
|
|
|
230
|
+
|
|
231
|
+
class ContextDict:
|
|
232
|
+
"""
|
|
233
|
+
A context aware version dictionary
|
|
234
|
+
"""
|
|
235
|
+
def __init__(self):
|
|
236
|
+
self._context_data = contextvars.ContextVar('context_data', default={})
|
|
237
|
+
|
|
238
|
+
def set(self, key=None, value=None, **kwargs):
|
|
239
|
+
data = self._context_data.get().copy()
|
|
240
|
+
|
|
241
|
+
if key is not None:
|
|
242
|
+
data[key] = value
|
|
243
|
+
|
|
244
|
+
for k, v in kwargs.items():
|
|
245
|
+
data[k] = v
|
|
246
|
+
|
|
247
|
+
self._context_data.set(data)
|
|
248
|
+
|
|
249
|
+
def get(self, key, default=None):
|
|
250
|
+
data = self._context_data.get()
|
|
251
|
+
return data.get(key, default)
|
|
252
|
+
|
|
253
|
+
def delete(self, key):
|
|
254
|
+
data = self._context_data.get().copy()
|
|
255
|
+
if key in data:
|
|
256
|
+
del data[key]
|
|
257
|
+
self._context_data.set(data)
|
|
258
|
+
|
|
259
|
+
def clear(self):
|
|
260
|
+
self._context_data.set({})
|
|
261
|
+
|
|
262
|
+
def all(self):
|
|
263
|
+
return self._context_data.get()
|
|
264
|
+
|
|
265
|
+
def update(self, *args, **kwargs):
|
|
266
|
+
data = self._context_data.get().copy()
|
|
267
|
+
|
|
268
|
+
if args:
|
|
269
|
+
if len(args) > 1:
|
|
270
|
+
raise TypeError(f"update() takes at most 1 positional argument ({len(args)} given)")
|
|
271
|
+
other = args[0]
|
|
272
|
+
if isinstance(other, dict):
|
|
273
|
+
data.update(other)
|
|
274
|
+
else:
|
|
275
|
+
for k, v in other:
|
|
276
|
+
data[k] = v
|
|
277
|
+
|
|
278
|
+
data.update(kwargs)
|
|
279
|
+
self._context_data.set(data)
|
|
280
|
+
|
|
281
|
+
def keys(self):
|
|
282
|
+
return self._context_data.get().keys()
|
|
283
|
+
|
|
284
|
+
def values(self):
|
|
285
|
+
return self._context_data.get().values()
|
|
286
|
+
|
|
287
|
+
def items(self):
|
|
288
|
+
return self._context_data.get().items()
|
|
289
|
+
|
|
290
|
+
def __getitem__(self, key):
|
|
291
|
+
return self.get(key)
|
|
292
|
+
|
|
293
|
+
def __setitem__(self, key, value):
|
|
294
|
+
self.set(key, value)
|
|
295
|
+
|
|
296
|
+
def __delitem__(self, key):
|
|
297
|
+
self.delete(key)
|
|
298
|
+
|
|
299
|
+
def __contains__(self, key):
|
|
300
|
+
return key in self._context_data.get()
|
|
301
|
+
|
|
302
|
+
def __len__(self):
|
|
303
|
+
return len(self._context_data.get())
|
|
304
|
+
|
|
305
|
+
def __iter__(self):
|
|
306
|
+
return iter(self._context_data.get())
|
|
307
|
+
|
|
308
|
+
def __repr__(self):
|
|
309
|
+
return repr(self._context_data.get())
|
|
@@ -1,29 +1,31 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: numexpr
|
|
3
|
-
Version: 2.10.
|
|
3
|
+
Version: 2.10.2
|
|
4
4
|
Summary: Fast numerical expression evaluator for NumPy
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
Author-email: "David M. Cooke, Francesc Alted, and others" <blosc@blosc.org>
|
|
6
|
+
Maintainer-email: Blosc Development Team <blosc@blosc.org>
|
|
7
|
+
Project-URL: homepage, https://github.com/pydata/numexpr
|
|
8
|
+
Project-URL: documentation, https://numexpr.readthedocs.io
|
|
9
|
+
Project-URL: repository, https://github.com/pydata/numexpr
|
|
10
10
|
Classifier: Development Status :: 6 - Mature
|
|
11
|
-
Classifier: Intended Audience ::
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Information Technology
|
|
12
13
|
Classifier: Intended Audience :: Science/Research
|
|
13
14
|
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
18
|
+
Classifier: Operating System :: Unix
|
|
14
19
|
Classifier: Programming Language :: Python :: 3
|
|
15
20
|
Classifier: Programming Language :: Python :: 3.9
|
|
16
21
|
Classifier: Programming Language :: Python :: 3.10
|
|
17
22
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
23
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
-
Classifier: Operating System :: Microsoft :: Windows
|
|
20
|
-
Classifier: Operating System :: POSIX
|
|
21
|
-
Classifier: Operating System :: MacOS
|
|
22
24
|
Requires-Python: >=3.9
|
|
23
25
|
Description-Content-Type: text/x-rst
|
|
24
26
|
License-File: LICENSE.txt
|
|
25
27
|
License-File: AUTHORS.txt
|
|
26
|
-
Requires-Dist: numpy>=1.
|
|
28
|
+
Requires-Dist: numpy>=1.23.0
|
|
27
29
|
|
|
28
30
|
======================================================
|
|
29
31
|
NumExpr: Fast numerical expression evaluator for NumPy
|
|
@@ -4,14 +4,15 @@ LICENSE.txt
|
|
|
4
4
|
MANIFEST.in
|
|
5
5
|
README.rst
|
|
6
6
|
RELEASE_NOTES.rst
|
|
7
|
+
VERSION
|
|
7
8
|
pyproject.toml
|
|
8
9
|
requirements.txt
|
|
9
|
-
setup.cfg
|
|
10
10
|
setup.py
|
|
11
11
|
site.cfg.example
|
|
12
12
|
bench/boolean_timing.py
|
|
13
13
|
bench/issue-36.py
|
|
14
14
|
bench/issue-47.py
|
|
15
|
+
bench/large_array_vs_numpy.py
|
|
15
16
|
bench/multidim.py
|
|
16
17
|
bench/poly.py
|
|
17
18
|
bench/timing.py
|
|
@@ -43,7 +44,6 @@ numexpr/version.py
|
|
|
43
44
|
numexpr.egg-info/PKG-INFO
|
|
44
45
|
numexpr.egg-info/SOURCES.txt
|
|
45
46
|
numexpr.egg-info/dependency_links.txt
|
|
46
|
-
numexpr.egg-info/not-zip-safe
|
|
47
47
|
numexpr.egg-info/requires.txt
|
|
48
48
|
numexpr.egg-info/top_level.txt
|
|
49
49
|
numexpr/win32/pthread.c
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
numpy>=1.23.0
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [
|
|
3
|
+
"setuptools",
|
|
4
|
+
"wheel",
|
|
5
|
+
"numpy>=2.0.0",
|
|
6
|
+
]
|
|
7
|
+
build-backend = "setuptools.build_meta"
|
|
8
|
+
|
|
9
|
+
[tool.setuptools.packages.find]
|
|
10
|
+
include = ["numexpr"]
|
|
11
|
+
|
|
12
|
+
[project]
|
|
13
|
+
name = "numexpr"
|
|
14
|
+
description = "Fast numerical expression evaluator for NumPy"
|
|
15
|
+
readme = "README.rst"
|
|
16
|
+
authors = [{name = "David M. Cooke, Francesc Alted, and others", email = "blosc@blosc.org"}]
|
|
17
|
+
maintainers = [{ name = "Blosc Development Team", email = "blosc@blosc.org"}]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Development Status :: 6 - Mature",
|
|
20
|
+
"Intended Audience :: Developers",
|
|
21
|
+
"Intended Audience :: Information Technology",
|
|
22
|
+
"Intended Audience :: Science/Research",
|
|
23
|
+
"License :: OSI Approved :: MIT License",
|
|
24
|
+
"Programming Language :: Python",
|
|
25
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
26
|
+
"Operating System :: Microsoft :: Windows",
|
|
27
|
+
"Operating System :: Unix",
|
|
28
|
+
"Programming Language :: Python :: 3",
|
|
29
|
+
"Programming Language :: Python :: 3.9",
|
|
30
|
+
"Programming Language :: Python :: 3.10",
|
|
31
|
+
"Programming Language :: Python :: 3.11",
|
|
32
|
+
"Programming Language :: Python :: 3.12",
|
|
33
|
+
]
|
|
34
|
+
requires-python = ">=3.9"
|
|
35
|
+
# Follow guidelines from https://scientific-python.org/specs/spec-0000/
|
|
36
|
+
dependencies = [
|
|
37
|
+
"numpy>=1.23.0",
|
|
38
|
+
]
|
|
39
|
+
dynamic = ["version"]
|
|
40
|
+
|
|
41
|
+
[project.urls]
|
|
42
|
+
homepage = "https://github.com/pydata/numexpr"
|
|
43
|
+
documentation = "https://numexpr.readthedocs.io"
|
|
44
|
+
repository = "https://github.com/pydata/numexpr"
|
|
45
|
+
|
|
46
|
+
[tool.cibuildwheel]
|
|
47
|
+
skip = "cp36-* cp37-* pp37-* cp38-* pp* *-manylinux_i686 *_ppc64le *_s390x"
|
|
48
|
+
# Let's use a more recent version of the manylinux image for more modern compilers
|
|
49
|
+
manylinux-x86_64-image = "manylinux_2_28"
|
|
50
|
+
manylinux-aarch64-image = "manylinux_2_28"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
numpy >= 1.23.0 # keep in sync with NPY_TARGET_VERSION (setup.py)
|
numexpr-2.10.2/setup.cfg
ADDED
|
@@ -10,32 +10,38 @@
|
|
|
10
10
|
####################################################################
|
|
11
11
|
|
|
12
12
|
import os, os.path as op
|
|
13
|
-
from setuptools import setup, Extension
|
|
14
13
|
import platform
|
|
15
14
|
import configparser
|
|
16
15
|
import numpy as np
|
|
16
|
+
from setuptools import setup, Extension
|
|
17
|
+
|
|
17
18
|
|
|
18
19
|
with open('requirements.txt') as f:
|
|
19
20
|
requirements = f.read().splitlines()
|
|
20
21
|
|
|
22
|
+
version = open("VERSION").read().strip()
|
|
21
23
|
with open('numexpr/version.py', 'w') as fh:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
fh.write(
|
|
25
|
-
fh.write("version = '
|
|
24
|
+
# Create the version.py file
|
|
25
|
+
fh.write("# THIS FILE IS GENERATED BY `setup.py`\n")
|
|
26
|
+
fh.write(f"__version__ = '{version}'\n")
|
|
27
|
+
fh.write(f"version = '{version}'\n")
|
|
26
28
|
try:
|
|
27
29
|
fh.write("numpy_build_version = '%s'\n" % np.__version__)
|
|
28
30
|
except ImportError:
|
|
29
31
|
pass
|
|
30
32
|
fh.write("platform_machine = '%s'\n" % platform.machine())
|
|
31
33
|
|
|
34
|
+
# Read the contents of your README file
|
|
35
|
+
with open('README.rst', encoding='utf-8') as f:
|
|
36
|
+
long_description = f.read()
|
|
37
|
+
|
|
32
38
|
lib_dirs = []
|
|
33
39
|
inc_dirs = [np.get_include()]
|
|
34
40
|
libs = [] # Pre-built libraries ONLY, like python36.so
|
|
35
41
|
clibs = []
|
|
36
42
|
def_macros = [
|
|
37
43
|
# keep in sync with minimal runtime requirement (requirements.txt)
|
|
38
|
-
('NPY_TARGET_VERSION', '
|
|
44
|
+
('NPY_TARGET_VERSION', 'NPY_1_23_API_VERSION')
|
|
39
45
|
]
|
|
40
46
|
sources = ['numexpr/interpreter.cpp',
|
|
41
47
|
'numexpr/module.cpp',
|
|
@@ -98,6 +104,9 @@ def setup_package():
|
|
|
98
104
|
)
|
|
99
105
|
|
|
100
106
|
metadata = dict(
|
|
107
|
+
version=version,
|
|
108
|
+
long_description=long_description,
|
|
109
|
+
long_description_content_type='text/x-rst',
|
|
101
110
|
install_requires=requirements,
|
|
102
111
|
libraries=clibs,
|
|
103
112
|
ext_modules=[
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
numpy>=1.19.3
|
numexpr-2.10.0/pyproject.toml
DELETED
numexpr-2.10.0/requirements.txt
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
numpy >= 1.19.3 # keep in sync with NPY_TARGET_VERSION (setup.py)
|
numexpr-2.10.0/setup.cfg
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
[metadata]
|
|
2
|
-
name = numexpr
|
|
3
|
-
version = 2.10.0
|
|
4
|
-
description = Fast numerical expression evaluator for NumPy
|
|
5
|
-
author = David M. Cooke, Francesc Alted, and others
|
|
6
|
-
maintainer = Francesc Alted
|
|
7
|
-
maintainer_email = faltet@gmail.com
|
|
8
|
-
url = https://github.com/pydata/numexpr
|
|
9
|
-
long_description = file: README.rst
|
|
10
|
-
long_description_content_type = text/x-rst
|
|
11
|
-
license = MIT
|
|
12
|
-
classifiers =
|
|
13
|
-
Development Status :: 6 - Mature
|
|
14
|
-
Intended Audience :: Financial and Insurance Industry
|
|
15
|
-
Intended Audience :: Science/Research
|
|
16
|
-
License :: OSI Approved :: MIT License
|
|
17
|
-
Programming Language :: Python :: 3
|
|
18
|
-
Programming Language :: Python :: 3.9
|
|
19
|
-
Programming Language :: Python :: 3.10
|
|
20
|
-
Programming Language :: Python :: 3.11
|
|
21
|
-
Programming Language :: Python :: 3.12
|
|
22
|
-
Operating System :: Microsoft :: Windows
|
|
23
|
-
Operating System :: POSIX
|
|
24
|
-
Operating System :: MacOS
|
|
25
|
-
|
|
26
|
-
[options]
|
|
27
|
-
zip_safe = False
|
|
28
|
-
packages = find:
|
|
29
|
-
python_requires = >=3.9
|
|
30
|
-
|
|
31
|
-
[egg_info]
|
|
32
|
-
tag_build =
|
|
33
|
-
tag_date = 0
|
|
34
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|