diff options
| -rw-r--r-- | numpy/__init__.py | 8 | ||||
| -rw-r--r-- | numpy/__init__.pyi | 87 | ||||
| -rw-r--r-- | numpy/core/_add_newdocs.py | 35 | ||||
| -rw-r--r-- | numpy/core/multiarray.py | 2 | ||||
| -rw-r--r-- | numpy/core/multiarray.pyi | 415 | ||||
| -rw-r--r-- | numpy/f2py/cfuncs.py | 153 | ||||
| -rwxr-xr-x | numpy/f2py/rules.py | 6 | ||||
| -rw-r--r-- | numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c | 2 | ||||
| -rw-r--r-- | numpy/f2py/tests/test_return_character.py | 4 | ||||
| -rw-r--r-- | numpy/f2py/tests/test_string.py | 146 | ||||
| -rw-r--r-- | numpy/lib/function_base.py | 7 | ||||
| -rw-r--r-- | numpy/lib/twodim_base.py | 37 | ||||
| -rw-r--r-- | numpy/typing/tests/data/fail/multiarray.py | 17 | ||||
| -rw-r--r-- | numpy/typing/tests/data/pass/lib_utils.py | 2 | ||||
| -rw-r--r-- | numpy/typing/tests/data/reveal/array_constructors.py | 35 | ||||
| -rw-r--r-- | numpy/typing/tests/data/reveal/arrayterator.py | 2 | ||||
| -rw-r--r-- | numpy/typing/tests/data/reveal/multiarray.py | 50 | ||||
| -rw-r--r-- | numpy/typing/tests/data/reveal/testing.py | 4 | ||||
| -rw-r--r-- | test_requirements.txt | 4 |
19 files changed, 692 insertions, 324 deletions
diff --git a/numpy/__init__.py b/numpy/__init__.py index baff5e141..8546238ec 100644 --- a/numpy/__init__.py +++ b/numpy/__init__.py @@ -383,10 +383,10 @@ else: error_message = "{}: {}".format(w[-1].category.__name__, str(w[-1].message)) msg = ( "Polyfit sanity test emitted a warning, most likely due " - "to using a buggy Accelerate backend. If you compiled " - "yourself, more information is available at " - "https://numpy.org/doc/stable/user/building.html#accelerated-blas-lapack-libraries " - "Otherwise report this to the vendor " + "to using a buggy Accelerate backend." + "\nIf you compiled yourself, more information is available at:" + "\nhttps://numpy.org/doc/stable/user/building.html#accelerated-blas-lapack-libraries" + "\nOtherwise report this to the vendor " "that provided NumPy.\n{}\n".format(error_message)) raise RuntimeError(msg) del _mac_os_check diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi index 85ab4e8d8..6e24f6bff 100644 --- a/numpy/__init__.pyi +++ b/numpy/__init__.pyi @@ -1,6 +1,8 @@ import builtins import os import sys +import mmap +import array as _array import datetime as dt from abc import abstractmethod from types import TracebackType @@ -324,6 +326,21 @@ from numpy.core.multiarray import ( asanyarray as asanyarray, ascontiguousarray as ascontiguousarray, asfortranarray as asfortranarray, + arange as arange, + busday_count as busday_count, + busday_offset as busday_offset, + compare_chararrays as compare_chararrays, + datetime_as_string as datetime_as_string, + datetime_data as datetime_data, + frombuffer as frombuffer, + fromfile as fromfile, + fromiter as fromiter, + is_busday as is_busday, + promote_types as promote_types, + seterrobj as seterrobj, + geterrobj as geterrobj, + fromstring as fromstring, + frompyfunc as frompyfunc, ) from numpy.core.numeric import ( @@ -609,10 +626,6 @@ class MachAr: ) -> None: ... def __getattr__(self, key: str) -> Any: ... -class busdaycalendar: - def __new__(cls, weekmask: Any = ..., holidays: Any = ...) -> Any: ... - def __getattr__(self, key: str) -> Any: ... - class chararray(ndarray[_ShapeType, _DType_co]): def __new__( subtype, @@ -876,46 +889,8 @@ def round(a, decimals=..., out=...): ... def round_(a, decimals=..., out=...): ... def show_config(): ... -# Placeholders for C-based functions # TODO: Sort out which parameters are positional-only -@overload -def arange(stop, dtype=..., *, like=...): ... -@overload -def arange(start, stop, step=..., dtype=..., *, like=...): ... -def busday_count( - begindates, - enddates, - weekmask=..., - holidays=..., - busdaycal=..., - out=..., -): ... -def busday_offset( - dates, - offsets, - roll=..., - weekmask=..., - holidays=..., - busdaycal=..., - out=..., -): ... -def compare_chararrays(a, b, cmp_op, rstrip): ... -def datetime_as_string(arr, unit=..., timezone=..., casting=...): ... -def datetime_data(__dtype): ... -def frombuffer(buffer, dtype=..., count=..., offset=..., *, like=...): ... -def fromfile( - file, dtype=..., count=..., sep=..., offset=..., *, like=... -): ... -def fromiter(iter, dtype, count=..., *, like=...): ... -def frompyfunc(func, nin, nout, * identity): ... -def fromstring(string, dtype=..., count=..., sep=..., *, like=...): ... -def geterrobj(): ... -def is_busday( - dates, weekmask=..., holidays=..., busdaycal=..., out=... -): ... -def nested_iters(*args, **kwargs): ... # TODO: Sort out parameters -def promote_types(type1, type2): ... -def seterrobj(errobj): ... +def nested_iters(*args, **kwargs): ... # TODO: Sort out parameters _NdArraySubClass = TypeVar("_NdArraySubClass", bound=ndarray) _DTypeScalar_co = TypeVar("_DTypeScalar_co", covariant=True, bound=generic) @@ -1626,7 +1601,18 @@ _DType_co = TypeVar("_DType_co", covariant=True, bound=dtype[Any]) # have proper shape support _ShapeType = TypeVar("_ShapeType", bound=Any) _NumberType = TypeVar("_NumberType", bound=number[Any]) -_BufferType = Union[ndarray, bytes, bytearray, memoryview] + +# There is currently no exhaustive way to type the buffer protocol, +# as it is implemented exclusivelly in the C API (python/typing#593) +_SupportsBuffer = Union[ + bytes, + bytearray, + memoryview, + _array.array[Any], + mmap.mmap, + NDArray[Any], + generic, +] _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) @@ -1668,7 +1654,7 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType_co]): cls: Type[_ArraySelf], shape: _ShapeLike, dtype: DTypeLike = ..., - buffer: _BufferType = ..., + buffer: _SupportsBuffer = ..., offset: int = ..., strides: _ShapeLike = ..., order: _OrderKACF = ..., @@ -3736,3 +3722,14 @@ class broadcast: def __next__(self) -> Tuple[Any, ...]: ... def __iter__(self: _T) -> _T: ... def reset(self) -> None: ... + +class busdaycalendar: + def __new__( + cls, + weekmask: ArrayLike = ..., + holidays: ArrayLike = ..., + ) -> busdaycalendar: ... + @property + def weekmask(self) -> NDArray[bool_]: ... + @property + def holidays(self) -> NDArray[datetime64]: ... diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py index 448f6a0c0..a29e2e8a8 100644 --- a/numpy/core/_add_newdocs.py +++ b/numpy/core/_add_newdocs.py @@ -1280,7 +1280,7 @@ add_newdoc('numpy.core.multiarray', 'set_typeDict', add_newdoc('numpy.core.multiarray', 'fromstring', """ - fromstring(string, dtype=float, count=-1, sep='', *, like=None) + fromstring(string, dtype=float, count=-1, *, sep, like=None) A new 1-D array initialized from text data in a string. @@ -1346,16 +1346,16 @@ add_newdoc('numpy.core.multiarray', 'fromstring', add_newdoc('numpy.core.multiarray', 'compare_chararrays', """ - compare_chararrays(a, b, cmp_op, rstrip) + compare_chararrays(a1, a2, cmp, rstrip) Performs element-wise comparison of two string arrays using the comparison operator specified by `cmp_op`. Parameters ---------- - a, b : array_like + a1, a2 : array_like Arrays to be compared. - cmp_op : {"<", "<=", "==", ">=", ">", "!="} + cmp : {"<", "<=", "==", ">=", ">", "!="} Type of comparison. rstrip : Boolean If True, the spaces at the end of Strings are removed before the comparison. @@ -1585,8 +1585,8 @@ add_newdoc('numpy.core.multiarray', 'arange', For integer arguments the function is equivalent to the Python built-in `range` function, but returns an ndarray rather than a list. - When using a non-integer step, such as 0.1, the results will often not - be consistent. It is better to use `numpy.linspace` for these cases. + When using a non-integer step, such as 0.1, it is often better to use + `numpy.linspace`. See the warnings section below for more information. Parameters ---------- @@ -1619,6 +1619,25 @@ add_newdoc('numpy.core.multiarray', 'arange', this rule may result in the last element of `out` being greater than `stop`. + Warnings + -------- + The length of the output might not be numerically stable. + + Another stability issue is due to the internal implementation of + `numpy.arange`. + The actual step value used to populate the array is + ``dtype(start + step) - dtype(start)`` and not `step`. Precision loss + can occur here, due to casting or due to using floating points when + `start` is much larger than `step`. This can lead to unexpected + behaviour. For example:: + + >>> np.arange(0, 5, 0.5, dtype=int) + array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + >>> np.arange(-3, 3, 0.5, dtype=int) + array([-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8]) + + In such cases, the use of `numpy.linspace` should be preferred. + See Also -------- numpy.linspace : Evenly spaced numbers with careful handling of endpoints. @@ -4475,7 +4494,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('view', add_newdoc('numpy.core.umath', 'frompyfunc', """ - frompyfunc(func, nin, nout, *[, identity]) + frompyfunc(func, /, nin, nout, *[, identity]) Takes an arbitrary Python function and returns a NumPy ufunc. @@ -4589,7 +4608,7 @@ add_newdoc('numpy.core.umath', 'geterrobj', add_newdoc('numpy.core.umath', 'seterrobj', """ - seterrobj(errobj) + seterrobj(errobj, /) Set the object that defines floating-point error handling. diff --git a/numpy/core/multiarray.py b/numpy/core/multiarray.py index 78aa7a65c..3205f4ecd 100644 --- a/numpy/core/multiarray.py +++ b/numpy/core/multiarray.py @@ -31,7 +31,7 @@ __all__ = [ 'busday_count', 'busday_offset', 'busdaycalendar', 'can_cast', 'compare_chararrays', 'concatenate', 'copyto', 'correlate', 'correlate2', 'count_nonzero', 'c_einsum', 'datetime_as_string', 'datetime_data', - 'digitize', 'dot', 'dragon4_positional', 'dragon4_scientific', 'dtype', + 'dot', 'dragon4_positional', 'dragon4_scientific', 'dtype', 'empty', 'empty_like', 'error', 'flagsobj', 'flatiter', 'format_longfloat', 'frombuffer', 'fromfile', 'fromiter', 'fromstring', 'inner', 'interp', 'interp_complex', 'is_busday', 'lexsort', diff --git a/numpy/core/multiarray.pyi b/numpy/core/multiarray.pyi index 30b3f416a..bc33165be 100644 --- a/numpy/core/multiarray.pyi +++ b/numpy/core/multiarray.pyi @@ -1,8 +1,13 @@ # TODO: Sort out any and all missing functions in this namespace +import os import sys +import datetime as dt from typing import ( Any, + Callable, + IO, + Iterable, Optional, overload, TypeVar, @@ -14,15 +19,24 @@ from typing import ( ) from numpy import ( + # Re-exports busdaycalendar as busdaycalendar, - ndarray, - dtype, + broadcast as broadcast, + dtype as dtype, + ndarray as ndarray, + nditer as nditer, + + # The rest + nditer, + ufunc, str_, bool_, uint8, intp, + int_, float64, timedelta64, + datetime64, generic, unsignedinteger, signedinteger, @@ -32,6 +46,7 @@ from numpy import ( _OrderCF, _CastingKind, _ModeKind, + _SupportsBuffer, ) from numpy.typing import ( @@ -53,8 +68,14 @@ from numpy.typing import ( _ArrayLikeFloat_co, _ArrayLikeComplex_co, _ArrayLikeTD64_co, + _ArrayLikeDT64_co, _ArrayLikeObject_co, + _ArrayLikeStr_co, + _ArrayLikeBytes_co, + _ScalarLike_co, _IntLike_co, + _FloatLike_co, + _TD64Like_co, ) if sys.version_info >= (3, 8): @@ -65,6 +86,7 @@ else: _SCT = TypeVar("_SCT", bound=generic) _ArrayType = TypeVar("_ArrayType", bound=NDArray[Any]) +# Subscriptable subsets of `npt.DTypeLike` and `npt.ArrayLike` _DTypeLike = Union[ dtype[_SCT], Type[_SCT], @@ -72,6 +94,31 @@ _DTypeLike = Union[ ] _ArrayLike = _NestedSequence[_SupportsArray[dtype[_SCT]]] +# Valid time units +_UnitKind = L[ + "Y", + "M", + "D", + "h", + "m", + "s", + "ms", + "us", "μs", + "ns", + "ps", + "fs", + "as", +] +_RollKind = L[ # `raise` is deliberately excluded + "nat", + "forward", + "following", + "backward", + "preceding", + "modifiedfollowing", + "modifiedpreceding", +] + __all__: List[str] ALLOW_THREADS: Final[int] # 0 or 1 (system-specific) @@ -537,3 +584,367 @@ def asfortranarray( *, like: ArrayLike = ..., ) -> NDArray[Any]: ... + +# In practice `List[Any]` is list with an int, int and a valid +# `np.seterrcall()` object +def geterrobj() -> List[Any]: ... +def seterrobj(__errobj: List[Any]) -> None: ... + +def promote_types(__type1: DTypeLike, __type2: DTypeLike) -> dtype[Any]: ... + +# `sep` is a de facto mandatory argument, as its default value is deprecated +@overload +def fromstring( + string: str | bytes, + dtype: None = ..., + count: SupportsIndex = ..., + *, + sep: str, + like: ArrayLike = ..., +) -> NDArray[float64]: ... +@overload +def fromstring( + string: str | bytes, + dtype: _DTypeLike[_SCT], + count: SupportsIndex = ..., + *, + sep: str, + like: ArrayLike = ..., +) -> NDArray[_SCT]: ... +@overload +def fromstring( + string: str | bytes, + dtype: DTypeLike, + count: SupportsIndex = ..., + *, + sep: str, + like: ArrayLike = ..., +) -> NDArray[Any]: ... + +def frompyfunc( + __func: Callable[..., Any], + nin: SupportsIndex, + nout: SupportsIndex, + *, + identity: Any = ..., +) -> ufunc: ... + +@overload +def fromfile( + file: str | bytes | os.PathLike[Any] | IO[Any], + dtype: None = ..., + count: SupportsIndex = ..., + sep: str = ..., + offset: SupportsIndex = ..., + *, + like: ArrayLike = ..., +) -> NDArray[float64]: ... +@overload +def fromfile( + file: str | bytes | os.PathLike[Any] | IO[Any], + dtype: _DTypeLike[_SCT], + count: SupportsIndex = ..., + sep: str = ..., + offset: SupportsIndex = ..., + *, + like: ArrayLike = ..., +) -> NDArray[_SCT]: ... +@overload +def fromfile( + file: str | bytes | os.PathLike[Any] | IO[Any], + dtype: DTypeLike, + count: SupportsIndex = ..., + sep: str = ..., + offset: SupportsIndex = ..., + *, + like: ArrayLike = ..., +) -> NDArray[Any]: ... + +@overload +def fromiter( + iter: Iterable[Any], + dtype: _DTypeLike[_SCT], + count: SupportsIndex = ..., + *, + like: ArrayLike = ..., +) -> NDArray[_SCT]: ... +@overload +def fromiter( + iter: Iterable[Any], + dtype: DTypeLike, + count: SupportsIndex = ..., + *, + like: ArrayLike = ..., +) -> NDArray[Any]: ... + +@overload +def frombuffer( + buffer: _SupportsBuffer, + dtype: None = ..., + count: SupportsIndex = ..., + offset: SupportsIndex = ..., + *, + like: ArrayLike = ..., +) -> NDArray[float64]: ... +@overload +def frombuffer( + buffer: _SupportsBuffer, + dtype: _DTypeLike[_SCT], + count: SupportsIndex = ..., + offset: SupportsIndex = ..., + *, + like: ArrayLike = ..., +) -> NDArray[_SCT]: ... +@overload +def frombuffer( + buffer: _SupportsBuffer, + dtype: DTypeLike, + count: SupportsIndex = ..., + offset: SupportsIndex = ..., + *, + like: ArrayLike = ..., +) -> NDArray[Any]: ... + +@overload +def arange( # type: ignore[misc] + __stop: _IntLike_co, + *, + dtype: None = ..., + like: ArrayLike = ..., +) -> NDArray[signedinteger[Any]]: ... +@overload +def arange( # type: ignore[misc] + start: _IntLike_co, + stop: _IntLike_co, + step: _IntLike_co = ..., + dtype: None = ..., + *, + like: ArrayLike = ..., +) -> NDArray[signedinteger[Any]]: ... +@overload +def arange( # type: ignore[misc] + __stop: _FloatLike_co, + *, + dtype: None = ..., + like: ArrayLike = ..., +) -> NDArray[floating[Any]]: ... +@overload +def arange( # type: ignore[misc] + start: _FloatLike_co, + stop: _FloatLike_co, + step: _FloatLike_co = ..., + dtype: None = ..., + *, + like: ArrayLike = ..., +) -> NDArray[floating[Any]]: ... +@overload +def arange( + __stop: _TD64Like_co, + *, + dtype: None = ..., + like: ArrayLike = ..., +) -> NDArray[timedelta64]: ... +@overload +def arange( + start: _TD64Like_co, + stop: _TD64Like_co, + step: _TD64Like_co = ..., + dtype: None = ..., + *, + like: ArrayLike = ..., +) -> NDArray[timedelta64]: ... +@overload +def arange( # both start and stop must always be specified for datetime64 + start: datetime64, + stop: datetime64, + step: datetime64 = ..., + dtype: None = ..., + *, + like: ArrayLike = ..., +) -> NDArray[datetime64]: ... +@overload +def arange( + __stop: Any, + *, + dtype: _DTypeLike[_SCT], + like: ArrayLike = ..., +) -> NDArray[_SCT]: ... +@overload +def arange( + start: Any, + stop: Any, + step: Any = ..., + dtype: _DTypeLike[_SCT] = ..., + *, + like: ArrayLike = ..., +) -> NDArray[_SCT]: ... +@overload +def arange( + __stop: Any, + *, + dtype: DTypeLike, + like: ArrayLike = ..., +) -> NDArray[Any]: ... +@overload +def arange( + start: Any, + stop: Any, + step: Any = ..., + dtype: DTypeLike = ..., + *, + like: ArrayLike = ..., +) -> NDArray[Any]: ... + +def datetime_data( + __dtype: str | _DTypeLike[datetime64] | _DTypeLike[timedelta64], +) -> Tuple[str, int]: ... + +# The datetime functions perform unsafe casts to `datetime64[D]`, +# so a lot of different argument types are allowed here + +@overload +def busday_count( # type: ignore[misc] + begindates: _ScalarLike_co, + enddates: _ScalarLike_co, + weekmask: ArrayLike = ..., + holidays: None | ArrayLike = ..., + busdaycal: None | busdaycalendar = ..., + out: None = ..., +) -> int_: ... +@overload +def busday_count( # type: ignore[misc] + begindates: ArrayLike, + enddates: ArrayLike, + weekmask: ArrayLike = ..., + holidays: None | ArrayLike = ..., + busdaycal: None | busdaycalendar = ..., + out: None = ..., +) -> NDArray[int_]: ... +@overload +def busday_count( + begindates: ArrayLike, + enddates: ArrayLike, + weekmask: ArrayLike = ..., + holidays: None | ArrayLike = ..., + busdaycal: None | busdaycalendar = ..., + out: _ArrayType = ..., +) -> _ArrayType: ... + +# `roll="raise"` is (more or less?) equivalent to `casting="safe"` +@overload +def busday_offset( # type: ignore[misc] + dates: datetime64, + offsets: _TD64Like_co, + roll: L["raise"] = ..., + weekmask: ArrayLike = ..., + holidays: None | ArrayLike = ..., + busdaycal: None | busdaycalendar = ..., + out: None = ..., +) -> datetime64: ... +@overload +def busday_offset( # type: ignore[misc] + dates: _ArrayLike[datetime64], + offsets: _ArrayLikeTD64_co, + roll: L["raise"] = ..., + weekmask: ArrayLike = ..., + holidays: None | ArrayLike = ..., + busdaycal: None | busdaycalendar = ..., + out: None = ..., +) -> NDArray[datetime64]: ... +@overload +def busday_offset( # type: ignore[misc] + dates: _ArrayLike[datetime64], + offsets: _ArrayLike[timedelta64], + roll: L["raise"] = ..., + weekmask: ArrayLike = ..., + holidays: None | ArrayLike = ..., + busdaycal: None | busdaycalendar = ..., + out: _ArrayType = ..., +) -> _ArrayType: ... +@overload +def busday_offset( # type: ignore[misc] + dates: _ScalarLike_co, + offsets: _ScalarLike_co, + roll: _RollKind, + weekmask: ArrayLike = ..., + holidays: None | ArrayLike = ..., + busdaycal: None | busdaycalendar = ..., + out: None = ..., +) -> datetime64: ... +@overload +def busday_offset( # type: ignore[misc] + dates: ArrayLike, + offsets: ArrayLike, + roll: _RollKind, + weekmask: ArrayLike = ..., + holidays: None | ArrayLike = ..., + busdaycal: None | busdaycalendar = ..., + out: None = ..., +) -> NDArray[datetime64]: ... +@overload +def busday_offset( + dates: ArrayLike, + offsets: ArrayLike, + roll: _RollKind, + weekmask: ArrayLike = ..., + holidays: None | ArrayLike = ..., + busdaycal: None | busdaycalendar = ..., + out: _ArrayType = ..., +) -> _ArrayType: ... + +@overload +def is_busday( # type: ignore[misc] + dates: _ScalarLike_co, + weekmask: ArrayLike = ..., + holidays: None | ArrayLike = ..., + busdaycal: None | busdaycalendar = ..., + out: None = ..., +) -> bool_: ... +@overload +def is_busday( # type: ignore[misc] + dates: ArrayLike, + weekmask: ArrayLike = ..., + holidays: None | ArrayLike = ..., + busdaycal: None | busdaycalendar = ..., + out: None = ..., +) -> NDArray[bool_]: ... +@overload +def is_busday( + dates: ArrayLike, + weekmask: ArrayLike = ..., + holidays: None | ArrayLike = ..., + busdaycal: None | busdaycalendar = ..., + out: _ArrayType = ..., +) -> _ArrayType: ... + +@overload +def datetime_as_string( # type: ignore[misc] + arr: datetime64, + unit: None | L["auto"] | _UnitKind = ..., + timezone: L["naive", "UTC", "local"] | dt.tzinfo = ..., + casting: _CastingKind = ..., +) -> str_: ... +@overload +def datetime_as_string( + arr: _ArrayLikeDT64_co, + unit: None | L["auto"] | _UnitKind = ..., + timezone: L["naive", "UTC", "local"] | dt.tzinfo = ..., + casting: _CastingKind = ..., +) -> NDArray[str_]: ... + +@overload +def compare_chararrays( + a1: _ArrayLikeStr_co, + a2: _ArrayLikeStr_co, + cmp: L["<", "<=", "==", ">=", ">", "!="], + rstrip: bool, +) -> NDArray[bool_]: ... +@overload +def compare_chararrays( + a1: _ArrayLikeBytes_co, + a2: _ArrayLikeBytes_co, + cmp: L["<", "<=", "==", ">=", ">", "!="], + rstrip: bool, +) -> NDArray[bool_]: ... + +def add_docstring(__obj: Callable[..., Any], __docstring: str) -> None: ... diff --git a/numpy/f2py/cfuncs.py b/numpy/f2py/cfuncs.py index 60685be8a..f403a66b5 100644 --- a/numpy/f2py/cfuncs.py +++ b/numpy/f2py/cfuncs.py @@ -469,7 +469,7 @@ cppmacros['MEMCOPY'] = """\ """ cppmacros['STRINGMALLOC'] = """\ #define STRINGMALLOC(str,len)\\ - if ((str = (string)malloc(len+1)) == NULL) {\\ + if ((str = (string)malloc(sizeof(char)*(len+1))) == NULL) {\\ PyErr_SetString(PyExc_MemoryError, \"out of memory\");\\ goto capi_fail;\\ } else {\\ @@ -481,18 +481,18 @@ cppmacros['STRINGFREE'] = """\ """ needs['STRINGCOPYN'] = ['string.h', 'FAILNULL'] cppmacros['STRINGCOPYN'] = """\ -/* -STRINGCOPYN copies N bytes. - -`to` and `from` buffers must have sizes of at least N bytes. -*/ -#define STRINGCOPYN(to,from,N) \\ +#define STRINGCOPYN(to,from,buf_size) \\ do { \\ - int _m = (N); \\ + int _m = (buf_size); \\ char *_to = (to); \\ char *_from = (from); \\ FAILNULL(_to); FAILNULL(_from); \\ - (void)strncpy(_to, _from, _m); \\ + (void)strncpy(_to, _from, sizeof(char)*_m); \\ + _to[_m-1] = '\\0'; \\ + /* Padding with spaces instead of nulls */ \\ + for (_m -= 2; _m >= 0 && _to[_m] == '\\0'; _m--) { \\ + _to[_m] = ' '; \\ + } \\ } while (0) """ needs['STRINGCOPY'] = ['string.h', 'FAILNULL'] @@ -623,121 +623,71 @@ static int *nextforcomb(void) { }""" needs['try_pyarr_from_string'] = ['STRINGCOPYN', 'PRINTPYOBJERR', 'string'] cfuncs['try_pyarr_from_string'] = """\ -/* - try_pyarr_from_string copies str[:len(obj)] to the data of an `ndarray`. - - If obj is an `ndarray`, it is assumed to be contiguous. - - If the specified len==-1, str must be null-terminated. -*/ -static int try_pyarr_from_string(PyObject *obj, - const string str, const int len) { -#ifdef DEBUGCFUNCS -fprintf(stderr, "try_pyarr_from_string(str='%s', len=%d, obj=%p)\\n", - (char*)str,len, obj); -#endif - if (PyArray_Check(obj)) { - PyArrayObject *arr = (PyArrayObject *)obj; - assert(ISCONTIGUOUS(arr)); - string buf = PyArray_DATA(arr); - npy_intp n = len; - if (n == -1) { - /* Assuming null-terminated str. */ - n = strlen(str); - } - if (n > PyArray_NBYTES(arr)) { - n = PyArray_NBYTES(arr); - } - STRINGCOPYN(buf, str, n); - return 1; - } +static int try_pyarr_from_string(PyObject *obj,const string str) { + PyArrayObject *arr = NULL; + if (PyArray_Check(obj) && (!((arr = (PyArrayObject *)obj) == NULL))) + { STRINGCOPYN(PyArray_DATA(arr),str,PyArray_NBYTES(arr)); } + return 1; capi_fail: PRINTPYOBJERR(obj); - PyErr_SetString(#modulename#_error, \"try_pyarr_from_string failed\"); + PyErr_SetString(#modulename#_error,\"try_pyarr_from_string failed\"); return 0; } """ needs['string_from_pyobj'] = ['string', 'STRINGMALLOC', 'STRINGCOPYN'] cfuncs['string_from_pyobj'] = """\ -/* - Create a new string buffer `str` of at most length `len` from a - Python string-like object `obj`. - - The string buffer has given size (len) or the size of inistr when len==-1. - - The string buffer is null-terminated. - */ static int -string_from_pyobj(string *str, int *len, const string inistr, PyObject *obj, - const char *errmess) +string_from_pyobj(string *str,int *len,const string inistr,PyObject *obj,const char *errmess) { + PyArrayObject *arr = NULL; PyObject *tmp = NULL; - string buf = NULL; - npy_intp n = -1; #ifdef DEBUGCFUNCS -fprintf(stderr,\"string_from_pyobj(str='%s',len=%d,inistr='%s',obj=%p)\\n\", - (char*)str, *len, (char *)inistr, obj); +fprintf(stderr,\"string_from_pyobj(str='%s',len=%d,inistr='%s',obj=%p)\\n\",(char*)str,*len,(char *)inistr,obj); #endif if (obj == Py_None) { - n = strlen(inistr); - buf = inistr; + if (*len == -1) + *len = strlen(inistr); /* Will this cause problems? */ + STRINGMALLOC(*str,*len); + STRINGCOPYN(*str,inistr,*len+1); + return 1; } - else if (PyArray_Check(obj)) { - PyArrayObject *arr = (PyArrayObject *)obj; + if (PyArray_Check(obj)) { + if ((arr = (PyArrayObject *)obj) == NULL) + goto capi_fail; if (!ISCONTIGUOUS(arr)) { - PyErr_SetString(PyExc_ValueError, - \"array object is non-contiguous.\"); + PyErr_SetString(PyExc_ValueError,\"array object is non-contiguous.\"); goto capi_fail; } - n = PyArray_NBYTES(arr); - buf = PyArray_DATA(arr); + if (*len == -1) + *len = (PyArray_ITEMSIZE(arr))*PyArray_SIZE(arr); + STRINGMALLOC(*str,*len); + STRINGCOPYN(*str,PyArray_DATA(arr),*len+1); + return 1; + } + if (PyBytes_Check(obj)) { + tmp = obj; + Py_INCREF(tmp); + } + else if (PyUnicode_Check(obj)) { + tmp = PyUnicode_AsASCIIString(obj); } else { - if (PyBytes_Check(obj)) { - tmp = obj; - Py_INCREF(tmp); - } - else if (PyUnicode_Check(obj)) { - tmp = PyUnicode_AsASCIIString(obj); + PyObject *tmp2; + tmp2 = PyObject_Str(obj); + if (tmp2) { + tmp = PyUnicode_AsASCIIString(tmp2); + Py_DECREF(tmp2); } else { - PyObject *tmp2; - tmp2 = PyObject_Str(obj); - if (tmp2) { - tmp = PyUnicode_AsASCIIString(tmp2); - Py_DECREF(tmp2); - } - else { - tmp = NULL; - } + tmp = NULL; } - if (tmp == NULL) goto capi_fail; - n = PyBytes_GET_SIZE(tmp); - buf = PyBytes_AS_STRING(tmp); } - if (*len == -1) { - /* TODO: change the type of `len` so that we can remove this */ - if (n > NPY_MAX_INT) { - PyErr_SetString(PyExc_OverflowError, - "object too large for a 32-bit int"); - goto capi_fail; - } - *len = n; - } - else if (*len < n) { - /* discard the last (len-n) bytes of input buf */ - n = *len; - } - if (n < 0 || *len < 0 || buf == NULL) { - goto capi_fail; - } - STRINGMALLOC(*str, *len); // *str is allocated with size (*len + 1) - if (n < *len) { - /* Pad fixed-width string with nulls */ - memset(*str + n, '\\0', *len - n); - } - STRINGCOPYN(*str, buf, n); - Py_XDECREF(tmp); + if (tmp == NULL) goto capi_fail; + if (*len == -1) + *len = PyBytes_GET_SIZE(tmp); + STRINGMALLOC(*str,*len); + STRINGCOPYN(*str,PyBytes_AS_STRING(tmp),*len+1); + Py_DECREF(tmp); return 1; capi_fail: Py_XDECREF(tmp); @@ -752,6 +702,7 @@ capi_fail: } """ + needs['char_from_pyobj'] = ['int_from_pyobj'] cfuncs['char_from_pyobj'] = """\ static int diff --git a/numpy/f2py/rules.py b/numpy/f2py/rules.py index f01b2bcfa..63e47baa2 100755 --- a/numpy/f2py/rules.py +++ b/numpy/f2py/rules.py @@ -561,8 +561,7 @@ rout_rules = [ '\tint #name#_return_value_len = 0;'], 'callfortran':'#name#_return_value,#name#_return_value_len,', 'callfortranroutine':['\t#name#_return_value_len = #rlength#;', - '\tif ((#name#_return_value = (string)malloc(' - '#name#_return_value_len+1) == NULL) {', + '\tif ((#name#_return_value = (string)malloc(sizeof(char)*(#name#_return_value_len+1))) == NULL) {', '\t\tPyErr_SetString(PyExc_MemoryError, \"out of memory\");', '\t\tf2py_success = 0;', '\t} else {', @@ -964,8 +963,7 @@ if (#varname#_cb.capi==Py_None) { 'args_capi': {isrequired: ',&#varname#_capi'}, 'keys_capi': {isoptional: ',&#varname#_capi'}, 'pyobjfrom': {isintent_inout: '''\ -\tf2py_success = try_pyarr_from_#ctype#(#varname#_capi, #varname#, -\t slen(#varname#)); +\tf2py_success = try_pyarr_from_#ctype#(#varname#_capi,#varname#); \tif (f2py_success) {'''}, 'closepyobjfrom': {isintent_inout: '\t} /*if (f2py_success) of #varname# pyobjfrom*/'}, 'need': {isintent_inout: 'try_pyarr_from_#ctype#'}, diff --git a/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c b/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c index fe21d4b9b..0411b62e0 100644 --- a/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c +++ b/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c @@ -93,7 +93,7 @@ static PyObject *f2py_rout_wrap_attrs(PyObject *capi_self, PyObject *strides = NULL; char s[100]; int i; - memset(s,0,100); + memset(s,0,100*sizeof(char)); if (!PyArg_ParseTuple(capi_args,"O!|:wrap.attrs", &PyArray_Type,&arr_capi)) return NULL; diff --git a/numpy/f2py/tests/test_return_character.py b/numpy/f2py/tests/test_return_character.py index dc524e60c..429e69bb4 100644 --- a/numpy/f2py/tests/test_return_character.py +++ b/numpy/f2py/tests/test_return_character.py @@ -24,8 +24,8 @@ class TestReturnCharacter(util.F2PyTest): assert_(t(23) == b'23 ', repr(t(23))) assert_(t('123456789abcdef') == b'123456789a') elif tname in ['t5', 's5']: - assert_(t(23) == b'23', repr(t(23))) - assert_(t('ab') == b'ab', repr(t('ab'))) + assert_(t(23) == b'23 ', repr(t(23))) + assert_(t('ab') == b'ab ', repr(t('ab'))) assert_(t('123456789abcdef') == b'12345') else: raise NotImplementedError diff --git a/numpy/f2py/tests/test_string.py b/numpy/f2py/tests/test_string.py index 1530c58f6..e3ec96af9 100644 --- a/numpy/f2py/tests/test_string.py +++ b/numpy/f2py/tests/test_string.py @@ -1,6 +1,6 @@ import os import pytest -import textwrap + from numpy.testing import assert_array_equal import numpy as np from . import util @@ -9,156 +9,14 @@ from . import util def _path(*a): return os.path.join(*((os.path.dirname(__file__),) + a)) - class TestString(util.F2PyTest): sources = [_path('src', 'string', 'char.f90')] @pytest.mark.slow def test_char(self): strings = np.array(['ab', 'cd', 'ef'], dtype='c').T - inp, out = self.module.char_test.change_strings(strings, - strings.shape[1]) + inp, out = self.module.char_test.change_strings(strings, strings.shape[1]) assert_array_equal(inp, strings) expected = strings.copy() expected[1, :] = 'AAA' assert_array_equal(out, expected) - - -class TestDocStringArguments(util.F2PyTest): - suffix = '.f' - - code = """ -C FILE: STRING.F - SUBROUTINE FOO(A,B,C,D) - CHARACTER*5 A, B - CHARACTER*(*) C,D -Cf2py intent(in) a,c -Cf2py intent(inout) b,d - PRINT*, "A=",A - PRINT*, "B=",B - PRINT*, "C=",C - PRINT*, "D=",D - PRINT*, "CHANGE A,B,C,D" - A(1:1) = 'A' - B(1:1) = 'B' - C(1:1) = 'C' - D(1:1) = 'D' - PRINT*, "A=",A - PRINT*, "B=",B - PRINT*, "C=",C - PRINT*, "D=",D - END -C END OF FILE STRING.F - """ - - def test_example(self): - a = np.array(b'123\0\0') - b = np.array(b'123\0\0') - c = np.array(b'123') - d = np.array(b'123') - - self.module.foo(a, b, c, d) - - assert a.tobytes() == b'123\0\0' - assert b.tobytes() == b'B23\0\0', (b.tobytes(),) - assert c.tobytes() == b'123' - assert d.tobytes() == b'D23' - - -class TestFixedString(util.F2PyTest): - suffix = '.f90' - - code = textwrap.dedent(""" - function sint(s) result(i) - implicit none - character(len=*) :: s - integer :: j, i - i = 0 - do j=1, len(s) - i = i + ichar(s(j:j)) * 10 ** (j - 1) - end do - return - end function sint - - function test_in_bytes4(a) result (i) - implicit none - integer :: sint - character(len=4) :: a - integer :: i - i = sint(a) - a(1:1) = 'A' - return - end function test_in_bytes4 - - function test_inout_bytes4(a) result (i) - implicit none - integer :: sint - character(len=4), intent(inout) :: a - integer :: i - if (ichar(a(1:1)).ne.0) then - a(1:1) = 'E' - endif - i = sint(a) - return - end function test_inout_bytes4 - """) - - @staticmethod - def _sint(s, start=0, end=None): - """Return the content of a string buffer as integer value. - - For example: - _sint('1234') -> 4321 - _sint('123A') -> 17321 - """ - if isinstance(s, np.ndarray): - s = s.tobytes() - elif isinstance(s, str): - s = s.encode() - assert isinstance(s, bytes) - if end is None: - end = len(s) - i = 0 - for j in range(start, min(end, len(s))): - i += s[j] * 10 ** j - return i - - def _get_input(self, intent='in'): - if intent in ['in']: - yield '' - yield '1' - yield '1234' - yield '12345' - yield b'' - yield b'\0' - yield b'1' - yield b'\01' - yield b'1\0' - yield b'1234' - yield b'12345' - yield np.ndarray((), np.bytes_, buffer=b'') # array(b'', dtype='|S0') - yield np.array(b'') # array(b'', dtype='|S1') - yield np.array(b'\0') - yield np.array(b'1') - yield np.array(b'1\0') - yield np.array(b'\01') - yield np.array(b'1234') - yield np.array(b'123\0') - yield np.array(b'12345') - - def test_intent_in(self): - for s in self._get_input(): - r = self.module.test_in_bytes4(s) - # also checks that s is not changed inplace - expected = self._sint(s, end=4) - assert r == expected, (s) - - def test_intent_inout(self): - for s in self._get_input(intent='inout'): - rest = self._sint(s, start=4) - r = self.module.test_inout_bytes4(s) - expected = self._sint(s, end=4) - assert r == expected - - # check that the rest of input string is preserved - assert rest == self._sint(s, start=4) diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index 783d45c2f..2e9ae6644 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -88,8 +88,11 @@ def rot90(m, k=1, axes=(0, 1)): Notes ----- - rot90(m, k=1, axes=(1,0)) is the reverse of rot90(m, k=1, axes=(0,1)) - rot90(m, k=1, axes=(1,0)) is equivalent to rot90(m, k=-1, axes=(0,1)) + ``rot90(m, k=1, axes=(1,0))`` is the reverse of + ``rot90(m, k=1, axes=(0,1))`` + + ``rot90(m, k=1, axes=(1,0))`` is equivalent to + ``rot90(m, k=-1, axes=(0,1))`` Examples -------- diff --git a/numpy/lib/twodim_base.py b/numpy/lib/twodim_base.py index ac5fe1c6b..83c028061 100644 --- a/numpy/lib/twodim_base.py +++ b/numpy/lib/twodim_base.py @@ -439,10 +439,12 @@ def tril(m, k=0): Lower triangle of an array. Return a copy of an array with elements above the `k`-th diagonal zeroed. + For arrays with ``ndim`` exceeding 2, `tril` will apply to the final two + axes. Parameters ---------- - m : array_like, shape (M, N) + m : array_like, shape (..., M, N) Input array. k : int, optional Diagonal above which to zero elements. `k = 0` (the default) is the @@ -450,7 +452,7 @@ def tril(m, k=0): Returns ------- - tril : ndarray, shape (M, N) + tril : ndarray, shape (..., M, N) Lower triangle of `m`, of same shape and data-type as `m`. See Also @@ -465,6 +467,20 @@ def tril(m, k=0): [ 7, 8, 0], [10, 11, 12]]) + >>> np.tril(np.arange(3*4*5).reshape(3, 4, 5)) + array([[[ 0, 0, 0, 0, 0], + [ 5, 6, 0, 0, 0], + [10, 11, 12, 0, 0], + [15, 16, 17, 18, 0]], + [[20, 0, 0, 0, 0], + [25, 26, 0, 0, 0], + [30, 31, 32, 0, 0], + [35, 36, 37, 38, 0]], + [[40, 0, 0, 0, 0], + [45, 46, 0, 0, 0], + [50, 51, 52, 0, 0], + [55, 56, 57, 58, 0]]]) + """ m = asanyarray(m) mask = tri(*m.shape[-2:], k=k, dtype=bool) @@ -478,7 +494,8 @@ def triu(m, k=0): Upper triangle of an array. Return a copy of an array with the elements below the `k`-th diagonal - zeroed. + zeroed. For arrays with ``ndim`` exceeding 2, `triu` will apply to the final + two axes. Please refer to the documentation for `tril` for further details. @@ -494,6 +511,20 @@ def triu(m, k=0): [ 0, 8, 9], [ 0, 0, 12]]) + >>> np.triu(np.arange(3*4*5).reshape(3, 4, 5)) + array([[[ 0, 1, 2, 3, 4], + [ 0, 6, 7, 8, 9], + [ 0, 0, 12, 13, 14], + [ 0, 0, 0, 18, 19]], + [[20, 21, 22, 23, 24], + [ 0, 26, 27, 28, 29], + [ 0, 0, 32, 33, 34], + [ 0, 0, 0, 38, 39]], + [[40, 41, 42, 43, 44], + [ 0, 46, 47, 48, 49], + [ 0, 0, 52, 53, 54], + [ 0, 0, 0, 58, 59]]]) + """ m = asanyarray(m) mask = tri(*m.shape[-2:], k=k-1, dtype=bool) diff --git a/numpy/typing/tests/data/fail/multiarray.py b/numpy/typing/tests/data/fail/multiarray.py index e931e9d5c..50361ec43 100644 --- a/numpy/typing/tests/data/fail/multiarray.py +++ b/numpy/typing/tests/data/fail/multiarray.py @@ -10,8 +10,12 @@ AR_i8: npt.NDArray[np.int64] AR_f8: npt.NDArray[np.float64] AR_M: npt.NDArray[np.datetime64] +M: np.datetime64 + AR_LIKE_f: List[float] +def func(a: int) -> None: ... + np.where(AR_b, 1) # E: No overload variant np.can_cast(AR_f8, 1) # E: incompatible type @@ -30,3 +34,16 @@ np.unpackbits(AR_u1, bitorder=">") # E: incompatible type np.shares_memory(1, 1, max_work=i8) # E: incompatible type np.may_share_memory(1, 1, max_work=i8) # E: incompatible type + +np.arange(M) # E: No overload variant +np.arange(stop=10) # E: No overload variant + +np.datetime_data(int) # E: incompatible type + +np.busday_offset("2012", 10) # E: incompatible type + +np.datetime_as_string("2012") # E: incompatible type + +np.compare_chararrays("a", b"a", "==", False) # E: No overload variant + +np.add_docstring(func, None) # E: incompatible type diff --git a/numpy/typing/tests/data/pass/lib_utils.py b/numpy/typing/tests/data/pass/lib_utils.py index c602923d9..0a15dad22 100644 --- a/numpy/typing/tests/data/pass/lib_utils.py +++ b/numpy/typing/tests/data/pass/lib_utils.py @@ -6,7 +6,7 @@ from typing import Any import numpy as np FILE = StringIO() -AR: np.ndarray[Any, np.dtype[np.float64]] = np.arange(10).astype(np.float64) +AR = np.arange(10, dtype=np.float64) def func(a: int) -> bool: ... diff --git a/numpy/typing/tests/data/reveal/array_constructors.py b/numpy/typing/tests/data/reveal/array_constructors.py index ed966679d..1b9006220 100644 --- a/numpy/typing/tests/data/reveal/array_constructors.py +++ b/numpy/typing/tests/data/reveal/array_constructors.py @@ -67,6 +67,41 @@ reveal_type(np.asfortranarray([1, 1.0])) # E: numpy.ndarray[Any, numpy.dtype[An reveal_type(np.asfortranarray(A, dtype=np.int64)) # E: numpy.ndarray[Any, numpy.dtype[{int64}]] reveal_type(np.asfortranarray(A, dtype='c16')) # E: numpy.ndarray[Any, numpy.dtype[Any]] +reveal_type(np.fromstring("1 1 1", sep=" ")) # E: numpy.ndarray[Any, numpy.dtype[{float64}]] +reveal_type(np.fromstring(b"1 1 1", sep=" ")) # E: numpy.ndarray[Any, numpy.dtype[{float64}]] +reveal_type(np.fromstring("1 1 1", dtype=np.int64, sep=" ")) # E: numpy.ndarray[Any, numpy.dtype[{int64}]] +reveal_type(np.fromstring(b"1 1 1", dtype=np.int64, sep=" ")) # E: numpy.ndarray[Any, numpy.dtype[{int64}]] +reveal_type(np.fromstring("1 1 1", dtype="c16", sep=" ")) # E: numpy.ndarray[Any, numpy.dtype[Any]] +reveal_type(np.fromstring(b"1 1 1", dtype="c16", sep=" ")) # E: numpy.ndarray[Any, numpy.dtype[Any]] + +reveal_type(np.fromfile("test.txt", sep=" ")) # E: numpy.ndarray[Any, numpy.dtype[{float64}]] +reveal_type(np.fromfile("test.txt", dtype=np.int64, sep=" ")) # E: numpy.ndarray[Any, numpy.dtype[{int64}]] +reveal_type(np.fromfile("test.txt", dtype="c16", sep=" ")) # E: numpy.ndarray[Any, numpy.dtype[Any]] +with open("test.txt") as f: + reveal_type(np.fromfile(f, sep=" ")) # E: numpy.ndarray[Any, numpy.dtype[{float64}]] + reveal_type(np.fromfile(b"test.txt", sep=" ")) # E: numpy.ndarray[Any, numpy.dtype[{float64}]] + reveal_type(np.fromfile(Path("test.txt"), sep=" ")) # E: numpy.ndarray[Any, numpy.dtype[{float64}]] + +reveal_type(np.fromiter("12345", np.float64)) # E: numpy.ndarray[Any, numpy.dtype[{float64}]] +reveal_type(np.fromiter("12345", float)) # E: numpy.ndarray[Any, numpy.dtype[Any]] + +reveal_type(np.frombuffer(A)) # E: numpy.ndarray[Any, numpy.dtype[{float64}]] +reveal_type(np.frombuffer(A, dtype=np.int64)) # E: numpy.ndarray[Any, numpy.dtype[{int64}]] +reveal_type(np.frombuffer(A, dtype="c16")) # E: numpy.ndarray[Any, numpy.dtype[Any]] + +reveal_type(np.arange(False, True)) # E: numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]] +reveal_type(np.arange(10)) # E: numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]] +reveal_type(np.arange(0, 10, step=2)) # E: numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]] +reveal_type(np.arange(10.0)) # E: numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]] +reveal_type(np.arange(start=0, stop=10.0)) # E: numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]] +reveal_type(np.arange(np.timedelta64(0))) # E: numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]] +reveal_type(np.arange(0, np.timedelta64(10))) # E: numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]] +reveal_type(np.arange(np.datetime64("0"), np.datetime64("10"))) # E: numpy.ndarray[Any, numpy.dtype[numpy.datetime64]] +reveal_type(np.arange(10, dtype=np.float64)) # E: numpy.ndarray[Any, numpy.dtype[{float64}]] +reveal_type(np.arange(0, 10, step=2, dtype=np.int16)) # E: numpy.ndarray[Any, numpy.dtype[{int16}]] +reveal_type(np.arange(10, dtype=int)) # E: numpy.ndarray[Any, numpy.dtype[Any]] +reveal_type(np.arange(0, 10, dtype="f8")) # E: numpy.ndarray[Any, numpy.dtype[Any]] + reveal_type(np.require(A)) # E: numpy.ndarray[Any, numpy.dtype[{float64}]] reveal_type(np.require(B)) # E: SubClass[{float64}] reveal_type(np.require(B, requirements=None)) # E: SubClass[{float64}] diff --git a/numpy/typing/tests/data/reveal/arrayterator.py b/numpy/typing/tests/data/reveal/arrayterator.py index b57861d00..ea4e75612 100644 --- a/numpy/typing/tests/data/reveal/arrayterator.py +++ b/numpy/typing/tests/data/reveal/arrayterator.py @@ -10,7 +10,7 @@ reveal_type(ar_iter.start) # E: builtins.list[builtins.int] reveal_type(ar_iter.stop) # E: builtins.list[builtins.int] reveal_type(ar_iter.step) # E: builtins.list[builtins.int] reveal_type(ar_iter.shape) # E: builtins.tuple[builtins.int] -reveal_type(ar_iter.flat) # E: 'typing.Generator[{int64}, None, None] +reveal_type(ar_iter.flat) # E: typing.Generator[{int64}, None, None] reveal_type(ar_iter.__array__()) # E: numpy.ndarray[Any, numpy.dtype[{int64}]] diff --git a/numpy/typing/tests/data/reveal/multiarray.py b/numpy/typing/tests/data/reveal/multiarray.py index 2811b1f35..cee51975e 100644 --- a/numpy/typing/tests/data/reveal/multiarray.py +++ b/numpy/typing/tests/data/reveal/multiarray.py @@ -1,17 +1,32 @@ -from typing import Any, List +from typing import Any, List, TypeVar +from pathlib import Path + import numpy as np import numpy.typing as npt +_SCT = TypeVar("_SCT", bound=np.generic, covariant=True) + +class SubClass(np.ndarray[Any, np.dtype[_SCT]]): ... + +subclass: SubClass[np.float64] + AR_f8: npt.NDArray[np.float64] AR_i8: npt.NDArray[np.int64] AR_u1: npt.NDArray[np.uint8] +AR_m: npt.NDArray[np.timedelta64] +AR_M: npt.NDArray[np.datetime64] AR_LIKE_f: List[float] AR_LIKE_i: List[int] +m: np.timedelta64 +M: np.datetime64 + b_f8 = np.broadcast(AR_f8) b_i8_f8_f8 = np.broadcast(AR_i8, AR_f8, AR_f8) +def func(a: int) -> bool: ... + reveal_type(next(b_f8)) # E: tuple[Any] reveal_type(b_f8.reset()) # E: None reveal_type(b_f8.index) # E: int @@ -75,3 +90,36 @@ reveal_type(np.shares_memory(AR_f8, AR_f8, max_work=1)) # E: bool reveal_type(np.may_share_memory(1, 2)) # E: bool reveal_type(np.may_share_memory(AR_f8, AR_f8, max_work=1)) # E: bool + +reveal_type(np.geterrobj()) # E: list[Any] + +reveal_type(np.seterrobj([8192, 521, None])) # E: None + +reveal_type(np.promote_types(np.int32, np.int64)) # E: numpy.dtype[Any] +reveal_type(np.promote_types("f4", float)) # E: numpy.dtype[Any] + +reveal_type(np.frompyfunc(func, 1, 1, identity=None)) # numpy.ufunc + +reveal_type(np.datetime_data("m8[D]")) # E: Tuple[builtins.str, builtins.int] +reveal_type(np.datetime_data(np.datetime64)) # E: Tuple[builtins.str, builtins.int] +reveal_type(np.datetime_data(np.dtype(np.timedelta64))) # E: Tuple[builtins.str, builtins.int] + +reveal_type(np.busday_count("2011-01", "2011-02")) # E: {int_} +reveal_type(np.busday_count(["2011-01"], "2011-02")) # E: numpy.ndarray[Any, numpy.dtype[{int_}]] + +reveal_type(np.busday_offset(M, m)) # E: numpy.datetime64 +reveal_type(np.busday_offset(M, 5)) # E: numpy.datetime64 +reveal_type(np.busday_offset(AR_M, m)) # E: numpy.ndarray[Any, numpy.dtype[numpy.datetime64]] +reveal_type(np.busday_offset("2011-01", "2011-02", roll="forward")) # E: numpy.datetime64 +reveal_type(np.busday_offset(["2011-01"], "2011-02", roll="forward")) # E: numpy.ndarray[Any, numpy.dtype[numpy.datetime64]] + +reveal_type(np.is_busday("2012")) # E: numpy.bool_ +reveal_type(np.is_busday(["2012"])) # E: numpy.ndarray[Any, numpy.dtype[numpy.bool_]] + +reveal_type(np.datetime_as_string(M)) # E: numpy.str_ +reveal_type(np.datetime_as_string(AR_M)) # E: numpy.ndarray[Any, numpy.dtype[numpy.str_]] + +reveal_type(np.compare_chararrays("a", "b", "!=", rstrip=False)) # E: numpy.ndarray[Any, numpy.dtype[numpy.bool_]] +reveal_type(np.compare_chararrays(b"a", b"a", "==", True)) # E: numpy.ndarray[Any, numpy.dtype[numpy.bool_]] + +reveal_type(np.add_docstring(func, "test")) # E: None diff --git a/numpy/typing/tests/data/reveal/testing.py b/numpy/typing/tests/data/reveal/testing.py index e244c225c..2b040ff60 100644 --- a/numpy/typing/tests/data/reveal/testing.py +++ b/numpy/typing/tests/data/reveal/testing.py @@ -29,8 +29,8 @@ reveal_type(np.testing.clear_and_catch_warnings(modules=[np.testing])) # E: _cl reveal_type(np.testing.clear_and_catch_warnings(True)) # E: _clear_and_catch_warnings_with_records reveal_type(np.testing.clear_and_catch_warnings(False)) # E: _clear_and_catch_warnings_without_records reveal_type(np.testing.clear_and_catch_warnings(bool_obj)) # E: clear_and_catch_warnings -reveal_type(np.testing.clear_and_catch_warnings.class_modules) # E: tuple[_importlib_modulespec.ModuleType] -reveal_type(np.testing.clear_and_catch_warnings.modules) # E: set[_importlib_modulespec.ModuleType] +reveal_type(np.testing.clear_and_catch_warnings.class_modules) # E: tuple[types.ModuleType] +reveal_type(np.testing.clear_and_catch_warnings.modules) # E: set[types.ModuleType] with np.testing.clear_and_catch_warnings(True) as c1: reveal_type(c1) # E: builtins.list[warnings.WarningMessage] diff --git a/test_requirements.txt b/test_requirements.txt index ca0edfbb4..35a78aff1 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -1,7 +1,7 @@ cython==0.29.23 wheel<0.36.3 setuptools<49.2.0 -hypothesis==6.13.14 +hypothesis==6.14.0 pytest==6.2.4 pytz==2021.1 pytest-cov==2.12.1 @@ -11,5 +11,5 @@ cffi # For testing types. Notes on the restrictions: # - Mypy relies on C API features not present in PyPy # - There is no point in installing typing_extensions without mypy -mypy==0.812; platform_python_implementation != "PyPy" +mypy==0.902; platform_python_implementation != "PyPy" typing_extensions==3.10.0.0; platform_python_implementation != "PyPy" |
