From 5ef53c6ad250eaf46739ca4d960e384e28857715 Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Thu, 14 Sep 2023 15:35:23 +0200 Subject: [PATCH 1/3] TYP: Add annotations for the py3.12 buffer protocol --- numpy/__init__.pyi | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi index 32d084b6e137..a185bfe754e3 100644 --- a/numpy/__init__.pyi +++ b/numpy/__init__.pyi @@ -1,4 +1,5 @@ import builtins +import sys import os import mmap import ctypes as ct @@ -1440,17 +1441,18 @@ _ShapeType = TypeVar("_ShapeType", bound=Any) _ShapeType2 = TypeVar("_ShapeType2", bound=Any) _NumberType = TypeVar("_NumberType", bound=number[Any]) -# There is currently no exhaustive way to type the buffer protocol, -# as it is implemented exclusively in the C API (python/typing#593) -_SupportsBuffer = Union[ - bytes, - bytearray, - memoryview, - _array.array[Any], - mmap.mmap, - NDArray[Any], - generic, -] +if sys.version_info >= (3, 12): + from collections.abc import Buffer as _SupportsBuffer +else: + _SupportsBuffer = ( + bytes + | bytearray + | memoryview + | _array.array[Any] + | mmap.mmap + | NDArray[Any] + | generic + ) _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) @@ -1513,6 +1515,9 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType_co]): order: _OrderKACF = ..., ) -> _ArraySelf: ... + if sys.version_info >= (3, 12): + def __buffer__(self, flags: int, /) -> memoryview: ... + def __class_getitem__(self, item: Any) -> GenericAlias: ... @overload @@ -2570,6 +2575,9 @@ class generic(_ArrayOrScalarCommon): @property def flat(self: _ScalarType) -> flatiter[ndarray[Any, _dtype[_ScalarType]]]: ... + if sys.version_info >= (3, 12): + def __buffer__(self, flags: int, /) -> memoryview: ... + @overload def astype( self, @@ -2772,6 +2780,9 @@ class object_(generic): def __float__(self) -> float: ... def __complex__(self) -> complex: ... + if sys.version_info >= (3, 12): + def __release_buffer__(self, buffer: memoryview, /) -> None: ... + # The `datetime64` constructors requires an object with the three attributes below, # and thus supports datetime duck typing class _DatetimeScalar(Protocol): From 56e580d2e2c9b238de3ed2ce2299356013bace27 Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Thu, 14 Sep 2023 15:49:26 +0200 Subject: [PATCH 2/3] TYP: Use `collections.abc.Buffer` in the Array API --- numpy/array_api/_typing.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/numpy/array_api/_typing.py b/numpy/array_api/_typing.py index 3f9b7186aebb..e63a375b5f66 100644 --- a/numpy/array_api/_typing.py +++ b/numpy/array_api/_typing.py @@ -17,6 +17,8 @@ "PyCapsule", ] +import sys + from typing import ( Any, Literal, @@ -63,8 +65,11 @@ def __len__(self, /) -> int: ... float64, ]] +if sys.version_info >= (3, 12): + from collections.abc import Buffer as SupportsBufferProtocol +else: + SupportsBufferProtocol = Any -SupportsBufferProtocol = Any PyCapsule = Any class SupportsDLPack(Protocol): From 92aab8c8ba396e046e7a10bc27a0979dc5bc030f Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Thu, 14 Sep 2023 15:50:08 +0200 Subject: [PATCH 3/3] TYP: Use `collections.abc.Buffer` in the `npt.ArrayLike` definition --- numpy/_typing/_array_like.py | 25 +++++++++++-------- .../tests/data/reveal/array_constructors.pyi | 8 ++++++ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/numpy/_typing/_array_like.py b/numpy/_typing/_array_like.py index cba6fffaf955..883e817d9a6c 100644 --- a/numpy/_typing/_array_like.py +++ b/numpy/_typing/_array_like.py @@ -1,7 +1,9 @@ from __future__ import annotations +import sys from collections.abc import Collection, Callable, Sequence from typing import Any, Protocol, Union, TypeVar, runtime_checkable + from numpy import ( ndarray, dtype, @@ -76,17 +78,18 @@ def __array_function__( _NestedSequence[_T], ] -# TODO: support buffer protocols once -# -# https://bugs.python.org/issue27501 -# -# is resolved. See also the mypy issue: -# -# https://github.com/python/typing/issues/593 -ArrayLike = _DualArrayLike[ - dtype[Any], - Union[bool, int, float, complex, str, bytes], -] +if sys.version_info >= (3, 12): + from collections.abc import Buffer + + ArrayLike = Buffer | _DualArrayLike[ + dtype[Any], + Union[bool, int, float, complex, str, bytes], + ] +else: + ArrayLike = _DualArrayLike[ + dtype[Any], + Union[bool, int, float, complex, str, bytes], + ] # `ArrayLike_co`: array-like objects that can be coerced into `X` # given the casting rules `same_kind` diff --git a/numpy/typing/tests/data/reveal/array_constructors.pyi b/numpy/typing/tests/data/reveal/array_constructors.pyi index 3eb560aafd9e..0bfbc63093a3 100644 --- a/numpy/typing/tests/data/reveal/array_constructors.pyi +++ b/numpy/typing/tests/data/reveal/array_constructors.pyi @@ -211,3 +211,11 @@ assert_type(np.stack([A, A], out=B), SubClass[np.float64]) assert_type(np.block([[A, A], [A, A]]), npt.NDArray[Any]) assert_type(np.block(C), npt.NDArray[Any]) + +if sys.version_info >= (3, 12): + from collections.abc import Buffer + + def create_array(obj: npt.ArrayLike) -> npt.NDArray[Any]: ... + + buffer: Buffer + assert_type(create_array(buffer), npt.NDArray[Any])