summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/TESTS.rst.txt2
-rw-r--r--doc/source/reference/random/index.rst3
-rw-r--r--doc/source/reference/random/new-or-different.rst12
-rw-r--r--numpy/compat/setup.py2
-rw-r--r--numpy/core/setup.py2
-rw-r--r--numpy/distutils/setup.py2
-rw-r--r--numpy/f2py/setup.py3
-rw-r--r--numpy/fft/setup.py2
-rw-r--r--numpy/lib/function_base.py22
-rw-r--r--numpy/lib/histograms.py10
-rw-r--r--numpy/lib/setup.py3
-rw-r--r--numpy/lib/tests/test_function_base.py69
-rw-r--r--numpy/linalg/setup.py2
-rw-r--r--numpy/ma/setup.py2
-rw-r--r--numpy/matrixlib/setup.py2
-rw-r--r--numpy/polynomial/setup.py2
-rw-r--r--numpy/random/setup.py3
-rw-r--r--numpy/setup.py2
-rwxr-xr-xnumpy/testing/setup.py2
-rwxr-xr-xruntests.py22
-rw-r--r--tools/openblas_support.py34
-rw-r--r--tools/refguide_check.py2
22 files changed, 160 insertions, 45 deletions
diff --git a/doc/TESTS.rst.txt b/doc/TESTS.rst.txt
index 007840b39..af47fe99c 100644
--- a/doc/TESTS.rst.txt
+++ b/doc/TESTS.rst.txt
@@ -256,7 +256,7 @@ section of your setup.py::
...
def configuration(parent_package='', top_path=None):
...
- config.add_data_dir('tests')
+ config.add_subpackage('tests')
return config
...
diff --git a/doc/source/reference/random/index.rst b/doc/source/reference/random/index.rst
index bda9c4d96..d559f2327 100644
--- a/doc/source/reference/random/index.rst
+++ b/doc/source/reference/random/index.rst
@@ -168,6 +168,9 @@ What's New or Different
Python's `random.random`.
* All BitGenerators in numpy use `SeedSequence` to convert seeds into
initialized states.
+* The addition of an ``axis`` keyword argument to methods such as
+ `Generator.choice`, `Generator.permutation`, and `Generator.shuffle`
+ improves support for sampling from and shuffling multi-dimensional arrays.
See :ref:`new-or-different` for a complete list of improvements and
differences from the traditional ``Randomstate``.
diff --git a/doc/source/reference/random/new-or-different.rst b/doc/source/reference/random/new-or-different.rst
index 1d6b09faf..03e7775a0 100644
--- a/doc/source/reference/random/new-or-different.rst
+++ b/doc/source/reference/random/new-or-different.rst
@@ -115,3 +115,15 @@ And in more detail:
rg.random(out=existing[:2])
print(existing)
+* Optional ``axis`` argument for methods like `~.Generator.choice`,
+ `~.Generator.permutation` and `~.Generator.shuffle` that controls which
+ axis an operation is performed over for multi-dimensional arrays.
+
+.. ipython:: python
+
+ rg = Generator(PCG64(123456789))
+ a = np.arange(12).reshape((3, 4))
+ a
+ rg.choice(a, axis=1, size=5)
+ rg.shuffle(a, axis=1) # Shuffle in-place
+ a
diff --git a/numpy/compat/setup.py b/numpy/compat/setup.py
index afa511673..c1b34a2cc 100644
--- a/numpy/compat/setup.py
+++ b/numpy/compat/setup.py
@@ -2,7 +2,7 @@ def configuration(parent_package='',top_path=None):
from numpy.distutils.misc_util import Configuration
config = Configuration('compat', parent_package, top_path)
- config.add_data_dir('tests')
+ config.add_subpackage('tests')
return config
if __name__ == '__main__':
diff --git a/numpy/core/setup.py b/numpy/core/setup.py
index 15e732614..76f3f5abe 100644
--- a/numpy/core/setup.py
+++ b/numpy/core/setup.py
@@ -961,7 +961,7 @@ def configuration(parent_package='',top_path=None):
config.add_extension('_operand_flag_tests',
sources=[join('src', 'umath', '_operand_flag_tests.c.src')])
- config.add_data_dir('tests')
+ config.add_subpackage('tests')
config.add_data_dir('tests/data')
config.make_svn_version_py()
diff --git a/numpy/distutils/setup.py b/numpy/distutils/setup.py
index 69d35f5c2..88cd1a160 100644
--- a/numpy/distutils/setup.py
+++ b/numpy/distutils/setup.py
@@ -4,7 +4,7 @@ def configuration(parent_package='',top_path=None):
config = Configuration('distutils', parent_package, top_path)
config.add_subpackage('command')
config.add_subpackage('fcompiler')
- config.add_data_dir('tests')
+ config.add_subpackage('tests')
config.add_data_files('site.cfg')
config.add_data_files('mingw/gfortran_vs2003_hack.c')
config.make_config_py()
diff --git a/numpy/f2py/setup.py b/numpy/f2py/setup.py
index 6314c5af3..80b47e527 100644
--- a/numpy/f2py/setup.py
+++ b/numpy/f2py/setup.py
@@ -25,7 +25,8 @@ from __version__ import version
def configuration(parent_package='', top_path=None):
config = Configuration('f2py', parent_package, top_path)
- config.add_data_dir('tests')
+ config.add_subpackage('tests')
+ config.add_data_dir('tests/src')
config.add_data_files(
'src/fortranobject.c',
'src/fortranobject.h')
diff --git a/numpy/fft/setup.py b/numpy/fft/setup.py
index e8204fcd3..9ed824e4f 100644
--- a/numpy/fft/setup.py
+++ b/numpy/fft/setup.py
@@ -4,7 +4,7 @@ def configuration(parent_package='',top_path=None):
from numpy.distutils.misc_util import Configuration
config = Configuration('fft', parent_package, top_path)
- config.add_data_dir('tests')
+ config.add_subpackage('tests')
# AIX needs to be told to use large file support - at all times
defs = [('_LARGE_FILES', None)] if sys.platform[:3] == "aix" else []
diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py
index 38acfd2d5..dea01d12d 100644
--- a/numpy/lib/function_base.py
+++ b/numpy/lib/function_base.py
@@ -2050,7 +2050,7 @@ class vectorize:
self.pyfunc = pyfunc
self.cache = cache
self.signature = signature
- self._ufunc = None # Caching to improve default performance
+ self._ufunc = {} # Caching to improve default performance
if doc is None:
self.__doc__ = pyfunc.__doc__
@@ -2115,14 +2115,22 @@ class vectorize:
if self.otypes is not None:
otypes = self.otypes
- nout = len(otypes)
- # Note logic here: We only *use* self._ufunc if func is self.pyfunc
- # even though we set self._ufunc regardless.
- if func is self.pyfunc and self._ufunc is not None:
- ufunc = self._ufunc
+ # self._ufunc is a dictionary whose keys are the number of
+ # arguments (i.e. len(args)) and whose values are ufuncs created
+ # by frompyfunc. len(args) can be different for different calls if
+ # self.pyfunc has parameters with default values. We only use the
+ # cache when func is self.pyfunc, which occurs when the call uses
+ # only positional arguments and no arguments are excluded.
+
+ nin = len(args)
+ nout = len(self.otypes)
+ if func is not self.pyfunc or nin not in self._ufunc:
+ ufunc = frompyfunc(func, nin, nout)
else:
- ufunc = self._ufunc = frompyfunc(func, len(args), nout)
+ ufunc = None # We'll get it from self._ufunc
+ if func is self.pyfunc:
+ ufunc = self._ufunc.setdefault(nin, ufunc)
else:
# Get number of outputs and output types by calling the function on
# the first entries of args. We also cache the result to prevent
diff --git a/numpy/lib/histograms.py b/numpy/lib/histograms.py
index f080cc392..1a9b41ced 100644
--- a/numpy/lib/histograms.py
+++ b/numpy/lib/histograms.py
@@ -1047,7 +1047,15 @@ def histogramdd(sample, bins=10, range=None, normed=None, weights=None,
raise ValueError(
'`bins[{}]` must be positive, when an integer'.format(i))
smin, smax = _get_outer_edges(sample[:,i], range[i])
- edges[i] = np.linspace(smin, smax, bins[i] + 1)
+ try:
+ n = operator.index(bins[i])
+
+ except TypeError as e:
+ raise TypeError(
+ "`bins[{}]` must be an integer, when a scalar".format(i)
+ ) from e
+
+ edges[i] = np.linspace(smin, smax, n + 1)
elif np.ndim(bins[i]) == 1:
edges[i] = np.asarray(bins[i])
if np.any(edges[i][:-1] > edges[i][1:]):
diff --git a/numpy/lib/setup.py b/numpy/lib/setup.py
index 5d0341d86..b3f441f38 100644
--- a/numpy/lib/setup.py
+++ b/numpy/lib/setup.py
@@ -2,7 +2,8 @@ def configuration(parent_package='',top_path=None):
from numpy.distutils.misc_util import Configuration
config = Configuration('lib', parent_package, top_path)
- config.add_data_dir('tests')
+ config.add_subpackage('tests')
+ config.add_data_dir('tests/data')
return config
if __name__ == '__main__':
diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py
index 23bf3296d..b4e928273 100644
--- a/numpy/lib/tests/test_function_base.py
+++ b/numpy/lib/tests/test_function_base.py
@@ -3,6 +3,7 @@ import warnings
import sys
import decimal
from fractions import Fraction
+import math
import pytest
import numpy as np
@@ -1221,6 +1222,16 @@ class TestExtins:
assert_array_equal(a, ac)
+# _foo1 and _foo2 are used in some tests in TestVectorize.
+
+def _foo1(x, y=1.0):
+ return y*math.floor(x)
+
+
+def _foo2(x, y=1.0, z=0.0):
+ return y*math.floor(x) + z
+
+
class TestVectorize:
def test_simple(self):
@@ -1252,7 +1263,6 @@ class TestVectorize:
assert_array_equal(y, x)
def test_ufunc(self):
- import math
f = vectorize(math.cos)
args = np.array([0, 0.5 * np.pi, np.pi, 1.5 * np.pi, 2 * np.pi])
r1 = f(args)
@@ -1273,6 +1283,63 @@ class TestVectorize:
r2 = np.array([3, 4, 5])
assert_array_equal(r1, r2)
+ def test_keywords_with_otypes_order1(self):
+ # gh-1620: The second call of f would crash with
+ # `ValueError: invalid number of arguments`.
+ f = vectorize(_foo1, otypes=[float])
+ # We're testing the caching of ufuncs by vectorize, so the order
+ # of these function calls is an important part of the test.
+ r1 = f(np.arange(3.0), 1.0)
+ r2 = f(np.arange(3.0))
+ assert_array_equal(r1, r2)
+
+ def test_keywords_with_otypes_order2(self):
+ # gh-1620: The second call of f would crash with
+ # `ValueError: non-broadcastable output operand with shape ()
+ # doesn't match the broadcast shape (3,)`.
+ f = vectorize(_foo1, otypes=[float])
+ # We're testing the caching of ufuncs by vectorize, so the order
+ # of these function calls is an important part of the test.
+ r1 = f(np.arange(3.0))
+ r2 = f(np.arange(3.0), 1.0)
+ assert_array_equal(r1, r2)
+
+ def test_keywords_with_otypes_order3(self):
+ # gh-1620: The third call of f would crash with
+ # `ValueError: invalid number of arguments`.
+ f = vectorize(_foo1, otypes=[float])
+ # We're testing the caching of ufuncs by vectorize, so the order
+ # of these function calls is an important part of the test.
+ r1 = f(np.arange(3.0))
+ r2 = f(np.arange(3.0), y=1.0)
+ r3 = f(np.arange(3.0))
+ assert_array_equal(r1, r2)
+ assert_array_equal(r1, r3)
+
+ def test_keywords_with_otypes_several_kwd_args1(self):
+ # gh-1620 Make sure different uses of keyword arguments
+ # don't break the vectorized function.
+ f = vectorize(_foo2, otypes=[float])
+ # We're testing the caching of ufuncs by vectorize, so the order
+ # of these function calls is an important part of the test.
+ r1 = f(10.4, z=100)
+ r2 = f(10.4, y=-1)
+ r3 = f(10.4)
+ assert_equal(r1, _foo2(10.4, z=100))
+ assert_equal(r2, _foo2(10.4, y=-1))
+ assert_equal(r3, _foo2(10.4))
+
+ def test_keywords_with_otypes_several_kwd_args2(self):
+ # gh-1620 Make sure different uses of keyword arguments
+ # don't break the vectorized function.
+ f = vectorize(_foo2, otypes=[float])
+ # We're testing the caching of ufuncs by vectorize, so the order
+ # of these function calls is an important part of the test.
+ r1 = f(z=100, x=10.4, y=-1)
+ r2 = f(1, 2, 3)
+ assert_equal(r1, _foo2(z=100, x=10.4, y=-1))
+ assert_equal(r2, _foo2(1, 2, 3))
+
def test_keywords_no_func_code(self):
# This needs to test a function that has keywords but
# no func_code attribute, since otherwise vectorize will
diff --git a/numpy/linalg/setup.py b/numpy/linalg/setup.py
index acfab0a68..57fdd502b 100644
--- a/numpy/linalg/setup.py
+++ b/numpy/linalg/setup.py
@@ -6,7 +6,7 @@ def configuration(parent_package='', top_path=None):
from numpy.distutils.system_info import get_info, system_info
config = Configuration('linalg', parent_package, top_path)
- config.add_data_dir('tests')
+ config.add_subpackage('tests')
# Configure lapack_lite
diff --git a/numpy/ma/setup.py b/numpy/ma/setup.py
index 144a961c2..d3f34c874 100644
--- a/numpy/ma/setup.py
+++ b/numpy/ma/setup.py
@@ -2,7 +2,7 @@
def configuration(parent_package='',top_path=None):
from numpy.distutils.misc_util import Configuration
config = Configuration('ma', parent_package, top_path)
- config.add_data_dir('tests')
+ config.add_subpackage('tests')
return config
if __name__ == "__main__":
diff --git a/numpy/matrixlib/setup.py b/numpy/matrixlib/setup.py
index 529d2a2eb..19b3bb2de 100644
--- a/numpy/matrixlib/setup.py
+++ b/numpy/matrixlib/setup.py
@@ -2,7 +2,7 @@
def configuration(parent_package='', top_path=None):
from numpy.distutils.misc_util import Configuration
config = Configuration('matrixlib', parent_package, top_path)
- config.add_data_dir('tests')
+ config.add_subpackage('tests')
return config
if __name__ == "__main__":
diff --git a/numpy/polynomial/setup.py b/numpy/polynomial/setup.py
index 8fc82cba1..641464518 100644
--- a/numpy/polynomial/setup.py
+++ b/numpy/polynomial/setup.py
@@ -1,7 +1,7 @@
def configuration(parent_package='',top_path=None):
from numpy.distutils.misc_util import Configuration
config = Configuration('polynomial', parent_package, top_path)
- config.add_data_dir('tests')
+ config.add_subpackage('tests')
return config
if __name__ == '__main__':
diff --git a/numpy/random/setup.py b/numpy/random/setup.py
index 90ec42671..88ddb1268 100644
--- a/numpy/random/setup.py
+++ b/numpy/random/setup.py
@@ -31,7 +31,8 @@ def configuration(parent_package='', top_path=None):
('_LARGEFILE64_SOURCE', '1')]
defs.append(('NPY_NO_DEPRECATED_API', 0))
- config.add_data_dir('tests')
+ config.add_subpackage('tests')
+ config.add_data_dir('tests/data')
config.add_data_dir('_examples')
EXTRA_LINK_ARGS = []
diff --git a/numpy/setup.py b/numpy/setup.py
index fb9b36b78..52db6a68b 100644
--- a/numpy/setup.py
+++ b/numpy/setup.py
@@ -18,7 +18,7 @@ def configuration(parent_package='',top_path=None):
config.add_subpackage('random')
config.add_subpackage('testing')
config.add_data_dir('doc')
- config.add_data_dir('tests')
+ config.add_subpackage('tests')
config.make_config_py() # installs __config__.py
return config
diff --git a/numpy/testing/setup.py b/numpy/testing/setup.py
index f4970991c..13191f13f 100755
--- a/numpy/testing/setup.py
+++ b/numpy/testing/setup.py
@@ -5,7 +5,7 @@ def configuration(parent_package='',top_path=None):
config = Configuration('testing', parent_package, top_path)
config.add_subpackage('_private')
- config.add_data_dir('tests')
+ config.add_subpackage('tests')
return config
if __name__ == '__main__':
diff --git a/runtests.py b/runtests.py
index e470f8a9d..7f1d55b85 100755
--- a/runtests.py
+++ b/runtests.py
@@ -125,7 +125,7 @@ def main(argv):
"COMMIT. Note that you need to commit your "
"changes first!"))
parser.add_argument("args", metavar="ARGS", default=[], nargs=REMAINDER,
- help="Arguments to pass to Nose, Python or shell")
+ help="Arguments to pass to Nose, asv, Python or shell")
args = parser.parse_args(argv)
if args.durations < 0:
@@ -162,8 +162,10 @@ def main(argv):
site_dir = os.path.sep.join(_temp.__file__.split(os.path.sep)[:-2])
extra_argv = args.args[:]
- if extra_argv and extra_argv[0] == '--':
- extra_argv = extra_argv[1:]
+ if not args.bench:
+ # extra_argv may also lists selected benchmarks
+ if extra_argv and extra_argv[0] == '--':
+ extra_argv = extra_argv[1:]
if args.python:
# Debugging issues with warnings is much easier if you can see them
@@ -220,13 +222,21 @@ def main(argv):
if args.bench:
# Run ASV
- items = extra_argv
+ for i, v in enumerate(extra_argv):
+ if v.startswith("--"):
+ items = extra_argv[:i]
+ if v == "--":
+ i += 1 # skip '--' indicating further are passed on.
+ bench_args = extra_argv[i:]
+ break
+ else:
+ items = extra_argv
+ bench_args = []
+
if args.tests:
items += args.tests
if args.submodule:
items += [args.submodule]
-
- bench_args = []
for a in items:
bench_args.extend(['--bench', a])
diff --git a/tools/openblas_support.py b/tools/openblas_support.py
index 105aae51f..a729662c5 100644
--- a/tools/openblas_support.py
+++ b/tools/openblas_support.py
@@ -14,7 +14,7 @@ OPENBLAS_V = '0.3.9'
OPENBLAS_LONG = 'v0.3.7-527-g79fd006c' # the 0.3.7 is misleading
BASE_LOC = 'https://anaconda.org/multibuild-wheels-staging/openblas-libs'
BASEURL = f'{BASE_LOC}/{OPENBLAS_LONG}/download'
-ARCHITECTURES = ['', 'windows', 'darwin', 'aarch64', 'x86', 'ppc64le', 's390x']
+ARCHITECTURES = ['', 'windows', 'darwin', 'aarch64', 'x86_64', 'i686', 'ppc64le', 's390x']
IS_32BIT = sys.maxsize < 2**32
def get_arch():
@@ -25,10 +25,10 @@ def get_arch():
else:
ret = platform.uname().machine
# What do 32 bit machines report?
- # If they are a docker, they report x86_64 or i686
- if 'x86' in ret or ret == 'i686':
- ret = 'x86'
- assert ret in ARCHITECTURES
+ # If they are a docker, they can report x86_64
+ if 'x86' in ret and IS_32BIT:
+ arch = 'i686'
+ assert ret in ARCHITECTURES, f'invalid architecture {ret}'
return ret
def get_ilp64():
@@ -38,15 +38,26 @@ def get_ilp64():
raise RuntimeError("NPY_USE_BLAS_ILP64 set on 32-bit arch")
return "64_"
+def get_manylinux(arch):
+ if arch in ('x86_64', 'i686'):
+ default = '2010'
+ else:
+ default = '2014'
+ ret = os.environ.get("MB_ML_VER", default)
+ # XXX For PEP 600 this can be a glibc version
+ assert ret in ('1', '2010', '2014'), f'invalid MB_ML_VER {ret}'
+ return ret
+
+
def download_openblas(target, arch, ilp64):
import urllib3
+ ml_ver = get_manylinux(arch)
fnsuffix = {None: "", "64_": "64_"}[ilp64]
filename = ''
- if arch in ('aarch64', 'ppc64le', 's390x'):
- suffix = f'manylinux2014_{arch}.tar.gz'
+ if arch in ('aarch64', 'ppc64le', 's390x', 'x86_64', 'i686'):
+ suffix = f'manylinux{ml_ver}_{arch}.tar.gz'
filename = f'{BASEURL}/openblas{fnsuffix}-{OPENBLAS_LONG}-{suffix}'
typ = 'tar.gz'
- typ = 'tar.gz'
elif arch == 'darwin':
suffix = 'macosx_10_9_x86_64-gf_1becaaa.tar.gz'
filename = f'{BASEURL}/openblas{fnsuffix}-{OPENBLAS_LONG}-{suffix}'
@@ -58,13 +69,6 @@ def download_openblas(target, arch, ilp64):
suffix = 'win_amd64-gcc_7_1_0.zip'
filename = f'{BASEURL}/openblas{fnsuffix}-{OPENBLAS_LONG}-{suffix}'
typ = 'zip'
- elif 'x86' in arch:
- if IS_32BIT:
- suffix = 'manylinux2010_i686.tar.gz'
- else:
- suffix = 'manylinux2010_x86_64.tar.gz'
- filename = f'{BASEURL}/openblas{fnsuffix}-{OPENBLAS_LONG}-{suffix}'
- typ = 'tar.gz'
if not filename:
return None
print("Downloading:", filename, file=sys.stderr)
diff --git a/tools/refguide_check.py b/tools/refguide_check.py
index e6cfc8b77..31d2997d3 100644
--- a/tools/refguide_check.py
+++ b/tools/refguide_check.py
@@ -450,7 +450,7 @@ def validate_rst_syntax(text, name, dots=True):
return False, "ERROR: %s: no documentation" % (name,)
ok_unknown_items = set([
- 'mod', 'currentmodule', 'autosummary', 'data', 'attr',
+ 'mod', 'doc', 'currentmodule', 'autosummary', 'data', 'attr',
'obj', 'versionadded', 'versionchanged', 'module', 'class',
'ref', 'func', 'toctree', 'moduleauthor', 'term', 'c:member',
'sectionauthor', 'codeauthor', 'eq', 'doi', 'DOI', 'arXiv', 'arxiv'