From f8f5f0a194b2420b2fee1cf88ac50220d3ba1538 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Tue, 16 Nov 2021 16:33:01 -0500 Subject: [PATCH] feat: add 'py.typed' declaration (#73) Check typing under CI using new 'mypy' nox session. --- mypy.ini | 3 +++ noxfile.py | 13 +++++++++++++ .../lower_bound_checker/lower_bound_checker.py | 3 ++- test_utils/prefixer.py | 3 ++- test_utils/py.typed | 2 ++ test_utils/system.py | 4 ++-- test_utils/vpcsc_config.py | 2 +- tests/unit/test_lower_bound_checker.py | 4 ++-- tests/unit/test_orchestrate.py | 4 ++-- tests/unit/test_prefixer.py | 2 +- 10 files changed, 30 insertions(+), 10 deletions(-) create mode 100644 mypy.ini create mode 100644 test_utils/py.typed diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 0000000..19d0802 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,3 @@ +[mypy] +python_version = 3.6 +exclude = tests/unit/resources/ diff --git a/noxfile.py b/noxfile.py index 197b231..67af2e7 100644 --- a/noxfile.py +++ b/noxfile.py @@ -27,6 +27,7 @@ "lint", "blacken", "lint_setup_py", + "mypy", "unit", "check_lower_bounds" ] @@ -74,6 +75,18 @@ def lint_setup_py(session): session.run("python", "setup.py", "check", "--restructuredtext", "--strict") +@nox.session(python="3.6") +def mypy(session): + """Verify type hints are mypy compatible.""" + session.install("-e", ".") + session.install( + "mypy", + "types-mock", + "types-setuptools", + ) + session.run("mypy", "test_utils/", "tests/") + + @nox.session(python=["3.6", "3.7", "3.8", "3.9", "3.10"]) def unit(session): constraints_path = str( diff --git a/test_utils/lower_bound_checker/lower_bound_checker.py b/test_utils/lower_bound_checker/lower_bound_checker.py index 7a8e65b..c51fd57 100644 --- a/test_utils/lower_bound_checker/lower_bound_checker.py +++ b/test_utils/lower_bound_checker/lower_bound_checker.py @@ -33,7 +33,8 @@ def _get_package_requirements(package_name: str) -> List[Requirement]: List[pkg_resources.Requirement]: A list of package requirements and extras. """ dist = pkg_resources.get_distribution(package_name) - requirements = [Requirement(str(r)) for r in dist.requires(extras=dist.extras)] + extras = tuple(dist.extras) + requirements = [Requirement(str(r)) for r in dist.requires(extras=extras)] return requirements diff --git a/test_utils/prefixer.py b/test_utils/prefixer.py index 6d85867..dd8c832 100644 --- a/test_utils/prefixer.py +++ b/test_utils/prefixer.py @@ -16,6 +16,7 @@ import random import re +from typing import Union _RESOURCE_DATE_FORMAT = "%Y%m%d%H%M%S" _RESOURCE_DATE_LENGTH = 4 + 2 + 2 + 2 + 2 + 2 @@ -61,7 +62,7 @@ def create_prefix(self) -> str: random_string = hex(random.randrange(0x1000000))[2:] return f"{self._prefix}{self._separator}{timestamp}{self._separator}{random_string}" - def _name_to_date(self, resource_name: str) -> datetime.datetime: + def _name_to_date(self, resource_name: str) -> Union[datetime.datetime, None]: start_date = len(self._prefix) + len(self._separator) date_string = resource_name[start_date : start_date + _RESOURCE_DATE_LENGTH] try: diff --git a/test_utils/py.typed b/test_utils/py.typed new file mode 100644 index 0000000..7f6cc03 --- /dev/null +++ b/test_utils/py.typed @@ -0,0 +1,2 @@ +# Marker file for PEP 561. +# The test_utils package uses inline types. diff --git a/test_utils/system.py b/test_utils/system.py index 119fbb1..18a2930 100644 --- a/test_utils/system.py +++ b/test_utils/system.py @@ -17,8 +17,8 @@ import sys import time -import google.auth.credentials -from google.auth.environment_vars import CREDENTIALS as TEST_CREDENTIALS +import google.auth.credentials # type: ignore +from google.auth.environment_vars import CREDENTIALS as TEST_CREDENTIALS # type: ignore # From shell environ. May be None. diff --git a/test_utils/vpcsc_config.py b/test_utils/vpcsc_config.py index 36b15d6..c5e36e7 100644 --- a/test_utils/vpcsc_config.py +++ b/test_utils/vpcsc_config.py @@ -16,7 +16,7 @@ import os -import pytest +import pytest # type: ignore INSIDE_VPCSC_ENVVAR = "GOOGLE_CLOUD_TESTS_IN_VPCSC" diff --git a/tests/unit/test_lower_bound_checker.py b/tests/unit/test_lower_bound_checker.py index 51da2e7..ab3ea0c 100644 --- a/tests/unit/test_lower_bound_checker.py +++ b/tests/unit/test_lower_bound_checker.py @@ -19,7 +19,7 @@ from typing import List from click.testing import CliRunner -import pytest +import pytest # type: ignore from test_utils.lower_bound_checker import lower_bound_checker @@ -45,7 +45,7 @@ def parse_error_msg(msg: str) -> List[str]: reqs = [] if match: - reqs = match.groups(1)[0].split(",") + reqs = match.groups(1)[0].split(",") # type: ignore reqs = [r.strip().replace("'", "").replace('"', "") for r in reqs] return reqs diff --git a/tests/unit/test_orchestrate.py b/tests/unit/test_orchestrate.py index 03c2675..d3e42a4 100644 --- a/tests/unit/test_orchestrate.py +++ b/tests/unit/test_orchestrate.py @@ -18,9 +18,9 @@ try: from unittest import mock except ImportError: # pragma: NO PY3 COVER - import mock + import mock # type: ignore -import pytest +import pytest # type: ignore from test_utils import orchestrate diff --git a/tests/unit/test_prefixer.py b/tests/unit/test_prefixer.py index 37157cc..aab1f5d 100644 --- a/tests/unit/test_prefixer.py +++ b/tests/unit/test_prefixer.py @@ -15,7 +15,7 @@ import datetime import re -import pytest +import pytest # type: ignore import test_utils.prefixer