diff options
author | Matt Clay <matt@mystile.com> | 2022-08-19 10:05:43 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-19 10:05:43 -0700 |
commit | fd1935048c47ac3e13e972b47e9eaf9bcdce6da8 (patch) | |
tree | d29892e002d61a42379e197fc3be9a589038ad94 | |
parent | d6b40a5bc6e52c1fef4f7b524c0f31dfba307cac (diff) | |
download | ansible-fd1935048c47ac3e13e972b47e9eaf9bcdce6da8.tar.gz |
Update mypy test. Fix type hints for Python 3.9. (#78587)
This also bumps the minimum controller version (for mypy only) to Python 3.9.
(cherry picked from commit cc5ac88c4c97a7f538f135cb659c73c4bbdd02ef)
-rw-r--r-- | lib/ansible/galaxy/collection/__init__.py | 2 | ||||
-rw-r--r-- | lib/ansible/galaxy/collection/concrete_artifact_manager.py | 36 | ||||
-rw-r--r-- | lib/ansible/galaxy/collection/gpg.py | 2 | ||||
-rw-r--r-- | lib/ansible/galaxy/dependency_resolution/providers.py | 4 | ||||
-rw-r--r-- | test/lib/ansible_test/_data/requirements/sanity.mypy.in | 3 | ||||
-rw-r--r-- | test/lib/ansible_test/_data/requirements/sanity.mypy.txt | 12 | ||||
-rw-r--r-- | test/lib/ansible_test/_internal/commands/sanity/mypy.py | 19 | ||||
-rw-r--r-- | test/sanity/ignore.txt | 1 |
8 files changed, 46 insertions, 33 deletions
diff --git a/lib/ansible/galaxy/collection/__init__.py b/lib/ansible/galaxy/collection/__init__.py index 220285adba..9812bcade5 100644 --- a/lib/ansible/galaxy/collection/__init__.py +++ b/lib/ansible/galaxy/collection/__init__.py @@ -180,7 +180,7 @@ class CollectionVerifyResult: def verify_local_collection( local_collection, remote_collection, artifacts_manager, -): # type: (Candidate, Candidate | None, ConcreteArtifactsManager) -> CollectionVerifyResult +): # type: (Candidate, t.Optional[Candidate], ConcreteArtifactsManager) -> CollectionVerifyResult """Verify integrity of the locally installed collection. :param local_collection: Collection being checked. diff --git a/lib/ansible/galaxy/collection/concrete_artifact_manager.py b/lib/ansible/galaxy/collection/concrete_artifact_manager.py index 1ef7eed28c..4115aeed80 100644 --- a/lib/ansible/galaxy/collection/concrete_artifact_manager.py +++ b/lib/ansible/galaxy/collection/concrete_artifact_manager.py @@ -100,7 +100,7 @@ class ConcreteArtifactsManager: self._require_build_metadata = value def get_galaxy_artifact_source_info(self, collection): - # type: (Candidate) -> dict[str, str | list[dict[str, str]]] + # type: (Candidate) -> dict[str, t.Union[str, list[dict[str, str]]]] server = collection.src.api_server try: @@ -124,7 +124,7 @@ class ConcreteArtifactsManager: } def get_galaxy_artifact_path(self, collection): - # type: (Candidate | Requirement) -> bytes + # type: (t.Union[Candidate, Requirement]) -> bytes """Given a Galaxy-stored collection, return a cached path. If it's not yet on disk, this method downloads the artifact first. @@ -184,7 +184,7 @@ class ConcreteArtifactsManager: return b_artifact_path def get_artifact_path(self, collection): - # type: (Candidate | Requirement) -> bytes + # type: (t.Union[Candidate, Requirement]) -> bytes """Given a concrete collection pointer, return a cached path. If it's not yet on disk, this method downloads the artifact first. @@ -249,15 +249,15 @@ class ConcreteArtifactsManager: return b_artifact_path def _get_direct_collection_namespace(self, collection): - # type: (Candidate) -> str | None + # type: (Candidate) -> t.Optional[str] return self.get_direct_collection_meta(collection)['namespace'] # type: ignore[return-value] def _get_direct_collection_name(self, collection): - # type: (Candidate) -> str | None + # type: (Candidate) -> t.Optional[str] return self.get_direct_collection_meta(collection)['name'] # type: ignore[return-value] def get_direct_collection_fqcn(self, collection): - # type: (Candidate) -> str | None + # type: (Candidate) -> t.Optional[str] """Extract FQCN from the given on-disk collection artifact. If the collection is virtual, ``None`` is returned instead @@ -273,17 +273,17 @@ class ConcreteArtifactsManager: )) def get_direct_collection_version(self, collection): - # type: (Candidate | Requirement) -> str + # type: (t.Union[Candidate, Requirement]) -> str """Extract version from the given on-disk collection artifact.""" return self.get_direct_collection_meta(collection)['version'] # type: ignore[return-value] def get_direct_collection_dependencies(self, collection): - # type: (Candidate | Requirement) -> dict[str, str] + # type: (t.Union[Candidate, Requirement]) -> dict[str, str] """Extract deps from the given on-disk collection artifact.""" return self.get_direct_collection_meta(collection)['dependencies'] # type: ignore[return-value] def get_direct_collection_meta(self, collection): - # type: (Candidate | Requirement) -> dict[str, str | dict[str, str] | list[str] | None] + # type: (t.Union[Candidate, Requirement]) -> dict[str, t.Union[str, dict[str, str], list[str], None]] """Extract meta from the given on-disk collection artifact.""" try: # FIXME: use unique collection identifier as a cache key? return self._artifact_meta_cache[collection.src] @@ -457,7 +457,7 @@ def _extract_collection_from_git(repo_url, coll_ver, b_path): # FIXME: use random subdirs while preserving the file names def _download_file(url, b_path, expected_hash, validate_certs, token=None, timeout=60): - # type: (str, bytes, str | None, bool, GalaxyToken, int) -> bytes + # type: (str, bytes, t.Optional[str], bool, GalaxyToken, int) -> bytes # ^ NOTE: used in download and verify_collections ^ b_tarball_name = to_bytes( url.rsplit('/', 1)[1], errors='surrogate_or_strict', @@ -513,15 +513,15 @@ def _consume_file(read_from, write_to=None): def _normalize_galaxy_yml_manifest( - galaxy_yml, # type: dict[str, str | list[str] | dict[str, str] | None] + galaxy_yml, # type: dict[str, t.Union[str, list[str], dict[str, str], None]] b_galaxy_yml_path, # type: bytes require_build_metadata=True, # type: bool ): - # type: (...) -> dict[str, str | list[str] | dict[str, str] | None] + # type: (...) -> dict[str, t.Union[str, list[str], dict[str, str], None]] galaxy_yml_schema = ( get_collections_galaxy_meta_info() ) # type: list[dict[str, t.Any]] # FIXME: <-- - # FIXME: 👆maybe precise type: list[dict[str, bool | str | list[str]]] + # FIXME: 👆maybe precise type: list[dict[str, t.Union[bool, str, list[str]]]] mandatory_keys = set() string_keys = set() # type: set[str] @@ -588,7 +588,7 @@ def _normalize_galaxy_yml_manifest( def _get_meta_from_dir( b_path, # type: bytes require_build_metadata=True, # type: bool -): # type: (...) -> dict[str, str | list[str] | dict[str, str] | None] +): # type: (...) -> dict[str, t.Union[str, list[str], dict[str, str], None]] try: return _get_meta_from_installed_dir(b_path) except LookupError: @@ -598,7 +598,7 @@ def _get_meta_from_dir( def _get_meta_from_src_dir( b_path, # type: bytes require_build_metadata=True, # type: bool -): # type: (...) -> dict[str, str | list[str] | dict[str, str] | None] +): # type: (...) -> dict[str, t.Union[str, list[str], dict[str, str], None]] galaxy_yml = os.path.join(b_path, _GALAXY_YAML) if not os.path.isfile(galaxy_yml): raise LookupError( @@ -667,7 +667,7 @@ def _get_json_from_installed_dir( def _get_meta_from_installed_dir( b_path, # type: bytes -): # type: (...) -> dict[str, str | list[str] | dict[str, str] | None] +): # type: (...) -> dict[str, t.Union[str, list[str], dict[str, str], None]] manifest = _get_json_from_installed_dir(b_path, MANIFEST_FILENAME) collection_info = manifest['collection_info'] @@ -688,7 +688,7 @@ def _get_meta_from_installed_dir( def _get_meta_from_tar( b_path, # type: bytes -): # type: (...) -> dict[str, str | list[str] | dict[str, str] | None] +): # type: (...) -> dict[str, t.Union[str, list[str], dict[str, str], None]] if not tarfile.is_tarfile(b_path): raise AnsibleError( "Collection artifact at '{path!s}' is not a valid tar file.". @@ -736,7 +736,7 @@ def _tarfile_extract( tar, # type: tarfile.TarFile member, # type: tarfile.TarInfo ): - # type: (...) -> t.Iterator[tuple[tarfile.TarInfo, t.IO[bytes] | None]] + # type: (...) -> t.Iterator[tuple[tarfile.TarInfo, t.Optional[t.IO[bytes]]]] tar_obj = tar.extractfile(member) try: yield member, tar_obj diff --git a/lib/ansible/galaxy/collection/gpg.py b/lib/ansible/galaxy/collection/gpg.py index f684de162b..8641f0d7f7 100644 --- a/lib/ansible/galaxy/collection/gpg.py +++ b/lib/ansible/galaxy/collection/gpg.py @@ -25,7 +25,7 @@ IS_PY310_PLUS = sys.version_info[:2] >= (3, 10) frozen_dataclass = partial(dataclass, frozen=True, **({'slots': True} if IS_PY310_PLUS else {})) -def get_signature_from_source(source, display=None): # type: (str, Display | None) -> str +def get_signature_from_source(source, display=None): # type: (str, t.Optional[Display]) -> str if display is not None: display.vvvv(f"Using signature at {source}") try: diff --git a/lib/ansible/galaxy/dependency_resolution/providers.py b/lib/ansible/galaxy/dependency_resolution/providers.py index 947fae61cd..ccb56a9d79 100644 --- a/lib/ansible/galaxy/dependency_resolution/providers.py +++ b/lib/ansible/galaxy/dependency_resolution/providers.py @@ -169,7 +169,7 @@ class CollectionDependencyProviderBase(AbstractProvider): return False def identify(self, requirement_or_candidate): - # type: (Candidate | Requirement) -> str + # type: (t.Union[Candidate, Requirement]) -> str """Given requirement or candidate, return an identifier for it. This is used to identify a requirement or candidate, e.g. @@ -181,7 +181,7 @@ class CollectionDependencyProviderBase(AbstractProvider): return requirement_or_candidate.canonical_package_id def get_preference(self, *args, **kwargs): - # type: (t.Any, t.Any) -> float | int + # type: (t.Any, t.Any) -> t.Union[float, int] """Return sort key function return value for given requirement. This result should be based on preference that is defined as diff --git a/test/lib/ansible_test/_data/requirements/sanity.mypy.in b/test/lib/ansible_test/_data/requirements/sanity.mypy.in index b7b8229794..890caf30f4 100644 --- a/test/lib/ansible_test/_data/requirements/sanity.mypy.in +++ b/test/lib/ansible_test/_data/requirements/sanity.mypy.in @@ -2,8 +2,9 @@ mypy[python2] packaging # type stubs not published separately types-backports types-jinja2 -types-paramiko +types-paramiko < 2.8.14 # newer versions drop support for Python 2.7 types-pyyaml < 6 # PyYAML 6+ stubs do not support Python 2.7 +types-cryptography < 3.3.16 # newer versions drop support for Python 2.7 types-requests types-setuptools types-toml diff --git a/test/lib/ansible_test/_data/requirements/sanity.mypy.txt b/test/lib/ansible_test/_data/requirements/sanity.mypy.txt index d4baf5630d..e448c9074e 100644 --- a/test/lib/ansible_test/_data/requirements/sanity.mypy.txt +++ b/test/lib/ansible_test/_data/requirements/sanity.mypy.txt @@ -1,10 +1,10 @@ # edit "sanity.mypy.in" and generate with: hacking/update-sanity-requirements.py --test mypy -mypy==0.931 +mypy==0.950 mypy-extensions==0.4.3 packaging==21.2 pyparsing==2.4.7 tomli==2.0.1 -typed-ast==1.5.2 +typed-ast==1.5.3 types-backports==0.1.3 types-cryptography==3.3.15 types-enum34==1.1.8 @@ -13,8 +13,8 @@ types-Jinja2==2.11.9 types-MarkupSafe==1.1.10 types-paramiko==2.8.13 types-PyYAML==5.4.12 -types-requests==2.27.10 -types-setuptools==57.4.9 -types-toml==0.10.4 -types-urllib3==1.26.9 +types-requests==2.27.25 +types-setuptools==57.4.14 +types-toml==0.10.6 +types-urllib3==1.26.14 typing-extensions==3.10.0.2 diff --git a/test/lib/ansible_test/_internal/commands/sanity/mypy.py b/test/lib/ansible_test/_internal/commands/sanity/mypy.py index 5b83aa8b9f..fe664ddc9f 100644 --- a/test/lib/ansible_test/_internal/commands/sanity/mypy.py +++ b/test/lib/ansible_test/_internal/commands/sanity/mypy.py @@ -90,11 +90,22 @@ class MypyTest(SanityMultipleVersion): display.warning(f'Skipping sanity test "{self.name}" due to missing virtual environment support on Python {args.controller_python.version}.') return SanitySkipped(self.name, python.version) + # Temporary hack to make Python 3.8 a remote-only Python version since we'll be dropping controller support for it soon. + # This avoids having to change annotations or add ignores for issues that are specific to that version. + + change_version = '3.8' + + if change_version not in CONTROLLER_PYTHON_VERSIONS or change_version in REMOTE_ONLY_PYTHON_VERSIONS: + raise Exception(f'Remove this hack now that Python {change_version} is not supported by the controller.') + + controller_python_versions = tuple(version for version in CONTROLLER_PYTHON_VERSIONS if version != change_version) + remote_only_python_versions = REMOTE_ONLY_PYTHON_VERSIONS + (change_version,) + contexts = ( - MyPyContext('ansible-test', ['test/lib/ansible_test/_util/target/sanity/import/'], CONTROLLER_PYTHON_VERSIONS), - MyPyContext('ansible-test', ['test/lib/ansible_test/_internal/'], CONTROLLER_PYTHON_VERSIONS), - MyPyContext('ansible-core', ['lib/ansible/'], CONTROLLER_PYTHON_VERSIONS), - MyPyContext('modules', ['lib/ansible/modules/', 'lib/ansible/module_utils/'], REMOTE_ONLY_PYTHON_VERSIONS), + MyPyContext('ansible-test', ['test/lib/ansible_test/_util/target/sanity/import/'], controller_python_versions), + MyPyContext('ansible-test', ['test/lib/ansible_test/_internal/'], controller_python_versions), + MyPyContext('ansible-core', ['lib/ansible/'], controller_python_versions), + MyPyContext('modules', ['lib/ansible/modules/', 'lib/ansible/module_utils/'], remote_only_python_versions), ) unfiltered_messages = [] # type: t.List[SanityMessage] diff --git a/test/sanity/ignore.txt b/test/sanity/ignore.txt index 0d2bb3520f..9f4b55d85d 100644 --- a/test/sanity/ignore.txt +++ b/test/sanity/ignore.txt @@ -252,6 +252,7 @@ lib/ansible/module_utils/six/__init__.py mypy-2.7:assignment # vendored code lib/ansible/module_utils/six/__init__.py mypy-3.5:assignment # vendored code lib/ansible/module_utils/six/__init__.py mypy-3.6:assignment # vendored code lib/ansible/module_utils/six/__init__.py mypy-3.7:assignment # vendored code +lib/ansible/module_utils/six/__init__.py mypy-3.8:assignment # vendored code lib/ansible/module_utils/six/__init__.py mypy-2.7:misc # vendored code lib/ansible/module_utils/six/__init__.py mypy-3.5:misc # vendored code lib/ansible/module_utils/six/__init__.py mypy-3.6:misc # vendored code |