summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/FUNDING.yml2
-rw-r--r--.github/ISSUE_TEMPLATE/bug-report.md30
-rw-r--r--.github/ISSUE_TEMPLATE/bug-report.yml49
-rw-r--r--.github/ISSUE_TEMPLATE/documentation.md20
-rw-r--r--.github/ISSUE_TEMPLATE/documentation.yml23
-rw-r--r--.github/ISSUE_TEMPLATE/feature-request.md16
-rw-r--r--.github/ISSUE_TEMPLATE/feature-request.yml22
-rw-r--r--.github/ISSUE_TEMPLATE/post-install.md21
-rw-r--r--.github/ISSUE_TEMPLATE/post-install.yml28
-rw-r--r--doc/cdoc/Doxyfile29
-rw-r--r--doc/cdoc/Makefile10
-rw-r--r--doc/cdoc/README31
-rwxr-xr-xdoc/cdoc/numpyfilter.py104
-rw-r--r--doc/release/upcoming_changes/19687.change.rst8
-rw-r--r--doc/release/upcoming_changes/19805.new_feature.rst5
-rw-r--r--doc/release/upcoming_changes/19921.deprecation.rst3
-rw-r--r--doc/source/f2py/index.rst2
-rw-r--r--doc/source/reference/c-api/types-and-structures.rst4
-rw-r--r--doc/source/user/basics.io.genfromtxt.rst2
-rw-r--r--doc/source/user/basics.rec.rst2
-rw-r--r--doc/source/user/building.rst3
-rw-r--r--doc/source/user/c-info.beyond-basics.rst5
-rw-r--r--doc/source/user/c-info.python-as-glue.rst87
-rw-r--r--environment.yml2
-rw-r--r--numpy/__init__.pyi75
-rw-r--r--numpy/core/_add_newdocs.py6
-rw-r--r--numpy/core/_dtype.py27
-rw-r--r--numpy/core/arrayprint.py98
-rw-r--r--numpy/core/arrayprint.pyi8
-rw-r--r--numpy/core/code_generators/ufunc_docstrings.py29
-rw-r--r--numpy/core/memmap.pyi5
-rw-r--r--numpy/core/records.py8
-rw-r--r--numpy/core/src/multiarray/datetime.c2
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c12
-rw-r--r--numpy/core/src/multiarray/scalartypes.c.src6
-rw-r--r--numpy/core/src/npymath/npy_math_internal.h.src19
-rw-r--r--numpy/core/tests/test_casting_unittests.py13
-rw-r--r--numpy/core/tests/test_dtype.py70
-rw-r--r--numpy/distutils/fcompiler/__init__.py3
-rw-r--r--numpy/distutils/fcompiler/nag.py7
-rw-r--r--numpy/f2py/cfuncs.py44
-rwxr-xr-xnumpy/f2py/rules.py4
-rw-r--r--numpy/f2py/src/fortranobject.c744
-rw-r--r--numpy/f2py/src/fortranobject.h121
-rw-r--r--numpy/f2py/tests/test_crackfortran.py4
-rw-r--r--numpy/lib/function_base.py2
-rw-r--r--numpy/lib/recfunctions.py3
-rw-r--r--numpy/lib/scimath.py21
-rw-r--r--numpy/linalg/lapack_lite/clapack_scrub.py21
-rw-r--r--numpy/ma/core.py2
-rw-r--r--numpy/ma/mrecords.py14
-rw-r--r--numpy/ma/mrecords.pyi2
-rw-r--r--numpy/ma/tests/test_deprecations.py21
-rw-r--r--numpy/random/_generator.pyx4
-rw-r--r--numpy/random/mtrand.pyx4
-rw-r--r--numpy/typing/__init__.py54
-rw-r--r--numpy/typing/_add_docstring.py15
-rw-r--r--numpy/typing/_callable.pyi (renamed from numpy/typing/_callable.py)8
-rw-r--r--numpy/typing/_dtype_like.py21
-rw-r--r--numpy/typing/_extended_precision.py3
-rw-r--r--numpy/typing/mypy_plugin.py36
-rw-r--r--numpy/typing/tests/data/fail/arithmetic.pyi (renamed from numpy/typing/tests/data/fail/arithmetic.py)0
-rw-r--r--numpy/typing/tests/data/fail/array_constructors.pyi (renamed from numpy/typing/tests/data/fail/array_constructors.py)0
-rw-r--r--numpy/typing/tests/data/fail/array_like.pyi (renamed from numpy/typing/tests/data/fail/array_like.py)0
-rw-r--r--numpy/typing/tests/data/fail/array_pad.pyi (renamed from numpy/typing/tests/data/fail/array_pad.py)0
-rw-r--r--numpy/typing/tests/data/fail/arrayprint.pyi (renamed from numpy/typing/tests/data/fail/arrayprint.py)0
-rw-r--r--numpy/typing/tests/data/fail/arrayterator.pyi (renamed from numpy/typing/tests/data/fail/arrayterator.py)0
-rw-r--r--numpy/typing/tests/data/fail/bitwise_ops.pyi (renamed from numpy/typing/tests/data/fail/bitwise_ops.py)0
-rw-r--r--numpy/typing/tests/data/fail/char.pyi (renamed from numpy/typing/tests/data/fail/char.py)0
-rw-r--r--numpy/typing/tests/data/fail/comparisons.pyi (renamed from numpy/typing/tests/data/fail/comparisons.py)0
-rw-r--r--numpy/typing/tests/data/fail/constants.pyi (renamed from numpy/typing/tests/data/fail/constants.py)0
-rw-r--r--numpy/typing/tests/data/fail/datasource.pyi (renamed from numpy/typing/tests/data/fail/datasource.py)0
-rw-r--r--numpy/typing/tests/data/fail/dtype.pyi (renamed from numpy/typing/tests/data/fail/dtype.py)0
-rw-r--r--numpy/typing/tests/data/fail/einsumfunc.pyi (renamed from numpy/typing/tests/data/fail/einsumfunc.py)0
-rw-r--r--numpy/typing/tests/data/fail/flatiter.pyi (renamed from numpy/typing/tests/data/fail/flatiter.py)0
-rw-r--r--numpy/typing/tests/data/fail/fromnumeric.pyi (renamed from numpy/typing/tests/data/fail/fromnumeric.py)0
-rw-r--r--numpy/typing/tests/data/fail/index_tricks.pyi (renamed from numpy/typing/tests/data/fail/index_tricks.py)0
-rw-r--r--numpy/typing/tests/data/fail/lib_utils.pyi (renamed from numpy/typing/tests/data/fail/lib_utils.py)0
-rw-r--r--numpy/typing/tests/data/fail/lib_version.pyi (renamed from numpy/typing/tests/data/fail/lib_version.py)0
-rw-r--r--numpy/typing/tests/data/fail/linalg.pyi (renamed from numpy/typing/tests/data/fail/linalg.py)0
-rw-r--r--numpy/typing/tests/data/fail/memmap.pyi5
-rw-r--r--numpy/typing/tests/data/fail/modules.pyi (renamed from numpy/typing/tests/data/fail/modules.py)0
-rw-r--r--numpy/typing/tests/data/fail/multiarray.pyi (renamed from numpy/typing/tests/data/fail/multiarray.py)0
-rw-r--r--numpy/typing/tests/data/fail/ndarray.pyi (renamed from numpy/typing/tests/data/fail/ndarray.py)0
-rw-r--r--numpy/typing/tests/data/fail/ndarray_misc.pyi (renamed from numpy/typing/tests/data/fail/ndarray_misc.py)0
-rw-r--r--numpy/typing/tests/data/fail/nditer.pyi (renamed from numpy/typing/tests/data/fail/nditer.py)0
-rw-r--r--numpy/typing/tests/data/fail/nested_sequence.pyi (renamed from numpy/typing/tests/data/fail/nested_sequence.py)0
-rw-r--r--numpy/typing/tests/data/fail/npyio.pyi (renamed from numpy/typing/tests/data/fail/npyio.py)0
-rw-r--r--numpy/typing/tests/data/fail/numerictypes.pyi (renamed from numpy/typing/tests/data/fail/numerictypes.py)0
-rw-r--r--numpy/typing/tests/data/fail/random.pyi (renamed from numpy/typing/tests/data/fail/random.py)0
-rw-r--r--numpy/typing/tests/data/fail/rec.pyi (renamed from numpy/typing/tests/data/fail/rec.py)0
-rw-r--r--numpy/typing/tests/data/fail/scalars.pyi (renamed from numpy/typing/tests/data/fail/scalars.py)0
-rw-r--r--numpy/typing/tests/data/fail/stride_tricks.pyi (renamed from numpy/typing/tests/data/fail/stride_tricks.py)0
-rw-r--r--numpy/typing/tests/data/fail/testing.pyi (renamed from numpy/typing/tests/data/fail/testing.py)0
-rw-r--r--numpy/typing/tests/data/fail/twodim_base.pyi (renamed from numpy/typing/tests/data/fail/twodim_base.py)0
-rw-r--r--numpy/typing/tests/data/fail/type_check.pyi (renamed from numpy/typing/tests/data/fail/type_check.py)0
-rw-r--r--numpy/typing/tests/data/fail/ufunc_config.pyi (renamed from numpy/typing/tests/data/fail/ufunc_config.py)0
-rw-r--r--numpy/typing/tests/data/fail/ufunclike.pyi (renamed from numpy/typing/tests/data/fail/ufunclike.py)0
-rw-r--r--numpy/typing/tests/data/fail/ufuncs.pyi (renamed from numpy/typing/tests/data/fail/ufuncs.py)0
-rw-r--r--numpy/typing/tests/data/fail/warnings_and_errors.pyi (renamed from numpy/typing/tests/data/fail/warnings_and_errors.py)0
-rw-r--r--numpy/typing/tests/data/misc/extended_precision.pyi (renamed from numpy/typing/tests/data/misc/extended_precision.py)0
-rw-r--r--numpy/typing/tests/data/reveal/arithmetic.pyi (renamed from numpy/typing/tests/data/reveal/arithmetic.py)0
-rw-r--r--numpy/typing/tests/data/reveal/array_constructors.pyi (renamed from numpy/typing/tests/data/reveal/array_constructors.py)0
-rw-r--r--numpy/typing/tests/data/reveal/arraypad.pyi (renamed from numpy/typing/tests/data/reveal/arraypad.py)0
-rw-r--r--numpy/typing/tests/data/reveal/arrayprint.pyi (renamed from numpy/typing/tests/data/reveal/arrayprint.py)0
-rw-r--r--numpy/typing/tests/data/reveal/arraysetops.pyi (renamed from numpy/typing/tests/data/reveal/arraysetops.py)0
-rw-r--r--numpy/typing/tests/data/reveal/arrayterator.pyi (renamed from numpy/typing/tests/data/reveal/arrayterator.py)0
-rw-r--r--numpy/typing/tests/data/reveal/bitwise_ops.pyi (renamed from numpy/typing/tests/data/reveal/bitwise_ops.py)0
-rw-r--r--numpy/typing/tests/data/reveal/char.pyi (renamed from numpy/typing/tests/data/reveal/char.py)0
-rw-r--r--numpy/typing/tests/data/reveal/comparisons.pyi (renamed from numpy/typing/tests/data/reveal/comparisons.py)0
-rw-r--r--numpy/typing/tests/data/reveal/constants.pyi (renamed from numpy/typing/tests/data/reveal/constants.py)0
-rw-r--r--numpy/typing/tests/data/reveal/ctypeslib.pyi (renamed from numpy/typing/tests/data/reveal/ctypeslib.py)0
-rw-r--r--numpy/typing/tests/data/reveal/datasource.pyi (renamed from numpy/typing/tests/data/reveal/datasource.py)0
-rw-r--r--numpy/typing/tests/data/reveal/dtype.pyi (renamed from numpy/typing/tests/data/reveal/dtype.py)0
-rw-r--r--numpy/typing/tests/data/reveal/einsumfunc.pyi (renamed from numpy/typing/tests/data/reveal/einsumfunc.py)0
-rw-r--r--numpy/typing/tests/data/reveal/flatiter.pyi (renamed from numpy/typing/tests/data/reveal/flatiter.py)0
-rw-r--r--numpy/typing/tests/data/reveal/fromnumeric.pyi (renamed from numpy/typing/tests/data/reveal/fromnumeric.py)0
-rw-r--r--numpy/typing/tests/data/reveal/getlimits.pyi (renamed from numpy/typing/tests/data/reveal/getlimits.py)0
-rw-r--r--numpy/typing/tests/data/reveal/index_tricks.pyi (renamed from numpy/typing/tests/data/reveal/index_tricks.py)0
-rw-r--r--numpy/typing/tests/data/reveal/lib_utils.pyi (renamed from numpy/typing/tests/data/reveal/lib_utils.py)0
-rw-r--r--numpy/typing/tests/data/reveal/lib_version.pyi (renamed from numpy/typing/tests/data/reveal/lib_version.py)0
-rw-r--r--numpy/typing/tests/data/reveal/linalg.pyi (renamed from numpy/typing/tests/data/reveal/linalg.py)0
-rw-r--r--numpy/typing/tests/data/reveal/memmap.pyi16
-rw-r--r--numpy/typing/tests/data/reveal/mod.pyi (renamed from numpy/typing/tests/data/reveal/mod.py)0
-rw-r--r--numpy/typing/tests/data/reveal/modules.pyi (renamed from numpy/typing/tests/data/reveal/modules.py)0
-rw-r--r--numpy/typing/tests/data/reveal/multiarray.pyi (renamed from numpy/typing/tests/data/reveal/multiarray.py)0
-rw-r--r--numpy/typing/tests/data/reveal/nbit_base_example.pyi (renamed from numpy/typing/tests/data/reveal/nbit_base_example.py)0
-rw-r--r--numpy/typing/tests/data/reveal/ndarray_conversion.pyi (renamed from numpy/typing/tests/data/reveal/ndarray_conversion.py)0
-rw-r--r--numpy/typing/tests/data/reveal/ndarray_misc.pyi (renamed from numpy/typing/tests/data/reveal/ndarray_misc.py)0
-rw-r--r--numpy/typing/tests/data/reveal/ndarray_shape_manipulation.pyi (renamed from numpy/typing/tests/data/reveal/ndarray_shape_manipulation.py)0
-rw-r--r--numpy/typing/tests/data/reveal/nditer.pyi (renamed from numpy/typing/tests/data/reveal/nditer.py)0
-rw-r--r--numpy/typing/tests/data/reveal/nested_sequence.pyi (renamed from numpy/typing/tests/data/reveal/nested_sequence.py)0
-rw-r--r--numpy/typing/tests/data/reveal/npyio.pyi (renamed from numpy/typing/tests/data/reveal/npyio.py)0
-rw-r--r--numpy/typing/tests/data/reveal/numeric.pyi (renamed from numpy/typing/tests/data/reveal/numeric.py)0
-rw-r--r--numpy/typing/tests/data/reveal/numerictypes.pyi (renamed from numpy/typing/tests/data/reveal/numerictypes.py)0
-rw-r--r--numpy/typing/tests/data/reveal/random.pyi (renamed from numpy/typing/tests/data/reveal/random.py)0
-rw-r--r--numpy/typing/tests/data/reveal/rec.pyi (renamed from numpy/typing/tests/data/reveal/rec.py)0
-rw-r--r--numpy/typing/tests/data/reveal/scalars.pyi (renamed from numpy/typing/tests/data/reveal/scalars.py)0
-rw-r--r--numpy/typing/tests/data/reveal/shape_base.pyi (renamed from numpy/typing/tests/data/reveal/shape_base.py)0
-rw-r--r--numpy/typing/tests/data/reveal/stride_tricks.pyi (renamed from numpy/typing/tests/data/reveal/stride_tricks.py)0
-rw-r--r--numpy/typing/tests/data/reveal/testing.pyi (renamed from numpy/typing/tests/data/reveal/testing.py)0
-rw-r--r--numpy/typing/tests/data/reveal/twodim_base.pyi (renamed from numpy/typing/tests/data/reveal/twodim_base.py)0
-rw-r--r--numpy/typing/tests/data/reveal/type_check.pyi (renamed from numpy/typing/tests/data/reveal/type_check.py)0
-rw-r--r--numpy/typing/tests/data/reveal/ufunc_config.pyi (renamed from numpy/typing/tests/data/reveal/ufunc_config.py)0
-rw-r--r--numpy/typing/tests/data/reveal/ufunclike.pyi (renamed from numpy/typing/tests/data/reveal/ufunclike.py)0
-rw-r--r--numpy/typing/tests/data/reveal/ufuncs.pyi (renamed from numpy/typing/tests/data/reveal/ufuncs.py)0
-rw-r--r--numpy/typing/tests/data/reveal/warnings_and_errors.pyi (renamed from numpy/typing/tests/data/reveal/warnings_and_errors.py)0
-rw-r--r--numpy/typing/tests/test_runtime.py4
-rw-r--r--numpy/typing/tests/test_typing.py112
-rw-r--r--pytest.ini2
-rw-r--r--test_requirements.txt2
-rw-r--r--tools/linter.py1
152 files changed, 1239 insertions, 947 deletions
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 8283a20f7..8c3502443 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,3 +1,3 @@
github: [numfocus]
tidelift: pypi/numpy
-custom: https://numpy.org/about/
+custom: https://numpy.org/about#donate
diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md
deleted file mode 100644
index 6da1f7370..000000000
--- a/.github/ISSUE_TEMPLATE/bug-report.md
+++ /dev/null
@@ -1,30 +0,0 @@
----
-name: "Bug report"
-about: Report a bug. Not for security vulnerabilities -- see below.
-
----
-
-<!-- Please describe the issue in detail here, and fill in the fields below -->
-
-### Reproducing code example:
-
-<!-- A short code example that reproduces the problem/missing feature. It should be
-self-contained, i.e., possible to run as-is via 'python myproblem.py' -->
-
-```python
-import numpy as np
-<< your code here >>
-```
-
-### Error message:
-
-<!-- If you are reporting a segfault please include a GDB traceback, which you
-can generate by following
-https://github.com/numpy/numpy/blob/main/doc/source/dev/development_environment.rst#debugging -->
-
-<!-- Full error message, if any (starting from line Traceback: ...) -->
-
-### NumPy/Python version information:
-
-<!-- Output from 'import sys, numpy; print(numpy.__version__, sys.version)' -->
-
diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml
new file mode 100644
index 000000000..b46225968
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug-report.yml
@@ -0,0 +1,49 @@
+name: Bug report
+description: Report a bug. For security vulnerabilities see Report a security vulnerability in the templates.
+title: "BUG: "
+labels: [00 - Bug]
+
+body:
+- type: markdown
+ attributes:
+ value: >
+ Thank you for taking the time to file a bug report. Before creating a new
+ issue, please make sure to take a few minutes to check the issue tracker
+ for existing issues about the bug.
+
+- type: textarea
+ attributes:
+ label: "Describe the issue:"
+ validations:
+ required: true
+
+- type: textarea
+ attributes:
+ label: "Reproduce the code example:"
+ description: >
+ A short code example that reproduces the problem/missing feature. It
+ should be self-contained, i.e., can be copy-pasted into the Python
+ interpreter or run as-is via `python myproblem.py`.
+ placeholder: |
+ import numpy as np
+ << your code here >>
+ render: python
+ validations:
+ required: true
+
+- type: textarea
+ attributes:
+ label: "Error message:"
+ description: >
+ Please include full error message, if any (starting from `Traceback: ...`).
+ If you are reporting a segfault please include a GDB traceback,
+ which you can generate by following
+ [these instructions](https://github.com/numpy/numpy/blob/main/doc/source/dev/development_environment.rst#debugging).
+ render: shell
+
+- type: textarea
+ attributes:
+ label: "NumPy/Python version information:"
+ description: Output from `import sys, numpy; print(numpy.__version__, sys.version)`.
+ validations:
+ required: true \ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md
deleted file mode 100644
index cdb7cde2e..000000000
--- a/.github/ISSUE_TEMPLATE/documentation.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-name: "Documentation"
-about: Report an issue related to the NumPy documentation
-labels: 04 - Documentation
-
----
-
-## Documentation
-
-<!-- If this is an issue with the current documentation for NumPy (e.g.
-incomplete/inaccurate docstring, unclear explanation in any part of the
-documentation), make sure to leave a reference to the document/code you're
-referring to. You can also check the development version of the documentation
-and see if this issue has already been addressed: https://numpy.org/devdocs/
--->
-
-<!-- If this is an idea or a request for content, please describe as clearly as
-possible what topics you think are missing from the current documentation. Make
-sure to check https://github.com/numpy/numpy-tutorials and see if this issue
-might be more appropriate there. -->
diff --git a/.github/ISSUE_TEMPLATE/documentation.yml b/.github/ISSUE_TEMPLATE/documentation.yml
new file mode 100644
index 000000000..1005d3ade
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/documentation.yml
@@ -0,0 +1,23 @@
+name: Documentation
+description: Report an issue related to the NumPy documentation.
+title: "DOC: "
+labels: [04 - Documentation]
+
+body:
+- type: textarea
+ attributes:
+ label: "Issue with current documentation:"
+ description: >
+ Please make sure to leave a reference to the document/code you're
+ referring to. You can also check the development version of the
+ documentation and see if this issue has already been addressed at
+ https://numpy.org/devdocs.
+
+- type: textarea
+ attributes:
+ label: "Idea or request for content:"
+ description: >
+ Please describe as clearly as possible what topics you think are missing
+ from the current documentation. Make sure to check
+ https://github.com/numpy/numpy-tutorials and see if this issue might be
+ more appropriate there. \ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md
deleted file mode 100644
index 68872ec06..000000000
--- a/.github/ISSUE_TEMPLATE/feature-request.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-name: "Feature request"
-about: Check instructions for submitting your idea on the mailing list first.
-
----
-
-## Feature
-
-<!-- If you're looking to request a new feature or change in functionality, including
-adding or changing the meaning of arguments to an existing function, please
-post your idea on the [numpy-discussion mailing list]
-(https://mail.python.org/mailman/listinfo/numpy-discussion) to explain your
-reasoning in addition to opening an issue or pull request. You can also check
-out our [Contributor Guide]
-(https://github.com/numpy/numpy/blob/main/doc/source/dev/index.rst) if you
-need more information. -->
diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml
new file mode 100644
index 000000000..5e2af4015
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature-request.yml
@@ -0,0 +1,22 @@
+name: Feature request
+description: Check instructions for submitting your idea on the mailing list first.
+title: "ENH: "
+
+body:
+- type: markdown
+ attributes:
+ value: >
+ If you're looking to request a new feature or change in functionality,
+ including adding or changing the meaning of arguments to an existing
+ function, please post your idea on the
+ [numpy-discussion mailing list](https://mail.python.org/mailman/listinfo/numpy-discussion)
+ to explain your reasoning in addition to opening an issue or pull request.
+ You can also check out our
+ [Contributor Guide](https://github.com/numpy/numpy/blob/main/doc/source/dev/index.rst)
+ if you need more information.
+
+- type: textarea
+ attributes:
+ label: "Proposed new feature or change:"
+ validations:
+ required: true \ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/post-install.md b/.github/ISSUE_TEMPLATE/post-install.md
deleted file mode 100644
index 11b91384c..000000000
--- a/.github/ISSUE_TEMPLATE/post-install.md
+++ /dev/null
@@ -1,21 +0,0 @@
----
-name: "Post-install/importing issue"
-about: If you have trouble importing or using NumPy after installation
-labels: 32 - Installation
-
----
-
-<!-- Please describe the issue in detail here, and fill in the fields below. Also, check our Troubleshooting ImportError document to see if your issue is listed there: https://numpy.org/devdocs/user/troubleshooting-importerror.html -->
-
-### Steps to reproduce:
-
-<!-- Please describe the installation method (e.g. building from source, Anaconda, pip), your OS and NumPy/Python version information -->
-
-### Error message:
-
-<!-- If you are reporting a segfault please include a GDB traceback, which you
-can generate by following
-https://github.com/numpy/numpy/blob/main/doc/source/dev/development_environment.rst#debugging -->
-
-<!-- Full error message, if any (starting from line Traceback: ...) -->
-
diff --git a/.github/ISSUE_TEMPLATE/post-install.yml b/.github/ISSUE_TEMPLATE/post-install.yml
new file mode 100644
index 000000000..5831994d1
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/post-install.yml
@@ -0,0 +1,28 @@
+name: Post-install/importing issue
+description: Report an issue if you have trouble importing or using NumPy after installation.
+labels: [32 - Installation]
+
+body:
+- type: textarea
+ attributes:
+ label: "Steps to reproduce:"
+ description: >
+ Please describe the installation method (e.g. building from source,
+ Anaconda, pip), your OS and NumPy/Python version information.
+ validations:
+ required: true
+
+- type: textarea
+ attributes:
+ label: "Error message:"
+ description: >
+ Please include full error message, if any (starting from `Traceback: ...`).
+ If you are reporting a segfault please include a GDB traceback,
+ which you can generate by following
+ [these instructions](https://github.com/numpy/numpy/blob/main/doc/source/dev/development_environment.rst#debugging).
+ render: shell
+
+- type: textarea
+ attributes:
+ label: "Additional information:"
+ description: Please add any additional information that could help us diagnose the problem better. \ No newline at end of file
diff --git a/doc/cdoc/Doxyfile b/doc/cdoc/Doxyfile
deleted file mode 100644
index c9c386e4e..000000000
--- a/doc/cdoc/Doxyfile
+++ /dev/null
@@ -1,29 +0,0 @@
-# Doxyfile for NumPy C API
-# See http://www.doxygen.nl/manual/config.html
-PROJECT_NAME = numpy
-PROJECT_NUMBER = 2.0.0
-OUTPUT_DIRECTORY = build
-STRIP_FROM_PATH = ../../numpy/core
-INHERIT_DOCS = YES
-TAB_SIZE = 8
-OPTIMIZE_OUTPUT_FOR_C = YES
-EXTRACT_ALL = YES
-EXTRACT_PRIVATE = YES
-EXTRACT_STATIC = YES
-CASE_SENSE_NAMES = NO
-INPUT = ../../numpy/core/src \
- ../../numpy/core/include
-FILE_PATTERNS = *.h *.c *.src
-RECURSIVE = YES
-INPUT_FILTER = ./numpyfilter.py
-REFERENCED_BY_RELATION = YES
-REFERENCES_RELATION = YES
-ALPHABETICAL_INDEX = NO
-GENERATE_HTML = YES
-HTML_TIMESTAMP = YES
-GENERATE_TREEVIEW = YES
-SEARCHENGINE = NO
-GENERATE_LATEX = NO
-PAPER_TYPE = a4wide
-GENERATE_XML = NO
-HAVE_DOT = NO
diff --git a/doc/cdoc/Makefile b/doc/cdoc/Makefile
deleted file mode 100644
index 8b9deada8..000000000
--- a/doc/cdoc/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-all: build
-
-build:
- doxygen
-
-clean:
- rm -rf build
-
-.PHONY: all build clean
-
diff --git a/doc/cdoc/README b/doc/cdoc/README
deleted file mode 100644
index a5363cfa1..000000000
--- a/doc/cdoc/README
+++ /dev/null
@@ -1,31 +0,0 @@
-cdoc
-====
-
-This is a simple Doxygen project for building NumPy C code documentation,
-with docstrings extracted from the C sources themselves.
-
-The understood syntax for documentation in the C source is
-
- /*
- * Some text in reStructuredText format
- */
- int function_to_which_the_text_applies()
- {
- ...
- }
-
- /*
- * More text in reStructuredText format
- */
- struct
- {
- int variable_1; /* Documentation for variable_1 */
-
- /*
- * Documentation for variable_2
- */
- int variable_2;
- } struct_name_t;
-
-Please do not use JavaDoc or Doxygen-specific formatting at the moment.
-
diff --git a/doc/cdoc/numpyfilter.py b/doc/cdoc/numpyfilter.py
deleted file mode 100755
index d3cfe18f0..000000000
--- a/doc/cdoc/numpyfilter.py
+++ /dev/null
@@ -1,104 +0,0 @@
-#!/usr/bin/env python3
-"""
-numpyfilter.py [-h] inputfile
-
-Interpret C comments as ReStructuredText, and replace them by the HTML output.
-Also, add Doxygen /** and /**< syntax automatically where appropriate.
-
-"""
-import sys
-import re
-import os
-import textwrap
-
-from numpy.compat import pickle
-
-CACHE_FILE = 'build/rst-cache.pck'
-
-def main():
- import argparse
-
- parser = argparse.ArgumentParser(usage=__doc__.strip())
- parser.add_argument('input_file', help='input file')
- args = parser.parse_args()
-
- comment_re = re.compile(r'(\n.*?)/\*(.*?)\*/', re.S)
-
- cache = load_cache()
-
- try:
- with open(args.input_file, 'r') as f:
- text = f.read()
- text = comment_re.sub(lambda m: process_match(m, cache), text)
- sys.stdout.write(text)
- finally:
- save_cache(cache)
-
-def filter_comment(text):
- if text.startswith('NUMPY_API'):
- text = text[9:].strip()
- if text.startswith('UFUNC_API'):
- text = text[9:].strip()
-
- html = render_html(text)
- return html
-
-def process_match(m, cache=None):
- pre, rawtext = m.groups()
-
- preline = pre.split("\n")[-1]
-
- if cache is not None and rawtext in cache:
- text = cache[rawtext]
- else:
- text = re.compile(r'^\s*\*', re.M).sub('', rawtext)
- text = textwrap.dedent(text)
- text = filter_comment(text)
-
- if cache is not None:
- cache[rawtext] = text
-
- if preline.strip():
- return pre + "/**< " + text + " */"
- else:
- return pre + "/** " + text + " */"
-
-def load_cache():
- if os.path.exists(CACHE_FILE):
- with open(CACHE_FILE, 'rb') as f:
- try:
- cache = pickle.load(f)
- except Exception:
- cache = {}
- else:
- cache = {}
- return cache
-
-def save_cache(cache):
- with open(CACHE_FILE + '.new', 'wb') as f:
- pickle.dump(cache, f)
- os.rename(CACHE_FILE + '.new', CACHE_FILE)
-
-def render_html(text):
- import docutils.parsers.rst
- import docutils.writers.html4css1
- import docutils.core
-
- docutils.parsers.rst.roles.DEFAULT_INTERPRETED_ROLE = 'title-reference'
- writer = docutils.writers.html4css1.Writer()
- parts = docutils.core.publish_parts(
- text,
- writer=writer,
- settings_overrides = dict(halt_level=5,
- traceback=True,
- default_reference_context='title-reference',
- stylesheet_path='',
- # security settings:
- raw_enabled=0,
- file_insertion_enabled=0,
- _disable_config=1,
- )
- )
- return parts['html_body']
-
-if __name__ == "__main__": main()
diff --git a/doc/release/upcoming_changes/19687.change.rst b/doc/release/upcoming_changes/19687.change.rst
new file mode 100644
index 000000000..c7f7512b6
--- /dev/null
+++ b/doc/release/upcoming_changes/19687.change.rst
@@ -0,0 +1,8 @@
+str/repr of complex dtypes now include space after punctuation
+--------------------------------------------------------------
+
+The repr of ``np.dtype({"names": ["a"], "formats": [int], "offsets": [2]})`` is
+now ``dtype({'names': ['a'], 'formats': ['<i8'], 'offsets': [2], 'itemsize': 10})``,
+whereas spaces where previously omitted after colons and between fields.
+
+The old behavior can be restored via ``np.set_printoptions(legacy="1.21")``.
diff --git a/doc/release/upcoming_changes/19805.new_feature.rst b/doc/release/upcoming_changes/19805.new_feature.rst
new file mode 100644
index 000000000..f59409254
--- /dev/null
+++ b/doc/release/upcoming_changes/19805.new_feature.rst
@@ -0,0 +1,5 @@
+Symbolic parser for Fortran dimension specifications
+----------------------------------------------------
+A new symbolic parser has been added to f2py in order to correctly parse
+dimension specifications. The parser is the basis for future improvements
+and provides compatibility with Draft Fortran 202x.
diff --git a/doc/release/upcoming_changes/19921.deprecation.rst b/doc/release/upcoming_changes/19921.deprecation.rst
new file mode 100644
index 000000000..17fa0f605
--- /dev/null
+++ b/doc/release/upcoming_changes/19921.deprecation.rst
@@ -0,0 +1,3 @@
+* the misspelled keyword argument ``delimitor`` of
+ ``numpy.ma.mrecords.fromtextfile()`` has been changed into
+ ``delimiter``, using it will emit a deprecation warning.
diff --git a/doc/source/f2py/index.rst b/doc/source/f2py/index.rst
index 07d26e39e..c774a0df6 100644
--- a/doc/source/f2py/index.rst
+++ b/doc/source/f2py/index.rst
@@ -1,3 +1,5 @@
+.. _f2py:
+
=====================================
F2PY user guide and reference manual
=====================================
diff --git a/doc/source/reference/c-api/types-and-structures.rst b/doc/source/reference/c-api/types-and-structures.rst
index 36293ce99..a4a9734c5 100644
--- a/doc/source/reference/c-api/types-and-structures.rst
+++ b/doc/source/reference/c-api/types-and-structures.rst
@@ -961,8 +961,8 @@ PyUFunc_Type and PyUFuncObject
.. deprecated:: 1.22
Some fallback support for this slot exists, but will be removed
- eventually. A univiersal function which relied on this will have
- eventually have to be ported.
+ eventually. A universal function that relied on this will
+ have to be ported eventually.
See ref:`NEP 41 <NEP41>` and ref:`NEP 43 <NEP43>`
.. c:member:: void *reserved2
diff --git a/doc/source/user/basics.io.genfromtxt.rst b/doc/source/user/basics.io.genfromtxt.rst
index 5364acbe9..8fe7565aa 100644
--- a/doc/source/user/basics.io.genfromtxt.rst
+++ b/doc/source/user/basics.io.genfromtxt.rst
@@ -437,7 +437,7 @@ process these missing data.
By default, any empty string is marked as missing. We can also consider
more complex strings, such as ``"N/A"`` or ``"???"`` to represent missing
-or invalid data. The ``missing_values`` argument accepts three kind
+or invalid data. The ``missing_values`` argument accepts three kinds
of values:
a string or a comma-separated string
diff --git a/doc/source/user/basics.rec.rst b/doc/source/user/basics.rec.rst
index 0524fde8e..1e6f30506 100644
--- a/doc/source/user/basics.rec.rst
+++ b/doc/source/user/basics.rec.rst
@@ -128,7 +128,7 @@ summary they are:
... 'formats': ['i4', 'f4'],
... 'offsets': [0, 4],
... 'itemsize': 12})
- dtype({'names':['col1','col2'], 'formats':['<i4','<f4'], 'offsets':[0,4], 'itemsize':12})
+ dtype({'names': ['col1', 'col2'], 'formats': ['<i4', '<f4'], 'offsets': [0, 4], 'itemsize': 12})
Offsets may be chosen such that the fields overlap, though this will mean
that assigning to one field may clobber any overlapping field's data. As
diff --git a/doc/source/user/building.rst b/doc/source/user/building.rst
index 10983ce8f..22efca4a6 100644
--- a/doc/source/user/building.rst
+++ b/doc/source/user/building.rst
@@ -45,6 +45,9 @@ Building NumPy requires the following software installed:
2) Compilers
+ Much of NumPy is written in C. You will need a C compiler that complies
+ with the C99 standard.
+
While a FORTRAN 77 compiler is not necessary for building NumPy, it is
needed to run the ``numpy.f2py`` tests. These tests are skipped if the
compiler is not auto-detected.
diff --git a/doc/source/user/c-info.beyond-basics.rst b/doc/source/user/c-info.beyond-basics.rst
index 121384d04..7dd22afbf 100644
--- a/doc/source/user/c-info.beyond-basics.rst
+++ b/doc/source/user/c-info.beyond-basics.rst
@@ -174,14 +174,13 @@ incrementing is automatically performed by
:c:func:`PyArray_MultiIter_NEXT` ( ``obj`` ) macro (which can handle a
multiterator ``obj`` as either a :c:expr:`PyArrayMultiIterObject *` or a
:c:expr:`PyObject *`). The data from input number ``i`` is available using
-:c:func:`PyArray_MultiIter_DATA` ( ``obj``, ``i`` ) and the total (broadcasted)
-size as :c:func:`PyArray_MultiIter_SIZE` ( ``obj``). An example of using this
+:c:func:`PyArray_MultiIter_DATA` ( ``obj``, ``i`` ). An example of using this
feature follows.
.. code-block:: c
mobj = PyArray_MultiIterNew(2, obj1, obj2);
- size = PyArray_MultiIter_SIZE(obj);
+ size = mobj->size;
while(size--) {
ptr1 = PyArray_MultiIter_DATA(mobj, 0);
ptr2 = PyArray_MultiIter_DATA(mobj, 1);
diff --git a/doc/source/user/c-info.python-as-glue.rst b/doc/source/user/c-info.python-as-glue.rst
index 2798aa08a..6d514f146 100644
--- a/doc/source/user/c-info.python-as-glue.rst
+++ b/doc/source/user/c-info.python-as-glue.rst
@@ -1,6 +1,6 @@
-********************
+====================
Using Python as glue
-********************
+====================
| There is no conversation more boring than the one where everybody
| agrees.
@@ -124,9 +124,9 @@ Creating source for a basic extension module
Probably the easiest way to introduce f2py is to offer a simple
example. Here is one of the subroutines contained in a file named
-:file:`add.f`:
+:file:`add.f`
-.. code-block:: none
+.. code-block:: fortran
C
SUBROUTINE ZADD(A,B,C,N)
@@ -149,14 +149,14 @@ routine can be automatically generated by f2py::
You should be able to run this command assuming your search-path is
set-up properly. This command will produce an extension module named
-addmodule.c in the current directory. This extension module can now be
+:file:`addmodule.c` in the current directory. This extension module can now be
compiled and used from Python just like any other extension module.
Creating a compiled extension module
------------------------------------
-You can also get f2py to compile add.f and also compile its produced
+You can also get f2py to both compile :file:`add.f` along with the produced
extension module leaving only a shared-library extension file that can
be imported from Python::
@@ -211,7 +211,7 @@ interface file use the -h option::
This command leaves the file add.pyf in the current directory. The
section of this file corresponding to zadd is:
-.. code-block:: none
+.. code-block:: fortran
subroutine zadd(a,b,c,n) ! in :add:add.f
double complex dimension(*) :: a
@@ -224,7 +224,7 @@ By placing intent directives and checking code, the interface can be
cleaned up quite a bit until the Python module method is both easier
to use and more robust.
-.. code-block:: none
+.. code-block:: fortran
subroutine zadd(a,b,c,n) ! in :add:add.f
double complex dimension(n) :: a
@@ -277,9 +277,9 @@ Inserting directives in Fortran source
The nice interface can also be generated automatically by placing the
variable directives as special comments in the original Fortran code.
-Thus, if I modify the source code to contain:
+Thus, if the source code is modified to contain:
-.. code-block:: none
+.. code-block:: fortran
C
SUBROUTINE ZADD(A,B,C,N)
@@ -298,14 +298,14 @@ Thus, if I modify the source code to contain:
20 CONTINUE
END
-Then, I can compile the extension module using::
+Then, one can compile the extension module using::
f2py -c -m add add.f
The resulting signature for the function add.zadd is exactly the same
one that was created previously. If the original source code had
contained ``A(N)`` instead of ``A(*)`` and so forth with ``B`` and ``C``,
-then I could obtain (nearly) the same interface simply by placing the
+then nearly the same interface can be obtained by placing the
``INTENT(OUT) :: C`` comment line in the source code. The only difference
is that ``N`` would be an optional input that would default to the length
of ``A``.
@@ -320,7 +320,7 @@ precision floating-point numbers using a fixed averaging filter. The
advantage of using Fortran to index into multi-dimensional arrays
should be clear from this example.
-.. code-block:: none
+.. code-block::
SUBROUTINE DFILTER2D(A,B,M,N)
C
@@ -407,13 +407,12 @@ conversion of the .pyf file to a .c file is handled by `numpy.disutils`.
Conclusion
----------
-The interface definition file (.pyf) is how you can fine-tune the
-interface between Python and Fortran. There is decent documentation
-for f2py found in the numpy/f2py/docs directory where-ever NumPy is
-installed on your system (usually under site-packages). There is also
-more information on using f2py (including how to use it to wrap C
-codes) at https://scipy-cookbook.readthedocs.io under the "Interfacing
-With Other Languages" heading.
+The interface definition file (.pyf) is how you can fine-tune the interface
+between Python and Fortran. There is decent documentation for f2py at
+:ref:`f2py`. There is also more information on using f2py (including how to use
+it to wrap C codes) at the `"Interfacing With Other Languages" heading of the
+SciPy Cookbook.
+<https://scipy-cookbook.readthedocs.io/items/idx_interfacing_with_other_languages.html>`_
The f2py method of linking compiled code is currently the most
sophisticated and integrated approach. It allows clean separation of
@@ -422,7 +421,7 @@ distribution of the extension module. The only draw-back is that it
requires the existence of a Fortran compiler in order for a user to
install the code. However, with the existence of the free-compilers
g77, gfortran, and g95, as well as high-quality commercial compilers,
-this restriction is not particularly onerous. In my opinion, Fortran
+this restriction is not particularly onerous. In our opinion, Fortran
is still the easiest way to write fast and clear code for scientific
computing. It handles complex numbers, and multi-dimensional indexing
in the most straightforward way. Be aware, however, that some Fortran
@@ -493,7 +492,7 @@ Complex addition in Cython
Here is part of a Cython module named ``add.pyx`` which implements the
complex addition functions we previously implemented using f2py:
-.. code-block:: none
+.. code-block:: cython
cimport cython
cimport numpy as np
@@ -546,7 +545,7 @@ Image filter in Cython
The two-dimensional example we created using Fortran is just as easy to write
in Cython:
-.. code-block:: none
+.. code-block:: cython
cimport numpy as np
import numpy as np
@@ -809,7 +808,7 @@ Calling the function
The function is accessed as an attribute of or an item from the loaded
shared-library. Thus, if ``./mylib.so`` has a function named
-``cool_function1``, I could access this function either as:
+``cool_function1``, it may be accessed either as:
.. code-block:: python
@@ -859,7 +858,7 @@ kind of array from a given input.
Complete example
----------------
-In this example, I will show how the addition function and the filter
+In this example, we will demonstrate how the addition function and the filter
function implemented previously using the other approaches can be
implemented using ctypes. First, the C code which implements the
algorithms contains the functions ``zadd``, ``dadd``, ``sadd``, ``cadd``,
@@ -1073,7 +1072,7 @@ Its disadvantages include
- It is difficult to distribute an extension module made using ctypes
because of a lack of support for building shared libraries in
- distutils (but I suspect this will change in time).
+ distutils.
- You must have shared-libraries of your code (no static libraries).
@@ -1095,15 +1094,14 @@ Additional tools you may find useful
These tools have been found useful by others using Python and so are
included here. They are discussed separately because they are
either older ways to do things now handled by f2py, Cython, or ctypes
-(SWIG, PyFort) or because I don't know much about them (SIP, Boost).
-I have not added links to these
-methods because my experience is that you can find the most relevant
-link faster using Google or some other search engine, and any links
-provided here would be quickly dated. Do not assume that just because
-it is included in this list, I don't think the package deserves your
-attention. I'm including information about these packages because many
-people have found them useful and I'd like to give you as many options
-as possible for tackling the problem of easily integrating your code.
+(SWIG, PyFort) or because of a lack of reasonable documentation (SIP, Boost).
+Links to these methods are not included since the most relevant
+can be found using Google or some other search engine, and any links provided
+here would be quickly dated. Do not assume that inclusion in this list means
+that the package deserves attention. Information about these packages are
+collected here because many people have found them useful and we'd like to give
+you as many options as possible for tackling the problem of easily integrating
+your code.
SWIG
@@ -1132,12 +1130,12 @@ to the Python-specific typemaps, SWIG can be used to interface a
library with other languages such as Perl, Tcl, and Ruby.
My experience with SWIG has been generally positive in that it is
-relatively easy to use and quite powerful. I used to use it quite
+relatively easy to use and quite powerful. It has been used
often before becoming more proficient at writing C-extensions.
-However, I struggled writing custom interfaces with SWIG because it
+However, writing custom interfaces with SWIG is often troublesome because it
must be done using the concept of typemaps which are not Python
-specific and are written in a C-like syntax. Therefore, I tend to
-prefer other gluing strategies and would only attempt to use SWIG to
+specific and are written in a C-like syntax. Therefore, other gluing strategies
+are preferred and SWIG would be probably considered only to
wrap a very-large C/C++ library. Nonetheless, there are others who use
SWIG quite happily.
@@ -1170,12 +1168,11 @@ those libraries which provides a concise interface for binding C++
classes and functions to Python. The amazing part of the Boost.Python
approach is that it works entirely in pure C++ without introducing a
new syntax. Many users of C++ report that Boost.Python makes it
-possible to combine the best of both worlds in a seamless fashion. I
-have not used Boost.Python because I am not a big user of C++ and
-using Boost to wrap simple C-subroutines is usually over-kill. It's
-primary purpose is to make C++ classes available in Python. So, if you
-have a set of C++ classes that need to be integrated cleanly into
-Python, consider learning about and using Boost.Python.
+possible to combine the best of both worlds in a seamless fashion. Using Boost
+to wrap simple C-subroutines is usually over-kill. Its primary purpose is to
+make C++ classes available in Python. So, if you have a set of C++ classes that
+need to be integrated cleanly into Python, consider learning about and using
+Boost.Python.
PyFort
diff --git a/environment.yml b/environment.yml
index 188e29a4f..7c9d28449 100644
--- a/environment.yml
+++ b/environment.yml
@@ -18,7 +18,7 @@ dependencies:
- pytest-xdist
- hypothesis
# For type annotations
- - mypy=0.902
+ - mypy=0.910
# For building docs
- sphinx=4.1.1
- numpydoc=1.1.0
diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi
index 84a60483d..c78d48cc6 100644
--- a/numpy/__init__.pyi
+++ b/numpy/__init__.pyi
@@ -196,6 +196,7 @@ from typing import (
SupportsIndex,
Final,
final,
+ ClassVar,
)
# Ensures that the stubs are picked up
@@ -636,6 +637,17 @@ class _IOProtocol(Protocol):
def tell(self) -> SupportsIndex: ...
def seek(self, offset: int, whence: int, /) -> object: ...
+# NOTE: `seek`, `write` and `flush` are technically only required
+# for `readwrite`/`write` modes
+class _MemMapIOProtocol(Protocol):
+ def flush(self) -> object: ...
+ def fileno(self) -> SupportsIndex: ...
+ def tell(self) -> int: ...
+ def seek(self, offset: int, whence: int, /) -> object: ...
+ def write(self, s: bytes, /) -> object: ...
+ @property
+ def read(self) -> object: ...
+
__all__: List[str]
__path__: List[str]
__version__: str
@@ -758,18 +770,6 @@ class matrix(ndarray[_ShapeType, _DType_co]):
def getH(self): ...
def getI(self): ...
-class memmap(ndarray[_ShapeType, _DType_co]):
- def __new__(
- subtype,
- filename: Any,
- dtype: Any = ...,
- mode: Any = ...,
- offset: Any = ...,
- shape: Any = ...,
- order: Any = ...,
- ) -> Any: ...
- def __getattr__(self, key: str) -> Any: ...
-
class poly1d:
def __init__(
self,
@@ -3828,3 +3828,54 @@ class nditer:
def shape(self) -> Tuple[int, ...]: ...
@property
def value(self) -> Tuple[NDArray[Any], ...]: ...
+
+_MemMapModeKind = L[
+ "readonly", "r",
+ "copyonwrite", "c",
+ "readwrite", "r+",
+ "write", "w+",
+]
+
+class memmap(ndarray[_ShapeType, _DType_co]):
+ __array_priority__: ClassVar[float]
+ filename: str | None
+ offset: int
+ mode: str
+ @overload
+ def __new__(
+ subtype,
+ filename: str | bytes | os.PathLike[str] | os.PathLike[bytes] | _MemMapIOProtocol,
+ dtype: Type[uint8] = ...,
+ mode: _MemMapModeKind = ...,
+ offset: int = ...,
+ shape: None | int | Tuple[int, ...] = ...,
+ order: _OrderKACF = ...,
+ ) -> memmap[Any, dtype[uint8]]: ...
+ @overload
+ def __new__(
+ subtype,
+ filename: str | bytes | os.PathLike[str] | os.PathLike[bytes] | _MemMapIOProtocol,
+ dtype: _DTypeLike[_ScalarType],
+ mode: _MemMapModeKind = ...,
+ offset: int = ...,
+ shape: None | int | Tuple[int, ...] = ...,
+ order: _OrderKACF = ...,
+ ) -> memmap[Any, dtype[_ScalarType]]: ...
+ @overload
+ def __new__(
+ subtype,
+ filename: str | bytes | os.PathLike[str] | os.PathLike[bytes] | _MemMapIOProtocol,
+ dtype: DTypeLike,
+ mode: _MemMapModeKind = ...,
+ offset: int = ...,
+ shape: None | int | Tuple[int, ...] = ...,
+ order: _OrderKACF = ...,
+ ) -> memmap[Any, dtype[Any]]: ...
+ def __array_finalize__(self, obj: memmap[Any, Any]) -> None: ...
+ def __array_wrap__(
+ self,
+ array: memmap[_ShapeType, _DType_co],
+ context: None | Tuple[ufunc, Tuple[Any, ...], int] = ...,
+ ) -> Any: ...
+ def __getitem__(self, index): ... # TODO
+ def flush(self) -> None: ...
diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py
index 2d5e9ae07..bb0c2ea12 100644
--- a/numpy/core/_add_newdocs.py
+++ b/numpy/core/_add_newdocs.py
@@ -3577,7 +3577,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('newbyteorder',
* 'S' - swap dtype from current to opposite endian
* {'<', 'little'} - little endian
* {'>', 'big'} - big endian
- * '=' - native order, equivalent to `sys.byteorder`
+ * {'=', 'native'} - native order, equivalent to `sys.byteorder`
* {'|', 'I'} - ignore (no change to byte order)
The default value ('S') results in swapping the current
@@ -6037,7 +6037,7 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('newbyteorder',
* 'S' - swap dtype from current to opposite endian
* {'<', 'little'} - little endian
* {'>', 'big'} - big endian
- * '=' - native order
+ * {'=', 'native'} - native order
* {'|', 'I'} - ignore (no change to byte order)
Returns
@@ -6437,7 +6437,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('newbyteorder',
* 'S' - swap dtype from current to opposite endian
* {'<', 'little'} - little endian
* {'>', 'big'} - big endian
- * '=' - native order
+ * {'=', 'native'} - native order
* {'|', 'I'} - ignore (no change to byte order)
Parameters
diff --git a/numpy/core/_dtype.py b/numpy/core/_dtype.py
index 4249071ff..c3a22b1c6 100644
--- a/numpy/core/_dtype.py
+++ b/numpy/core/_dtype.py
@@ -200,30 +200,37 @@ def _struct_dict_str(dtype, includealignedflag):
# Build up a string to make the dictionary
+ if np.core.arrayprint._get_legacy_print_mode() <= 121:
+ colon = ":"
+ fieldsep = ","
+ else:
+ colon = ": "
+ fieldsep = ", "
+
# First, the names
- ret = "{'names':["
- ret += ",".join(repr(name) for name in names)
+ ret = "{'names'%s[" % colon
+ ret += fieldsep.join(repr(name) for name in names)
# Second, the formats
- ret += "], 'formats':["
- ret += ",".join(
+ ret += "], 'formats'%s[" % colon
+ ret += fieldsep.join(
_construction_repr(fld_dtype, short=True) for fld_dtype in fld_dtypes)
# Third, the offsets
- ret += "], 'offsets':["
- ret += ",".join("%d" % offset for offset in offsets)
+ ret += "], 'offsets'%s[" % colon
+ ret += fieldsep.join("%d" % offset for offset in offsets)
# Fourth, the titles
if any(title is not None for title in titles):
- ret += "], 'titles':["
- ret += ",".join(repr(title) for title in titles)
+ ret += "], 'titles'%s[" % colon
+ ret += fieldsep.join(repr(title) for title in titles)
# Fifth, the itemsize
- ret += "], 'itemsize':%d" % dtype.itemsize
+ ret += "], 'itemsize'%s%d" % (colon, dtype.itemsize)
if (includealignedflag and dtype.isalignedstruct):
# Finally, the aligned flag
- ret += ", 'aligned':True}"
+ ret += ", 'aligned'%sTrue}" % colon
else:
ret += "}"
diff --git a/numpy/core/arrayprint.py b/numpy/core/arrayprint.py
index 2a4bef669..d7e9bf795 100644
--- a/numpy/core/arrayprint.py
+++ b/numpy/core/arrayprint.py
@@ -24,6 +24,7 @@ __docformat__ = 'restructuredtext'
import functools
import numbers
+import sys
try:
from _thread import get_ident
except ImportError:
@@ -56,12 +57,17 @@ _format_options = {
'infstr': 'inf',
'sign': '-',
'formatter': None,
- 'legacy': False}
+ # Internally stored as an int to simplify comparisons; converted from/to
+ # str/False on the way in/out.
+ 'legacy': sys.maxsize}
def _make_options_dict(precision=None, threshold=None, edgeitems=None,
linewidth=None, suppress=None, nanstr=None, infstr=None,
sign=None, formatter=None, floatmode=None, legacy=None):
- """ make a dictionary out of the non-None arguments, plus sanity checks """
+ """
+ Make a dictionary out of the non-None arguments, plus conversion of
+ *legacy* and sanity checks.
+ """
options = {k: v for k, v in locals().items() if v is not None}
@@ -76,9 +82,18 @@ def _make_options_dict(precision=None, threshold=None, edgeitems=None,
if sign not in [None, '-', '+', ' ']:
raise ValueError("sign option must be one of ' ', '+', or '-'")
- if legacy not in [None, False, '1.13']:
- warnings.warn("legacy printing option can currently only be '1.13' or "
- "`False`", stacklevel=3)
+ if legacy == False:
+ options['legacy'] = sys.maxsize
+ elif legacy == '1.13':
+ options['legacy'] = 113
+ elif legacy == '1.21':
+ options['legacy'] = 121
+ elif legacy is None:
+ pass # OK, do nothing.
+ else:
+ warnings.warn(
+ "legacy printing option can currently only be '1.13', '1.21', or "
+ "`False`", stacklevel=3)
if threshold is not None:
# forbid the bad threshold arg suggested by stack overflow, gh-12351
@@ -186,11 +201,21 @@ def set_printoptions(precision=None, threshold=None, edgeitems=None,
legacy : string or `False`, optional
If set to the string `'1.13'` enables 1.13 legacy printing mode. This
approximates numpy 1.13 print output by including a space in the sign
- position of floats and different behavior for 0d arrays. If set to
- `False`, disables legacy mode. Unrecognized strings will be ignored
- with a warning for forward compatibility.
+ position of floats and different behavior for 0d arrays. This also
+ enables 1.21 legacy printing mode (described below).
+
+ If set to the string `'1.21'` enables 1.21 legacy printing mode. This
+ approximates numpy 1.21 print output of complex structured dtypes
+ by not inserting spaces after commas that separate fields and after
+ colons.
+
+ If set to `False`, disables legacy mode.
+
+ Unrecognized strings will be ignored with a warning for forward
+ compatibility.
.. versionadded:: 1.14.0
+ .. versionchanged:: 1.22.0
See Also
--------
@@ -257,11 +282,13 @@ def set_printoptions(precision=None, threshold=None, edgeitems=None,
_format_options.update(opt)
# set the C variable for legacy mode
- if _format_options['legacy'] == '1.13':
+ if _format_options['legacy'] == 113:
set_legacy_print_mode(113)
# reset the sign option in legacy mode to avoid confusion
_format_options['sign'] = '-'
- elif _format_options['legacy'] is False:
+ elif _format_options['legacy'] == 121:
+ set_legacy_print_mode(121)
+ elif _format_options['legacy'] == sys.maxsize:
set_legacy_print_mode(0)
@@ -292,7 +319,16 @@ def get_printoptions():
set_printoptions, printoptions, set_string_function
"""
- return _format_options.copy()
+ opts = _format_options.copy()
+ opts['legacy'] = {
+ 113: '1.13', 121: '1.21', sys.maxsize: False,
+ }[opts['legacy']]
+ return opts
+
+
+def _get_legacy_print_mode():
+ """Return the legacy print mode as an int."""
+ return _format_options['legacy']
@set_module('numpy')
@@ -678,7 +714,7 @@ def array2string(a, max_line_width=None, precision=None,
options = _format_options.copy()
options.update(overrides)
- if options['legacy'] == '1.13':
+ if options['legacy'] <= 113:
if style is np._NoValue:
style = repr
@@ -690,7 +726,7 @@ def array2string(a, max_line_width=None, precision=None,
" except in 1.13 'legacy' mode",
DeprecationWarning, stacklevel=3)
- if options['legacy'] != '1.13':
+ if options['legacy'] > 113:
options['linewidth'] -= len(suffix)
# treat as a null array if any of shape elements == 0
@@ -702,7 +738,7 @@ def array2string(a, max_line_width=None, precision=None,
def _extendLine(s, line, word, line_width, next_line_prefix, legacy):
needs_wrap = len(line) + len(word) > line_width
- if legacy != '1.13':
+ if legacy > 113:
# don't wrap lines if it won't help
if len(line) <= len(next_line_prefix):
needs_wrap = False
@@ -719,7 +755,7 @@ def _extendLine_pretty(s, line, word, line_width, next_line_prefix, legacy):
Extends line with nicely formatted (possibly multi-line) string ``word``.
"""
words = word.splitlines()
- if len(words) == 1 or legacy == '1.13':
+ if len(words) == 1 or legacy <= 113:
return _extendLine(s, line, word, line_width, next_line_prefix, legacy)
max_word_length = max(len(word) for word in words)
@@ -765,7 +801,7 @@ def _formatArray(a, format_function, line_width, next_line_prefix,
# when recursing, add a space to align with the [ added, and reduce the
# length of the line by 1
next_hanging_indent = hanging_indent + ' '
- if legacy == '1.13':
+ if legacy <= 113:
next_width = curr_width
else:
next_width = curr_width - len(']')
@@ -785,7 +821,7 @@ def _formatArray(a, format_function, line_width, next_line_prefix,
# last axis (rows) - wrap elements if they would not fit on one line
if axes_left == 1:
# the length up until the beginning of the separator / bracket
- if legacy == '1.13':
+ if legacy <= 113:
elem_width = curr_width - len(separator.rstrip())
else:
elem_width = curr_width - max(len(separator.rstrip()), len(']'))
@@ -800,7 +836,7 @@ def _formatArray(a, format_function, line_width, next_line_prefix,
if show_summary:
s, line = _extendLine(
s, line, summary_insert, elem_width, hanging_indent, legacy)
- if legacy == '1.13':
+ if legacy <= 113:
line += ", "
else:
line += separator
@@ -811,7 +847,7 @@ def _formatArray(a, format_function, line_width, next_line_prefix,
s, line, word, elem_width, hanging_indent, legacy)
line += separator
- if legacy == '1.13':
+ if legacy <= 113:
# width of the separator is not considered on 1.13
elem_width = curr_width
word = recurser(index + (-1,), next_hanging_indent, next_width)
@@ -830,7 +866,7 @@ def _formatArray(a, format_function, line_width, next_line_prefix,
s += hanging_indent + nested + line_sep
if show_summary:
- if legacy == '1.13':
+ if legacy <= 113:
# trailing space, fixed nbr of newlines, and fixed separator
s += hanging_indent + summary_insert + ", \n"
else:
@@ -875,7 +911,7 @@ class FloatingFormat:
sign = '+' if sign else '-'
self._legacy = legacy
- if self._legacy == '1.13':
+ if self._legacy <= 113:
# when not 0d, legacy does not support '-'
if data.shape != () and sign == '-':
sign = ' '
@@ -919,7 +955,7 @@ class FloatingFormat:
self.min_digits = None
elif self.exp_format:
trim, unique = '.', True
- if self.floatmode == 'fixed' or self._legacy == '1.13':
+ if self.floatmode == 'fixed' or self._legacy <= 113:
trim, unique = 'k', False
strs = (dragon4_scientific(x, precision=self.precision,
unique=unique, trim=trim, sign=self.sign == '+')
@@ -934,7 +970,7 @@ class FloatingFormat:
self.unique = unique
# for back-compat with np 1.13, use 2 spaces & sign and full prec
- if self._legacy == '1.13':
+ if self._legacy <= 113:
self.pad_left = 3
else:
# this should be only 1 or 2. Can be calculated from sign.
@@ -951,7 +987,7 @@ class FloatingFormat:
sign=self.sign == '+')
for x in finite_vals)
int_part, frac_part = zip(*(s.split('.') for s in strs))
- if self._legacy == '1.13':
+ if self._legacy <= 113:
self.pad_left = 1 + max(len(s.lstrip('-+')) for s in int_part)
else:
self.pad_left = max(len(s) for s in int_part)
@@ -966,7 +1002,7 @@ class FloatingFormat:
self.trim = '.'
self.min_digits = 0
- if self._legacy != '1.13':
+ if self._legacy > 113:
# account for sign = ' ' by adding one to pad_left
if self.sign == ' ' and not any(np.signbit(finite_vals)):
self.pad_left += 1
@@ -1215,7 +1251,7 @@ class ComplexFloatingFormat:
sign = '+' if sign else '-'
floatmode_real = floatmode_imag = floatmode
- if legacy == '1.13':
+ if legacy <= 113:
floatmode_real = 'maxprec_equal'
floatmode_imag = 'maxprec'
@@ -1286,7 +1322,7 @@ class DatetimeFormat(_TimelikeFormat):
super().__init__(x)
def __call__(self, x):
- if self.legacy == '1.13':
+ if self.legacy <= 113:
return self._format_non_nat(x)
return super().__call__(x)
@@ -1390,7 +1426,7 @@ def dtype_is_implied(dtype):
array([1, 2, 3], dtype=int8)
"""
dtype = np.dtype(dtype)
- if _format_options['legacy'] == '1.13' and dtype.type == bool_:
+ if _format_options['legacy'] <= 113 and dtype.type == bool_:
return False
# not just void types can be structured, and names are not part of the repr
@@ -1445,7 +1481,7 @@ def _array_repr_implementation(
prefix = class_name + "("
suffix = ")" if skipdtype else ","
- if (_format_options['legacy'] == '1.13' and
+ if (_format_options['legacy'] <= 113 and
arr.shape == () and not arr.dtype.names):
lst = repr(arr.item())
elif arr.size > 0 or arr.shape == (0,):
@@ -1466,7 +1502,7 @@ def _array_repr_implementation(
# Note: This line gives the correct result even when rfind returns -1.
last_line_len = len(arr_str) - (arr_str.rfind('\n') + 1)
spacer = " "
- if _format_options['legacy'] == '1.13':
+ if _format_options['legacy'] <= 113:
if issubclass(arr.dtype.type, flexible):
spacer = '\n' + ' '*len(class_name + "(")
elif last_line_len + len(dtype_str) + 1 > max_line_width:
@@ -1540,7 +1576,7 @@ def _array_str_implementation(
a, max_line_width=None, precision=None, suppress_small=None,
array2string=array2string):
"""Internal version of array_str() that allows overriding array2string."""
- if (_format_options['legacy'] == '1.13' and
+ if (_format_options['legacy'] <= 113 and
a.shape == () and not a.dtype.names):
return str(a.item())
diff --git a/numpy/core/arrayprint.pyi b/numpy/core/arrayprint.pyi
index 3731e6578..0d338206f 100644
--- a/numpy/core/arrayprint.pyi
+++ b/numpy/core/arrayprint.pyi
@@ -53,7 +53,7 @@ class _FormatOptions(TypedDict):
formatter: Optional[_FormatDict]
sign: Literal["-", "+", " "]
floatmode: _FloatMode
- legacy: Literal[False, "1.13"]
+ legacy: Literal[False, "1.13", "1.21"]
def set_printoptions(
precision: Optional[SupportsIndex] = ...,
@@ -67,7 +67,7 @@ def set_printoptions(
sign: Optional[Literal["-", "+", " "]] = ...,
floatmode: Optional[_FloatMode] = ...,
*,
- legacy: Optional[Literal[False, "1.13"]] = ...
+ legacy: Optional[Literal[False, "1.13", "1.21"]] = ...
) -> None: ...
def get_printoptions() -> _FormatOptions: ...
def array2string(
@@ -87,7 +87,7 @@ def array2string(
sign: Optional[Literal["-", "+", " "]] = ...,
floatmode: Optional[_FloatMode] = ...,
suffix: str = ...,
- legacy: Optional[Literal[False, "1.13"]] = ...,
+ legacy: Optional[Literal[False, "1.13", "1.21"]] = ...,
) -> str: ...
def format_float_scientific(
x: _FloatLike_co,
@@ -137,5 +137,5 @@ def printoptions(
sign: Optional[Literal["-", "+", " "]] = ...,
floatmode: Optional[_FloatMode] = ...,
*,
- legacy: Optional[Literal[False, "1.13"]] = ...
+ legacy: Optional[Literal[False, "1.13", "1.21"]] = ...
) -> _GeneratorContextManager[_FormatOptions]: ...
diff --git a/numpy/core/code_generators/ufunc_docstrings.py b/numpy/core/code_generators/ufunc_docstrings.py
index f19946be4..c15e1f042 100644
--- a/numpy/core/code_generators/ufunc_docstrings.py
+++ b/numpy/core/code_generators/ufunc_docstrings.py
@@ -201,7 +201,8 @@ add_newdoc('numpy.core.umath', 'arccos',
References
----------
M. Abramowitz and I.A. Stegun, "Handbook of Mathematical Functions",
- 10th printing, 1964, pp. 79. http://www.math.sfu.ca/~cbm/aands/
+ 10th printing, 1964, pp. 79.
+ https://personal.math.ubc.ca/~cbm/aands/page_79.htm
Examples
--------
@@ -258,7 +259,8 @@ add_newdoc('numpy.core.umath', 'arccosh',
References
----------
.. [1] M. Abramowitz and I.A. Stegun, "Handbook of Mathematical Functions",
- 10th printing, 1964, pp. 86. http://www.math.sfu.ca/~cbm/aands/
+ 10th printing, 1964, pp. 86.
+ https://personal.math.ubc.ca/~cbm/aands/page_86.htm
.. [2] Wikipedia, "Inverse hyperbolic function",
https://en.wikipedia.org/wiki/Arccosh
@@ -312,7 +314,7 @@ add_newdoc('numpy.core.umath', 'arcsin',
----------
Abramowitz, M. and Stegun, I. A., *Handbook of Mathematical Functions*,
10th printing, New York: Dover, 1964, pp. 79ff.
- http://www.math.sfu.ca/~cbm/aands/
+ https://personal.math.ubc.ca/~cbm/aands/page_79.htm
Examples
--------
@@ -360,7 +362,8 @@ add_newdoc('numpy.core.umath', 'arcsinh',
References
----------
.. [1] M. Abramowitz and I.A. Stegun, "Handbook of Mathematical Functions",
- 10th printing, 1964, pp. 86. http://www.math.sfu.ca/~cbm/aands/
+ 10th printing, 1964, pp. 86.
+ https://personal.math.ubc.ca/~cbm/aands/page_86.htm
.. [2] Wikipedia, "Inverse hyperbolic function",
https://en.wikipedia.org/wiki/Arcsinh
@@ -415,7 +418,7 @@ add_newdoc('numpy.core.umath', 'arctan',
----------
Abramowitz, M. and Stegun, I. A., *Handbook of Mathematical Functions*,
10th printing, New York: Dover, 1964, pp. 79.
- http://www.math.sfu.ca/~cbm/aands/
+ https://personal.math.ubc.ca/~cbm/aands/page_79.htm
Examples
--------
@@ -560,7 +563,8 @@ add_newdoc('numpy.core.umath', 'arctanh',
References
----------
.. [1] M. Abramowitz and I.A. Stegun, "Handbook of Mathematical Functions",
- 10th printing, 1964, pp. 86. http://www.math.sfu.ca/~cbm/aands/
+ 10th printing, 1964, pp. 86.
+ https://personal.math.ubc.ca/~cbm/aands/page_86.htm
.. [2] Wikipedia, "Inverse hyperbolic function",
https://en.wikipedia.org/wiki/Arctanh
@@ -1222,7 +1226,7 @@ add_newdoc('numpy.core.umath', 'exp',
https://en.wikipedia.org/wiki/Exponential_function
.. [2] M. Abramovitz and I. A. Stegun, "Handbook of Mathematical Functions
with Formulas, Graphs, and Mathematical Tables," Dover, 1964, p. 69,
- http://www.math.sfu.ca/~cbm/aands/page_69.htm
+ https://personal.math.ubc.ca/~cbm/aands/page_69.htm
Examples
--------
@@ -2052,7 +2056,8 @@ add_newdoc('numpy.core.umath', 'log',
References
----------
.. [1] M. Abramowitz and I.A. Stegun, "Handbook of Mathematical Functions",
- 10th printing, 1964, pp. 67. http://www.math.sfu.ca/~cbm/aands/
+ 10th printing, 1964, pp. 67.
+ https://personal.math.ubc.ca/~cbm/aands/page_67.htm
.. [2] Wikipedia, "Logarithm". https://en.wikipedia.org/wiki/Logarithm
Examples
@@ -2101,7 +2106,8 @@ add_newdoc('numpy.core.umath', 'log10',
References
----------
.. [1] M. Abramowitz and I.A. Stegun, "Handbook of Mathematical Functions",
- 10th printing, 1964, pp. 67. http://www.math.sfu.ca/~cbm/aands/
+ 10th printing, 1964, pp. 67.
+ https://personal.math.ubc.ca/~cbm/aands/page_67.htm
.. [2] Wikipedia, "Logarithm". https://en.wikipedia.org/wiki/Logarithm
Examples
@@ -2289,7 +2295,8 @@ add_newdoc('numpy.core.umath', 'log1p',
References
----------
.. [1] M. Abramowitz and I.A. Stegun, "Handbook of Mathematical Functions",
- 10th printing, 1964, pp. 67. http://www.math.sfu.ca/~cbm/aands/
+ 10th printing, 1964, pp. 67.
+ https://personal.math.ubc.ca/~cbm/aands/page_67.htm
.. [2] Wikipedia, "Logarithm". https://en.wikipedia.org/wiki/Logarithm
Examples
@@ -4002,7 +4009,7 @@ add_newdoc('numpy.core.umath', 'tanh',
----------
.. [1] M. Abramowitz and I. A. Stegun, Handbook of Mathematical Functions.
New York, NY: Dover, 1972, pg. 83.
- http://www.math.sfu.ca/~cbm/aands/
+ https://personal.math.ubc.ca/~cbm/aands/page_83.htm
.. [2] Wikipedia, "Hyperbolic function",
https://en.wikipedia.org/wiki/Hyperbolic_function
diff --git a/numpy/core/memmap.pyi b/numpy/core/memmap.pyi
new file mode 100644
index 000000000..ba595bf1e
--- /dev/null
+++ b/numpy/core/memmap.pyi
@@ -0,0 +1,5 @@
+from typing import List
+
+from numpy import memmap as memmap
+
+__all__: List[str]
diff --git a/numpy/core/records.py b/numpy/core/records.py
index 90e3b96df..c014bc97c 100644
--- a/numpy/core/records.py
+++ b/numpy/core/records.py
@@ -41,7 +41,7 @@ from . import numeric as sb
from . import numerictypes as nt
from numpy.compat import os_fspath
from numpy.core.overrides import set_module
-from .arrayprint import get_printoptions
+from .arrayprint import _get_legacy_print_mode
# All of the functions allow formats to be a dtype
__all__ = [
@@ -230,12 +230,12 @@ class record(nt.void):
__module__ = 'numpy'
def __repr__(self):
- if get_printoptions()['legacy'] == '1.13':
+ if _get_legacy_print_mode() <= 113:
return self.__str__()
return super().__repr__()
def __str__(self):
- if get_printoptions()['legacy'] == '1.13':
+ if _get_legacy_print_mode() <= 113:
return str(self.item())
return super().__str__()
@@ -551,7 +551,7 @@ class recarray(ndarray):
lst = "[], shape=%s" % (repr(self.shape),)
lf = '\n'+' '*len(prefix)
- if get_printoptions()['legacy'] == '1.13':
+ if _get_legacy_print_mode() <= 113:
lf = ' ' + lf # trailing space
return fmt % (lst, lf, repr_dtype)
diff --git a/numpy/core/src/multiarray/datetime.c b/numpy/core/src/multiarray/datetime.c
index 11a941e72..b24bc0356 100644
--- a/numpy/core/src/multiarray/datetime.c
+++ b/numpy/core/src/multiarray/datetime.c
@@ -1160,7 +1160,7 @@ get_datetime_conversion_factor(PyArray_DatetimeMetaData *src_meta,
}
/* If something overflowed, make both num and denom 0 */
- if (denom == 0 || num == 0) {
+ if (num == 0) {
PyErr_Format(PyExc_OverflowError,
"Integer overflow while computing the conversion "
"factor between NumPy datetime units %s and %s",
diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c
index 3b70424a5..5ceed1678 100644
--- a/numpy/core/src/multiarray/multiarraymodule.c
+++ b/numpy/core/src/multiarray/multiarraymodule.c
@@ -82,11 +82,12 @@ NPY_NO_EXPORT int set_matmul_flags(PyObject *d); /* in ufunc_object.c */
/*
* global variable to determine if legacy printing is enabled, accessible from
- * C. For simplicity the mode is encoded as an integer where '0' means no
- * legacy mode, and '113' means 1.13 legacy mode. We can upgrade this if we
- * have more complex requirements in the future.
+ * C. For simplicity the mode is encoded as an integer where INT_MAX means no
+ * legacy mode, and '113'/'121' means 1.13/1.21 legacy mode; and 0 maps to
+ * INT_MAX. We can upgrade this if we have more complex requirements in the
+ * future.
*/
-int npy_legacy_print_mode = 0;
+int npy_legacy_print_mode = INT_MAX;
static PyObject *
set_legacy_print_mode(PyObject *NPY_UNUSED(self), PyObject *args)
@@ -94,6 +95,9 @@ set_legacy_print_mode(PyObject *NPY_UNUSED(self), PyObject *args)
if (!PyArg_ParseTuple(args, "i", &npy_legacy_print_mode)) {
return NULL;
}
+ if (!npy_legacy_print_mode) {
+ npy_legacy_print_mode = INT_MAX;
+ }
Py_RETURN_NONE;
}
diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src
index 93cc9666e..56f17431a 100644
--- a/numpy/core/src/multiarray/scalartypes.c.src
+++ b/numpy/core/src/multiarray/scalartypes.c.src
@@ -866,7 +866,7 @@ static PyObject *
{
npy_@name@ absval;
- if (npy_legacy_print_mode == 113) {
+ if (npy_legacy_print_mode <= 113) {
return legacy_@name@_format@kind@(val);
}
@@ -892,7 +892,7 @@ c@name@type_@kind@(PyObject *self)
npy_c@name@ val = PyArrayScalar_VAL(self, C@Name@);
TrimMode trim = TrimMode_DptZeros;
- if (npy_legacy_print_mode == 113) {
+ if (npy_legacy_print_mode <= 113) {
return legacy_c@name@_format@kind@(val);
}
@@ -957,7 +957,7 @@ halftype_@kind@(PyObject *self)
float floatval = npy_half_to_float(val);
float absval;
- if (npy_legacy_print_mode == 113) {
+ if (npy_legacy_print_mode <= 113) {
return legacy_float_format@kind@(floatval);
}
diff --git a/numpy/core/src/npymath/npy_math_internal.h.src b/numpy/core/src/npymath/npy_math_internal.h.src
index 1e46a2303..cae84befe 100644
--- a/numpy/core/src/npymath/npy_math_internal.h.src
+++ b/numpy/core/src/npymath/npy_math_internal.h.src
@@ -457,21 +457,40 @@ NPY_INPLACE @type@ npy_frexp@c@(@type@ x, int* exp)
* #c = l,,f#
* #C = L,,F#
*/
+
+/*
+ * On arm64 macOS, there's a bug with sin, cos, and tan where they don't
+ * raise "invalid" when given INFINITY as input.
+ */
+#if defined(__APPLE__) && defined(__arm64__)
+#define WORKAROUND_APPLE_TRIG_BUG 1
+#else
+#define WORKAROUND_APPLE_TRIG_BUG 0
+#endif
+
/**begin repeat1
* #kind = sin,cos,tan,sinh,cosh,tanh,fabs,floor,ceil,rint,trunc,sqrt,log10,
* log,exp,expm1,asin,acos,atan,asinh,acosh,atanh,log1p,exp2,log2#
* #KIND = SIN,COS,TAN,SINH,COSH,TANH,FABS,FLOOR,CEIL,RINT,TRUNC,SQRT,LOG10,
* LOG,EXP,EXPM1,ASIN,ACOS,ATAN,ASINH,ACOSH,ATANH,LOG1P,EXP2,LOG2#
+ * #TRIG_WORKAROUND = WORKAROUND_APPLE_TRIG_BUG*3, 0*22#
*/
#ifdef HAVE_@KIND@@C@
NPY_INPLACE @type@ npy_@kind@@c@(@type@ x)
{
+#if @TRIG_WORKAROUND@
+ if (!npy_isfinite(x)) {
+ return (x - x);
+ }
+#endif
return @kind@@c@(x);
}
#endif
/**end repeat1**/
+#undef WORKAROUND_APPLE_TRIG_BUG
+
/**begin repeat1
* #kind = atan2,hypot,pow,fmod,copysign#
* #KIND = ATAN2,HYPOT,POW,FMOD,COPYSIGN#
diff --git a/numpy/core/tests/test_casting_unittests.py b/numpy/core/tests/test_casting_unittests.py
index d41d6dcc0..b0d8ff503 100644
--- a/numpy/core/tests/test_casting_unittests.py
+++ b/numpy/core/tests/test_casting_unittests.py
@@ -699,9 +699,14 @@ class TestCasting:
else:
assert_array_equal(expected, arr_NULLs.astype(dtype))
- def test_float_to_bool(self):
- # test case corresponding to gh-19514
- # simple test for casting bool_ to float16
- res = np.array([0, 3, -7], dtype=np.int8).view(bool)
+ @pytest.mark.parametrize("dtype",
+ np.typecodes["AllInteger"] + np.typecodes["AllFloat"])
+ def test_nonstandard_bool_to_other(self, dtype):
+ # simple test for casting bool_ to numeric types, which should not
+ # expose the detail that NumPy bools can sometimes take values other
+ # than 0 and 1. See also gh-19514.
+ nonstandard_bools = np.array([0, 3, -7], dtype=np.int8).view(bool)
+ res = nonstandard_bools.astype(dtype)
expected = [0, 1, 1]
assert_array_equal(res, expected)
+
diff --git a/numpy/core/tests/test_dtype.py b/numpy/core/tests/test_dtype.py
index db4f275b5..1c25bee00 100644
--- a/numpy/core/tests/test_dtype.py
+++ b/numpy/core/tests/test_dtype.py
@@ -878,14 +878,24 @@ class TestString:
('bright', '>f4', (8, 36))])],
align=True)
assert_equal(str(dt),
- "{'names':['top','bottom'], "
- "'formats':[([('tiles', ('>f4', (64, 64)), (1,)), "
- "('rtile', '>f4', (64, 36))], (3,)),"
- "[('bleft', ('>f4', (8, 64)), (1,)), "
- "('bright', '>f4', (8, 36))]], "
- "'offsets':[0,76800], "
- "'itemsize':80000, "
- "'aligned':True}")
+ "{'names': ['top', 'bottom'],"
+ " 'formats': [([('tiles', ('>f4', (64, 64)), (1,)), "
+ "('rtile', '>f4', (64, 36))], (3,)), "
+ "[('bleft', ('>f4', (8, 64)), (1,)), "
+ "('bright', '>f4', (8, 36))]],"
+ " 'offsets': [0, 76800],"
+ " 'itemsize': 80000,"
+ " 'aligned': True}")
+ with np.printoptions(legacy='1.21'):
+ assert_equal(str(dt),
+ "{'names':['top','bottom'], "
+ "'formats':[([('tiles', ('>f4', (64, 64)), (1,)), "
+ "('rtile', '>f4', (64, 36))], (3,)),"
+ "[('bleft', ('>f4', (8, 64)), (1,)), "
+ "('bright', '>f4', (8, 36))]], "
+ "'offsets':[0,76800], "
+ "'itemsize':80000, "
+ "'aligned':True}")
assert_equal(np.dtype(eval(str(dt))), dt)
dt = np.dtype({'names': ['r', 'g', 'b'], 'formats': ['u1', 'u1', 'u1'],
@@ -902,22 +912,22 @@ class TestString:
'titles': ['Color', 'Red pixel',
'Green pixel', 'Blue pixel']})
assert_equal(str(dt),
- "{'names':['rgba','r','g','b'],"
- " 'formats':['<u4','u1','u1','u1'],"
- " 'offsets':[0,0,1,2],"
- " 'titles':['Color','Red pixel',"
- "'Green pixel','Blue pixel'],"
- " 'itemsize':4}")
+ "{'names': ['rgba', 'r', 'g', 'b'],"
+ " 'formats': ['<u4', 'u1', 'u1', 'u1'],"
+ " 'offsets': [0, 0, 1, 2],"
+ " 'titles': ['Color', 'Red pixel', "
+ "'Green pixel', 'Blue pixel'],"
+ " 'itemsize': 4}")
dt = np.dtype({'names': ['r', 'b'], 'formats': ['u1', 'u1'],
'offsets': [0, 2],
'titles': ['Red pixel', 'Blue pixel']})
assert_equal(str(dt),
- "{'names':['r','b'],"
- " 'formats':['u1','u1'],"
- " 'offsets':[0,2],"
- " 'titles':['Red pixel','Blue pixel'],"
- " 'itemsize':3}")
+ "{'names': ['r', 'b'],"
+ " 'formats': ['u1', 'u1'],"
+ " 'offsets': [0, 2],"
+ " 'titles': ['Red pixel', 'Blue pixel'],"
+ " 'itemsize': 3}")
dt = np.dtype([('a', '<m8[D]'), ('b', '<M8[us]')])
assert_equal(str(dt),
@@ -950,23 +960,23 @@ class TestString:
'titles': ['Color', 'Red pixel',
'Green pixel', 'Blue pixel']}, align=True)
assert_equal(repr(dt),
- "dtype({'names':['rgba','r','g','b'],"
- " 'formats':['<u4','u1','u1','u1'],"
- " 'offsets':[0,0,1,2],"
- " 'titles':['Color','Red pixel',"
- "'Green pixel','Blue pixel'],"
- " 'itemsize':4}, align=True)")
+ "dtype({'names': ['rgba', 'r', 'g', 'b'],"
+ " 'formats': ['<u4', 'u1', 'u1', 'u1'],"
+ " 'offsets': [0, 0, 1, 2],"
+ " 'titles': ['Color', 'Red pixel', "
+ "'Green pixel', 'Blue pixel'],"
+ " 'itemsize': 4}, align=True)")
dt = np.dtype({'names': ['r', 'b'], 'formats': ['u1', 'u1'],
'offsets': [0, 2],
'titles': ['Red pixel', 'Blue pixel'],
'itemsize': 4})
assert_equal(repr(dt),
- "dtype({'names':['r','b'], "
- "'formats':['u1','u1'], "
- "'offsets':[0,2], "
- "'titles':['Red pixel','Blue pixel'], "
- "'itemsize':4})")
+ "dtype({'names': ['r', 'b'], "
+ "'formats': ['u1', 'u1'], "
+ "'offsets': [0, 2], "
+ "'titles': ['Red pixel', 'Blue pixel'], "
+ "'itemsize': 4})")
def test_repr_structured_datetime(self):
dt = np.dtype([('a', '<M8[D]'), ('b', '<m8[us]')])
diff --git a/numpy/distutils/fcompiler/__init__.py b/numpy/distutils/fcompiler/__init__.py
index d7579e976..c333517c0 100644
--- a/numpy/distutils/fcompiler/__init__.py
+++ b/numpy/distutils/fcompiler/__init__.py
@@ -745,7 +745,8 @@ _default_compilers = (
('cygwin.*', ('gnu', 'intelv', 'absoft', 'compaqv', 'intelev', 'gnu95', 'g95')),
('linux.*', ('gnu95', 'intel', 'lahey', 'pg', 'nv', 'absoft', 'nag', 'vast', 'compaq',
'intele', 'intelem', 'gnu', 'g95', 'pathf95', 'nagfor', 'fujitsu')),
- ('darwin.*', ('gnu95', 'nag', 'absoft', 'ibm', 'intel', 'gnu', 'g95', 'pg')),
+ ('darwin.*', ('gnu95', 'nag', 'nagfor', 'absoft', 'ibm', 'intel', 'gnu',
+ 'g95', 'pg')),
('sunos.*', ('sun', 'gnu', 'gnu95', 'g95')),
('irix.*', ('mips', 'gnu', 'gnu95',)),
('aix.*', ('ibm', 'gnu', 'gnu95',)),
diff --git a/numpy/distutils/fcompiler/nag.py b/numpy/distutils/fcompiler/nag.py
index 7df8ffe2c..fb85c821a 100644
--- a/numpy/distutils/fcompiler/nag.py
+++ b/numpy/distutils/fcompiler/nag.py
@@ -15,6 +15,9 @@ class BaseNAGFCompiler(FCompiler):
return None
def get_flags_linker_so(self):
+ if sys.platform == 'darwin':
+ return ['-unsharedf95',
+ '-Wl,-bundle,-flat_namespace,-undefined,suppress']
return ["-Wl,-shared"]
def get_flags_opt(self):
return ['-O4']
@@ -36,10 +39,6 @@ class NAGFCompiler(BaseNAGFCompiler):
'ranlib' : ["ranlib"]
}
- def get_flags_linker_so(self):
- if sys.platform == 'darwin':
- return ['-unsharedf95', '-Wl,-bundle,-flat_namespace,-undefined,suppress']
- return BaseNAGFCompiler.get_flags_linker_so(self)
def get_flags_arch(self):
version = self.get_version()
if version and version < '5.1':
diff --git a/numpy/f2py/cfuncs.py b/numpy/f2py/cfuncs.py
index fb1688744..1d9236dcd 100644
--- a/numpy/f2py/cfuncs.py
+++ b/numpy/f2py/cfuncs.py
@@ -338,16 +338,16 @@ cppmacros['TRYPYARRAYTEMPLATE'] = """\
if (!(arr=(PyArrayObject *)obj)) {fprintf(stderr,\"TRYPYARRAYTEMPLATE:\");PRINTPYOBJERR(obj);return 0;}\\
if (PyArray_DESCR(arr)->type==typecode) {*(ctype *)(PyArray_DATA(arr))=*v; return 1;}\\
switch (PyArray_TYPE(arr)) {\\
- case NPY_DOUBLE: *(double *)(PyArray_DATA(arr))=*v; break;\\
- case NPY_INT: *(int *)(PyArray_DATA(arr))=*v; break;\\
- case NPY_LONG: *(long *)(PyArray_DATA(arr))=*v; break;\\
- case NPY_FLOAT: *(float *)(PyArray_DATA(arr))=*v; break;\\
- case NPY_CDOUBLE: *(double *)(PyArray_DATA(arr))=*v; break;\\
- case NPY_CFLOAT: *(float *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_DOUBLE: *(npy_double *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_INT: *(npy_int *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_LONG: *(npy_long *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_FLOAT: *(npy_float *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_CDOUBLE: *(npy_double *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_CFLOAT: *(npy_float *)(PyArray_DATA(arr))=*v; break;\\
case NPY_BOOL: *(npy_bool *)(PyArray_DATA(arr))=(*v!=0); break;\\
- case NPY_UBYTE: *(unsigned char *)(PyArray_DATA(arr))=*v; break;\\
- case NPY_BYTE: *(signed char *)(PyArray_DATA(arr))=*v; break;\\
- case NPY_SHORT: *(short *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_UBYTE: *(npy_ubyte *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_BYTE: *(npy_byte *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_SHORT: *(npy_short *)(PyArray_DATA(arr))=*v; break;\\
case NPY_USHORT: *(npy_ushort *)(PyArray_DATA(arr))=*v; break;\\
case NPY_UINT: *(npy_uint *)(PyArray_DATA(arr))=*v; break;\\
case NPY_ULONG: *(npy_ulong *)(PyArray_DATA(arr))=*v; break;\\
@@ -375,15 +375,19 @@ cppmacros['TRYCOMPLEXPYARRAYTEMPLATE'] = """\
return 1;\\
}\\
switch (PyArray_TYPE(arr)) {\\
- case NPY_CDOUBLE: *(double *)(PyArray_DATA(arr))=(*v).r;*(double *)(PyArray_DATA(arr)+sizeof(double))=(*v).i;break;\\
- case NPY_CFLOAT: *(float *)(PyArray_DATA(arr))=(*v).r;*(float *)(PyArray_DATA(arr)+sizeof(float))=(*v).i;break;\\
- case NPY_DOUBLE: *(double *)(PyArray_DATA(arr))=(*v).r; break;\\
- case NPY_LONG: *(long *)(PyArray_DATA(arr))=(*v).r; break;\\
- case NPY_FLOAT: *(float *)(PyArray_DATA(arr))=(*v).r; break;\\
- case NPY_INT: *(int *)(PyArray_DATA(arr))=(*v).r; break;\\
- case NPY_SHORT: *(short *)(PyArray_DATA(arr))=(*v).r; break;\\
- case NPY_UBYTE: *(unsigned char *)(PyArray_DATA(arr))=(*v).r; break;\\
- case NPY_BYTE: *(signed char *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_CDOUBLE: *(npy_double *)(PyArray_DATA(arr))=(*v).r;\\
+ *(npy_double *)(PyArray_DATA(arr)+sizeof(npy_double))=(*v).i;\\
+ break;\\
+ case NPY_CFLOAT: *(npy_float *)(PyArray_DATA(arr))=(*v).r;\\
+ *(npy_float *)(PyArray_DATA(arr)+sizeof(npy_float))=(*v).i;\\
+ break;\\
+ case NPY_DOUBLE: *(npy_double *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_LONG: *(npy_long *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_FLOAT: *(npy_float *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_INT: *(npy_int *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_SHORT: *(npy_short *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_UBYTE: *(npy_ubyte *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_BYTE: *(npy_byte *)(PyArray_DATA(arr))=(*v).r; break;\\
case NPY_BOOL: *(npy_bool *)(PyArray_DATA(arr))=((*v).r!=0 && (*v).i!=0); break;\\
case NPY_USHORT: *(npy_ushort *)(PyArray_DATA(arr))=(*v).r; break;\\
case NPY_UINT: *(npy_uint *)(PyArray_DATA(arr))=(*v).r; break;\\
@@ -391,7 +395,9 @@ cppmacros['TRYCOMPLEXPYARRAYTEMPLATE'] = """\
case NPY_LONGLONG: *(npy_longlong *)(PyArray_DATA(arr))=(*v).r; break;\\
case NPY_ULONGLONG: *(npy_ulonglong *)(PyArray_DATA(arr))=(*v).r; break;\\
case NPY_LONGDOUBLE: *(npy_longdouble *)(PyArray_DATA(arr))=(*v).r; break;\\
- case NPY_CLONGDOUBLE: *(npy_longdouble *)(PyArray_DATA(arr))=(*v).r;*(npy_longdouble *)(PyArray_DATA(arr)+sizeof(npy_longdouble))=(*v).i;break;\\
+ case NPY_CLONGDOUBLE: *(npy_longdouble *)(PyArray_DATA(arr))=(*v).r;\\
+ *(npy_longdouble *)(PyArray_DATA(arr)+sizeof(npy_longdouble))=(*v).i;\\
+ break;\\
case NPY_OBJECT: PyArray_SETITEM(arr, PyArray_DATA(arr), pyobj_from_complex_ ## ctype ## 1((*v))); break;\\
default: return -2;\\
};\\
diff --git a/numpy/f2py/rules.py b/numpy/f2py/rules.py
index 587ae2e5f..66f11f6b5 100755
--- a/numpy/f2py/rules.py
+++ b/numpy/f2py/rules.py
@@ -120,6 +120,10 @@ module_rules = {
extern \"C\" {
#endif
+#ifndef PY_SSIZE_T_CLEAN
+#define PY_SSIZE_T_CLEAN
+#endif /* PY_SSIZE_T_CLEAN */
+
""" + gentitle("See f2py2e/cfuncs.py: includes") + """
#includes#
#includes0#
diff --git a/numpy/f2py/src/fortranobject.c b/numpy/f2py/src/fortranobject.c
index b9ef18701..0b32137ef 100644
--- a/numpy/f2py/src/fortranobject.c
+++ b/numpy/f2py/src/fortranobject.c
@@ -19,7 +19,7 @@ extern "C" {
int
F2PyDict_SetItemString(PyObject *dict, char *name, PyObject *obj)
{
- if (obj==NULL) {
+ if (obj == NULL) {
fprintf(stderr, "Error loading %s\n", name);
if (PyErr_Occurred()) {
PyErr_Print();
@@ -33,21 +33,25 @@ F2PyDict_SetItemString(PyObject *dict, char *name, PyObject *obj)
/*
* Python-only fallback for thread-local callback pointers
*/
-void *F2PySwapThreadLocalCallbackPtr(char *key, void *ptr)
+void *
+F2PySwapThreadLocalCallbackPtr(char *key, void *ptr)
{
PyObject *local_dict, *value;
void *prev;
local_dict = PyThreadState_GetDict();
if (local_dict == NULL) {
- Py_FatalError("F2PySwapThreadLocalCallbackPtr: PyThreadState_GetDict failed");
+ Py_FatalError(
+ "F2PySwapThreadLocalCallbackPtr: PyThreadState_GetDict "
+ "failed");
}
value = PyDict_GetItemString(local_dict, key);
if (value != NULL) {
prev = PyLong_AsVoidPtr(value);
if (PyErr_Occurred()) {
- Py_FatalError("F2PySwapThreadLocalCallbackPtr: PyLong_AsVoidPtr failed");
+ Py_FatalError(
+ "F2PySwapThreadLocalCallbackPtr: PyLong_AsVoidPtr failed");
}
}
else {
@@ -56,11 +60,13 @@ void *F2PySwapThreadLocalCallbackPtr(char *key, void *ptr)
value = PyLong_FromVoidPtr((void *)ptr);
if (value == NULL) {
- Py_FatalError("F2PySwapThreadLocalCallbackPtr: PyLong_FromVoidPtr failed");
+ Py_FatalError(
+ "F2PySwapThreadLocalCallbackPtr: PyLong_FromVoidPtr failed");
}
if (PyDict_SetItemString(local_dict, key, value) != 0) {
- Py_FatalError("F2PySwapThreadLocalCallbackPtr: PyDict_SetItemString failed");
+ Py_FatalError(
+ "F2PySwapThreadLocalCallbackPtr: PyDict_SetItemString failed");
}
Py_DECREF(value);
@@ -68,21 +74,24 @@ void *F2PySwapThreadLocalCallbackPtr(char *key, void *ptr)
return prev;
}
-void *F2PyGetThreadLocalCallbackPtr(char *key)
+void *
+F2PyGetThreadLocalCallbackPtr(char *key)
{
PyObject *local_dict, *value;
void *prev;
local_dict = PyThreadState_GetDict();
if (local_dict == NULL) {
- Py_FatalError("F2PyGetThreadLocalCallbackPtr: PyThreadState_GetDict failed");
+ Py_FatalError(
+ "F2PyGetThreadLocalCallbackPtr: PyThreadState_GetDict failed");
}
value = PyDict_GetItemString(local_dict, key);
if (value != NULL) {
prev = PyLong_AsVoidPtr(value);
if (PyErr_Occurred()) {
- Py_FatalError("F2PyGetThreadLocalCallbackPtr: PyLong_AsVoidPtr failed");
+ Py_FatalError(
+ "F2PyGetThreadLocalCallbackPtr: PyLong_AsVoidPtr failed");
}
}
else {
@@ -94,14 +103,15 @@ void *F2PyGetThreadLocalCallbackPtr(char *key)
/************************* FortranObject *******************************/
-typedef PyObject *(*fortranfunc)(PyObject *,PyObject *,PyObject *,void *);
+typedef PyObject *(*fortranfunc)(PyObject *, PyObject *, PyObject *, void *);
PyObject *
-PyFortranObject_New(FortranDataDef* defs, f2py_void_func init) {
+PyFortranObject_New(FortranDataDef *defs, f2py_void_func init)
+{
int i;
PyFortranObject *fp = NULL;
PyObject *v = NULL;
- if (init!=NULL) { /* Initialize F90 module objects */
+ if (init != NULL) { /* Initialize F90 module objects */
(*(init))();
}
fp = PyObject_New(PyFortranObject, &PyFortran_Type);
@@ -120,46 +130,49 @@ PyFortranObject_New(FortranDataDef* defs, f2py_void_func init) {
goto fail;
}
fp->defs = defs;
- for (i=0;i<fp->len;i++) {
- if (fp->defs[i].rank == -1) { /* Is Fortran routine */
+ for (i = 0; i < fp->len; i++) {
+ if (fp->defs[i].rank == -1) { /* Is Fortran routine */
v = PyFortranObject_NewAsAttr(&(fp->defs[i]));
- if (v==NULL) {
+ if (v == NULL) {
goto fail;
}
- PyDict_SetItemString(fp->dict,fp->defs[i].name,v);
+ PyDict_SetItemString(fp->dict, fp->defs[i].name, v);
Py_XDECREF(v);
- } else
- if ((fp->defs[i].data)!=NULL) { /* Is Fortran variable or array (not allocatable) */
- if (fp->defs[i].type == NPY_STRING) {
- int n = fp->defs[i].rank-1;
- v = PyArray_New(&PyArray_Type, n, fp->defs[i].dims.d,
- NPY_STRING, NULL, fp->defs[i].data, fp->defs[i].dims.d[n],
- NPY_ARRAY_FARRAY, NULL);
- }
- else {
- v = PyArray_New(&PyArray_Type, fp->defs[i].rank, fp->defs[i].dims.d,
- fp->defs[i].type, NULL, fp->defs[i].data, 0, NPY_ARRAY_FARRAY,
- NULL);
- }
- if (v==NULL) {
- goto fail;
- }
- PyDict_SetItemString(fp->dict,fp->defs[i].name,v);
- Py_XDECREF(v);
+ }
+ else if ((fp->defs[i].data) !=
+ NULL) { /* Is Fortran variable or array (not allocatable) */
+ if (fp->defs[i].type == NPY_STRING) {
+ npy_intp n = fp->defs[i].rank - 1;
+ v = PyArray_New(&PyArray_Type, n, fp->defs[i].dims.d,
+ NPY_STRING, NULL, fp->defs[i].data,
+ fp->defs[i].dims.d[n], NPY_ARRAY_FARRAY, NULL);
+ }
+ else {
+ v = PyArray_New(&PyArray_Type, fp->defs[i].rank,
+ fp->defs[i].dims.d, fp->defs[i].type, NULL,
+ fp->defs[i].data, 0, NPY_ARRAY_FARRAY, NULL);
+ }
+ if (v == NULL) {
+ goto fail;
}
+ PyDict_SetItemString(fp->dict, fp->defs[i].name, v);
+ Py_XDECREF(v);
+ }
}
return (PyObject *)fp;
- fail:
+fail:
Py_XDECREF(fp);
return NULL;
}
PyObject *
-PyFortranObject_NewAsAttr(FortranDataDef* defs) { /* used for calling F90 module routines */
+PyFortranObject_NewAsAttr(FortranDataDef *defs)
+{ /* used for calling F90 module routines */
PyFortranObject *fp = NULL;
fp = PyObject_New(PyFortranObject, &PyFortran_Type);
- if (fp == NULL) return NULL;
- if ((fp->dict = PyDict_New())==NULL) {
+ if (fp == NULL)
+ return NULL;
+ if ((fp->dict = PyDict_New()) == NULL) {
PyObject_Del(fp);
return NULL;
}
@@ -171,18 +184,19 @@ PyFortranObject_NewAsAttr(FortranDataDef* defs) { /* used for calling F90 module
/* Fortran methods */
static void
-fortran_dealloc(PyFortranObject *fp) {
+fortran_dealloc(PyFortranObject *fp)
+{
Py_XDECREF(fp->dict);
PyObject_Del(fp);
}
-
/* Returns number of bytes consumed from buf, or -1 on error. */
static Py_ssize_t
format_def(char *buf, Py_ssize_t size, FortranDataDef def)
{
char *p = buf;
- int i, n;
+ int i;
+ npy_intp n;
n = PyOS_snprintf(p, size, "array(%" NPY_INTP_FMT, def.dims.d[0]);
if (n < 0 || n >= size) {
@@ -209,7 +223,7 @@ format_def(char *buf, Py_ssize_t size, FortranDataDef def)
if (def.data == NULL) {
static const char notalloc[] = ", not allocated";
- if ((size_t) size < sizeof(notalloc)) {
+ if ((size_t)size < sizeof(notalloc)) {
return -1;
}
memcpy(p, notalloc, sizeof(notalloc));
@@ -290,7 +304,6 @@ fortran_doc(FortranDataDef def)
p += n;
size -= n;
}
-
}
if (size <= 1) {
goto fail;
@@ -304,17 +317,20 @@ fortran_doc(FortranDataDef def)
PyMem_Free(buf);
return s;
- fail:
- fprintf(stderr, "fortranobject.c: fortran_doc: len(p)=%zd>%zd=size:"
- " too long docstring required, increase size\n",
+fail:
+ fprintf(stderr,
+ "fortranobject.c: fortran_doc: len(p)=%zd>%zd=size:"
+ " too long docstring required, increase size\n",
p - buf, origsize);
PyMem_Free(buf);
return NULL;
}
static FortranDataDef *save_def; /* save pointer of an allocatable array */
-static void set_data(char *d,npy_intp *f) { /* callback from Fortran */
- if (*f) /* In fortran f=allocated(d) */
+static void
+set_data(char *d, npy_intp *f)
+{ /* callback from Fortran */
+ if (*f) /* In fortran f=allocated(d) */
save_def->data = d;
else
save_def->data = NULL;
@@ -322,8 +338,9 @@ static void set_data(char *d,npy_intp *f) { /* callback from Fortran */
}
static PyObject *
-fortran_getattr(PyFortranObject *fp, char *name) {
- int i,j,k,flag;
+fortran_getattr(PyFortranObject *fp, char *name)
+{
+ int i, j, k, flag;
if (fp->dict != NULL) {
PyObject *v = _PyDict_GetItemStringWithError(fp->dict, name);
if (v == NULL && PyErr_Occurred()) {
@@ -334,36 +351,41 @@ fortran_getattr(PyFortranObject *fp, char *name) {
return v;
}
}
- for (i=0,j=1;i<fp->len && (j=strcmp(name,fp->defs[i].name));i++);
- if (j==0)
- if (fp->defs[i].rank!=-1) { /* F90 allocatable array */
- if (fp->defs[i].func==NULL) return NULL;
- for(k=0;k<fp->defs[i].rank;++k)
- fp->defs[i].dims.d[k]=-1;
+ for (i = 0, j = 1; i < fp->len && (j = strcmp(name, fp->defs[i].name));
+ i++)
+ ;
+ if (j == 0)
+ if (fp->defs[i].rank != -1) { /* F90 allocatable array */
+ if (fp->defs[i].func == NULL)
+ return NULL;
+ for (k = 0; k < fp->defs[i].rank; ++k) fp->defs[i].dims.d[k] = -1;
save_def = &fp->defs[i];
- (*(fp->defs[i].func))(&fp->defs[i].rank,fp->defs[i].dims.d,set_data,&flag);
- if (flag==2)
+ (*(fp->defs[i].func))(&fp->defs[i].rank, fp->defs[i].dims.d,
+ set_data, &flag);
+ if (flag == 2)
k = fp->defs[i].rank + 1;
else
k = fp->defs[i].rank;
- if (fp->defs[i].data !=NULL) { /* array is allocated */
- PyObject *v = PyArray_New(&PyArray_Type, k, fp->defs[i].dims.d,
- fp->defs[i].type, NULL, fp->defs[i].data, 0, NPY_ARRAY_FARRAY,
- NULL);
- if (v==NULL) return NULL;
+ if (fp->defs[i].data != NULL) { /* array is allocated */
+ PyObject *v = PyArray_New(
+ &PyArray_Type, k, fp->defs[i].dims.d, fp->defs[i].type,
+ NULL, fp->defs[i].data, 0, NPY_ARRAY_FARRAY, NULL);
+ if (v == NULL)
+ return NULL;
/* Py_INCREF(v); */
return v;
- } else { /* array is not allocated */
+ }
+ else { /* array is not allocated */
Py_RETURN_NONE;
}
}
- if (strcmp(name,"__dict__")==0) {
+ if (strcmp(name, "__dict__") == 0) {
Py_INCREF(fp->dict);
return fp->dict;
}
- if (strcmp(name,"__doc__")==0) {
+ if (strcmp(name, "__doc__") == 0) {
PyObject *s = PyUnicode_FromString(""), *s2, *s3;
- for (i=0;i<fp->len;i++) {
+ for (i = 0; i < fp->len; i++) {
s2 = fortran_doc(fp->defs[i]);
s3 = PyUnicode_Concat(s, s2);
Py_DECREF(s2);
@@ -374,8 +396,9 @@ fortran_getattr(PyFortranObject *fp, char *name) {
return NULL;
return s;
}
- if ((strcmp(name,"_cpointer")==0) && (fp->len==1)) {
- PyObject *cobj = F2PyCapsule_FromVoidPtr((void *)(fp->defs[0].data),NULL);
+ if ((strcmp(name, "_cpointer") == 0) && (fp->len == 1)) {
+ PyObject *cobj =
+ F2PyCapsule_FromVoidPtr((void *)(fp->defs[0].data), NULL);
if (PyDict_SetItemString(fp->dict, name, cobj))
return NULL;
return cobj;
@@ -388,51 +411,68 @@ fortran_getattr(PyFortranObject *fp, char *name) {
}
static int
-fortran_setattr(PyFortranObject *fp, char *name, PyObject *v) {
- int i,j,flag;
+fortran_setattr(PyFortranObject *fp, char *name, PyObject *v)
+{
+ int i, j, flag;
PyArrayObject *arr = NULL;
- for (i=0,j=1;i<fp->len && (j=strcmp(name,fp->defs[i].name));i++);
- if (j==0) {
- if (fp->defs[i].rank==-1) {
- PyErr_SetString(PyExc_AttributeError,"over-writing fortran routine");
+ for (i = 0, j = 1; i < fp->len && (j = strcmp(name, fp->defs[i].name));
+ i++)
+ ;
+ if (j == 0) {
+ if (fp->defs[i].rank == -1) {
+ PyErr_SetString(PyExc_AttributeError,
+ "over-writing fortran routine");
return -1;
}
- if (fp->defs[i].func!=NULL) { /* is allocatable array */
+ if (fp->defs[i].func != NULL) { /* is allocatable array */
npy_intp dims[F2PY_MAX_DIMS];
int k;
save_def = &fp->defs[i];
- if (v!=Py_None) { /* set new value (reallocate if needed --
- see f2py generated code for more
- details ) */
- for(k=0;k<fp->defs[i].rank;k++) dims[k]=-1;
- if ((arr = array_from_pyobj(fp->defs[i].type,dims,fp->defs[i].rank,F2PY_INTENT_IN,v))==NULL)
+ if (v != Py_None) { /* set new value (reallocate if needed --
+ see f2py generated code for more
+ details ) */
+ for (k = 0; k < fp->defs[i].rank; k++) dims[k] = -1;
+ if ((arr = array_from_pyobj(fp->defs[i].type, dims,
+ fp->defs[i].rank, F2PY_INTENT_IN,
+ v)) == NULL)
return -1;
- (*(fp->defs[i].func))(&fp->defs[i].rank,PyArray_DIMS(arr),set_data,&flag);
- } else { /* deallocate */
- for(k=0;k<fp->defs[i].rank;k++) dims[k]=0;
- (*(fp->defs[i].func))(&fp->defs[i].rank,dims,set_data,&flag);
- for(k=0;k<fp->defs[i].rank;k++) dims[k]=-1;
+ (*(fp->defs[i].func))(&fp->defs[i].rank, PyArray_DIMS(arr),
+ set_data, &flag);
+ }
+ else { /* deallocate */
+ for (k = 0; k < fp->defs[i].rank; k++) dims[k] = 0;
+ (*(fp->defs[i].func))(&fp->defs[i].rank, dims, set_data,
+ &flag);
+ for (k = 0; k < fp->defs[i].rank; k++) dims[k] = -1;
}
- memcpy(fp->defs[i].dims.d,dims,fp->defs[i].rank*sizeof(npy_intp));
- } else { /* not allocatable array */
- if ((arr = array_from_pyobj(fp->defs[i].type,fp->defs[i].dims.d,fp->defs[i].rank,F2PY_INTENT_IN,v))==NULL)
+ memcpy(fp->defs[i].dims.d, dims,
+ fp->defs[i].rank * sizeof(npy_intp));
+ }
+ else { /* not allocatable array */
+ if ((arr = array_from_pyobj(fp->defs[i].type, fp->defs[i].dims.d,
+ fp->defs[i].rank, F2PY_INTENT_IN,
+ v)) == NULL)
return -1;
}
- if (fp->defs[i].data!=NULL) { /* copy Python object to Fortran array */
- npy_intp s = PyArray_MultiplyList(fp->defs[i].dims.d,PyArray_NDIM(arr));
- if (s==-1)
- s = PyArray_MultiplyList(PyArray_DIMS(arr),PyArray_NDIM(arr));
- if (s<0 ||
- (memcpy(fp->defs[i].data,PyArray_DATA(arr),s*PyArray_ITEMSIZE(arr)))==NULL) {
- if ((PyObject*)arr!=v) {
+ if (fp->defs[i].data !=
+ NULL) { /* copy Python object to Fortran array */
+ npy_intp s = PyArray_MultiplyList(fp->defs[i].dims.d,
+ PyArray_NDIM(arr));
+ if (s == -1)
+ s = PyArray_MultiplyList(PyArray_DIMS(arr), PyArray_NDIM(arr));
+ if (s < 0 || (memcpy(fp->defs[i].data, PyArray_DATA(arr),
+ s * PyArray_ITEMSIZE(arr))) == NULL) {
+ if ((PyObject *)arr != v) {
Py_DECREF(arr);
}
return -1;
}
- if ((PyObject*)arr!=v) {
+ if ((PyObject *)arr != v) {
Py_DECREF(arr);
}
- } else return (fp->defs[i].func==NULL?-1:0);
+ }
+ else
+ return (fp->defs[i].func == NULL ? -1 : 0);
return 0; /* successful */
}
if (fp->dict == NULL) {
@@ -443,30 +483,33 @@ fortran_setattr(PyFortranObject *fp, char *name, PyObject *v) {
if (v == NULL) {
int rv = PyDict_DelItemString(fp->dict, name);
if (rv < 0)
- PyErr_SetString(PyExc_AttributeError,"delete non-existing fortran attribute");
+ PyErr_SetString(PyExc_AttributeError,
+ "delete non-existing fortran attribute");
return rv;
}
else
return PyDict_SetItemString(fp->dict, name, v);
}
-static PyObject*
-fortran_call(PyFortranObject *fp, PyObject *arg, PyObject *kw) {
+static PyObject *
+fortran_call(PyFortranObject *fp, PyObject *arg, PyObject *kw)
+{
int i = 0;
/* printf("fortran call
name=%s,func=%p,data=%p,%p\n",fp->defs[i].name,
fp->defs[i].func,fp->defs[i].data,&fp->defs[i].data); */
- if (fp->defs[i].rank==-1) {/* is Fortran routine */
- if (fp->defs[i].func==NULL) {
+ if (fp->defs[i].rank == -1) { /* is Fortran routine */
+ if (fp->defs[i].func == NULL) {
PyErr_Format(PyExc_RuntimeError, "no function to call");
return NULL;
}
- else if (fp->defs[i].data==NULL)
+ else if (fp->defs[i].data == NULL)
/* dummy routine */
- return (*((fortranfunc)(fp->defs[i].func)))((PyObject *)fp,arg,kw,NULL);
+ return (*((fortranfunc)(fp->defs[i].func)))((PyObject *)fp, arg,
+ kw, NULL);
else
- return (*((fortranfunc)(fp->defs[i].func)))((PyObject *)fp,arg,kw,
- (void *)fp->defs[i].data);
+ return (*((fortranfunc)(fp->defs[i].func)))(
+ (PyObject *)fp, arg, kw, (void *)fp->defs[i].data);
}
PyErr_Format(PyExc_TypeError, "this fortran object is not callable");
return NULL;
@@ -488,16 +531,14 @@ fortran_repr(PyFortranObject *fp)
return repr;
}
-
PyTypeObject PyFortran_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name ="fortran",
- .tp_basicsize = sizeof(PyFortranObject),
- .tp_dealloc = (destructor)fortran_dealloc,
- .tp_getattr = (getattrfunc)fortran_getattr,
- .tp_setattr = (setattrfunc)fortran_setattr,
- .tp_repr = (reprfunc)fortran_repr,
- .tp_call = (ternaryfunc)fortran_call,
+ PyVarObject_HEAD_INIT(NULL, 0).tp_name = "fortran",
+ .tp_basicsize = sizeof(PyFortranObject),
+ .tp_dealloc = (destructor)fortran_dealloc,
+ .tp_getattr = (getattrfunc)fortran_getattr,
+ .tp_setattr = (setattrfunc)fortran_setattr,
+ .tp_repr = (reprfunc)fortran_repr,
+ .tp_call = (ternaryfunc)fortran_call,
};
/************************* f2py_report_atexit *******************************/
@@ -518,99 +559,123 @@ static struct timeb cb_stop_time;
static struct timeb cb_start_call_time;
static struct timeb cb_stop_call_time;
-extern void f2py_start_clock(void) { ftime(&start_time); }
-extern
-void f2py_start_call_clock(void) {
+extern void
+f2py_start_clock(void)
+{
+ ftime(&start_time);
+}
+extern void
+f2py_start_call_clock(void)
+{
f2py_stop_clock();
ftime(&start_call_time);
}
-extern
-void f2py_stop_clock(void) {
+extern void
+f2py_stop_clock(void)
+{
ftime(&stop_time);
- passed_time += 1000*(stop_time.time - start_time.time);
+ passed_time += 1000 * (stop_time.time - start_time.time);
passed_time += stop_time.millitm - start_time.millitm;
}
-extern
-void f2py_stop_call_clock(void) {
+extern void
+f2py_stop_call_clock(void)
+{
ftime(&stop_call_time);
- passed_call_time += 1000*(stop_call_time.time - start_call_time.time);
+ passed_call_time += 1000 * (stop_call_time.time - start_call_time.time);
passed_call_time += stop_call_time.millitm - start_call_time.millitm;
passed_counter += 1;
f2py_start_clock();
}
-extern void f2py_cb_start_clock(void) { ftime(&cb_start_time); }
-extern
-void f2py_cb_start_call_clock(void) {
+extern void
+f2py_cb_start_clock(void)
+{
+ ftime(&cb_start_time);
+}
+extern void
+f2py_cb_start_call_clock(void)
+{
f2py_cb_stop_clock();
ftime(&cb_start_call_time);
}
-extern
-void f2py_cb_stop_clock(void) {
+extern void
+f2py_cb_stop_clock(void)
+{
ftime(&cb_stop_time);
- cb_passed_time += 1000*(cb_stop_time.time - cb_start_time.time);
+ cb_passed_time += 1000 * (cb_stop_time.time - cb_start_time.time);
cb_passed_time += cb_stop_time.millitm - cb_start_time.millitm;
}
-extern
-void f2py_cb_stop_call_clock(void) {
+extern void
+f2py_cb_stop_call_clock(void)
+{
ftime(&cb_stop_call_time);
- cb_passed_call_time += 1000*(cb_stop_call_time.time - cb_start_call_time.time);
- cb_passed_call_time += cb_stop_call_time.millitm - cb_start_call_time.millitm;
+ cb_passed_call_time +=
+ 1000 * (cb_stop_call_time.time - cb_start_call_time.time);
+ cb_passed_call_time +=
+ cb_stop_call_time.millitm - cb_start_call_time.millitm;
cb_passed_counter += 1;
f2py_cb_start_clock();
}
static int f2py_report_on_exit_been_here = 0;
-extern
-void f2py_report_on_exit(int exit_flag,void *name) {
+extern void
+f2py_report_on_exit(int exit_flag, void *name)
+{
if (f2py_report_on_exit_been_here) {
- fprintf(stderr," %s\n",(char*)name);
+ fprintf(stderr, " %s\n", (char *)name);
return;
}
f2py_report_on_exit_been_here = 1;
- fprintf(stderr," /-----------------------\\\n");
- fprintf(stderr," < F2PY performance report >\n");
- fprintf(stderr," \\-----------------------/\n");
- fprintf(stderr,"Overall time spent in ...\n");
- fprintf(stderr,"(a) wrapped (Fortran/C) functions : %8d msec\n",
+ fprintf(stderr, " /-----------------------\\\n");
+ fprintf(stderr, " < F2PY performance report >\n");
+ fprintf(stderr, " \\-----------------------/\n");
+ fprintf(stderr, "Overall time spent in ...\n");
+ fprintf(stderr, "(a) wrapped (Fortran/C) functions : %8d msec\n",
passed_call_time);
- fprintf(stderr,"(b) f2py interface, %6d calls : %8d msec\n",
- passed_counter,passed_time);
- fprintf(stderr,"(c) call-back (Python) functions : %8d msec\n",
+ fprintf(stderr, "(b) f2py interface, %6d calls : %8d msec\n",
+ passed_counter, passed_time);
+ fprintf(stderr, "(c) call-back (Python) functions : %8d msec\n",
cb_passed_call_time);
- fprintf(stderr,"(d) f2py call-back interface, %6d calls : %8d msec\n",
- cb_passed_counter,cb_passed_time);
-
- fprintf(stderr,"(e) wrapped (Fortran/C) functions (actual) : %8d msec\n\n",
- passed_call_time-cb_passed_call_time-cb_passed_time);
- fprintf(stderr,"Use -DF2PY_REPORT_ATEXIT_DISABLE to disable this message.\n");
- fprintf(stderr,"Exit status: %d\n",exit_flag);
- fprintf(stderr,"Modules : %s\n",(char*)name);
+ fprintf(stderr, "(d) f2py call-back interface, %6d calls : %8d msec\n",
+ cb_passed_counter, cb_passed_time);
+
+ fprintf(stderr,
+ "(e) wrapped (Fortran/C) functions (actual) : %8d msec\n\n",
+ passed_call_time - cb_passed_call_time - cb_passed_time);
+ fprintf(stderr,
+ "Use -DF2PY_REPORT_ATEXIT_DISABLE to disable this message.\n");
+ fprintf(stderr, "Exit status: %d\n", exit_flag);
+ fprintf(stderr, "Modules : %s\n", (char *)name);
}
#endif
/********************** report on array copy ****************************/
#ifdef F2PY_REPORT_ON_ARRAY_COPY
-static void f2py_report_on_array_copy(PyArrayObject* arr) {
+static void
+f2py_report_on_array_copy(PyArrayObject *arr)
+{
const npy_intp arr_size = PyArray_Size((PyObject *)arr);
- if (arr_size>F2PY_REPORT_ON_ARRAY_COPY) {
- fprintf(stderr,"copied an array: size=%ld, elsize=%"NPY_INTP_FMT"\n",
+ if (arr_size > F2PY_REPORT_ON_ARRAY_COPY) {
+ fprintf(stderr,
+ "copied an array: size=%ld, elsize=%" NPY_INTP_FMT "\n",
arr_size, (npy_intp)PyArray_ITEMSIZE(arr));
}
}
-static void f2py_report_on_array_copy_fromany(void) {
- fprintf(stderr,"created an array from object\n");
+static void
+f2py_report_on_array_copy_fromany(void)
+{
+ fprintf(stderr, "created an array from object\n");
}
-#define F2PY_REPORT_ON_ARRAY_COPY_FROMARR f2py_report_on_array_copy((PyArrayObject *)arr)
+#define F2PY_REPORT_ON_ARRAY_COPY_FROMARR \
+ f2py_report_on_array_copy((PyArrayObject *)arr)
#define F2PY_REPORT_ON_ARRAY_COPY_FROMANY f2py_report_on_array_copy_fromany()
#else
#define F2PY_REPORT_ON_ARRAY_COPY_FROMARR
#define F2PY_REPORT_ON_ARRAY_COPY_FROMANY
#endif
-
/************************* array_from_obj *******************************/
/*
@@ -632,72 +697,82 @@ static void f2py_report_on_array_copy_fromany(void) {
* $Id: fortranobject.c,v 1.52 2005/07/11 07:44:20 pearu Exp $
*/
-static int check_and_fix_dimensions(const PyArrayObject* arr,
- const int rank,
- npy_intp *dims);
+static int
+check_and_fix_dimensions(const PyArrayObject *arr, const int rank,
+ npy_intp *dims);
static int
-count_negative_dimensions(const int rank,
- const npy_intp *dims) {
- int i=0,r=0;
- while (i<rank) {
- if (dims[i] < 0) ++r;
+count_negative_dimensions(const int rank, const npy_intp *dims)
+{
+ int i = 0, r = 0;
+ while (i < rank) {
+ if (dims[i] < 0)
+ ++r;
++i;
}
return r;
}
#ifdef DEBUG_COPY_ND_ARRAY
-void dump_dims(int rank, npy_intp const* dims) {
+void
+dump_dims(int rank, npy_intp const *dims)
+{
int i;
printf("[");
- for(i=0;i<rank;++i) {
+ for (i = 0; i < rank; ++i) {
printf("%3" NPY_INTP_FMT, dims[i]);
}
printf("]\n");
}
-void dump_attrs(const PyArrayObject* obj) {
- const PyArrayObject_fields *arr = (const PyArrayObject_fields*) obj;
+void
+dump_attrs(const PyArrayObject *obj)
+{
+ const PyArrayObject_fields *arr = (const PyArrayObject_fields *)obj;
int rank = PyArray_NDIM(arr);
npy_intp size = PyArray_Size((PyObject *)arr);
- printf("\trank = %d, flags = %d, size = %" NPY_INTP_FMT "\n",
- rank,arr->flags,size);
+ printf("\trank = %d, flags = %d, size = %" NPY_INTP_FMT "\n", rank,
+ arr->flags, size);
printf("\tstrides = ");
- dump_dims(rank,arr->strides);
+ dump_dims(rank, arr->strides);
printf("\tdimensions = ");
- dump_dims(rank,arr->dimensions);
+ dump_dims(rank, arr->dimensions);
}
#endif
-#define SWAPTYPE(a,b,t) {t c; c = (a); (a) = (b); (b) = c; }
-
-static int swap_arrays(PyArrayObject* obj1, PyArrayObject* obj2) {
- PyArrayObject_fields *arr1 = (PyArrayObject_fields*) obj1,
- *arr2 = (PyArrayObject_fields*) obj2;
- SWAPTYPE(arr1->data,arr2->data,char*);
- SWAPTYPE(arr1->nd,arr2->nd,int);
- SWAPTYPE(arr1->dimensions,arr2->dimensions,npy_intp*);
- SWAPTYPE(arr1->strides,arr2->strides,npy_intp*);
- SWAPTYPE(arr1->base,arr2->base,PyObject*);
- SWAPTYPE(arr1->descr,arr2->descr,PyArray_Descr*);
- SWAPTYPE(arr1->flags,arr2->flags,int);
+#define SWAPTYPE(a, b, t) \
+ { \
+ t c; \
+ c = (a); \
+ (a) = (b); \
+ (b) = c; \
+ }
+
+static int
+swap_arrays(PyArrayObject *obj1, PyArrayObject *obj2)
+{
+ PyArrayObject_fields *arr1 = (PyArrayObject_fields *)obj1,
+ *arr2 = (PyArrayObject_fields *)obj2;
+ SWAPTYPE(arr1->data, arr2->data, char *);
+ SWAPTYPE(arr1->nd, arr2->nd, int);
+ SWAPTYPE(arr1->dimensions, arr2->dimensions, npy_intp *);
+ SWAPTYPE(arr1->strides, arr2->strides, npy_intp *);
+ SWAPTYPE(arr1->base, arr2->base, PyObject *);
+ SWAPTYPE(arr1->descr, arr2->descr, PyArray_Descr *);
+ SWAPTYPE(arr1->flags, arr2->flags, int);
/* SWAPTYPE(arr1->weakreflist,arr2->weakreflist,PyObject*); */
return 0;
}
-#define ARRAY_ISCOMPATIBLE(arr,type_num) \
- ( (PyArray_ISINTEGER(arr) && PyTypeNum_ISINTEGER(type_num)) \
- ||(PyArray_ISFLOAT(arr) && PyTypeNum_ISFLOAT(type_num)) \
- ||(PyArray_ISCOMPLEX(arr) && PyTypeNum_ISCOMPLEX(type_num)) \
- ||(PyArray_ISBOOL(arr) && PyTypeNum_ISBOOL(type_num)) \
- )
-
-extern
-PyArrayObject* array_from_pyobj(const int type_num,
- npy_intp *dims,
- const int rank,
- const int intent,
- PyObject *obj) {
+#define ARRAY_ISCOMPATIBLE(arr, type_num) \
+ ((PyArray_ISINTEGER(arr) && PyTypeNum_ISINTEGER(type_num)) || \
+ (PyArray_ISFLOAT(arr) && PyTypeNum_ISFLOAT(type_num)) || \
+ (PyArray_ISCOMPLEX(arr) && PyTypeNum_ISCOMPLEX(type_num)) || \
+ (PyArray_ISBOOL(arr) && PyTypeNum_ISBOOL(type_num)))
+
+extern PyArrayObject *
+array_from_pyobj(const int type_num, npy_intp *dims, const int rank,
+ const int intent, PyObject *obj)
+{
/*
* Note about reference counting
* -----------------------------
@@ -716,27 +791,26 @@ PyArrayObject* array_from_pyobj(const int type_num,
char typechar;
int elsize;
- if ((intent & F2PY_INTENT_HIDE)
- || ((intent & F2PY_INTENT_CACHE) && (obj==Py_None))
- || ((intent & F2PY_OPTIONAL) && (obj==Py_None))
- ) {
+ if ((intent & F2PY_INTENT_HIDE) ||
+ ((intent & F2PY_INTENT_CACHE) && (obj == Py_None)) ||
+ ((intent & F2PY_OPTIONAL) && (obj == Py_None))) {
/* intent(cache), optional, intent(hide) */
- if (count_negative_dimensions(rank,dims) > 0) {
+ if (count_negative_dimensions(rank, dims) > 0) {
int i;
- strcpy(mess, "failed to create intent(cache|hide)|optional array"
+ strcpy(mess,
+ "failed to create intent(cache|hide)|optional array"
"-- must have defined dimensions but got (");
- for(i=0;i<rank;++i)
- sprintf(mess+strlen(mess),"%" NPY_INTP_FMT ",",dims[i]);
+ for (i = 0; i < rank; ++i)
+ sprintf(mess + strlen(mess), "%" NPY_INTP_FMT ",", dims[i]);
strcat(mess, ")");
- PyErr_SetString(PyExc_ValueError,mess);
+ PyErr_SetString(PyExc_ValueError, mess);
return NULL;
}
- arr = (PyArrayObject *)
- PyArray_New(&PyArray_Type, rank, dims, type_num,
- NULL,NULL,1,
- !(intent&F2PY_INTENT_C),
- NULL);
- if (arr==NULL) return NULL;
+ arr = (PyArrayObject *)PyArray_New(&PyArray_Type, rank, dims, type_num,
+ NULL, NULL, 1,
+ !(intent & F2PY_INTENT_C), NULL);
+ if (arr == NULL)
+ return NULL;
if (!(intent & F2PY_INTENT_CACHE))
PyArray_FILLWBYTE(arr, 0);
return arr;
@@ -760,8 +834,7 @@ PyArrayObject* array_from_pyobj(const int type_num,
if (intent & F2PY_INTENT_CACHE) {
/* intent(cache) */
- if (PyArray_ISONESEGMENT(arr)
- && PyArray_ITEMSIZE(arr)>=elsize) {
+ if (PyArray_ISONESEGMENT(arr) && PyArray_ITEMSIZE(arr) >= elsize) {
if (check_and_fix_dimensions(arr, rank, dims)) {
return NULL;
}
@@ -772,17 +845,17 @@ PyArrayObject* array_from_pyobj(const int type_num,
strcpy(mess, "failed to initialize intent(cache) array");
if (!PyArray_ISONESEGMENT(arr))
strcat(mess, " -- input must be in one segment");
- if (PyArray_ITEMSIZE(arr)<elsize)
- sprintf(mess+strlen(mess),
- " -- expected at least elsize=%d but got %" NPY_INTP_FMT,
- elsize,
- (npy_intp)PyArray_ITEMSIZE(arr)
- );
- PyErr_SetString(PyExc_ValueError,mess);
+ if (PyArray_ITEMSIZE(arr) < elsize)
+ sprintf(mess + strlen(mess),
+ " -- expected at least elsize=%d but got "
+ "%" NPY_INTP_FMT,
+ elsize, (npy_intp)PyArray_ITEMSIZE(arr));
+ PyErr_SetString(PyExc_ValueError, mess);
return NULL;
}
- /* here we have always intent(in) or intent(inout) or intent(inplace) */
+ /* here we have always intent(in) or intent(inout) or intent(inplace)
+ */
if (check_and_fix_dimensions(arr, rank, dims)) {
return NULL;
@@ -794,12 +867,12 @@ PyArrayObject* array_from_pyobj(const int type_num,
for (i=1;i<=16;i++)
printf("i=%d isaligned=%d\n", i, ARRAY_ISALIGNED(arr, i));
*/
- if ((! (intent & F2PY_INTENT_COPY))
- && PyArray_ITEMSIZE(arr)==elsize
- && ARRAY_ISCOMPATIBLE(arr,type_num)
- && F2PY_CHECK_ALIGNMENT(arr, intent)
- ) {
- if ((intent & F2PY_INTENT_C)?PyArray_ISCARRAY_RO(arr):PyArray_ISFARRAY_RO(arr)) {
+ if ((!(intent & F2PY_INTENT_COPY)) &&
+ PyArray_ITEMSIZE(arr) == elsize &&
+ ARRAY_ISCOMPATIBLE(arr, type_num) &&
+ F2PY_CHECK_ALIGNMENT(arr, intent)) {
+ if ((intent & F2PY_INTENT_C) ? PyArray_ISCARRAY_RO(arr)
+ : PyArray_ISFARRAY_RO(arr)) {
if ((intent & F2PY_INTENT_OUT)) {
Py_INCREF(arr);
}
@@ -809,36 +882,35 @@ PyArrayObject* array_from_pyobj(const int type_num,
}
if (intent & F2PY_INTENT_INOUT) {
strcpy(mess, "failed to initialize intent(inout) array");
- /* Must use PyArray_IS*ARRAY because intent(inout) requires writable input */
+ /* Must use PyArray_IS*ARRAY because intent(inout) requires
+ * writable input */
if ((intent & F2PY_INTENT_C) && !PyArray_ISCARRAY(arr))
strcat(mess, " -- input not contiguous");
if (!(intent & F2PY_INTENT_C) && !PyArray_ISFARRAY(arr))
strcat(mess, " -- input not fortran contiguous");
- if (PyArray_ITEMSIZE(arr)!=elsize)
- sprintf(mess+strlen(mess),
+ if (PyArray_ITEMSIZE(arr) != elsize)
+ sprintf(mess + strlen(mess),
" -- expected elsize=%d but got %" NPY_INTP_FMT,
- elsize,
- (npy_intp)PyArray_ITEMSIZE(arr)
- );
- if (!(ARRAY_ISCOMPATIBLE(arr,type_num)))
- sprintf(mess+strlen(mess)," -- input '%c' not compatible to '%c'",
- PyArray_DESCR(arr)->type,typechar);
+ elsize, (npy_intp)PyArray_ITEMSIZE(arr));
+ if (!(ARRAY_ISCOMPATIBLE(arr, type_num)))
+ sprintf(mess + strlen(mess),
+ " -- input '%c' not compatible to '%c'",
+ PyArray_DESCR(arr)->type, typechar);
if (!(F2PY_CHECK_ALIGNMENT(arr, intent)))
- sprintf(mess+strlen(mess)," -- input not %d-aligned", F2PY_GET_ALIGNMENT(intent));
- PyErr_SetString(PyExc_ValueError,mess);
+ sprintf(mess + strlen(mess), " -- input not %d-aligned",
+ F2PY_GET_ALIGNMENT(intent));
+ PyErr_SetString(PyExc_ValueError, mess);
return NULL;
}
/* here we have always intent(in) or intent(inplace) */
{
- PyArrayObject * retarr;
- retarr = (PyArrayObject *) \
- PyArray_New(&PyArray_Type, PyArray_NDIM(arr), PyArray_DIMS(arr), type_num,
- NULL,NULL,1,
- !(intent&F2PY_INTENT_C),
- NULL);
- if (retarr==NULL)
+ PyArrayObject *retarr;
+ retarr = (PyArrayObject *)PyArray_New(
+ &PyArray_Type, PyArray_NDIM(arr), PyArray_DIMS(arr),
+ type_num, NULL, NULL, 1, !(intent & F2PY_INTENT_C), NULL);
+ if (retarr == NULL)
return NULL;
F2PY_REPORT_ON_ARRAY_COPY_FROMARR;
if (PyArray_CopyInto(retarr, arr)) {
@@ -846,21 +918,21 @@ PyArrayObject* array_from_pyobj(const int type_num,
return NULL;
}
if (intent & F2PY_INTENT_INPLACE) {
- if (swap_arrays(arr,retarr))
+ if (swap_arrays(arr, retarr))
return NULL; /* XXX: set exception */
Py_XDECREF(retarr);
if (intent & F2PY_INTENT_OUT)
Py_INCREF(arr);
- } else {
+ }
+ else {
arr = retarr;
}
}
return arr;
}
- if ((intent & F2PY_INTENT_INOUT) ||
- (intent & F2PY_INTENT_INPLACE) ||
- (intent & F2PY_INTENT_CACHE)) {
+ if ((intent & F2PY_INTENT_INOUT) || (intent & F2PY_INTENT_INPLACE) ||
+ (intent & F2PY_INTENT_CACHE)) {
PyErr_Format(PyExc_TypeError,
"failed to initialize intent(inout|inplace|cache) "
"array, input '%s' object is not an array",
@@ -869,7 +941,7 @@ PyArrayObject* array_from_pyobj(const int type_num,
}
{
- PyArray_Descr * descr = PyArray_DescrFromType(type_num);
+ PyArray_Descr *descr = PyArray_DescrFromType(type_num);
/* compatibility with NPY_CHAR */
if (type_num == NPY_STRING) {
PyArray_DESCR_REPLACE(descr);
@@ -880,26 +952,28 @@ PyArrayObject* array_from_pyobj(const int type_num,
descr->type = NPY_CHARLTR;
}
F2PY_REPORT_ON_ARRAY_COPY_FROMANY;
- arr = (PyArrayObject *) \
- PyArray_FromAny(obj, descr, 0,0,
- ((intent & F2PY_INTENT_C)?NPY_ARRAY_CARRAY:NPY_ARRAY_FARRAY) \
- | NPY_ARRAY_FORCECAST, NULL);
- if (arr==NULL)
+ arr = (PyArrayObject *)PyArray_FromAny(
+ obj, descr, 0, 0,
+ ((intent & F2PY_INTENT_C) ? NPY_ARRAY_CARRAY
+ : NPY_ARRAY_FARRAY) |
+ NPY_ARRAY_FORCECAST,
+ NULL);
+ if (arr == NULL)
return NULL;
if (check_and_fix_dimensions(arr, rank, dims)) {
return NULL;
}
return arr;
}
-
}
/*****************************************/
/* Helper functions for array_from_pyobj */
/*****************************************/
-static
-int check_and_fix_dimensions(const PyArrayObject* arr, const int rank, npy_intp *dims)
+static int
+check_and_fix_dimensions(const PyArrayObject *arr, const int rank,
+ npy_intp *dims)
{
/*
* This function fills in blanks (that are -1's) in dims list using
@@ -908,13 +982,15 @@ int check_and_fix_dimensions(const PyArrayObject* arr, const int rank, npy_intp
*
* Returns 0 if the function is successful.
*
- * If an error condition is detected, an exception is set and 1 is returned.
+ * If an error condition is detected, an exception is set and 1 is
+ * returned.
*/
- const npy_intp arr_size = (PyArray_NDIM(arr))?PyArray_Size((PyObject *)arr):1;
+ const npy_intp arr_size =
+ (PyArray_NDIM(arr)) ? PyArray_Size((PyObject *)arr) : 1;
#ifdef DEBUG_COPY_ND_ARRAY
dump_attrs(arr);
printf("check_and_fix_dimensions:init: dims=");
- dump_dims(rank,dims);
+ dump_dims(rank, dims);
#endif
if (rank > PyArray_NDIM(arr)) { /* [1,2] -> [[1],[2]]; 1 -> [[1]] */
npy_intp new_size = 1;
@@ -922,35 +998,39 @@ int check_and_fix_dimensions(const PyArrayObject* arr, const int rank, npy_intp
int i;
npy_intp d;
/* Fill dims where -1 or 0; check dimensions; calc new_size; */
- for(i=0;i<PyArray_NDIM(arr);++i) {
- d = PyArray_DIM(arr,i);
+ for (i = 0; i < PyArray_NDIM(arr); ++i) {
+ d = PyArray_DIM(arr, i);
if (dims[i] >= 0) {
- if (d>1 && dims[i]!=d) {
- PyErr_Format(PyExc_ValueError,
- "%d-th dimension must be fixed to %"
- NPY_INTP_FMT " but got %" NPY_INTP_FMT "\n",
- i, dims[i], d);
+ if (d > 1 && dims[i] != d) {
+ PyErr_Format(
+ PyExc_ValueError,
+ "%d-th dimension must be fixed to %" NPY_INTP_FMT
+ " but got %" NPY_INTP_FMT "\n",
+ i, dims[i], d);
return 1;
}
- if (!dims[i]) dims[i] = 1;
- } else {
+ if (!dims[i])
+ dims[i] = 1;
+ }
+ else {
dims[i] = d ? d : 1;
}
new_size *= dims[i];
}
- for(i=PyArray_NDIM(arr);i<rank;++i)
- if (dims[i]>1) {
+ for (i = PyArray_NDIM(arr); i < rank; ++i)
+ if (dims[i] > 1) {
PyErr_Format(PyExc_ValueError,
"%d-th dimension must be %" NPY_INTP_FMT
" but got 0 (not defined).\n",
i, dims[i]);
return 1;
- } else if (free_axe<0)
+ }
+ else if (free_axe < 0)
free_axe = i;
else
dims[i] = 1;
- if (free_axe>=0) {
- dims[free_axe] = arr_size/new_size;
+ if (free_axe >= 0) {
+ dims[free_axe] = arr_size / new_size;
new_size *= dims[free_axe];
}
if (new_size != arr_size) {
@@ -961,22 +1041,27 @@ int check_and_fix_dimensions(const PyArrayObject* arr, const int rank, npy_intp
new_size, arr_size);
return 1;
}
- } else if (rank==PyArray_NDIM(arr)) {
+ }
+ else if (rank == PyArray_NDIM(arr)) {
npy_intp new_size = 1;
int i;
npy_intp d;
- for (i=0; i<rank; ++i) {
- d = PyArray_DIM(arr,i);
- if (dims[i]>=0) {
- if (d > 1 && d!=dims[i]) {
- PyErr_Format(PyExc_ValueError,
- "%d-th dimension must be fixed to %"
- NPY_INTP_FMT " but got %" NPY_INTP_FMT "\n",
- i, dims[i], d);
+ for (i = 0; i < rank; ++i) {
+ d = PyArray_DIM(arr, i);
+ if (dims[i] >= 0) {
+ if (d > 1 && d != dims[i]) {
+ PyErr_Format(
+ PyExc_ValueError,
+ "%d-th dimension must be fixed to %" NPY_INTP_FMT
+ " but got %" NPY_INTP_FMT "\n",
+ i, dims[i], d);
return 1;
}
- if (!dims[i]) dims[i] = 1;
- } else dims[i] = d;
+ if (!dims[i])
+ dims[i] = 1;
+ }
+ else
+ dims[i] = d;
new_size *= dims[i];
}
if (new_size != arr_size) {
@@ -986,15 +1071,17 @@ int check_and_fix_dimensions(const PyArrayObject* arr, const int rank, npy_intp
new_size, arr_size);
return 1;
}
- } else { /* [[1,2]] -> [[1],[2]] */
- int i,j;
+ }
+ else { /* [[1,2]] -> [[1],[2]] */
+ int i, j;
npy_intp d;
int effrank;
npy_intp size;
- for (i=0,effrank=0;i<PyArray_NDIM(arr);++i)
- if (PyArray_DIM(arr,i)>1) ++effrank;
- if (dims[rank-1]>=0)
- if (effrank>rank) {
+ for (i = 0, effrank = 0; i < PyArray_NDIM(arr); ++i)
+ if (PyArray_DIM(arr, i) > 1)
+ ++effrank;
+ if (dims[rank - 1] >= 0)
+ if (effrank > rank) {
PyErr_Format(PyExc_ValueError,
"too many axes: %d (effrank=%d), "
"expected rank=%d\n",
@@ -1002,31 +1089,38 @@ int check_and_fix_dimensions(const PyArrayObject* arr, const int rank, npy_intp
return 1;
}
- for (i=0,j=0;i<rank;++i) {
- while (j<PyArray_NDIM(arr) && PyArray_DIM(arr,j)<2) ++j;
- if (j>=PyArray_NDIM(arr)) d = 1;
- else d = PyArray_DIM(arr,j++);
- if (dims[i]>=0) {
- if (d>1 && d!=dims[i]) {
- PyErr_Format(PyExc_ValueError,
- "%d-th dimension must be fixed to %"
- NPY_INTP_FMT " but got %" NPY_INTP_FMT
- " (real index=%d)\n",
- i, dims[i], d, j-1);
+ for (i = 0, j = 0; i < rank; ++i) {
+ while (j < PyArray_NDIM(arr) && PyArray_DIM(arr, j) < 2) ++j;
+ if (j >= PyArray_NDIM(arr))
+ d = 1;
+ else
+ d = PyArray_DIM(arr, j++);
+ if (dims[i] >= 0) {
+ if (d > 1 && d != dims[i]) {
+ PyErr_Format(
+ PyExc_ValueError,
+ "%d-th dimension must be fixed to %" NPY_INTP_FMT
+ " but got %" NPY_INTP_FMT " (real index=%d)\n",
+ i, dims[i], d, j - 1);
return 1;
}
- if (!dims[i]) dims[i] = 1;
- } else
+ if (!dims[i])
+ dims[i] = 1;
+ }
+ else
dims[i] = d;
}
- for (i=rank;i<PyArray_NDIM(arr);++i) { /* [[1,2],[3,4]] -> [1,2,3,4] */
- while (j<PyArray_NDIM(arr) && PyArray_DIM(arr,j)<2) ++j;
- if (j>=PyArray_NDIM(arr)) d = 1;
- else d = PyArray_DIM(arr,j++);
- dims[rank-1] *= d;
+ for (i = rank; i < PyArray_NDIM(arr);
+ ++i) { /* [[1,2],[3,4]] -> [1,2,3,4] */
+ while (j < PyArray_NDIM(arr) && PyArray_DIM(arr, j) < 2) ++j;
+ if (j >= PyArray_NDIM(arr))
+ d = 1;
+ else
+ d = PyArray_DIM(arr, j++);
+ dims[rank - 1] *= d;
}
- for (i=0,size=1;i<rank;++i) size *= dims[i];
+ for (i = 0, size = 1; i < rank; ++i) size *= dims[i];
if (size != arr_size) {
char msg[200];
int len;
@@ -1037,15 +1131,15 @@ int check_and_fix_dimensions(const PyArrayObject* arr, const int rank, npy_intp
size, arr_size, rank, effrank, PyArray_NDIM(arr));
for (i = 0; i < rank; ++i) {
len = strlen(msg);
- snprintf(msg + len, sizeof(msg) - len,
- " %" NPY_INTP_FMT, dims[i]);
+ snprintf(msg + len, sizeof(msg) - len, " %" NPY_INTP_FMT,
+ dims[i]);
}
len = strlen(msg);
snprintf(msg + len, sizeof(msg) - len, " ], arr.dims=[");
for (i = 0; i < PyArray_NDIM(arr); ++i) {
len = strlen(msg);
- snprintf(msg + len, sizeof(msg) - len,
- " %" NPY_INTP_FMT, PyArray_DIM(arr, i));
+ snprintf(msg + len, sizeof(msg) - len, " %" NPY_INTP_FMT,
+ PyArray_DIM(arr, i));
}
len = strlen(msg);
snprintf(msg + len, sizeof(msg) - len, " ]\n");
@@ -1055,7 +1149,7 @@ int check_and_fix_dimensions(const PyArrayObject* arr, const int rank, npy_intp
}
#ifdef DEBUG_COPY_ND_ARRAY
printf("check_and_fix_dimensions:end: dims=");
- dump_dims(rank,dims);
+ dump_dims(rank, dims);
#endif
return 0;
}
@@ -1064,8 +1158,8 @@ int check_and_fix_dimensions(const PyArrayObject* arr, const int rank, npy_intp
/************************* copy_ND_array *******************************/
-extern
-int copy_ND_array(const PyArrayObject *arr, PyArrayObject *out)
+extern int
+copy_ND_array(const PyArrayObject *arr, PyArrayObject *out)
{
F2PY_REPORT_ON_ARRAY_COPY_FROMARR;
return PyArray_CopyInto(out, (PyArrayObject *)arr);
diff --git a/numpy/f2py/src/fortranobject.h b/numpy/f2py/src/fortranobject.h
index 278c236a7..a1e9fdbdf 100644
--- a/numpy/f2py/src/fortranobject.h
+++ b/numpy/f2py/src/fortranobject.h
@@ -13,18 +13,19 @@ extern "C" {
#include "numpy/arrayobject.h"
#include "numpy/npy_3kcompat.h"
-
#ifdef F2PY_REPORT_ATEXIT
#include <sys/timeb.h>
- extern void f2py_start_clock(void);
- extern void f2py_stop_clock(void);
- extern void f2py_start_call_clock(void);
- extern void f2py_stop_call_clock(void);
- extern void f2py_cb_start_clock(void);
- extern void f2py_cb_stop_clock(void);
- extern void f2py_cb_start_call_clock(void);
- extern void f2py_cb_stop_call_clock(void);
- extern void f2py_report_on_exit(int,void*);
+// clang-format off
+extern void f2py_start_clock(void);
+extern void f2py_stop_clock(void);
+extern void f2py_start_call_clock(void);
+extern void f2py_stop_call_clock(void);
+extern void f2py_cb_start_clock(void);
+extern void f2py_cb_stop_clock(void);
+extern void f2py_cb_start_call_clock(void);
+extern void f2py_cb_stop_call_clock(void);
+extern void f2py_report_on_exit(int, void *);
+// clang-format on
#endif
#ifdef DMALLOC
@@ -44,50 +45,60 @@ Author: Pearu Peterson <pearu@cens.ioc.ee>
#define F2PY_MAX_DIMS 40
-typedef void (*f2py_set_data_func)(char*,npy_intp*);
+typedef void (*f2py_set_data_func)(char *, npy_intp *);
typedef void (*f2py_void_func)(void);
-typedef void (*f2py_init_func)(int*,npy_intp*,f2py_set_data_func,int*);
+typedef void (*f2py_init_func)(int *, npy_intp *, f2py_set_data_func, int *);
- /*typedef void* (*f2py_c_func)(void*,...);*/
+/*typedef void* (*f2py_c_func)(void*,...);*/
typedef void *(*f2pycfunc)(void);
typedef struct {
- char *name; /* attribute (array||routine) name */
- int rank; /* array rank, 0 for scalar, max is F2PY_MAX_DIMS,
- || rank=-1 for Fortran routine */
- struct {npy_intp d[F2PY_MAX_DIMS];} dims; /* dimensions of the array, || not used */
- int type; /* PyArray_<type> || not used */
- char *data; /* pointer to array || Fortran routine */
- f2py_init_func func; /* initialization function for
- allocatable arrays:
- func(&rank,dims,set_ptr_func,name,len(name))
- || C/API wrapper for Fortran routine */
- char *doc; /* documentation string; only recommended
- for routines. */
+ char *name; /* attribute (array||routine) name */
+ int rank; /* array rank, 0 for scalar, max is F2PY_MAX_DIMS,
+ || rank=-1 for Fortran routine */
+ struct {
+ npy_intp d[F2PY_MAX_DIMS];
+ } dims; /* dimensions of the array, || not used */
+ int type; /* PyArray_<type> || not used */
+ char *data; /* pointer to array || Fortran routine */
+ f2py_init_func func; /* initialization function for
+ allocatable arrays:
+ func(&rank,dims,set_ptr_func,name,len(name))
+ || C/API wrapper for Fortran routine */
+ char *doc; /* documentation string; only recommended
+ for routines. */
} FortranDataDef;
typedef struct {
- PyObject_HEAD
- int len; /* Number of attributes */
- FortranDataDef *defs; /* An array of FortranDataDef's */
- PyObject *dict; /* Fortran object attribute dictionary */
+ PyObject_HEAD
+ int len; /* Number of attributes */
+ FortranDataDef *defs; /* An array of FortranDataDef's */
+ PyObject *dict; /* Fortran object attribute dictionary */
} PyFortranObject;
#define PyFortran_Check(op) (Py_TYPE(op) == &PyFortran_Type)
-#define PyFortran_Check1(op) (0==strcmp(Py_TYPE(op)->tp_name,"fortran"))
-
- extern PyTypeObject PyFortran_Type;
- extern int F2PyDict_SetItemString(PyObject* dict, char *name, PyObject *obj);
- extern PyObject * PyFortranObject_New(FortranDataDef* defs, f2py_void_func init);
- extern PyObject * PyFortranObject_NewAsAttr(FortranDataDef* defs);
-
-PyObject * F2PyCapsule_FromVoidPtr(void *ptr, void (*dtor)(PyObject *));
-void * F2PyCapsule_AsVoidPtr(PyObject *obj);
-int F2PyCapsule_Check(PyObject *ptr);
-
-extern void *F2PySwapThreadLocalCallbackPtr(char *key, void *ptr);
-extern void *F2PyGetThreadLocalCallbackPtr(char *key);
+#define PyFortran_Check1(op) (0 == strcmp(Py_TYPE(op)->tp_name, "fortran"))
+
+extern PyTypeObject PyFortran_Type;
+extern int
+F2PyDict_SetItemString(PyObject *dict, char *name, PyObject *obj);
+extern PyObject *
+PyFortranObject_New(FortranDataDef *defs, f2py_void_func init);
+extern PyObject *
+PyFortranObject_NewAsAttr(FortranDataDef *defs);
+
+PyObject *
+F2PyCapsule_FromVoidPtr(void *ptr, void (*dtor)(PyObject *));
+void *
+F2PyCapsule_AsVoidPtr(PyObject *obj);
+int
+F2PyCapsule_Check(PyObject *ptr);
+
+extern void *
+F2PySwapThreadLocalCallbackPtr(char *key, void *ptr);
+extern void *
+F2PyGetThreadLocalCallbackPtr(char *key);
#define ISCONTIGUOUS(m) (PyArray_FLAGS(m) & NPY_ARRAY_C_CONTIGUOUS)
#define F2PY_INTENT_IN 1
@@ -109,23 +120,23 @@ extern void *F2PyGetThreadLocalCallbackPtr(char *key);
#define F2PY_ALIGN16(intent) (intent & F2PY_INTENT_ALIGNED16)
#define F2PY_GET_ALIGNMENT(intent) \
- (F2PY_ALIGN4(intent) ? 4 : \
- (F2PY_ALIGN8(intent) ? 8 : \
- (F2PY_ALIGN16(intent) ? 16 : 1) ))
-#define F2PY_CHECK_ALIGNMENT(arr, intent) ARRAY_ISALIGNED(arr, F2PY_GET_ALIGNMENT(intent))
-
- extern PyArrayObject* array_from_pyobj(const int type_num,
- npy_intp *dims,
- const int rank,
- const int intent,
- PyObject *obj);
- extern int copy_ND_array(const PyArrayObject *in, PyArrayObject *out);
+ (F2PY_ALIGN4(intent) \
+ ? 4 \
+ : (F2PY_ALIGN8(intent) ? 8 : (F2PY_ALIGN16(intent) ? 16 : 1)))
+#define F2PY_CHECK_ALIGNMENT(arr, intent) \
+ ARRAY_ISALIGNED(arr, F2PY_GET_ALIGNMENT(intent))
+
+extern PyArrayObject *
+array_from_pyobj(const int type_num, npy_intp *dims, const int rank,
+ const int intent, PyObject *obj);
+extern int
+copy_ND_array(const PyArrayObject *in, PyArrayObject *out);
#ifdef DEBUG_COPY_ND_ARRAY
- extern void dump_attrs(const PyArrayObject* arr);
+extern void
+dump_attrs(const PyArrayObject *arr);
#endif
-
#ifdef __cplusplus
}
#endif
diff --git a/numpy/f2py/tests/test_crackfortran.py b/numpy/f2py/tests/test_crackfortran.py
index da7974d1a..b1503c1e0 100644
--- a/numpy/f2py/tests/test_crackfortran.py
+++ b/numpy/f2py/tests/test_crackfortran.py
@@ -170,7 +170,7 @@ class TestMarkinnerspaces():
class TestDimSpec(util.F2PyTest):
- """This test site tests various expressions that are used as dimension
+ """This test suite tests various expressions that are used as dimension
specifications.
There exists two usage cases where analyzing dimensions
@@ -183,7 +183,7 @@ class TestDimSpec(util.F2PyTest):
`lower` and `upper` are arbitrary expressions of input parameters.
The evaluation is performed in C, so f2py has to translate Fortran
expressions to valid C expressions (an alternative approach is
- that a developer specifies the corresponing C expressions in a
+ that a developer specifies the corresponding C expressions in a
.pyf file).
In the second case, when user provides an input array with a given
diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py
index b77ce8782..80eaf8acf 100644
--- a/numpy/lib/function_base.py
+++ b/numpy/lib/function_base.py
@@ -3252,7 +3252,7 @@ def i0(x):
Her Majesty's Stationery Office, 1962.
.. [2] M. Abramowitz and I. A. Stegun, *Handbook of Mathematical
Functions*, 10th printing, New York: Dover, 1964, pp. 379.
- http://www.math.sfu.ca/~cbm/aands/page_379.htm
+ https://personal.math.ubc.ca/~cbm/aands/page_379.htm
.. [3] https://metacpan.org/pod/distribution/Math-Cephes/lib/Math/Cephes.pod#i0:-Modified-Bessel-function-of-order-zero
Examples
diff --git a/numpy/lib/recfunctions.py b/numpy/lib/recfunctions.py
index fbfbca73d..a491f612e 100644
--- a/numpy/lib/recfunctions.py
+++ b/numpy/lib/recfunctions.py
@@ -819,7 +819,8 @@ def repack_fields(a, align=False, recurse=False):
...
>>> dt = np.dtype('u1, <i8, <f8', align=True)
>>> dt
- dtype({'names':['f0','f1','f2'], 'formats':['u1','<i8','<f8'], 'offsets':[0,8,16], 'itemsize':24}, align=True)
+ dtype({'names': ['f0', 'f1', 'f2'], 'formats': ['u1', '<i8', '<f8'], \
+'offsets': [0, 8, 16], 'itemsize': 24}, align=True)
>>> print_offsets(dt)
offsets: [0, 8, 16]
itemsize: 24
diff --git a/numpy/lib/scimath.py b/numpy/lib/scimath.py
index ed9ffd295..308f1328b 100644
--- a/numpy/lib/scimath.py
+++ b/numpy/lib/scimath.py
@@ -7,8 +7,7 @@ For example, for functions like `log` with branch cuts, the versions in this
module provide the mathematically valid answers in the complex plane::
>>> import math
- >>> from numpy.lib import scimath
- >>> scimath.log(-math.exp(1)) == (1+1j*math.pi)
+ >>> np.emath.log(-math.exp(1)) == (1+1j*math.pi)
True
Similarly, `sqrt`, other base logarithms, `power` and trig functions are
@@ -223,16 +222,16 @@ def sqrt(x):
--------
For real, non-negative inputs this works just like `numpy.sqrt`:
- >>> np.lib.scimath.sqrt(1)
+ >>> np.emath.sqrt(1)
1.0
- >>> np.lib.scimath.sqrt([1, 4])
+ >>> np.emath.sqrt([1, 4])
array([1., 2.])
But it automatically handles negative inputs:
- >>> np.lib.scimath.sqrt(-1)
+ >>> np.emath.sqrt(-1)
1j
- >>> np.lib.scimath.sqrt([-1,4])
+ >>> np.emath.sqrt([-1,4])
array([0.+1.j, 2.+0.j])
"""
@@ -367,9 +366,9 @@ def logn(n, x):
--------
>>> np.set_printoptions(precision=4)
- >>> np.lib.scimath.logn(2, [4, 8])
+ >>> np.emath.logn(2, [4, 8])
array([2., 3.])
- >>> np.lib.scimath.logn(2, [-4, -8, 8])
+ >>> np.emath.logn(2, [-4, -8, 8])
array([2.+4.5324j, 3.+4.5324j, 3.+0.j ])
"""
@@ -462,11 +461,11 @@ def power(x, p):
--------
>>> np.set_printoptions(precision=4)
- >>> np.lib.scimath.power([2, 4], 2)
+ >>> np.emath.power([2, 4], 2)
array([ 4, 16])
- >>> np.lib.scimath.power([2, 4], -2)
+ >>> np.emath.power([2, 4], -2)
array([0.25 , 0.0625])
- >>> np.lib.scimath.power([-2, 4], 2)
+ >>> np.emath.power([-2, 4], 2)
array([ 4.-0.j, 16.+0.j])
"""
diff --git a/numpy/linalg/lapack_lite/clapack_scrub.py b/numpy/linalg/lapack_lite/clapack_scrub.py
index e6f2d09f4..fffd70910 100644
--- a/numpy/linalg/lapack_lite/clapack_scrub.py
+++ b/numpy/linalg/lapack_lite/clapack_scrub.py
@@ -228,15 +228,18 @@ def removeHeader(source):
return lines.getValue()
def removeSubroutinePrototypes(source):
- expression = re.compile(
- r'/\* Subroutine \*/^\s*(?:(?:inline|static)\s+){0,2}(?!else|typedef|return)\w+\s+\*?\s*(\w+)\s*\([^0]+\)\s*;?'
- )
- lines = LineQueue()
- for line in UStringIO(source):
- if not expression.match(line):
- lines.add(line)
-
- return lines.getValue()
+ # This function has never worked as advertised by its name:
+ # - "/* Subroutine */" declarations may span multiple lines and
+ # cannot be matched by a line by line approach.
+ # - The caret in the initial regex would prevent any match, even
+ # of single line "/* Subroutine */" declarations.
+ #
+ # While we could "fix" this function to do what the name implies
+ # it should do, we have no hint of what it should really do.
+ #
+ # Therefore we keep the existing (non-)functionaity, documenting
+ # this function as doing nothing at all.
+ return source
def removeBuiltinFunctions(source):
lines = LineQueue()
diff --git a/numpy/ma/core.py b/numpy/ma/core.py
index b2ac383a2..7e2d744a3 100644
--- a/numpy/ma/core.py
+++ b/numpy/ma/core.py
@@ -3949,7 +3949,7 @@ class MaskedArray(ndarray):
# 2016-11-19: Demoted to legacy format
- if np.get_printoptions()['legacy'] == '1.13':
+ if np.core.arrayprint._get_legacy_print_mode() <= 113:
is_long = self.ndim > 1
parameters = dict(
name=name,
diff --git a/numpy/ma/mrecords.py b/numpy/ma/mrecords.py
index bdce8b3bd..2ce1f0a23 100644
--- a/numpy/ma/mrecords.py
+++ b/numpy/ma/mrecords.py
@@ -668,7 +668,8 @@ def openfile(fname):
def fromtextfile(fname, delimiter=None, commentchar='#', missingchar='',
- varnames=None, vartypes=None):
+ varnames=None, vartypes=None,
+ *, delimitor=np._NoValue): # backwards compatibility
"""
Creates a mrecarray from data stored in the file `filename`.
@@ -692,6 +693,17 @@ def fromtextfile(fname, delimiter=None, commentchar='#', missingchar='',
Ultra simple: the varnames are in the header, one line"""
+ if delimitor is not np._NoValue:
+ if delimiter is not None:
+ raise TypeError("fromtextfile() got multiple values for argument "
+ "'delimiter'")
+ # NumPy 1.22.0, 2021-09-23
+ warnings.warn("The 'delimitor' keyword argument of "
+ "numpy.ma.mrecords.fromtextfile() is deprecated "
+ "since NumPy 1.22.0, use 'delimiter' instead.",
+ DeprecationWarning, stacklevel=2)
+ delimiter = delimitor
+
# Try to open the file.
ftext = openfile(fname)
diff --git a/numpy/ma/mrecords.pyi b/numpy/ma/mrecords.pyi
index cdd5347d6..7bd8678cf 100644
--- a/numpy/ma/mrecords.pyi
+++ b/numpy/ma/mrecords.pyi
@@ -83,6 +83,8 @@ def fromtextfile(
missingchar=...,
varnames=...,
vartypes=...,
+ # NOTE: deprecated: NumPy 1.22.0, 2021-09-23
+ # delimitor=...,
): ...
def addfield(mrecord, newfield, newfieldname=...): ...
diff --git a/numpy/ma/tests/test_deprecations.py b/numpy/ma/tests/test_deprecations.py
index 14f697375..3e0e09fdd 100644
--- a/numpy/ma/tests/test_deprecations.py
+++ b/numpy/ma/tests/test_deprecations.py
@@ -1,10 +1,13 @@
"""Test deprecation and future warnings.
"""
+import pytest
import numpy as np
from numpy.testing import assert_warns
from numpy.ma.testutils import assert_equal
from numpy.ma.core import MaskedArrayFutureWarning
+import io
+import textwrap
class TestArgsort:
""" gh-8701 """
@@ -66,3 +69,21 @@ class TestMinimumMaximum:
result = ma_max(data1d)
assert_equal(result, ma_max(data1d, axis=None))
assert_equal(result, ma_max(data1d, axis=0))
+
+
+class TestFromtextfile:
+ def test_fromtextfile_delimitor(self):
+ # NumPy 1.22.0, 2021-09-23
+
+ textfile = io.StringIO(textwrap.dedent(
+ """
+ A,B,C,D
+ 'string 1';1;1.0;'mixed column'
+ 'string 2';2;2.0;
+ 'string 3';3;3.0;123
+ 'string 4';4;4.0;3.14
+ """
+ ))
+
+ with pytest.warns(DeprecationWarning):
+ result = np.ma.mrecords.fromtextfile(textfile, delimitor=';')
diff --git a/numpy/random/_generator.pyx b/numpy/random/_generator.pyx
index 8db1f0269..5bacb9f6f 100644
--- a/numpy/random/_generator.pyx
+++ b/numpy/random/_generator.pyx
@@ -4441,7 +4441,7 @@ cdef class Generator:
# Fast, statically typed path: shuffle the underlying buffer.
# Only for non-empty, 1d objects of class ndarray (subclasses such
# as MaskedArrays may not support this approach).
- x_ptr = <char*><size_t>np.PyArray_DATA(x)
+ x_ptr = np.PyArray_BYTES(x)
stride = x.strides[0]
itemsize = x.dtype.itemsize
# As the array x could contain python objects we use a buffer
@@ -4449,7 +4449,7 @@ cdef class Generator:
# within the buffer and erroneously decrementing it's refcount
# when the function exits.
buf = np.empty(itemsize, dtype=np.int8) # GC'd at function exit
- buf_ptr = <char*><size_t>np.PyArray_DATA(buf)
+ buf_ptr = np.PyArray_BYTES(buf)
if x.dtype.hasobject:
with self.lock:
_shuffle_raw_wrap(&self._bitgen, n, 1, itemsize, stride,
diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx
index c9d8ee8e3..06e75a698 100644
--- a/numpy/random/mtrand.pyx
+++ b/numpy/random/mtrand.pyx
@@ -4472,7 +4472,7 @@ cdef class RandomState:
# Fast, statically typed path: shuffle the underlying buffer.
# Only for non-empty, 1d objects of class ndarray (subclasses such
# as MaskedArrays may not support this approach).
- x_ptr = <char*><size_t>np.PyArray_DATA(x)
+ x_ptr = np.PyArray_BYTES(x)
stride = x.strides[0]
itemsize = x.dtype.itemsize
# As the array x could contain python objects we use a buffer
@@ -4480,7 +4480,7 @@ cdef class RandomState:
# within the buffer and erroneously decrementing it's refcount
# when the function exits.
buf = np.empty(itemsize, dtype=np.int8) # GC'd at function exit
- buf_ptr = <char*><size_t>np.PyArray_DATA(buf)
+ buf_ptr = np.PyArray_BYTES(buf)
with self.lock:
# We trick gcc into providing a specialized implementation for
# the most common case, yielding a ~33% performance improvement.
diff --git a/numpy/typing/__init__.py b/numpy/typing/__init__.py
index 1e366eb34..d5cfbf5ac 100644
--- a/numpy/typing/__init__.py
+++ b/numpy/typing/__init__.py
@@ -114,8 +114,9 @@ runtime, they're not necessarily considered as sub-classes.
Timedelta64
~~~~~~~~~~~
-The `~numpy.timedelta64` class is not considered a subclass of `~numpy.signedinteger`,
-the former only inheriting from `~numpy.generic` while static type checking.
+The `~numpy.timedelta64` class is not considered a subclass of
+`~numpy.signedinteger`, the former only inheriting from `~numpy.generic`
+while static type checking.
0D arrays
~~~~~~~~~
@@ -154,8 +155,10 @@ API
# NOTE: The API section will be appended with additional entries
# further down in this file
+from __future__ import annotations
+
from numpy import ufunc
-from typing import TYPE_CHECKING, List, final
+from typing import TYPE_CHECKING, final
if not TYPE_CHECKING:
__all__ = ["ArrayLike", "DTypeLike", "NBitBase", "NDArray"]
@@ -166,14 +169,14 @@ else:
#
# Declare to mypy that `__all__` is a list of strings without assigning
# an explicit value
- __all__: List[str]
- __path__: List[str]
+ __all__: list[str]
+ __path__: list[str]
@final # Disallow the creation of arbitrary `NBitBase` subclasses
class NBitBase:
"""
- An object representing `numpy.number` precision during static type checking.
+ A type representing `numpy.number` precision during static type checking.
Used exclusively for the purpose static type checking, `NBitBase`
represents the base of a hierarchical set of subclasses.
@@ -184,9 +187,9 @@ class NBitBase:
Examples
--------
- Below is a typical usage example: `NBitBase` is herein used for annotating a
- function that takes a float and integer of arbitrary precision as arguments
- and returns a new float of whichever precision is largest
+ Below is a typical usage example: `NBitBase` is herein used for annotating
+ a function that takes a float and integer of arbitrary precision
+ as arguments and returns a new float of whichever precision is largest
(*e.g.* ``np.float16 + np.int64 -> np.float64``).
.. code-block:: python
@@ -226,14 +229,29 @@ class NBitBase:
# Silence errors about subclassing a `@final`-decorated class
-class _256Bit(NBitBase): ... # type: ignore[misc]
-class _128Bit(_256Bit): ... # type: ignore[misc]
-class _96Bit(_128Bit): ... # type: ignore[misc]
-class _80Bit(_96Bit): ... # type: ignore[misc]
-class _64Bit(_80Bit): ... # type: ignore[misc]
-class _32Bit(_64Bit): ... # type: ignore[misc]
-class _16Bit(_32Bit): ... # type: ignore[misc]
-class _8Bit(_16Bit): ... # type: ignore[misc]
+class _256Bit(NBitBase): # type: ignore[misc]
+ pass
+
+class _128Bit(_256Bit): # type: ignore[misc]
+ pass
+
+class _96Bit(_128Bit): # type: ignore[misc]
+ pass
+
+class _80Bit(_96Bit): # type: ignore[misc]
+ pass
+
+class _64Bit(_80Bit): # type: ignore[misc]
+ pass
+
+class _32Bit(_64Bit): # type: ignore[misc]
+ pass
+
+class _16Bit(_32Bit): # type: ignore[misc]
+ pass
+
+class _8Bit(_16Bit): # type: ignore[misc]
+ pass
from ._nested_sequence import _NestedSequence
@@ -363,7 +381,7 @@ else:
_GUFunc_Nin2_Nout1 = ufunc
# Clean up the namespace
-del TYPE_CHECKING, final, List, ufunc
+del TYPE_CHECKING, final, ufunc
if __doc__ is not None:
from ._add_docstring import _docstrings
diff --git a/numpy/typing/_add_docstring.py b/numpy/typing/_add_docstring.py
index 846b67042..10d77f516 100644
--- a/numpy/typing/_add_docstring.py
+++ b/numpy/typing/_add_docstring.py
@@ -50,16 +50,17 @@ def _parse_docstrings() -> str:
new_lines.append("")
else:
new_lines.append(f"{indent}{line}")
- s = "\n".join(new_lines)
- # Done.
- type_list_ret.append(f""".. data:: {name}\n :value: {value}\n {s}""")
+ s = "\n".join(new_lines)
+ s_block = f""".. data:: {name}\n :value: {value}\n {s}"""
+ type_list_ret.append(s_block)
return "\n".join(type_list_ret)
add_newdoc('ArrayLike', 'typing.Union[...]',
"""
- A `~typing.Union` representing objects that can be coerced into an `~numpy.ndarray`.
+ A `~typing.Union` representing objects that can be coerced
+ into an `~numpy.ndarray`.
Among others this includes the likes of:
@@ -88,7 +89,8 @@ add_newdoc('ArrayLike', 'typing.Union[...]',
add_newdoc('DTypeLike', 'typing.Union[...]',
"""
- A `~typing.Union` representing objects that can be coerced into a `~numpy.dtype`.
+ A `~typing.Union` representing objects that can be coerced
+ into a `~numpy.dtype`.
Among others this includes the likes of:
@@ -101,7 +103,8 @@ add_newdoc('DTypeLike', 'typing.Union[...]',
See Also
--------
:ref:`Specifying and constructing data types <arrays.dtypes.constructing>`
- A comprehensive overview of all objects that can be coerced into data types.
+ A comprehensive overview of all objects that can be coerced
+ into data types.
Examples
--------
diff --git a/numpy/typing/_callable.py b/numpy/typing/_callable.pyi
index 44ad5c291..e1149f26a 100644
--- a/numpy/typing/_callable.py
+++ b/numpy/typing/_callable.pyi
@@ -49,6 +49,8 @@ from ._generic_alias import NDArray
_T1 = TypeVar("_T1")
_T2 = TypeVar("_T2")
+_T1_contra = TypeVar("_T1_contra", contravariant=True)
+_T2_contra = TypeVar("_T2_contra", contravariant=True)
_2Tuple = Tuple[_T1, _T1]
_NBit1 = TypeVar("_NBit1", bound=NBitBase)
@@ -318,8 +320,8 @@ class _ComplexOp(Protocol[_NBit1]):
class _NumberOp(Protocol):
def __call__(self, other: _NumberLike_co, /) -> Any: ...
-class _ComparisonOp(Protocol[_T1, _T2]):
+class _ComparisonOp(Protocol[_T1_contra, _T2_contra]):
@overload
- def __call__(self, other: _T1, /) -> bool_: ...
+ def __call__(self, other: _T1_contra, /) -> bool_: ...
@overload
- def __call__(self, other: _T2, /) -> NDArray[bool_]: ...
+ def __call__(self, other: _T2_contra, /) -> NDArray[bool_]: ...
diff --git a/numpy/typing/_dtype_like.py b/numpy/typing/_dtype_like.py
index 0955f5b18..c9bf1a137 100644
--- a/numpy/typing/_dtype_like.py
+++ b/numpy/typing/_dtype_like.py
@@ -1,4 +1,14 @@
-from typing import Any, List, Sequence, Tuple, Union, Type, TypeVar, Protocol, TypedDict
+from typing import (
+ Any,
+ List,
+ Sequence,
+ Tuple,
+ Union,
+ Type,
+ TypeVar,
+ Protocol,
+ TypedDict,
+)
import numpy as np
@@ -55,18 +65,23 @@ class _DTypeDictBase(TypedDict):
names: Sequence[str]
formats: Sequence[_DTypeLikeNested]
+
# Mandatory + optional keys
class _DTypeDict(_DTypeDictBase, total=False):
+ # Only `str` elements are usable as indexing aliases,
+ # but `titles` can in principle accept any object
offsets: Sequence[int]
- titles: Sequence[Any] # Only `str` elements are usable as indexing aliases, but all objects are legal
+ titles: Sequence[Any]
itemsize: int
aligned: bool
+
# A protocol for anything with the dtype attribute
class _SupportsDType(Protocol[_DType_co]):
@property
def dtype(self) -> _DType_co: ...
+
# Would create a dtype[np.void]
_VoidDTypeLike = Union[
# (flexible_dtype, itemsize)
@@ -93,7 +108,7 @@ DTypeLike = Union[
# default data type (float64)
None,
# array-scalar types and generic types
- Type[Any], # TODO: enumerate these when we add type hints for numpy scalars
+ Type[Any], # NOTE: We're stuck with `Type[Any]` due to object dtypes
# anything with a dtype attribute
_SupportsDType[DType[Any]],
# character codes, type strings or comma-separated fields, e.g., 'float64'
diff --git a/numpy/typing/_extended_precision.py b/numpy/typing/_extended_precision.py
index 0900bc659..edc1778ce 100644
--- a/numpy/typing/_extended_precision.py
+++ b/numpy/typing/_extended_precision.py
@@ -1,4 +1,5 @@
-"""A module with platform-specific extended precision `numpy.number` subclasses.
+"""A module with platform-specific extended precision
+`numpy.number` subclasses.
The subclasses are defined here (instead of ``__init__.pyi``) such
that they can be imported conditionally via the numpy's mypy plugin.
diff --git a/numpy/typing/mypy_plugin.py b/numpy/typing/mypy_plugin.py
index 091980d65..5421d6bfa 100644
--- a/numpy/typing/mypy_plugin.py
+++ b/numpy/typing/mypy_plugin.py
@@ -33,7 +33,8 @@ To enable the plugin, one must add it to their mypy `configuration file`_:
from __future__ import annotations
-import typing as t
+from collections.abc import Iterable
+from typing import Final, TYPE_CHECKING, Callable
import numpy as np
@@ -44,15 +45,15 @@ try:
from mypy.nodes import MypyFile, ImportFrom, Statement
from mypy.build import PRI_MED
- _HookFunc = t.Callable[[AnalyzeTypeContext], Type]
+ _HookFunc = Callable[[AnalyzeTypeContext], Type]
MYPY_EX: None | ModuleNotFoundError = None
except ModuleNotFoundError as ex:
MYPY_EX = ex
-__all__: t.List[str] = []
+__all__: list[str] = []
-def _get_precision_dict() -> t.Dict[str, str]:
+def _get_precision_dict() -> dict[str, str]:
names = [
("_NBitByte", np.byte),
("_NBitShort", np.short),
@@ -73,7 +74,7 @@ def _get_precision_dict() -> t.Dict[str, str]:
return ret
-def _get_extended_precision_list() -> t.List[str]:
+def _get_extended_precision_list() -> list[str]:
extended_types = [np.ulonglong, np.longlong, np.longdouble, np.clongdouble]
extended_names = {
"uint128",
@@ -107,13 +108,13 @@ def _get_c_intp_name() -> str:
#: A dictionary mapping type-aliases in `numpy.typing._nbit` to
#: concrete `numpy.typing.NBitBase` subclasses.
-_PRECISION_DICT: t.Final = _get_precision_dict()
+_PRECISION_DICT: Final = _get_precision_dict()
#: A list with the names of all extended precision `np.number` subclasses.
-_EXTENDED_PRECISION_LIST: t.Final = _get_extended_precision_list()
+_EXTENDED_PRECISION_LIST: Final = _get_extended_precision_list()
#: The name of the ctypes quivalent of `np.intp`
-_C_INTP: t.Final = _get_c_intp_name()
+_C_INTP: Final = _get_c_intp_name()
def _hook(ctx: AnalyzeTypeContext) -> Type:
@@ -124,8 +125,8 @@ def _hook(ctx: AnalyzeTypeContext) -> Type:
return api.named_type(name_new)
-if t.TYPE_CHECKING or MYPY_EX is None:
- def _index(iterable: t.Iterable[Statement], id: str) -> int:
+if TYPE_CHECKING or MYPY_EX is None:
+ def _index(iterable: Iterable[Statement], id: str) -> int:
"""Identify the first ``ImportFrom`` instance the specified `id`."""
for i, value in enumerate(iterable):
if getattr(value, "id", None) == id:
@@ -137,7 +138,7 @@ if t.TYPE_CHECKING or MYPY_EX is None:
def _override_imports(
file: MypyFile,
module: str,
- imports: t.List[t.Tuple[str, t.Optional[str]]],
+ imports: list[tuple[str, None | str]],
) -> None:
"""Override the first `module`-based import with new `imports`."""
# Construct a new `from module import y` statement
@@ -145,7 +146,7 @@ if t.TYPE_CHECKING or MYPY_EX is None:
import_obj.is_top_level = True
# Replace the first `module`-based import statement with `import_obj`
- for lst in [file.defs, file.imports]: # type: t.List[Statement]
+ for lst in [file.defs, file.imports]: # type: list[Statement]
i = _index(lst, module)
lst[i] = import_obj
@@ -153,7 +154,8 @@ if t.TYPE_CHECKING or MYPY_EX is None:
"""A mypy plugin for handling versus numpy-specific typing tasks."""
def get_type_analyze_hook(self, fullname: str) -> None | _HookFunc:
- """Set the precision of platform-specific `numpy.number` subclasses.
+ """Set the precision of platform-specific `numpy.number`
+ subclasses.
For example: `numpy.int_`, `numpy.longlong` and `numpy.longdouble`.
"""
@@ -161,7 +163,9 @@ if t.TYPE_CHECKING or MYPY_EX is None:
return _hook
return None
- def get_additional_deps(self, file: MypyFile) -> t.List[t.Tuple[int, str, int]]:
+ def get_additional_deps(
+ self, file: MypyFile
+ ) -> list[tuple[int, str, int]]:
"""Handle all import-based overrides.
* Import platform-specific extended-precision `numpy.number`
@@ -184,11 +188,11 @@ if t.TYPE_CHECKING or MYPY_EX is None:
)
return ret
- def plugin(version: str) -> t.Type[_NumpyPlugin]:
+ def plugin(version: str) -> type[_NumpyPlugin]:
"""An entry-point for mypy."""
return _NumpyPlugin
else:
- def plugin(version: str) -> t.Type[_NumpyPlugin]:
+ def plugin(version: str) -> type[_NumpyPlugin]:
"""An entry-point for mypy."""
raise MYPY_EX
diff --git a/numpy/typing/tests/data/fail/arithmetic.py b/numpy/typing/tests/data/fail/arithmetic.pyi
index 02bbffa53..02bbffa53 100644
--- a/numpy/typing/tests/data/fail/arithmetic.py
+++ b/numpy/typing/tests/data/fail/arithmetic.pyi
diff --git a/numpy/typing/tests/data/fail/array_constructors.py b/numpy/typing/tests/data/fail/array_constructors.pyi
index 0e2250513..0e2250513 100644
--- a/numpy/typing/tests/data/fail/array_constructors.py
+++ b/numpy/typing/tests/data/fail/array_constructors.pyi
diff --git a/numpy/typing/tests/data/fail/array_like.py b/numpy/typing/tests/data/fail/array_like.pyi
index 3bbd29061..3bbd29061 100644
--- a/numpy/typing/tests/data/fail/array_like.py
+++ b/numpy/typing/tests/data/fail/array_like.pyi
diff --git a/numpy/typing/tests/data/fail/array_pad.py b/numpy/typing/tests/data/fail/array_pad.pyi
index 2be51a871..2be51a871 100644
--- a/numpy/typing/tests/data/fail/array_pad.py
+++ b/numpy/typing/tests/data/fail/array_pad.pyi
diff --git a/numpy/typing/tests/data/fail/arrayprint.py b/numpy/typing/tests/data/fail/arrayprint.pyi
index 86297a0b2..86297a0b2 100644
--- a/numpy/typing/tests/data/fail/arrayprint.py
+++ b/numpy/typing/tests/data/fail/arrayprint.pyi
diff --git a/numpy/typing/tests/data/fail/arrayterator.py b/numpy/typing/tests/data/fail/arrayterator.pyi
index c50fb2ec4..c50fb2ec4 100644
--- a/numpy/typing/tests/data/fail/arrayterator.py
+++ b/numpy/typing/tests/data/fail/arrayterator.pyi
diff --git a/numpy/typing/tests/data/fail/bitwise_ops.py b/numpy/typing/tests/data/fail/bitwise_ops.pyi
index ee9090007..ee9090007 100644
--- a/numpy/typing/tests/data/fail/bitwise_ops.py
+++ b/numpy/typing/tests/data/fail/bitwise_ops.pyi
diff --git a/numpy/typing/tests/data/fail/char.py b/numpy/typing/tests/data/fail/char.pyi
index 320f05df5..320f05df5 100644
--- a/numpy/typing/tests/data/fail/char.py
+++ b/numpy/typing/tests/data/fail/char.pyi
diff --git a/numpy/typing/tests/data/fail/comparisons.py b/numpy/typing/tests/data/fail/comparisons.pyi
index 0432177e2..0432177e2 100644
--- a/numpy/typing/tests/data/fail/comparisons.py
+++ b/numpy/typing/tests/data/fail/comparisons.pyi
diff --git a/numpy/typing/tests/data/fail/constants.py b/numpy/typing/tests/data/fail/constants.pyi
index 324cbe9fa..324cbe9fa 100644
--- a/numpy/typing/tests/data/fail/constants.py
+++ b/numpy/typing/tests/data/fail/constants.pyi
diff --git a/numpy/typing/tests/data/fail/datasource.py b/numpy/typing/tests/data/fail/datasource.pyi
index 345277d45..345277d45 100644
--- a/numpy/typing/tests/data/fail/datasource.py
+++ b/numpy/typing/tests/data/fail/datasource.pyi
diff --git a/numpy/typing/tests/data/fail/dtype.py b/numpy/typing/tests/data/fail/dtype.pyi
index 0f3810f3c..0f3810f3c 100644
--- a/numpy/typing/tests/data/fail/dtype.py
+++ b/numpy/typing/tests/data/fail/dtype.pyi
diff --git a/numpy/typing/tests/data/fail/einsumfunc.py b/numpy/typing/tests/data/fail/einsumfunc.pyi
index 33722f861..33722f861 100644
--- a/numpy/typing/tests/data/fail/einsumfunc.py
+++ b/numpy/typing/tests/data/fail/einsumfunc.pyi
diff --git a/numpy/typing/tests/data/fail/flatiter.py b/numpy/typing/tests/data/fail/flatiter.pyi
index 544ffbe4a..544ffbe4a 100644
--- a/numpy/typing/tests/data/fail/flatiter.py
+++ b/numpy/typing/tests/data/fail/flatiter.pyi
diff --git a/numpy/typing/tests/data/fail/fromnumeric.py b/numpy/typing/tests/data/fail/fromnumeric.pyi
index 8fafed1b7..8fafed1b7 100644
--- a/numpy/typing/tests/data/fail/fromnumeric.py
+++ b/numpy/typing/tests/data/fail/fromnumeric.pyi
diff --git a/numpy/typing/tests/data/fail/index_tricks.py b/numpy/typing/tests/data/fail/index_tricks.pyi
index c508bf3ae..c508bf3ae 100644
--- a/numpy/typing/tests/data/fail/index_tricks.py
+++ b/numpy/typing/tests/data/fail/index_tricks.pyi
diff --git a/numpy/typing/tests/data/fail/lib_utils.py b/numpy/typing/tests/data/fail/lib_utils.pyi
index e16c926aa..e16c926aa 100644
--- a/numpy/typing/tests/data/fail/lib_utils.py
+++ b/numpy/typing/tests/data/fail/lib_utils.pyi
diff --git a/numpy/typing/tests/data/fail/lib_version.py b/numpy/typing/tests/data/fail/lib_version.pyi
index 2758cfe40..2758cfe40 100644
--- a/numpy/typing/tests/data/fail/lib_version.py
+++ b/numpy/typing/tests/data/fail/lib_version.pyi
diff --git a/numpy/typing/tests/data/fail/linalg.py b/numpy/typing/tests/data/fail/linalg.pyi
index da9390328..da9390328 100644
--- a/numpy/typing/tests/data/fail/linalg.py
+++ b/numpy/typing/tests/data/fail/linalg.pyi
diff --git a/numpy/typing/tests/data/fail/memmap.pyi b/numpy/typing/tests/data/fail/memmap.pyi
new file mode 100644
index 000000000..434870b60
--- /dev/null
+++ b/numpy/typing/tests/data/fail/memmap.pyi
@@ -0,0 +1,5 @@
+import numpy as np
+
+with open("file.txt", "r") as f:
+ np.memmap(f) # E: No overload variant
+np.memmap("test.txt", shape=[10, 5]) # E: No overload variant
diff --git a/numpy/typing/tests/data/fail/modules.py b/numpy/typing/tests/data/fail/modules.pyi
index 59e724f22..59e724f22 100644
--- a/numpy/typing/tests/data/fail/modules.py
+++ b/numpy/typing/tests/data/fail/modules.pyi
diff --git a/numpy/typing/tests/data/fail/multiarray.py b/numpy/typing/tests/data/fail/multiarray.pyi
index 22bcf8c92..22bcf8c92 100644
--- a/numpy/typing/tests/data/fail/multiarray.py
+++ b/numpy/typing/tests/data/fail/multiarray.pyi
diff --git a/numpy/typing/tests/data/fail/ndarray.py b/numpy/typing/tests/data/fail/ndarray.pyi
index 5a5130d40..5a5130d40 100644
--- a/numpy/typing/tests/data/fail/ndarray.py
+++ b/numpy/typing/tests/data/fail/ndarray.pyi
diff --git a/numpy/typing/tests/data/fail/ndarray_misc.py b/numpy/typing/tests/data/fail/ndarray_misc.pyi
index cf3fedc45..cf3fedc45 100644
--- a/numpy/typing/tests/data/fail/ndarray_misc.py
+++ b/numpy/typing/tests/data/fail/ndarray_misc.pyi
diff --git a/numpy/typing/tests/data/fail/nditer.py b/numpy/typing/tests/data/fail/nditer.pyi
index 1e8e37ee5..1e8e37ee5 100644
--- a/numpy/typing/tests/data/fail/nditer.py
+++ b/numpy/typing/tests/data/fail/nditer.pyi
diff --git a/numpy/typing/tests/data/fail/nested_sequence.py b/numpy/typing/tests/data/fail/nested_sequence.pyi
index e28661a05..e28661a05 100644
--- a/numpy/typing/tests/data/fail/nested_sequence.py
+++ b/numpy/typing/tests/data/fail/nested_sequence.pyi
diff --git a/numpy/typing/tests/data/fail/npyio.py b/numpy/typing/tests/data/fail/npyio.pyi
index c91b4c9cb..c91b4c9cb 100644
--- a/numpy/typing/tests/data/fail/npyio.py
+++ b/numpy/typing/tests/data/fail/npyio.pyi
diff --git a/numpy/typing/tests/data/fail/numerictypes.py b/numpy/typing/tests/data/fail/numerictypes.pyi
index a5c2814ef..a5c2814ef 100644
--- a/numpy/typing/tests/data/fail/numerictypes.py
+++ b/numpy/typing/tests/data/fail/numerictypes.pyi
diff --git a/numpy/typing/tests/data/fail/random.py b/numpy/typing/tests/data/fail/random.pyi
index c4d1e3e3e..c4d1e3e3e 100644
--- a/numpy/typing/tests/data/fail/random.py
+++ b/numpy/typing/tests/data/fail/random.pyi
diff --git a/numpy/typing/tests/data/fail/rec.py b/numpy/typing/tests/data/fail/rec.pyi
index a57f1ba27..a57f1ba27 100644
--- a/numpy/typing/tests/data/fail/rec.py
+++ b/numpy/typing/tests/data/fail/rec.pyi
diff --git a/numpy/typing/tests/data/fail/scalars.py b/numpy/typing/tests/data/fail/scalars.pyi
index 94fe3f71e..94fe3f71e 100644
--- a/numpy/typing/tests/data/fail/scalars.py
+++ b/numpy/typing/tests/data/fail/scalars.pyi
diff --git a/numpy/typing/tests/data/fail/stride_tricks.py b/numpy/typing/tests/data/fail/stride_tricks.pyi
index f2bfba743..f2bfba743 100644
--- a/numpy/typing/tests/data/fail/stride_tricks.py
+++ b/numpy/typing/tests/data/fail/stride_tricks.pyi
diff --git a/numpy/typing/tests/data/fail/testing.py b/numpy/typing/tests/data/fail/testing.pyi
index e753a9810..e753a9810 100644
--- a/numpy/typing/tests/data/fail/testing.py
+++ b/numpy/typing/tests/data/fail/testing.pyi
diff --git a/numpy/typing/tests/data/fail/twodim_base.py b/numpy/typing/tests/data/fail/twodim_base.pyi
index ab34a374c..ab34a374c 100644
--- a/numpy/typing/tests/data/fail/twodim_base.py
+++ b/numpy/typing/tests/data/fail/twodim_base.pyi
diff --git a/numpy/typing/tests/data/fail/type_check.py b/numpy/typing/tests/data/fail/type_check.pyi
index 95f52bfbd..95f52bfbd 100644
--- a/numpy/typing/tests/data/fail/type_check.py
+++ b/numpy/typing/tests/data/fail/type_check.pyi
diff --git a/numpy/typing/tests/data/fail/ufunc_config.py b/numpy/typing/tests/data/fail/ufunc_config.pyi
index f547fbb46..f547fbb46 100644
--- a/numpy/typing/tests/data/fail/ufunc_config.py
+++ b/numpy/typing/tests/data/fail/ufunc_config.pyi
diff --git a/numpy/typing/tests/data/fail/ufunclike.py b/numpy/typing/tests/data/fail/ufunclike.pyi
index 82a5f3a1d..82a5f3a1d 100644
--- a/numpy/typing/tests/data/fail/ufunclike.py
+++ b/numpy/typing/tests/data/fail/ufunclike.pyi
diff --git a/numpy/typing/tests/data/fail/ufuncs.py b/numpy/typing/tests/data/fail/ufuncs.pyi
index e827267c6..e827267c6 100644
--- a/numpy/typing/tests/data/fail/ufuncs.py
+++ b/numpy/typing/tests/data/fail/ufuncs.pyi
diff --git a/numpy/typing/tests/data/fail/warnings_and_errors.py b/numpy/typing/tests/data/fail/warnings_and_errors.pyi
index f4fa38293..f4fa38293 100644
--- a/numpy/typing/tests/data/fail/warnings_and_errors.py
+++ b/numpy/typing/tests/data/fail/warnings_and_errors.pyi
diff --git a/numpy/typing/tests/data/misc/extended_precision.py b/numpy/typing/tests/data/misc/extended_precision.pyi
index 1e495e4f3..1e495e4f3 100644
--- a/numpy/typing/tests/data/misc/extended_precision.py
+++ b/numpy/typing/tests/data/misc/extended_precision.pyi
diff --git a/numpy/typing/tests/data/reveal/arithmetic.py b/numpy/typing/tests/data/reveal/arithmetic.pyi
index 0d9132e5b..0d9132e5b 100644
--- a/numpy/typing/tests/data/reveal/arithmetic.py
+++ b/numpy/typing/tests/data/reveal/arithmetic.pyi
diff --git a/numpy/typing/tests/data/reveal/array_constructors.py b/numpy/typing/tests/data/reveal/array_constructors.pyi
index 44c85e988..44c85e988 100644
--- a/numpy/typing/tests/data/reveal/array_constructors.py
+++ b/numpy/typing/tests/data/reveal/array_constructors.pyi
diff --git a/numpy/typing/tests/data/reveal/arraypad.py b/numpy/typing/tests/data/reveal/arraypad.pyi
index 03c03fb4e..03c03fb4e 100644
--- a/numpy/typing/tests/data/reveal/arraypad.py
+++ b/numpy/typing/tests/data/reveal/arraypad.pyi
diff --git a/numpy/typing/tests/data/reveal/arrayprint.py b/numpy/typing/tests/data/reveal/arrayprint.pyi
index e797097eb..e797097eb 100644
--- a/numpy/typing/tests/data/reveal/arrayprint.py
+++ b/numpy/typing/tests/data/reveal/arrayprint.pyi
diff --git a/numpy/typing/tests/data/reveal/arraysetops.py b/numpy/typing/tests/data/reveal/arraysetops.pyi
index c8aeb03ab..c8aeb03ab 100644
--- a/numpy/typing/tests/data/reveal/arraysetops.py
+++ b/numpy/typing/tests/data/reveal/arraysetops.pyi
diff --git a/numpy/typing/tests/data/reveal/arrayterator.py b/numpy/typing/tests/data/reveal/arrayterator.pyi
index ea4e75612..ea4e75612 100644
--- a/numpy/typing/tests/data/reveal/arrayterator.py
+++ b/numpy/typing/tests/data/reveal/arrayterator.pyi
diff --git a/numpy/typing/tests/data/reveal/bitwise_ops.py b/numpy/typing/tests/data/reveal/bitwise_ops.pyi
index 6b9969568..6b9969568 100644
--- a/numpy/typing/tests/data/reveal/bitwise_ops.py
+++ b/numpy/typing/tests/data/reveal/bitwise_ops.pyi
diff --git a/numpy/typing/tests/data/reveal/char.py b/numpy/typing/tests/data/reveal/char.pyi
index dd2e76a2d..dd2e76a2d 100644
--- a/numpy/typing/tests/data/reveal/char.py
+++ b/numpy/typing/tests/data/reveal/char.pyi
diff --git a/numpy/typing/tests/data/reveal/comparisons.py b/numpy/typing/tests/data/reveal/comparisons.pyi
index 16f21cc39..16f21cc39 100644
--- a/numpy/typing/tests/data/reveal/comparisons.py
+++ b/numpy/typing/tests/data/reveal/comparisons.pyi
diff --git a/numpy/typing/tests/data/reveal/constants.py b/numpy/typing/tests/data/reveal/constants.pyi
index 9a46bfded..9a46bfded 100644
--- a/numpy/typing/tests/data/reveal/constants.py
+++ b/numpy/typing/tests/data/reveal/constants.pyi
diff --git a/numpy/typing/tests/data/reveal/ctypeslib.py b/numpy/typing/tests/data/reveal/ctypeslib.pyi
index 0c32d70ed..0c32d70ed 100644
--- a/numpy/typing/tests/data/reveal/ctypeslib.py
+++ b/numpy/typing/tests/data/reveal/ctypeslib.pyi
diff --git a/numpy/typing/tests/data/reveal/datasource.py b/numpy/typing/tests/data/reveal/datasource.pyi
index 245ac7649..245ac7649 100644
--- a/numpy/typing/tests/data/reveal/datasource.py
+++ b/numpy/typing/tests/data/reveal/datasource.pyi
diff --git a/numpy/typing/tests/data/reveal/dtype.py b/numpy/typing/tests/data/reveal/dtype.pyi
index 364d1dcab..364d1dcab 100644
--- a/numpy/typing/tests/data/reveal/dtype.py
+++ b/numpy/typing/tests/data/reveal/dtype.pyi
diff --git a/numpy/typing/tests/data/reveal/einsumfunc.py b/numpy/typing/tests/data/reveal/einsumfunc.pyi
index f1a90428d..f1a90428d 100644
--- a/numpy/typing/tests/data/reveal/einsumfunc.py
+++ b/numpy/typing/tests/data/reveal/einsumfunc.pyi
diff --git a/numpy/typing/tests/data/reveal/flatiter.py b/numpy/typing/tests/data/reveal/flatiter.pyi
index 97776dd9f..97776dd9f 100644
--- a/numpy/typing/tests/data/reveal/flatiter.py
+++ b/numpy/typing/tests/data/reveal/flatiter.pyi
diff --git a/numpy/typing/tests/data/reveal/fromnumeric.py b/numpy/typing/tests/data/reveal/fromnumeric.pyi
index bbcfbb85a..bbcfbb85a 100644
--- a/numpy/typing/tests/data/reveal/fromnumeric.py
+++ b/numpy/typing/tests/data/reveal/fromnumeric.pyi
diff --git a/numpy/typing/tests/data/reveal/getlimits.py b/numpy/typing/tests/data/reveal/getlimits.pyi
index e12723bfe..e12723bfe 100644
--- a/numpy/typing/tests/data/reveal/getlimits.py
+++ b/numpy/typing/tests/data/reveal/getlimits.pyi
diff --git a/numpy/typing/tests/data/reveal/index_tricks.py b/numpy/typing/tests/data/reveal/index_tricks.pyi
index 863d60220..863d60220 100644
--- a/numpy/typing/tests/data/reveal/index_tricks.py
+++ b/numpy/typing/tests/data/reveal/index_tricks.pyi
diff --git a/numpy/typing/tests/data/reveal/lib_utils.py b/numpy/typing/tests/data/reveal/lib_utils.pyi
index d82012707..d82012707 100644
--- a/numpy/typing/tests/data/reveal/lib_utils.py
+++ b/numpy/typing/tests/data/reveal/lib_utils.pyi
diff --git a/numpy/typing/tests/data/reveal/lib_version.py b/numpy/typing/tests/data/reveal/lib_version.pyi
index e6f695558..e6f695558 100644
--- a/numpy/typing/tests/data/reveal/lib_version.py
+++ b/numpy/typing/tests/data/reveal/lib_version.pyi
diff --git a/numpy/typing/tests/data/reveal/linalg.py b/numpy/typing/tests/data/reveal/linalg.pyi
index fecdc0d37..fecdc0d37 100644
--- a/numpy/typing/tests/data/reveal/linalg.py
+++ b/numpy/typing/tests/data/reveal/linalg.pyi
diff --git a/numpy/typing/tests/data/reveal/memmap.pyi b/numpy/typing/tests/data/reveal/memmap.pyi
new file mode 100644
index 000000000..c1d8edc67
--- /dev/null
+++ b/numpy/typing/tests/data/reveal/memmap.pyi
@@ -0,0 +1,16 @@
+import numpy as np
+from typing import Any
+
+memmap_obj: np.memmap[Any, np.dtype[np.str_]]
+
+reveal_type(np.memmap.__array_priority__) # E: float
+reveal_type(memmap_obj.__array_priority__) # E: float
+reveal_type(memmap_obj.filename) # E: Union[builtins.str, None]
+reveal_type(memmap_obj.offset) # E: int
+reveal_type(memmap_obj.mode) # E: str
+reveal_type(memmap_obj.flush()) # E: None
+
+reveal_type(np.memmap("file.txt", offset=5)) # E: numpy.memmap[Any, numpy.dtype[{uint8}]]
+reveal_type(np.memmap(b"file.txt", dtype=np.float64, shape=(10, 3))) # E: numpy.memmap[Any, numpy.dtype[{float64}]]
+with open("file.txt", "rb") as f:
+ reveal_type(np.memmap(f, dtype=float, order="K")) # E: numpy.memmap[Any, numpy.dtype[Any]]
diff --git a/numpy/typing/tests/data/reveal/mod.py b/numpy/typing/tests/data/reveal/mod.pyi
index bf45b8c58..bf45b8c58 100644
--- a/numpy/typing/tests/data/reveal/mod.py
+++ b/numpy/typing/tests/data/reveal/mod.pyi
diff --git a/numpy/typing/tests/data/reveal/modules.py b/numpy/typing/tests/data/reveal/modules.pyi
index 7e695433e..7e695433e 100644
--- a/numpy/typing/tests/data/reveal/modules.py
+++ b/numpy/typing/tests/data/reveal/modules.pyi
diff --git a/numpy/typing/tests/data/reveal/multiarray.py b/numpy/typing/tests/data/reveal/multiarray.pyi
index ee818c08a..ee818c08a 100644
--- a/numpy/typing/tests/data/reveal/multiarray.py
+++ b/numpy/typing/tests/data/reveal/multiarray.pyi
diff --git a/numpy/typing/tests/data/reveal/nbit_base_example.py b/numpy/typing/tests/data/reveal/nbit_base_example.pyi
index d34f6f69a..d34f6f69a 100644
--- a/numpy/typing/tests/data/reveal/nbit_base_example.py
+++ b/numpy/typing/tests/data/reveal/nbit_base_example.pyi
diff --git a/numpy/typing/tests/data/reveal/ndarray_conversion.py b/numpy/typing/tests/data/reveal/ndarray_conversion.pyi
index 03f2faf43..03f2faf43 100644
--- a/numpy/typing/tests/data/reveal/ndarray_conversion.py
+++ b/numpy/typing/tests/data/reveal/ndarray_conversion.pyi
diff --git a/numpy/typing/tests/data/reveal/ndarray_misc.py b/numpy/typing/tests/data/reveal/ndarray_misc.pyi
index 050b82cdc..050b82cdc 100644
--- a/numpy/typing/tests/data/reveal/ndarray_misc.py
+++ b/numpy/typing/tests/data/reveal/ndarray_misc.pyi
diff --git a/numpy/typing/tests/data/reveal/ndarray_shape_manipulation.py b/numpy/typing/tests/data/reveal/ndarray_shape_manipulation.pyi
index a44e1cfa1..a44e1cfa1 100644
--- a/numpy/typing/tests/data/reveal/ndarray_shape_manipulation.py
+++ b/numpy/typing/tests/data/reveal/ndarray_shape_manipulation.pyi
diff --git a/numpy/typing/tests/data/reveal/nditer.py b/numpy/typing/tests/data/reveal/nditer.pyi
index 473e922a2..473e922a2 100644
--- a/numpy/typing/tests/data/reveal/nditer.py
+++ b/numpy/typing/tests/data/reveal/nditer.pyi
diff --git a/numpy/typing/tests/data/reveal/nested_sequence.py b/numpy/typing/tests/data/reveal/nested_sequence.pyi
index 07e24e357..07e24e357 100644
--- a/numpy/typing/tests/data/reveal/nested_sequence.py
+++ b/numpy/typing/tests/data/reveal/nested_sequence.pyi
diff --git a/numpy/typing/tests/data/reveal/npyio.py b/numpy/typing/tests/data/reveal/npyio.pyi
index bee97a8e1..bee97a8e1 100644
--- a/numpy/typing/tests/data/reveal/npyio.py
+++ b/numpy/typing/tests/data/reveal/npyio.pyi
diff --git a/numpy/typing/tests/data/reveal/numeric.py b/numpy/typing/tests/data/reveal/numeric.pyi
index ec6e47ca0..ec6e47ca0 100644
--- a/numpy/typing/tests/data/reveal/numeric.py
+++ b/numpy/typing/tests/data/reveal/numeric.pyi
diff --git a/numpy/typing/tests/data/reveal/numerictypes.py b/numpy/typing/tests/data/reveal/numerictypes.pyi
index c50a3a3d6..c50a3a3d6 100644
--- a/numpy/typing/tests/data/reveal/numerictypes.py
+++ b/numpy/typing/tests/data/reveal/numerictypes.pyi
diff --git a/numpy/typing/tests/data/reveal/random.py b/numpy/typing/tests/data/reveal/random.pyi
index 6fc35aced..6fc35aced 100644
--- a/numpy/typing/tests/data/reveal/random.py
+++ b/numpy/typing/tests/data/reveal/random.pyi
diff --git a/numpy/typing/tests/data/reveal/rec.py b/numpy/typing/tests/data/reveal/rec.pyi
index 2fa8cc7b9..2fa8cc7b9 100644
--- a/numpy/typing/tests/data/reveal/rec.py
+++ b/numpy/typing/tests/data/reveal/rec.pyi
diff --git a/numpy/typing/tests/data/reveal/scalars.py b/numpy/typing/tests/data/reveal/scalars.pyi
index a95f8f6f2..a95f8f6f2 100644
--- a/numpy/typing/tests/data/reveal/scalars.py
+++ b/numpy/typing/tests/data/reveal/scalars.pyi
diff --git a/numpy/typing/tests/data/reveal/shape_base.py b/numpy/typing/tests/data/reveal/shape_base.pyi
index 57633defb..57633defb 100644
--- a/numpy/typing/tests/data/reveal/shape_base.py
+++ b/numpy/typing/tests/data/reveal/shape_base.pyi
diff --git a/numpy/typing/tests/data/reveal/stride_tricks.py b/numpy/typing/tests/data/reveal/stride_tricks.pyi
index 152d9cea6..152d9cea6 100644
--- a/numpy/typing/tests/data/reveal/stride_tricks.py
+++ b/numpy/typing/tests/data/reveal/stride_tricks.pyi
diff --git a/numpy/typing/tests/data/reveal/testing.py b/numpy/typing/tests/data/reveal/testing.pyi
index 2b040ff60..2b040ff60 100644
--- a/numpy/typing/tests/data/reveal/testing.py
+++ b/numpy/typing/tests/data/reveal/testing.pyi
diff --git a/numpy/typing/tests/data/reveal/twodim_base.py b/numpy/typing/tests/data/reveal/twodim_base.pyi
index b95fbc71e..b95fbc71e 100644
--- a/numpy/typing/tests/data/reveal/twodim_base.py
+++ b/numpy/typing/tests/data/reveal/twodim_base.pyi
diff --git a/numpy/typing/tests/data/reveal/type_check.py b/numpy/typing/tests/data/reveal/type_check.pyi
index 416dd42a8..416dd42a8 100644
--- a/numpy/typing/tests/data/reveal/type_check.py
+++ b/numpy/typing/tests/data/reveal/type_check.pyi
diff --git a/numpy/typing/tests/data/reveal/ufunc_config.py b/numpy/typing/tests/data/reveal/ufunc_config.pyi
index 26be80314..26be80314 100644
--- a/numpy/typing/tests/data/reveal/ufunc_config.py
+++ b/numpy/typing/tests/data/reveal/ufunc_config.pyi
diff --git a/numpy/typing/tests/data/reveal/ufunclike.py b/numpy/typing/tests/data/reveal/ufunclike.pyi
index 8b3aea7ce..8b3aea7ce 100644
--- a/numpy/typing/tests/data/reveal/ufunclike.py
+++ b/numpy/typing/tests/data/reveal/ufunclike.pyi
diff --git a/numpy/typing/tests/data/reveal/ufuncs.py b/numpy/typing/tests/data/reveal/ufuncs.pyi
index ade45577c..ade45577c 100644
--- a/numpy/typing/tests/data/reveal/ufuncs.py
+++ b/numpy/typing/tests/data/reveal/ufuncs.pyi
diff --git a/numpy/typing/tests/data/reveal/warnings_and_errors.py b/numpy/typing/tests/data/reveal/warnings_and_errors.pyi
index 3f20a0135..3f20a0135 100644
--- a/numpy/typing/tests/data/reveal/warnings_and_errors.py
+++ b/numpy/typing/tests/data/reveal/warnings_and_errors.pyi
diff --git a/numpy/typing/tests/test_runtime.py b/numpy/typing/tests/test_runtime.py
index 151b06bed..5b5df49dc 100644
--- a/numpy/typing/tests/test_runtime.py
+++ b/numpy/typing/tests/test_runtime.py
@@ -3,7 +3,7 @@
from __future__ import annotations
import sys
-from typing import get_type_hints, Union, Tuple, NamedTuple, get_args, get_origin
+from typing import get_type_hints, Union, NamedTuple, get_args, get_origin
import pytest
import numpy as np
@@ -12,7 +12,7 @@ import numpy.typing as npt
class TypeTup(NamedTuple):
typ: type
- args: Tuple[type, ...]
+ args: tuple[type, ...]
origin: None | type
diff --git a/numpy/typing/tests/test_typing.py b/numpy/typing/tests/test_typing.py
index 81863c780..0f3e10b7b 100644
--- a/numpy/typing/tests/test_typing.py
+++ b/numpy/typing/tests/test_typing.py
@@ -1,10 +1,13 @@
+from __future__ import annotations
+
import importlib.util
import itertools
import os
import re
import shutil
from collections import defaultdict
-from typing import Optional, IO, Dict, List
+from collections.abc import Iterator
+from typing import IO, TYPE_CHECKING
import pytest
import numpy as np
@@ -21,6 +24,10 @@ except ImportError:
else:
NO_MYPY = False
+if TYPE_CHECKING:
+ # We need this as annotation, but it's located in a private namespace.
+ # As a compromise, do *not* import it during runtime
+ from _pytest.mark.structures import ParameterSet
DATA_DIR = os.path.join(os.path.dirname(__file__), "data")
PASS_DIR = os.path.join(DATA_DIR, "pass")
@@ -32,7 +39,7 @@ CACHE_DIR = os.path.join(DATA_DIR, ".mypy_cache")
#: A dictionary with file names as keys and lists of the mypy stdout as values.
#: To-be populated by `run_mypy`.
-OUTPUT_MYPY: Dict[str, List[str]] = {}
+OUTPUT_MYPY: dict[str, list[str]] = {}
def _key_func(key: str) -> str:
@@ -62,7 +69,10 @@ def run_mypy() -> None:
NUMPY_TYPING_TEST_CLEAR_CACHE=0 pytest numpy/typing/tests
"""
- if os.path.isdir(CACHE_DIR) and bool(os.environ.get("NUMPY_TYPING_TEST_CLEAR_CACHE", True)):
+ if (
+ os.path.isdir(CACHE_DIR)
+ and bool(os.environ.get("NUMPY_TYPING_TEST_CLEAR_CACHE", True))
+ ):
shutil.rmtree(CACHE_DIR)
for directory in (PASS_DIR, REVEAL_DIR, FAIL_DIR, MISC_DIR):
@@ -85,10 +95,10 @@ def run_mypy() -> None:
OUTPUT_MYPY.update((k, list(v)) for k, v in iterator if k)
-def get_test_cases(directory):
+def get_test_cases(directory: str) -> Iterator[ParameterSet]:
for root, _, files in os.walk(directory):
for fname in files:
- if os.path.splitext(fname)[-1] == ".py":
+ if os.path.splitext(fname)[-1] in (".pyi", ".py"):
fullpath = os.path.join(root, fname)
# Use relative path for nice py.test name
relpath = os.path.relpath(fullpath, start=directory)
@@ -103,7 +113,7 @@ def get_test_cases(directory):
@pytest.mark.slow
@pytest.mark.skipif(NO_MYPY, reason="Mypy is not installed")
@pytest.mark.parametrize("path", get_test_cases(PASS_DIR))
-def test_success(path):
+def test_success(path) -> None:
# Alias `OUTPUT_MYPY` so that it appears in the local namespace
output_mypy = OUTPUT_MYPY
if path in output_mypy:
@@ -115,7 +125,7 @@ def test_success(path):
@pytest.mark.slow
@pytest.mark.skipif(NO_MYPY, reason="Mypy is not installed")
@pytest.mark.parametrize("path", get_test_cases(FAIL_DIR))
-def test_fail(path):
+def test_fail(path: str) -> None:
__tracebackhide__ = True
with open(path) as fin:
@@ -138,7 +148,10 @@ def test_fail(path):
for i, line in enumerate(lines):
lineno = i + 1
- if line.startswith('#') or (" E:" not in line and lineno not in errors):
+ if (
+ line.startswith('#')
+ or (" E:" not in line and lineno not in errors)
+ ):
continue
target_line = lines[lineno - 1]
@@ -162,14 +175,19 @@ Observed error: {!r}
"""
-def _test_fail(path: str, error: str, expected_error: Optional[str], lineno: int) -> None:
+def _test_fail(
+ path: str,
+ error: str,
+ expected_error: None | str,
+ lineno: int,
+) -> None:
if expected_error is None:
raise AssertionError(_FAIL_MSG1.format(lineno, error))
elif error not in expected_error:
raise AssertionError(_FAIL_MSG2.format(lineno, expected_error, error))
-def _construct_format_dict():
+def _construct_format_dict() -> dict[str, str]:
dct = {k.split(".")[-1]: v.replace("numpy", "numpy.typing") for
k, v in _PRECISION_DICT.items()}
@@ -193,12 +211,18 @@ def _construct_format_dict():
"float96": "numpy.floating[numpy.typing._96Bit]",
"float128": "numpy.floating[numpy.typing._128Bit]",
"float256": "numpy.floating[numpy.typing._256Bit]",
- "complex64": "numpy.complexfloating[numpy.typing._32Bit, numpy.typing._32Bit]",
- "complex128": "numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit]",
- "complex160": "numpy.complexfloating[numpy.typing._80Bit, numpy.typing._80Bit]",
- "complex192": "numpy.complexfloating[numpy.typing._96Bit, numpy.typing._96Bit]",
- "complex256": "numpy.complexfloating[numpy.typing._128Bit, numpy.typing._128Bit]",
- "complex512": "numpy.complexfloating[numpy.typing._256Bit, numpy.typing._256Bit]",
+ "complex64": ("numpy.complexfloating"
+ "[numpy.typing._32Bit, numpy.typing._32Bit]"),
+ "complex128": ("numpy.complexfloating"
+ "[numpy.typing._64Bit, numpy.typing._64Bit]"),
+ "complex160": ("numpy.complexfloating"
+ "[numpy.typing._80Bit, numpy.typing._80Bit]"),
+ "complex192": ("numpy.complexfloating"
+ "[numpy.typing._96Bit, numpy.typing._96Bit]"),
+ "complex256": ("numpy.complexfloating"
+ "[numpy.typing._128Bit, numpy.typing._128Bit]"),
+ "complex512": ("numpy.complexfloating"
+ "[numpy.typing._256Bit, numpy.typing._256Bit]"),
"ubyte": f"numpy.unsignedinteger[{dct['_NBitByte']}]",
"ushort": f"numpy.unsignedinteger[{dct['_NBitShort']}]",
@@ -217,9 +241,14 @@ def _construct_format_dict():
"single": f"numpy.floating[{dct['_NBitSingle']}]",
"double": f"numpy.floating[{dct['_NBitDouble']}]",
"longdouble": f"numpy.floating[{dct['_NBitLongDouble']}]",
- "csingle": f"numpy.complexfloating[{dct['_NBitSingle']}, {dct['_NBitSingle']}]",
- "cdouble": f"numpy.complexfloating[{dct['_NBitDouble']}, {dct['_NBitDouble']}]",
- "clongdouble": f"numpy.complexfloating[{dct['_NBitLongDouble']}, {dct['_NBitLongDouble']}]",
+ "csingle": ("numpy.complexfloating"
+ f"[{dct['_NBitSingle']}, {dct['_NBitSingle']}]"),
+ "cdouble": ("numpy.complexfloating"
+ f"[{dct['_NBitDouble']}, {dct['_NBitDouble']}]"),
+ "clongdouble": (
+ "numpy.complexfloating"
+ f"[{dct['_NBitLongDouble']}, {dct['_NBitLongDouble']}]"
+ ),
# numpy.typing
"_NBitInt": dct['_NBitInt'],
@@ -231,14 +260,16 @@ def _construct_format_dict():
#: A dictionary with all supported format keys (as keys)
#: and matching values
-FORMAT_DICT: Dict[str, str] = _construct_format_dict()
+FORMAT_DICT: dict[str, str] = _construct_format_dict()
-def _parse_reveals(file: IO[str]) -> List[str]:
- """Extract and parse all ``" # E: "`` comments from the passed file-like object.
+def _parse_reveals(file: IO[str]) -> list[str]:
+ """Extract and parse all ``" # E: "`` comments from the passed
+ file-like object.
- All format keys will be substituted for their respective value from `FORMAT_DICT`,
- *e.g.* ``"{float64}"`` becomes ``"numpy.floating[numpy.typing._64Bit]"``.
+ All format keys will be substituted for their respective value
+ from `FORMAT_DICT`, *e.g.* ``"{float64}"`` becomes
+ ``"numpy.floating[numpy.typing._64Bit]"``.
"""
string = file.read().replace("*", "")
@@ -250,7 +281,8 @@ def _parse_reveals(file: IO[str]) -> List[str]:
# there is the risk of accidentally grabbing dictionaries and sets
key_set = set(re.findall(r"\{(.*?)\}", comments))
kwargs = {
- k: FORMAT_DICT.get(k, f"<UNRECOGNIZED FORMAT KEY {k!r}>") for k in key_set
+ k: FORMAT_DICT.get(k, f"<UNRECOGNIZED FORMAT KEY {k!r}>") for
+ k in key_set
}
fmt_str = comments.format(**kwargs)
@@ -260,7 +292,10 @@ def _parse_reveals(file: IO[str]) -> List[str]:
@pytest.mark.slow
@pytest.mark.skipif(NO_MYPY, reason="Mypy is not installed")
@pytest.mark.parametrize("path", get_test_cases(REVEAL_DIR))
-def test_reveal(path):
+def test_reveal(path: str) -> None:
+ """Validate that mypy correctly infers the return-types of
+ the expressions in `path`.
+ """
__tracebackhide__ = True
with open(path) as fin:
@@ -290,18 +325,33 @@ Observed reveal: {!r}
"""
-def _test_reveal(path: str, reveal: str, expected_reveal: str, lineno: int) -> None:
+def _test_reveal(
+ path: str,
+ reveal: str,
+ expected_reveal: str,
+ lineno: int,
+) -> None:
+ """Error-reporting helper function for `test_reveal`."""
if reveal not in expected_reveal:
- raise AssertionError(_REVEAL_MSG.format(lineno, expected_reveal, reveal))
+ raise AssertionError(
+ _REVEAL_MSG.format(lineno, expected_reveal, reveal)
+ )
@pytest.mark.slow
@pytest.mark.skipif(NO_MYPY, reason="Mypy is not installed")
@pytest.mark.parametrize("path", get_test_cases(PASS_DIR))
-def test_code_runs(path):
+def test_code_runs(path: str) -> None:
+ """Validate that the code in `path` properly during runtime."""
path_without_extension, _ = os.path.splitext(path)
dirname, filename = path.split(os.sep)[-2:]
- spec = importlib.util.spec_from_file_location(f"{dirname}.{filename}", path)
+
+ spec = importlib.util.spec_from_file_location(
+ f"{dirname}.{filename}", path
+ )
+ assert spec is not None
+ assert spec.loader is not None
+
test_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(test_module)
@@ -325,7 +375,7 @@ LINENO_MAPPING = {
@pytest.mark.slow
@pytest.mark.skipif(NO_MYPY, reason="Mypy is not installed")
def test_extended_precision() -> None:
- path = os.path.join(MISC_DIR, "extended_precision.py")
+ path = os.path.join(MISC_DIR, "extended_precision.pyi")
output_mypy = OUTPUT_MYPY
assert path in output_mypy
diff --git a/pytest.ini b/pytest.ini
index dfad538c2..92ce6d6e2 100644
--- a/pytest.ini
+++ b/pytest.ini
@@ -16,3 +16,5 @@ filterwarnings =
ignore:Importing from numpy.matlib is
# pytest warning when using PYTHONOPTIMIZE
ignore:assertions not in test modules or plugins:pytest.PytestConfigWarning
+# TODO: remove below when array_api user warning is removed
+ ignore:The numpy.array_api submodule is still experimental. See NEP 47.
diff --git a/test_requirements.txt b/test_requirements.txt
index 9d2da2e0d..6b6211872 100644
--- a/test_requirements.txt
+++ b/test_requirements.txt
@@ -1,7 +1,7 @@
cython==0.29.24
wheel<0.37.1
setuptools<49.2.0
-hypothesis==6.21.6
+hypothesis==6.23.0
pytest==6.2.5
pytz==2021.1
pytest-cov==2.12.1
diff --git a/tools/linter.py b/tools/linter.py
index 9d23ffb48..0031ff83a 100644
--- a/tools/linter.py
+++ b/tools/linter.py
@@ -14,6 +14,7 @@ CONFIG = os.path.join(
# computing the diff itself.
EXCLUDE = (
"numpy/typing/tests/data/",
+ "numpy/typing/_char_codes.py",
"numpy/__config__.py",
"numpy/f2py",
)