From 14a6bba17cba0edc856977e3c87d76e2aedfbba5 Mon Sep 17 00:00:00 2001 From: Ramon Hagenaars <37958579+ramonhagenaars@users.noreply.github.com> Date: Wed, 8 Jun 2022 21:38:30 +0200 Subject: [PATCH] Release/2.1.2 (#78) * Fixed bug that ndarrays were considered to be instances of RecArray. * Version bump. * Fix for "_DType_co" MyPy complaint. * Added test to check the version is increased. * Fix for the install task to install on every environment. * Moved some requirements from build to qa. * Updated the constraints * Added pip upgrade to the install task * Changed date. Co-authored-by: Ramon --- HISTORY.md | 4 + USERDOCS.md | 13 ++- constraints.txt | 47 +++++---- dependencies/build-requirements.txt | 1 - dependencies/qa-requirements.txt | 2 + dependencies/requirements.txt | 5 +- nptyping/package_info.py | 2 +- nptyping/structure_expression.py | 7 +- nptyping/typing_.py | 128 +++++++++++----------- nptyping/typing_.pyi | 110 +++++++++++++++++++ setup.cfg | 1 - tasks.py | 8 +- tests/test_mypy.py | 158 +++++++++++++++------------- tests/test_package_info.py | 15 +++ tests/test_wheel.py | 1 + 15 files changed, 334 insertions(+), 168 deletions(-) create mode 100644 nptyping/typing_.pyi create mode 100644 tests/test_package_info.py diff --git a/HISTORY.md b/HISTORY.md index 13857db..defef1f 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,9 @@ # History +## 2.1.2 (2022-06-08) + +- Fixed bug that caused MyPy to fail with the message: Value of type variable "_DType_co" of "ndarray" cannot be "floating[Any]" + ## 2.1.1 (2022-06-01) - Fixed bug that numpy ndarrays were incorrectly instance checked against `RecArray`. diff --git a/USERDOCS.md b/USERDOCS.md index d6d1ab1..639ee19 100644 --- a/USERDOCS.md +++ b/USERDOCS.md @@ -298,14 +298,23 @@ Unicode Str0 ``` -These are just aliases for `numpy` dtypes. +These are special aliases for `numpy` dtypes. ```python >>> from nptyping import Int >>> Int ``` -As a result, you may also provide `numpy` dtypes directly to an `NDArray`. +You may also provide `numpy` dtypes directly to an `NDArray`. This is not recommended though, because +MyPy won't accept it. +```python +>>> import numpy as np + +>>> NDArray[Any, np.floating] +NDArray[Any, Floating] + +``` + ### Structure expressions You can denote the structure of a structured array using what we call a **structure expression**. This expression diff --git a/constraints.txt b/constraints.txt index 4882a29..80d2973 100644 --- a/constraints.txt +++ b/constraints.txt @@ -4,33 +4,39 @@ # # pip-compile --output-file=constraints.txt './dependencies\build-requirements.txt' './dependencies\qa-requirements.txt' './dependencies\requirements.txt' # -astroid==2.9.3 +astroid==2.11.5 # via pylint autoflake==1.4 # via -r ./dependencies\qa-requirements.txt -black==22.1.0 +beartype==0.10.4 ; python_version >= "3.10" # via -r ./dependencies\qa-requirements.txt -certifi==2021.10.8 +black==22.3.0 + # via -r ./dependencies\qa-requirements.txt +certifi==2022.5.18.1 # via requests charset-normalizer==2.0.12 # via requests -click==8.0.4 +click==8.1.3 # via # black # pip-tools codecov==2.1.12 - # via -r ./dependencies\build-requirements.txt + # via -r ./dependencies\qa-requirements.txt colorama==0.4.4 # via # click # pylint -coverage==6.3.1 +coverage==6.4.1 # via # -r ./dependencies\qa-requirements.txt # codecov +dill==0.3.5.1 + # via pylint +feedparser==6.0.10 + # via -r ./dependencies\qa-requirements.txt idna==3.3 # via requests -invoke==1.6.0 +invoke==1.7.1 # via -r ./dependencies\build-requirements.txt isort==5.10.1 # via @@ -38,48 +44,53 @@ isort==5.10.1 # pylint lazy-object-proxy==1.7.1 # via astroid -mccabe==0.6.1 +mccabe==0.6.0 # via pylint -mypy==0.931 +mypy==0.961 # via -r ./dependencies\qa-requirements.txt mypy-extensions==0.4.3 # via # black # mypy -numpy==1.21.5 +numpy==1.22.4 ; python_version >= "3.8" # via -r ./dependencies\requirements.txt pathspec==0.9.0 # via black pep517==0.12.0 # via pip-tools -pip-tools==6.5.1 +pip-tools==6.6.2 # via -r ./dependencies\build-requirements.txt -platformdirs==2.5.1 +platformdirs==2.5.2 # via # black # pylint pyflakes==2.4.0 # via autoflake -pylint==2.12.2 +pylint==2.14.1 # via -r ./dependencies\qa-requirements.txt requests==2.27.1 # via codecov -toml==0.10.2 - # via pylint +sgmllib3k==1.0.0 + # via feedparser tomli==2.0.1 # via # black # mypy # pep517 -typing-extensions==4.1.1 + # pylint +tomlkit==0.11.0 + # via pylint +typeguard==2.13.3 + # via -r ./dependencies\qa-requirements.txt +typing-extensions==4.2.0 # via mypy -urllib3==1.26.8 +urllib3==1.26.9 # via requests wheel==0.37.1 # via # -r ./dependencies\qa-requirements.txt # pip-tools -wrapt==1.13.3 +wrapt==1.14.1 # via astroid # The following packages are considered to be unsafe in a requirements file: diff --git a/dependencies/build-requirements.txt b/dependencies/build-requirements.txt index 35bb263..c49c460 100644 --- a/dependencies/build-requirements.txt +++ b/dependencies/build-requirements.txt @@ -1,3 +1,2 @@ invoke>=1.6.0 pip-tools>=6.5.0 -codecov>=2.1.0 diff --git a/dependencies/qa-requirements.txt b/dependencies/qa-requirements.txt index 97fb401..08571b6 100644 --- a/dependencies/qa-requirements.txt +++ b/dependencies/qa-requirements.txt @@ -1,6 +1,7 @@ autoflake black coverage +codecov>=2.1.0 isort mypy pylint @@ -9,3 +10,4 @@ wheel beartype<0.10.0; python_version<'3.10' beartype>=0.10.0; python_version>='3.10' typeguard +feedparser diff --git a/dependencies/requirements.txt b/dependencies/requirements.txt index 5c1c7a0..14a87b7 100644 --- a/dependencies/requirements.txt +++ b/dependencies/requirements.txt @@ -1,2 +1,3 @@ -numpy>=1.20.0,<2.0.0 -typing_extensions>=4.0.0,<5.0.0; python_version < '3.10' +numpy==1.21.5; python_version<'3.8' +numpy>=1.20.0,<2.0.0; python_version>='3.8' +typing_extensions>=4.0.0,<5.0.0; python_version<'3.10' diff --git a/nptyping/package_info.py b/nptyping/package_info.py index 38e06f6..e2ccab4 100644 --- a/nptyping/package_info.py +++ b/nptyping/package_info.py @@ -22,7 +22,7 @@ SOFTWARE. """ __title__ = "nptyping" -__version__ = "2.1.1" +__version__ = "2.1.2" __author__ = "Ramon Hagenaars" __author_email__ = "ramon.hagenaars@gmail.com" __description__ = "Type hints for NumPy." diff --git a/nptyping/structure_expression.py b/nptyping/structure_expression.py index 9dc49b4..63f61d1 100644 --- a/nptyping/structure_expression.py +++ b/nptyping/structure_expression.py @@ -30,7 +30,6 @@ Dict, List, Mapping, - Tuple, Union, ) @@ -77,9 +76,7 @@ def check_structure( occur in a structure expression. :return: True if the given dtype is valid with the given target. """ - fields: Mapping[ - str, Union[Tuple[np.dtype[Any], int], Tuple[np.dtype[Any], int, Any]] - ] = (structured_dtype.fields or {}) + fields: Mapping[str, Any] = structured_dtype.fields or {} # type: ignore[assignment] for name, dtype_tuple in fields.items(): dtype = dtype_tuple[0] target_type_name = target.get_type(name) @@ -166,7 +163,7 @@ def _validate_structure_expression_contains_no_multiple_field_names( # Validate that there are not multiple occurrences of the same field names. matches = re.findall(_REGEX_FIELD, re.sub(r"\s*", "", structure_expression)) field_name_combinations = [match[0].split(":")[0] for match in matches] - field_names = [] + field_names: List[str] = [] for field_name_combination in field_name_combinations: field_name_combination_match = re.match( _REGEX_FIELD_NAMES_COMBINATION, field_name_combination diff --git a/nptyping/typing_.py b/nptyping/typing_.py index 6e10a40..9b8cb81 100644 --- a/nptyping/typing_.py +++ b/nptyping/typing_.py @@ -46,70 +46,70 @@ DType: TypeAlias = Union[np.generic, StructureExpression] ShapeTuple: TypeAlias = Tuple[int, ...] -Number: TypeAlias = np.number -Bool: TypeAlias = np.bool_ -Bool8: TypeAlias = np.bool8 -Object: TypeAlias = np.object_ -Object0: TypeAlias = np.object0 -Datetime64: TypeAlias = np.datetime64 -Integer: TypeAlias = np.integer -SignedInteger: TypeAlias = np.signedinteger -Int8: TypeAlias = np.int8 -Int16: TypeAlias = np.int16 -Int32: TypeAlias = np.int32 -Int64: TypeAlias = np.int64 -Byte: TypeAlias = np.byte -Short: TypeAlias = np.short -IntC: TypeAlias = np.intc -IntP: TypeAlias = np.intp -Int0: TypeAlias = np.int0 -Int: TypeAlias = np.int_ -LongLong: TypeAlias = np.longlong -Timedelta64: TypeAlias = np.timedelta64 -UnsignedInteger: TypeAlias = np.unsignedinteger -UInt8: TypeAlias = np.uint8 -UInt16: TypeAlias = np.uint16 -UInt32: TypeAlias = np.uint32 -UInt64: TypeAlias = np.uint64 -UByte: TypeAlias = np.ubyte -UShort: TypeAlias = np.ushort -UIntC: TypeAlias = np.uintc -UIntP: TypeAlias = np.uintp -UInt0: TypeAlias = np.uint0 -UInt: TypeAlias = np.uint -ULongLong: TypeAlias = np.ulonglong -Inexact: TypeAlias = np.inexact -Floating: TypeAlias = np.floating -Float16: TypeAlias = np.float16 -Float32: TypeAlias = np.float32 -Float64: TypeAlias = np.float64 -Half: TypeAlias = np.half -Single: TypeAlias = np.single -Double: TypeAlias = np.double -Float: TypeAlias = np.float_ -LongDouble: TypeAlias = np.longdouble -LongFloat: TypeAlias = np.longfloat -ComplexFloating: TypeAlias = np.complexfloating -Complex64: TypeAlias = np.complex64 -Complex128: TypeAlias = np.complex128 -CSingle: TypeAlias = np.csingle -SingleComplex: TypeAlias = np.singlecomplex -CDouble: TypeAlias = np.cdouble -Complex: TypeAlias = np.complex_ -CFloat: TypeAlias = np.cfloat -CLongDouble: TypeAlias = np.clongdouble -CLongFloat: TypeAlias = np.clongfloat -LongComplex: TypeAlias = np.longcomplex -Flexible: TypeAlias = np.flexible -Void: TypeAlias = np.void -Void0: TypeAlias = np.void0 -Character: TypeAlias = np.character -Bytes: TypeAlias = np.bytes_ -Str: TypeAlias = np.str_ -String: TypeAlias = np.string_ -Bytes0: TypeAlias = np.bytes0 -Unicode: TypeAlias = np.unicode_ -Str0: TypeAlias = np.str0 +Number = np.number +Bool = np.bool_ +Bool8 = np.bool8 +Object = np.object_ +Object0 = np.object0 +Datetime64 = np.datetime64 +Integer = np.integer +SignedInteger = np.signedinteger +Int8 = np.int8 +Int16 = np.int16 +Int32 = np.int32 +Int64 = np.int64 +Byte = np.byte +Short = np.short +IntC = np.intc +IntP = np.intp +Int0 = np.int0 +Int = np.int_ +LongLong = np.longlong +Timedelta64 = np.timedelta64 +UnsignedInteger = np.unsignedinteger +UInt8 = np.uint8 +UInt16 = np.uint16 +UInt32 = np.uint32 +UInt64 = np.uint64 +UByte = np.ubyte +UShort = np.ushort +UIntC = np.uintc +UIntP = np.uintp +UInt0 = np.uint0 +UInt = np.uint +ULongLong = np.ulonglong +Inexact = np.inexact +Floating = np.floating +Float16 = np.float16 +Float32 = np.float32 +Float64 = np.float64 +Half = np.half +Single = np.single +Double = np.double +Float = np.float_ +LongDouble = np.longdouble +LongFloat = np.longfloat +ComplexFloating = np.complexfloating +Complex64 = np.complex64 +Complex128 = np.complex128 +CSingle = np.csingle +SingleComplex = np.singlecomplex +CDouble = np.cdouble +Complex = np.complex_ +CFloat = np.cfloat +CLongDouble = np.clongdouble +CLongFloat = np.clongfloat +LongComplex = np.longcomplex +Flexible = np.flexible +Void = np.void +Void0 = np.void0 +Character = np.character +Bytes = np.bytes_ +Str = np.str_ +String = np.string_ +Bytes0 = np.bytes0 +Unicode = np.unicode_ +Str0 = np.str0 dtypes = [ (Number, "Number"), diff --git a/nptyping/typing_.pyi b/nptyping/typing_.pyi new file mode 100644 index 0000000..33d5913 --- /dev/null +++ b/nptyping/typing_.pyi @@ -0,0 +1,110 @@ +""" +MIT License + +Copyright (c) 2022 Ramon Hagenaars + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +""" + +try: + from typing import ( # type: ignore[attr-defined] # pylint: disable=unused-import + TypeAlias, + ) +except ImportError: # pragma: no cover + from typing_extensions import ( + TypeAlias, + ) + +from typing import ( + Any, + Tuple, + Union, +) + +import numpy as np + +ShapeExpression: TypeAlias = str +StructureExpression: TypeAlias = str +DType: TypeAlias = Union[np.generic, StructureExpression] +ShapeTuple: TypeAlias = Tuple[int, ...] + +Number: TypeAlias = np.dtype[np.number[Any]] +Bool: TypeAlias = np.dtype[np.bool_] +Bool8: TypeAlias = np.dtype[np.bool8] +Object: TypeAlias = np.dtype[np.object_] +Object0: TypeAlias = np.dtype[np.object0] +Datetime64: TypeAlias = np.dtype[np.datetime64] +Integer: TypeAlias = np.dtype[np.integer[Any]] +SignedInteger: TypeAlias = np.dtype[np.signedinteger[Any]] +Int8: TypeAlias = np.dtype[np.int8] +Int16: TypeAlias = np.dtype[np.int16] +Int32: TypeAlias = np.dtype[np.int32] +Int64: TypeAlias = np.dtype[np.int64] +Byte: TypeAlias = np.dtype[np.byte] +Short: TypeAlias = np.dtype[np.short] +IntC: TypeAlias = np.dtype[np.intc] +IntP: TypeAlias = np.dtype[np.intp] +Int0: TypeAlias = np.dtype[np.int0] +Int: TypeAlias = np.dtype[np.int_] +LongLong: TypeAlias = np.dtype[np.longlong] +Timedelta64: TypeAlias = np.dtype[np.timedelta64] +UnsignedInteger: TypeAlias = np.dtype[np.unsignedinteger[Any]] +UInt8: TypeAlias = np.dtype[np.uint8] +UInt16: TypeAlias = np.dtype[np.uint16] +UInt32: TypeAlias = np.dtype[np.uint32] +UInt64: TypeAlias = np.dtype[np.uint64] +UByte: TypeAlias = np.dtype[np.ubyte] +UShort: TypeAlias = np.dtype[np.ushort] +UIntC: TypeAlias = np.dtype[np.uintc] +UIntP: TypeAlias = np.dtype[np.uintp] +UInt0: TypeAlias = np.dtype[np.uint0] +UInt: TypeAlias = np.dtype[np.uint] +ULongLong: TypeAlias = np.dtype[np.ulonglong] +Inexact: TypeAlias = np.dtype[np.inexact[Any]] +Floating: TypeAlias = np.dtype[np.floating[Any]] +Float16: TypeAlias = np.dtype[np.float16] +Float32: TypeAlias = np.dtype[np.float32] +Float64: TypeAlias = np.dtype[np.float64] +Half: TypeAlias = np.dtype[np.half] +Single: TypeAlias = np.dtype[np.single] +Double: TypeAlias = np.dtype[np.double] +Float: TypeAlias = np.dtype[np.float_] +LongDouble: TypeAlias = np.dtype[np.longdouble] +LongFloat: TypeAlias = np.dtype[np.longfloat] +ComplexFloating: TypeAlias = np.dtype[np.complexfloating[Any, Any]] +Complex64: TypeAlias = np.dtype[np.complex64] +Complex128: TypeAlias = np.dtype[np.complex128] +CSingle: TypeAlias = np.dtype[np.csingle] +SingleComplex: TypeAlias = np.dtype[np.singlecomplex] +CDouble: TypeAlias = np.dtype[np.cdouble] +Complex: TypeAlias = np.dtype[np.complex_] +CFloat: TypeAlias = np.dtype[np.cfloat] +CLongDouble: TypeAlias = np.dtype[np.clongdouble] +CLongFloat: TypeAlias = np.dtype[np.clongfloat] +LongComplex: TypeAlias = np.dtype[np.longcomplex] +Flexible: TypeAlias = np.dtype[np.flexible] +Void: TypeAlias = np.dtype[np.void] +Void0: TypeAlias = np.dtype[np.void0] +Character: TypeAlias = np.dtype[np.character] +Bytes: TypeAlias = np.dtype[np.bytes_] +Str: TypeAlias = np.dtype[np.str_] +String: TypeAlias = np.dtype[np.string_] +Bytes0: TypeAlias = np.dtype[np.bytes0] +Unicode: TypeAlias = np.dtype[np.unicode_] +Str0: TypeAlias = np.dtype[np.str0] diff --git a/setup.cfg b/setup.cfg index 0204844..abeffe9 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,7 +1,6 @@ [pylint] disable = too-few-public-methods, - no-self-use, no-value-for-parameter, duplicate-code, too-many-ancestors, diff --git a/tasks.py b/tasks.py index 8a128f1..94cfdbf 100644 --- a/tasks.py +++ b/tasks.py @@ -128,8 +128,12 @@ def lock(context, py=None): @task def install(context, py=None): """Install all dependencies (dev).""" - print(f"Installing dependencies into: {_DEFAULT_VENV}") - context.run(f"{get_pip(py)} install .[dev] --constraint constraints.txt") + for version in get_versions(py): + print_header(version, install) + print(f"Upgrading pip") + context.run(f"{get_py(version)} -m pip install --upgrade pip") + print(f"Installing dependencies into: {version}") + context.run(f"{get_pip(version)} install .[dev] --constraint constraints.txt") @task(clean, venv, lock, install) diff --git a/tests/test_mypy.py b/tests/test_mypy.py index 830d8ed..48a9303 100644 --- a/tests/test_mypy.py +++ b/tests/test_mypy.py @@ -28,7 +28,6 @@ def test_mypy_accepts_ndarray_with_any(self): NDArray[Any, Any] """ ) - self.assertIn("Success", mypy_findings) def test_mypy_accepts_ndarray_with_shape(self): @@ -130,15 +129,32 @@ def test_mypy_accepts_numpy_types(self): import numpy as np - NDArray[np.int_, Any] - NDArray[np.float_, Any] - NDArray[np.uint8, Any] - NDArray[np.bool_, Any] + NDArray[Any, np.dtype[np.int_]] + NDArray[Any, np.dtype[np.float_]] + NDArray[Any, np.dtype[np.uint8]] + NDArray[Any, np.dtype[np.bool_]] """ ) self.assertIn("Success", mypy_findings) + def test_mypy_wont_accept_numpy_types_without_dtype(self): + mypy_findings = _check_mypy_on_code( + """ + from nptyping import NDArray + from typing import Any + import numpy as np + + + NDArray[Any, np.int_] + """ + ) + + self.assertIn( + 'Value of type variable "_DType_co" of "ndarray" cannot be "signedinteger[Any]"', + mypy_findings, + ) + def test_mypy_knows_of_ndarray_methods(self): # If MyPy knows of some arbitrary ndarray methods, we can assume that # code completion works. @@ -162,7 +178,7 @@ def test_mypy_knows_of_ndarray_methods(self): def test_mypy_accepts_nptyping_types(self): mypy_findings = _check_mypy_on_code( """ - from typing import Any, TypeVar + from typing import Any import numpy as np import numpy.typing as npt from nptyping import ( @@ -231,72 +247,70 @@ def test_mypy_accepts_nptyping_types(self): Unicode, Str0, ) - - T = TypeVar("T", bound=npt.NBitBase) - - NDArray[Number[T], Any] - NDArray[Bool, Any] - NDArray[Bool8, Any] - NDArray[Object, Any] - NDArray[Object0, Any] - NDArray[Datetime64, Any] - NDArray[Integer[T], Any] - NDArray[SignedInteger[T], Any] - NDArray[Int8, Any] - NDArray[Int16, Any] - NDArray[Int32, Any] - NDArray[Int64, Any] - NDArray[Byte, Any] - NDArray[Short, Any] - NDArray[IntC, Any] - NDArray[IntP, Any] - NDArray[Int0, Any] - NDArray[Int, Any] - NDArray[LongLong, Any] - NDArray[Timedelta64, Any] - NDArray[UnsignedInteger[T], Any] - NDArray[UInt8, Any] - NDArray[UInt16, Any] - NDArray[UInt32, Any] - NDArray[UInt64, Any] - NDArray[UByte, Any] - NDArray[UShort, Any] - NDArray[UIntC, Any] - NDArray[UIntP, Any] - NDArray[UInt0, Any] - NDArray[UInt, Any] - NDArray[ULongLong, Any] - NDArray[Inexact[T], Any] - NDArray[Floating[T], Any] - NDArray[Float16, Any] - NDArray[Float32, Any] - NDArray[Float64, Any] - NDArray[Half, Any] - NDArray[Single, Any] - NDArray[Double, Any] - NDArray[Float, Any] - NDArray[LongDouble, Any] - NDArray[LongFloat, Any] - NDArray[ComplexFloating[T, T], Any] - NDArray[Complex64, Any] - NDArray[Complex128, Any] - NDArray[CSingle, Any] - NDArray[SingleComplex, Any] - NDArray[CDouble, Any] - NDArray[Complex, Any] - NDArray[CFloat, Any] - NDArray[CLongDouble, Any] - NDArray[CLongFloat, Any] - NDArray[LongComplex, Any] - NDArray[Flexible, Any] - NDArray[Void, Any] - NDArray[Void0, Any] - NDArray[Character, Any] - NDArray[Bytes, Any] - NDArray[String, Any] - NDArray[Bytes0, Any] - NDArray[Unicode, Any] - NDArray[Str0, Any] + + NDArray[Any, Number] + NDArray[Any, Bool] + NDArray[Any, Bool8] + NDArray[Any, Object] + NDArray[Any, Object0] + NDArray[Any, Datetime64] + NDArray[Any, Integer] + NDArray[Any, SignedInteger] + NDArray[Any, Int8] + NDArray[Any, Int16] + NDArray[Any, Int32] + NDArray[Any, Int64] + NDArray[Any, Byte] + NDArray[Any, Short] + NDArray[Any, IntC] + NDArray[Any, IntP] + NDArray[Any, Int0] + NDArray[Any, Int] + NDArray[Any, LongLong] + NDArray[Any, Timedelta64] + NDArray[Any, UnsignedInteger] + NDArray[Any, UInt8] + NDArray[Any, UInt16] + NDArray[Any, UInt32] + NDArray[Any, UInt64] + NDArray[Any, UByte] + NDArray[Any, UShort] + NDArray[Any, UIntC] + NDArray[Any, UIntP] + NDArray[Any, UInt0] + NDArray[Any, UInt] + NDArray[Any, ULongLong] + NDArray[Any, Inexact] + NDArray[Any, Floating] + NDArray[Any, Float16] + NDArray[Any, Float32] + NDArray[Any, Float64] + NDArray[Any, Half] + NDArray[Any, Single] + NDArray[Any, Double] + NDArray[Any, Float] + NDArray[Any, LongDouble] + NDArray[Any, LongFloat] + NDArray[Any, ComplexFloating] + NDArray[Any, Complex64] + NDArray[Any, Complex128] + NDArray[Any, CSingle] + NDArray[Any, SingleComplex] + NDArray[Any, CDouble] + NDArray[Any, Complex] + NDArray[Any, CFloat] + NDArray[Any, CLongDouble] + NDArray[Any, CLongFloat] + NDArray[Any, LongComplex] + NDArray[Any, Flexible] + NDArray[Any, Void] + NDArray[Any, Void0] + NDArray[Any, Character] + NDArray[Any, Bytes] + NDArray[Any, String] + NDArray[Any, Bytes0] + NDArray[Any, Unicode] + NDArray[Any, Str0] """ ) diff --git a/tests/test_package_info.py b/tests/test_package_info.py new file mode 100644 index 0000000..7fb96af --- /dev/null +++ b/tests/test_package_info.py @@ -0,0 +1,15 @@ +from unittest import TestCase + +import feedparser + +from nptyping import __version__ + + +class PackageInfoTest(TestCase): + def test_version_bump(self): + releases = feedparser.parse( + "https://pypi.org/rss/project/nptyping/releases.xml" + ) + release_versions = {entry.title for entry in releases.entries} + + self.assertNotIn(__version__, release_versions, "Version bump required") diff --git a/tests/test_wheel.py b/tests/test_wheel.py index 805b926..b6d02a8 100644 --- a/tests/test_wheel.py +++ b/tests/test_wheel.py @@ -40,6 +40,7 @@ "structure.pyi", "structure_expression.py", "typing_.py", + "typing_.pyi", }