summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/FUNDING.yml2
-rw-r--r--doc/TESTS.rst.txt8
-rw-r--r--doc/source/user/basics.io.genfromtxt.rst2
-rw-r--r--doc/source/user/building.rst3
-rw-r--r--doc/source/user/c-info.beyond-basics.rst5
-rw-r--r--numpy/__init__.pyi75
-rw-r--r--numpy/core/memmap.pyi5
-rw-r--r--numpy/core/src/npymath/npy_math_internal.h.src19
-rw-r--r--numpy/distutils/fcompiler/__init__.py3
-rw-r--r--numpy/lib/scimath.py21
-rw-r--r--numpy/linalg/lapack_lite/clapack_scrub.py21
-rw-r--r--numpy/typing/tests/data/fail/memmap.py5
-rw-r--r--numpy/typing/tests/data/reveal/memmap.py16
-rw-r--r--test_requirements.txt2
14 files changed, 141 insertions, 46 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/doc/TESTS.rst.txt b/doc/TESTS.rst.txt
index ba09aa800..d048a4569 100644
--- a/doc/TESTS.rst.txt
+++ b/doc/TESTS.rst.txt
@@ -16,13 +16,7 @@ Our goal is that every module and package in NumPy
should have a thorough set of unit
tests. These tests should exercise the full functionality of a given
routine as well as its robustness to erroneous or unexpected input
-arguments. Long experience has shown that by far the best time to
-write the tests is before you write or change the code - this is
-`test-driven development
-<https://en.wikipedia.org/wiki/Test-driven_development>`__. The
-arguments for this can sound rather abstract, but we can assure you
-that you will find that writing the tests first leads to more robust
-and better designed code. Well-designed tests with good coverage make
+arguments. Well-designed tests with good coverage make
an enormous difference to the ease of refactoring. Whenever a new bug
is found in a routine, you should write a new test for that specific
case and add it to the test suite to prevent that bug from creeping
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/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/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/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/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/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/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/typing/tests/data/fail/memmap.py b/numpy/typing/tests/data/fail/memmap.py
new file mode 100644
index 000000000..434870b60
--- /dev/null
+++ b/numpy/typing/tests/data/fail/memmap.py
@@ -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/reveal/memmap.py b/numpy/typing/tests/data/reveal/memmap.py
new file mode 100644
index 000000000..c1d8edc67
--- /dev/null
+++ b/numpy/typing/tests/data/reveal/memmap.py
@@ -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/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