summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.circleci/config.yml49
-rw-r--r--.travis.yml23
-rw-r--r--doc/Makefile2
-rw-r--r--doc/changelog/1.14.2-changelog.rst22
-rw-r--r--doc/neps/.gitignore1
-rw-r--r--doc/neps/Makefile9
-rw-r--r--doc/neps/index.rst.tmpl (renamed from doc/neps/index.rst)31
-rw-r--r--doc/neps/nep-0000.rst15
-rw-r--r--doc/neps/nep-0001-npy-format.rst7
-rw-r--r--doc/neps/nep-0002-warnfix.rst39
-rw-r--r--doc/neps/nep-0003-math_config_clean.rst1
-rw-r--r--doc/neps/nep-0004-datetime-proposal3.rst2
-rw-r--r--doc/neps/nep-0005-generalized-ufuncs.rst2
-rw-r--r--doc/neps/nep-0006-newbugtracker.rst1
-rw-r--r--doc/neps/nep-0007-datetime-proposal.rst2
-rw-r--r--doc/neps/nep-0008-groupby_additions.rst18
-rw-r--r--doc/neps/nep-0009-structured_array_extensions.rst2
-rw-r--r--doc/neps/nep-0010-new-iterator-ufunc.rst1
-rw-r--r--doc/neps/nep-0011-deferred-ufunc-evaluation.rst1
-rw-r--r--doc/neps/nep-0012-missing-data.rst1
-rw-r--r--doc/neps/nep-0013-ufunc-overrides.rst8
-rw-r--r--doc/neps/nep-0014-dropping-python2.7-proposal.rst3
-rw-r--r--doc/neps/nep-template.rst2
-rw-r--r--doc/neps/tools/build_index.py99
-rw-r--r--doc/release/1.14.2-notes.rst40
-rw-r--r--doc/release/1.15.0-notes.rst31
-rw-r--r--doc/source/dev/development_environment.rst2
-rw-r--r--doc/source/release.rst1
-rw-r--r--doc/source/user/building.rst2
-rwxr-xr-xdoc/summarize.py9
-rw-r--r--numpy/__init__.py1
-rw-r--r--numpy/add_newdocs.py12
-rw-r--r--numpy/compat/setup.py4
-rw-r--r--numpy/conftest.py4
-rw-r--r--numpy/core/__init__.py1
-rw-r--r--numpy/core/code_generators/generate_umath.py4
-rw-r--r--numpy/core/code_generators/ufunc_docstrings.py278
-rw-r--r--numpy/core/fromnumeric.py16
-rw-r--r--numpy/core/include/numpy/npy_common.h16
-rw-r--r--numpy/core/include/numpy/npy_cpu.h3
-rw-r--r--numpy/core/include/numpy/npy_endian.h3
-rw-r--r--numpy/core/numeric.py13
-rw-r--r--numpy/core/setup.py21
-rw-r--r--numpy/core/setup_common.py1
-rw-r--r--numpy/core/src/multiarray/_multiarray_tests.c.src (renamed from numpy/core/src/multiarray/multiarray_tests.c.src)10
-rw-r--r--numpy/core/src/multiarray/arraytypes.c.src19
-rw-r--r--numpy/core/src/multiarray/buffer.c143
-rw-r--r--numpy/core/src/multiarray/buffer.h3
-rw-r--r--numpy/core/src/multiarray/common.c16
-rw-r--r--numpy/core/src/multiarray/compiled_base.c4
-rw-r--r--numpy/core/src/multiarray/conversion_utils.c16
-rw-r--r--numpy/core/src/multiarray/ctors.c62
-rw-r--r--numpy/core/src/multiarray/datetime_strings.c2
-rw-r--r--numpy/core/src/multiarray/einsum.c.src36
-rw-r--r--numpy/core/src/multiarray/flagsobject.c2
-rw-r--r--numpy/core/src/multiarray/getset.c50
-rw-r--r--numpy/core/src/multiarray/methods.c4
-rw-r--r--numpy/core/src/multiarray/scalartypes.c.src41
-rw-r--r--numpy/core/src/multiarray/shape.c2
-rw-r--r--numpy/core/src/npymath/npy_math_complex.c.src4
-rw-r--r--numpy/core/src/umath/_operand_flag_tests.c.src (renamed from numpy/core/src/umath/operand_flag_tests.c.src)10
-rw-r--r--numpy/core/src/umath/_rational_tests.c.src (renamed from numpy/core/src/umath/test_rational.c.src)10
-rw-r--r--numpy/core/src/umath/_struct_ufunc_tests.c.src (renamed from numpy/core/src/umath/struct_ufunc_test.c.src)8
-rw-r--r--numpy/core/src/umath/_umath_tests.c.src (renamed from numpy/core/src/umath/umath_tests.c.src)10
-rw-r--r--numpy/core/src/umath/cpuid.c56
-rw-r--r--numpy/core/src/umath/cpuid.h9
-rw-r--r--numpy/core/src/umath/scalarmath.c.src49
-rw-r--r--numpy/core/tests/_locales.py76
-rw-r--r--numpy/core/tests/test_arrayprint.py3
-rw-r--r--numpy/core/tests/test_datetime.py7
-rw-r--r--numpy/core/tests/test_deprecations.py6
-rw-r--r--numpy/core/tests/test_dtype.py2
-rw-r--r--numpy/core/tests/test_einsum.py15
-rw-r--r--numpy/core/tests/test_extint128.py2
-rw-r--r--numpy/core/tests/test_indexing.py20
-rw-r--r--numpy/core/tests/test_longdouble.py84
-rw-r--r--numpy/core/tests/test_mem_overlap.py6
-rw-r--r--numpy/core/tests/test_memmap.py2
-rw-r--r--numpy/core/tests/test_multiarray.py166
-rw-r--r--numpy/core/tests/test_nditer.py15
-rw-r--r--numpy/core/tests/test_numeric.py4
-rw-r--r--numpy/core/tests/test_print.py53
-rw-r--r--numpy/core/tests/test_records.py9
-rw-r--r--numpy/core/tests/test_regression.py8
-rw-r--r--numpy/core/tests/test_scalarbuffer.py84
-rw-r--r--numpy/core/tests/test_ufunc.py57
-rw-r--r--numpy/core/tests/test_umath.py6
-rw-r--r--numpy/core/tests/test_umath_complex.py8
-rw-r--r--numpy/distutils/__init__.py4
-rw-r--r--numpy/distutils/tests/test_system_info.py2
-rw-r--r--numpy/doc/subclassing.py2
-rw-r--r--numpy/f2py/__init__.py1
-rwxr-xr-xnumpy/f2py/crackfortran.py2
-rw-r--r--numpy/fft/__init__.py1
-rw-r--r--numpy/fft/fftpack.py4
-rw-r--r--numpy/fft/helper.py5
-rw-r--r--numpy/lib/__init__.py1
-rw-r--r--numpy/lib/arraypad.py6
-rw-r--r--numpy/lib/function_base.py83
-rw-r--r--numpy/lib/histograms.py184
-rw-r--r--numpy/lib/npyio.py2
-rw-r--r--numpy/lib/tests/test_function_base.py8
-rw-r--r--numpy/lib/tests/test_histograms.py16
-rw-r--r--numpy/lib/tests/test_io.py7
-rw-r--r--numpy/lib/tests/test_stride_tricks.py2
-rw-r--r--numpy/linalg/__init__.py1
-rw-r--r--numpy/ma/__init__.py1
-rw-r--r--numpy/ma/core.py26
-rw-r--r--numpy/ma/extras.py51
-rw-r--r--numpy/ma/tests/test_core.py6
-rw-r--r--numpy/ma/tests/test_extras.py42
-rw-r--r--numpy/ma/testutils.py3
-rw-r--r--numpy/matrixlib/__init__.py1
-rw-r--r--numpy/matrixlib/tests/test_defmatrix.py9
-rw-r--r--numpy/polynomial/__init__.py1
-rw-r--r--numpy/random/__init__.py1
-rw-r--r--numpy/testing/__init__.py11
-rw-r--r--numpy/testing/_private/__init__.py (renamed from numpy/testing/nose_tools/__init__.py)0
-rw-r--r--numpy/testing/_private/decorators.py (renamed from numpy/testing/nose_tools/decorators.py)19
-rw-r--r--numpy/testing/_private/noseclasses.py (renamed from numpy/testing/nose_tools/noseclasses.py)2
-rw-r--r--numpy/testing/_private/nosetester.py (renamed from numpy/testing/nose_tools/nosetester.py)0
-rw-r--r--numpy/testing/_private/parameterized.py (renamed from numpy/testing/nose_tools/parameterized.py)0
-rw-r--r--numpy/testing/_private/pytesttester.py175
-rw-r--r--numpy/testing/_private/utils.py (renamed from numpy/testing/nose_tools/utils.py)60
-rw-r--r--numpy/testing/decorators.py7
-rw-r--r--numpy/testing/noseclasses.py8
-rw-r--r--numpy/testing/nosetester.py6
-rw-r--r--numpy/testing/pytest_tools/decorators.py20
-rw-r--r--numpy/testing/pytest_tools/utils.py4
-rwxr-xr-xnumpy/testing/setup.py2
-rw-r--r--numpy/testing/tests/test_utils.py443
-rw-r--r--numpy/testing/utils.py7
-rw-r--r--pytest.ini18
-rwxr-xr-xsetup.py25
-rwxr-xr-xtools/ci/push_docs_to_repo.py65
135 files changed, 2302 insertions, 1044 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index e055739e5..86470e086 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -21,6 +21,8 @@ jobs:
python3 -m venv venv
. venv/bin/activate
pip install cython sphinx matplotlib
+ sudo apt-get update
+ sudo apt-get install -y graphviz
- run:
name: build numpy
@@ -54,8 +56,51 @@ jobs:
# path: doc/neps/_build/html/
# destination: neps
- - deploy:
+ - add_ssh_keys:
+ fingerprints:
+ - "9f:8c:e5:3f:53:40:0b:ee:c9:c3:0f:fd:0f:3c:cc:55"
+
+ - run:
+ name: deploy devdocs
command: |
if [ "${CIRCLE_BRANCH}" == "master" ]; then
- echo "Deploying on master"
+ touch doc/build/html/.nojekyll
+
+ ./tools/ci/push_docs_to_repo.py doc/build/html \
+ git@github.com:numpy/devdocs.git \
+ --committer "numpy-circleci-bot" \
+ --email "numpy-circleci-bot@nomail" \
+ --message "Docs build of $CIRCLE_SHA1" \
+ --force
+ else
+ echo "Not on the master branch; skipping deployment"
+ fi
+
+ - add_ssh_keys:
+ fingerprints:
+ - "11:fb:19:69:80:3a:6d:37:9c:d1:ac:20:17:cd:c8:17"
+
+ - run:
+ name: select SSH key for neps repo
+ command: |
+ cat <<\EOF > ~/.ssh/config
+ Host github.com
+ IdentitiesOnly yes
+ IdentityFile /home/circleci/.ssh/id_rsa_11fb1969803a6d379cd1ac2017cdc817
+ EOF
+
+ - run:
+ name: deploy neps
+ command: |
+ if [ "${CIRCLE_BRANCH}" == "master" ]; then
+ touch doc/neps/_build/html/.nojekyll
+
+ ./tools/ci/push_docs_to_repo.py doc/neps/_build/html \
+ git@github.com:numpy/neps.git \
+ --committer "numpy-circleci-bot" \
+ --email "numpy-circleci-bot@nomail" \
+ --message "Docs build of $CIRCLE_SHA1" \
+ --force
+ else
+ echo "Not on the master branch; skipping deployment"
fi
diff --git a/.travis.yml b/.travis.yml
index fca0c632d..168a7a385 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -35,19 +35,18 @@ python:
- 3.4
- 3.5
- 3.6
+ - 3.7-dev
matrix:
include:
- - python: 2.7
- env: USE_CHROOT=1 ARCH=i386 DIST=artful PYTHON=2.7
+ - python: 3.6
+ env: USE_CHROOT=1 ARCH=i386 DIST=artful PYTHON=3.6
sudo: true
- dist: trusty
addons:
apt:
packages:
- debootstrap
- python: 3.4
env: USE_DEBUG=1
- dist: trusty
addons:
apt:
packages:
@@ -57,19 +56,21 @@ matrix:
- python3-dev
- python3-nose
- python3-setuptools
- - python: 3.5
+ - python: 3.6
env: USE_WHEEL=1 RUN_FULL_TESTS=1
- - python: 3.5
- env: USE_SDIST=1
- python: 2.7
+ env: USE_WHEEL=1 RUN_FULL_TESTS=1 PYTHON_OPTS="-3 -OO"
+ - python: 3.6
+ env: USE_SDIST=1
+ - python: 3.6
env:
- PYTHONOPTIMIZE=2
- USE_ASV=1
- - python: 2.7
- env: NPY_RELAXED_STRIDES_CHECKING=0 PYTHON_OPTS="-3 -OO"
- - python: 2.7
+ - python: 3.5
+ env: NPY_RELAXED_STRIDES_CHECKING=0
+ - python: 3.6
env: USE_WHEEL=1 NPY_RELAXED_STRIDES_DEBUG=1
- - python: 2.7
+ - python: 3.6
env:
- BLAS=None
- LAPACK=None
diff --git a/doc/Makefile b/doc/Makefile
index d414d26d7..667dbef29 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -1,7 +1,7 @@
# Makefile for Sphinx documentation
#
-PYVER = 2.7
+PYVER = 3.6
PYTHON = python$(PYVER)
# You can set these variables from the command line.
diff --git a/doc/changelog/1.14.2-changelog.rst b/doc/changelog/1.14.2-changelog.rst
new file mode 100644
index 000000000..fae815c8e
--- /dev/null
+++ b/doc/changelog/1.14.2-changelog.rst
@@ -0,0 +1,22 @@
+
+Contributors
+============
+
+A total of 4 people contributed to this release. People with a "+" by their
+names contributed a patch for the first time.
+
+* Allan Haldane
+* Charles Harris
+* Eric Wieser
+* Pauli Virtanen
+
+Pull requests merged
+====================
+
+A total of 5 pull requests were merged for this release.
+
+* `#10674 <https://github.com/numpy/numpy/pull/10674>`__: BUG: Further back-compat fix for subclassed array repr
+* `#10725 <https://github.com/numpy/numpy/pull/10725>`__: BUG: dragon4 fractional output mode adds too many trailing zeros
+* `#10726 <https://github.com/numpy/numpy/pull/10726>`__: BUG: Fix f2py generated code to work on PyPy
+* `#10727 <https://github.com/numpy/numpy/pull/10727>`__: BUG: Fix missing NPY_VISIBILITY_HIDDEN on npy_longdouble_to_PyLong
+* `#10729 <https://github.com/numpy/numpy/pull/10729>`__: DOC: Create 1.14.2 notes and changelog.
diff --git a/doc/neps/.gitignore b/doc/neps/.gitignore
new file mode 100644
index 000000000..04163f707
--- /dev/null
+++ b/doc/neps/.gitignore
@@ -0,0 +1 @@
+index.rst
diff --git a/doc/neps/Makefile b/doc/neps/Makefile
index 2d1a063de..3c023ae9b 100644
--- a/doc/neps/Makefile
+++ b/doc/neps/Makefile
@@ -2,7 +2,7 @@
#
# You can set these variables from the command line.
-SPHINXOPTS =
+SPHINXOPTS = -W
SPHINXBUILD = sphinx-build
SPHINXPROJ = NumPyEnhancementProposals
SOURCEDIR = .
@@ -12,9 +12,12 @@ BUILDDIR = _build
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
-.PHONY: help Makefile
+.PHONY: help Makefile index
+
+index:
+ python tools/build_index.py
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
-%: Makefile
+%: Makefile index
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/doc/neps/index.rst b/doc/neps/index.rst.tmpl
index 8a2df4078..8d0c5da77 100644
--- a/doc/neps/index.rst
+++ b/doc/neps/index.rst.tmpl
@@ -14,9 +14,11 @@ Meta-NEPs (NEPs about NEPs or Processes)
.. toctree::
:maxdepth: 1
- nep-0000
- nep-template
+{% for nep, tags in neps.items() if tags['Type'] == 'Process' %}
+ NEP {{ nep }} — {{ tags['Title'] }} <{{ tags['Filename'] }}>
+{% endfor %}
+ nep-template
Accepted NEPs, implementation in progress
-----------------------------------------
@@ -24,8 +26,9 @@ Accepted NEPs, implementation in progress
.. toctree::
:maxdepth: 1
- nep-0014-dropping-python2.7-proposal
-
+{% for nep, tags in neps.items() if tags['Status'] == 'Accepted' %}
+ NEP {{ nep }} — {{ tags['Title'] }} <{{ tags['Filename'] }}>
+{% endfor %}
Implemented NEPs
----------------
@@ -33,12 +36,9 @@ Implemented NEPs
.. toctree::
:maxdepth: 1
- nep-0001-npy-format
- nep-0005-generalized-ufuncs
- nep-0007-datetime-proposal
- nep-0010-new-iterator-ufunc
- nep-0013-ufunc-overrides
-
+{% for nep, tags in neps.items() if tags['Status'] == 'Final' %}
+ NEP {{ nep }} — {{ tags['Title'] }} <{{ tags['Filename'] }}>
+{% endfor %}
Defunct NEPs
------------
@@ -46,11 +46,6 @@ Defunct NEPs
.. toctree::
:maxdepth: 1
- nep-0002-warnfix
- nep-0003-math_config_clean
- nep-0004-datetime-proposal3
- nep-0006-newbugtracker
- nep-0008-groupby_additions
- nep-0009-structured_array_extensions
- nep-0011-deferred-ufunc-evaluation
- nep-0012-missing-data
+{% for nep, tags in neps.items() if tags['Status'] == 'Deferred' %}
+ NEP {{ nep }} — {{ tags['Title'] }} <{{ tags['Filename'] }}>
+{% endfor %}
diff --git a/doc/neps/nep-0000.rst b/doc/neps/nep-0000.rst
index ae8603c62..a7d6d7115 100644
--- a/doc/neps/nep-0000.rst
+++ b/doc/neps/nep-0000.rst
@@ -1,6 +1,6 @@
-=======================
-NEP Purpose and Process
-=======================
+===================
+Purpose and Process
+===================
:Author: Jarrod Millman <millman@berkeley.edu>
:Status: Draft
@@ -121,9 +121,12 @@ updated accordingly. In addition to updating the status field, at the very
least the ``Resolution`` header should be added with a link to the relevant
post in the mailing list archives.
-NEPs can also be ``Replaced`` by a different NEP, rendering the original
-obsolete. Process NEPs may also have a status of
-``Active`` if they are never meant to be completed. E.g. NEP 0 (this NEP).
+NEPs can also be ``Superseded`` by a different NEP, rendering the
+original obsolete. The ``Replaced-By`` and ``Replaces`` headers
+should be added to the original and new NEPs respectively.
+
+Process NEPs may also have a status of ``Active`` if they are never
+meant to be completed, e.g. NEP 0 (this NEP).
Maintenance
diff --git a/doc/neps/nep-0001-npy-format.rst b/doc/neps/nep-0001-npy-format.rst
index 3f12e1bf1..2057aed83 100644
--- a/doc/neps/nep-0001-npy-format.rst
+++ b/doc/neps/nep-0001-npy-format.rst
@@ -2,10 +2,9 @@
A Simple File Format for NumPy Arrays
=====================================
-Author: Robert Kern <robert.kern@gmail.com>
-Status: Draft
-Created: 20-Dec-2007
-
+:Author: Robert Kern <robert.kern@gmail.com>
+:Status: Final
+:Created: 20-Dec-2007
Abstract
--------
diff --git a/doc/neps/nep-0002-warnfix.rst b/doc/neps/nep-0002-warnfix.rst
index 4b0a2a56e..60dc885b2 100644
--- a/doc/neps/nep-0002-warnfix.rst
+++ b/doc/neps/nep-0002-warnfix.rst
@@ -5,6 +5,7 @@ A proposal to build numpy without warning with a big set of warning flags
:Author: David Cournapeau
:Contact: david@ar.media.kyoto-u.ac.jp
:Date: 2008-09-04
+:Status: Deferred
Executive summary
=================
@@ -20,13 +21,13 @@ Warning flags
=============
Each compiler detects a different set of potential errors. The baseline will
-be gcc -Wall -W -Wextra. Ideally, a complete set would be nice:
+be gcc -Wall -W -Wextra. Ideally, a complete set would be nice::
--W -Wall -Wextra -Wstrict-prototypes -Wmissing-prototypes -Waggregate-return
--Wcast-align -Wcast-qual -Wnested-externs -Wshadow -Wbad-function-cast
--Wwrite-strings "
+ -W -Wall -Wextra -Wstrict-prototypes -Wmissing-prototypes -Waggregate-return
+ -Wcast-align -Wcast-qual -Wnested-externs -Wshadow -Wbad-function-cast
+ -Wwrite-strings "
-Intel compiler, VS with /W3 /Wall, Sun compilers have extra warnings too.
+Intel compiler, VS with ``/W3 /Wall``, Sun compilers have extra warnings too.
Kind of warnings
================
@@ -46,27 +47,29 @@ solve it is to tag the function argument with a macro NPY_UNUSED. This macro
uses compiler specific code to tag the variable, and mangle it such as it is
not possible to use it accidentally once it is tagged.
-The code to apply compiler specific option could be:
+The code to apply compiler specific option could be::
-#if defined(__GNUC__)
- #define __COMP_NPY_UNUSED __attribute__ ((__unused__))
-# elif defined(__ICC)
- #define __COMP_NPY_UNUSED __attribute__ ((__unused__))
-#else
- #define __COMP_NPY_UNUSED
-#endif
+ #if defined(__GNUC__)
+ #define __COMP_NPY_UNUSED __attribute__ ((__unused__))
+ # elif defined(__ICC)
+ #define __COMP_NPY_UNUSED __attribute__ ((__unused__))
+ #else
+ #define __COMP_NPY_UNUSED
+ #endif
-The variable mangling would be:
+The variable mangling would be::
-#define NPY_UNUSED(x) (__NPY_UNUSED_TAGGED ## x) __COMP_NPY_UNUSED
+ #define NPY_UNUSED(x) (__NPY_UNUSED_TAGGED ## x) __COMP_NPY_UNUSED
-When applied to a variable, one would get:
+When applied to a variable, one would get::
-int foo(int * NPY_UNUSED(dummy))
+ int foo(int * NPY_UNUSED(dummy))
expanded to
-int foo(int * __NPY_UNUSED_TAGGEDdummy __COMP_NPY_UNUSED)
+::
+
+ int foo(int * __NPY_UNUSED_TAGGEDdummy __COMP_NPY_UNUSED)
Thus avoiding any accidental use of the variable. The mangling is pure C, and
thuse portable. The per-variable warning disabling is compiler specific.
diff --git a/doc/neps/nep-0003-math_config_clean.rst b/doc/neps/nep-0003-math_config_clean.rst
index 27c0adfa1..5af907437 100644
--- a/doc/neps/nep-0003-math_config_clean.rst
+++ b/doc/neps/nep-0003-math_config_clean.rst
@@ -5,6 +5,7 @@ Cleaning the math configuration of numpy.core
:Author: David Cournapeau
:Contact: david@ar.media.kyoto-u.ac.jp
:Date: 2008-09-04
+:Status: Deferred
Executive summary
=================
diff --git a/doc/neps/nep-0004-datetime-proposal3.rst b/doc/neps/nep-0004-datetime-proposal3.rst
index fcfb39e54..46d8e314b 100644
--- a/doc/neps/nep-0004-datetime-proposal3.rst
+++ b/doc/neps/nep-0004-datetime-proposal3.rst
@@ -7,7 +7,7 @@
:Author: Ivan Vilata i Balaguer
:Contact: ivan@selidor.net
:Date: 2008-07-30
-
+:Status: Deferred
Executive summary
=================
diff --git a/doc/neps/nep-0005-generalized-ufuncs.rst b/doc/neps/nep-0005-generalized-ufuncs.rst
index 98e436990..54b2b370e 100644
--- a/doc/neps/nep-0005-generalized-ufuncs.rst
+++ b/doc/neps/nep-0005-generalized-ufuncs.rst
@@ -2,6 +2,8 @@
Generalized Universal Functions
===============================
+:Status: Final
+
There is a general need for looping over not only functions on scalars
but also over functions on vectors (or arrays), as explained on
http://scipy.org/scipy/numpy/wiki/GeneralLoopingFunctions. We propose
diff --git a/doc/neps/nep-0006-newbugtracker.rst b/doc/neps/nep-0006-newbugtracker.rst
index 5af633552..2b9344ed0 100644
--- a/doc/neps/nep-0006-newbugtracker.rst
+++ b/doc/neps/nep-0006-newbugtracker.rst
@@ -3,6 +3,7 @@ Replacing Trac with a different bug tracker
===========================================
:Author: David Cournapeau, Stefan van der Walt
+:Status: Deferred
Some release managers of both numpy and scipy are becoming more and more
dissatisfied with the current development workflow, in particular for bug
diff --git a/doc/neps/nep-0007-datetime-proposal.rst b/doc/neps/nep-0007-datetime-proposal.rst
index 76c361f4f..72d48d244 100644
--- a/doc/neps/nep-0007-datetime-proposal.rst
+++ b/doc/neps/nep-0007-datetime-proposal.rst
@@ -5,6 +5,7 @@
:Author: Travis Oliphant
:Contact: oliphant@enthought.com
:Date: 2009-06-09
+:Status: Final
Revised only slightly from the third proposal by
@@ -14,7 +15,6 @@ Revised only slightly from the third proposal by
:Contact: ivan@selidor.net
:Date: 2008-07-30
-
Executive summary
=================
diff --git a/doc/neps/nep-0008-groupby_additions.rst b/doc/neps/nep-0008-groupby_additions.rst
index a86bdd642..fa02f2f9c 100644
--- a/doc/neps/nep-0008-groupby_additions.rst
+++ b/doc/neps/nep-0008-groupby_additions.rst
@@ -5,6 +5,7 @@
:Author: Travis Oliphant
:Contact: oliphant@enthought.com
:Date: 2010-04-27
+:Status: Deferred
Executive summary
@@ -22,9 +23,9 @@ Example Use Case
================
Suppose you have a NumPy structured array containing information about
the number of purchases at several stores over multiple days. To be clear, the
-structured array data-type is:
+structured array data-type is::
-dt = [('year', i2), ('month', i1), ('day', i1), ('time', float),
+ dt = [('year', i2), ('month', i1), ('day', i1), ('time', float),
('store', i4), ('SKU', 'S6'), ('number', i4)]
Suppose there is a 1-d NumPy array of this data-type and you would like
@@ -98,14 +99,5 @@ reduceby::
Functions proposed
==================
-segment::
-
-
-edges::
-
-
-.. Local Variables:
-.. mode: rst
-.. coding: utf-8
-.. fill-column: 72
-.. End:
+- segment
+- edges
diff --git a/doc/neps/nep-0009-structured_array_extensions.rst b/doc/neps/nep-0009-structured_array_extensions.rst
index a4248362c..695d0d516 100644
--- a/doc/neps/nep-0009-structured_array_extensions.rst
+++ b/doc/neps/nep-0009-structured_array_extensions.rst
@@ -2,6 +2,8 @@
Structured array extensions
===========================
+:Status: Deferred
+
1. Create with-style context that makes "named-columns" available as names in the namespace.
with np.columns(array):
diff --git a/doc/neps/nep-0010-new-iterator-ufunc.rst b/doc/neps/nep-0010-new-iterator-ufunc.rst
index 7a9e7627c..7b388a974 100644
--- a/doc/neps/nep-0010-new-iterator-ufunc.rst
+++ b/doc/neps/nep-0010-new-iterator-ufunc.rst
@@ -5,6 +5,7 @@ Optimizing Iterator/UFunc Performance
:Author: Mark Wiebe <mwwiebe@gmail.com>
:Content-Type: text/x-rst
:Created: 25-Nov-2010
+:Status: Final
*****************
Table of Contents
diff --git a/doc/neps/nep-0011-deferred-ufunc-evaluation.rst b/doc/neps/nep-0011-deferred-ufunc-evaluation.rst
index b00c0dd2d..5f5de3518 100644
--- a/doc/neps/nep-0011-deferred-ufunc-evaluation.rst
+++ b/doc/neps/nep-0011-deferred-ufunc-evaluation.rst
@@ -5,6 +5,7 @@ Deferred UFunc Evaluation
:Author: Mark Wiebe <mwwiebe@gmail.com>
:Content-Type: text/x-rst
:Created: 30-Nov-2010
+:Status: Deferred
********
Abstract
diff --git a/doc/neps/nep-0012-missing-data.rst b/doc/neps/nep-0012-missing-data.rst
index 00a6034f4..1553339f4 100644
--- a/doc/neps/nep-0012-missing-data.rst
+++ b/doc/neps/nep-0012-missing-data.rst
@@ -6,6 +6,7 @@ Missing Data Functionality in NumPy
:Copyright: Copyright 2011 by Enthought, Inc
:License: CC By-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0/)
:Date: 2011-06-23
+:Status: Deferred
*****************
Table of Contents
diff --git a/doc/neps/nep-0013-ufunc-overrides.rst b/doc/neps/nep-0013-ufunc-overrides.rst
index 90869e1ac..c97b69023 100644
--- a/doc/neps/nep-0013-ufunc-overrides.rst
+++ b/doc/neps/nep-0013-ufunc-overrides.rst
@@ -1,5 +1,3 @@
-.. _neps.ufunc-overrides:
-
=================================
A Mechanism for Overriding Ufuncs
=================================
@@ -19,6 +17,8 @@ A Mechanism for Overriding Ufuncs
:Author: Stephan Hoyer
:Date: 2017-03-31
+:Status: Final
+
Executive summary
=================
@@ -154,8 +154,8 @@ Here:
- *ufunc* is the ufunc object that was called.
- *method* is a string indicating how the Ufunc was called, either
``"__call__"`` to indicate it was called directly, or one of its
- :ref:`methods<ufuncs.methods>`: ``"reduce"``, ``"accumulate"``,
- ``"reduceat"``, ``"outer"``, or ``"at"``.
+ methods: ``"reduce"``, ``"accumulate"``, ``"reduceat"``, ``"outer"``,
+ or ``"at"``.
- *inputs* is a tuple of the input arguments to the ``ufunc``
- *kwargs* contains any optional or keyword arguments passed to the
function. This includes any ``out`` arguments, which are always
diff --git a/doc/neps/nep-0014-dropping-python2.7-proposal.rst b/doc/neps/nep-0014-dropping-python2.7-proposal.rst
index 3cfe50bd0..6cfd4707f 100644
--- a/doc/neps/nep-0014-dropping-python2.7-proposal.rst
+++ b/doc/neps/nep-0014-dropping-python2.7-proposal.rst
@@ -2,6 +2,9 @@
Plan for dropping Python 2.7 support
====================================
+:Status: Accepted
+:Resolution: https://mail.python.org/pipermail/numpy-discussion/2017-November/077419.html
+
The Python core team plans to stop supporting Python 2 in 2020. The NumPy
project has supported both Python 2 and Python 3 in parallel since 2010, and
has found that supporting Python 2 is an increasing burden on our limited
diff --git a/doc/neps/nep-template.rst b/doc/neps/nep-template.rst
index d51ad3688..56b06049e 100644
--- a/doc/neps/nep-template.rst
+++ b/doc/neps/nep-template.rst
@@ -4,7 +4,7 @@ NEP Template and Instructions
:Author: <list of authors' real names and optionally, email addresses>
:Status: <Draft | Active | Accepted | Deferred | Rejected | Withdrawn | Final | Superseded>
-:Type: <Standards Track | Informational | Process>
+:Type: <Standards Track | Process>
:Created: <date created on, in yyyy-mm-dd format>
diff --git a/doc/neps/tools/build_index.py b/doc/neps/tools/build_index.py
new file mode 100644
index 000000000..65225c995
--- /dev/null
+++ b/doc/neps/tools/build_index.py
@@ -0,0 +1,99 @@
+"""
+Scan the directory of nep files and extract their metadata. The
+metadata is passed to Jinja for filling out `index.rst.tmpl`.
+"""
+
+import os
+import sys
+import jinja2
+import glob
+import re
+
+
+def render(tpl_path, context):
+ path, filename = os.path.split(tpl_path)
+ return jinja2.Environment(
+ loader=jinja2.FileSystemLoader(path or './')
+ ).get_template(filename).render(context)
+
+def nep_metadata():
+ ignore = ('nep-template.rst')
+ sources = sorted(glob.glob(r'nep-*.rst'))
+ sources = [s for s in sources if not s in ignore]
+
+ meta_re = r':([a-zA-Z\-]*): (.*)'
+
+ neps = {}
+ print('Loading metadata for:')
+ for source in sources:
+ print(f' - {source}')
+ nr = int(re.match(r'nep-([0-9]{4}).*\.rst', source).group(1))
+
+ with open(source) as f:
+ lines = f.readlines()
+ tags = [re.match(meta_re, line) for line in lines]
+ tags = [match.groups() for match in tags if match is not None]
+ tags = {tag[0]: tag[1] for tag in tags}
+
+ # We could do a clever regexp, but for now just assume the title is
+ # the second line of the document
+ tags['Title'] = lines[1].strip()
+ tags['Filename'] = source
+
+
+ if tags['Status'] in ('Accepted', 'Rejected', 'Withdrawn'):
+ if not 'Resolution' in tags:
+ raise RuntimeError(
+ f'NEP {nr} is Accepted/Rejected/Withdrawn but '
+ 'has no Resolution tag'
+ )
+
+ neps[nr] = tags
+
+ # Now that we have all of the NEP metadata, do some global consistency
+ # checks
+
+ for nr, tags in neps.items():
+ if tags['Status'] == 'Superseded':
+ if not 'Replaced-By' in tags:
+ raise RuntimeError(
+ f'NEP {nr} has been Superseded, but has no Replaced-By tag'
+ )
+
+ replaced_by = int(tags['Replaced-By'])
+ replacement_nep = neps[replaced_by]
+
+ if not 'Replaces' in replacement_nep:
+ raise RuntimeError(
+ f'NEP {nr} is superseded by {replaced_by}, but that NEP has '
+ f"no Replaces tag."
+ )
+
+ if not int(replacement_nep['Replaces']) == nr:
+ raise RuntimeError(
+ f'NEP {nr} is superseded by {replaced_by}, but that NEP has a '
+ f"Replaces tag of `{replacement_nep['Replaces']}`."
+ )
+
+ if 'Replaces' in tags:
+ replaced_nep = int(tags['Replaces'])
+ replaced_nep_tags = neps[replaced_nep]
+ if not replaced_nep_tags['Status'] == 'Superseded':
+ raise RuntimeError(
+ f'NEP {nr} replaces {replaced_nep}, but that NEP has not '
+ f'been set to Superseded'
+ )
+
+ return {'neps': neps}
+
+
+infile = 'index.rst.tmpl'
+outfile = 'index.rst'
+
+meta = nep_metadata()
+
+print(f'Compiling {infile} -> {outfile}')
+index = render(infile, meta)
+
+with open(outfile, 'w') as f:
+ f.write(index)
diff --git a/doc/release/1.14.2-notes.rst b/doc/release/1.14.2-notes.rst
new file mode 100644
index 000000000..3f47cb5f5
--- /dev/null
+++ b/doc/release/1.14.2-notes.rst
@@ -0,0 +1,40 @@
+==========================
+NumPy 1.14.2 Release Notes
+==========================
+
+This is a bugfix release for some bugs reported following the 1.14.1 release. The major
+problems dealt with are as follows.
+
+* Residual bugs in the new array printing functionality.
+* Regression resulting in a relocation problem with shared library.
+* Improved PyPy compatibility.
+
+The Python versions supported in this release are 2.7 and 3.4 - 3.6. The Python
+3.6 wheels available from PIP are built with Python 3.6.2 and should be
+compatible with all previous versions of Python 3.6. The source releases were
+cythonized with Cython 0.26.1, which is known to **not** support the upcoming
+Python 3.7 release. People who wish to run Python 3.7 should check out the
+NumPy repo and try building with the, as yet, unreleased master branch of
+Cython.
+
+Contributors
+============
+
+A total of 4 people contributed to this release. People with a "+" by their
+names contributed a patch for the first time.
+
+* Allan Haldane
+* Charles Harris
+* Eric Wieser
+* Pauli Virtanen
+
+Pull requests merged
+====================
+
+A total of 5 pull requests were merged for this release.
+
+* `#10674 <https://github.com/numpy/numpy/pull/10674>`__: BUG: Further back-compat fix for subclassed array repr
+* `#10725 <https://github.com/numpy/numpy/pull/10725>`__: BUG: dragon4 fractional output mode adds too many trailing zeros
+* `#10726 <https://github.com/numpy/numpy/pull/10726>`__: BUG: Fix f2py generated code to work on PyPy
+* `#10727 <https://github.com/numpy/numpy/pull/10727>`__: BUG: Fix missing NPY_VISIBILITY_HIDDEN on npy_longdouble_to_PyLong
+* `#10729 <https://github.com/numpy/numpy/pull/10729>`__: DOC: Create 1.14.2 notes and changelog.
diff --git a/doc/release/1.15.0-notes.rst b/doc/release/1.15.0-notes.rst
index 4d19a953d..2a8c57351 100644
--- a/doc/release/1.15.0-notes.rst
+++ b/doc/release/1.15.0-notes.rst
@@ -19,9 +19,11 @@ New functions
for the scope of the ``with`` block::
>>> with np.printoptions(precision=2):
- ... print(np.array([2.0])) / 3
+ ... print(np.array([2.0]) / 3)
[0.67]
+ * `np.histogram_bin_edges`, a function to get the edges of the bins used by a histogram
+ without needing to calculate the histogram.
Deprecations
============
@@ -44,6 +46,15 @@ Future Changes
Compatibility notes
===================
+``np.ma.notmasked_contiguous`` and ``np.ma.flatnotmasked_contiguous`` always return lists
+-----------------------------------------------------------------------------------------
+This was always the documented behavior, but in reality the result used to be
+any of slice, None, or list.
+
+All downstream users seem to use detect the `None` result from
+``flatnotmasked_contiguous`` and replace it with ``[]``.
+These callers will continue to work as before.
+
C API changes
=============
@@ -71,6 +82,10 @@ Creating a full iOS-compatible NumPy package requires building for the 5
architectures supported by iOS (i386, x86_64, armv7, armv7s and arm64), and
combining these 5 compiled builds products into a single "fat" binary.
+Build system
+------------
+Added experimental support for the 64-bit RISC-V architecture.
+
Improvements
============
@@ -154,5 +169,19 @@ This change makes it easier to write Python 2/3 compatible code using
``from __future__ import unicode_literals``, which previously would cause
string literal field names to raise a TypeError in Python 2.
+``sort`` functions accept ``kind='stable'``
+-------------------------------------------
+Up until now, to perform a stable sort on the data, the user must do::
+
+ >>> np.sort([5, 2, 6, 2, 1], kind='mergesort')
+ [1, 2, 2, 5, 6]
+
+because merge sort is the only stable sorting algorithm available in
+NumPy. However, having kind='mergesort' does not make it explicit that
+the user wants to perform a stable sort thus harming the readability.
+
+This change allows the user to specify kind='stable' thus clarifying
+the intent.
+
Changes
=======
diff --git a/doc/source/dev/development_environment.rst b/doc/source/dev/development_environment.rst
index e6df9803c..f4c6f3ec7 100644
--- a/doc/source/dev/development_environment.rst
+++ b/doc/source/dev/development_environment.rst
@@ -203,7 +203,7 @@ typically packaged as ``python-dbg``) is highly recommended.
.. _DebuggingWithGdb: https://wiki.python.org/moin/DebuggingWithGdb
-.. _tox: http://tox.testrun.org
+.. _tox: https://tox.readthedocs.io/
.. _virtualenv: http://www.virtualenv.org/
diff --git a/doc/source/release.rst b/doc/source/release.rst
index 0bb759dce..224436b82 100644
--- a/doc/source/release.rst
+++ b/doc/source/release.rst
@@ -3,6 +3,7 @@ Release Notes
*************
.. include:: ../release/1.15.0-notes.rst
+.. include:: ../release/1.14.2-notes.rst
.. include:: ../release/1.14.1-notes.rst
.. include:: ../release/1.14.0-notes.rst
.. include:: ../release/1.13.3-notes.rst
diff --git a/doc/source/user/building.rst b/doc/source/user/building.rst
index b98f89c2d..76eb48487 100644
--- a/doc/source/user/building.rst
+++ b/doc/source/user/building.rst
@@ -132,6 +132,8 @@ Supplying additional compiler flags
Additional compiler flags can be supplied by setting the ``OPT``,
``FOPT`` (for Fortran), and ``CC`` environment variables.
+When providing options that should improve the performance of the code ensure
+that you also set ``-DNDEBUG`` so that debugging code is not executed.
Building with ATLAS support
diff --git a/doc/summarize.py b/doc/summarize.py
index dbadb30b3..cfce2713e 100755
--- a/doc/summarize.py
+++ b/doc/summarize.py
@@ -8,7 +8,12 @@ Show a summary about which NumPy functions are documented and which are not.
from __future__ import division, absolute_import, print_function
import os, glob, re, sys, inspect, optparse
-import collections
+try:
+ # Accessing collections abstract classes from collections
+ # has been deprecated since Python 3.3
+ import collections.abc as collections_abc
+except ImportError:
+ import collections as collections_abc
sys.path.append(os.path.join(os.path.dirname(__file__), 'sphinxext'))
from sphinxext.phantom_import import import_phantom_module
@@ -136,7 +141,7 @@ def get_undocumented(documented, module, module_name=None, skip=[]):
if full_name in skip: continue
if full_name.startswith('numpy.') and full_name[6:] in skip: continue
- if not (inspect.ismodule(obj) or isinstance(obj, collections.Callable) or inspect.isclass(obj)):
+ if not (inspect.ismodule(obj) or isinstance(obj, collections_abc.Callable) or inspect.isclass(obj)):
continue
if full_name not in documented:
diff --git a/numpy/__init__.py b/numpy/__init__.py
index db99294bc..db7bc0368 100644
--- a/numpy/__init__.py
+++ b/numpy/__init__.py
@@ -150,7 +150,6 @@ else:
# no-one else in the world is using it (though I hope not)
from .testing import Tester, _numpy_tester
test = _numpy_tester().test
- bench = _numpy_tester().bench
# Allow distributors to run custom init code
from . import _distributor_init
diff --git a/numpy/add_newdocs.py b/numpy/add_newdocs.py
index 38da1f0b3..0a7b2b13d 100644
--- a/numpy/add_newdocs.py
+++ b/numpy/add_newdocs.py
@@ -3060,9 +3060,17 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('size',
"""
Number of elements in the array.
- Equivalent to ``np.prod(a.shape)``, i.e., the product of the array's
+ Equal to ``np.prod(a.shape)``, i.e., the product of the array's
dimensions.
+ Notes
+ -----
+ `a.size` returns a standard arbitrary precision Python integer. This
+ may not be the case with other methods of obtaining the same value
+ (like the suggested ``np.prod(a.shape)``, which returns an instance
+ of ``np.int_``), and may be relevant if the value is used further in
+ calculations that may overflow a fixed size integer type.
+
Examples
--------
>>> x = np.zeros((3, 5, 2), dtype=np.complex128)
@@ -4486,7 +4494,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('sort',
axis : int, optional
Axis along which to sort. Default is -1, which means sort along the
last axis.
- kind : {'quicksort', 'mergesort', 'heapsort'}, optional
+ kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional
Sorting algorithm. Default is 'quicksort'.
order : str or list of str, optional
When `a` is an array with fields defined, this argument specifies
diff --git a/numpy/compat/setup.py b/numpy/compat/setup.py
index 26161f330..882857428 100644
--- a/numpy/compat/setup.py
+++ b/numpy/compat/setup.py
@@ -1,10 +1,10 @@
-#!/usr/bin/env python
from __future__ import division, print_function
-
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')
return config
if __name__ == '__main__':
diff --git a/numpy/conftest.py b/numpy/conftest.py
index 15985a75b..ce985d079 100644
--- a/numpy/conftest.py
+++ b/numpy/conftest.py
@@ -8,7 +8,7 @@ import pytest
import numpy
import importlib
-from numpy.core.multiarray_tests import get_fpu_mode
+from numpy.core._multiarray_tests import get_fpu_mode
_old_fpu_mode = None
@@ -21,7 +21,7 @@ def pytest_itemcollected(item):
Check FPU precision mode was not changed during test collection.
The clumsy way we do it here is mainly necessary because numpy
- still uses yield tests, which can execute code at test collection
+ still uses yield tests, which can execute code at test collection
time.
"""
global _old_fpu_mode
diff --git a/numpy/core/__init__.py b/numpy/core/__init__.py
index 6db484de4..264324503 100644
--- a/numpy/core/__init__.py
+++ b/numpy/core/__init__.py
@@ -73,7 +73,6 @@ __all__ += einsumfunc.__all__
from numpy.testing import _numpy_tester
test = _numpy_tester().test
-bench = _numpy_tester().bench
# Make it possible so that ufuncs can be pickled
# Here are the loading and unloading functions
diff --git a/numpy/core/code_generators/generate_umath.py b/numpy/core/code_generators/generate_umath.py
index ebcf864ea..1d3550e06 100644
--- a/numpy/core/code_generators/generate_umath.py
+++ b/numpy/core/code_generators/generate_umath.py
@@ -966,7 +966,7 @@ def make_arrays(funcdict):
for vt in t.simd:
code2list.append(textwrap.dedent("""\
#ifdef HAVE_ATTRIBUTE_TARGET_{ISA}
- if (NPY_CPU_SUPPORTS_{ISA}) {{
+ if (npy_cpu_supports("{ISA}")) {{
{fname}_functions[{idx}] = {type}_{fname}_{isa};
}}
#endif
@@ -1073,7 +1073,7 @@ def make_code(funcdict, filename):
Please make changes to the code generator program (%s)
**/
-
+ #include "cpuid.h"
%s
static int
diff --git a/numpy/core/code_generators/ufunc_docstrings.py b/numpy/core/code_generators/ufunc_docstrings.py
index 75dee7084..c7e5cf600 100644
--- a/numpy/core/code_generators/ufunc_docstrings.py
+++ b/numpy/core/code_generators/ufunc_docstrings.py
@@ -18,23 +18,36 @@ def get(name):
return docdict.get(name)
# common parameter text to all ufuncs
-_params_text = textwrap.dedent("""
- out : ndarray, None, or tuple of ndarray and None, optional
- A location into which the result is stored. If provided, it must have
- a shape that the inputs broadcast to. If not provided or `None`,
- a freshly-allocated array is returned. A tuple (possible only as a
- keyword argument) must have length equal to the number of outputs.
- where : array_like, optional
- Values of True indicate to calculate the ufunc at that position, values
- of False indicate to leave the value in the output alone.
- **kwargs
- For other keyword-only arguments, see the
- :ref:`ufunc docs <ufuncs.kwargs>`.
-""").strip()
+subst = {
+ 'PARAMS': textwrap.dedent("""
+ out : ndarray, None, or tuple of ndarray and None, optional
+ A location into which the result is stored. If provided, it must have
+ a shape that the inputs broadcast to. If not provided or `None`,
+ a freshly-allocated array is returned. A tuple (possible only as a
+ keyword argument) must have length equal to the number of outputs.
+ where : array_like, optional
+ Values of True indicate to calculate the ufunc at that position, values
+ of False indicate to leave the value in the output alone.
+ **kwargs
+ For other keyword-only arguments, see the
+ :ref:`ufunc docs <ufuncs.kwargs>`.
+ """).strip(),
+ 'OUT_SCALAR_1': "This is a scalar if `x` is a scalar.",
+ 'OUT_SCALAR_2': "This is a scalar if both `x1` and `x2` are scalars.",
+}
def add_newdoc(place, name, doc):
doc = textwrap.dedent(doc).strip()
- doc = doc.replace('$PARAMS', _params_text)
+
+ if name[0] != '_':
+ if '\nx :' in doc:
+ assert '$OUT_SCALAR_1' in doc, "in {}".format(name)
+ elif '\nx2 :' in doc or '\nx1, x2 :' in doc:
+ assert '$OUT_SCALAR_2' in doc, "in {}".format(name)
+ else:
+ assert False, "Could not detect number of inputs in {}".format(name)
+ for k, v in subst.items():
+ doc = doc.replace('$' + k, v)
docdict['.'.join((place, name))] = doc
@@ -57,6 +70,7 @@ add_newdoc('numpy.core.umath', 'absolute',
An ndarray containing the absolute value of
each element in `x`. For complex input, ``a + ib``, the
absolute value is :math:`\\sqrt{ a^2 + b^2 }`.
+ $OUT_SCALAR_1
Examples
--------
@@ -97,8 +111,8 @@ add_newdoc('numpy.core.umath', 'add',
Returns
-------
add : ndarray or scalar
- The sum of `x1` and `x2`, element-wise. Returns a scalar if
- both `x1` and `x2` are scalars.
+ The sum of `x1` and `x2`, element-wise.
+ $OUT_SCALAR_2
Notes
-----
@@ -134,9 +148,8 @@ add_newdoc('numpy.core.umath', 'arccos',
-------
angle : ndarray
The angle of the ray intersecting the unit circle at the given
- `x`-coordinate in radians [0, pi]. If `x` is a scalar then a
- scalar is returned, otherwise an array of the same shape as `x`
- is returned.
+ `x`-coordinate in radians [0, pi].
+ $OUT_SCALAR_1
See Also
--------
@@ -194,6 +207,7 @@ add_newdoc('numpy.core.umath', 'arccosh',
-------
arccosh : ndarray
Array of the same shape as `x`.
+ $OUT_SCALAR_1
See Also
--------
@@ -244,8 +258,8 @@ add_newdoc('numpy.core.umath', 'arcsin',
-------
angle : ndarray
The inverse sine of each element in `x`, in radians and in the
- closed interval ``[-pi/2, pi/2]``. If `x` is a scalar, a scalar
- is returned, otherwise an array.
+ closed interval ``[-pi/2, pi/2]``.
+ $OUT_SCALAR_1
See Also
--------
@@ -296,8 +310,9 @@ add_newdoc('numpy.core.umath', 'arcsinh',
Returns
-------
- out : ndarray
+ out : ndarray or scalar
Array of the same shape as `x`.
+ $OUT_SCALAR_1
Notes
-----
@@ -342,10 +357,10 @@ add_newdoc('numpy.core.umath', 'arctan',
Returns
-------
- out : ndarray
+ out : ndarray or scalar
Out has the same shape as `x`. Its real part is in
``[-pi/2, pi/2]`` (``arctan(+/-inf)`` returns ``+/-pi/2``).
- It is a scalar if `x` is a scalar.
+ $OUT_SCALAR_1
See Also
--------
@@ -424,6 +439,7 @@ add_newdoc('numpy.core.umath', 'arctan2',
-------
angle : ndarray
Array of angles in radians, in the range ``[-pi, pi]``.
+ $OUT_SCALAR_2
See Also
--------
@@ -490,8 +506,9 @@ add_newdoc('numpy.core.umath', 'arctanh',
Returns
-------
- out : ndarray
+ out : ndarray or scalar
Array of the same shape as `x`.
+ $OUT_SCALAR_1
See Also
--------
@@ -543,8 +560,9 @@ add_newdoc('numpy.core.umath', 'bitwise_and',
Returns
-------
- out : array_like
+ out : ndarray or scalar
Result.
+ $OUT_SCALAR_2
See Also
--------
@@ -595,8 +613,9 @@ add_newdoc('numpy.core.umath', 'bitwise_or',
Returns
-------
- out : array_like
+ out : ndarray or scalar
Result.
+ $OUT_SCALAR_2
See Also
--------
@@ -652,8 +671,9 @@ add_newdoc('numpy.core.umath', 'bitwise_xor',
Returns
-------
- out : array_like
+ out : ndarray or scalar
Result.
+ $OUT_SCALAR_2
See Also
--------
@@ -703,6 +723,7 @@ add_newdoc('numpy.core.umath', 'ceil',
-------
y : ndarray or scalar
The ceiling of each element in `x`, with `float` dtype.
+ $OUT_SCALAR_1
See Also
--------
@@ -734,6 +755,7 @@ add_newdoc('numpy.core.umath', 'trunc',
-------
y : ndarray or scalar
The truncated value of each element in `x`.
+ $OUT_SCALAR_1
See Also
--------
@@ -768,6 +790,7 @@ add_newdoc('numpy.core.umath', 'conjugate',
-------
y : ndarray
The complex conjugate of `x`, with same dtype as `y`.
+ $OUT_SCALAR_1
Examples
--------
@@ -795,6 +818,7 @@ add_newdoc('numpy.core.umath', 'cos',
-------
y : ndarray
The corresponding cosine values.
+ $OUT_SCALAR_1
Notes
-----
@@ -838,8 +862,9 @@ add_newdoc('numpy.core.umath', 'cosh',
Returns
-------
- out : ndarray
+ out : ndarray or scalar
Output array of same shape as `x`.
+ $OUT_SCALAR_1
Examples
--------
@@ -870,6 +895,7 @@ add_newdoc('numpy.core.umath', 'degrees',
y : ndarray of floats
The corresponding degree values; if `out` was supplied this is a
reference to it.
+ $OUT_SCALAR_1
See Also
--------
@@ -905,6 +931,7 @@ add_newdoc('numpy.core.umath', 'rad2deg',
-------
y : ndarray
The corresponding angle in degrees.
+ $OUT_SCALAR_1
See Also
--------
@@ -946,8 +973,9 @@ add_newdoc('numpy.core.umath', 'heaviside',
Returns
-------
- out : ndarray
+ out : ndarray or scalar
The output array, element-wise Heaviside step function of `x1`.
+ $OUT_SCALAR_2
Notes
-----
@@ -981,8 +1009,8 @@ add_newdoc('numpy.core.umath', 'divide',
Returns
-------
y : ndarray or scalar
- The quotient ``x1/x2``, element-wise. Returns a scalar if
- both ``x1`` and ``x2`` are scalars.
+ The quotient ``x1/x2``, element-wise.
+ $OUT_SCALAR_2
See Also
--------
@@ -1050,7 +1078,8 @@ add_newdoc('numpy.core.umath', 'equal',
Returns
-------
out : ndarray or bool
- Output array of bools, or a single bool if x1 and x2 are scalars.
+ Output array of bools.
+ $OUT_SCALAR_2
See Also
--------
@@ -1081,8 +1110,9 @@ add_newdoc('numpy.core.umath', 'exp',
Returns
-------
- out : ndarray
+ out : ndarray or scalar
Output array, element-wise exponential of `x`.
+ $OUT_SCALAR_1
See Also
--------
@@ -1145,8 +1175,9 @@ add_newdoc('numpy.core.umath', 'exp2',
Returns
-------
- out : ndarray
+ out : ndarray or scalar
Element-wise 2 to the power `x`.
+ $OUT_SCALAR_1
See Also
--------
@@ -1177,8 +1208,9 @@ add_newdoc('numpy.core.umath', 'expm1',
Returns
-------
- out : ndarray
+ out : ndarray or scalar
Element-wise exponential minus one: ``out = exp(x) - 1``.
+ $OUT_SCALAR_1
See Also
--------
@@ -1222,6 +1254,7 @@ add_newdoc('numpy.core.umath', 'fabs',
-------
y : ndarray or scalar
The absolute values of `x`, the returned values are always floats.
+ $OUT_SCALAR_1
See Also
--------
@@ -1253,6 +1286,7 @@ add_newdoc('numpy.core.umath', 'floor',
-------
y : ndarray or scalar
The floor of each element in `x`.
+ $OUT_SCALAR_1
See Also
--------
@@ -1291,7 +1325,7 @@ add_newdoc('numpy.core.umath', 'floor_divide',
-------
y : ndarray
y = floor(`x1`/`x2`)
-
+ $OUT_SCALAR_2
See Also
--------
@@ -1322,15 +1356,16 @@ add_newdoc('numpy.core.umath', 'fmod',
Parameters
----------
x1 : array_like
- Dividend.
+ Dividend.
x2 : array_like
- Divisor.
+ Divisor.
$PARAMS
Returns
-------
y : array_like
- The remainder of the division of `x1` by `x2`.
+ The remainder of the division of `x1` by `x2`.
+ $OUT_SCALAR_2
See Also
--------
@@ -1381,7 +1416,8 @@ add_newdoc('numpy.core.umath', 'greater',
Returns
-------
out : bool or ndarray of bool
- Array of bools, or a single bool if `x1` and `x2` are scalars.
+ Array of bools.
+ $OUT_SCALAR_2
See Also
@@ -1417,7 +1453,8 @@ add_newdoc('numpy.core.umath', 'greater_equal',
Returns
-------
out : bool or ndarray of bool
- Array of bools, or a single bool if `x1` and `x2` are scalars.
+ Array of bools.
+ $OUT_SCALAR_2
See Also
--------
@@ -1449,6 +1486,7 @@ add_newdoc('numpy.core.umath', 'hypot',
-------
z : ndarray
The hypotenuse of the triangle(s).
+ $OUT_SCALAR_2
Examples
--------
@@ -1489,8 +1527,9 @@ add_newdoc('numpy.core.umath', 'invert',
Returns
-------
- out : array_like
+ out : ndarray or scalar
Result.
+ $OUT_SCALAR_1
See Also
--------
@@ -1562,15 +1601,9 @@ add_newdoc('numpy.core.umath', 'isfinite',
Returns
-------
y : ndarray, bool
- For scalar input, the result is a new boolean with value True
- if the input is finite; otherwise the value is False (input is
- either positive infinity, negative infinity or Not a Number).
-
- For array input, the result is a boolean array with the same
- dimensions as the input and the values are True if the
- corresponding element of the input is finite; otherwise the values
- are False (element is either positive infinity, negative infinity
- or Not a Number).
+ True where ``x`` is not positive infinity, negative infinity,
+ or NaN; false otherwise.
+ $OUT_SCALAR_1
See Also
--------
@@ -1628,18 +1661,8 @@ add_newdoc('numpy.core.umath', 'isinf',
Returns
-------
y : bool (scalar) or boolean ndarray
- For scalar input, the result is a new boolean with value True if
- the input is positive or negative infinity; otherwise the value is
- False.
-
- For array input, the result is a boolean array with the same shape
- as the input and the values are True where the corresponding
- element of the input is positive or negative infinity; elsewhere
- the values are False. If a second argument was supplied the result
- is stored there. If the type of that array is a numeric type the
- result is represented as zeros and ones, if the type is boolean
- then as False and True, respectively. The return value `y` is then
- a reference to that array.
+ True where ``x`` is positive or negative infinity, false otherwise.
+ $OUT_SCALAR_1
See Also
--------
@@ -1687,13 +1710,8 @@ add_newdoc('numpy.core.umath', 'isnan',
Returns
-------
y : ndarray or bool
- For scalar input, the result is a new boolean with value True if
- the input is NaN; otherwise the value is False.
-
- For array input, the result is a boolean array of the same
- dimensions as the input and the values are True if the
- corresponding element of the input is NaN; otherwise the values are
- False.
+ True where ``x`` is NaN, false otherwise.
+ $OUT_SCALAR_1
See Also
--------
@@ -1728,13 +1746,8 @@ add_newdoc('numpy.core.umath', 'isnat',
Returns
-------
y : ndarray or bool
- For scalar input, the result is a new boolean with value True if
- the input is NaT; otherwise the value is False.
-
- For array input, the result is a boolean array of the same
- dimensions as the input and the values are True if the
- corresponding element of the input is NaT; otherwise the values are
- False.
+ True where ``x`` is NaT, false otherwise.
+ $OUT_SCALAR_1
See Also
--------
@@ -1771,6 +1784,7 @@ add_newdoc('numpy.core.umath', 'left_shift',
-------
out : array of integer type
Return `x1` with bits shifted `x2` times to the left.
+ $OUT_SCALAR_2
See Also
--------
@@ -1807,7 +1821,8 @@ add_newdoc('numpy.core.umath', 'less',
Returns
-------
out : bool or ndarray of bool
- Array of bools, or a single bool if `x1` and `x2` are scalars.
+ Array of bools.
+ $OUT_SCALAR_2
See Also
--------
@@ -1835,7 +1850,8 @@ add_newdoc('numpy.core.umath', 'less_equal',
Returns
-------
out : bool or ndarray of bool
- Array of bools, or a single bool if `x1` and `x2` are scalars.
+ Array of bools.
+ $OUT_SCALAR_2
See Also
--------
@@ -1866,6 +1882,7 @@ add_newdoc('numpy.core.umath', 'log',
-------
y : ndarray
The natural logarithm of `x`, element-wise.
+ $OUT_SCALAR_1
See Also
--------
@@ -1914,6 +1931,7 @@ add_newdoc('numpy.core.umath', 'log10',
y : ndarray
The logarithm to the base 10 of `x`, element-wise. NaNs are
returned where x is negative.
+ $OUT_SCALAR_1
See Also
--------
@@ -1961,6 +1979,7 @@ add_newdoc('numpy.core.umath', 'log2',
-------
y : ndarray
Base-2 logarithm of `x`.
+ $OUT_SCALAR_1
See Also
--------
@@ -2015,6 +2034,7 @@ add_newdoc('numpy.core.umath', 'logaddexp',
-------
result : ndarray
Logarithm of ``exp(x1) + exp(x2)``.
+ $OUT_SCALAR_2
See Also
--------
@@ -2056,6 +2076,7 @@ add_newdoc('numpy.core.umath', 'logaddexp2',
-------
result : ndarray
Base-2 logarithm of ``2**x1 + 2**x2``.
+ $OUT_SCALAR_2
See Also
--------
@@ -2093,6 +2114,7 @@ add_newdoc('numpy.core.umath', 'log1p',
-------
y : ndarray
Natural logarithm of `1 + x`, element-wise.
+ $OUT_SCALAR_1
See Also
--------
@@ -2146,6 +2168,7 @@ add_newdoc('numpy.core.umath', 'logical_and',
y : ndarray or bool
Boolean result with the same shape as `x1` and `x2` of the logical
AND operation on corresponding elements of `x1` and `x2`.
+ $OUT_SCALAR_2
See Also
--------
@@ -2180,6 +2203,7 @@ add_newdoc('numpy.core.umath', 'logical_not',
y : bool or ndarray of bool
Boolean result with the same shape as `x` of the NOT operation
on elements of `x`.
+ $OUT_SCALAR_1
See Also
--------
@@ -2214,6 +2238,7 @@ add_newdoc('numpy.core.umath', 'logical_or',
y : ndarray or bool
Boolean result with the same shape as `x1` and `x2` of the logical
OR operation on elements of `x1` and `x2`.
+ $OUT_SCALAR_2
See Also
--------
@@ -2250,6 +2275,7 @@ add_newdoc('numpy.core.umath', 'logical_xor',
Boolean result of the logical XOR operation applied to the elements
of `x1` and `x2`; the shape is determined by whether or not
broadcasting of one or both arrays was required.
+ $OUT_SCALAR_2
See Also
--------
@@ -2295,8 +2321,8 @@ add_newdoc('numpy.core.umath', 'maximum',
Returns
-------
y : ndarray or scalar
- The maximum of `x1` and `x2`, element-wise. Returns scalar if
- both `x1` and `x2` are scalars.
+ The maximum of `x1` and `x2`, element-wise.
+ $OUT_SCALAR_2
See Also
--------
@@ -2354,8 +2380,8 @@ add_newdoc('numpy.core.umath', 'minimum',
Returns
-------
y : ndarray or scalar
- The minimum of `x1` and `x2`, element-wise. Returns scalar if
- both `x1` and `x2` are scalars.
+ The minimum of `x1` and `x2`, element-wise.
+ $OUT_SCALAR_2
See Also
--------
@@ -2413,8 +2439,8 @@ add_newdoc('numpy.core.umath', 'fmax',
Returns
-------
y : ndarray or scalar
- The maximum of `x1` and `x2`, element-wise. Returns scalar if
- both `x1` and `x2` are scalars.
+ The maximum of `x1` and `x2`, element-wise.
+ $OUT_SCALAR_2
See Also
--------
@@ -2471,8 +2497,8 @@ add_newdoc('numpy.core.umath', 'fmin',
Returns
-------
y : ndarray or scalar
- The minimum of `x1` and `x2`, element-wise. Returns scalar if
- both `x1` and `x2` are scalars.
+ The minimum of `x1` and `x2`, element-wise.
+ $OUT_SCALAR_2
See Also
--------
@@ -2525,8 +2551,10 @@ add_newdoc('numpy.core.umath', 'modf',
-------
y1 : ndarray
Fractional part of `x`.
+ $OUT_SCALAR_1
y2 : ndarray
Integral part of `x`.
+ $OUT_SCALAR_1
Notes
-----
@@ -2560,7 +2588,8 @@ add_newdoc('numpy.core.umath', 'multiply',
-------
y : ndarray
The product of `x1` and `x2`, element-wise. Returns a scalar if
- both `x1` and `x2` are scalars.
+ both `x1` and `x2` are scalars.
+ $OUT_SCALAR_2
Notes
-----
@@ -2594,6 +2623,7 @@ add_newdoc('numpy.core.umath', 'negative',
-------
y : ndarray or scalar
Returned array or scalar: `y = -x`.
+ $OUT_SCALAR_1
Examples
--------
@@ -2617,6 +2647,7 @@ add_newdoc('numpy.core.umath', 'positive',
-------
y : ndarray or scalar
Returned array or scalar: `y = +x`.
+ $OUT_SCALAR_1
Notes
-----
@@ -2632,14 +2663,15 @@ add_newdoc('numpy.core.umath', 'not_equal',
Parameters
----------
x1, x2 : array_like
- Input arrays.
+ Input arrays.
$PARAMS
Returns
-------
not_equal : ndarray bool, scalar bool
- For each element in `x1, x2`, return True if `x1` is not equal
- to `x2` and False otherwise.
+ For each element in `x1, x2`, return True if `x1` is not equal
+ to `x2` and False otherwise.
+ $OUT_SCALAR_2
See Also
@@ -2688,6 +2720,7 @@ add_newdoc('numpy.core.umath', 'power',
-------
y : ndarray
The bases in `x1` raised to the exponents in `x2`.
+ $OUT_SCALAR_2
See Also
--------
@@ -2746,6 +2779,7 @@ add_newdoc('numpy.core.umath', 'float_power',
-------
y : ndarray
The bases in `x1` raised to the exponents in `x2`.
+ $OUT_SCALAR_2
See Also
--------
@@ -2793,6 +2827,7 @@ add_newdoc('numpy.core.umath', 'radians',
-------
y : ndarray
The corresponding radian values.
+ $OUT_SCALAR_1
See Also
--------
@@ -2829,6 +2864,7 @@ add_newdoc('numpy.core.umath', 'deg2rad',
-------
y : ndarray
The corresponding angle in radians.
+ $OUT_SCALAR_1
See Also
--------
@@ -2864,6 +2900,7 @@ add_newdoc('numpy.core.umath', 'reciprocal',
-------
y : ndarray
Return array.
+ $OUT_SCALAR_1
Notes
-----
@@ -2914,7 +2951,7 @@ add_newdoc('numpy.core.umath', 'remainder',
-------
y : ndarray
The element-wise remainder of the quotient ``floor_divide(x1, x2)``.
- Returns a scalar if both `x1` and `x2` are scalars.
+ $OUT_SCALAR_2
See Also
--------
@@ -2959,8 +2996,10 @@ add_newdoc('numpy.core.umath', 'divmod',
-------
out1 : ndarray
Element-wise quotient resulting from floor division.
+ $OUT_SCALAR_2
out2 : ndarray
Element-wise remainder from floor division.
+ $OUT_SCALAR_2
See Also
--------
@@ -2996,6 +3035,7 @@ add_newdoc('numpy.core.umath', 'right_shift',
-------
out : ndarray, int
Return `x1` with bits shifted `x2` times to the right.
+ $OUT_SCALAR_2
See Also
--------
@@ -3031,6 +3071,7 @@ add_newdoc('numpy.core.umath', 'rint',
-------
out : ndarray or scalar
Output array is same shape and type as `x`.
+ $OUT_SCALAR_1
See Also
--------
@@ -3059,13 +3100,14 @@ add_newdoc('numpy.core.umath', 'sign',
Parameters
----------
x : array_like
- Input values.
+ Input values.
$PARAMS
Returns
-------
y : ndarray
- The sign of `x`.
+ The sign of `x`.
+ $OUT_SCALAR_1
Notes
-----
@@ -3098,6 +3140,7 @@ add_newdoc('numpy.core.umath', 'signbit',
-------
result : ndarray of bool
Output array, or reference to `out` if that was supplied.
+ $OUT_SCALAR_1
Examples
--------
@@ -3126,8 +3169,9 @@ add_newdoc('numpy.core.umath', 'copysign',
Returns
-------
- out : array_like
+ out : ndarray or scalar
The values of `x1` with the sign of `x2`.
+ $OUT_SCALAR_2
Examples
--------
@@ -3159,8 +3203,9 @@ add_newdoc('numpy.core.umath', 'nextafter',
Returns
-------
- out : array_like
+ out : ndarray or scalar
The next representable values of `x1` in the direction of `x2`.
+ $OUT_SCALAR_2
Examples
--------
@@ -3184,8 +3229,9 @@ add_newdoc('numpy.core.umath', 'spacing',
Returns
-------
- out : array_like
- The spacing of values of `x1`.
+ out : ndarray or scalar
+ The spacing of values of `x`.
+ $OUT_SCALAR_1
Notes
-----
@@ -3217,6 +3263,7 @@ add_newdoc('numpy.core.umath', 'sin',
-------
y : array_like
The sine of each element of x.
+ $OUT_SCALAR_1
See Also
--------
@@ -3277,6 +3324,7 @@ add_newdoc('numpy.core.umath', 'sinh',
-------
y : ndarray
The corresponding hyperbolic sine values.
+ $OUT_SCALAR_1
Notes
-----
@@ -3330,6 +3378,7 @@ add_newdoc('numpy.core.umath', 'sqrt',
negative reals are calculated). If all of the elements in `x`
are real, so is `y`, with negative elements returning ``nan``.
If `out` was provided, `y` is a reference to it.
+ $OUT_SCALAR_1
See Also
--------
@@ -3374,6 +3423,7 @@ add_newdoc('numpy.core.umath', 'cbrt',
An array of the same shape as `x`, containing the cube
cube-root of each element in `x`.
If `out` was provided, `y` is a reference to it.
+ $OUT_SCALAR_1
Examples
@@ -3395,9 +3445,9 @@ add_newdoc('numpy.core.umath', 'square',
Returns
-------
- out : ndarray
+ out : ndarray or scalar
Element-wise `x*x`, of the same shape and dtype as `x`.
- Returns scalar if `x` is a scalar.
+ $OUT_SCALAR_1
See Also
--------
@@ -3425,8 +3475,8 @@ add_newdoc('numpy.core.umath', 'subtract',
Returns
-------
y : ndarray
- The difference of `x1` and `x2`, element-wise. Returns a scalar if
- both `x1` and `x2` are scalars.
+ The difference of `x1` and `x2`, element-wise.
+ $OUT_SCALAR_2
Notes
-----
@@ -3455,13 +3505,14 @@ add_newdoc('numpy.core.umath', 'tan',
Parameters
----------
x : array_like
- Input array.
+ Input array.
$PARAMS
Returns
-------
y : ndarray
- The corresponding tangent values.
+ The corresponding tangent values.
+ $OUT_SCALAR_1
Notes
-----
@@ -3509,6 +3560,7 @@ add_newdoc('numpy.core.umath', 'tanh',
-------
y : ndarray
The corresponding hyperbolic tangent values.
+ $OUT_SCALAR_1
Notes
-----
@@ -3561,8 +3613,8 @@ add_newdoc('numpy.core.umath', 'true_divide',
Returns
-------
- out : ndarray
- Result is scalar if both inputs are scalar, ndarray otherwise.
+ out : ndarray or scalar
+ $OUT_SCALAR_2
Notes
-----
@@ -3614,9 +3666,12 @@ add_newdoc('numpy.core.umath', 'frexp',
Returns
-------
- (mantissa, exponent) : tuple of ndarrays, (float, int)
- `mantissa` is a float array with values between -1 and 1.
- `exponent` is an int array which represents the exponent of 2.
+ mantissa : ndarray
+ Floating values between -1 and 1.
+ $OUT_SCALAR_1
+ exponent : ndarray
+ Integer exponents of 2.
+ $OUT_SCALAR_1
See Also
--------
@@ -3659,6 +3714,7 @@ add_newdoc('numpy.core.umath', 'ldexp',
-------
y : ndarray or scalar
The result of ``x1 * 2**x2``.
+ $OUT_SCALAR_2
See Also
--------
@@ -3695,6 +3751,7 @@ add_newdoc('numpy.core.umath', 'gcd',
-------
y : ndarray or scalar
The greatest common divisor of the absolute value of the inputs
+ $OUT_SCALAR_2
See Also
--------
@@ -3724,6 +3781,7 @@ add_newdoc('numpy.core.umath', 'lcm',
-------
y : ndarray or scalar
The lowest common multiple of the absolute value of the inputs
+ $OUT_SCALAR_2
See Also
--------
diff --git a/numpy/core/fromnumeric.py b/numpy/core/fromnumeric.py
index 10256c3c0..63279ffb3 100644
--- a/numpy/core/fromnumeric.py
+++ b/numpy/core/fromnumeric.py
@@ -764,7 +764,7 @@ def sort(a, axis=-1, kind='quicksort', order=None):
axis : int or None, optional
Axis along which to sort. If None, the array is flattened before
sorting. The default is -1, which sorts along the last axis.
- kind : {'quicksort', 'mergesort', 'heapsort'}, optional
+ kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional
Sorting algorithm. Default is 'quicksort'.
order : str or list of str, optional
When `a` is an array with fields defined, this argument specifies
@@ -794,13 +794,13 @@ def sort(a, axis=-1, kind='quicksort', order=None):
order. The three available algorithms have the following
properties:
- =========== ======= ============= ============ =======
- kind speed worst case work space stable
- =========== ======= ============= ============ =======
+ =========== ======= ============= ============ ========
+ kind speed worst case work space stable
+ =========== ======= ============= ============ ========
'quicksort' 1 O(n^2) 0 no
'mergesort' 2 O(n*log(n)) ~n/2 yes
'heapsort' 3 O(n*log(n)) 0 no
- =========== ======= ============= ============ =======
+ =========== ======= ============= ============ ========
All the sort algorithms make temporary copies of the data when
sorting along any but the last axis. Consequently, sorting along
@@ -829,6 +829,10 @@ def sort(a, axis=-1, kind='quicksort', order=None):
heapsort when it does not make enough progress. This makes its
worst case O(n*log(n)).
+ 'stable' automatically choses the best stable sorting algorithm
+ for the data type being sorted. It is currently mapped to
+ merge sort.
+
Examples
--------
>>> a = np.array([[1,4],[3,1]])
@@ -886,7 +890,7 @@ def argsort(a, axis=-1, kind='quicksort', order=None):
axis : int or None, optional
Axis along which to sort. The default is -1 (the last axis). If None,
the flattened array is used.
- kind : {'quicksort', 'mergesort', 'heapsort'}, optional
+ kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional
Sorting algorithm.
order : str or list of str, optional
When `a` is an array with fields defined, this argument specifies
diff --git a/numpy/core/include/numpy/npy_common.h b/numpy/core/include/numpy/npy_common.h
index b7634a930..5faff4385 100644
--- a/numpy/core/include/numpy/npy_common.h
+++ b/numpy/core/include/numpy/npy_common.h
@@ -101,22 +101,6 @@
#endif
#endif
-#ifdef HAVE___BUILTIN_CPU_SUPPORTS
- #ifdef HAVE_ATTRIBUTE_TARGET_AVX2
- #define NPY_CPU_SUPPORTS_AVX2 __builtin_cpu_supports("avx2")
- #else
- #define NPY_CPU_SUPPORTS_AVX2 0
- #endif
- #ifdef HAVE_ATTRIBUTE_TARGET_AVX
- #define NPY_CPU_SUPPORTS_AVX __builtin_cpu_supports("avx")
- #else
- #define NPY_CPU_SUPPORTS_AVX 0
- #endif
-#else
- #define NPY_CPU_SUPPORTS_AVX 0
- #define NPY_CPU_SUPPORTS_AVX2 0
-#endif
-
#if defined(_MSC_VER)
#define NPY_INLINE __inline
#elif defined(__GNUC__)
diff --git a/numpy/core/include/numpy/npy_cpu.h b/numpy/core/include/numpy/npy_cpu.h
index 84653ea18..106ffa450 100644
--- a/numpy/core/include/numpy/npy_cpu.h
+++ b/numpy/core/include/numpy/npy_cpu.h
@@ -17,6 +17,7 @@
* NPY_CPU_SH_BE
* NPY_CPU_ARCEL
* NPY_CPU_ARCEB
+ * NPY_CPU_RISCV64
*/
#ifndef _NPY_CPUARCH_H_
#define _NPY_CPUARCH_H_
@@ -82,6 +83,8 @@
#define NPY_CPU_ARCEL
#elif defined(__arc__) && defined(__BIG_ENDIAN__)
#define NPY_CPU_ARCEB
+#elif defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 64
+ #define NPY_CPU_RISCV64
#else
#error Unknown CPU, please report this to numpy maintainers with \
information about your platform (OS, CPU and compiler)
diff --git a/numpy/core/include/numpy/npy_endian.h b/numpy/core/include/numpy/npy_endian.h
index 1a42121db..649bdb0a6 100644
--- a/numpy/core/include/numpy/npy_endian.h
+++ b/numpy/core/include/numpy/npy_endian.h
@@ -46,7 +46,8 @@
|| defined(NPY_CPU_SH_LE) \
|| defined(NPY_CPU_MIPSEL) \
|| defined(NPY_CPU_PPC64LE) \
- || defined(NPY_CPU_ARCEL)
+ || defined(NPY_CPU_ARCEL) \
+ || defined(NPY_CPU_RISCV64)
#define NPY_BYTE_ORDER NPY_LITTLE_ENDIAN
#elif defined(NPY_CPU_PPC) \
|| defined(NPY_CPU_SPARC) \
diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py
index 1f249ae6c..d154206c5 100644
--- a/numpy/core/numeric.py
+++ b/numpy/core/numeric.py
@@ -1,6 +1,11 @@
from __future__ import division, absolute_import, print_function
-import collections
+try:
+ # Accessing collections abstract classes from collections
+ # has been deprecated since Python 3.3
+ import collections.abc as collections_abc
+except ImportError:
+ import collections as collections_abc
import itertools
import operator
import sys
@@ -1084,7 +1089,7 @@ def outer(a, b, out=None):
References
----------
- .. [1] : G. H. Golub and C. F. van Loan, *Matrix Computations*, 3rd
+ .. [1] : G. H. Golub and C. F. Van Loan, *Matrix Computations*, 3rd
ed., Baltimore, MD, Johns Hopkins University Press, 1996,
pg. 8.
@@ -2758,8 +2763,8 @@ def seterrcall(func):
{'over': 'log', 'divide': 'log', 'invalid': 'log', 'under': 'log'}
"""
- if func is not None and not isinstance(func, collections.Callable):
- if not hasattr(func, 'write') or not isinstance(func.write, collections.Callable):
+ if func is not None and not isinstance(func, collections_abc.Callable):
+ if not hasattr(func, 'write') or not isinstance(func.write, collections_abc.Callable):
raise ValueError("Only callable can be used as callback")
pyvals = umath.geterrobj()
old = geterrcall()
diff --git a/numpy/core/setup.py b/numpy/core/setup.py
index 11b1acb07..15f6e1522 100644
--- a/numpy/core/setup.py
+++ b/numpy/core/setup.py
@@ -888,6 +888,7 @@ def configuration(parent_package='',top_path=None):
join('src', 'umath', 'loops.c.src'),
join('src', 'umath', 'ufunc_object.c'),
join('src', 'umath', 'extobj.c'),
+ join('src', 'umath', 'cpuid.c'),
join('src', 'umath', 'scalarmath.c.src'),
join('src', 'umath', 'ufunc_type_resolution.c'),
join('src', 'umath', 'override.c'),
@@ -924,29 +925,29 @@ def configuration(parent_package='',top_path=None):
# umath_tests module #
#######################################################################
- config.add_extension('umath_tests',
- sources=[join('src', 'umath', 'umath_tests.c.src')])
+ config.add_extension('_umath_tests',
+ sources=[join('src', 'umath', '_umath_tests.c.src')])
#######################################################################
# custom rational dtype module #
#######################################################################
- config.add_extension('test_rational',
- sources=[join('src', 'umath', 'test_rational.c.src')])
+ config.add_extension('_rational_tests',
+ sources=[join('src', 'umath', '_rational_tests.c.src')])
#######################################################################
# struct_ufunc_test module #
#######################################################################
- config.add_extension('struct_ufunc_test',
- sources=[join('src', 'umath', 'struct_ufunc_test.c.src')])
+ config.add_extension('_struct_ufunc_tests',
+ sources=[join('src', 'umath', '_struct_ufunc_tests.c.src')])
#######################################################################
# multiarray_tests module #
#######################################################################
- config.add_extension('multiarray_tests',
- sources=[join('src', 'multiarray', 'multiarray_tests.c.src'),
+ config.add_extension('_multiarray_tests',
+ sources=[join('src', 'multiarray', '_multiarray_tests.c.src'),
join('src', 'private', 'mem_overlap.c')],
depends=[join('src', 'private', 'mem_overlap.h'),
join('src', 'private', 'npy_extint128.h')],
@@ -956,8 +957,8 @@ def configuration(parent_package='',top_path=None):
# operand_flag_tests module #
#######################################################################
- config.add_extension('operand_flag_tests',
- sources=[join('src', 'umath', 'operand_flag_tests.c.src')])
+ config.add_extension('_operand_flag_tests',
+ sources=[join('src', 'umath', '_operand_flag_tests.c.src')])
config.add_data_dir('tests')
config.add_data_dir('tests/data')
diff --git a/numpy/core/setup_common.py b/numpy/core/setup_common.py
index 1fe953910..f36d61f55 100644
--- a/numpy/core/setup_common.py
+++ b/numpy/core/setup_common.py
@@ -146,6 +146,7 @@ OPTIONAL_INTRINSICS = [("__builtin_isnan", '5.'),
"stdio.h", "LINK_AVX"),
("__asm__ volatile", '"vpand %ymm1, %ymm2, %ymm3"',
"stdio.h", "LINK_AVX2"),
+ ("__asm__ volatile", '"xgetbv"', "stdio.h", "XGETBV"),
]
# function attributes
diff --git a/numpy/core/src/multiarray/multiarray_tests.c.src b/numpy/core/src/multiarray/_multiarray_tests.c.src
index d63349560..afc6db1aa 100644
--- a/numpy/core/src/multiarray/multiarray_tests.c.src
+++ b/numpy/core/src/multiarray/_multiarray_tests.c.src
@@ -1867,7 +1867,7 @@ static PyMethodDef Multiarray_TestsMethods[] = {
#if defined(NPY_PY3K)
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
- "multiarray_tests",
+ "_multiarray_tests",
NULL,
-1,
Multiarray_TestsMethods,
@@ -1880,11 +1880,11 @@ static struct PyModuleDef moduledef = {
#if defined(NPY_PY3K)
#define RETVAL m
-PyMODINIT_FUNC PyInit_multiarray_tests(void)
+PyMODINIT_FUNC PyInit__multiarray_tests(void)
#else
#define RETVAL
PyMODINIT_FUNC
-initmultiarray_tests(void)
+init_multiarray_tests(void)
#endif
{
PyObject *m;
@@ -1892,7 +1892,7 @@ initmultiarray_tests(void)
#if defined(NPY_PY3K)
m = PyModule_Create(&moduledef);
#else
- m = Py_InitModule("multiarray_tests", Multiarray_TestsMethods);
+ m = Py_InitModule("_multiarray_tests", Multiarray_TestsMethods);
#endif
if (m == NULL) {
return RETVAL;
@@ -1900,7 +1900,7 @@ initmultiarray_tests(void)
import_array();
if (PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError,
- "cannot load umath_tests module.");
+ "cannot load _multiarray_tests module.");
}
return RETVAL;
}
diff --git a/numpy/core/src/multiarray/arraytypes.c.src b/numpy/core/src/multiarray/arraytypes.c.src
index e8aa19416..5e6804a5c 100644
--- a/numpy/core/src/multiarray/arraytypes.c.src
+++ b/numpy/core/src/multiarray/arraytypes.c.src
@@ -998,11 +998,25 @@ VOID_setitem(PyObject *op, void *input, void *vap)
* undiscerning case: It interprets any object as a buffer
* and reads as many bytes as possible, padding with 0.
*/
+#if defined(NPY_PY3K)
+ {
+ Py_buffer view;
+
+ if (PyObject_GetBuffer(op, &view, PyBUF_SIMPLE) < 0) {
+ return -1;
+ }
+ memcpy(ip, view.buf, PyArray_MIN(view.len, itemsize));
+ if (itemsize > view.len) {
+ memset(ip + view.len, 0, itemsize - view.len);
+ }
+ PyBuffer_Release(&view);
+ }
+#else
{
const void *buffer;
Py_ssize_t buflen;
- res = PyObject_AsReadBuffer(op, &buffer, &buflen);
- if (res == -1) {
+
+ if (PyObject_AsReadBuffer(op, &buffer, &buflen) < 0) {
return -1;
}
memcpy(ip, buffer, PyArray_MIN(buflen, itemsize));
@@ -1010,6 +1024,7 @@ VOID_setitem(PyObject *op, void *input, void *vap)
memset(ip + buflen, 0, itemsize - buflen);
}
}
+#endif
return 0;
}
diff --git a/numpy/core/src/multiarray/buffer.c b/numpy/core/src/multiarray/buffer.c
index 4aa25a196..21dbdefd6 100644
--- a/numpy/core/src/multiarray/buffer.c
+++ b/numpy/core/src/multiarray/buffer.c
@@ -15,6 +15,7 @@
#include "common.h"
#include "numpyos.h"
#include "arrayobject.h"
+#include "scalartypes.h"
/*************************************************************************
**************** Implement Buffer Protocol ****************************
@@ -176,7 +177,7 @@ _is_natively_aligned_at(PyArray_Descr *descr,
static int
_buffer_format_string(PyArray_Descr *descr, _tmp_string_t *str,
- PyArrayObject* arr, Py_ssize_t *offset,
+ PyObject* obj, Py_ssize_t *offset,
char *active_byteorder)
{
int k;
@@ -223,7 +224,7 @@ _buffer_format_string(PyArray_Descr *descr, _tmp_string_t *str,
Py_DECREF(subarray_tuple);
old_offset = *offset;
- ret = _buffer_format_string(descr->subarray->base, str, arr, offset,
+ ret = _buffer_format_string(descr->subarray->base, str, obj, offset,
active_byteorder);
*offset = old_offset + (*offset - old_offset) * total_count;
return ret;
@@ -265,7 +266,7 @@ _buffer_format_string(PyArray_Descr *descr, _tmp_string_t *str,
}
/* Insert child item */
- _buffer_format_string(child, str, arr, offset,
+ _buffer_format_string(child, str, obj, offset,
active_byteorder);
/* Insert field name */
@@ -302,6 +303,7 @@ _buffer_format_string(PyArray_Descr *descr, _tmp_string_t *str,
}
else {
int is_standard_size = 1;
+ int is_natively_aligned;
int is_native_only_type = (descr->type_num == NPY_LONGDOUBLE ||
descr->type_num == NPY_CLONGDOUBLE);
if (sizeof(npy_longlong) != 8) {
@@ -312,8 +314,16 @@ _buffer_format_string(PyArray_Descr *descr, _tmp_string_t *str,
*offset += descr->elsize;
- if (descr->byteorder == '=' &&
- _is_natively_aligned_at(descr, arr, *offset)) {
+ if (PyArray_IsScalar(obj, Generic)) {
+ /* scalars are always natively aligned */
+ is_natively_aligned = 1;
+ }
+ else {
+ is_natively_aligned = _is_natively_aligned_at(descr,
+ (PyArrayObject*)obj, *offset);
+ }
+
+ if (descr->byteorder == '=' && is_natively_aligned) {
/* Prefer native types, to cater for Cython */
is_standard_size = 0;
if (*active_byteorder != '@') {
@@ -448,43 +458,61 @@ static PyObject *_buffer_info_cache = NULL;
/* Fill in the info structure */
static _buffer_info_t*
-_buffer_info_new(PyArrayObject *arr)
+_buffer_info_new(PyObject *obj)
{
_buffer_info_t *info;
_tmp_string_t fmt = {NULL, 0, 0};
int k;
+ PyArray_Descr *descr = NULL;
+ int err = 0;
info = malloc(sizeof(_buffer_info_t));
if (info == NULL) {
goto fail;
}
- /* Fill in format */
- if (_buffer_format_string(PyArray_DESCR(arr), &fmt, arr, NULL, NULL) != 0) {
- free(fmt.s);
- goto fail;
- }
- _append_char(&fmt, '\0');
- info->format = fmt.s;
-
- /* Fill in shape and strides */
- info->ndim = PyArray_NDIM(arr);
-
- if (info->ndim == 0) {
+ if (PyArray_IsScalar(obj, Generic)) {
+ descr = PyArray_DescrFromScalar(obj);
+ if (descr == NULL) {
+ goto fail;
+ }
+ info->ndim = 0;
info->shape = NULL;
info->strides = NULL;
}
else {
- info->shape = malloc(sizeof(Py_ssize_t) * PyArray_NDIM(arr) * 2 + 1);
- if (info->shape == NULL) {
- goto fail;
+ PyArrayObject * arr = (PyArrayObject *)obj;
+ descr = PyArray_DESCR(arr);
+ /* Fill in shape and strides */
+ info->ndim = PyArray_NDIM(arr);
+
+ if (info->ndim == 0) {
+ info->shape = NULL;
+ info->strides = NULL;
}
- info->strides = info->shape + PyArray_NDIM(arr);
- for (k = 0; k < PyArray_NDIM(arr); ++k) {
- info->shape[k] = PyArray_DIMS(arr)[k];
- info->strides[k] = PyArray_STRIDES(arr)[k];
+ else {
+ info->shape = malloc(sizeof(Py_ssize_t) * PyArray_NDIM(arr) * 2 + 1);
+ if (info->shape == NULL) {
+ goto fail;
+ }
+ info->strides = info->shape + PyArray_NDIM(arr);
+ for (k = 0; k < PyArray_NDIM(arr); ++k) {
+ info->shape[k] = PyArray_DIMS(arr)[k];
+ info->strides[k] = PyArray_STRIDES(arr)[k];
+ }
}
+ Py_INCREF(descr);
+ }
+
+ /* Fill in format */
+ err = _buffer_format_string(descr, &fmt, obj, NULL, NULL);
+ Py_DECREF(descr);
+ if (err != 0) {
+ free(fmt.s);
+ goto fail;
}
+ _append_char(&fmt, '\0');
+ info->format = fmt.s;
return info;
@@ -530,7 +558,7 @@ _buffer_info_free(_buffer_info_t *info)
/* Get buffer info from the global dictionary */
static _buffer_info_t*
-_buffer_get_info(PyObject *arr)
+_buffer_get_info(PyObject *obj)
{
PyObject *key = NULL, *item_list = NULL, *item = NULL;
_buffer_info_t *info = NULL, *old_info = NULL;
@@ -543,13 +571,13 @@ _buffer_get_info(PyObject *arr)
}
/* Compute information */
- info = _buffer_info_new((PyArrayObject*)arr);
+ info = _buffer_info_new(obj);
if (info == NULL) {
return NULL;
}
/* Check if it is identical with an old one; reuse old one, if yes */
- key = PyLong_FromVoidPtr((void*)arr);
+ key = PyLong_FromVoidPtr((void*)obj);
if (key == NULL) {
goto fail;
}
@@ -627,9 +655,8 @@ _buffer_clear_info(PyObject *arr)
}
/*
- * Retrieving buffers
+ * Retrieving buffers for ndarray
*/
-
static int
array_getbuffer(PyObject *obj, Py_buffer *view, int flags)
{
@@ -751,6 +778,62 @@ fail:
return -1;
}
+/*
+ * Retrieving buffers for scalars
+ */
+int
+gentype_getbuffer(PyObject *self, Py_buffer *view, int flags)
+{
+ _buffer_info_t *info = NULL;
+ PyArray_Descr *descr = NULL;
+ int elsize;
+
+ if (flags & PyBUF_WRITABLE) {
+ PyErr_SetString(PyExc_BufferError, "scalar buffer is readonly");
+ goto fail;
+ }
+
+ /* Fill in information */
+ info = _buffer_get_info(self);
+ if (info == NULL) {
+ PyErr_SetString(PyExc_BufferError,
+ "could not get scalar buffer information");
+ goto fail;
+ }
+
+ view->ndim = info->ndim;
+ view->shape = info->shape;
+ view->strides = info->strides;
+
+ if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) {
+ view->format = info->format;
+ } else {
+ view->format = NULL;
+ }
+
+ descr = PyArray_DescrFromScalar(self);
+ view->buf = (void *)scalar_value(self, descr);
+ elsize = descr->elsize;
+#ifndef Py_UNICODE_WIDE
+ if (descr->type_num == NPY_UNICODE) {
+ elsize >>= 1;
+ }
+#endif
+ view->len = elsize;
+ view->itemsize = elsize;
+
+ Py_DECREF(descr);
+
+ view->readonly = 1;
+ view->suboffsets = NULL;
+ view->obj = self;
+ Py_INCREF(self);
+ return 0;
+
+fail:
+ view->obj = NULL;
+ return -1;
+}
/*
* NOTE: for backward compatibility (esp. with PyArg_ParseTuple("s#", ...))
diff --git a/numpy/core/src/multiarray/buffer.h b/numpy/core/src/multiarray/buffer.h
index d2ea01b34..d5da8f440 100644
--- a/numpy/core/src/multiarray/buffer.h
+++ b/numpy/core/src/multiarray/buffer.h
@@ -9,4 +9,7 @@ _array_dealloc_buffer_info(PyArrayObject *self);
NPY_NO_EXPORT PyArray_Descr*
_descriptor_from_pep3118_format(char *s);
+NPY_NO_EXPORT int
+gentype_getbuffer(PyObject *obj, Py_buffer *view, int flags);
+
#endif
diff --git a/numpy/core/src/multiarray/common.c b/numpy/core/src/multiarray/common.c
index 10efdc4c8..f191f8db4 100644
--- a/numpy/core/src/multiarray/common.c
+++ b/numpy/core/src/multiarray/common.c
@@ -305,7 +305,8 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
memset(&buffer_view, 0, sizeof(Py_buffer));
if (PyObject_GetBuffer(obj, &buffer_view,
PyBUF_FORMAT|PyBUF_STRIDES) == 0 ||
- PyObject_GetBuffer(obj, &buffer_view, PyBUF_FORMAT) == 0) {
+ PyObject_GetBuffer(obj, &buffer_view,
+ PyBUF_FORMAT|PyBUF_SIMPLE) == 0) {
PyErr_Clear();
dtype = _descriptor_from_pep3118_format(buffer_view.format);
@@ -633,8 +634,12 @@ NPY_NO_EXPORT npy_bool
_IsWriteable(PyArrayObject *ap)
{
PyObject *base=PyArray_BASE(ap);
+#if defined(NPY_PY3K)
+ Py_buffer view;
+#else
void *dummy;
Py_ssize_t n;
+#endif
/* If we own our own data, then no-problem */
if ((base == NULL) || (PyArray_FLAGS(ap) & NPY_ARRAY_OWNDATA)) {
@@ -668,9 +673,18 @@ _IsWriteable(PyArrayObject *ap)
if (PyString_Check(base)) {
return NPY_TRUE;
}
+#if defined(NPY_PY3K)
+ if (PyObject_GetBuffer(base, &view, PyBUF_WRITABLE|PyBUF_SIMPLE) < 0) {
+ PyErr_Clear();
+ return NPY_FALSE;
+ }
+ PyBuffer_Release(&view);
+#else
if (PyObject_AsWriteBuffer(base, &dummy, &n) < 0) {
+ PyErr_Clear();
return NPY_FALSE;
}
+#endif
return NPY_TRUE;
}
diff --git a/numpy/core/src/multiarray/compiled_base.c b/numpy/core/src/multiarray/compiled_base.c
index 56bd65eed..5ee385c46 100644
--- a/numpy/core/src/multiarray/compiled_base.c
+++ b/numpy/core/src/multiarray/compiled_base.c
@@ -1402,7 +1402,11 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args)
{
PyObject *obj;
PyObject *str;
+ #if (PY_VERSION_HEX >= 0x030700A2)
+ const char *docstr;
+ #else
char *docstr;
+ #endif
static char *msg = "already has a docstring";
PyObject *tp_dict = PyArrayDescr_Type.tp_dict;
PyObject *myobj;
diff --git a/numpy/core/src/multiarray/conversion_utils.c b/numpy/core/src/multiarray/conversion_utils.c
index 2bb1cbfc1..7e92e5991 100644
--- a/numpy/core/src/multiarray/conversion_utils.c
+++ b/numpy/core/src/multiarray/conversion_utils.c
@@ -165,10 +165,12 @@ PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *buf)
}
#if defined(NPY_PY3K)
- if (PyObject_GetBuffer(obj, &view, PyBUF_ANY_CONTIGUOUS|PyBUF_WRITABLE) != 0) {
+ if (PyObject_GetBuffer(obj, &view,
+ PyBUF_ANY_CONTIGUOUS|PyBUF_WRITABLE|PyBUF_SIMPLE) != 0) {
PyErr_Clear();
buf->flags &= ~NPY_ARRAY_WRITEABLE;
- if (PyObject_GetBuffer(obj, &view, PyBUF_ANY_CONTIGUOUS) != 0) {
+ if (PyObject_GetBuffer(obj, &view,
+ PyBUF_ANY_CONTIGUOUS|PyBUF_SIMPLE) != 0) {
return NPY_FAIL;
}
}
@@ -177,8 +179,10 @@ PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *buf)
buf->len = (npy_intp) view.len;
/*
- * XXX: PyObject_AsWriteBuffer does also this, but it is unsafe, as there is
- * no strict guarantee that the buffer sticks around after being released.
+ * In Python 3 both of the deprecated functions PyObject_AsWriteBuffer and
+ * PyObject_AsReadBuffer that this code replaces release the buffer. It is
+ * up to the object that supplies the buffer to guarantee that the buffer
+ * sticks around after the release.
*/
PyBuffer_Release(&view);
@@ -415,6 +419,10 @@ PyArray_SortkindConverter(PyObject *obj, NPY_SORTKIND *sortkind)
else if (str[0] == 'm' || str[0] == 'M') {
*sortkind = NPY_MERGESORT;
}
+ else if (str[0] == 's' || str[0] == 'S') {
+ /* mergesort is the only stable sorting method in numpy */
+ *sortkind = NPY_MERGESORT;
+ }
else {
PyErr_Format(PyExc_ValueError,
"%s is an unrecognized kind of sort",
diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c
index 3d6b161b1..0eba077da 100644
--- a/numpy/core/src/multiarray/ctors.c
+++ b/numpy/core/src/multiarray/ctors.c
@@ -729,13 +729,16 @@ discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it,
/* PEP 3118 buffer interface */
if (PyObject_CheckBuffer(obj) == 1) {
memset(&buffer_view, 0, sizeof(Py_buffer));
- if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_STRIDES) == 0 ||
- PyObject_GetBuffer(obj, &buffer_view, PyBUF_ND) == 0) {
+ if (PyObject_GetBuffer(obj, &buffer_view,
+ PyBUF_STRIDES|PyBUF_SIMPLE) == 0 ||
+ PyObject_GetBuffer(obj, &buffer_view,
+ PyBUF_ND|PyBUF_SIMPLE) == 0) {
int nd = buffer_view.ndim;
+
if (nd < *maxndim) {
*maxndim = nd;
}
- for (i=0; i<*maxndim; i++) {
+ for (i = 0; i < *maxndim; i++) {
d[i] = buffer_view.shape[i];
}
PyBuffer_Release(&buffer_view);
@@ -756,6 +759,7 @@ discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it,
e = PyArray_LookupSpecial_OnInstance(obj, "__array_struct__");
if (e != NULL) {
int nd = -1;
+
if (NpyCapsule_Check(e)) {
PyArrayInterface *inter;
inter = (PyArrayInterface *)NpyCapsule_AsVoidPtr(e);
@@ -2187,7 +2191,11 @@ PyArray_FromInterface(PyObject *origin)
PyArrayObject *ret;
PyArray_Descr *dtype = NULL;
char *data = NULL;
+#if defined(NPY_PY3K)
+ Py_buffer view;
+#else
Py_ssize_t buffer_len;
+#endif
int res, i, n;
npy_intp dims[NPY_MAXDIMS], strides[NPY_MAXDIMS];
int dataflags = NPY_ARRAY_BEHAVED;
@@ -2217,7 +2225,7 @@ PyArray_FromInterface(PyObject *origin)
if (PyUnicode_Check(attr)) {
PyObject *tmp = PyUnicode_AsASCIIString(attr);
if (tmp == NULL) {
- goto fail;
+ goto fail;
}
attr = tmp;
}
@@ -2251,7 +2259,7 @@ PyArray_FromInterface(PyObject *origin)
dtype = new_dtype;
}
}
-
+
#if defined(NPY_PY3K)
Py_DECREF(attr); /* Pairs with the unicode handling above */
#endif
@@ -2335,6 +2343,25 @@ PyArray_FromInterface(PyObject *origin)
else {
base = origin;
}
+#if defined(NPY_PY3K)
+ if (PyObject_GetBuffer(base, &view,
+ PyBUF_WRITABLE|PyBUF_SIMPLE) < 0) {
+ PyErr_Clear();
+ if (PyObject_GetBuffer(base, &view,
+ PyBUF_SIMPLE) < 0) {
+ goto fail;
+ }
+ dataflags &= ~NPY_ARRAY_WRITEABLE;
+ }
+ data = (char *)view.buf;
+ /*
+ * In Python 3 both of the deprecated functions PyObject_AsWriteBuffer and
+ * PyObject_AsReadBuffer that this code replaces release the buffer. It is
+ * up to the object that supplies the buffer to guarantee that the buffer
+ * sticks around after the release.
+ */
+ PyBuffer_Release(&view);
+#else
res = PyObject_AsWriteBuffer(base, (void **)&data, &buffer_len);
if (res < 0) {
PyErr_Clear();
@@ -2345,6 +2372,7 @@ PyArray_FromInterface(PyObject *origin)
}
dataflags &= ~NPY_ARRAY_WRITEABLE;
}
+#endif
/* Get offset number from interface specification */
attr = PyDict_GetItemString(origin, "offset");
if (attr) {
@@ -3480,6 +3508,9 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
{
PyArrayObject *ret;
char *data;
+#if defined(NPY_PY3K)
+ Py_buffer view;
+#endif
Py_ssize_t ts;
npy_intp s, n;
int itemsize;
@@ -3519,6 +3550,26 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
Py_INCREF(buf);
}
+#if defined(NPY_PY3K)
+ if (PyObject_GetBuffer(buf, &view, PyBUF_WRITABLE|PyBUF_SIMPLE) < 0) {
+ writeable = 0;
+ PyErr_Clear();
+ if (PyObject_GetBuffer(buf, &view, PyBUF_SIMPLE) < 0) {
+ Py_DECREF(buf);
+ Py_DECREF(type);
+ return NULL;
+ }
+ }
+ data = (char *)view.buf;
+ ts = view.len;
+ /*
+ * In Python 3 both of the deprecated functions PyObject_AsWriteBuffer and
+ * PyObject_AsReadBuffer that this code replaces release the buffer. It is
+ * up to the object that supplies the buffer to guarantee that the buffer
+ * sticks around after the release.
+ */
+ PyBuffer_Release(&view);
+#else
if (PyObject_AsWriteBuffer(buf, (void *)&data, &ts) == -1) {
writeable = 0;
PyErr_Clear();
@@ -3528,6 +3579,7 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
return NULL;
}
}
+#endif
if ((offset < 0) || (offset > ts)) {
PyErr_Format(PyExc_ValueError,
diff --git a/numpy/core/src/multiarray/datetime_strings.c b/numpy/core/src/multiarray/datetime_strings.c
index 96cb66b95..4f9d8fa41 100644
--- a/numpy/core/src/multiarray/datetime_strings.c
+++ b/numpy/core/src/multiarray/datetime_strings.c
@@ -374,7 +374,7 @@ parse_iso_8601_datetime(char *str, Py_ssize_t len,
}
/* Leading '-' sign for negative year */
- if (*substr == '-') {
+ if (*substr == '-' || *substr == '+') {
++substr;
--sublen;
}
diff --git a/numpy/core/src/multiarray/einsum.c.src b/numpy/core/src/multiarray/einsum.c.src
index 7db606194..5dbc30aa9 100644
--- a/numpy/core/src/multiarray/einsum.c.src
+++ b/numpy/core/src/multiarray/einsum.c.src
@@ -1829,9 +1829,10 @@ parse_operand_subscripts(char *subscripts, int length,
break;
}
else {
- PyErr_SetString(PyExc_ValueError,
+ PyErr_Format(PyExc_ValueError,
"einstein sum subscripts string contains a "
- "'.' that is not part of an ellipsis ('...')");
+ "'.' that is not part of an ellipsis ('...') in "
+ "operand %d", iop);
return 0;
}
@@ -1888,6 +1889,12 @@ parse_operand_subscripts(char *subscripts, int length,
return 0;
}
}
+ else if (label == '.') {
+ PyErr_Format(PyExc_ValueError,
+ "einstein sum subscripts string contains a "
+ "'.' that is not part of an ellipsis ('...') in "
+ "operand %d", iop);
+ }
else if (label != ' ') {
PyErr_Format(PyExc_ValueError,
"invalid subscript '%c' in einstein sum "
@@ -2011,7 +2018,8 @@ parse_output_subscripts(char *subscripts, int length,
else {
PyErr_SetString(PyExc_ValueError,
"einstein sum subscripts string contains a "
- "'.' that is not part of an ellipsis ('...')");
+ "'.' that is not part of an ellipsis ('...') "
+ "in the output");
return -1;
}
@@ -2037,8 +2045,15 @@ parse_output_subscripts(char *subscripts, int length,
if (i > 0) {
for (i = 0; i < length; ++i) {
label = subscripts[i];
+ if (label == '.') {
+ PyErr_SetString(PyExc_ValueError,
+ "einstein sum subscripts string contains a "
+ "'.' that is not part of an ellipsis ('...') "
+ "in the output");
+ return -1;
+ }
/* A label for an axis */
- if (label != '.' && label != ' ') {
+ else if (label != ' ') {
if (idim < ndim_left) {
out_labels[idim++] = label;
}
@@ -2049,12 +2064,6 @@ parse_output_subscripts(char *subscripts, int length,
return -1;
}
}
- else {
- PyErr_SetString(PyExc_ValueError,
- "einstein sum subscripts string contains a "
- "'.' that is not part of an ellipsis ('...')");
- return -1;
- }
}
}
@@ -2185,7 +2194,7 @@ get_combined_dims_view(PyArrayObject *op, int iop, char *labels)
{
npy_intp new_strides[NPY_MAXDIMS];
npy_intp new_dims[NPY_MAXDIMS];
- int i, idim, ndim, icombine, combineoffset, label;
+ int idim, ndim, icombine, combineoffset;
int icombinemap[NPY_MAXDIMS];
PyArrayObject *ret = NULL;
@@ -2205,7 +2214,7 @@ get_combined_dims_view(PyArrayObject *op, int iop, char *labels)
* The char type may be either signed or unsigned, we
* need it to be signed here.
*/
- label = (signed char)labels[idim];
+ int label = (signed char)labels[idim];
/* If this label says to merge axes, get the actual label */
if (label < 0) {
combineoffset = label;
@@ -2225,7 +2234,7 @@ get_combined_dims_view(PyArrayObject *op, int iop, char *labels)
}
else {
/* Update the combined axis dimensions and strides */
- i = idim + combineoffset;
+ int i = icombinemap[idim + combineoffset];
if (combineoffset < 0 && new_dims[i] != 0 &&
new_dims[i] != PyArray_DIM(op, idim)) {
PyErr_Format(PyExc_ValueError,
@@ -2235,7 +2244,6 @@ get_combined_dims_view(PyArrayObject *op, int iop, char *labels)
(int)PyArray_DIM(op, idim));
return NULL;
}
- i = icombinemap[i];
new_dims[i] = PyArray_DIM(op, idim);
new_strides[i] += PyArray_STRIDE(op, idim);
}
diff --git a/numpy/core/src/multiarray/flagsobject.c b/numpy/core/src/multiarray/flagsobject.c
index d3dcc934f..a78bedccb 100644
--- a/numpy/core/src/multiarray/flagsobject.c
+++ b/numpy/core/src/multiarray/flagsobject.c
@@ -575,7 +575,7 @@ arrayflags_getitem(PyArrayFlagsObject *self, PyObject *ind)
return arrayflags_fortran_get(self);
}
break;
- case 14:
+ case 15:
if (strncmp(key, "WRITEBACKIFCOPY", n) == 0) {
return arrayflags_writebackifcopy_get(self);
}
diff --git a/numpy/core/src/multiarray/getset.c b/numpy/core/src/multiarray/getset.c
index 825363f19..86e6e7a2f 100644
--- a/numpy/core/src/multiarray/getset.c
+++ b/numpy/core/src/multiarray/getset.c
@@ -106,8 +106,12 @@ array_strides_set(PyArrayObject *self, PyObject *obj)
npy_intp offset = 0;
npy_intp lower_offset = 0;
npy_intp upper_offset = 0;
+#if defined(NPY_PY3K)
+ Py_buffer view;
+#else
Py_ssize_t buf_len;
char *buf;
+#endif
if (obj == NULL) {
PyErr_SetString(PyExc_AttributeError,
@@ -132,12 +136,21 @@ array_strides_set(PyArrayObject *self, PyObject *obj)
* Get the available memory through the buffer interface on
* PyArray_BASE(new) or if that fails from the current new
*/
- if (PyArray_BASE(new) && PyObject_AsReadBuffer(PyArray_BASE(new),
- (const void **)&buf,
- &buf_len) >= 0) {
+#if defined(NPY_PY3K)
+ if (PyArray_BASE(new) &&
+ PyObject_GetBuffer(PyArray_BASE(new), &view, PyBUF_SIMPLE) >= 0) {
+ offset = PyArray_BYTES(self) - (char *)view.buf;
+ numbytes = view.len + offset;
+ PyBuffer_Release(&view);
+ }
+#else
+ if (PyArray_BASE(new) &&
+ PyObject_AsReadBuffer(PyArray_BASE(new), (const void **)&buf,
+ &buf_len) >= 0) {
offset = PyArray_BYTES(self) - buf;
numbytes = buf_len + offset;
}
+#endif
else {
PyErr_Clear();
offset_bounds_from_strides(PyArray_ITEMSIZE(new), PyArray_NDIM(new),
@@ -328,6 +341,9 @@ array_data_set(PyArrayObject *self, PyObject *op)
void *buf;
Py_ssize_t buf_len;
int writeable=1;
+#if defined(NPY_PY3K)
+ Py_buffer view;
+#endif
/* 2016-19-02, 1.12 */
int ret = DEPRECATE("Assigning the 'data' attribute is an "
@@ -342,18 +358,38 @@ array_data_set(PyArrayObject *self, PyObject *op)
"Cannot delete array data");
return -1;
}
+#if defined(NPY_PY3K)
+ if (PyObject_GetBuffer(op, &view, PyBUF_WRITABLE|PyBUF_SIMPLE) < 0) {
+ writeable = 0;
+ PyErr_Clear();
+ if (PyObject_GetBuffer(op, &view, PyBUF_SIMPLE) < 0) {
+ return -1;
+ }
+ }
+ buf = view.buf;
+ buf_len = view.len;
+ /*
+ * In Python 3 both of the deprecated functions PyObject_AsWriteBuffer and
+ * PyObject_AsReadBuffer that this code replaces release the buffer. It is
+ * up to the object that supplies the buffer to guarantee that the buffer
+ * sticks around after the release.
+ */
+ PyBuffer_Release(&view);
+#else
if (PyObject_AsWriteBuffer(op, &buf, &buf_len) < 0) {
+ PyErr_Clear();
writeable = 0;
if (PyObject_AsReadBuffer(op, (const void **)&buf, &buf_len) < 0) {
+ PyErr_Clear();
PyErr_SetString(PyExc_AttributeError,
- "object does not have single-segment " \
- "buffer interface");
+ "object does not have single-segment buffer interface");
return -1;
}
}
+#endif
if (!PyArray_ISONESEGMENT(self)) {
- PyErr_SetString(PyExc_AttributeError, "cannot set single-" \
- "segment buffer for discontiguous array");
+ PyErr_SetString(PyExc_AttributeError,
+ "cannot set single-segment buffer for discontiguous array");
return -1;
}
if (PyArray_NBYTES(self) > buf_len) {
diff --git a/numpy/core/src/multiarray/methods.c b/numpy/core/src/multiarray/methods.c
index cd88ab76b..004af8a70 100644
--- a/numpy/core/src/multiarray/methods.c
+++ b/numpy/core/src/multiarray/methods.c
@@ -2305,7 +2305,7 @@ array_setflags(PyArrayObject *self, PyObject *args, PyObject *kwds)
}
else {
PyErr_SetString(PyExc_ValueError,
- "cannot set aligned flag of mis-"\
+ "cannot set aligned flag of mis-"
"aligned array to True");
return NULL;
}
@@ -2315,7 +2315,7 @@ array_setflags(PyArrayObject *self, PyObject *args, PyObject *kwds)
if (PyObject_IsTrue(uic)) {
fa->flags = flagback;
PyErr_SetString(PyExc_ValueError,
- "cannot set WRITEBACKIFCOPY " \
+ "cannot set WRITEBACKIFCOPY "
"flag to True");
return NULL;
}
diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src
index 3e17ec040..9df635dee 100644
--- a/numpy/core/src/multiarray/scalartypes.c.src
+++ b/numpy/core/src/multiarray/scalartypes.c.src
@@ -28,6 +28,7 @@
#include "npy_import.h"
#include "dragon4.h"
#include "npy_longdouble.h"
+#include "buffer.h"
#include <stdlib.h>
@@ -1842,6 +1843,9 @@ static PyObject *
gentype_reduce(PyObject *self, PyObject *NPY_UNUSED(args))
{
PyObject *ret = NULL, *obj = NULL, *mod = NULL;
+#if defined(NPY_PY3K)
+ Py_buffer view;
+#endif
const char *buffer;
Py_ssize_t buflen;
@@ -1850,18 +1854,35 @@ gentype_reduce(PyObject *self, PyObject *NPY_UNUSED(args))
if (ret == NULL) {
return NULL;
}
+
#if defined(NPY_PY3K)
if (PyArray_IsScalar(self, Unicode)) {
/* Unicode on Python 3 does not expose the buffer interface */
buffer = PyUnicode_AS_DATA(self);
buflen = PyUnicode_GET_DATA_SIZE(self);
}
- else
-#endif
+ else if (PyObject_GetBuffer(self, &view, PyBUF_SIMPLE) >= 0) {
+ buffer = view.buf;
+ buflen = view.len;
+ /*
+ * In Python 3 both of the deprecated functions PyObject_AsWriteBuffer and
+ * PyObject_AsReadBuffer that this code replaces release the buffer. It is
+ * up to the object that supplies the buffer to guarantee that the buffer
+ * sticks around after the release.
+ */
+ PyBuffer_Release(&view);
+ }
+ else {
+ Py_DECREF(ret);
+ return NULL;
+ }
+#else
if (PyObject_AsReadBuffer(self, (const void **)&buffer, &buflen)<0) {
Py_DECREF(ret);
return NULL;
}
+#endif
+
mod = PyImport_ImportModule("numpy.core.multiarray");
if (mod == NULL) {
return NULL;
@@ -2506,22 +2527,6 @@ gentype_getcharbuf(PyObject *self, Py_ssize_t segment, constchar **ptrptr)
}
#endif /* !defined(NPY_PY3K) */
-
-static int
-gentype_getbuffer(PyObject *self, Py_buffer *view, int flags)
-{
- Py_ssize_t len;
- void *buf;
-
- /* FIXME: XXX: the format is not implemented! -- this needs more work */
-
- len = gentype_getreadbuf(self, 0, &buf);
- return PyBuffer_FillInfo(view, self, buf, len, 1, flags);
-}
-
-/* releasebuffer is not needed */
-
-
static PyBufferProcs gentype_as_buffer = {
#if !defined(NPY_PY3K)
gentype_getreadbuf, /* bf_getreadbuffer*/
diff --git a/numpy/core/src/multiarray/shape.c b/numpy/core/src/multiarray/shape.c
index 29c122bd3..05c24d6da 100644
--- a/numpy/core/src/multiarray/shape.c
+++ b/numpy/core/src/multiarray/shape.c
@@ -1078,7 +1078,7 @@ build_shape_string(npy_intp n, npy_intp *vals)
* WARNING: If an axis flagged for removal has a shape equal to zero,
* the array will point to invalid memory. The caller must
* validate this!
- * If an axis flagged for removal has a shape larger then one,
+ * If an axis flagged for removal has a shape larger than one,
* the aligned flag (and in the future the contiguous flags),
* may need explicit update.
* (check also NPY_RELAXED_STRIDES_CHECKING)
diff --git a/numpy/core/src/npymath/npy_math_complex.c.src b/numpy/core/src/npymath/npy_math_complex.c.src
index ea784ec5b..cf427dad8 100644
--- a/numpy/core/src/npymath/npy_math_complex.c.src
+++ b/numpy/core/src/npymath/npy_math_complex.c.src
@@ -1526,9 +1526,13 @@ const npy_float SQRT_MIN = 1.0842022e-19f;
const npy_double SQRT_MIN = 1.4916681462400413e-154; /* sqrt(DBL_MIN) */
#endif
#if @precision@ == 3
+#if NPY_SIZEOF_LONGDOUBLE == NPY_SIZEOF_DOUBLE
+const npy_longdouble SQRT_MIN = 1.4916681462400413e-154; /* sqrt(DBL_MIN) */
+#else
/* this is correct for 80 bit long doubles */
const npy_longdouble SQRT_MIN = 1.8336038675548471656e-2466l;
#endif
+#endif
/* Avoid underflow when y is small. */
if (y < SQRT_MIN) {
return (x * x);
diff --git a/numpy/core/src/umath/operand_flag_tests.c.src b/numpy/core/src/umath/_operand_flag_tests.c.src
index 046c37595..551a9c632 100644
--- a/numpy/core/src/umath/operand_flag_tests.c.src
+++ b/numpy/core/src/umath/_operand_flag_tests.c.src
@@ -42,7 +42,7 @@ static void *data[1] = {NULL};
#if defined(NPY_PY3K)
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
- "operand_flag_tests",
+ "_operand_flag_tests",
NULL,
-1,
TestMethods,
@@ -53,11 +53,11 @@ static struct PyModuleDef moduledef = {
};
#define RETVAL m
-PyMODINIT_FUNC PyInit_operand_flag_tests(void)
+PyMODINIT_FUNC PyInit__operand_flag_tests(void)
{
#else
#define RETVAL
-PyMODINIT_FUNC initoperand_flag_tests(void)
+PyMODINIT_FUNC init_operand_flag_tests(void)
{
#endif
PyObject *m = NULL;
@@ -66,7 +66,7 @@ PyMODINIT_FUNC initoperand_flag_tests(void)
#if defined(NPY_PY3K)
m = PyModule_Create(&moduledef);
#else
- m = Py_InitModule("operand_flag_tests", TestMethods);
+ m = Py_InitModule("_operand_flag_tests", TestMethods);
#endif
if (m == NULL) {
goto fail;
@@ -92,7 +92,7 @@ PyMODINIT_FUNC initoperand_flag_tests(void)
fail:
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError,
- "cannot load operand_flag_tests module.");
+ "cannot load _operand_flag_tests module.");
}
#if defined(NPY_PY3K)
if (m) {
diff --git a/numpy/core/src/umath/test_rational.c.src b/numpy/core/src/umath/_rational_tests.c.src
index ffc92b732..9e74845df 100644
--- a/numpy/core/src/umath/test_rational.c.src
+++ b/numpy/core/src/umath/_rational_tests.c.src
@@ -1129,7 +1129,7 @@ PyMethodDef module_methods[] = {
#if defined(NPY_PY3K)
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
- "test_rational",
+ "_rational_tests",
NULL,
-1,
module_methods,
@@ -1142,10 +1142,10 @@ static struct PyModuleDef moduledef = {
#if defined(NPY_PY3K)
#define RETVAL m
-PyMODINIT_FUNC PyInit_test_rational(void) {
+PyMODINIT_FUNC PyInit__rational_tests(void) {
#else
#define RETVAL
-PyMODINIT_FUNC inittest_rational(void) {
+PyMODINIT_FUNC init_rational_tests(void) {
#endif
PyObject *m = NULL;
@@ -1295,7 +1295,7 @@ PyMODINIT_FUNC inittest_rational(void) {
#if defined(NPY_PY3K)
m = PyModule_Create(&moduledef);
#else
- m = Py_InitModule("test_rational", module_methods);
+ m = Py_InitModule("_rational_tests", module_methods);
#endif
if (!m) {
@@ -1397,7 +1397,7 @@ PyMODINIT_FUNC inittest_rational(void) {
fail:
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError,
- "cannot load test_rational module.");
+ "cannot load _rational_tests module.");
}
#if defined(NPY_PY3K)
if (m) {
diff --git a/numpy/core/src/umath/struct_ufunc_test.c.src b/numpy/core/src/umath/_struct_ufunc_tests.c.src
index 9a6318f47..b831d5c2a 100644
--- a/numpy/core/src/umath/struct_ufunc_test.c.src
+++ b/numpy/core/src/umath/_struct_ufunc_tests.c.src
@@ -56,7 +56,7 @@ static void add_uint64_triplet(char **args, npy_intp *dimensions,
#if defined(NPY_PY3K)
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
- "struct_ufunc_test",
+ "_struct_ufunc_tests",
NULL,
-1,
StructUfuncTestMethods,
@@ -68,9 +68,9 @@ static struct PyModuleDef moduledef = {
#endif
#if defined(NPY_PY3K)
-PyMODINIT_FUNC PyInit_struct_ufunc_test(void)
+PyMODINIT_FUNC PyInit__struct_ufunc_tests(void)
#else
-PyMODINIT_FUNC initstruct_ufunc_test(void)
+PyMODINIT_FUNC init_struct_ufunc_tests(void)
#endif
{
PyObject *m, *add_triplet, *d;
@@ -81,7 +81,7 @@ PyMODINIT_FUNC initstruct_ufunc_test(void)
#if defined(NPY_PY3K)
m = PyModule_Create(&moduledef);
#else
- m = Py_InitModule("struct_ufunc_test", StructUfuncTestMethods);
+ m = Py_InitModule("_struct_ufunc_tests", StructUfuncTestMethods);
#endif
if (m == NULL) {
diff --git a/numpy/core/src/umath/umath_tests.c.src b/numpy/core/src/umath/_umath_tests.c.src
index 8d9009a1a..120ce0332 100644
--- a/numpy/core/src/umath/umath_tests.c.src
+++ b/numpy/core/src/umath/_umath_tests.c.src
@@ -360,7 +360,7 @@ static PyMethodDef UMath_TestsMethods[] = {
#if defined(NPY_PY3K)
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
- "umath_tests",
+ "_umath_tests",
NULL,
-1,
UMath_TestsMethods,
@@ -373,11 +373,11 @@ static struct PyModuleDef moduledef = {
#if defined(NPY_PY3K)
#define RETVAL m
-PyMODINIT_FUNC PyInit_umath_tests(void)
+PyMODINIT_FUNC PyInit__umath_tests(void)
#else
#define RETVAL
PyMODINIT_FUNC
-initumath_tests(void)
+init_umath_tests(void)
#endif
{
PyObject *m;
@@ -387,7 +387,7 @@ initumath_tests(void)
#if defined(NPY_PY3K)
m = PyModule_Create(&moduledef);
#else
- m = Py_InitModule("umath_tests", UMath_TestsMethods);
+ m = Py_InitModule("_umath_tests", UMath_TestsMethods);
#endif
if (m == NULL)
return RETVAL;
@@ -406,7 +406,7 @@ initumath_tests(void)
if (PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError,
- "cannot load umath_tests module.");
+ "cannot load _umath_tests module.");
}
return RETVAL;
diff --git a/numpy/core/src/umath/cpuid.c b/numpy/core/src/umath/cpuid.c
new file mode 100644
index 000000000..912d51eeb
--- /dev/null
+++ b/numpy/core/src/umath/cpuid.c
@@ -0,0 +1,56 @@
+#define _UMATHMODULE
+#define NPY_NO_DEPRECATED_API NPY_API_VERSION
+
+#include <Python.h>
+
+#include "npy_config.h"
+
+#define PY_ARRAY_UNIQUE_SYMBOL _npy_umathmodule_ARRAY_API
+#define NO_IMPORT_ARRAY
+
+#include "cpuid.h"
+
+#define XCR_XFEATURE_ENABLED_MASK 0x0
+#define XSTATE_SSE 0x2
+#define XSTATE_YMM 0x4
+
+/*
+ * verify the OS supports avx instructions
+ * it can be disabled in some OS, e.g. with the nosavex boot option of linux
+ */
+static NPY_INLINE
+int os_avx_support(void)
+{
+#if HAVE_XGETBV
+ /*
+ * use bytes for xgetbv to avoid issues with compiler not knowing the
+ * instruction
+ */
+ unsigned int eax, edx;
+ unsigned int ecx = XCR_XFEATURE_ENABLED_MASK;
+ __asm__("xgetbv" : "=a" (eax), "=d" (edx) : "c" (ecx));
+ return (eax & (XSTATE_SSE | XSTATE_YMM)) == (XSTATE_SSE | XSTATE_YMM);
+#else
+ return 0;
+#endif
+}
+
+
+/*
+ * Primitive cpu feature detect function
+ * Currently only supports checking for avx on gcc compatible compilers.
+ */
+NPY_NO_EXPORT int
+npy_cpu_supports(const char * feature)
+{
+#ifdef HAVE___BUILTIN_CPU_SUPPORTS
+ if (strcmp(feature, "avx2") == 0) {
+ return __builtin_cpu_supports("avx2") && os_avx_support();
+ }
+ else if (strcmp(feature, "avx") == 0) {
+ return __builtin_cpu_supports("avx") && os_avx_support();
+ }
+#endif
+
+ return 0;
+}
diff --git a/numpy/core/src/umath/cpuid.h b/numpy/core/src/umath/cpuid.h
new file mode 100644
index 000000000..33702ed41
--- /dev/null
+++ b/numpy/core/src/umath/cpuid.h
@@ -0,0 +1,9 @@
+#ifndef _NPY_PRIVATE__CPUID_H_
+#define _NPY_PRIVATE__CPUID_H_
+
+#include <numpy/ndarraytypes.h> /* for NPY_NO_EXPORT */
+
+NPY_NO_EXPORT int
+npy_cpu_supports(const char * feature);
+
+#endif
diff --git a/numpy/core/src/umath/scalarmath.c.src b/numpy/core/src/umath/scalarmath.c.src
index 7b424cc74..6e1fb1ee8 100644
--- a/numpy/core/src/umath/scalarmath.c.src
+++ b/numpy/core/src/umath/scalarmath.c.src
@@ -274,9 +274,6 @@ static void
* #type = npy_float, npy_double, npy_longdouble#
* #c = f, , l#
*/
-static @type@ (*_basic_@name@_sqrt)(@type@);
-static @type@ (*_basic_@name@_fmod)(@type@, @type@);
-
#define @name@_ctype_add(a, b, outp) *(outp) = (a) + (b)
#define @name@_ctype_subtract(a, b, outp) *(outp) = (a) - (b)
#define @name@_ctype_multiply(a, b, outp) *(outp) = (a) * (b)
@@ -306,9 +303,6 @@ static void
/**end repeat**/
-static npy_half (*_basic_half_sqrt)(npy_half);
-static npy_half (*_basic_half_fmod)(npy_half, npy_half);
-
#define half_ctype_add(a, b, outp) *(outp) = \
npy_float_to_half(npy_half_to_float(a) + npy_half_to_float(b))
#define half_ctype_subtract(a, b, outp) *(outp) = \
@@ -1693,49 +1687,6 @@ get_functions(PyObject * mm)
_basic_clongdouble_pow = funcdata[j + 5];
Py_DECREF(obj);
- /* Get the sqrt functions */
- obj = PyObject_GetAttrString(mm, "sqrt");
- if (obj == NULL) {
- goto fail;
- }
- funcdata = ((PyUFuncObject *)obj)->data;
- signatures = ((PyUFuncObject *)obj)->types;
- /*
- * sqrt ufunc is specialized for double and float loops in
- * generate_umath.py, the first to go into FLOAT/DOUBLE_sqrt
- * they have the same signature as the scalar variants so we need to skip
- * over them
- * also skip float16 copy placed before
- */
- i = 6;
- j = 3;
- while (signatures[i] != NPY_FLOAT) {
- i += 2; j++;
- }
- _basic_half_sqrt = funcdata[j - 1];
- _basic_float_sqrt = funcdata[j];
- _basic_double_sqrt = funcdata[j + 1];
- _basic_longdouble_sqrt = funcdata[j + 2];
- Py_DECREF(obj);
-
- /* Get the fmod functions */
- obj = PyObject_GetAttrString(mm, "fmod");
- if (obj == NULL) {
- goto fail;
- }
- funcdata = ((PyUFuncObject *)obj)->data;
- signatures = ((PyUFuncObject *)obj)->types;
- i = 0;
- j = 0;
- while (signatures[i] != NPY_FLOAT) {
- i += 3;
- j++;
- }
- _basic_half_fmod = funcdata[j - 1];
- _basic_float_fmod = funcdata[j];
- _basic_double_fmod = funcdata[j + 1];
- _basic_longdouble_fmod = funcdata[j + 2];
- Py_DECREF(obj);
return ret = 0;
fail:
diff --git a/numpy/core/tests/_locales.py b/numpy/core/tests/_locales.py
new file mode 100644
index 000000000..28eebb14d
--- /dev/null
+++ b/numpy/core/tests/_locales.py
@@ -0,0 +1,76 @@
+"""Provide class for testing in French locale
+
+"""
+from __future__ import division, absolute_import, print_function
+
+import sys
+import locale
+
+from numpy.testing import SkipTest
+
+__ALL__ = ['CommaDecimalPointLocale']
+
+
+def find_comma_decimal_point_locale():
+ """See if platform has a decimal point as comma locale.
+
+ Find a locale that uses a comma instead of a period as the
+ decimal point.
+
+ Returns
+ -------
+ old_locale: str
+ Locale when the function was called.
+ new_locale: {str, None)
+ First French locale found, None if none found.
+
+ """
+ if sys.platform == 'win32':
+ locales = ['FRENCH']
+ else:
+ locales = ['fr_FR', 'fr_FR.UTF-8', 'fi_FI', 'fi_FI.UTF-8']
+
+ old_locale = locale.getlocale(locale.LC_NUMERIC)
+ new_locale = None
+ try:
+ for loc in locales:
+ try:
+ locale.setlocale(locale.LC_NUMERIC, loc)
+ new_locale = loc
+ break
+ except locale.Error:
+ pass
+ finally:
+ locale.setlocale(locale.LC_NUMERIC, locale=old_locale)
+ return old_locale, new_locale
+
+
+class CommaDecimalPointLocale(object):
+ """Sets LC_NUMERIC to a locale with comma as decimal point.
+
+ Classes derived from this class have setup and teardown methods that run
+ tests with locale.LC_NUMERIC set to a locale where commas (',') are used as
+ the decimal point instead of periods ('.'). On exit the locale is restored
+ to the initial locale. It also serves as context manager with the same
+ effect. If no such locale is available, it raises SkipTest in both cases.
+
+ .. versionadded:: 1.15.0
+
+ """
+ (cur_locale, tst_locale) = find_comma_decimal_point_locale()
+
+ def setup(self):
+ if self.tst_locale is None:
+ raise SkipTest("No French locale available")
+ locale.setlocale(locale.LC_NUMERIC, locale=self.tst_locale)
+
+ def teardown(self):
+ locale.setlocale(locale.LC_NUMERIC, locale=self.cur_locale)
+
+ def __enter__(self):
+ if self.tst_locale is None:
+ raise SkipTest("No French locale available")
+ locale.setlocale(locale.LC_NUMERIC, locale=self.tst_locale)
+
+ def __exit__(self, type, value, traceback):
+ locale.setlocale(locale.LC_NUMERIC, locale=self.cur_locale)
diff --git a/numpy/core/tests/test_arrayprint.py b/numpy/core/tests/test_arrayprint.py
index 309df8545..6c2403e67 100644
--- a/numpy/core/tests/test_arrayprint.py
+++ b/numpy/core/tests/test_arrayprint.py
@@ -5,7 +5,7 @@ import sys, gc
import numpy as np
from numpy.testing import (
- run_module_suite, assert_, assert_equal, assert_raises, assert_warns, dec
+ run_module_suite, assert_, assert_equal, assert_raises, assert_warns, dec,
)
import textwrap
@@ -388,6 +388,7 @@ class TestArray2String(object):
"[ 'xxxxx']"
)
+ @dec._needs_refcount
def test_refcount(self):
# make sure we do not hold references to the array due to a recursive
# closure (gh-10620)
diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py
index 638994aee..ba291737a 100644
--- a/numpy/core/tests/test_datetime.py
+++ b/numpy/core/tests/test_datetime.py
@@ -1255,12 +1255,19 @@ class TestDateTime(object):
# Allow space instead of 'T' between date and time
assert_equal(np.array(['1980-02-29T01:02:03'], np.dtype('M8[s]')),
np.array(['1980-02-29 01:02:03'], np.dtype('M8[s]')))
+ # Allow positive years
+ assert_equal(np.array(['+1980-02-29T01:02:03'], np.dtype('M8[s]')),
+ np.array(['+1980-02-29 01:02:03'], np.dtype('M8[s]')))
# Allow negative years
assert_equal(np.array(['-1980-02-29T01:02:03'], np.dtype('M8[s]')),
np.array(['-1980-02-29 01:02:03'], np.dtype('M8[s]')))
# UTC specifier
with assert_warns(DeprecationWarning):
assert_equal(
+ np.array(['+1980-02-29T01:02:03'], np.dtype('M8[s]')),
+ np.array(['+1980-02-29 01:02:03Z'], np.dtype('M8[s]')))
+ with assert_warns(DeprecationWarning):
+ assert_equal(
np.array(['-1980-02-29T01:02:03'], np.dtype('M8[s]')),
np.array(['-1980-02-29 01:02:03Z'], np.dtype('M8[s]')))
# Time zone offset
diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py
index fe0c7cc5f..2c2900e6c 100644
--- a/numpy/core/tests/test_deprecations.py
+++ b/numpy/core/tests/test_deprecations.py
@@ -429,7 +429,7 @@ class TestNonNumericConjugate(_DeprecationTestCase):
class TestNPY_CHAR(_DeprecationTestCase):
# 2017-05-03, 1.13.0
def test_npy_char_deprecation(self):
- from numpy.core.multiarray_tests import npy_char_deprecation
+ from numpy.core._multiarray_tests import npy_char_deprecation
self.assert_deprecated(npy_char_deprecation)
assert_(npy_char_deprecation() == 'S1')
@@ -440,11 +440,11 @@ class Test_UPDATEIFCOPY(_DeprecationTestCase):
WRITEBACKIFCOPY instead
"""
def test_npy_updateifcopy_deprecation(self):
- from numpy.core.multiarray_tests import npy_updateifcopy_deprecation
+ from numpy.core._multiarray_tests import npy_updateifcopy_deprecation
arr = np.arange(9).reshape(3, 3)
v = arr.T
self.assert_deprecated(npy_updateifcopy_deprecation, args=(v,))
-
+
class TestDatetimeEvent(_DeprecationTestCase):
# 2017-08-11, 1.14.0
diff --git a/numpy/core/tests/test_dtype.py b/numpy/core/tests/test_dtype.py
index 2f997b4f7..c924e6f43 100644
--- a/numpy/core/tests/test_dtype.py
+++ b/numpy/core/tests/test_dtype.py
@@ -5,7 +5,7 @@ import sys
import operator
import numpy as np
-from numpy.core.test_rational import rational
+from numpy.core._rational_tests import rational
from numpy.testing import (
run_module_suite, assert_, assert_equal, assert_raises,
dec
diff --git a/numpy/core/tests/test_einsum.py b/numpy/core/tests/test_einsum.py
index 9bd85fdb9..406b10eab 100644
--- a/numpy/core/tests/test_einsum.py
+++ b/numpy/core/tests/test_einsum.py
@@ -1,5 +1,7 @@
from __future__ import division, absolute_import, print_function
+import itertools
+
import numpy as np
from numpy.testing import (
run_module_suite, assert_, assert_equal, assert_array_equal,
@@ -791,6 +793,12 @@ class TestEinSum(object):
self.optimize_compare('dba,ead,cad->bce')
self.optimize_compare('aef,fbc,dca->bde')
+ def test_combined_views_mapping(self):
+ # gh-10792
+ a = np.arange(9).reshape(1, 1, 3, 1, 3)
+ b = np.einsum('bbcdc->d', a)
+ assert_equal(b, [12])
+
class TestEinSumPath(object):
def build_operands(self, string, size_dict=global_size_dict):
@@ -918,6 +926,13 @@ class TestEinSumPath(object):
opt = np.einsum(*path_test, optimize=exp_path)
assert_almost_equal(noopt, opt)
+ def test_spaces(self):
+ #gh-10794
+ arr = np.array([[1]])
+ for sp in itertools.product(['', ' '], repeat=4):
+ # no error for any spacing
+ np.einsum('{}...a{}->{}...a{}'.format(*sp), arr)
+
if __name__ == "__main__":
run_module_suite()
diff --git a/numpy/core/tests/test_extint128.py b/numpy/core/tests/test_extint128.py
index d87585dcf..31786124d 100644
--- a/numpy/core/tests/test_extint128.py
+++ b/numpy/core/tests/test_extint128.py
@@ -6,7 +6,7 @@ import contextlib
import operator
import numpy as np
-import numpy.core.multiarray_tests as mt
+import numpy.core._multiarray_tests as mt
from numpy.compat import long
from numpy.testing import assert_raises, assert_equal, dec
diff --git a/numpy/core/tests/test_indexing.py b/numpy/core/tests/test_indexing.py
index cd4ea611a..082ecb496 100644
--- a/numpy/core/tests/test_indexing.py
+++ b/numpy/core/tests/test_indexing.py
@@ -6,7 +6,7 @@ import functools
import operator
import numpy as np
-from numpy.core.multiarray_tests import array_indexing
+from numpy.core._multiarray_tests import array_indexing
from itertools import product
from numpy.testing import (
run_module_suite, assert_, assert_equal, assert_raises,
@@ -14,20 +14,6 @@ from numpy.testing import (
)
-try:
- cdll = None
- if hasattr(sys, 'gettotalrefcount'):
- try:
- cdll = np.ctypeslib.load_library('multiarray_d', np.core.multiarray.__file__)
- except OSError:
- pass
- if cdll is None:
- cdll = np.ctypeslib.load_library('multiarray', np.core.multiarray.__file__)
- _HAS_CTYPE = True
-except ImportError:
- _HAS_CTYPE = False
-
-
class TestIndexing(object):
def test_index_no_floats(self):
a = np.array([[[5]]])
@@ -513,7 +499,7 @@ class TestIndexing(object):
arro = np.zeros((4, 4))
arr = arro[::-1, ::-1]
- slices = [slice(None), [0, 1, 2, 3]]
+ slices = (slice(None), [0, 1, 2, 3])
arr[slices] = 10
assert_array_equal(arr, 10.)
@@ -622,7 +608,7 @@ class TestSubclasses(object):
assert_array_equal(new_s.finalize_status, new_s)
assert_array_equal(new_s.old, s)
- @dec.skipif(not HAS_REFCOUNT)
+ @dec._needs_refcount
def test_slice_decref_getsetslice(self):
# See gh-10066, a temporary slice object should be discarted.
# This test is only really interesting on Python 2 since
diff --git a/numpy/core/tests/test_longdouble.py b/numpy/core/tests/test_longdouble.py
index 625d40c1b..7cd5b04d8 100644
--- a/numpy/core/tests/test_longdouble.py
+++ b/numpy/core/tests/test_longdouble.py
@@ -7,7 +7,7 @@ from numpy.testing import (
run_module_suite, assert_, assert_equal, dec, assert_raises,
assert_array_equal, temppath,
)
-from .test_print import in_foreign_locale
+from ._locales import CommaDecimalPointLocale
LD_INFO = np.finfo(np.longdouble)
longdouble_longer_than_double = (LD_INFO.eps < np.finfo(np.double).eps)
@@ -50,25 +50,12 @@ def test_bytes():
np.longdouble(b"1.2")
-@in_foreign_locale
-def test_fromstring_foreign_repr():
- f = 1.234
- a = np.fromstring(repr(f), dtype=float, sep=" ")
- assert_equal(a[0], f)
-
-
@dec.knownfailureif(string_to_longdouble_inaccurate, "Need strtold_l")
def test_repr_roundtrip_bytes():
o = 1 + LD_INFO.eps
assert_equal(np.longdouble(repr(o).encode("ascii")), o)
-@in_foreign_locale
-def test_repr_roundtrip_foreign():
- o = 1.5
- assert_equal(o, np.longdouble(repr(o)))
-
-
def test_bogus_string():
assert_raises(ValueError, np.longdouble, "spam")
assert_raises(ValueError, np.longdouble, "1.0 flub")
@@ -83,18 +70,6 @@ def test_fromstring():
err_msg="reading '%s'" % s)
-@in_foreign_locale
-def test_fromstring_best_effort_float():
- assert_equal(np.fromstring("1,234", dtype=float, sep=" "),
- np.array([1.]))
-
-
-@in_foreign_locale
-def test_fromstring_best_effort():
- assert_equal(np.fromstring("1,234", dtype=np.longdouble, sep=" "),
- np.array([1.]))
-
-
def test_fromstring_bogus():
assert_equal(np.fromstring("1. 2. 3. flop 4.", dtype=float, sep=" "),
np.array([1., 2., 3.]))
@@ -155,26 +130,6 @@ class TestFileBased(object):
assert_equal(res, self.tgt)
-@in_foreign_locale
-def test_fromstring_foreign():
- s = "1.234"
- a = np.fromstring(s, dtype=np.longdouble, sep=" ")
- assert_equal(a[0], np.longdouble(s))
-
-
-@in_foreign_locale
-def test_fromstring_foreign_sep():
- a = np.array([1, 2, 3, 4])
- b = np.fromstring("1,2,3,4,", dtype=np.longdouble, sep=",")
- assert_array_equal(a, b)
-
-
-@in_foreign_locale
-def test_fromstring_foreign_value():
- b = np.fromstring("1,234", dtype=np.longdouble, sep=" ")
- assert_array_equal(b[0], 1)
-
-
# Conversions long double -> string
@@ -207,6 +162,43 @@ def test_array_repr():
raise ValueError("precision loss creating arrays")
assert_(repr(a) != repr(b))
+#
+# Locale tests: scalar types formatting should be independent of the locale
+#
+
+class TestCommaDecimalPointLocale(CommaDecimalPointLocale):
+
+ def test_repr_roundtrip_foreign(self):
+ o = 1.5
+ assert_equal(o, np.longdouble(repr(o)))
+
+ def test_fromstring_foreign_repr(self):
+ f = 1.234
+ a = np.fromstring(repr(f), dtype=float, sep=" ")
+ assert_equal(a[0], f)
+
+ def test_fromstring_best_effort_float(self):
+ assert_equal(np.fromstring("1,234", dtype=float, sep=" "),
+ np.array([1.]))
+
+ def test_fromstring_best_effort(self):
+ assert_equal(np.fromstring("1,234", dtype=np.longdouble, sep=" "),
+ np.array([1.]))
+
+ def test_fromstring_foreign(self):
+ s = "1.234"
+ a = np.fromstring(s, dtype=np.longdouble, sep=" ")
+ assert_equal(a[0], np.longdouble(s))
+
+ def test_fromstring_foreign_sep(self):
+ a = np.array([1, 2, 3, 4])
+ b = np.fromstring("1,2,3,4,", dtype=np.longdouble, sep=",")
+ assert_array_equal(a, b)
+
+ def test_fromstring_foreign_value(self):
+ b = np.fromstring("1,234", dtype=np.longdouble, sep=" ")
+ assert_array_equal(b[0], 1)
+
if __name__ == "__main__":
run_module_suite()
diff --git a/numpy/core/tests/test_mem_overlap.py b/numpy/core/tests/test_mem_overlap.py
index 9c17ed210..92baa0896 100644
--- a/numpy/core/tests/test_mem_overlap.py
+++ b/numpy/core/tests/test_mem_overlap.py
@@ -7,8 +7,8 @@ import numpy as np
from numpy.testing import (run_module_suite, assert_, assert_raises, assert_equal,
assert_array_equal, assert_allclose, dec)
-from numpy.core.multiarray_tests import solve_diophantine, internal_overlap
-from numpy.core import umath_tests
+from numpy.core._multiarray_tests import solve_diophantine, internal_overlap
+from numpy.core import _umath_tests
from numpy.lib.stride_tricks import as_strided
from numpy.compat import long
@@ -749,7 +749,7 @@ class TestUFunc(object):
def test_unary_gufunc_fuzz(self):
shapes = [7, 13, 8, 21, 29, 32]
- gufunc = umath_tests.euclidean_pdist
+ gufunc = _umath_tests.euclidean_pdist
rng = np.random.RandomState(1234)
diff --git a/numpy/core/tests/test_memmap.py b/numpy/core/tests/test_memmap.py
index 1cd09ab21..c00867ce1 100644
--- a/numpy/core/tests/test_memmap.py
+++ b/numpy/core/tests/test_memmap.py
@@ -126,7 +126,7 @@ class TestMemmap(object):
def test_indexing_drops_references(self):
fp = memmap(self.tmpfp, dtype=self.dtype, mode='w+',
shape=self.shape)
- tmp = fp[[(1, 2), (2, 3)]]
+ tmp = fp[(1, 2), (2, 3)]
if isinstance(tmp, memmap):
assert_(tmp._mmap is not fp._mmap)
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index 43bfb0635..d861da4b6 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -1,6 +1,11 @@
from __future__ import division, absolute_import, print_function
-import collections
+try:
+ # Accessing collections abstract classes from collections
+ # has been deprecated since Python 3.3
+ import collections.abc as collections_abc
+except ImportError:
+ import collections as collections_abc
import tempfile
import sys
import shutil
@@ -18,22 +23,17 @@ if sys.version_info[0] >= 3:
else:
import __builtin__ as builtins
from decimal import Decimal
-from unittest import TestCase
import numpy as np
from numpy.compat import strchar, unicode
-from numpy.core.tests.test_print import in_foreign_locale
-from numpy.core.multiarray_tests import (
- test_neighborhood_iterator, test_neighborhood_iterator_oob,
- test_pydatamem_seteventhook_start, test_pydatamem_seteventhook_end,
- test_inplace_increment, get_buffer_info, test_as_c_array,
- )
+import numpy.core._multiarray_tests as _multiarray_tests
from numpy.testing import (
run_module_suite, assert_, assert_raises, assert_warns,
assert_equal, assert_almost_equal, assert_array_equal, assert_raises_regex,
assert_array_almost_equal, assert_allclose, IS_PYPY, HAS_REFCOUNT,
assert_array_less, runstring, dec, SkipTest, temppath, suppress_warnings
)
+from ._locales import CommaDecimalPointLocale
# Need to test an object that does not fully implement math interface
from datetime import timedelta, datetime
@@ -101,8 +101,10 @@ class TestFlags(object):
assert_equal(self.a.flags.updateifcopy, False)
with assert_warns(DeprecationWarning):
assert_equal(self.a.flags['U'], False)
+ assert_equal(self.a.flags['UPDATEIFCOPY'], False)
assert_equal(self.a.flags.writebackifcopy, False)
assert_equal(self.a.flags['X'], False)
+ assert_equal(self.a.flags['WRITEBACKIFCOPY'], False)
def test_string_align(self):
@@ -189,7 +191,7 @@ class TestAttributes(object):
assert_equal(isinstance(numpy_int, int), True)
# ... and fast-path checks on C-API level should also work
- from numpy.core.multiarray_tests import test_int_subclass
+ from numpy.core._multiarray_tests import test_int_subclass
assert_equal(test_int_subclass(numpy_int), True)
def test_stridesattr(self):
@@ -3340,7 +3342,7 @@ class TestTemporaryElide(object):
# def incref_elide(a):
# d = input.copy() # refcount 1
# return d, d + d # PyNumber_Add without increasing refcount
- from numpy.core.multiarray_tests import incref_elide
+ from numpy.core._multiarray_tests import incref_elide
d = np.ones(100000)
orig, res = incref_elide(d)
d + d
@@ -3355,7 +3357,7 @@ class TestTemporaryElide(object):
#
# def incref_elide_l(d):
# return l[4] + l[4] # PyNumber_Add without increasing refcount
- from numpy.core.multiarray_tests import incref_elide_l
+ from numpy.core._multiarray_tests import incref_elide_l
# padding with 1 makes sure the object on the stack is not overwritten
l = [1, 1, 1, 1, np.ones(100000)]
res = incref_elide_l(l)
@@ -3434,7 +3436,7 @@ class TestTemporaryElide(object):
class TestCAPI(object):
def test_IsPythonScalar(self):
- from numpy.core.multiarray_tests import IsPythonScalar
+ from numpy.core._multiarray_tests import IsPythonScalar
assert_(IsPythonScalar(b'foobar'))
assert_(IsPythonScalar(1))
assert_(IsPythonScalar(2**80))
@@ -4471,14 +4473,15 @@ class TestIO(object):
assert_equal(s, '1.51,2.00,3.51,4.00')
def test_locale(self):
- in_foreign_locale(self.test_numbers)()
- in_foreign_locale(self.test_nan)()
- in_foreign_locale(self.test_inf)()
- in_foreign_locale(self.test_counted_string)()
- in_foreign_locale(self.test_ascii)()
- in_foreign_locale(self.test_malformed)()
- in_foreign_locale(self.test_tofile_sep)()
- in_foreign_locale(self.test_tofile_format)()
+ with CommaDecimalPointLocale():
+ self.test_numbers()
+ self.test_nan()
+ self.test_inf()
+ self.test_counted_string()
+ self.test_ascii()
+ self.test_malformed()
+ self.test_tofile_sep()
+ self.test_tofile_format()
class TestFromBuffer(object):
@@ -5350,8 +5353,6 @@ class TestDot(object):
class MatmulCommon(object):
"""Common tests for '@' operator and numpy.matmul.
- Do not derive from TestCase to avoid nose running it.
-
"""
# Should work with these types. Will want to add
# "O" at some point
@@ -5804,24 +5805,24 @@ class TestNeighborhoodIter(object):
np.array([[0, 0, 0], [0, 1, 0]], dtype=dt),
np.array([[0, 0, 1], [0, 2, 3]], dtype=dt),
np.array([[0, 1, 0], [2, 3, 0]], dtype=dt)]
- l = test_neighborhood_iterator(x, [-1, 0, -1, 1], x[0],
- NEIGH_MODE['zero'])
+ l = _multiarray_tests.test_neighborhood_iterator(
+ x, [-1, 0, -1, 1], x[0], NEIGH_MODE['zero'])
assert_array_equal(l, r)
r = [np.array([[1, 1, 1], [1, 0, 1]], dtype=dt),
np.array([[1, 1, 1], [0, 1, 1]], dtype=dt),
np.array([[1, 0, 1], [1, 2, 3]], dtype=dt),
np.array([[0, 1, 1], [2, 3, 1]], dtype=dt)]
- l = test_neighborhood_iterator(x, [-1, 0, -1, 1], x[0],
- NEIGH_MODE['one'])
+ l = _multiarray_tests.test_neighborhood_iterator(
+ x, [-1, 0, -1, 1], x[0], NEIGH_MODE['one'])
assert_array_equal(l, r)
r = [np.array([[4, 4, 4], [4, 0, 1]], dtype=dt),
np.array([[4, 4, 4], [0, 1, 4]], dtype=dt),
np.array([[4, 0, 1], [4, 2, 3]], dtype=dt),
np.array([[0, 1, 4], [2, 3, 4]], dtype=dt)]
- l = test_neighborhood_iterator(x, [-1, 0, -1, 1], 4,
- NEIGH_MODE['constant'])
+ l = _multiarray_tests.test_neighborhood_iterator(
+ x, [-1, 0, -1, 1], 4, NEIGH_MODE['constant'])
assert_array_equal(l, r)
def test_simple2d(self):
@@ -5836,8 +5837,8 @@ class TestNeighborhoodIter(object):
np.array([[0, 1, 1], [0, 1, 1]], dtype=dt),
np.array([[0, 0, 1], [2, 2, 3]], dtype=dt),
np.array([[0, 1, 1], [2, 3, 3]], dtype=dt)]
- l = test_neighborhood_iterator(x, [-1, 0, -1, 1], x[0],
- NEIGH_MODE['mirror'])
+ l = _multiarray_tests.test_neighborhood_iterator(
+ x, [-1, 0, -1, 1], x[0], NEIGH_MODE['mirror'])
assert_array_equal(l, r)
def test_mirror2d(self):
@@ -5851,15 +5852,18 @@ class TestNeighborhoodIter(object):
# Test padding with constant values
x = np.linspace(1, 5, 5).astype(dt)
r = [[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 0]]
- l = test_neighborhood_iterator(x, [-1, 1], x[0], NEIGH_MODE['zero'])
+ l = _multiarray_tests.test_neighborhood_iterator(
+ x, [-1, 1], x[0], NEIGH_MODE['zero'])
assert_array_equal(l, r)
r = [[1, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 1]]
- l = test_neighborhood_iterator(x, [-1, 1], x[0], NEIGH_MODE['one'])
+ l = _multiarray_tests.test_neighborhood_iterator(
+ x, [-1, 1], x[0], NEIGH_MODE['one'])
assert_array_equal(l, r)
r = [[x[4], 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, x[4]]]
- l = test_neighborhood_iterator(x, [-1, 1], x[4], NEIGH_MODE['constant'])
+ l = _multiarray_tests.test_neighborhood_iterator(
+ x, [-1, 1], x[4], NEIGH_MODE['constant'])
assert_array_equal(l, r)
def test_simple_float(self):
@@ -5873,7 +5877,8 @@ class TestNeighborhoodIter(object):
x = np.linspace(1, 5, 5).astype(dt)
r = np.array([[2, 1, 1, 2, 3], [1, 1, 2, 3, 4], [1, 2, 3, 4, 5],
[2, 3, 4, 5, 5], [3, 4, 5, 5, 4]], dtype=dt)
- l = test_neighborhood_iterator(x, [-2, 2], x[1], NEIGH_MODE['mirror'])
+ l = _multiarray_tests.test_neighborhood_iterator(
+ x, [-2, 2], x[1], NEIGH_MODE['mirror'])
assert_([i.dtype == dt for i in l])
assert_array_equal(l, r)
@@ -5888,7 +5893,8 @@ class TestNeighborhoodIter(object):
x = np.linspace(1, 5, 5).astype(dt)
r = np.array([[4, 5, 1, 2, 3], [5, 1, 2, 3, 4], [1, 2, 3, 4, 5],
[2, 3, 4, 5, 1], [3, 4, 5, 1, 2]], dtype=dt)
- l = test_neighborhood_iterator(x, [-2, 2], x[0], NEIGH_MODE['circular'])
+ l = _multiarray_tests.test_neighborhood_iterator(
+ x, [-2, 2], x[0], NEIGH_MODE['circular'])
assert_array_equal(l, r)
def test_circular(self):
@@ -5911,8 +5917,8 @@ class TestStackedNeighborhoodIter(object):
np.array([3], dtype=dt),
np.array([0], dtype=dt),
np.array([0], dtype=dt)]
- l = test_neighborhood_iterator_oob(x, [-2, 4], NEIGH_MODE['zero'],
- [0, 0], NEIGH_MODE['zero'])
+ l = _multiarray_tests.test_neighborhood_iterator_oob(
+ x, [-2, 4], NEIGH_MODE['zero'], [0, 0], NEIGH_MODE['zero'])
assert_array_equal(l, r)
r = [np.array([1, 0, 1], dtype=dt),
@@ -5920,8 +5926,8 @@ class TestStackedNeighborhoodIter(object):
np.array([1, 2, 3], dtype=dt),
np.array([2, 3, 0], dtype=dt),
np.array([3, 0, 1], dtype=dt)]
- l = test_neighborhood_iterator_oob(x, [-1, 3], NEIGH_MODE['zero'],
- [-1, 1], NEIGH_MODE['one'])
+ l = _multiarray_tests.test_neighborhood_iterator_oob(
+ x, [-1, 3], NEIGH_MODE['zero'], [-1, 1], NEIGH_MODE['one'])
assert_array_equal(l, r)
# 2nd simple, 1d test: stacking 2 neigh iterators, mixing const padding and
@@ -5935,8 +5941,8 @@ class TestStackedNeighborhoodIter(object):
np.array([1, 2, 3], dtype=dt),
np.array([2, 3, 3], dtype=dt),
np.array([3, 3, 0], dtype=dt)]
- l = test_neighborhood_iterator_oob(x, [-1, 3], NEIGH_MODE['mirror'],
- [-1, 1], NEIGH_MODE['zero'])
+ l = _multiarray_tests.test_neighborhood_iterator_oob(
+ x, [-1, 3], NEIGH_MODE['mirror'], [-1, 1], NEIGH_MODE['zero'])
assert_array_equal(l, r)
# Stacking mirror on top of zero
@@ -5946,8 +5952,8 @@ class TestStackedNeighborhoodIter(object):
np.array([0, 1, 2], dtype=dt),
np.array([1, 2, 3], dtype=dt),
np.array([2, 3, 0], dtype=dt)]
- l = test_neighborhood_iterator_oob(x, [-1, 3], NEIGH_MODE['zero'],
- [-2, 0], NEIGH_MODE['mirror'])
+ l = _multiarray_tests.test_neighborhood_iterator_oob(
+ x, [-1, 3], NEIGH_MODE['zero'], [-2, 0], NEIGH_MODE['mirror'])
assert_array_equal(l, r)
# Stacking mirror on top of zero: 2nd
@@ -5957,8 +5963,8 @@ class TestStackedNeighborhoodIter(object):
np.array([2, 3, 0], dtype=dt),
np.array([3, 0, 0], dtype=dt),
np.array([0, 0, 3], dtype=dt)]
- l = test_neighborhood_iterator_oob(x, [-1, 3], NEIGH_MODE['zero'],
- [0, 2], NEIGH_MODE['mirror'])
+ l = _multiarray_tests.test_neighborhood_iterator_oob(
+ x, [-1, 3], NEIGH_MODE['zero'], [0, 2], NEIGH_MODE['mirror'])
assert_array_equal(l, r)
# Stacking mirror on top of zero: 3rd
@@ -5968,8 +5974,8 @@ class TestStackedNeighborhoodIter(object):
np.array([0, 1, 2, 3, 0], dtype=dt),
np.array([1, 2, 3, 0, 0], dtype=dt),
np.array([2, 3, 0, 0, 3], dtype=dt)]
- l = test_neighborhood_iterator_oob(x, [-1, 3], NEIGH_MODE['zero'],
- [-2, 2], NEIGH_MODE['mirror'])
+ l = _multiarray_tests.test_neighborhood_iterator_oob(
+ x, [-1, 3], NEIGH_MODE['zero'], [-2, 2], NEIGH_MODE['mirror'])
assert_array_equal(l, r)
# 3rd simple, 1d test: stacking 2 neigh iterators, mixing const padding and
@@ -5983,8 +5989,8 @@ class TestStackedNeighborhoodIter(object):
np.array([1, 2, 3], dtype=dt),
np.array([2, 3, 1], dtype=dt),
np.array([3, 1, 0], dtype=dt)]
- l = test_neighborhood_iterator_oob(x, [-1, 3], NEIGH_MODE['circular'],
- [-1, 1], NEIGH_MODE['zero'])
+ l = _multiarray_tests.test_neighborhood_iterator_oob(
+ x, [-1, 3], NEIGH_MODE['circular'], [-1, 1], NEIGH_MODE['zero'])
assert_array_equal(l, r)
# Stacking mirror on top of zero
@@ -5994,8 +6000,8 @@ class TestStackedNeighborhoodIter(object):
np.array([0, 1, 2], dtype=dt),
np.array([1, 2, 3], dtype=dt),
np.array([2, 3, 0], dtype=dt)]
- l = test_neighborhood_iterator_oob(x, [-1, 3], NEIGH_MODE['zero'],
- [-2, 0], NEIGH_MODE['circular'])
+ l = _multiarray_tests.test_neighborhood_iterator_oob(
+ x, [-1, 3], NEIGH_MODE['zero'], [-2, 0], NEIGH_MODE['circular'])
assert_array_equal(l, r)
# Stacking mirror on top of zero: 2nd
@@ -6005,8 +6011,8 @@ class TestStackedNeighborhoodIter(object):
np.array([2, 3, 0], dtype=dt),
np.array([3, 0, 0], dtype=dt),
np.array([0, 0, 1], dtype=dt)]
- l = test_neighborhood_iterator_oob(x, [-1, 3], NEIGH_MODE['zero'],
- [0, 2], NEIGH_MODE['circular'])
+ l = _multiarray_tests.test_neighborhood_iterator_oob(
+ x, [-1, 3], NEIGH_MODE['zero'], [0, 2], NEIGH_MODE['circular'])
assert_array_equal(l, r)
# Stacking mirror on top of zero: 3rd
@@ -6016,8 +6022,8 @@ class TestStackedNeighborhoodIter(object):
np.array([0, 1, 2, 3, 0], dtype=dt),
np.array([1, 2, 3, 0, 0], dtype=dt),
np.array([2, 3, 0, 0, 1], dtype=dt)]
- l = test_neighborhood_iterator_oob(x, [-1, 3], NEIGH_MODE['zero'],
- [-2, 2], NEIGH_MODE['circular'])
+ l = _multiarray_tests.test_neighborhood_iterator_oob(
+ x, [-1, 3], NEIGH_MODE['zero'], [-2, 2], NEIGH_MODE['circular'])
assert_array_equal(l, r)
# 4th simple, 1d test: stacking 2 neigh iterators, but with lower iterator
@@ -6028,24 +6034,24 @@ class TestStackedNeighborhoodIter(object):
# array
x = np.array([1, 2, 3], dtype=dt)
r = [np.array([1, 2, 3, 0], dtype=dt)]
- l = test_neighborhood_iterator_oob(x, [1, 1], NEIGH_MODE['zero'],
- [-1, 2], NEIGH_MODE['zero'])
+ l = _multiarray_tests.test_neighborhood_iterator_oob(
+ x, [1, 1], NEIGH_MODE['zero'], [-1, 2], NEIGH_MODE['zero'])
assert_array_equal(l, r)
# Stacking mirror on top of zero, first neighborhood strictly inside the
# array
x = np.array([1, 2, 3], dtype=dt)
r = [np.array([1, 2, 3, 3], dtype=dt)]
- l = test_neighborhood_iterator_oob(x, [1, 1], NEIGH_MODE['zero'],
- [-1, 2], NEIGH_MODE['mirror'])
+ l = _multiarray_tests.test_neighborhood_iterator_oob(
+ x, [1, 1], NEIGH_MODE['zero'], [-1, 2], NEIGH_MODE['mirror'])
assert_array_equal(l, r)
# Stacking mirror on top of zero, first neighborhood strictly inside the
# array
x = np.array([1, 2, 3], dtype=dt)
r = [np.array([1, 2, 3, 1], dtype=dt)]
- l = test_neighborhood_iterator_oob(x, [1, 1], NEIGH_MODE['zero'],
- [-1, 2], NEIGH_MODE['circular'])
+ l = _multiarray_tests.test_neighborhood_iterator_oob(
+ x, [1, 1], NEIGH_MODE['zero'], [-1, 2], NEIGH_MODE['circular'])
assert_array_equal(l, r)
class TestWarnings(object):
@@ -6429,7 +6435,9 @@ class TestNewBufferProtocol(object):
def test_export_flags(self):
# Check SIMPLE flag, see also gh-3613 (exception should be BufferError)
- assert_raises(ValueError, get_buffer_info, np.arange(5)[::2], ('SIMPLE',))
+ assert_raises(ValueError,
+ _multiarray_tests.get_buffer_info,
+ np.arange(5)[::2], ('SIMPLE',))
def test_padding(self):
for j in range(8):
@@ -6485,10 +6493,12 @@ class TestNewBufferProtocol(object):
arr = np.ones((1, 10))
if arr.flags.f_contiguous:
- shape, strides = get_buffer_info(arr, ['F_CONTIGUOUS'])
+ shape, strides = _multiarray_tests.get_buffer_info(
+ arr, ['F_CONTIGUOUS'])
assert_(strides[0] == 8)
arr = np.ones((10, 1), order='F')
- shape, strides = get_buffer_info(arr, ['C_CONTIGUOUS'])
+ shape, strides = _multiarray_tests.get_buffer_info(
+ arr, ['C_CONTIGUOUS'])
assert_(strides[-1] == 8)
def test_out_of_order_fields(self):
@@ -6630,26 +6640,26 @@ def test_scalar_element_deletion():
class TestMemEventHook(object):
def test_mem_seteventhook(self):
# The actual tests are within the C code in
- # multiarray/multiarray_tests.c.src
- test_pydatamem_seteventhook_start()
+ # multiarray/_multiarray_tests.c.src
+ _multiarray_tests.test_pydatamem_seteventhook_start()
# force an allocation and free of a numpy array
# needs to be larger then limit of small memory cacher in ctors.c
a = np.zeros(1000)
del a
gc.collect()
- test_pydatamem_seteventhook_end()
+ _multiarray_tests.test_pydatamem_seteventhook_end()
class TestMapIter(object):
def test_mapiter(self):
# The actual tests are within the C code in
- # multiarray/multiarray_tests.c.src
+ # multiarray/_multiarray_tests.c.src
a = np.arange(12).reshape((3, 4)).astype(float)
index = ([1, 1, 2, 0],
[0, 0, 2, 3])
vals = [50, 50, 30, 16]
- test_inplace_increment(a, index, vals)
+ _multiarray_tests.test_inplace_increment(a, index, vals)
assert_equal(a, [[0.00, 1., 2.0, 19.],
[104., 5., 6.0, 7.0],
[8.00, 9., 40., 11.]])
@@ -6657,24 +6667,24 @@ class TestMapIter(object):
b = np.arange(6).astype(float)
index = (np.array([1, 2, 0]),)
vals = [50, 4, 100.1]
- test_inplace_increment(b, index, vals)
+ _multiarray_tests.test_inplace_increment(b, index, vals)
assert_equal(b, [100.1, 51., 6., 3., 4., 5.])
class TestAsCArray(object):
def test_1darray(self):
array = np.arange(24, dtype=np.double)
- from_c = test_as_c_array(array, 3)
+ from_c = _multiarray_tests.test_as_c_array(array, 3)
assert_equal(array[3], from_c)
def test_2darray(self):
array = np.arange(24, dtype=np.double).reshape(3, 8)
- from_c = test_as_c_array(array, 2, 4)
+ from_c = _multiarray_tests.test_as_c_array(array, 2, 4)
assert_equal(array[2, 4], from_c)
def test_3darray(self):
array = np.arange(24, dtype=np.double).reshape(2, 3, 4)
- from_c = test_as_c_array(array, 1, 2, 3)
+ from_c = _multiarray_tests.test_as_c_array(array, 1, 2, 3)
assert_equal(array[1, 2, 3], from_c)
@@ -6992,7 +7002,7 @@ class TestHashing(object):
def test_collections_hashable(self):
x = np.array([])
- assert_(not isinstance(x, collections.Hashable))
+ assert_(not isinstance(x, collections_abc.Hashable))
class TestArrayPriority(object):
@@ -7168,7 +7178,7 @@ class TestCTypes(object):
_internal.ctypes = ctypes
-class TestWritebackIfCopy(TestCase):
+class TestWritebackIfCopy(object):
# all these tests use the WRITEBACKIFCOPY mechanism
def test_argmax_with_out(self):
mat = np.eye(5)
@@ -7234,7 +7244,7 @@ class TestWritebackIfCopy(TestCase):
assert_equal(b, np.array([[15, 18, 21], [42, 54, 66], [69, 90, 111]]))
def test_view_assign(self):
- from numpy.core.multiarray_tests import npy_create_writebackifcopy, npy_resolve
+ from numpy.core._multiarray_tests import npy_create_writebackifcopy, npy_resolve
arr = np.arange(9).reshape(3, 3).T
arr_wb = npy_create_writebackifcopy(arr)
assert_(arr_wb.flags.writebackifcopy)
@@ -7304,7 +7314,7 @@ def test_equal_override():
def test_npymath_complex():
# Smoketest npymath functions
- from numpy.core.multiarray_tests import (
+ from numpy.core._multiarray_tests import (
npy_cabs, npy_carg)
funcs = {npy_cabs: np.absolute,
@@ -7323,7 +7333,7 @@ def test_npymath_complex():
def test_npymath_real():
# Smoketest npymath functions
- from numpy.core.multiarray_tests import (
+ from numpy.core._multiarray_tests import (
npy_log10, npy_cosh, npy_sinh, npy_tan, npy_tanh)
funcs = {npy_log10: np.log10,
diff --git a/numpy/core/tests/test_nditer.py b/numpy/core/tests/test_nditer.py
index f3f8706b5..9d8f4f06a 100644
--- a/numpy/core/tests/test_nditer.py
+++ b/numpy/core/tests/test_nditer.py
@@ -4,8 +4,8 @@ import sys
import warnings
import numpy as np
+import numpy.core._multiarray_tests as _multiarray_tests
from numpy import array, arange, nditer, all
-from numpy.core.multiarray_tests import test_nditer_too_large
from numpy.testing import (
run_module_suite, assert_, assert_equal, assert_array_equal,
assert_raises, assert_warns, dec, HAS_REFCOUNT, suppress_warnings
@@ -33,7 +33,7 @@ def iter_iterindices(i):
i.iternext()
return ret
-@dec.skipif(not HAS_REFCOUNT, "python does not have sys.getrefcount")
+@dec._needs_refcount
def test_iter_refcount():
# Make sure the iterator doesn't leak
@@ -2697,18 +2697,19 @@ def test_iter_too_large_with_multiindex():
# arrays are now too large to be broadcast. The different modes test
# different nditer functionality with or without GIL.
for mode in range(6):
- assert_raises(ValueError, test_nditer_too_large, arrays, -1, mode)
+ with assert_raises(ValueError):
+ _multiarray_tests.test_nditer_too_large(arrays, -1, mode)
# but if we do nothing with the nditer, it can be constructed:
- test_nditer_too_large(arrays, -1, 7)
+ _multiarray_tests.test_nditer_too_large(arrays, -1, 7)
# When an axis is removed, things should work again (half the time):
for i in range(num):
for mode in range(6):
# an axis with size 1024 is removed:
- test_nditer_too_large(arrays, i*2, mode)
+ _multiarray_tests.test_nditer_too_large(arrays, i*2, mode)
# an axis with size 1 is removed:
- assert_raises(ValueError, test_nditer_too_large,
- arrays, i*2 + 1, mode)
+ with assert_raises(ValueError):
+ _multiarray_tests.test_nditer_too_large(arrays, i*2 + 1, mode)
if __name__ == "__main__":
diff --git a/numpy/core/tests/test_numeric.py b/numpy/core/tests/test_numeric.py
index 7c012e9e8..d7cdd77f1 100644
--- a/numpy/core/tests/test_numeric.py
+++ b/numpy/core/tests/test_numeric.py
@@ -12,7 +12,7 @@ from numpy.random import rand, randint, randn
from numpy.testing import (
run_module_suite, assert_, assert_equal, assert_raises,
assert_raises_regex, assert_array_equal, assert_almost_equal,
- assert_array_almost_equal, dec, HAS_REFCOUNT, suppress_warnings
+ assert_array_almost_equal, dec, suppress_warnings
)
@@ -2092,7 +2092,7 @@ class TestCreationFuncs(object):
self.check_function(np.full, 0)
self.check_function(np.full, 1)
- @dec.skipif(not HAS_REFCOUNT, "python has no sys.getrefcount")
+ @dec._needs_refcount
def test_for_reference_leak(self):
# Make sure we have an object for reference
dim = 1
diff --git a/numpy/core/tests/test_print.py b/numpy/core/tests/test_print.py
index 6ebb4733c..f432711a9 100644
--- a/numpy/core/tests/test_print.py
+++ b/numpy/core/tests/test_print.py
@@ -2,12 +2,14 @@ from __future__ import division, absolute_import, print_function
import sys
import locale
+import contextlib
import nose
import numpy as np
from numpy.testing import (
- run_module_suite, assert_, assert_equal, SkipTest
+ run_module_suite, assert_, assert_equal, SkipTest, dec
)
+from ._locales import CommaDecimalPointLocale
if sys.version_info[0] >= 3:
@@ -201,46 +203,21 @@ def test_scalar_format():
(fmat, repr(val), repr(valtype), str(e)))
+#
# Locale tests: scalar types formatting should be independent of the locale
-def in_foreign_locale(func):
- """
- Swap LC_NUMERIC locale to one in which the decimal point is ',' and not '.'
- If not possible, raise SkipTest
+#
- """
- if sys.platform == 'win32':
- locales = ['FRENCH']
- else:
- locales = ['fr_FR', 'fr_FR.UTF-8', 'fi_FI', 'fi_FI.UTF-8']
+class TestCommaDecimalPointLocale(CommaDecimalPointLocale):
+
+ def test_locale_single(self):
+ assert_equal(str(np.float32(1.2)), str(float(1.2)))
+
+ def test_locale_double(self):
+ assert_equal(str(np.double(1.2)), str(float(1.2)))
+
+ def test_locale_longdouble(self):
+ assert_equal(str(np.longdouble('1.2')), str(float(1.2)))
- def wrapper(*args, **kwargs):
- curloc = locale.getlocale(locale.LC_NUMERIC)
- try:
- for loc in locales:
- try:
- locale.setlocale(locale.LC_NUMERIC, loc)
- break
- except locale.Error:
- pass
- else:
- raise SkipTest("Skipping locale test, because "
- "French locale not found")
- return func(*args, **kwargs)
- finally:
- locale.setlocale(locale.LC_NUMERIC, locale=curloc)
- return nose.tools.make_decorator(func)(wrapper)
-
-@in_foreign_locale
-def test_locale_single():
- assert_equal(str(np.float32(1.2)), str(float(1.2)))
-
-@in_foreign_locale
-def test_locale_double():
- assert_equal(str(np.double(1.2)), str(float(1.2)))
-
-@in_foreign_locale
-def test_locale_longdouble():
- assert_equal(str(np.longdouble('1.2')), str(float(1.2)))
if __name__ == "__main__":
run_module_suite()
diff --git a/numpy/core/tests/test_records.py b/numpy/core/tests/test_records.py
index d5423b1f1..8e261d226 100644
--- a/numpy/core/tests/test_records.py
+++ b/numpy/core/tests/test_records.py
@@ -1,7 +1,12 @@
from __future__ import division, absolute_import, print_function
import sys
-import collections
+try:
+ # Accessing collections abstract classes from collections
+ # has been deprecated since Python 3.3
+ import collections.abc as collections_abc
+except ImportError:
+ import collections as collections_abc
import pickle
import warnings
import textwrap
@@ -252,7 +257,7 @@ class TestFromrecords(object):
assert_array_equal(ra['shape'], [['A', 'B', 'C']])
ra.field = 5
assert_array_equal(ra['field'], [[5, 5, 5]])
- assert_(isinstance(ra.field, collections.Callable))
+ assert_(isinstance(ra.field, collections_abc.Callable))
def test_fromrecords_with_explicit_dtype(self):
a = np.rec.fromrecords([(1, 'a'), (2, 'bbb')],
diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py
index a3b011454..016b720f3 100644
--- a/numpy/core/tests/test_regression.py
+++ b/numpy/core/tests/test_regression.py
@@ -1424,7 +1424,7 @@ class TestRegression(object):
x[x.nonzero()] = x.ravel()[:1]
assert_(x[0, 1] == x[0, 0])
- @dec.skipif(not HAS_REFCOUNT, "python has no sys.getrefcount")
+ @dec._needs_refcount
def test_structured_arrays_with_objects2(self):
# Ticket #1299 second test
stra = 'aaaa'
@@ -1537,7 +1537,7 @@ class TestRegression(object):
y = np.add(x, x, x)
assert_equal(id(x), id(y))
- @dec.skipif(not HAS_REFCOUNT, "python has no sys.getrefcount")
+ @dec._needs_refcount
def test_take_refcount(self):
# ticket #939
a = np.arange(16, dtype=float)
@@ -1937,7 +1937,7 @@ class TestRegression(object):
a = np.empty((100000000,), dtype='i1')
del a
- @dec.skipif(not HAS_REFCOUNT, "python has no sys.getrefcount")
+ @dec._needs_refcount
def test_ufunc_reduce_memoryleak(self):
a = np.arange(6)
acnt = sys.getrefcount(a)
@@ -2167,7 +2167,7 @@ class TestRegression(object):
assert_equal(uf(a), ())
assert_array_equal(a, [[3, 2, 1], [5, 4], [9, 7, 8, 6]])
- @dec.skipif(not HAS_REFCOUNT, "python has no sys.getrefcount")
+ @dec._needs_refcount
def test_leak_in_structured_dtype_comparison(self):
# gh-6250
recordtype = np.dtype([('a', np.float64),
diff --git a/numpy/core/tests/test_scalarbuffer.py b/numpy/core/tests/test_scalarbuffer.py
new file mode 100644
index 000000000..cd887f2fb
--- /dev/null
+++ b/numpy/core/tests/test_scalarbuffer.py
@@ -0,0 +1,84 @@
+"""
+Test scalar buffer interface adheres to PEP 3118
+"""
+import sys
+import numpy as np
+from numpy.testing import run_module_suite, assert_, assert_equal, dec
+
+# PEP3118 format strings for native (standard alignment and byteorder) types
+scalars_and_codes = [
+ (np.bool_, '?'),
+ (np.byte, 'b'),
+ (np.short, 'h'),
+ (np.intc, 'i'),
+ (np.int_, 'l'),
+ (np.longlong, 'q'),
+ (np.ubyte, 'B'),
+ (np.ushort, 'H'),
+ (np.uintc, 'I'),
+ (np.uint, 'L'),
+ (np.ulonglong, 'Q'),
+ (np.half, 'e'),
+ (np.single, 'f'),
+ (np.double, 'd'),
+ (np.longdouble, 'g'),
+ (np.csingle, 'Zf'),
+ (np.cdouble, 'Zd'),
+ (np.clongdouble, 'Zg'),
+]
+
+
+class TestScalarPEP3118(object):
+ skip_if_no_buffer_interface = dec.skipif(sys.version_info.major < 3,
+ "scalars do not implement buffer interface in Python 2")
+
+ @skip_if_no_buffer_interface
+ def test_scalar_match_array(self):
+ for scalar, _ in scalars_and_codes:
+ x = scalar()
+ a = np.array([], dtype=np.dtype(scalar))
+ mv_x = memoryview(x)
+ mv_a = memoryview(a)
+ assert_equal(mv_x.format, mv_a.format)
+
+ @skip_if_no_buffer_interface
+ def test_scalar_dim(self):
+ for scalar, _ in scalars_and_codes:
+ x = scalar()
+ mv_x = memoryview(x)
+ assert_equal(mv_x.itemsize, np.dtype(scalar).itemsize)
+ assert_equal(mv_x.ndim, 0)
+ assert_equal(mv_x.shape, ())
+ assert_equal(mv_x.strides, ())
+ assert_equal(mv_x.suboffsets, ())
+
+ @skip_if_no_buffer_interface
+ def test_scalar_known_code(self):
+ for scalar, code in scalars_and_codes:
+ x = scalar()
+ mv_x = memoryview(x)
+ assert_equal(mv_x.format, code)
+
+ @skip_if_no_buffer_interface
+ def test_void_scalar_structured_data(self):
+ dt = np.dtype([('name', np.unicode_, 16), ('grades', np.float64, (2,))])
+ x = np.array(('ndarray_scalar', (1.2, 3.0)), dtype=dt)[()]
+ assert_(isinstance(x, np.void))
+ mv_x = memoryview(x)
+ expected_size = 16 * np.dtype((np.unicode_, 1)).itemsize
+ expected_size += 2 * np.dtype((np.float64, 1)).itemsize
+ assert_equal(mv_x.itemsize, expected_size)
+ assert_equal(mv_x.ndim, 0)
+ assert_equal(mv_x.shape, ())
+ assert_equal(mv_x.strides, ())
+ assert_equal(mv_x.suboffsets, ())
+
+ # check scalar format string against ndarray format string
+ a = np.array([('Sarah', (8.0, 7.0)), ('John', (6.0, 7.0))], dtype=dt)
+ assert_(isinstance(a, np.ndarray))
+ mv_a = memoryview(a)
+ assert_equal(mv_x.itemsize, mv_a.itemsize)
+ assert_equal(mv_x.format, mv_a.format)
+
+if __name__ == "__main__":
+ run_module_suite()
diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py
index 7e1bfbdbe..576ecaf0d 100644
--- a/numpy/core/tests/test_ufunc.py
+++ b/numpy/core/tests/test_ufunc.py
@@ -4,9 +4,9 @@ import warnings
import itertools
import numpy as np
-import numpy.core.umath_tests as umt
-import numpy.core.operand_flag_tests as opflag_tests
-from numpy.core.test_rational import rational, test_add, test_add_rationals
+import numpy.core._umath_tests as umt
+import numpy.core._operand_flag_tests as opflag_tests
+import numpy.core._rational_tests as _rational_tests
from numpy.testing import (
run_module_suite, assert_, assert_equal, assert_raises,
assert_array_equal, assert_almost_equal, assert_array_almost_equal,
@@ -42,8 +42,9 @@ class TestUfunc(object):
assert_(pickle.loads(pickle.dumps(np.sin)) is np.sin)
# Check that ufunc not defined in the top level numpy namespace such as
- # numpy.core.test_rational.test_add can also be pickled
- assert_(pickle.loads(pickle.dumps(test_add)) is test_add)
+ # numpy.core._rational_tests.test_add can also be pickled
+ res = pickle.loads(pickle.dumps(_rational_tests.test_add))
+ assert_(res is _rational_tests.test_add)
def test_pickle_withstring(self):
import pickle
@@ -625,7 +626,7 @@ class TestUfunc(object):
assert_array_equal(c, (a * b).sum(0))
c = in1d(a, b, axes=[0, 2])
assert_array_equal(c, (a.transpose(1, 2, 0) * b).sum(-1))
- # Check errors for inproperly constructed axes arguments.
+ # Check errors for improperly constructed axes arguments.
# should have list.
assert_raises(TypeError, in1d, a, b, axes=-1)
# needs enough elements
@@ -670,7 +671,7 @@ class TestUfunc(object):
d = mm(a, b, out=c, axes=[(-2, -1), (-2, -1), (3, 0)])
assert_(c is d)
assert_array_equal(c, np.matmul(a, b).transpose(3, 0, 1, 2))
- # Check errors for inproperly constructed axes arguments.
+ # Check errors for improperly constructed axes arguments.
# wrong argument
assert_raises(TypeError, mm, a, b, axis=1)
# axes should be list
@@ -1143,15 +1144,17 @@ class TestUfunc(object):
a = np.array([0, 1, 2], dtype='i8')
b = np.array([0, 1, 2], dtype='i8')
- c = np.empty(3, dtype=rational)
+ c = np.empty(3, dtype=_rational_tests.rational)
# Output must be specified so numpy knows what
# ufunc signature to look for
- result = test_add(a, b, c)
- assert_equal(result, np.array([0, 2, 4], dtype=rational))
+ result = _rational_tests.test_add(a, b, c)
+ target = np.array([0, 2, 4], dtype=_rational_tests.rational)
+ assert_equal(result, target)
# no output type should raise TypeError
- assert_raises(TypeError, test_add, a, b)
+ with assert_raises(TypeError):
+ _rational_tests.test_add(a, b)
def test_operand_flags(self):
a = np.arange(16, dtype='l').reshape(4, 4)
@@ -1167,7 +1170,7 @@ class TestUfunc(object):
assert_equal(a, 10)
def test_struct_ufunc(self):
- import numpy.core.struct_ufunc_test as struct_ufunc
+ import numpy.core._struct_ufunc_tests as struct_ufunc
a = np.array([(1, 2, 3)], dtype='u8,u8,u8')
b = np.array([(1, 2, 3)], dtype='u8,u8,u8')
@@ -1176,20 +1179,30 @@ class TestUfunc(object):
assert_equal(result, np.array([(2, 4, 6)], dtype='u8,u8,u8'))
def test_custom_ufunc(self):
- a = np.array([rational(1, 2), rational(1, 3), rational(1, 4)],
- dtype=rational)
- b = np.array([rational(1, 2), rational(1, 3), rational(1, 4)],
- dtype=rational)
-
- result = test_add_rationals(a, b)
- expected = np.array([rational(1), rational(2, 3), rational(1, 2)],
- dtype=rational)
+ a = np.array(
+ [_rational_tests.rational(1, 2),
+ _rational_tests.rational(1, 3),
+ _rational_tests.rational(1, 4)],
+ dtype=_rational_tests.rational)
+ b = np.array(
+ [_rational_tests.rational(1, 2),
+ _rational_tests.rational(1, 3),
+ _rational_tests.rational(1, 4)],
+ dtype=_rational_tests.rational)
+
+ result = _rational_tests.test_add_rationals(a, b)
+ expected = np.array(
+ [_rational_tests.rational(1),
+ _rational_tests.rational(2, 3),
+ _rational_tests.rational(1, 2)],
+ dtype=_rational_tests.rational)
assert_equal(result, expected)
def test_custom_ufunc_forced_sig(self):
# gh-9351 - looking for a non-first userloop would previously hang
- assert_raises(TypeError,
- np.multiply, rational(1), 1, signature=(rational, int, None))
+ with assert_raises(TypeError):
+ np.multiply(_rational_tests.rational(1), 1,
+ signature=(_rational_tests.rational, int, None))
def test_custom_array_like(self):
diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py
index ac97b8b0d..fe7768e53 100644
--- a/numpy/core/tests/test_umath.py
+++ b/numpy/core/tests/test_umath.py
@@ -7,7 +7,7 @@ import fnmatch
import itertools
import numpy.core.umath as ncu
-from numpy.core import umath_tests as ncu_tests
+from numpy.core import _umath_tests as ncu_tests
import numpy as np
from numpy.testing import (
run_module_suite, assert_, assert_equal, assert_raises,
@@ -24,10 +24,10 @@ def on_powerpc():
class _FilterInvalids(object):
- def setUp(self):
+ def setup(self):
self.olderr = np.seterr(invalid='ignore')
- def tearDown(self):
+ def teardown(self):
np.seterr(**self.olderr)
diff --git a/numpy/core/tests/test_umath_complex.py b/numpy/core/tests/test_umath_complex.py
index fb3b6577c..1b098a120 100644
--- a/numpy/core/tests/test_umath_complex.py
+++ b/numpy/core/tests/test_umath_complex.py
@@ -351,10 +351,10 @@ class TestCsqrt(object):
# cuts first)
class TestCpow(object):
- def setUp(self):
+ def setup(self):
self.olderr = np.seterr(invalid='ignore')
- def tearDown(self):
+ def teardown(self):
np.seterr(**self.olderr)
def test_simple(self):
@@ -391,10 +391,10 @@ class TestCpow(object):
assert_almost_equal(n_r[i], p_r[i], err_msg='Loop %d\n' % i)
class TestCabs(object):
- def setUp(self):
+ def setup(self):
self.olderr = np.seterr(invalid='ignore')
- def tearDown(self):
+ def teardown(self):
np.seterr(**self.olderr)
def test_simple(self):
diff --git a/numpy/distutils/__init__.py b/numpy/distutils/__init__.py
index 0450334ff..d5921b399 100644
--- a/numpy/distutils/__init__.py
+++ b/numpy/distutils/__init__.py
@@ -17,7 +17,7 @@ try:
# Normally numpy is installed if the above import works, but an interrupted
# in-place build could also have left a __config__.py. In that case the
# next import may still fail, so keep it inside the try block.
- from numpy.testing.nosetester import _numpy_tester
+ from numpy.testing import _numpy_tester
test = _numpy_tester().test
except ImportError:
pass
@@ -26,7 +26,7 @@ except ImportError:
def customized_fcompiler(plat=None, compiler=None):
from numpy.distutils.fcompiler import new_fcompiler
c = new_fcompiler(plat=plat, compiler=compiler)
- c.customize()
+ c.customize()
return c
def customized_ccompiler(plat=None, compiler=None):
diff --git a/numpy/distutils/tests/test_system_info.py b/numpy/distutils/tests/test_system_info.py
index 50befa15b..c6a9b9915 100644
--- a/numpy/distutils/tests/test_system_info.py
+++ b/numpy/distutils/tests/test_system_info.py
@@ -160,7 +160,7 @@ class TestSystemInfoReading(object):
self.c_temp1 = site_and_parse(get_class('temp1'), self._sitecfg)
self.c_temp2 = site_and_parse(get_class('temp2'), self._sitecfg)
- def tearDown(self):
+ def teardown(self):
# Do each removal separately
try:
shutil.rmtree(self._dir1)
diff --git a/numpy/doc/subclassing.py b/numpy/doc/subclassing.py
index 467e31cea..3be3d94b3 100644
--- a/numpy/doc/subclassing.py
+++ b/numpy/doc/subclassing.py
@@ -562,7 +562,7 @@ pass on to ``A.__array_ufunc__``, the ``super`` call in ``A`` would go to
Prior to numpy 1.13, the behaviour of ufuncs could only be tuned using
``__array_wrap__`` and ``__array_prepare__``. These two allowed one to
-change the output type of a ufunc, but, in constrast to
+change the output type of a ufunc, but, in contrast to
``__array_ufunc__``, did not allow one to make any changes to the inputs.
It is hoped to eventually deprecate these, but ``__array_wrap__`` is also
used by other numpy functions and methods, such as ``squeeze``, so at the
diff --git a/numpy/f2py/__init__.py b/numpy/f2py/__init__.py
index 250c4322b..86cc45b42 100644
--- a/numpy/f2py/__init__.py
+++ b/numpy/f2py/__init__.py
@@ -71,4 +71,3 @@ def compile(source,
from numpy.testing import _numpy_tester
test = _numpy_tester().test
-bench = _numpy_tester().bench
diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py
index dc560f98e..19ce8c145 100755
--- a/numpy/f2py/crackfortran.py
+++ b/numpy/f2py/crackfortran.py
@@ -612,7 +612,7 @@ multilinepattern = re.compile(
def split_by_unquoted(line, characters):
"""
Splits the line into (line[:i], line[i:]),
- where i is the index of first occurence of one of the characters
+ where i is the index of first occurrence of one of the characters
not within quotes, or len(line) if no such index exists
"""
assert not (set('"\'') & set(characters)), "cannot split by unquoted quotes"
diff --git a/numpy/fft/__init__.py b/numpy/fft/__init__.py
index 72d61a728..d1716bd4b 100644
--- a/numpy/fft/__init__.py
+++ b/numpy/fft/__init__.py
@@ -8,4 +8,3 @@ from .helper import *
from numpy.testing import _numpy_tester
test = _numpy_tester().test
-bench = _numpy_tester().bench
diff --git a/numpy/fft/fftpack.py b/numpy/fft/fftpack.py
index bd116b9cb..e17e1cb34 100644
--- a/numpy/fft/fftpack.py
+++ b/numpy/fft/fftpack.py
@@ -69,13 +69,13 @@ def _raw_fft(a, n=None, axis=-1, init_function=fftpack.cffti,
if s[axis] > n:
index = [slice(None)]*len(s)
index[axis] = slice(0, n)
- a = a[index]
+ a = a[tuple(index)]
else:
index = [slice(None)]*len(s)
index[axis] = slice(0, s[axis])
s[axis] = n
z = zeros(s, a.dtype.char)
- z[index] = a
+ z[tuple(index)] = a
a = z
if axis != -1:
diff --git a/numpy/fft/helper.py b/numpy/fft/helper.py
index 1a1266e12..729121f31 100644
--- a/numpy/fft/helper.py
+++ b/numpy/fft/helper.py
@@ -5,7 +5,10 @@ Discrete Fourier Transforms - helper.py
from __future__ import division, absolute_import, print_function
import collections
-import threading
+try:
+ import threading
+except ImportError:
+ import dummy_threading as threading
from numpy.compat import integer_types
from numpy.core import integer, empty, arange, asarray, roll
diff --git a/numpy/lib/__init__.py b/numpy/lib/__init__.py
index cc05232a2..0c2e6dfab 100644
--- a/numpy/lib/__init__.py
+++ b/numpy/lib/__init__.py
@@ -48,4 +48,3 @@ __all__ += histograms.__all__
from numpy.testing import _numpy_tester
test = _numpy_tester().test
-bench = _numpy_tester().bench
diff --git a/numpy/lib/arraypad.py b/numpy/lib/arraypad.py
index cdc354a02..daaa68d06 100644
--- a/numpy/lib/arraypad.py
+++ b/numpy/lib/arraypad.py
@@ -1346,9 +1346,9 @@ def pad(array, pad_width, mode, **kwargs):
# Create a new padded array
rank = list(range(narray.ndim))
total_dim_increase = [np.sum(pad_width[i]) for i in rank]
- offset_slices = [slice(pad_width[i][0],
- pad_width[i][0] + narray.shape[i])
- for i in rank]
+ offset_slices = tuple(
+ slice(pad_width[i][0], pad_width[i][0] + narray.shape[i])
+ for i in rank)
new_shape = np.array(narray.shape) + total_dim_increase
newmat = np.zeros(new_shape, narray.dtype)
diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py
index 422a87322..8440be52e 100644
--- a/numpy/lib/function_base.py
+++ b/numpy/lib/function_base.py
@@ -1,6 +1,11 @@
from __future__ import division, absolute_import, print_function
-import collections
+try:
+ # Accessing collections abstact classes from collections
+ # has been deprecated since Python 3.3
+ import collections.abc as collections_abc
+except ImportError:
+ import collections as collections_abc
import re
import sys
import warnings
@@ -179,21 +184,18 @@ def flip(m, axis):
>>> A
array([[[0, 1],
[2, 3]],
-
[[4, 5],
[6, 7]]])
>>> flip(A, 0)
array([[[4, 5],
[6, 7]],
-
[[0, 1],
[2, 3]]])
>>> flip(A, 1)
array([[[2, 3],
[0, 1]],
-
[[6, 7],
[4, 5]]])
@@ -547,7 +549,7 @@ def piecewise(x, condlist, funclist, *args, **kw):
y = zeros(x.shape, x.dtype)
for k in range(n):
item = funclist[k]
- if not isinstance(item, collections.Callable):
+ if not isinstance(item, collections_abc.Callable):
y[condlist[k]] = item
else:
vals = x[condlist[k]]
@@ -970,7 +972,7 @@ def gradient(f, *varargs, **kwargs):
slice4[axis] = slice(2, None)
if uniform_spacing:
- out[slice1] = (f[slice4] - f[slice2]) / (2. * ax_dx)
+ out[tuple(slice1)] = (f[tuple(slice4)] - f[tuple(slice2)]) / (2. * ax_dx)
else:
dx1 = ax_dx[0:-1]
dx2 = ax_dx[1:]
@@ -982,7 +984,7 @@ def gradient(f, *varargs, **kwargs):
shape[axis] = -1
a.shape = b.shape = c.shape = shape
# 1D equivalent -- out[1:-1] = a * f[:-2] + b * f[1:-1] + c * f[2:]
- out[slice1] = a * f[slice2] + b * f[slice3] + c * f[slice4]
+ out[tuple(slice1)] = a * f[tuple(slice2)] + b * f[tuple(slice3)] + c * f[tuple(slice4)]
# Numerical differentiation: 1st order edges
if edge_order == 1:
@@ -991,14 +993,14 @@ def gradient(f, *varargs, **kwargs):
slice3[axis] = 0
dx_0 = ax_dx if uniform_spacing else ax_dx[0]
# 1D equivalent -- out[0] = (f[1] - f[0]) / (x[1] - x[0])
- out[slice1] = (f[slice2] - f[slice3]) / dx_0
+ out[tuple(slice1)] = (f[tuple(slice2)] - f[tuple(slice3)]) / dx_0
slice1[axis] = -1
slice2[axis] = -1
slice3[axis] = -2
dx_n = ax_dx if uniform_spacing else ax_dx[-1]
# 1D equivalent -- out[-1] = (f[-1] - f[-2]) / (x[-1] - x[-2])
- out[slice1] = (f[slice2] - f[slice3]) / dx_n
+ out[tuple(slice1)] = (f[tuple(slice2)] - f[tuple(slice3)]) / dx_n
# Numerical differentiation: 2nd order edges
else:
@@ -1017,7 +1019,7 @@ def gradient(f, *varargs, **kwargs):
b = (dx1 + dx2) / (dx1 * dx2)
c = - dx1 / (dx2 * (dx1 + dx2))
# 1D equivalent -- out[0] = a * f[0] + b * f[1] + c * f[2]
- out[slice1] = a * f[slice2] + b * f[slice3] + c * f[slice4]
+ out[tuple(slice1)] = a * f[tuple(slice2)] + b * f[tuple(slice3)] + c * f[tuple(slice4)]
slice1[axis] = -1
slice2[axis] = -3
@@ -1034,7 +1036,7 @@ def gradient(f, *varargs, **kwargs):
b = - (dx2 + dx1) / (dx1 * dx2)
c = (2. * dx2 + dx1) / (dx2 * (dx1 + dx2))
# 1D equivalent -- out[-1] = a * f[-3] + b * f[-2] + c * f[-1]
- out[slice1] = a * f[slice2] + b * f[slice3] + c * f[slice4]
+ out[tuple(slice1)] = a * f[tuple(slice2)] + b * f[tuple(slice3)] + c * f[tuple(slice4)]
outvals.append(out)
@@ -1372,6 +1374,7 @@ def unwrap(p, discont=pi, axis=-1):
dd = diff(p, axis=axis)
slice1 = [slice(None, None)]*nd # full slices
slice1[axis] = slice(1, None)
+ slice1 = tuple(slice1)
ddmod = mod(dd + pi, 2*pi) - pi
_nx.copyto(ddmod, pi, where=(ddmod == -pi) & (dd > 0))
ph_correct = ddmod - dd
@@ -2296,7 +2299,7 @@ def cov(m, y=None, rowvar=True, bias=False, ddof=None, fweights=None,
else:
X_T = (X*w).T
c = dot(X, X_T.conj())
- c *= 1. / np.float64(fact)
+ c *= np.true_divide(1, fact)
return c.squeeze()
@@ -3354,6 +3357,7 @@ def _median(a, axis=None, out=None, overwrite_input=False):
indexer[axis] = slice(index, index+1)
else:
indexer[axis] = slice(index-1, index+1)
+ indexer = tuple(indexer)
# Check if the array contains any nan's
if np.issubdtype(a.dtype, np.inexact) and sz > 0:
@@ -3473,6 +3477,33 @@ def percentile(a, q, axis=None, out=None,
array([ 7., 2.])
>>> assert not np.all(a == b)
+ The different types of interpolation can be visualized graphically:
+
+ ..plot::
+ import matplotlib.pyplot as plt
+
+ a = np.arange(4)
+ p = np.linspace(0, 100, 6001)
+ ax = plt.gca()
+ lines = [
+ ('linear', None)
+ ('higher', '--')
+ ('lower', '--')
+ ('nearest', '-.')
+ ('midpoint', '-.')
+ ]
+ for interpolation, style in lines:
+ ax.plot(
+ p, np.percentile(a, p, interpolation=interpolation),
+ label=interpolation, linestyle=style)
+ ax.set(
+ title='Interpolation methods for list: ' + str(a),
+ xlabel='Percentile',
+ ylabel='List item returned',
+ yticks=a)
+ ax.legend()
+ plt.show()
+
"""
q = np.true_divide(q, 100.0) # handles the asarray for us too
if not _quantile_is_valid(q):
@@ -3719,12 +3750,12 @@ def trapz(y, x=None, dx=1.0, axis=-1):
slice1[axis] = slice(1, None)
slice2[axis] = slice(None, -1)
try:
- ret = (d * (y[slice1] + y[slice2]) / 2.0).sum(axis)
+ ret = (d * (y[tuple(slice1)] + y[tuple(slice2)]) / 2.0).sum(axis)
except ValueError:
# Operations didn't work, cast to ndarray
d = np.asarray(d)
y = np.asarray(y)
- ret = add.reduce(d * (y[slice1]+y[slice2])/2.0, axis)
+ ret = add.reduce(d * (y[tuple(slice1)]+y[tuple(slice2)])/2.0, axis)
return ret
@@ -4013,7 +4044,7 @@ def delete(arr, obj, axis=None):
pass
else:
slobj[axis] = slice(None, start)
- new[slobj] = arr[slobj]
+ new[tuple(slobj)] = arr[tuple(slobj)]
# copy end chunck
if stop == N:
pass
@@ -4021,7 +4052,7 @@ def delete(arr, obj, axis=None):
slobj[axis] = slice(stop-numtodel, None)
slobj2 = [slice(None)]*ndim
slobj2[axis] = slice(stop, None)
- new[slobj] = arr[slobj2]
+ new[tuple(slobj)] = arr[tuple(slobj2)]
# copy middle pieces
if step == 1:
pass
@@ -4031,9 +4062,9 @@ def delete(arr, obj, axis=None):
slobj[axis] = slice(start, stop-numtodel)
slobj2 = [slice(None)]*ndim
slobj2[axis] = slice(start, stop)
- arr = arr[slobj2]
+ arr = arr[tuple(slobj2)]
slobj2[axis] = keep
- new[slobj] = arr[slobj2]
+ new[tuple(slobj)] = arr[tuple(slobj2)]
if wrap:
return wrap(new)
else:
@@ -4060,11 +4091,11 @@ def delete(arr, obj, axis=None):
newshape[axis] -= 1
new = empty(newshape, arr.dtype, arrorder)
slobj[axis] = slice(None, obj)
- new[slobj] = arr[slobj]
+ new[tuple(slobj)] = arr[tuple(slobj)]
slobj[axis] = slice(obj, None)
slobj2 = [slice(None)]*ndim
slobj2[axis] = slice(obj+1, None)
- new[slobj] = arr[slobj2]
+ new[tuple(slobj)] = arr[tuple(slobj2)]
else:
if obj.size == 0 and not isinstance(_obj, np.ndarray):
obj = obj.astype(intp)
@@ -4096,7 +4127,7 @@ def delete(arr, obj, axis=None):
keep[obj, ] = False
slobj[axis] = keep
- new = arr[slobj]
+ new = arr[tuple(slobj)]
if wrap:
return wrap(new)
@@ -4267,13 +4298,13 @@ def insert(arr, obj, values, axis=None):
newshape[axis] += numnew
new = empty(newshape, arr.dtype, arrorder)
slobj[axis] = slice(None, index)
- new[slobj] = arr[slobj]
+ new[tuple(slobj)] = arr[tuple(slobj)]
slobj[axis] = slice(index, index+numnew)
- new[slobj] = values
+ new[tuple(slobj)] = values
slobj[axis] = slice(index+numnew, None)
slobj2 = [slice(None)] * ndim
slobj2[axis] = slice(index, None)
- new[slobj] = arr[slobj2]
+ new[tuple(slobj)] = arr[tuple(slobj2)]
if wrap:
return wrap(new)
return new
@@ -4302,8 +4333,8 @@ def insert(arr, obj, values, axis=None):
slobj2 = [slice(None)]*ndim
slobj[axis] = indices
slobj2[axis] = old_mask
- new[slobj] = values
- new[slobj2] = arr
+ new[tuple(slobj)] = values
+ new[tuple(slobj2)] = arr
if wrap:
return wrap(new)
diff --git a/numpy/lib/histograms.py b/numpy/lib/histograms.py
index ccc6c0616..aa067a431 100644
--- a/numpy/lib/histograms.py
+++ b/numpy/lib/histograms.py
@@ -8,7 +8,7 @@ import operator
import numpy as np
from numpy.compat.py3k import basestring
-__all__ = ['histogram', 'histogramdd']
+__all__ = ['histogram', 'histogramdd', 'histogram_bin_edges']
def _hist_bin_sqrt(x):
@@ -348,10 +348,9 @@ def _search_sorted_inclusive(a, v):
))
-def histogram(a, bins=10, range=None, normed=False, weights=None,
- density=None):
+def histogram_bin_edges(a, bins=10, range=None, weights=None):
r"""
- Compute the histogram of a set of data.
+ Function to calculate only the edges of the bins used by the `histogram` function.
Parameters
----------
@@ -363,9 +362,7 @@ def histogram(a, bins=10, range=None, normed=False, weights=None,
sequence, it defines the bin edges, including the rightmost
edge, allowing for non-uniform bin widths.
- .. versionadded:: 1.11.0
-
- If `bins` is a string from the list below, `histogram` will use
+ If `bins` is a string from the list below, `histogram_bin_edges` will use
the method chosen to calculate the optimal bin width and
consequently the number of bins (see `Notes` for more detail on
the estimators) from the data that falls within the requested
@@ -412,57 +409,24 @@ def histogram(a, bins=10, range=None, normed=False, weights=None,
computation as well. While bin width is computed to be optimal
based on the actual data within `range`, the bin count will fill
the entire range including portions containing no data.
- normed : bool, optional
- This keyword is deprecated in NumPy 1.6.0 due to confusing/buggy
- behavior. It will be removed in NumPy 2.0.0. Use the ``density``
- keyword instead. If ``False``, the result will contain the
- number of samples in each bin. If ``True``, the result is the
- value of the probability *density* function at the bin,
- normalized such that the *integral* over the range is 1. Note
- that this latter behavior is known to be buggy with unequal bin
- widths; use ``density`` instead.
+
weights : array_like, optional
An array of weights, of the same shape as `a`. Each value in
`a` only contributes its associated weight towards the bin count
- (instead of 1). If `density` is True, the weights are
- normalized, so that the integral of the density over the range
- remains 1.
- density : bool, optional
- If ``False``, the result will contain the number of samples in
- each bin. If ``True``, the result is the value of the
- probability *density* function at the bin, normalized such that
- the *integral* over the range is 1. Note that the sum of the
- histogram values will not be equal to 1 unless bins of unity
- width are chosen; it is not a probability *mass* function.
-
- Overrides the ``normed`` keyword if given.
+ (instead of 1). This is currently not used by any of the bin estimators,
+ but may be in the future.
Returns
-------
- hist : array
- The values of the histogram. See `density` and `weights` for a
- description of the possible semantics.
bin_edges : array of dtype float
- Return the bin edges ``(length(hist)+1)``.
-
+ The edges to pass into `histogram`
See Also
--------
- histogramdd, bincount, searchsorted, digitize
+ histogram
Notes
-----
- All but the last (righthand-most) bin is half-open. In other words,
- if `bins` is::
-
- [1, 2, 3, 4]
-
- then the first bin is ``[1, 2)`` (including 1, but excluding 2) and
- the second ``[2, 3)``. The last bin, however, is ``[3, 4]``, which
- *includes* 4.
-
- .. versionadded:: 1.11.0
-
The methods to estimate the optimal number of bins are well founded
in literature, and are inspired by the choices R provides for
histogram visualisation. Note that having the number of bins
@@ -533,6 +497,134 @@ def histogram(a, bins=10, range=None, normed=False, weights=None,
Examples
--------
+ >>> arr = np.array([0, 0, 0, 1, 2, 3, 3, 4, 5])
+ >>> np.histogram_bin_edges(arr, bins='auto', range=(0, 1))
+ array([0. , 0.25, 0.5 , 0.75, 1. ])
+ >>> np.histogram_bin_edges(arr, bins=2)
+ array([0. , 2.5, 5. ])
+
+ For consistency with histogram, an array of pre-computed bins is
+ passed through unmodified:
+
+ >>> np.histogram_bin_edges(arr, [1, 2])
+ array([1, 2])
+
+ This function allows one set of bins to be computed, and reused across
+ multiple histograms:
+
+ >>> shared_bins = np.histogram_bin_edges(arr, bins='auto')
+ >>> shared_bins
+ array([0., 1., 2., 3., 4., 5.])
+
+ >>> group_id = np.array([0, 1, 1, 0, 1, 1, 0, 1, 1])
+ >>> hist_0, _ = np.histogram(arr[group_id == 0], bins=shared_bins)
+ >>> hist_1, _ = np.histogram(arr[group_id == 1], bins=shared_bins)
+
+ >>> hist_0; hist_1
+ array([1, 1, 0, 1, 0])
+ array([2, 0, 1, 1, 2])
+
+ Which gives more easily comparable results than using separate bins for
+ each histogram:
+
+ >>> hist_0, bins_0 = np.histogram(arr[group_id == 0], bins='auto')
+ >>> hist_1, bins_1 = np.histogram(arr[group_id == 1], bins='auto')
+ >>> hist_0; hist1
+ array([1, 1, 1])
+ array([2, 1, 1, 2])
+ >>> bins_0; bins_1
+ array([0., 1., 2., 3.])
+ array([0. , 1.25, 2.5 , 3.75, 5. ])
+
+ """
+ a, weights = _ravel_and_check_weights(a, weights)
+ bin_edges, _ = _get_bin_edges(a, bins, range, weights)
+ return bin_edges
+
+
+def histogram(a, bins=10, range=None, normed=False, weights=None,
+ density=None):
+ r"""
+ Compute the histogram of a set of data.
+
+ Parameters
+ ----------
+ a : array_like
+ Input data. The histogram is computed over the flattened array.
+ bins : int or sequence of scalars or str, optional
+ If `bins` is an int, it defines the number of equal-width
+ bins in the given range (10, by default). If `bins` is a
+ sequence, it defines the bin edges, including the rightmost
+ edge, allowing for non-uniform bin widths.
+
+ .. versionadded:: 1.11.0
+
+ If `bins` is a string, it defines the method used to calculate the
+ optimal bin width, as defined by `histogram_bin_edges`.
+
+ range : (float, float), optional
+ The lower and upper range of the bins. If not provided, range
+ is simply ``(a.min(), a.max())``. Values outside the range are
+ ignored. The first element of the range must be less than or
+ equal to the second. `range` affects the automatic bin
+ computation as well. While bin width is computed to be optimal
+ based on the actual data within `range`, the bin count will fill
+ the entire range including portions containing no data.
+ normed : bool, optional
+
+ .. deprecated:: 1.6.0
+
+ This keyword is deprecated in NumPy 1.6.0 due to confusing/buggy
+ behavior. It will be removed in NumPy 2.0.0. Use the ``density``
+ keyword instead. If ``False``, the result will contain the
+ number of samples in each bin. If ``True``, the result is the
+ value of the probability *density* function at the bin,
+ normalized such that the *integral* over the range is 1. Note
+ that this latter behavior is known to be buggy with unequal bin
+ widths; use ``density`` instead.
+ weights : array_like, optional
+ An array of weights, of the same shape as `a`. Each value in
+ `a` only contributes its associated weight towards the bin count
+ (instead of 1). If `density` is True, the weights are
+ normalized, so that the integral of the density over the range
+ remains 1.
+ density : bool, optional
+ If ``False``, the result will contain the number of samples in
+ each bin. If ``True``, the result is the value of the
+ probability *density* function at the bin, normalized such that
+ the *integral* over the range is 1. Note that the sum of the
+ histogram values will not be equal to 1 unless bins of unity
+ width are chosen; it is not a probability *mass* function.
+
+ Overrides the ``normed`` keyword if given.
+
+ Returns
+ -------
+ hist : array
+ The values of the histogram. See `density` and `weights` for a
+ description of the possible semantics.
+ bin_edges : array of dtype float
+ Return the bin edges ``(length(hist)+1)``.
+
+
+ See Also
+ --------
+ histogramdd, bincount, searchsorted, digitize, histogram_bin_edges
+
+ Notes
+ -----
+ All but the last (righthand-most) bin is half-open. In other words,
+ if `bins` is::
+
+ [1, 2, 3, 4]
+
+ then the first bin is ``[1, 2)`` (including 1, but excluding 2) and
+ the second ``[2, 3)``. The last bin, however, is ``[3, 4]``, which
+ *includes* 4.
+
+
+ Examples
+ --------
>>> np.histogram([1, 2, 1], bins=[0, 1, 2, 3])
(array([0, 2, 1]), array([0, 1, 2, 3]))
>>> np.histogram(np.arange(4), bins=np.arange(5), density=True)
@@ -860,7 +952,7 @@ def histogramdd(sample, bins=10, range=None, normed=False, weights=None):
ni[i], ni[j] = ni[j], ni[i]
# Remove outliers (indices 0 and -1 for each dimension).
- core = D*[slice(1, -1)]
+ core = D*(slice(1, -1),)
hist = hist[core]
# Normalize if normed is True
diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py
index 959574594..0f338d781 100644
--- a/numpy/lib/npyio.py
+++ b/numpy/lib/npyio.py
@@ -1104,7 +1104,7 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None,
nshape = list(X.shape)
pos = nshape[0]
nshape[0] += len(x)
- X.resize(nshape)
+ X.resize(nshape, refcheck=False)
X[pos:, ...] = x
finally:
if fown:
diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py
index 49b450175..c28257c6d 100644
--- a/numpy/lib/tests/test_function_base.py
+++ b/numpy/lib/tests/test_function_base.py
@@ -11,7 +11,7 @@ from numpy.testing import (
run_module_suite, assert_, assert_equal, assert_array_equal,
assert_almost_equal, assert_array_almost_equal, assert_raises,
assert_allclose, assert_array_max_ulp, assert_warns, assert_raises_regex,
- dec, suppress_warnings, HAS_REFCOUNT,
+ dec, suppress_warnings,
)
import numpy.lib.function_base as nfb
from numpy.random import rand
@@ -1752,7 +1752,9 @@ class TestCov(object):
def test_complex(self):
x = np.array([[1, 2, 3], [1j, 2j, 3j]])
- assert_allclose(cov(x), np.array([[1., -1.j], [1.j, 1.]]))
+ res = np.array([[1., -1.j], [1.j, 1.]])
+ assert_allclose(cov(x), res)
+ assert_allclose(cov(x, aweights=np.ones(3)), res)
def test_xy(self):
x = np.array([[1, 2, 3]])
@@ -2141,7 +2143,7 @@ class TestBincount(object):
"must not be negative",
lambda: np.bincount(x, minlength=-1))
- @dec.skipif(not HAS_REFCOUNT, "python has no sys.getrefcount")
+ @dec._needs_refcount
def test_dtype_reference_leaks(self):
# gh-6805
intp_refcount = sys.getrefcount(np.dtype(np.intp))
diff --git a/numpy/lib/tests/test_histograms.py b/numpy/lib/tests/test_histograms.py
index a2c684a20..4f7af214c 100644
--- a/numpy/lib/tests/test_histograms.py
+++ b/numpy/lib/tests/test_histograms.py
@@ -2,7 +2,7 @@ from __future__ import division, absolute_import, print_function
import numpy as np
-from numpy.lib.histograms import histogram, histogramdd
+from numpy.lib.histograms import histogram, histogramdd, histogram_bin_edges
from numpy.testing import (
run_module_suite, assert_, assert_equal, assert_array_equal,
assert_almost_equal, assert_array_almost_equal, assert_raises,
@@ -346,6 +346,20 @@ class TestHistogram(object):
self.do_precision(np.single, np.longdouble)
self.do_precision(np.double, np.longdouble)
+ def test_histogram_bin_edges(self):
+ hist, e = histogram([1, 2, 3, 4], [1, 2])
+ edges = histogram_bin_edges([1, 2, 3, 4], [1, 2])
+ assert_array_equal(edges, e)
+
+ arr = np.array([0., 0., 0., 1., 2., 3., 3., 4., 5.])
+ hist, e = histogram(arr, bins=30, range=(-0.5, 5))
+ edges = histogram_bin_edges(arr, bins=30, range=(-0.5, 5))
+ assert_array_equal(edges, e)
+
+ hist, e = histogram(arr, bins='auto', range=(0, 1))
+ edges = histogram_bin_edges(arr, bins='auto', range=(0, 1))
+ assert_array_equal(edges, e)
+
class TestHistogramOptimBinNums(object):
"""
diff --git a/numpy/lib/tests/test_io.py b/numpy/lib/tests/test_io.py
index ae40cf73b..5d7dc32dd 100644
--- a/numpy/lib/tests/test_io.py
+++ b/numpy/lib/tests/test_io.py
@@ -22,7 +22,7 @@ from numpy.ma.testutils import assert_equal
from numpy.testing import (
run_module_suite, assert_warns, assert_, SkipTest,
assert_raises_regex, assert_raises, assert_allclose,
- assert_array_equal, temppath, tempdir, dec, IS_PYPY, suppress_warnings
+ assert_array_equal, temppath, tempdir, dec, IS_PYPY, suppress_warnings,
)
@@ -599,11 +599,11 @@ class LoadTxtBase(object):
class TestLoadTxt(LoadTxtBase):
loadfunc = staticmethod(np.loadtxt)
- def setUp(self):
+ def setup(self):
# lower chunksize for testing
self.orig_chunk = np.lib.npyio._loadtxt_chunksize
np.lib.npyio._loadtxt_chunksize = 1
- def tearDown(self):
+ def teardown(self):
np.lib.npyio._loadtxt_chunksize = self.orig_chunk
def test_record(self):
@@ -2364,6 +2364,7 @@ def test_npzfile_dict():
assert_('x' in z.keys())
+@dec._needs_refcount
def test_load_refcount():
# Check that objects returned by np.load are directly freed based on
# their refcount, rather than needing the gc to collect them.
diff --git a/numpy/lib/tests/test_stride_tricks.py b/numpy/lib/tests/test_stride_tricks.py
index 0599324d7..475119481 100644
--- a/numpy/lib/tests/test_stride_tricks.py
+++ b/numpy/lib/tests/test_stride_tricks.py
@@ -1,7 +1,7 @@
from __future__ import division, absolute_import, print_function
import numpy as np
-from numpy.core.test_rational import rational
+from numpy.core._rational_tests import rational
from numpy.testing import (
run_module_suite, assert_equal, assert_array_equal,
assert_raises, assert_
diff --git a/numpy/linalg/__init__.py b/numpy/linalg/__init__.py
index 2537926c5..1510a8448 100644
--- a/numpy/linalg/__init__.py
+++ b/numpy/linalg/__init__.py
@@ -52,4 +52,3 @@ from .linalg import *
from numpy.testing import _numpy_tester
test = _numpy_tester().test
-bench = _numpy_tester().bench
diff --git a/numpy/ma/__init__.py b/numpy/ma/__init__.py
index fbefc47a4..0689f2932 100644
--- a/numpy/ma/__init__.py
+++ b/numpy/ma/__init__.py
@@ -53,4 +53,3 @@ __all__ += extras.__all__
from numpy.testing import _numpy_tester
test = _numpy_tester().test
-bench = _numpy_tester().bench
diff --git a/numpy/ma/core.py b/numpy/ma/core.py
index 698d39cda..91cf8ed0f 100644
--- a/numpy/ma/core.py
+++ b/numpy/ma/core.py
@@ -26,6 +26,7 @@ import sys
import operator
import warnings
import textwrap
+import re
from functools import reduce
if sys.version_info[0] >= 3:
@@ -132,19 +133,17 @@ def doc_note(initialdoc, note):
if note is None:
return initialdoc
- # FIXME: disable this function for the moment until we figure out what to
- # do with it. Currently it may result in duplicate Notes sections or Notes
- # sections in the wrong place
- return initialdoc
+ notesplit = re.split(r'\n\s*?Notes\n\s*?-----', initialdoc)
- newdoc = """
- %s
-
- Notes
+ notedoc = """\
+Notes
-----
- %s
- """
- return newdoc % (initialdoc, note)
+ %s""" % note
+
+ if len(notesplit) > 1:
+ notedoc = '\n\n ' + notedoc + '\n'
+
+ return ''.join(notesplit[:1] + [notedoc] + notesplit[1:])
def get_object_signature(obj):
@@ -5318,7 +5317,7 @@ class MaskedArray(ndarray):
originally intended.
Until then, the axis should be given explicitly when
``arr.ndim > 1``, to avoid a FutureWarning.
- kind : {'quicksort', 'mergesort', 'heapsort'}, optional
+ kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional
Sorting algorithm.
order : list, optional
When `a` is an array with fields defined, this argument specifies
@@ -5469,7 +5468,7 @@ class MaskedArray(ndarray):
axis : int, optional
Axis along which to sort. If None, the array is flattened before
sorting. The default is -1, which sorts along the last axis.
- kind : {'quicksort', 'mergesort', 'heapsort'}, optional
+ kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional
Sorting algorithm. Default is 'quicksort'.
order : list, optional
When `a` is a structured array, this argument specifies which fields
@@ -5538,6 +5537,7 @@ class MaskedArray(ndarray):
else:
idx = list(np.ix_(*[np.arange(x) for x in self.shape]))
idx[axis] = sidx
+ idx = tuple(idx)
self[...] = self[idx]
diff --git a/numpy/ma/extras.py b/numpy/ma/extras.py
index 99f5234d1..8272dced9 100644
--- a/numpy/ma/extras.py
+++ b/numpy/ma/extras.py
@@ -724,6 +724,7 @@ def _median(a, axis=None, out=None, overwrite_input=False):
# as median (which is mean of empty slice = nan)
indexer = [slice(None)] * asorted.ndim
indexer[axis] = slice(0, 0)
+ indexer = tuple(indexer)
return np.ma.mean(asorted[indexer], axis=axis, out=out)
if asorted.ndim == 1:
@@ -1619,7 +1620,10 @@ def flatnotmasked_contiguous(a):
Returns
-------
slice_list : list
- A sorted sequence of slices (start index, end index).
+ A sorted sequence of `slice` objects (start index, end index).
+
+ ..versionchanged:: 1.15.0
+ Now returns an empty list instead of None for a fully masked array
See Also
--------
@@ -1634,7 +1638,7 @@ def flatnotmasked_contiguous(a):
--------
>>> a = np.ma.arange(10)
>>> np.ma.flatnotmasked_contiguous(a)
- slice(0, 10, None)
+ [slice(0, 10, None)]
>>> mask = (a < 3) | (a > 8) | (a == 5)
>>> a[mask] = np.ma.masked
@@ -1644,13 +1648,13 @@ def flatnotmasked_contiguous(a):
>>> np.ma.flatnotmasked_contiguous(a)
[slice(3, 5, None), slice(6, 9, None)]
>>> a[:] = np.ma.masked
- >>> print(np.ma.flatnotmasked_edges(a))
- None
+ >>> np.ma.flatnotmasked_contiguous(a)
+ []
"""
m = getmask(a)
if m is nomask:
- return slice(0, a.size, None)
+ return [slice(0, a.size)]
i = 0
result = []
for (k, g) in itertools.groupby(m.ravel()):
@@ -1658,7 +1662,7 @@ def flatnotmasked_contiguous(a):
if not k:
result.append(slice(i, i + n))
i += n
- return result or None
+ return result
def notmasked_contiguous(a, axis=None):
"""
@@ -1670,7 +1674,8 @@ def notmasked_contiguous(a, axis=None):
The input array.
axis : int, optional
Axis along which to perform the operation.
- If None (default), applies to a flattened version of the array.
+ If None (default), applies to a flattened version of the array, and this
+ is the same as `flatnotmasked_contiguous`.
Returns
-------
@@ -1678,6 +1683,8 @@ def notmasked_contiguous(a, axis=None):
A list of slices (start and end indexes) of unmasked indexes
in the array.
+ If the input is 2d and axis is specified, the result is a list of lists.
+
See Also
--------
flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges,
@@ -1689,17 +1696,35 @@ def notmasked_contiguous(a, axis=None):
Examples
--------
- >>> a = np.arange(9).reshape((3, 3))
+ >>> a = np.arange(12).reshape((3, 4))
>>> mask = np.zeros_like(a)
- >>> mask[1:, 1:] = 1
-
+ >>> mask[1:, :-1] = 1; mask[0, 1] = 1; mask[-1, 0] = 0
>>> ma = np.ma.array(a, mask=mask)
+ >>> ma
+ masked_array(
+ data=[[0, --, 2, 3],
+ [--, --, --, 7],
+ [8, --, --, 11]],
+ mask=[[False, True, False, False],
+ [ True, True, True, False],
+ [False, True, True, False]],
+ fill_value=999999)
>>> np.array(ma[~ma.mask])
- array([0, 1, 2, 3, 6])
+ array([ 0, 2, 3, 7, 8, 11])
>>> np.ma.notmasked_contiguous(ma)
- [slice(0, 4, None), slice(6, 7, None)]
+ [slice(0, 1, None), slice(2, 4, None), slice(7, 9, None), slice(11, 12, None)]
+
+ >>> np.ma.notmasked_contiguous(ma, axis=0)
+ [[slice(0, 1, None), slice(2, 3, None)], # column broken into two segments
+ [], # fully masked column
+ [slice(0, 1, None)],
+ [slice(0, 3, None)]]
+ >>> np.ma.notmasked_contiguous(ma, axis=1)
+ [[slice(0, 1, None), slice(2, 4, None)], # row broken into two segments
+ [slice(3, 4, None)],
+ [slice(0, 1, None), slice(3, 4, None)]]
"""
a = asarray(a)
nd = a.ndim
@@ -1716,7 +1741,7 @@ def notmasked_contiguous(a, axis=None):
#
for i in range(a.shape[other]):
idx[other] = i
- result.append(flatnotmasked_contiguous(a[idx]) or None)
+ result.append(flatnotmasked_contiguous(a[tuple(idx)]))
return result
diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py
index 4c6bb2b42..ff1e087b5 100644
--- a/numpy/ma/tests/test_core.py
+++ b/numpy/ma/tests/test_core.py
@@ -3200,6 +3200,12 @@ class TestMaskedArrayMethods(object):
assert_equal(sortedx._data, [1, 2, -2, -1, 0])
assert_equal(sortedx._mask, [1, 1, 0, 0, 0])
+ def test_stable_sort(self):
+ x = array([1, 2, 3, 1, 2, 3], dtype=np.uint8)
+ expected = array([0, 3, 1, 4, 2, 5])
+ computed = argsort(x, kind='stable')
+ assert_equal(computed, expected)
+
def test_argsort_matches_sort(self):
x = array([1, 4, 2, 3], mask=[0, 1, 0, 0], dtype=np.uint8)
diff --git a/numpy/ma/tests/test_extras.py b/numpy/ma/tests/test_extras.py
index d1c1aa63e..95319eb65 100644
--- a/numpy/ma/tests/test_extras.py
+++ b/numpy/ma/tests/test_extras.py
@@ -128,7 +128,10 @@ class TestGeneric(object):
a = arange(10)
# No mask
test = flatnotmasked_contiguous(a)
- assert_equal(test, slice(0, a.size))
+ assert_equal(test, [slice(0, a.size)])
+ # mask of all false
+ a.mask = np.zeros(10, dtype=bool)
+ assert_equal(test, [slice(0, a.size)])
# Some mask
a[(a < 3) | (a > 8) | (a == 5)] = masked
test = flatnotmasked_contiguous(a)
@@ -136,7 +139,7 @@ class TestGeneric(object):
#
a[:] = masked
test = flatnotmasked_contiguous(a)
- assert_equal(test, None)
+ assert_equal(test, [])
class TestAverage(object):
@@ -368,23 +371,32 @@ class TestNotMasked(object):
a = masked_array(np.arange(24).reshape(3, 8),
mask=[[0, 0, 0, 0, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1],
- [0, 0, 0, 0, 0, 0, 1, 0], ])
+ [0, 0, 0, 0, 0, 0, 1, 0]])
tmp = notmasked_contiguous(a, None)
- assert_equal(tmp[-1], slice(23, 24, None))
- assert_equal(tmp[-2], slice(16, 22, None))
- assert_equal(tmp[-3], slice(0, 4, None))
- #
+ assert_equal(tmp, [
+ slice(0, 4, None),
+ slice(16, 22, None),
+ slice(23, 24, None)
+ ])
+
tmp = notmasked_contiguous(a, 0)
- assert_(len(tmp[-1]) == 1)
- assert_(tmp[-2] is None)
- assert_equal(tmp[-3], tmp[-1])
- assert_(len(tmp[0]) == 2)
+ assert_equal(tmp, [
+ [slice(0, 1, None), slice(2, 3, None)],
+ [slice(0, 1, None), slice(2, 3, None)],
+ [slice(0, 1, None), slice(2, 3, None)],
+ [slice(0, 1, None), slice(2, 3, None)],
+ [slice(2, 3, None)],
+ [slice(2, 3, None)],
+ [],
+ [slice(2, 3, None)]
+ ])
#
tmp = notmasked_contiguous(a, 1)
- assert_equal(tmp[0][-1], slice(0, 4, None))
- assert_(tmp[1] is None)
- assert_equal(tmp[2][-1], slice(7, 8, None))
- assert_equal(tmp[2][-2], slice(0, 6, None))
+ assert_equal(tmp, [
+ [slice(0, 4, None)],
+ [],
+ [slice(0, 6, None), slice(7, 8, None)]
+ ])
class TestCompressFunctions(object):
diff --git a/numpy/ma/testutils.py b/numpy/ma/testutils.py
index a95c170c8..c4ee639ed 100644
--- a/numpy/ma/testutils.py
+++ b/numpy/ma/testutils.py
@@ -14,7 +14,7 @@ from numpy import ndarray, float_
import numpy.core.umath as umath
import numpy.testing
from numpy.testing import (
- TestCase, assert_, assert_allclose, assert_array_almost_equal_nulp,
+ assert_, assert_allclose, assert_array_almost_equal_nulp,
assert_raises, build_err_msg, run_module_suite
)
from .core import mask_or, getmask, masked_array, nomask, masked, filled
@@ -31,6 +31,7 @@ __all__masked = [
# have mistakenly included them from this file. SciPy is one. That is
# unfortunate, as some of these functions are not intended to work with
# masked arrays. But there was no way to tell before.
+from unittest import TestCase
__some__from_testing = [
'TestCase', 'assert_', 'assert_allclose',
'assert_array_almost_equal_nulp', 'assert_raises', 'run_module_suite',
diff --git a/numpy/matrixlib/__init__.py b/numpy/matrixlib/__init__.py
index 11dce2928..95713580d 100644
--- a/numpy/matrixlib/__init__.py
+++ b/numpy/matrixlib/__init__.py
@@ -9,4 +9,3 @@ __all__ = defmatrix.__all__
from numpy.testing import _numpy_tester
test = _numpy_tester().test
-bench = _numpy_tester().bench
diff --git a/numpy/matrixlib/tests/test_defmatrix.py b/numpy/matrixlib/tests/test_defmatrix.py
index 77f262031..d5435a1a3 100644
--- a/numpy/matrixlib/tests/test_defmatrix.py
+++ b/numpy/matrixlib/tests/test_defmatrix.py
@@ -1,6 +1,11 @@
from __future__ import division, absolute_import, print_function
-import collections
+try:
+ # Accessing collections abstract classes from collections
+ # has been deprecated since Python 3.3
+ import collections.abc as collections_abc
+except ImportError:
+ import collections as collections_abc
import numpy as np
from numpy import matrix, asmatrix, bmat
@@ -302,7 +307,7 @@ class TestMatrixReturn(object):
if attrib.startswith('_') or attrib in excluded_methods:
continue
f = getattr(a, attrib)
- if isinstance(f, collections.Callable):
+ if isinstance(f, collections_abc.Callable):
# reset contents of a
a.astype('f8')
a.fill(1.0)
diff --git a/numpy/polynomial/__init__.py b/numpy/polynomial/__init__.py
index ae5b1f078..f7cbc19b0 100644
--- a/numpy/polynomial/__init__.py
+++ b/numpy/polynomial/__init__.py
@@ -24,4 +24,3 @@ from .laguerre import Laguerre
from numpy.testing import _numpy_tester
test = _numpy_tester().test
-bench = _numpy_tester().bench
diff --git a/numpy/random/__init__.py b/numpy/random/__init__.py
index 869818a22..409f50ec0 100644
--- a/numpy/random/__init__.py
+++ b/numpy/random/__init__.py
@@ -119,4 +119,3 @@ def __RandomState_ctor():
from numpy.testing import _numpy_tester
test = _numpy_tester().test
-bench = _numpy_tester().bench
diff --git a/numpy/testing/__init__.py b/numpy/testing/__init__.py
index 9485b455e..f4970b06b 100644
--- a/numpy/testing/__init__.py
+++ b/numpy/testing/__init__.py
@@ -9,7 +9,12 @@ from __future__ import division, absolute_import, print_function
from unittest import TestCase
-from . import decorators as dec
-from .nosetester import run_module_suite, NoseTester as Tester, _numpy_tester
-from .utils import *
+from ._private.utils import *
+from ._private import decorators as dec
+from ._private.nosetester import (
+ run_module_suite, NoseTester as Tester, _numpy_tester,
+ )
+
+__all__ = _private.utils.__all__ + ['TestCase', 'run_module_suite']
+
test = _numpy_tester().test
diff --git a/numpy/testing/nose_tools/__init__.py b/numpy/testing/_private/__init__.py
index e69de29bb..e69de29bb 100644
--- a/numpy/testing/nose_tools/__init__.py
+++ b/numpy/testing/_private/__init__.py
diff --git a/numpy/testing/nose_tools/decorators.py b/numpy/testing/_private/decorators.py
index 243c0c8c1..60d3f968f 100644
--- a/numpy/testing/nose_tools/decorators.py
+++ b/numpy/testing/_private/decorators.py
@@ -15,12 +15,17 @@ function name, setup and teardown functions and so on - see
"""
from __future__ import division, absolute_import, print_function
-import collections
+try:
+ # Accessing collections abstract classes from collections
+ # has been deprecated since Python 3.3
+ import collections.abc as collections_abc
+except ImportError:
+ import collections as collections_abc
-from .utils import SkipTest, assert_warns
+from .utils import SkipTest, assert_warns, HAS_REFCOUNT
__all__ = ['slow', 'setastest', 'skipif', 'knownfailureif', 'deprecated',
- 'parametrize',]
+ 'parametrize', '_needs_refcount',]
def slow(t):
@@ -126,7 +131,7 @@ def skipif(skip_condition, msg=None):
import nose
# Allow for both boolean or callable skip conditions.
- if isinstance(skip_condition, collections.Callable):
+ if isinstance(skip_condition, collections_abc.Callable):
skip_val = lambda: skip_condition()
else:
skip_val = lambda: skip_condition
@@ -202,7 +207,7 @@ def knownfailureif(fail_condition, msg=None):
msg = 'Test skipped due to known failure'
# Allow for both boolean or callable known failure conditions.
- if isinstance(fail_condition, collections.Callable):
+ if isinstance(fail_condition, collections_abc.Callable):
fail_val = lambda: fail_condition()
else:
fail_val = lambda: fail_condition
@@ -257,7 +262,7 @@ def deprecated(conditional=True):
with assert_warns(DeprecationWarning):
f(*args, **kwargs)
- if isinstance(conditional, collections.Callable):
+ if isinstance(conditional, collections_abc.Callable):
cond = conditional()
else:
cond = conditional
@@ -283,3 +288,5 @@ def parametrize(vars, input):
from .parameterized import parameterized
return parameterized(input)
+
+_needs_refcount = skipif(not HAS_REFCOUNT, "python has no sys.getrefcount")
diff --git a/numpy/testing/nose_tools/noseclasses.py b/numpy/testing/_private/noseclasses.py
index 9756b9b45..08dec0ca9 100644
--- a/numpy/testing/nose_tools/noseclasses.py
+++ b/numpy/testing/_private/noseclasses.py
@@ -325,7 +325,7 @@ class FPUModeCheckPlugin(Plugin):
"""
def prepareTestCase(self, test):
- from numpy.core.multiarray_tests import get_fpu_mode
+ from numpy.core._multiarray_tests import get_fpu_mode
def run(result):
old_mode = get_fpu_mode()
diff --git a/numpy/testing/nose_tools/nosetester.py b/numpy/testing/_private/nosetester.py
index c2cf58377..c2cf58377 100644
--- a/numpy/testing/nose_tools/nosetester.py
+++ b/numpy/testing/_private/nosetester.py
diff --git a/numpy/testing/nose_tools/parameterized.py b/numpy/testing/_private/parameterized.py
index 53e67517d..53e67517d 100644
--- a/numpy/testing/nose_tools/parameterized.py
+++ b/numpy/testing/_private/parameterized.py
diff --git a/numpy/testing/_private/pytesttester.py b/numpy/testing/_private/pytesttester.py
new file mode 100644
index 000000000..6a92a52fd
--- /dev/null
+++ b/numpy/testing/_private/pytesttester.py
@@ -0,0 +1,175 @@
+"""
+Pytest test running.
+
+This module implements the ``test()`` function for NumPy modules. The usual
+boiler plate for doing that is to put the following in the module
+``__init__.py`` file::
+
+ from numpy.testing import PytestTester
+ test = PytestTester(__name__).test
+ del PytestTester
+
+
+Warnings filtering and other runtime settings should be dealt with in the
+``pytest.ini`` file in the numpy repo root. The behavior of the test depends on
+whether or not that file is found as follows:
+
+* ``pytest.ini`` is present (develop mode)
+ All warnings except those explicily filtered out are raised as error.
+* ``pytest.ini`` is absent (release mode)
+ DeprecationWarnings and PendingDeprecationWarnings are ignored, other
+ warnings are passed through.
+
+In practice, tests run from the numpy repo are run in develop mode. That
+includes the standard ``python runtests.py`` invocation.
+
+"""
+from __future__ import division, absolute_import, print_function
+
+import sys
+import os
+
+__all__ = ['PytestTester']
+
+
+def _show_numpy_info():
+ import numpy as np
+
+ print("NumPy version %s" % np.__version__)
+ relaxed_strides = np.ones((10, 1), order="C").flags.f_contiguous
+ print("NumPy relaxed strides checking option:", relaxed_strides)
+
+
+class PytestTester(object):
+ """
+ Pytest test runner.
+
+ This class is made available in ``numpy.testing``, and a test function
+ is typically added to a package's __init__.py like so::
+
+ from numpy.testing import PytestTester
+ test = PytestTester(__name__).test
+ del PytestTester
+
+ Calling this test function finds and runs all tests associated with the
+ module and all its sub-modules.
+
+ Attributes
+ ----------
+ module_name : str
+ Full path to the package to test.
+
+ Parameters
+ ----------
+ module_name : module name
+ The name of the module to test.
+
+ """
+ def __init__(self, module_name):
+ self.module_name = module_name
+
+ def test(self, label='fast', verbose=1, extra_argv=None,
+ doctests=False, coverage=False, timer=0, tests=None):
+ """
+ Run tests for module using pytest.
+
+ Parameters
+ ----------
+ label : {'fast', 'full'}, optional
+ Identifies the tests to run. When set to 'fast', tests decorated
+ with `pytest.mark.slow` are skipped, when 'full', the slow marker
+ is ignored.
+ verbose : int, optional
+ Verbosity value for test outputs, in the range 1-3. Default is 1.
+ extra_argv : list, optional
+ List with any extra arguments to pass to pytests.
+ doctests : bool, optional
+ .. note:: Not supported
+ coverage : bool, optional
+ If True, report coverage of NumPy code. Default is False.
+ Requires installation of (pip) pytest-cov.
+ timer : int, optional
+ If > 0, report the time of the slowest `timer` tests. Default is 0.
+
+ tests : test or list of tests
+ Tests to be executed with pytest '--pyargs'
+
+ Returns
+ -------
+ result : bool
+ Return True on success, false otherwise.
+
+ Notes
+ -----
+ Each NumPy module exposes `test` in its namespace to run all tests for it.
+ For example, to run all tests for numpy.lib:
+
+ >>> np.lib.test() #doctest: +SKIP
+
+ Examples
+ --------
+ >>> result = np.lib.test() #doctest: +SKIP
+ Running unit tests for numpy.lib
+ ...
+ Ran 976 tests in 3.933s
+
+ OK
+
+ >>> result.errors #doctest: +SKIP
+ []
+ >>> result.knownfail #doctest: +SKIP
+ []
+
+ """
+ import pytest
+
+ #FIXME This is no longer needed? Assume it was for use in tests.
+ # cap verbosity at 3, which is equivalent to the pytest '-vv' option
+ #from . import utils
+ #verbose = min(int(verbose), 3)
+ #utils.verbose = verbose
+ #
+
+ module = sys.modules[self.module_name]
+ module_path = os.path.abspath(module.__path__[0])
+
+ # setup the pytest arguments
+ pytest_args = ['-l']
+
+ if doctests:
+ raise ValueError("Doctests not supported")
+
+ if extra_argv:
+ pytest_args += list(extra_argv)
+
+ if verbose > 1:
+ pytest_args += ["-" + "v"*(verbose - 1)]
+ else:
+ pytest_args += ["-q"]
+
+ if coverage:
+ pytest_args += ["--cov=" + module_path]
+
+ if label == "fast":
+ pytest_args += ["-m", "not slow"]
+ elif label != "full":
+ pytest_args += ["-m", label]
+
+ if timer > 0:
+ pytest_args += ["--durations=%s" % timer]
+
+ if tests is None:
+ tests = [self.module_name]
+
+ pytest_args += ['--pyargs'] + list(tests)
+
+
+ # run tests.
+ _show_numpy_info()
+
+ try:
+ code = pytest.main(pytest_args)
+ except SystemExit as exc:
+ code = exc.code
+
+ return code == 0
diff --git a/numpy/testing/nose_tools/utils.py b/numpy/testing/_private/utils.py
index 2d97b5c1e..507ecb1e2 100644
--- a/numpy/testing/nose_tools/utils.py
+++ b/numpy/testing/_private/utils.py
@@ -1156,10 +1156,54 @@ def rundocs(filename=None, raise_on_error=True):
raise AssertionError("Some doctests failed:\n%s" % "\n".join(msg))
-def raises(*args,**kwargs):
+def raises(*args):
+ """Decorator to check for raised exceptions.
+
+ The decorated test function must raise one of the passed exceptions to
+ pass. If you want to test many assertions about exceptions in a single
+ test, you may want to use `assert_raises` instead.
+
+ .. warning::
+ This decorator is nose specific, do not use it if you are using a
+ different test framework.
+
+ Parameters
+ ----------
+ args : exceptions
+ The test passes if any of the passed exceptions is raised.
+
+ Raises
+ ------
+ AssertionError
+
+ Examples
+ --------
+
+ Usage::
+
+ @raises(TypeError, ValueError)
+ def test_raises_type_error():
+ raise TypeError("This test passes")
+
+ @raises(Exception)
+ def test_that_fails_by_passing():
+ pass
+
+ """
nose = import_nose()
- return nose.tools.raises(*args,**kwargs)
+ return nose.tools.raises(*args)
+#
+# assert_raises and assert_raises_regex are taken from unittest.
+#
+import unittest
+
+
+class _Dummy(unittest.TestCase):
+ def nop(self):
+ pass
+
+_d = _Dummy('nop')
def assert_raises(*args, **kwargs):
"""
@@ -1187,8 +1231,7 @@ def assert_raises(*args, **kwargs):
"""
__tracebackhide__ = True # Hide traceback for py.test
- nose = import_nose()
- return nose.tools.assert_raises(*args,**kwargs)
+ return _d.assertRaises(*args,**kwargs)
def assert_raises_regex(exception_class, expected_regexp, *args, **kwargs):
@@ -1212,13 +1255,12 @@ def assert_raises_regex(exception_class, expected_regexp, *args, **kwargs):
"""
__tracebackhide__ = True # Hide traceback for py.test
- nose = import_nose()
if sys.version_info.major >= 3:
- funcname = nose.tools.assert_raises_regex
+ funcname = _d.assertRaisesRegex
else:
# Only present in Python 2.7, missing from unittest in 2.6
- funcname = nose.tools.assert_raises_regexp
+ funcname = _d.assertRaisesRegexp
return funcname(exception_class, expected_regexp, *args, **kwargs)
@@ -1577,7 +1619,9 @@ def integer_repr(x):
"""Return the signed-magnitude interpretation of the binary representation of
x."""
import numpy as np
- if x.dtype == np.float32:
+ if x.dtype == np.float16:
+ return _integer_repr(x, np.int16, np.int16(-2**15))
+ elif x.dtype == np.float32:
return _integer_repr(x, np.int32, np.int32(-2**31))
elif x.dtype == np.float64:
return _integer_repr(x, np.int64, np.int64(-2**63))
diff --git a/numpy/testing/decorators.py b/numpy/testing/decorators.py
index 21bcdd798..1988afd29 100644
--- a/numpy/testing/decorators.py
+++ b/numpy/testing/decorators.py
@@ -3,6 +3,9 @@ Back compatibility decorators module. It will import the appropriate
set of tools
"""
-import os
+import warnings
-from .nose_tools.decorators import *
+warnings.warn("Import from numpy.testing, not numpy.testing.decorators",
+ ImportWarning)
+
+from ._private.decorators import *
diff --git a/numpy/testing/noseclasses.py b/numpy/testing/noseclasses.py
index 144c4e7e4..dde62e825 100644
--- a/numpy/testing/noseclasses.py
+++ b/numpy/testing/noseclasses.py
@@ -2,4 +2,10 @@
Back compatibility noseclasses module. It will import the appropriate
set of tools
"""
-from .nose_tools.noseclasses import * \ No newline at end of file
+import warnings
+
+warnings.warn("Import from numpy.testing, not numpy.testing.noseclasses",
+ ImportWarning)
+
+from ._private.noseclasses import *
+
diff --git a/numpy/testing/nosetester.py b/numpy/testing/nosetester.py
index 949fae03e..772bff305 100644
--- a/numpy/testing/nosetester.py
+++ b/numpy/testing/nosetester.py
@@ -3,10 +3,12 @@ Back compatibility nosetester module. It will import the appropriate
set of tools
"""
-import os
+import warnings
-from .nose_tools.nosetester import *
+warnings.warn("Import from numpy.testing, not numpy.testing.nosetester",
+ ImportWarning)
+from ._private.nosetester import *
__all__ = ['get_package_name', 'run_module_suite', 'NoseTester',
'_numpy_tester', 'get_package_name', 'import_nose',
diff --git a/numpy/testing/pytest_tools/decorators.py b/numpy/testing/pytest_tools/decorators.py
index 08a39e0c0..e72b1eb0b 100644
--- a/numpy/testing/pytest_tools/decorators.py
+++ b/numpy/testing/pytest_tools/decorators.py
@@ -12,12 +12,17 @@ function name, setup and teardown functions and so on.
"""
from __future__ import division, absolute_import, print_function
-import collections
+try:
+ # Accessing collections abstract classes from collections
+ # has been deprecated since Python 3.3
+ import collections.abc as collections_abc
+except ImportError:
+ import collections as collections_abc
-from .utils import SkipTest, assert_warns
+from .utils import SkipTest, assert_warns, HAS_REFCOUNT
__all__ = ['slow', 'setastest', 'skipif', 'knownfailureif', 'deprecated',
- 'parametrize',]
+ 'parametrize', '_needs_refcount',]
def slow(t):
@@ -127,7 +132,7 @@ def skipif(skip_condition, msg=None):
out = msg
# Allow for both boolean or callable skip conditions.
- if isinstance(skip_condition, collections.Callable):
+ if isinstance(skip_condition, collections_abc.Callable):
skip_val = lambda: skip_condition()
else:
skip_val = lambda: skip_condition
@@ -203,7 +208,7 @@ def knownfailureif(fail_condition, msg=None):
msg = 'Test skipped due to known failure'
# Allow for both boolean or callable known failure conditions.
- if isinstance(fail_condition, collections.Callable):
+ if isinstance(fail_condition, collections_abc.Callable):
fail_val = lambda: fail_condition()
else:
fail_val = lambda: fail_condition
@@ -252,7 +257,7 @@ def deprecated(conditional=True):
with assert_warns(DeprecationWarning):
f(*args, **kwargs)
- if isinstance(conditional, collections.Callable):
+ if isinstance(conditional, collections_abc.Callable):
cond = conditional()
else:
cond = conditional
@@ -276,3 +281,6 @@ def parametrize(vars, input):
import pytest
return pytest.mark.parametrize(vars, input)
+
+
+_needs_refcount = skipif(not HAS_REFCOUNT, "python has no sys.getrefcount")
diff --git a/numpy/testing/pytest_tools/utils.py b/numpy/testing/pytest_tools/utils.py
index 8a0eb8be3..9640d48c3 100644
--- a/numpy/testing/pytest_tools/utils.py
+++ b/numpy/testing/pytest_tools/utils.py
@@ -1619,7 +1619,9 @@ def integer_repr(x):
"""Return the signed-magnitude interpretation of the binary representation of
x."""
import numpy as np
- if x.dtype == np.float32:
+ if x.dtype == np.float16:
+ return _integer_repr(x, np.int16, np.int16(-2**15))
+ elif x.dtype == np.float32:
return _integer_repr(x, np.int32, np.int32(-2**31))
elif x.dtype == np.float64:
return _integer_repr(x, np.int64, np.int64(-2**63))
diff --git a/numpy/testing/setup.py b/numpy/testing/setup.py
index 5a0f977d9..b00e5e029 100755
--- a/numpy/testing/setup.py
+++ b/numpy/testing/setup.py
@@ -6,7 +6,7 @@ def configuration(parent_package='',top_path=None):
from numpy.distutils.misc_util import Configuration
config = Configuration('testing', parent_package, top_path)
- config.add_subpackage('nose_tools')
+ config.add_subpackage('_private')
config.add_subpackage('pytest_tools')
config.add_data_dir('tests')
return config
diff --git a/numpy/testing/tests/test_utils.py b/numpy/testing/tests/test_utils.py
index 77fb974cf..d5c582ad3 100644
--- a/numpy/testing/tests/test_utils.py
+++ b/numpy/testing/tests/test_utils.py
@@ -16,7 +16,6 @@ from numpy.testing import (
clear_and_catch_warnings, suppress_warnings, run_module_suite,
assert_string_equal, assert_, tempdir, temppath,
)
-import unittest
class _GenericTest(object):
@@ -69,9 +68,9 @@ class _GenericTest(object):
self._test_equal([1, 2, 3], (1, 2, 3))
-class TestArrayEqual(_GenericTest, unittest.TestCase):
+class TestArrayEqual(_GenericTest):
- def setUp(self):
+ def setup(self):
self._assert_func = assert_array_equal
def test_generic_rank1(self):
@@ -149,10 +148,10 @@ class TestArrayEqual(_GenericTest, unittest.TestCase):
with suppress_warnings() as sup:
l = sup.record(FutureWarning, message="elementwise == ")
self._test_not_equal(c, b)
- assert_(len(l) == 1)
+ assert_equal(len(l), 1)
-class TestBuildErrorMessage(unittest.TestCase):
+class TestBuildErrorMessage(object):
def test_build_err_msg_defaults(self):
x = np.array([1.00001, 2.00002, 3.00003])
@@ -163,7 +162,7 @@ class TestBuildErrorMessage(unittest.TestCase):
b = ('\nItems are not equal: There is a mismatch\n ACTUAL: array(['
'1.00001, 2.00002, 3.00003])\n DESIRED: array([1.00002, '
'2.00003, 3.00004])')
- self.assertEqual(a, b)
+ assert_equal(a, b)
def test_build_err_msg_no_verbose(self):
x = np.array([1.00001, 2.00002, 3.00003])
@@ -172,7 +171,7 @@ class TestBuildErrorMessage(unittest.TestCase):
a = build_err_msg([x, y], err_msg, verbose=False)
b = '\nItems are not equal: There is a mismatch'
- self.assertEqual(a, b)
+ assert_equal(a, b)
def test_build_err_msg_custom_names(self):
x = np.array([1.00001, 2.00002, 3.00003])
@@ -183,7 +182,7 @@ class TestBuildErrorMessage(unittest.TestCase):
b = ('\nItems are not equal: There is a mismatch\n FOO: array(['
'1.00001, 2.00002, 3.00003])\n BAR: array([1.00002, 2.00003, '
'3.00004])')
- self.assertEqual(a, b)
+ assert_equal(a, b)
def test_build_err_msg_custom_precision(self):
x = np.array([1.000000001, 2.00002, 3.00003])
@@ -194,12 +193,12 @@ class TestBuildErrorMessage(unittest.TestCase):
b = ('\nItems are not equal: There is a mismatch\n ACTUAL: array(['
'1.000000001, 2.00002 , 3.00003 ])\n DESIRED: array(['
'1.000000002, 2.00003 , 3.00004 ])')
- self.assertEqual(a, b)
+ assert_equal(a, b)
class TestEqual(TestArrayEqual):
- def setUp(self):
+ def setup(self):
self._assert_func = assert_equal
def test_nan_items(self):
@@ -298,16 +297,16 @@ class TestEqual(TestArrayEqual):
x: array([1, 2])
y: matrix([[1, 2]])""")
try:
- self.assertEqual(msg, msg_reference)
+ assert_equal(msg, msg_reference)
except AssertionError:
- self.assertEqual(msg2, msg_reference)
+ assert_equal(msg2, msg_reference)
else:
raise AssertionError("Did not raise")
-class TestArrayAlmostEqual(_GenericTest, unittest.TestCase):
+class TestArrayAlmostEqual(_GenericTest):
- def setUp(self):
+ def setup(self):
self._assert_func = assert_array_almost_equal
def test_closeness(self):
@@ -319,12 +318,12 @@ class TestArrayAlmostEqual(_GenericTest, unittest.TestCase):
# test scalars
self._assert_func(1.499999, 0.0, decimal=0)
- self.assertRaises(AssertionError,
+ assert_raises(AssertionError,
lambda: self._assert_func(1.5, 0.0, decimal=0))
# test arrays
self._assert_func([1.499999], [0.0], decimal=0)
- self.assertRaises(AssertionError,
+ assert_raises(AssertionError,
lambda: self._assert_func([1.5], [0.0], decimal=0))
def test_simple(self):
@@ -333,7 +332,7 @@ class TestArrayAlmostEqual(_GenericTest, unittest.TestCase):
self._assert_func(x, y, decimal=3)
self._assert_func(x, y, decimal=4)
- self.assertRaises(AssertionError,
+ assert_raises(AssertionError,
lambda: self._assert_func(x, y, decimal=5))
def test_nan(self):
@@ -341,21 +340,21 @@ class TestArrayAlmostEqual(_GenericTest, unittest.TestCase):
aone = np.array([1])
ainf = np.array([np.inf])
self._assert_func(anan, anan)
- self.assertRaises(AssertionError,
+ assert_raises(AssertionError,
lambda: self._assert_func(anan, aone))
- self.assertRaises(AssertionError,
+ assert_raises(AssertionError,
lambda: self._assert_func(anan, ainf))
- self.assertRaises(AssertionError,
+ assert_raises(AssertionError,
lambda: self._assert_func(ainf, anan))
def test_inf(self):
a = np.array([[1., 2.], [3., 4.]])
b = a.copy()
a[0, 0] = np.inf
- self.assertRaises(AssertionError,
+ assert_raises(AssertionError,
lambda: self._assert_func(a, b))
b[0, 0] = -np.inf
- self.assertRaises(AssertionError,
+ assert_raises(AssertionError,
lambda: self._assert_func(a, b))
def test_subclass(self):
@@ -396,9 +395,9 @@ class TestArrayAlmostEqual(_GenericTest, unittest.TestCase):
self._assert_func(a, a)
-class TestAlmostEqual(_GenericTest, unittest.TestCase):
+class TestAlmostEqual(_GenericTest):
- def setUp(self):
+ def setup(self):
self._assert_func = assert_almost_equal
def test_closeness(self):
@@ -410,30 +409,30 @@ class TestAlmostEqual(_GenericTest, unittest.TestCase):
# test scalars
self._assert_func(1.499999, 0.0, decimal=0)
- self.assertRaises(AssertionError,
- lambda: self._assert_func(1.5, 0.0, decimal=0))
+ assert_raises(AssertionError,
+ lambda: self._assert_func(1.5, 0.0, decimal=0))
# test arrays
self._assert_func([1.499999], [0.0], decimal=0)
- self.assertRaises(AssertionError,
- lambda: self._assert_func([1.5], [0.0], decimal=0))
+ assert_raises(AssertionError,
+ lambda: self._assert_func([1.5], [0.0], decimal=0))
def test_nan_item(self):
self._assert_func(np.nan, np.nan)
- self.assertRaises(AssertionError,
- lambda: self._assert_func(np.nan, 1))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(np.nan, np.inf))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(np.inf, np.nan))
+ assert_raises(AssertionError,
+ lambda: self._assert_func(np.nan, 1))
+ assert_raises(AssertionError,
+ lambda: self._assert_func(np.nan, np.inf))
+ assert_raises(AssertionError,
+ lambda: self._assert_func(np.inf, np.nan))
def test_inf_item(self):
self._assert_func(np.inf, np.inf)
self._assert_func(-np.inf, -np.inf)
- self.assertRaises(AssertionError,
- lambda: self._assert_func(np.inf, 1))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(-np.inf, np.inf))
+ assert_raises(AssertionError,
+ lambda: self._assert_func(np.inf, 1))
+ assert_raises(AssertionError,
+ lambda: self._assert_func(-np.inf, np.inf))
def test_simple_item(self):
self._test_not_equal(1, 2)
@@ -467,7 +466,7 @@ class TestAlmostEqual(_GenericTest, unittest.TestCase):
self._assert_func(x, y, decimal=12)
except AssertionError as e:
# remove anything that's not the array string
- self.assertEqual(str(e).split('%)\n ')[1], b)
+ assert_equal(str(e).split('%)\n ')[1], b)
# with the default value of decimal digits, only the 3rd element differs
# note that we only check for the formatting of the arrays themselves
@@ -477,7 +476,7 @@ class TestAlmostEqual(_GenericTest, unittest.TestCase):
self._assert_func(x, y)
except AssertionError as e:
# remove anything that's not the array string
- self.assertEqual(str(e).split('%)\n ')[1], b)
+ assert_equal(str(e).split('%)\n ')[1], b)
def test_matrix(self):
# Matrix slicing keeps things 2-D, while array does not necessarily.
@@ -509,9 +508,9 @@ class TestAlmostEqual(_GenericTest, unittest.TestCase):
self._assert_func(a, a)
-class TestApproxEqual(unittest.TestCase):
+class TestApproxEqual(object):
- def setUp(self):
+ def setup(self):
self._assert_func = assert_approx_equal
def test_simple_arrays(self):
@@ -520,8 +519,8 @@ class TestApproxEqual(unittest.TestCase):
self._assert_func(x, y, significant=5)
self._assert_func(x, y, significant=6)
- self.assertRaises(AssertionError,
- lambda: self._assert_func(x, y, significant=7))
+ assert_raises(AssertionError,
+ lambda: self._assert_func(x, y, significant=7))
def test_simple_items(self):
x = 1234.22
@@ -530,37 +529,31 @@ class TestApproxEqual(unittest.TestCase):
self._assert_func(x, y, significant=4)
self._assert_func(x, y, significant=5)
self._assert_func(x, y, significant=6)
- self.assertRaises(AssertionError,
- lambda: self._assert_func(x, y, significant=7))
+ assert_raises(AssertionError,
+ lambda: self._assert_func(x, y, significant=7))
def test_nan_array(self):
anan = np.array(np.nan)
aone = np.array(1)
ainf = np.array(np.inf)
self._assert_func(anan, anan)
- self.assertRaises(AssertionError,
- lambda: self._assert_func(anan, aone))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(anan, ainf))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(ainf, anan))
+ assert_raises(AssertionError, lambda: self._assert_func(anan, aone))
+ assert_raises(AssertionError, lambda: self._assert_func(anan, ainf))
+ assert_raises(AssertionError, lambda: self._assert_func(ainf, anan))
def test_nan_items(self):
anan = np.array(np.nan)
aone = np.array(1)
ainf = np.array(np.inf)
self._assert_func(anan, anan)
- self.assertRaises(AssertionError,
- lambda: self._assert_func(anan, aone))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(anan, ainf))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(ainf, anan))
+ assert_raises(AssertionError, lambda: self._assert_func(anan, aone))
+ assert_raises(AssertionError, lambda: self._assert_func(anan, ainf))
+ assert_raises(AssertionError, lambda: self._assert_func(ainf, anan))
-class TestArrayAssertLess(unittest.TestCase):
+class TestArrayAssertLess(object):
- def setUp(self):
+ def setup(self):
self._assert_func = assert_array_less
def test_simple_arrays(self):
@@ -568,100 +561,79 @@ class TestArrayAssertLess(unittest.TestCase):
y = np.array([1.2, 2.3])
self._assert_func(x, y)
- self.assertRaises(AssertionError,
- lambda: self._assert_func(y, x))
+ assert_raises(AssertionError, lambda: self._assert_func(y, x))
y = np.array([1.0, 2.3])
- self.assertRaises(AssertionError,
- lambda: self._assert_func(x, y))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(y, x))
+ assert_raises(AssertionError, lambda: self._assert_func(x, y))
+ assert_raises(AssertionError, lambda: self._assert_func(y, x))
def test_rank2(self):
x = np.array([[1.1, 2.2], [3.3, 4.4]])
y = np.array([[1.2, 2.3], [3.4, 4.5]])
self._assert_func(x, y)
- self.assertRaises(AssertionError,
- lambda: self._assert_func(y, x))
+ assert_raises(AssertionError, lambda: self._assert_func(y, x))
y = np.array([[1.0, 2.3], [3.4, 4.5]])
- self.assertRaises(AssertionError,
- lambda: self._assert_func(x, y))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(y, x))
+ assert_raises(AssertionError, lambda: self._assert_func(x, y))
+ assert_raises(AssertionError, lambda: self._assert_func(y, x))
def test_rank3(self):
x = np.ones(shape=(2, 2, 2))
y = np.ones(shape=(2, 2, 2))+1
self._assert_func(x, y)
- self.assertRaises(AssertionError,
- lambda: self._assert_func(y, x))
+ assert_raises(AssertionError, lambda: self._assert_func(y, x))
y[0, 0, 0] = 0
- self.assertRaises(AssertionError,
- lambda: self._assert_func(x, y))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(y, x))
+ assert_raises(AssertionError, lambda: self._assert_func(x, y))
+ assert_raises(AssertionError, lambda: self._assert_func(y, x))
def test_simple_items(self):
x = 1.1
y = 2.2
self._assert_func(x, y)
- self.assertRaises(AssertionError,
- lambda: self._assert_func(y, x))
+ assert_raises(AssertionError, lambda: self._assert_func(y, x))
y = np.array([2.2, 3.3])
self._assert_func(x, y)
- self.assertRaises(AssertionError,
- lambda: self._assert_func(y, x))
+ assert_raises(AssertionError, lambda: self._assert_func(y, x))
y = np.array([1.0, 3.3])
- self.assertRaises(AssertionError,
- lambda: self._assert_func(x, y))
+ assert_raises(AssertionError, lambda: self._assert_func(x, y))
def test_nan_noncompare(self):
anan = np.array(np.nan)
aone = np.array(1)
ainf = np.array(np.inf)
self._assert_func(anan, anan)
- self.assertRaises(AssertionError,
- lambda: self._assert_func(aone, anan))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(anan, aone))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(anan, ainf))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(ainf, anan))
+ assert_raises(AssertionError, lambda: self._assert_func(aone, anan))
+ assert_raises(AssertionError, lambda: self._assert_func(anan, aone))
+ assert_raises(AssertionError, lambda: self._assert_func(anan, ainf))
+ assert_raises(AssertionError, lambda: self._assert_func(ainf, anan))
def test_nan_noncompare_array(self):
x = np.array([1.1, 2.2, 3.3])
anan = np.array(np.nan)
- self.assertRaises(AssertionError,
- lambda: self._assert_func(x, anan))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(anan, x))
+ assert_raises(AssertionError, lambda: self._assert_func(x, anan))
+ assert_raises(AssertionError, lambda: self._assert_func(anan, x))
x = np.array([1.1, 2.2, np.nan])
- self.assertRaises(AssertionError,
- lambda: self._assert_func(x, anan))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(anan, x))
+ assert_raises(AssertionError, lambda: self._assert_func(x, anan))
+ assert_raises(AssertionError, lambda: self._assert_func(anan, x))
y = np.array([1.0, 2.0, np.nan])
self._assert_func(y, x)
- self.assertRaises(AssertionError,
- lambda: self._assert_func(x, y))
+ assert_raises(AssertionError, lambda: self._assert_func(x, y))
def test_inf_compare(self):
aone = np.array(1)
@@ -670,37 +642,27 @@ class TestArrayAssertLess(unittest.TestCase):
self._assert_func(aone, ainf)
self._assert_func(-ainf, aone)
self._assert_func(-ainf, ainf)
- self.assertRaises(AssertionError,
- lambda: self._assert_func(ainf, aone))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(aone, -ainf))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(ainf, ainf))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(ainf, -ainf))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(-ainf, -ainf))
+ assert_raises(AssertionError, lambda: self._assert_func(ainf, aone))
+ assert_raises(AssertionError, lambda: self._assert_func(aone, -ainf))
+ assert_raises(AssertionError, lambda: self._assert_func(ainf, ainf))
+ assert_raises(AssertionError, lambda: self._assert_func(ainf, -ainf))
+ assert_raises(AssertionError, lambda: self._assert_func(-ainf, -ainf))
def test_inf_compare_array(self):
x = np.array([1.1, 2.2, np.inf])
ainf = np.array(np.inf)
- self.assertRaises(AssertionError,
- lambda: self._assert_func(x, ainf))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(ainf, x))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(x, -ainf))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(-x, -ainf))
- self.assertRaises(AssertionError,
- lambda: self._assert_func(-ainf, -x))
+ assert_raises(AssertionError, lambda: self._assert_func(x, ainf))
+ assert_raises(AssertionError, lambda: self._assert_func(ainf, x))
+ assert_raises(AssertionError, lambda: self._assert_func(x, -ainf))
+ assert_raises(AssertionError, lambda: self._assert_func(-x, -ainf))
+ assert_raises(AssertionError, lambda: self._assert_func(-ainf, -x))
self._assert_func(-ainf, x)
-class TestRaises(unittest.TestCase):
+class TestRaises(object):
- def setUp(self):
+ def setup(self):
class MyException(Exception):
pass
@@ -732,7 +694,7 @@ class TestRaises(unittest.TestCase):
raise AssertionError("should have raised an AssertionError")
-class TestWarns(unittest.TestCase):
+class TestWarns(object):
def test_warn(self):
def f():
@@ -783,28 +745,27 @@ class TestWarns(unittest.TestCase):
raise AssertionError("wrong warning caught by assert_warn")
-class TestAssertAllclose(unittest.TestCase):
+class TestAssertAllclose(object):
def test_simple(self):
x = 1e-3
y = 1e-9
assert_allclose(x, y, atol=1)
- self.assertRaises(AssertionError, assert_allclose, x, y)
+ assert_raises(AssertionError, assert_allclose, x, y)
a = np.array([x, y, x, y])
b = np.array([x, y, x, x])
assert_allclose(a, b, atol=1)
- self.assertRaises(AssertionError, assert_allclose, a, b)
+ assert_raises(AssertionError, assert_allclose, a, b)
b[-1] = y * (1 + 1e-8)
assert_allclose(a, b)
- self.assertRaises(AssertionError, assert_allclose, a, b,
- rtol=1e-9)
+ assert_raises(AssertionError, assert_allclose, a, b, rtol=1e-9)
assert_allclose(6, 10, rtol=0.5)
- self.assertRaises(AssertionError, assert_allclose, 10, 6, rtol=0.5)
+ assert_raises(AssertionError, assert_allclose, 10, 6, rtol=0.5)
def test_min_int(self):
a = np.array([np.iinfo(np.int_).min], dtype=np.int_)
@@ -819,7 +780,7 @@ class TestAssertAllclose(unittest.TestCase):
msg = ''
except AssertionError as exc:
msg = exc.args[0]
- self.assertTrue("mismatch 25.0%" in msg)
+ assert_("mismatch 25.0%" in msg)
def test_equal_nan(self):
a = np.array([np.nan])
@@ -830,8 +791,7 @@ class TestAssertAllclose(unittest.TestCase):
def test_not_equal_nan(self):
a = np.array([np.nan])
b = np.array([np.nan])
- self.assertRaises(AssertionError, assert_allclose, a, b,
- equal_nan=False)
+ assert_raises(AssertionError, assert_allclose, a, b, equal_nan=False)
def test_equal_nan_default(self):
# Make sure equal_nan default behavior remains unchanged. (All
@@ -845,7 +805,7 @@ class TestAssertAllclose(unittest.TestCase):
assert_allclose(a, b)
-class TestArrayAlmostEqualNulp(unittest.TestCase):
+class TestArrayAlmostEqualNulp(object):
def test_float64_pass(self):
# The number of units of least precision
@@ -873,13 +833,13 @@ class TestArrayAlmostEqualNulp(unittest.TestCase):
eps = np.finfo(x.dtype).eps
y = x + x*eps*nulp*2.
- self.assertRaises(AssertionError, assert_array_almost_equal_nulp,
- x, y, nulp)
+ assert_raises(AssertionError, assert_array_almost_equal_nulp,
+ x, y, nulp)
epsneg = np.finfo(x.dtype).epsneg
y = x - x*epsneg*nulp*2.
- self.assertRaises(AssertionError, assert_array_almost_equal_nulp,
- x, y, nulp)
+ assert_raises(AssertionError, assert_array_almost_equal_nulp,
+ x, y, nulp)
def test_float32_pass(self):
nulp = 5
@@ -903,13 +863,43 @@ class TestArrayAlmostEqualNulp(unittest.TestCase):
eps = np.finfo(x.dtype).eps
y = x + x*eps*nulp*2.
- self.assertRaises(AssertionError, assert_array_almost_equal_nulp,
- x, y, nulp)
+ assert_raises(AssertionError, assert_array_almost_equal_nulp,
+ x, y, nulp)
+
+ epsneg = np.finfo(x.dtype).epsneg
+ y = x - x*epsneg*nulp*2.
+ assert_raises(AssertionError, assert_array_almost_equal_nulp,
+ x, y, nulp)
+
+ def test_float16_pass(self):
+ nulp = 5
+ x = np.linspace(-4, 4, 10, dtype=np.float16)
+ x = 10**x
+ x = np.r_[-x, x]
+
+ eps = np.finfo(x.dtype).eps
+ y = x + x*eps*nulp/2.
+ assert_array_almost_equal_nulp(x, y, nulp)
+
+ epsneg = np.finfo(x.dtype).epsneg
+ y = x - x*epsneg*nulp/2.
+ assert_array_almost_equal_nulp(x, y, nulp)
+
+ def test_float16_fail(self):
+ nulp = 5
+ x = np.linspace(-4, 4, 10, dtype=np.float16)
+ x = 10**x
+ x = np.r_[-x, x]
+
+ eps = np.finfo(x.dtype).eps
+ y = x + x*eps*nulp*2.
+ assert_raises(AssertionError, assert_array_almost_equal_nulp,
+ x, y, nulp)
epsneg = np.finfo(x.dtype).epsneg
y = x - x*epsneg*nulp*2.
- self.assertRaises(AssertionError, assert_array_almost_equal_nulp,
- x, y, nulp)
+ assert_raises(AssertionError, assert_array_almost_equal_nulp,
+ x, y, nulp)
def test_complex128_pass(self):
nulp = 5
@@ -943,25 +933,25 @@ class TestArrayAlmostEqualNulp(unittest.TestCase):
eps = np.finfo(x.dtype).eps
y = x + x*eps*nulp*2.
- self.assertRaises(AssertionError, assert_array_almost_equal_nulp,
- xi, x + y*1j, nulp)
- self.assertRaises(AssertionError, assert_array_almost_equal_nulp,
- xi, y + x*1j, nulp)
+ assert_raises(AssertionError, assert_array_almost_equal_nulp,
+ xi, x + y*1j, nulp)
+ assert_raises(AssertionError, assert_array_almost_equal_nulp,
+ xi, y + x*1j, nulp)
# The test condition needs to be at least a factor of sqrt(2) smaller
# because the real and imaginary parts both change
y = x + x*eps*nulp
- self.assertRaises(AssertionError, assert_array_almost_equal_nulp,
- xi, y + y*1j, nulp)
+ assert_raises(AssertionError, assert_array_almost_equal_nulp,
+ xi, y + y*1j, nulp)
epsneg = np.finfo(x.dtype).epsneg
y = x - x*epsneg*nulp*2.
- self.assertRaises(AssertionError, assert_array_almost_equal_nulp,
- xi, x + y*1j, nulp)
- self.assertRaises(AssertionError, assert_array_almost_equal_nulp,
- xi, y + x*1j, nulp)
+ assert_raises(AssertionError, assert_array_almost_equal_nulp,
+ xi, x + y*1j, nulp)
+ assert_raises(AssertionError, assert_array_almost_equal_nulp,
+ xi, y + x*1j, nulp)
y = x - x*epsneg*nulp
- self.assertRaises(AssertionError, assert_array_almost_equal_nulp,
- xi, y + y*1j, nulp)
+ assert_raises(AssertionError, assert_array_almost_equal_nulp,
+ xi, y + y*1j, nulp)
def test_complex64_pass(self):
nulp = 5
@@ -993,26 +983,26 @@ class TestArrayAlmostEqualNulp(unittest.TestCase):
eps = np.finfo(x.dtype).eps
y = x + x*eps*nulp*2.
- self.assertRaises(AssertionError, assert_array_almost_equal_nulp,
- xi, x + y*1j, nulp)
- self.assertRaises(AssertionError, assert_array_almost_equal_nulp,
- xi, y + x*1j, nulp)
+ assert_raises(AssertionError, assert_array_almost_equal_nulp,
+ xi, x + y*1j, nulp)
+ assert_raises(AssertionError, assert_array_almost_equal_nulp,
+ xi, y + x*1j, nulp)
y = x + x*eps*nulp
- self.assertRaises(AssertionError, assert_array_almost_equal_nulp,
- xi, y + y*1j, nulp)
+ assert_raises(AssertionError, assert_array_almost_equal_nulp,
+ xi, y + y*1j, nulp)
epsneg = np.finfo(x.dtype).epsneg
y = x - x*epsneg*nulp*2.
- self.assertRaises(AssertionError, assert_array_almost_equal_nulp,
- xi, x + y*1j, nulp)
- self.assertRaises(AssertionError, assert_array_almost_equal_nulp,
- xi, y + x*1j, nulp)
+ assert_raises(AssertionError, assert_array_almost_equal_nulp,
+ xi, x + y*1j, nulp)
+ assert_raises(AssertionError, assert_array_almost_equal_nulp,
+ xi, y + x*1j, nulp)
y = x - x*epsneg*nulp
- self.assertRaises(AssertionError, assert_array_almost_equal_nulp,
- xi, y + y*1j, nulp)
+ assert_raises(AssertionError, assert_array_almost_equal_nulp,
+ xi, y + y*1j, nulp)
-class TestULP(unittest.TestCase):
+class TestULP(object):
def test_equal(self):
x = np.random.randn(10)
@@ -1051,24 +1041,24 @@ class TestULP(unittest.TestCase):
tiny = np.array([np.finfo(dt).tiny])
zero = np.array([np.PZERO]).astype(dt)
nzero = np.array([np.NZERO]).astype(dt)
- self.assertRaises(AssertionError,
- lambda: assert_array_max_ulp(nan, inf,
- maxulp=maxulp))
- self.assertRaises(AssertionError,
- lambda: assert_array_max_ulp(nan, big,
- maxulp=maxulp))
- self.assertRaises(AssertionError,
- lambda: assert_array_max_ulp(nan, tiny,
- maxulp=maxulp))
- self.assertRaises(AssertionError,
- lambda: assert_array_max_ulp(nan, zero,
- maxulp=maxulp))
- self.assertRaises(AssertionError,
- lambda: assert_array_max_ulp(nan, nzero,
- maxulp=maxulp))
-
-
-class TestStringEqual(unittest.TestCase):
+ assert_raises(AssertionError,
+ lambda: assert_array_max_ulp(nan, inf,
+ maxulp=maxulp))
+ assert_raises(AssertionError,
+ lambda: assert_array_max_ulp(nan, big,
+ maxulp=maxulp))
+ assert_raises(AssertionError,
+ lambda: assert_array_max_ulp(nan, tiny,
+ maxulp=maxulp))
+ assert_raises(AssertionError,
+ lambda: assert_array_max_ulp(nan, zero,
+ maxulp=maxulp))
+ assert_raises(AssertionError,
+ lambda: assert_array_max_ulp(nan, nzero,
+ maxulp=maxulp))
+
+
+class TestStringEqual(object):
def test_simple(self):
assert_string_equal("hello", "hello")
assert_string_equal("hello\nmultiline", "hello\nmultiline")
@@ -1080,22 +1070,32 @@ class TestStringEqual(unittest.TestCase):
else:
raise AssertionError("exception not raised")
- self.assertRaises(AssertionError,
- lambda: assert_string_equal("foo", "hello"))
+ assert_raises(AssertionError,
+ lambda: assert_string_equal("foo", "hello"))
-def assert_warn_len_equal(mod, n_in_context, py3_n_in_context=None):
+def assert_warn_len_equal(mod, n_in_context, py34=None, py37=None):
mod_warns = mod.__warningregistry__
+ num_warns = len(mod_warns)
# Python 3.4 appears to clear any pre-existing warnings of the same type,
# when raising warnings inside a catch_warnings block. So, there is a
# warning generated by the tests within the context manager, but no
# previous warnings.
if 'version' in mod_warns:
- if py3_n_in_context is None:
- py3_n_in_context = n_in_context
- assert_equal(len(mod_warns) - 1, py3_n_in_context)
- else:
- assert_equal(len(mod_warns), n_in_context)
+ # Python 3 adds a 'version' entry to the registry,
+ # do not count it.
+ num_warns -= 1
+
+ # Behavior of warnings is Python version dependent. Adjust the
+ # expected result to compensate. In particular, Python 3.7 does
+ # not make an entry for ignored warnings.
+ if sys.version_info[:2] >= (3, 7):
+ if py37 is not None:
+ n_in_context = py37
+ elif sys.version_info[:2] >= (3, 4):
+ if py34 is not None:
+ n_in_context = py34
+ assert_equal(num_warns, n_in_context)
def _get_fresh_mod():
@@ -1104,6 +1104,8 @@ def _get_fresh_mod():
try:
my_mod.__warningregistry__.clear()
except AttributeError:
+ # will not have a __warningregistry__ unless warning has been
+ # raised in the module at some point
pass
return my_mod
@@ -1117,21 +1119,23 @@ def test_clear_and_catch_warnings():
warnings.warn('Some warning')
assert_equal(my_mod.__warningregistry__, {})
# Without specified modules, don't clear warnings during context
+ # Python 3.7 catch_warnings doesn't make an entry for 'ignore'.
with clear_and_catch_warnings():
warnings.simplefilter('ignore')
warnings.warn('Some warning')
- assert_warn_len_equal(my_mod, 1)
+ assert_warn_len_equal(my_mod, 1, py37=0)
# Confirm that specifying module keeps old warning, does not add new
with clear_and_catch_warnings(modules=[my_mod]):
warnings.simplefilter('ignore')
warnings.warn('Another warning')
- assert_warn_len_equal(my_mod, 1)
+ assert_warn_len_equal(my_mod, 1, py37=0)
# Another warning, no module spec does add to warnings dict, except on
# Python 3.4 (see comments in `assert_warn_len_equal`)
+ # Python 3.7 catch_warnings doesn't make an entry for 'ignore'.
with clear_and_catch_warnings():
warnings.simplefilter('ignore')
warnings.warn('Another warning')
- assert_warn_len_equal(my_mod, 2, 1)
+ assert_warn_len_equal(my_mod, 2, py34=1, py37=0)
def test_suppress_warnings_module():
@@ -1148,6 +1152,7 @@ def test_suppress_warnings_module():
np.apply_along_axis(warn, 0, [0])
# Test module based warning suppression:
+ assert_warn_len_equal(my_mod, 0)
with suppress_warnings() as sup:
sup.record(UserWarning)
# suppress warning from other module (may have .pyc ending),
@@ -1157,10 +1162,9 @@ def test_suppress_warnings_module():
warn_other_module()
# Check that the suppression did test the file correctly (this module
# got filtered)
- assert_(len(sup.log) == 1)
- assert_(sup.log[0].message.args[0] == "Some warning")
-
- assert_warn_len_equal(my_mod, 0)
+ assert_equal(len(sup.log), 1)
+ assert_equal(sup.log[0].message.args[0], "Some warning")
+ assert_warn_len_equal(my_mod, 0, py37=0)
sup = suppress_warnings()
# Will have to be changed if apply_along_axis is moved:
sup.filter(module=my_mod)
@@ -1174,11 +1178,11 @@ def test_suppress_warnings_module():
assert_warn_len_equal(my_mod, 0)
# Without specified modules, don't clear warnings during context
+ # Python 3.7 does not add ignored warnings.
with suppress_warnings():
warnings.simplefilter('ignore')
warnings.warn('Some warning')
- assert_warn_len_equal(my_mod, 1)
-
+ assert_warn_len_equal(my_mod, 1, py37=0)
def test_suppress_warnings_type():
# Initial state of module, no warnings
@@ -1202,10 +1206,11 @@ def test_suppress_warnings_type():
assert_warn_len_equal(my_mod, 0)
# Without specified modules, don't clear warnings during context
+ # Python 3.7 does not add ignored warnings.
with suppress_warnings():
warnings.simplefilter('ignore')
warnings.warn('Some warning')
- assert_warn_len_equal(my_mod, 1)
+ assert_warn_len_equal(my_mod, 1, py37=0)
def test_suppress_warnings_decorate_no_record():
@@ -1220,7 +1225,7 @@ def test_suppress_warnings_decorate_no_record():
warnings.simplefilter("always")
warn(UserWarning) # should be supppressed
warn(RuntimeWarning)
- assert_(len(w) == 1)
+ assert_equal(len(w), 1)
def test_suppress_warnings_record():
@@ -1234,10 +1239,10 @@ def test_suppress_warnings_record():
warnings.warn('Some other warning')
warnings.warn('Some other warning 2')
- assert_(len(sup.log) == 2)
- assert_(len(log1) == 1)
- assert_(len(log2) == 1)
- assert_(log2[0].message.args[0] == 'Some other warning 2')
+ assert_equal(len(sup.log), 2)
+ assert_equal(len(log1), 1)
+ assert_equal(len(log2),1)
+ assert_equal(log2[0].message.args[0], 'Some other warning 2')
# Do it again, with the same context to see if some warnings survived:
with sup:
@@ -1247,10 +1252,10 @@ def test_suppress_warnings_record():
warnings.warn('Some other warning')
warnings.warn('Some other warning 2')
- assert_(len(sup.log) == 2)
- assert_(len(log1) == 1)
- assert_(len(log2) == 1)
- assert_(log2[0].message.args[0] == 'Some other warning 2')
+ assert_equal(len(sup.log), 2)
+ assert_equal(len(log1), 1)
+ assert_equal(len(log2), 1)
+ assert_equal(log2[0].message.args[0], 'Some other warning 2')
# Test nested:
with suppress_warnings() as sup:
@@ -1259,8 +1264,8 @@ def test_suppress_warnings_record():
sup2.record(message='Some warning')
warnings.warn('Some warning')
warnings.warn('Some other warning')
- assert_(len(sup2.log) == 1)
- assert_(len(sup.log) == 1)
+ assert_equal(len(sup2.log), 1)
+ assert_equal(len(sup.log), 1)
def test_suppress_warnings_forwarding():
@@ -1278,7 +1283,7 @@ def test_suppress_warnings_forwarding():
for i in range(2):
warnings.warn("Some warning")
- assert_(len(sup.log) == 2)
+ assert_equal(len(sup.log), 2)
with suppress_warnings() as sup:
sup.record()
@@ -1287,7 +1292,7 @@ def test_suppress_warnings_forwarding():
warnings.warn("Some warning")
warnings.warn("Some warning")
- assert_(len(sup.log) == 2)
+ assert_equal(len(sup.log), 2)
with suppress_warnings() as sup:
sup.record()
@@ -1297,7 +1302,7 @@ def test_suppress_warnings_forwarding():
warnings.warn("Some warning")
warn_other_module()
- assert_(len(sup.log) == 2)
+ assert_equal(len(sup.log), 2)
with suppress_warnings() as sup:
sup.record()
@@ -1307,7 +1312,7 @@ def test_suppress_warnings_forwarding():
warnings.warn("Some other warning")
warn_other_module()
- assert_(len(sup.log) == 2)
+ assert_equal(len(sup.log), 2)
def test_tempdir():
diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py
index a0218c4e6..3cd89e639 100644
--- a/numpy/testing/utils.py
+++ b/numpy/testing/utils.py
@@ -3,9 +3,12 @@ Back compatibility utils module. It will import the appropriate
set of tools
"""
-import os
+import warnings
-from .nose_tools.utils import *
+warnings.warn("Import from numpy.testing, not numpy.testing.utils",
+ ImportWarning)
+
+from ._private.utils import *
__all__ = [
'assert_equal', 'assert_almost_equal', 'assert_approx_equal',
diff --git a/pytest.ini b/pytest.ini
index d3d7142d4..e901beb8c 100644
--- a/pytest.ini
+++ b/pytest.ini
@@ -1,9 +1,21 @@
[pytest]
+addopts = -l -q
norecursedirs = doc tools numpy/linalg/lapack_lite numpy/core/code_generators
doctest_optionflags = NORMALIZE_WHITESPACE
-testpaths = numpy
+filterwarnings =
+ error
+# Filter out annoying import messages.
+ ignore:Not importing directory
+ ignore:numpy.dtype size changed
+ ignore:numpy.ufunc size changed
+# Ignore python2.7 -3 warnings
+ ignore:sys\.exc_clear\(\) not supported in 3\.x:DeprecationWarning
+ ignore:in 3\.x, __setslice__:DeprecationWarning
+ ignore:in 3\.x, __getslice__:DeprecationWarning
+ ignore:buffer\(\) not supported in 3\.x:DeprecationWarning
+ ignore:CObject type is not supported in 3\.x:DeprecationWarning
+ ignore:comparing unequal types not supported in 3\.x:DeprecationWarning
+ ignore:the commands module has been removed in Python 3\.0:DeprecationWarning
env =
PYTHONHASHSEED=0
-
-# addopts = --doctest-modules --ignore=numpy/f2py/__main__.py --ignore=numpy/core/cversions.py --ignore=numpy/ma/core.py --ignore=numpy/ma/version.py --ignore=numpy/testing/utils.py --ignore=numpy/testing/decorators.py
diff --git a/setup.py b/setup.py
index 479d1849f..4af382fa8 100755
--- a/setup.py
+++ b/setup.py
@@ -219,7 +219,9 @@ def parse_setuppy_commands():
Return a boolean value for whether or not to run the build or not (avoid
parsing Cython and template files if False).
"""
- if len(sys.argv) < 2:
+ args = sys.argv[1:]
+
+ if not args:
# User forgot to give an argument probably, let setuptools handle that.
return True
@@ -229,12 +231,9 @@ def parse_setuppy_commands():
'--contact-email', '--url', '--license', '--description',
'--long-description', '--platforms', '--classifiers',
'--keywords', '--provides', '--requires', '--obsoletes']
- # Add commands that do more than print info, but also don't need Cython and
- # template parsing.
- info_commands.extend(['egg_info', 'install_egg_info', 'rotate'])
for command in info_commands:
- if command in sys.argv[1:]:
+ if command in args:
return False
# Note that 'alias', 'saveopts' and 'setopt' commands also seem to work
@@ -245,12 +244,12 @@ def parse_setuppy_commands():
'bdist_wininst', 'bdist_msi', 'bdist_mpkg')
for command in good_commands:
- if command in sys.argv[1:]:
+ if command in args:
return True
# The following commands are supported, but we need to show more
# useful messages to the user
- if 'install' in sys.argv[1:]:
+ if 'install' in args:
print(textwrap.dedent("""
Note: if you need reliable uninstall behavior, then install
with pip instead of using `setup.py install`:
@@ -262,7 +261,7 @@ def parse_setuppy_commands():
"""))
return True
- if '--help' in sys.argv[1:] or '-h' in sys.argv[1]:
+ if '--help' in args or '-h' in sys.argv[1]:
print(textwrap.dedent("""
NumPy-specific help
-------------------
@@ -280,6 +279,7 @@ def parse_setuppy_commands():
"""))
return False
+
# The following commands aren't supported. They can only be executed when
# the user explicitly adds a --force command-line argument.
bad_commands = dict(
@@ -322,12 +322,19 @@ def parse_setuppy_commands():
bad_commands[command] = "`setup.py %s` is not supported" % command
for command in bad_commands.keys():
- if command in sys.argv[1:]:
+ if command in args:
print(textwrap.dedent(bad_commands[command]) +
"\nAdd `--force` to your command to use it anyway if you "
"must (unsupported).\n")
sys.exit(1)
+ # Commands that do more than print info, but also don't need Cython and
+ # template parsing.
+ other_commands = ['egg_info', 'install_egg_info', 'rotate']
+ for command in other_commands:
+ if command in args:
+ return False
+
# If we got here, we didn't detect what setup.py command was given
import warnings
warnings.warn("Unrecognized setuptools command, proceeding with "
diff --git a/tools/ci/push_docs_to_repo.py b/tools/ci/push_docs_to_repo.py
new file mode 100755
index 000000000..a98966880
--- /dev/null
+++ b/tools/ci/push_docs_to_repo.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+
+import argparse
+import subprocess
+import tempfile
+import os
+import sys
+import shutil
+
+
+parser = argparse.ArgumentParser(
+ description='Upload files to a remote repo, replacing existing content'
+)
+parser.add_argument('dir', help='directory of which content will be uploaded')
+parser.add_argument('remote', help='remote to which content will be pushed')
+parser.add_argument('--message', default='Commit bot upload',
+ help='commit message to use')
+parser.add_argument('--committer', default='numpy-commit-bot',
+ help='Name of the git committer')
+parser.add_argument('--email', default='numpy-commit-bot@nomail',
+ help='Email of the git committer')
+
+parser.add_argument(
+ '--force', action='store_true',
+ help='hereby acknowledge that remote repo content will be overwritten'
+)
+args = parser.parse_args()
+args.dir = os.path.abspath(args.dir)
+
+if not os.path.exists(args.dir):
+ print('Content directory does not exist')
+ sys.exit(1)
+
+
+def run(cmd, stdout=True):
+ pipe = None if stdout else subprocess.DEVNULL
+ try:
+ subprocess.check_call(cmd, stdout=pipe, stderr=pipe)
+ except subprocess.CalledProcessError:
+ print("\n! Error executing: `%s;` aborting" % ' '.join(cmd))
+ sys.exit(1)
+
+
+workdir = tempfile.mkdtemp()
+os.chdir(workdir)
+
+run(['git', 'init'])
+run(['git', 'remote', 'add', 'origin', args.remote])
+run(['git', 'config', '--local', 'user.name', args.committer])
+run(['git', 'config', '--local', 'user.email', args.email])
+
+print('- committing new content: "%s"' % args.message)
+run(['cp', '-R', os.path.join(args.dir, '.'), '.'])
+run(['git', 'add', '.'], stdout=False)
+run(['git', 'commit', '--allow-empty', '-m', args.message], stdout=False)
+
+print('- uploading as %s <%s>' % (args.committer, args.email))
+if args.force:
+ run(['git', 'push', 'origin', 'master', '--force'])
+else:
+ print('\n!! No `--force` argument specified; aborting')
+ print('!! Before enabling that flag, make sure you know what it does\n')
+ sys.exit(1)
+
+shutil.rmtree(workdir)