From c43070909b93c45a6762e611907a206082114417 Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Mon, 12 Nov 2018 16:35:48 +0300 Subject: [PATCH 1/5] Add array conversion methods to ndarray --- numpy-stubs/__init__.pyi | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/numpy-stubs/__init__.pyi b/numpy-stubs/__init__.pyi index 427b477..833f4c3 100644 --- a/numpy-stubs/__init__.pyi +++ b/numpy-stubs/__init__.pyi @@ -6,6 +6,7 @@ from typing import ( Any, Container, Dict, + IO, Iterable, List, Mapping, @@ -369,6 +370,35 @@ class ndarray(_ArrayOrScalarCommon, Iterable, Sized, Container): @strides.setter def strides(self, value: _ShapeLike): ... + # Array conversion + def item(self, *args: int) -> Any: ... + def tolist(self) -> List[Any]: ... + @overload + def itemset(self, __value: Any): ... + @overload + def itemset(self, __item: _ShapeLike, __value: Any): ... + def tostring(self, order: str=...) -> bytes: ... + def tobytes(self, order: str=...) -> bytes: ... + def tofile(self, fid: Union[IO[Any], str], sep: str, format: str): ... + def dump(self, file: str): ... + def dumps(self) -> bytes: ... + def astype(self, + dtype: _DtypeLike, + order: str=..., + casting: str=..., + subok: bool=..., + copy: bool=...) -> ndarray: ... + def byteswap(self, inplace: bool=...) -> ndarray: ... + def copy(self, order: str=...) -> ndarray: ... + def view(self, + dtype: Union[_DtypeLike, Type]=..., + type: Any=...) -> ndarray: ... + def getfield(self, + dtype: Union[_DtypeLike, str], + offset: int=...) -> ndarray: ... + def setflags(self, write: bool=..., align: bool=..., uic: bool=...): ... + def fill(self, value: Any): ... + # Shape manipulation @overload def reshape(self, shape: Sequence[int], *, order: str=...) -> ndarray: ... From 7d46b9a635c3db2db9270883ccbe01f2e6b53eeb Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Tue, 13 Nov 2018 15:43:13 +0300 Subject: [PATCH 2/5] Fix array conversion methods after review --- numpy-stubs/__init__.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/numpy-stubs/__init__.pyi b/numpy-stubs/__init__.pyi index 833f4c3..92babff 100644 --- a/numpy-stubs/__init__.pyi +++ b/numpy-stubs/__init__.pyi @@ -391,8 +391,8 @@ class ndarray(_ArrayOrScalarCommon, Iterable, Sized, Container): def byteswap(self, inplace: bool=...) -> ndarray: ... def copy(self, order: str=...) -> ndarray: ... def view(self, - dtype: Union[_DtypeLike, Type]=..., - type: Any=...) -> ndarray: ... + dtype: Union[_DtypeLike, Type[ndarray]]=..., + type: Type[ndarray]=...) -> ndarray: ... def getfield(self, dtype: Union[_DtypeLike, str], offset: int=...) -> ndarray: ... From f0a6c6a160ba3dc64bc6ded60c82c853f0670754 Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Tue, 13 Nov 2018 18:17:15 +0300 Subject: [PATCH 3/5] Add tests for array conversion methods --- numpy-stubs/__init__.pyi | 22 +++--- tests/pass/ndarray_conversion.py | 92 ++++++++++++++++++++++++++ tests/reveal/ndarray_conversion.py | 58 ++++++++++++++++ tests/reveal/ndarray_conversion_py2.py | 15 +++++ tests/reveal/ndarray_conversion_py3.py | 15 +++++ tests/test_stubs.py | 3 + 6 files changed, 197 insertions(+), 8 deletions(-) create mode 100644 tests/pass/ndarray_conversion.py create mode 100644 tests/reveal/ndarray_conversion.py create mode 100644 tests/reveal/ndarray_conversion_py2.py create mode 100644 tests/reveal/ndarray_conversion_py3.py diff --git a/numpy-stubs/__init__.pyi b/numpy-stubs/__init__.pyi index 92babff..55a85f6 100644 --- a/numpy-stubs/__init__.pyi +++ b/numpy-stubs/__init__.pyi @@ -371,16 +371,22 @@ class ndarray(_ArrayOrScalarCommon, Iterable, Sized, Container): def strides(self, value: _ShapeLike): ... # Array conversion + @overload def item(self, *args: int) -> Any: ... + @overload + def item(self, args: Tuple[int, ...]) -> Any: ... def tolist(self) -> List[Any]: ... @overload - def itemset(self, __value: Any): ... + def itemset(self, __value: Any) -> None: ... @overload - def itemset(self, __item: _ShapeLike, __value: Any): ... - def tostring(self, order: str=...) -> bytes: ... - def tobytes(self, order: str=...) -> bytes: ... - def tofile(self, fid: Union[IO[Any], str], sep: str, format: str): ... - def dump(self, file: str): ... + def itemset(self, __item: _ShapeLike, __value: Any) -> None: ... + def tostring(self, order: Optional[str]=...) -> bytes: ... + def tobytes(self, order: Optional[str]=...) -> bytes: ... + def tofile(self, + fid: Union[IO[bytes], str], + sep: str=..., + format: str=...) -> None: ... + def dump(self, file: str) -> None: ... def dumps(self) -> bytes: ... def astype(self, dtype: _DtypeLike, @@ -396,8 +402,8 @@ class ndarray(_ArrayOrScalarCommon, Iterable, Sized, Container): def getfield(self, dtype: Union[_DtypeLike, str], offset: int=...) -> ndarray: ... - def setflags(self, write: bool=..., align: bool=..., uic: bool=...): ... - def fill(self, value: Any): ... + def setflags(self, write: bool=..., align: bool=..., uic: bool=...) -> None: ... + def fill(self, value: Any) -> None: ... # Shape manipulation @overload diff --git a/tests/pass/ndarray_conversion.py b/tests/pass/ndarray_conversion.py new file mode 100644 index 0000000..81200e4 --- /dev/null +++ b/tests/pass/ndarray_conversion.py @@ -0,0 +1,92 @@ +import numpy as np + +nd = np.array([[1, 2], [3, 4]]) + +# item +nd.item() # `nd` should be one-element in runtime +nd.item(1) +nd.item(0, 1) +nd.item((0, 1)) + +# tolist +nd.tolist() + +# itemset +nd.itemset(3) # `nd` should be one-element in runtime +nd.itemset(3, 0) +nd.itemset((0, 0), 3) + +# tostring/tobytes +nd.tostring() +nd.tostring("C") +nd.tostring(None) + +nd.tobytes() +nd.tobytes("C") +nd.tobytes(None) + +# tofile +nd.tofile("a.txt") +nd.tofile(open("a.txt", mode="bw")) + +nd.tofile("a.txt", "") +nd.tofile("a.txt", sep="") + +nd.tofile("a.txt", "", "%s") +nd.tofile("a.txt", format="%s") + +# dump +nd.dump("a.txt") + +# astype +nd.astype("float") +nd.astype(float) + +nd.astype(float, "K") +nd.astype(float, order="K") + +nd.astype(float, "K", "unsafe") +nd.astype(float, casting="unsafe") + +nd.astype(float, "K", "unsafe", True) +nd.astype(float, subok=True) + +nd.astype(float, "K", "unsafe", True, True) +nd.astype(float, copy=True) + +# byteswap +nd.byteswap() +nd.byteswap(True) + +# copy +nd.copy() +nd.copy("C") + +# view +nd.view() +nd.view(np.int64) +nd.view(dtype=np.int64) +nd.view(np.int64, np.matrix) +nd.view(type=np.matrix) + +# getfield +nd.getfield("float") +nd.getfield(float) + +nd.getfield("float", 8) +nd.getfield(float, offset=8) + +# setflags +nd.setflags() + +nd.setflags(True) +nd.setflags(write=True) + +nd.setflags(True, True) +nd.setflags(write=True, align=True) + +nd.setflags(True, True, False) +nd.setflags(write=True, align=True, uic=False) + +# fill +nd.fill(3) diff --git a/tests/reveal/ndarray_conversion.py b/tests/reveal/ndarray_conversion.py new file mode 100644 index 0000000..8974f4d --- /dev/null +++ b/tests/reveal/ndarray_conversion.py @@ -0,0 +1,58 @@ +import numpy as np + +nd = np.array([[1, 2], [3, 4]]) + +# item +reveal_type(nd.item()) # E: Any +reveal_type(nd.item(1)) # E: Any +reveal_type(nd.item(0, 1)) # E: Any +reveal_type(nd.item((0, 1))) # E: Any + +# tolist +reveal_type(nd.tolist()) # E: builtins.list[Any] + +# itemset does not return a value +# tofile does not return a value +# dump does not return a value + +# astype +reveal_type(nd.astype("float")) # E: numpy.ndarray +reveal_type(nd.astype(float)) # E: numpy.ndarray + +reveal_type(nd.astype(float, "K")) # E: numpy.ndarray +reveal_type(nd.astype(float, order="K")) # E: numpy.ndarray + +reveal_type(nd.astype(float, "K", "unsafe")) # E: numpy.ndarray +reveal_type(nd.astype(float, casting="unsafe")) # E: numpy.ndarray + +reveal_type(nd.astype(float, "K", "unsafe", True)) # E: numpy.ndarray +reveal_type(nd.astype(float, subok=True)) # E: numpy.ndarray + +reveal_type(nd.astype(float, "K", "unsafe", True, True)) # E: numpy.ndarray +reveal_type(nd.astype(float, copy=True)) # E: numpy.ndarray + +# byteswap +reveal_type(nd.byteswap()) # E: numpy.ndarray +reveal_type(nd.byteswap(True)) # E: numpy.ndarray + +# copy +reveal_type(nd.copy()) # E: numpy.ndarray +reveal_type(nd.copy("C")) # E: numpy.ndarray + +# view +reveal_type(nd.view()) # E: numpy.ndarray +reveal_type(nd.view(np.int64)) # E: numpy.ndarray +reveal_type(nd.view(dtype=np.int64)) # E: numpy.ndarray +reveal_type(nd.view(np.int64, np.matrix)) # E: numpy.ndarray +reveal_type(nd.view(type=np.matrix)) # E: numpy.ndarray + +# getfield +reveal_type(nd.getfield("float")) # E: numpy.ndarray +reveal_type(nd.getfield(float)) # E: numpy.ndarray + +reveal_type(nd.getfield(float)) # E: numpy.ndarray +reveal_type(nd.getfield(float, offset=8)) # E: numpy.ndarray + +# setflags does not return a value +# fill does not return a value + diff --git a/tests/reveal/ndarray_conversion_py2.py b/tests/reveal/ndarray_conversion_py2.py new file mode 100644 index 0000000..cd2e705 --- /dev/null +++ b/tests/reveal/ndarray_conversion_py2.py @@ -0,0 +1,15 @@ +import numpy as np + +nd = np.array([[1, 2], [3, 4]]) + +# tostring/tobytes +reveal_type(nd.tostring()) # E: str +reveal_type(nd.tostring('C')) # E: str +reveal_type(nd.tostring(None)) # E: str + +reveal_type(nd.tobytes()) # E: str +reveal_type(nd.tobytes('C')) # E: str +reveal_type(nd.tobytes(None)) # E: str + +# dumps +reveal_type(nd.dumps()) # E: str \ No newline at end of file diff --git a/tests/reveal/ndarray_conversion_py3.py b/tests/reveal/ndarray_conversion_py3.py new file mode 100644 index 0000000..3dc3dc2 --- /dev/null +++ b/tests/reveal/ndarray_conversion_py3.py @@ -0,0 +1,15 @@ +import numpy as np + +nd = np.array([[1, 2], [3, 4]]) + +# tostring/tobytes +reveal_type(nd.tostring()) # E: bytes +reveal_type(nd.tostring('C')) # E: bytes +reveal_type(nd.tostring(None)) # E: bytes + +reveal_type(nd.tobytes()) # E: bytes +reveal_type(nd.tobytes('C')) # E: bytes +reveal_type(nd.tobytes(None)) # E: bytes + +# dumps +reveal_type(nd.dumps()) # E: bytes \ No newline at end of file diff --git a/tests/test_stubs.py b/tests/test_stubs.py index b0e8809..0eaf93b 100644 --- a/tests/test_stubs.py +++ b/tests/test_stubs.py @@ -17,10 +17,13 @@ def get_test_cases(directory): # Use relative path for nice py.test name relpath = os.path.relpath(fullpath, start=directory) skip_py2 = fname.endswith("_py3.py") + skip_py3 = fname.endswith("_py2.py") for py_version_number in (2, 3): if py_version_number == 2 and skip_py2: continue + if py_version_number == 3 and skip_py3: + continue py2_arg = ['--py2'] if py_version_number == 2 else [] yield pytest.param( From 7d0dbf3005d443ac4ba26631854a2918b7ec1273 Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Wed, 14 Nov 2018 14:59:05 +0300 Subject: [PATCH 4/5] Cleanup tests for array conversion methods Remove simple ones and leave comments for consistency --- tests/pass/ndarray_conversion.py | 10 ++++------ tests/reveal/ndarray_conversion.py | 17 ++++------------- tests/reveal/ndarray_conversion_py2.py | 15 --------------- tests/reveal/ndarray_conversion_py3.py | 15 --------------- 4 files changed, 8 insertions(+), 49 deletions(-) delete mode 100644 tests/reveal/ndarray_conversion_py2.py delete mode 100644 tests/reveal/ndarray_conversion_py3.py diff --git a/tests/pass/ndarray_conversion.py b/tests/pass/ndarray_conversion.py index 81200e4..21b71e1 100644 --- a/tests/pass/ndarray_conversion.py +++ b/tests/pass/ndarray_conversion.py @@ -8,8 +8,7 @@ nd.item(0, 1) nd.item((0, 1)) -# tolist -nd.tolist() +# tolist is pretty simple # itemset nd.itemset(3) # `nd` should be one-element in runtime @@ -35,8 +34,8 @@ nd.tofile("a.txt", "", "%s") nd.tofile("a.txt", format="%s") -# dump -nd.dump("a.txt") +# dump is pretty simple +# dumps is pretty simple # astype nd.astype("float") @@ -88,5 +87,4 @@ nd.setflags(True, True, False) nd.setflags(write=True, align=True, uic=False) -# fill -nd.fill(3) +# fill is pretty simple diff --git a/tests/reveal/ndarray_conversion.py b/tests/reveal/ndarray_conversion.py index 8974f4d..0bac2a9 100644 --- a/tests/reveal/ndarray_conversion.py +++ b/tests/reveal/ndarray_conversion.py @@ -12,24 +12,19 @@ reveal_type(nd.tolist()) # E: builtins.list[Any] # itemset does not return a value +# tostring is pretty simple +# tobytes is pretty simple # tofile does not return a value # dump does not return a value +# dumps is pretty simple # astype reveal_type(nd.astype("float")) # E: numpy.ndarray reveal_type(nd.astype(float)) # E: numpy.ndarray - reveal_type(nd.astype(float, "K")) # E: numpy.ndarray -reveal_type(nd.astype(float, order="K")) # E: numpy.ndarray - reveal_type(nd.astype(float, "K", "unsafe")) # E: numpy.ndarray -reveal_type(nd.astype(float, casting="unsafe")) # E: numpy.ndarray - reveal_type(nd.astype(float, "K", "unsafe", True)) # E: numpy.ndarray -reveal_type(nd.astype(float, subok=True)) # E: numpy.ndarray - reveal_type(nd.astype(float, "K", "unsafe", True, True)) # E: numpy.ndarray -reveal_type(nd.astype(float, copy=True)) # E: numpy.ndarray # byteswap reveal_type(nd.byteswap()) # E: numpy.ndarray @@ -42,16 +37,12 @@ # view reveal_type(nd.view()) # E: numpy.ndarray reveal_type(nd.view(np.int64)) # E: numpy.ndarray -reveal_type(nd.view(dtype=np.int64)) # E: numpy.ndarray reveal_type(nd.view(np.int64, np.matrix)) # E: numpy.ndarray -reveal_type(nd.view(type=np.matrix)) # E: numpy.ndarray # getfield reveal_type(nd.getfield("float")) # E: numpy.ndarray reveal_type(nd.getfield(float)) # E: numpy.ndarray - -reveal_type(nd.getfield(float)) # E: numpy.ndarray -reveal_type(nd.getfield(float, offset=8)) # E: numpy.ndarray +reveal_type(nd.getfield(float, 8)) # E: numpy.ndarray # setflags does not return a value # fill does not return a value diff --git a/tests/reveal/ndarray_conversion_py2.py b/tests/reveal/ndarray_conversion_py2.py deleted file mode 100644 index cd2e705..0000000 --- a/tests/reveal/ndarray_conversion_py2.py +++ /dev/null @@ -1,15 +0,0 @@ -import numpy as np - -nd = np.array([[1, 2], [3, 4]]) - -# tostring/tobytes -reveal_type(nd.tostring()) # E: str -reveal_type(nd.tostring('C')) # E: str -reveal_type(nd.tostring(None)) # E: str - -reveal_type(nd.tobytes()) # E: str -reveal_type(nd.tobytes('C')) # E: str -reveal_type(nd.tobytes(None)) # E: str - -# dumps -reveal_type(nd.dumps()) # E: str \ No newline at end of file diff --git a/tests/reveal/ndarray_conversion_py3.py b/tests/reveal/ndarray_conversion_py3.py deleted file mode 100644 index 3dc3dc2..0000000 --- a/tests/reveal/ndarray_conversion_py3.py +++ /dev/null @@ -1,15 +0,0 @@ -import numpy as np - -nd = np.array([[1, 2], [3, 4]]) - -# tostring/tobytes -reveal_type(nd.tostring()) # E: bytes -reveal_type(nd.tostring('C')) # E: bytes -reveal_type(nd.tostring(None)) # E: bytes - -reveal_type(nd.tobytes()) # E: bytes -reveal_type(nd.tobytes('C')) # E: bytes -reveal_type(nd.tobytes(None)) # E: bytes - -# dumps -reveal_type(nd.dumps()) # E: bytes \ No newline at end of file From 7ddb6d7fd92a4d326ec43962e5c7c15a8f62a6cb Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Wed, 14 Nov 2018 15:49:34 +0300 Subject: [PATCH 5/5] Update type hints for ndarray.view Its stub was splitted into all possible overloads. `view(self, dtype: Type[_NdArraySubClass], type: Type[_NdArraySubClass])` could not be used. --- numpy-stubs/__init__.pyi | 12 +++++++++--- tests/reveal/ndarray_conversion.py | 7 ++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/numpy-stubs/__init__.pyi b/numpy-stubs/__init__.pyi index 55a85f6..a7cdc23 100644 --- a/numpy-stubs/__init__.pyi +++ b/numpy-stubs/__init__.pyi @@ -72,6 +72,7 @@ _DtypeLike = Union[ Tuple[_DtypeLikeNested, _DtypeLikeNested], ] +_NdArraySubClass = TypeVar("_NdArraySubClass", bound=ndarray) class dtype: names: Optional[Tuple[str, ...]] @@ -396,9 +397,14 @@ class ndarray(_ArrayOrScalarCommon, Iterable, Sized, Container): copy: bool=...) -> ndarray: ... def byteswap(self, inplace: bool=...) -> ndarray: ... def copy(self, order: str=...) -> ndarray: ... - def view(self, - dtype: Union[_DtypeLike, Type[ndarray]]=..., - type: Type[ndarray]=...) -> ndarray: ... + @overload + def view(self, dtype: _DtypeLike=...) -> ndarray: ... + @overload + def view(self, dtype: Type[_NdArraySubClass]) -> _NdArraySubClass: ... + @overload + def view(self, dtype: _DtypeLike, type: Type[_NdArraySubClass]) -> _NdArraySubClass: ... + @overload + def view(self, *, type: Type[_NdArraySubClass]) -> _NdArraySubClass: ... def getfield(self, dtype: Union[_DtypeLike, str], offset: int=...) -> ndarray: ... diff --git a/tests/reveal/ndarray_conversion.py b/tests/reveal/ndarray_conversion.py index 0bac2a9..1e17d44 100644 --- a/tests/reveal/ndarray_conversion.py +++ b/tests/reveal/ndarray_conversion.py @@ -35,9 +35,14 @@ reveal_type(nd.copy("C")) # E: numpy.ndarray # view +class SubArray(np.ndarray): + pass + reveal_type(nd.view()) # E: numpy.ndarray reveal_type(nd.view(np.int64)) # E: numpy.ndarray -reveal_type(nd.view(np.int64, np.matrix)) # E: numpy.ndarray +# replace `Any` with `numpy.matrix` when `matrix` will be added to stubs +reveal_type(nd.view(np.int64, np.matrix)) # E: Any +reveal_type(nd.view(np.int64, SubArray)) # E: SubArray # getfield reveal_type(nd.getfield("float")) # E: numpy.ndarray