From 2461a7bfe53c44d41fb45d712d9f51fb9780146a Mon Sep 17 00:00:00 2001 From: finswimmer Date: Sun, 14 Nov 2021 11:14:59 +0100 Subject: [PATCH 1/5] change type annotations to type hints using com2ann --- tests/conftest.py | 26 +++++++++++++------------- tests/pyproject/conftest.py | 6 +++--- tests/testutils.py | 14 +++++++------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 5ff99b202..69cbc6a44 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -27,8 +27,8 @@ def pytest_configure(config): config.option.markexpr = "not integration" -def get_project_from_dir(base_directory): # type: (Path) -> Callable[[str], Path] - def get(name): # type: (str) -> Path +def get_project_from_dir(base_directory: Path) -> Callable[[str], Path]: + def get(name: str) -> Path: path = base_directory / name if not path.exists(): raise FileNotFoundError(str(path)) @@ -38,45 +38,45 @@ def get(name): # type: (str) -> Path @pytest.fixture(scope="session") -def project_source_root(): # type: () -> Path +def project_source_root() -> Path: return Path(__file__).parent.parent @pytest.fixture(scope="session") -def project_source_test_root(): # type: () -> Path +def project_source_test_root() -> Path: return Path(__file__).parent @pytest.fixture(scope="session") -def common_fixtures_directory(project_source_test_root): # type: (Path) -> Path +def common_fixtures_directory(project_source_test_root: Path) -> Path: return project_source_test_root / "fixtures" @pytest.fixture(scope="session") -def common_project(common_fixtures_directory): # type: (Path) -> Callable[[str], Path] +def common_project(common_fixtures_directory: Path) -> Callable[[str], Path]: return get_project_from_dir(common_fixtures_directory) @pytest.fixture(scope="session") -def masonry_fixtures_directory(project_source_test_root): # type: (Path) -> Path +def masonry_fixtures_directory(project_source_test_root: Path) -> Path: return project_source_test_root / "masonry" / "builders" / "fixtures" @pytest.fixture(scope="session") def masonry_project( - masonry_fixtures_directory, -): # type: (Path) -> Callable[[str], Path] + masonry_fixtures_directory: Path, +) -> Callable[[str], Path]: return get_project_from_dir(masonry_fixtures_directory) @pytest.fixture -def temporary_directory(): # type: () -> Path +def temporary_directory() -> Path: with tempfile.TemporaryDirectory(prefix="poetry-core") as tmp: yield Path(tmp) @pytest.fixture -def venv(temporary_directory): # type: (Path) -> Path +def venv(temporary_directory: Path) -> Path: venv_dir = temporary_directory / ".venv" virtualenv.cli_run( [ @@ -91,10 +91,10 @@ def venv(temporary_directory): # type: (Path) -> Path @pytest.fixture -def python(venv): # type: (Path) -> str +def python(venv: Path) -> str: return (venv / "bin" / "python").as_posix() @pytest.fixture() -def f(): # type: () -> Factory +def f() -> Factory: return Factory() diff --git a/tests/pyproject/conftest.py b/tests/pyproject/conftest.py index 31df17f78..0d24a2758 100644 --- a/tests/pyproject/conftest.py +++ b/tests/pyproject/conftest.py @@ -4,7 +4,7 @@ @pytest.fixture -def pyproject_toml(tmp_path): # type: (Path) -> Path +def pyproject_toml(tmp_path: Path) -> Path: path = tmp_path / "pyproject.toml" with path.open(mode="w"): pass @@ -12,7 +12,7 @@ def pyproject_toml(tmp_path): # type: (Path) -> Path @pytest.fixture -def build_system_section(pyproject_toml): # type: (Path) -> str +def build_system_section(pyproject_toml: Path) -> str: content = """ [build-system] requires = ["poetry-core"] @@ -24,7 +24,7 @@ def build_system_section(pyproject_toml): # type: (Path) -> str @pytest.fixture -def poetry_section(pyproject_toml): # type: (Path) -> str +def poetry_section(pyproject_toml: Path) -> str: content = """ [tool.poetry] name = "poetry" diff --git a/tests/testutils.py b/tests/testutils.py index 4b335e790..6bea2b85d 100644 --- a/tests/testutils.py +++ b/tests/testutils.py @@ -31,8 +31,8 @@ @contextmanager def temporary_project_directory( - path, toml_patch=None -): # type: (Path, Optional[Dict[str, Any]]) -> ContextManager[str] + path: Path, toml_patch: Optional[Dict[str, Any]] = None +) -> ContextManager[str]: """ Context manager that takes a project source directory, copies content to a temporary directory, patches the `pyproject.toml` using the provided patch, or using the default @@ -57,7 +57,7 @@ def temporary_project_directory( yield str(dst) -def subprocess_run(*args, **kwargs): # type: (str, Any) -> subprocess.CompletedProcess +def subprocess_run(*args: str, **kwargs: Any) -> subprocess.CompletedProcess: """ Helper method to run a subprocess. Asserts for success. """ @@ -70,8 +70,8 @@ def subprocess_run(*args, **kwargs): # type: (str, Any) -> subprocess.Completed def validate_wheel_contents( - name, version, path, files=None -): # type: (str, str, str, Optional[List[str]]) -> None + name: str, version: str, path: str, files: Optional[List[str]] = None +) -> None: dist_info = "{}-{}.dist-info".format(name, version) files = files or [] @@ -83,8 +83,8 @@ def validate_wheel_contents( def validate_sdist_contents( - name, version, path, files -): # type: (str, str, str, List[str]) -> None + name: str, version: str, path: str, files: List[str] +) -> None: with tarfile.open(path) as tar: namelist = tar.getnames() for filename in files: From 15c2bc3c83b08c49456c1d81b91651ce60fe04df Mon Sep 17 00:00:00 2001 From: finswimmer Date: Sun, 14 Nov 2021 11:26:22 +0100 Subject: [PATCH 2/5] add missing type hints to core --- poetry/core/semver/version.py | 2 +- poetry/core/vcs/git.py | 4 ++-- poetry/core/version/parser.py | 3 ++- poetry/core/version/pep440/parser.py | 4 +++- poetry/core/version/pep440/segments.py | 4 ++-- poetry/core/version/pep440/version.py | 13 +++++++++---- 6 files changed, 19 insertions(+), 11 deletions(-) diff --git a/poetry/core/semver/version.py b/poetry/core/semver/version.py index 64ae8fe43..529593998 100644 --- a/poetry/core/semver/version.py +++ b/poetry/core/semver/version.py @@ -171,7 +171,7 @@ def from_parts( post: Optional[ReleaseTag] = None, dev: Optional[ReleaseTag] = None, local: "LocalSegmentType" = None, - ): + ) -> "Version": return cls( release=Release(major=major, minor=minor, patch=patch, extra=extra), pre=pre, diff --git a/poetry/core/vcs/git.py b/poetry/core/vcs/git.py index b311746bf..620698a75 100644 --- a/poetry/core/vcs/git.py +++ b/poetry/core/vcs/git.py @@ -188,7 +188,7 @@ def __str__(self) -> str: _executable: Optional[str] = None -def executable(): +def executable() -> str: global _executable if _executable is not None: @@ -220,7 +220,7 @@ def executable(): return _executable -def _reset_executable(): +def _reset_executable() -> None: global _executable _executable = None diff --git a/poetry/core/version/parser.py b/poetry/core/version/parser.py index 252736d56..52270ad90 100644 --- a/poetry/core/version/parser.py +++ b/poetry/core/version/parser.py @@ -1,5 +1,6 @@ from pathlib import Path from typing import TYPE_CHECKING +from typing import Any from typing import Optional @@ -17,7 +18,7 @@ def __init__( self._debug = debug self._lark: Optional["Lark"] = None - def parse(self, text: str, **kwargs) -> "Tree": + def parse(self, text: str, **kwargs: Any) -> "Tree": from lark import Lark if self._lark is None: diff --git a/poetry/core/version/pep440/parser.py b/poetry/core/version/pep440/parser.py index 08962c53a..51a8842ac 100644 --- a/poetry/core/version/pep440/parser.py +++ b/poetry/core/version/pep440/parser.py @@ -61,7 +61,9 @@ def _get_local(cls, match: Optional[Match[AnyStr]]) -> Optional[LocalSegmentType ) @classmethod - def parse(cls, value: str, version_class: Optional[Type["PEP440Version"]] = None): + def parse( + cls, value: str, version_class: Optional[Type["PEP440Version"]] = None + ) -> "PEP440Version": match = cls._regex.search(value) if value else None if not match: raise InvalidVersion(f"Invalid PEP 440 version: '{value}'") diff --git a/poetry/core/version/pep440/segments.py b/poetry/core/version/pep440/segments.py index 3f4562afc..7d73704b1 100644 --- a/poetry/core/version/pep440/segments.py +++ b/poetry/core/version/pep440/segments.py @@ -39,7 +39,7 @@ class Release: default=None, init=False, compare=True ) - def __post_init__(self): + def __post_init__(self) -> None: if self.extra is None: object.__setattr__(self, "extra", ()) elif not isinstance(self.extra, tuple): @@ -110,7 +110,7 @@ class ReleaseTag: phase: str number: int = dataclasses.field(default=0) - def __post_init__(self): + def __post_init__(self) -> None: object.__setattr__(self, "phase", self.expand(self.phase)) @classmethod diff --git a/poetry/core/version/pep440/version.py b/poetry/core/version/pep440/version.py index 2837bd195..8aaf6545e 100644 --- a/poetry/core/version/pep440/version.py +++ b/poetry/core/version/pep440/version.py @@ -1,6 +1,7 @@ import dataclasses import math +from typing import Any from typing import Optional from typing import Tuple from typing import Union @@ -32,7 +33,7 @@ class PEP440Version: int, Release, ReleaseTag, ReleaseTag, ReleaseTag, Tuple[Union[int, str], ...] ] = dataclasses.field(default=None, init=False, compare=True) - def __post_init__(self): + def __post_init__(self) -> None: if self.local is not None and not isinstance(self.local, tuple): object.__setattr__(self, "local", (self.local,)) @@ -46,7 +47,11 @@ def __post_init__(self): object.__setattr__(self, "_compare_key", self._make_compare_key()) - def _make_compare_key(self): + def _make_compare_key( + self, + ) -> Tuple[ + int, Release, ReleaseTag, ReleaseTag, ReleaseTag, Tuple[Tuple[float, str], ...] + ]: """ This code is based on the implementation of packaging.version._cmpkey(..) """ @@ -103,7 +108,7 @@ def patch(self) -> Optional[int]: def non_semver_parts(self) -> Optional[Tuple[int]]: return self.release.extra - def to_string(self, short=False): + def to_string(self, short: bool = False) -> str: dash = "-" if not short else "" version_string = dash.join( @@ -209,7 +214,7 @@ def first_prerelease(self) -> "PEP440Version": epoch=self.epoch, release=self.release, pre=ReleaseTag(RELEASE_PHASE_ALPHA) ) - def replace(self, **kwargs): + def replace(self, **kwargs: Any) -> "PEP440Version": return self.__class__( **{ **{ From cc70d6992f4ea441f64f21d1c105d3c091c58c6b Mon Sep 17 00:00:00 2001 From: finswimmer Date: Sun, 14 Nov 2021 18:32:56 +0100 Subject: [PATCH 3/5] add type hints to tests --- tests/conftest.py | 10 +- tests/integration/test_pep517.py | 18 ++-- tests/json/test_poetry_schema.py | 12 ++- tests/masonry/builders/test_builder.py | 19 ++-- tests/masonry/builders/test_complete.py | 10 +- tests/masonry/builders/test_sdist.py | 16 +-- tests/masonry/builders/test_wheel.py | 18 ++-- tests/masonry/test_api.py | 4 +- tests/packages/constraints/test_main.py | 8 +- tests/packages/test_dependency.py | 11 ++- tests/packages/test_directory_dependency.py | 5 +- tests/packages/test_file_dependency.py | 28 ++++-- tests/packages/test_package.py | 21 ++-- tests/packages/test_vcs_dependency.py | 4 +- tests/packages/utils/test_utils.py | 2 +- tests/packages/utils/test_utils_link.py | 2 +- tests/packages/utils/test_utils_urls.py | 3 +- tests/pyproject/test_pyproject_toml.py | 18 ++-- tests/pyproject/test_pyproject_toml_file.py | 12 ++- tests/semver/test_helpers.py | 21 ++-- tests/semver/test_parse_constraint.py | 4 +- tests/semver/test_version.py | 9 +- tests/semver/test_version_range.py | 102 ++++++++++++++------ tests/utils/test_helpers.py | 2 +- tests/vcs/test_vcs.py | 18 +++- tests/version/test_markers.py | 22 +++-- tests/version/test_requirements.py | 22 ++++- tests/version/test_version_pep440.py | 17 ++-- 28 files changed, 302 insertions(+), 136 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 69cbc6a44..76d389c78 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,7 @@ import sys from pathlib import Path +from typing import TYPE_CHECKING from typing import Callable import pytest @@ -10,7 +11,12 @@ from tests.testutils import tempfile -def pytest_addoption(parser): +if TYPE_CHECKING: + from _pytest.config import Config + from _pytest.config.argparsing import Parser + + +def pytest_addoption(parser: "Parser") -> None: parser.addoption( "--integration", action="store_true", @@ -20,7 +26,7 @@ def pytest_addoption(parser): ) -def pytest_configure(config): +def pytest_configure(config: "Config") -> None: config.addinivalue_line("markers", "integration: mark integration tests") if not config.option.integration: diff --git a/tests/integration/test_pep517.py b/tests/integration/test_pep517.py index d5805a7dd..d05f4c5c1 100644 --- a/tests/integration/test_pep517.py +++ b/tests/integration/test_pep517.py @@ -1,4 +1,5 @@ from pathlib import Path +from typing import TYPE_CHECKING import pytest @@ -9,6 +10,9 @@ from tests.testutils import temporary_project_directory +if TYPE_CHECKING: + from _pytest.fixtures import FixtureRequest + pytestmark = pytest.mark.integration @@ -20,16 +24,18 @@ ("masonry_project", "disable_setup_py"), ], ) -def test_pep517_check_poetry_managed(request, getter, project): +def test_pep517_check_poetry_managed( + request: "FixtureRequest", getter: str, project: str +): with temporary_project_directory(request.getfixturevalue(getter)(project)) as path: assert check(path) -def test_pep517_check(project_source_root): +def test_pep517_check(project_source_root: Path): assert check(str(project_source_root)) -def test_pep517_build_sdist(temporary_directory, project_source_root): +def test_pep517_build_sdist(temporary_directory: Path, project_source_root: Path): build( source_dir=str(project_source_root), dist="sdist", dest=str(temporary_directory) ) @@ -37,7 +43,7 @@ def test_pep517_build_sdist(temporary_directory, project_source_root): assert len(distributions) == 1 -def test_pep517_build_wheel(temporary_directory, project_source_root): +def test_pep517_build_wheel(temporary_directory: Path, project_source_root: Path): build( source_dir=str(project_source_root), dist="wheel", dest=str(temporary_directory) ) @@ -45,7 +51,7 @@ def test_pep517_build_wheel(temporary_directory, project_source_root): assert len(distributions) == 1 -def test_pip_wheel_build(temporary_directory, project_source_root): +def test_pip_wheel_build(temporary_directory: Path, project_source_root: Path): tmp = str(temporary_directory) pip = subprocess_run( "pip", "wheel", "--use-pep517", "-w", tmp, str(project_source_root) @@ -58,7 +64,7 @@ def test_pip_wheel_build(temporary_directory, project_source_root): assert len(wheels) == 1 -def test_pip_install_no_binary(python, project_source_root): +def test_pip_install_no_binary(python: str, project_source_root: Path): subprocess_run( python, "-m", diff --git a/tests/json/test_poetry_schema.py b/tests/json/test_poetry_schema.py index e414f7f9d..c2f4d61a5 100644 --- a/tests/json/test_poetry_schema.py +++ b/tests/json/test_poetry_schema.py @@ -1,10 +1,12 @@ +from typing import Dict + import pytest from poetry.core.json import validate_object @pytest.fixture -def base_object(): +def base_object() -> Dict: return { "name": "myapp", "version": "1.0.0", @@ -15,7 +17,7 @@ def base_object(): @pytest.fixture -def multi_url_object(): +def multi_url_object() -> Dict: return { "name": "myapp", "version": "1.0.0", @@ -33,18 +35,18 @@ def multi_url_object(): } -def test_path_dependencies(base_object): +def test_path_dependencies(base_object: Dict): base_object["dependencies"].update({"foo": {"path": "../foo"}}) base_object["dev-dependencies"].update({"foo": {"path": "../foo"}}) assert len(validate_object(base_object, "poetry-schema")) == 0 -def test_multi_url_dependencies(multi_url_object): +def test_multi_url_dependencies(multi_url_object: Dict): assert len(validate_object(multi_url_object, "poetry-schema")) == 0 -def test_multiline_description(base_object): +def test_multiline_description(base_object: Dict): bad_description = "Some multi-\nline string" base_object["description"] = bad_description diff --git a/tests/masonry/builders/test_builder.py b/tests/masonry/builders/test_builder.py index 590266421..a9189d3ee 100644 --- a/tests/masonry/builders/test_builder.py +++ b/tests/masonry/builders/test_builder.py @@ -2,6 +2,9 @@ from email.parser import Parser from pathlib import Path +from typing import TYPE_CHECKING +from typing import Dict +from typing import List import pytest @@ -10,7 +13,11 @@ from poetry.core.utils._compat import PY37 -def test_builder_find_excluded_files(mocker): +if TYPE_CHECKING: + from pytest_mock import MockerFixture + + +def test_builder_find_excluded_files(mocker: "MockerFixture"): p = mocker.patch("poetry.core.vcs.git.Git.get_ignored_files") p.return_value = [] @@ -25,7 +32,7 @@ def test_builder_find_excluded_files(mocker): sys.platform == "win32" and not PY37, reason="Windows is case insensitive for the most part", ) -def test_builder_find_case_sensitive_excluded_files(mocker): +def test_builder_find_case_sensitive_excluded_files(mocker: "MockerFixture"): p = mocker.patch("poetry.core.vcs.git.Git.get_ignored_files") p.return_value = [] @@ -50,7 +57,7 @@ def test_builder_find_case_sensitive_excluded_files(mocker): sys.platform == "win32" and not PY37, reason="Windows is case insensitive for the most part", ) -def test_builder_find_invalid_case_sensitive_excluded_files(mocker): +def test_builder_find_invalid_case_sensitive_excluded_files(mocker: "MockerFixture"): p = mocker.patch("poetry.core.vcs.git.Git.get_ignored_files") p.return_value = [] @@ -189,7 +196,7 @@ def test_invalid_script_files_definition(): "script_callable_legacy_table", ], ) -def test_entrypoint_scripts_legacy_warns(fixture): +def test_entrypoint_scripts_legacy_warns(fixture: str): with pytest.warns(DeprecationWarning): Builder( Factory().create_poetry(Path(__file__).parent / "fixtures" / fixture) @@ -228,7 +235,7 @@ def test_entrypoint_scripts_legacy_warns(fixture): ], ) @pytest.mark.filterwarnings("ignore::DeprecationWarning") -def test_builder_convert_entry_points(fixture, result): +def test_builder_convert_entry_points(fixture: str, result: Dict[str, List[str]]): entry_points = Builder( Factory().create_poetry(Path(__file__).parent / "fixtures" / fixture) ).convert_entry_points() @@ -256,7 +263,7 @@ def test_builder_convert_entry_points(fixture, result): ), ], ) -def test_builder_convert_script_files(fixture, result): +def test_builder_convert_script_files(fixture: str, result: List[Path]): project_root = Path(__file__).parent / "fixtures" / fixture script_files = Builder(Factory().create_poetry(project_root)).convert_script_files() assert [p.relative_to(project_root) for p in script_files] == result diff --git a/tests/masonry/builders/test_complete.py b/tests/masonry/builders/test_complete.py index d110443f8..28c11811a 100644 --- a/tests/masonry/builders/test_complete.py +++ b/tests/masonry/builders/test_complete.py @@ -11,6 +11,7 @@ import zipfile from pathlib import Path +from typing import TYPE_CHECKING import pytest @@ -19,11 +20,14 @@ from poetry.core.masonry.builder import Builder +if TYPE_CHECKING: + from pytest_mock import MockerFixture + fixtures_dir = Path(__file__).parent / "fixtures" @pytest.fixture(autouse=True) -def setup(): +def setup() -> None: clear_samples_dist() yield @@ -31,7 +35,7 @@ def setup(): clear_samples_dist() -def clear_samples_dist(): +def clear_samples_dist() -> None: for dist in fixtures_dir.glob("**/dist"): if dist.is_dir(): shutil.rmtree(str(dist)) @@ -473,7 +477,7 @@ def test_package_src(): zip.close() -def test_package_with_include(mocker): +def test_package_with_include(mocker: "MockerFixture"): module_path = fixtures_dir / "with-include" # Patch git module to return specific excluded files diff --git a/tests/masonry/builders/test_sdist.py b/tests/masonry/builders/test_sdist.py index 7ccd65ee9..30216fc18 100644 --- a/tests/masonry/builders/test_sdist.py +++ b/tests/masonry/builders/test_sdist.py @@ -6,6 +6,7 @@ from email.parser import Parser from pathlib import Path +from typing import TYPE_CHECKING import pytest @@ -17,11 +18,14 @@ from poetry.core.packages.vcs_dependency import VCSDependency +if TYPE_CHECKING: + from pytest_mock import MockerFixture + fixtures_dir = Path(__file__).parent / "fixtures" @pytest.fixture(autouse=True) -def setup(): +def setup() -> None: clear_samples_dist() yield @@ -29,13 +33,13 @@ def setup(): clear_samples_dist() -def clear_samples_dist(): +def clear_samples_dist() -> None: for dist in fixtures_dir.glob("**/dist"): if dist.is_dir(): shutil.rmtree(str(dist)) -def project(name): +def project(name: str) -> Path: return Path(__file__).parent / "fixtures" / name @@ -138,7 +142,7 @@ def test_make_setup(): } -def test_make_pkg_info(mocker): +def test_make_pkg_info(mocker: "MockerFixture"): get_metadata_content = mocker.patch( "poetry.core.masonry.builders.builder.Builder.get_metadata_content" ) @@ -322,7 +326,7 @@ def test_prelease(): @pytest.mark.parametrize("directory", [("extended"), ("extended_legacy_config")]) -def test_with_c_extensions(directory): +def test_with_c_extensions(directory: str): poetry = Factory().create_poetry(project("extended")) builder = SdistBuilder(poetry) @@ -403,7 +407,7 @@ def test_with_src_module_dir(): assert "package-src-0.1/src/package_src/module.py" in tar.getnames() -def test_default_with_excluded_data(mocker): +def test_default_with_excluded_data(mocker: "MockerFixture"): # Patch git module to return specific excluded files p = mocker.patch("poetry.core.vcs.git.Git.get_ignored_files") p.return_value = [ diff --git a/tests/masonry/builders/test_wheel.py b/tests/masonry/builders/test_wheel.py index 9a54ea9f2..cca2354a7 100644 --- a/tests/masonry/builders/test_wheel.py +++ b/tests/masonry/builders/test_wheel.py @@ -3,6 +3,8 @@ import zipfile from pathlib import Path +from typing import TYPE_CHECKING +from typing import Any import pytest @@ -11,11 +13,15 @@ from tests.masonry.builders.test_sdist import project +if TYPE_CHECKING: + from _pytest.monkeypatch import MonkeyPatch + from pytest_mock import MockerFixture + fixtures_dir = Path(__file__).parent / "fixtures" @pytest.fixture(autouse=True) -def setup(): +def setup() -> None: clear_samples_dist() yield @@ -23,7 +29,7 @@ def setup(): clear_samples_dist() -def clear_samples_dist(): +def clear_samples_dist() -> None: for dist in fixtures_dir.glob("**/dist"): if dist.is_dir(): shutil.rmtree(str(dist)) @@ -191,7 +197,7 @@ def test_wheel_includes_inline_table(): "package", ["pep_561_stub_only", "pep_561_stub_only_partial", "pep_561_stub_only_src"], ) -def test_wheel_package_pep_561_stub_only(package): +def test_wheel_package_pep_561_stub_only(package: str): root = fixtures_dir / package WheelBuilder.make(Factory().create_poetry(root)) @@ -247,7 +253,7 @@ def test_wheel_with_file_with_comma(): assert '\n"comma_file/a,b.py"' in records.decode() -def test_default_src_with_excluded_data(mocker): +def test_default_src_with_excluded_data(mocker: "MockerFixture"): # Patch git module to return specific excluded files p = mocker.patch("poetry.core.vcs.git.Git.get_ignored_files") p.return_value = [ @@ -288,7 +294,7 @@ def test_default_src_with_excluded_data(mocker): assert "my_package/data/sub_data/data3.txt" in names -def test_wheel_file_is_closed(monkeypatch): +def test_wheel_file_is_closed(monkeypatch: "MonkeyPatch"): """Confirm that wheel zip files are explicitly closed.""" # Using a list is a hack for Python 2.7 compatibility. @@ -296,7 +302,7 @@ def test_wheel_file_is_closed(monkeypatch): real_fdopen = os.fdopen - def capturing_fdopen(*args, **kwargs): + def capturing_fdopen(*args: Any, **kwargs: Any): fd_file[0] = real_fdopen(*args, **kwargs) return fd_file[0] diff --git a/tests/masonry/test_api.py b/tests/masonry/test_api.py index 040a0a5e9..74ba6ac81 100644 --- a/tests/masonry/test_api.py +++ b/tests/masonry/test_api.py @@ -7,6 +7,8 @@ from contextlib import contextmanager from pathlib import Path +from typing import Iterator +from typing import Union import pytest @@ -18,7 +20,7 @@ @contextmanager -def cwd(directory): +def cwd(directory: Union[str, Path]) -> Iterator[None]: prev = os.getcwd() os.chdir(str(directory)) try: diff --git a/tests/packages/constraints/test_main.py b/tests/packages/constraints/test_main.py index 0769a47a0..4aa6b243c 100644 --- a/tests/packages/constraints/test_main.py +++ b/tests/packages/constraints/test_main.py @@ -1,3 +1,5 @@ +from typing import Union + import pytest from poetry.core.packages.constraints import parse_constraint @@ -18,7 +20,7 @@ ("!= win32", Constraint("win32", "!=")), ], ) -def test_parse_constraint(input, constraint): +def test_parse_constraint(input: str, constraint: Union[AnyConstraint, Constraint]): assert parse_constraint(input) == constraint @@ -39,7 +41,7 @@ def test_parse_constraint(input, constraint): ), ], ) -def test_parse_constraint_multi(input, constraint): +def test_parse_constraint_multi(input: str, constraint: MultiConstraint): assert parse_constraint(input) == constraint @@ -53,5 +55,5 @@ def test_parse_constraint_multi(input, constraint): ), ], ) -def test_parse_constraint_union(input, constraint): +def test_parse_constraint_union(input: str, constraint: UnionConstraint): assert parse_constraint(input) == constraint diff --git a/tests/packages/test_dependency.py b/tests/packages/test_dependency.py index a0e9d2524..960c4b1d1 100644 --- a/tests/packages/test_dependency.py +++ b/tests/packages/test_dependency.py @@ -1,3 +1,6 @@ +from typing import List +from typing import Optional + import pytest from poetry.core.packages.dependency import Dependency @@ -25,7 +28,7 @@ def test_accepts(): ("^1.0.0-1", False), ], ) -def test_allows_prerelease(constraint, result): +def test_allows_prerelease(constraint: str, result: bool): assert Dependency("A", constraint).allows_prereleases() == result @@ -162,7 +165,7 @@ def test_to_pep_508_with_single_version_excluded(): ("== 3.5.4", 'python_full_version == "3.5.4"'), ], ) -def test_to_pep_508_with_patch_python_version(python_versions, marker): +def test_to_pep_508_with_patch_python_version(python_versions: str, marker: str): dependency = Dependency("Django", "^1.23") dependency.python_versions = python_versions @@ -240,7 +243,9 @@ def test_complete_name(): ), ], ) -def test_dependency_string_representation(name, constraint, extras, expected): +def test_dependency_string_representation( + name: str, constraint: str, extras: Optional[List[str]], expected: str +): dependency = Dependency(name=name, constraint=constraint, extras=extras) assert str(dependency) == expected diff --git a/tests/packages/test_directory_dependency.py b/tests/packages/test_directory_dependency.py index a69364532..27fc850e5 100644 --- a/tests/packages/test_directory_dependency.py +++ b/tests/packages/test_directory_dependency.py @@ -1,4 +1,5 @@ from pathlib import Path +from typing import Optional import pytest @@ -14,7 +15,9 @@ def test_directory_dependency_must_exist(): DirectoryDependency("demo", DIST_PATH / "invalid") -def _test_directory_dependency_pep_508(name, path, pep_508_input, pep_508_output=None): +def _test_directory_dependency_pep_508( + name: str, path: Path, pep_508_input: str, pep_508_output: Optional[str] = None +) -> None: dep = Dependency.create_from_pep_508( pep_508_input, relative_to=Path(__file__).parent ) diff --git a/tests/packages/test_file_dependency.py b/tests/packages/test_file_dependency.py index c3c1b8ddb..b1dbd2a3e 100644 --- a/tests/packages/test_file_dependency.py +++ b/tests/packages/test_file_dependency.py @@ -1,4 +1,6 @@ from pathlib import Path +from typing import TYPE_CHECKING +from typing import Optional import pytest @@ -7,6 +9,11 @@ from poetry.core.version.markers import SingleMarker +if TYPE_CHECKING: + from pytest_mock import MockerFixture + + from poetry.core.version.markers import BaseMarker + DIST_PATH = Path(__file__).parent.parent / "fixtures" / "distributions" TEST_FILE = "demo-0.1.0.tar.gz" @@ -78,15 +85,20 @@ def test_default_hash(): if hash_name in ALGORITHMS_GUARANTEED ], ) -def test_guaranteed_hash(hash_name, expected): +def test_guaranteed_hash(hash_name: str, expected: str): path = DIST_PATH / TEST_FILE dep = FileDependency("demo", path) assert dep.hash(hash_name) == expected def _test_file_dependency_pep_508( - mocker, name, path, pep_508_input, pep_508_output=None, marker=None -): + mocker: "MockerFixture", + name: str, + path: Path, + pep_508_input: str, + pep_508_output: Optional[str] = None, + marker: Optional["BaseMarker"] = None, +) -> None: mocker.patch.object(Path, "exists").return_value = True mocker.patch.object(Path, "is_file").return_value = True @@ -102,7 +114,7 @@ def _test_file_dependency_pep_508( assert dep.to_pep_508() == pep_508_output or pep_508_input -def test_file_dependency_pep_508_local_file_absolute(mocker): +def test_file_dependency_pep_508_local_file_absolute(mocker: "MockerFixture"): path = DIST_PATH / "demo-0.2.0.tar.gz" requirement = "{} @ file://{}".format("demo", path.as_posix()) _test_file_dependency_pep_508(mocker, "demo", path, requirement) @@ -111,7 +123,7 @@ def test_file_dependency_pep_508_local_file_absolute(mocker): _test_file_dependency_pep_508(mocker, "demo", path, requirement) -def test_file_dependency_pep_508_local_file_localhost(mocker): +def test_file_dependency_pep_508_local_file_localhost(mocker: "MockerFixture"): path = DIST_PATH / "demo-0.2.0.tar.gz" requirement = "{} @ file://localhost{}".format("demo", path.as_posix()) requirement_expected = "{} @ file://{}".format("demo", path.as_posix()) @@ -120,7 +132,7 @@ def test_file_dependency_pep_508_local_file_localhost(mocker): ) -def test_file_dependency_pep_508_local_file_relative_path(mocker): +def test_file_dependency_pep_508_local_file_relative_path(mocker: "MockerFixture"): path = Path("..") / "fixtures" / "distributions" / "demo-0.2.0.tar.gz" with pytest.raises(ValueError): @@ -131,7 +143,7 @@ def test_file_dependency_pep_508_local_file_relative_path(mocker): _test_file_dependency_pep_508(mocker, "demo", path, requirement) -def test_absolute_file_dependency_to_pep_508_with_marker(mocker): +def test_absolute_file_dependency_to_pep_508_with_marker(mocker: "MockerFixture"): wheel = "demo-0.1.0-py2.py3-none-any.whl" abs_path = DIST_PATH / wheel @@ -147,7 +159,7 @@ def test_absolute_file_dependency_to_pep_508_with_marker(mocker): ) -def test_relative_file_dependency_to_pep_508_with_marker(mocker): +def test_relative_file_dependency_to_pep_508_with_marker(mocker: "MockerFixture"): wheel = "demo-0.1.0-py2.py3-none-any.whl" rel_path = Path("..") / "fixtures" / "distributions" / wheel diff --git a/tests/packages/test_package.py b/tests/packages/test_package.py index 6e9f971d9..888d7c7fd 100644 --- a/tests/packages/test_package.py +++ b/tests/packages/test_package.py @@ -3,6 +3,7 @@ import random from pathlib import Path +from typing import List import pytest @@ -12,7 +13,7 @@ @pytest.fixture() -def package_with_groups(): +def package_with_groups() -> Package: package = Package("foo", "1.2.3") optional_group = DependencyGroup("optional", optional=True) @@ -52,7 +53,7 @@ def test_package_authors_invalid(): @pytest.mark.parametrize("groups", [["default"], ["dev"]]) -def test_package_add_dependency_vcs_groups(groups, f): +def test_package_add_dependency_vcs_groups(groups: List[str], f: Factory): package = Package("foo", "0.1.0") dependency = package.add_dependency( @@ -65,7 +66,7 @@ def test_package_add_dependency_vcs_groups(groups, f): assert dependency.groups == frozenset(groups) -def test_package_add_dependency_vcs_groups_default_main(f): +def test_package_add_dependency_vcs_groups_default_main(f: Factory): package = Package("foo", "0.1.0") dependency = package.add_dependency( @@ -78,7 +79,7 @@ def test_package_add_dependency_vcs_groups_default_main(f): @pytest.mark.parametrize("groups", [["default"], ["dev"]]) @pytest.mark.parametrize("optional", [True, False]) -def test_package_url_groups_optional(groups, optional, f): +def test_package_url_groups_optional(groups: List[str], optional: bool, f: Factory): package = Package("foo", "0.1.0") dependency = package.add_dependency( @@ -327,7 +328,7 @@ def test_to_dependency_for_vcs(): assert "baz" == dep.source_subdirectory -def test_package_clone(f): +def test_package_clone(f: Factory): # TODO(nic): this test is not future-proof, in that any attributes added # to the Package object and not filled out in this test setup might # cause comparisons to match that otherwise should not. A factory method @@ -358,12 +359,12 @@ def test_package_clone(f): assert len(p2.all_requires) == 2 -def test_dependency_groups(package_with_groups): +def test_dependency_groups(package_with_groups: Package): assert len(package_with_groups.requires) == 2 assert len(package_with_groups.all_requires) == 4 -def test_without_dependency_groups(package_with_groups): +def test_without_dependency_groups(package_with_groups: Package): package = package_with_groups.without_dependency_groups(["dev"]) assert len(package.requires) == 2 @@ -375,7 +376,7 @@ def test_without_dependency_groups(package_with_groups): assert len(package.all_requires) == 2 -def test_with_dependency_groups(package_with_groups): +def test_with_dependency_groups(package_with_groups: Package): package = package_with_groups.with_dependency_groups([]) assert len(package.requires) == 2 @@ -387,14 +388,14 @@ def test_with_dependency_groups(package_with_groups): assert len(package.all_requires) == 4 -def test_without_optional_dependency_groups(package_with_groups): +def test_without_optional_dependency_groups(package_with_groups: Package): package = package_with_groups.without_optional_dependency_groups() assert len(package.requires) == 2 assert len(package.all_requires) == 3 -def test_only_with_dependency_groups(package_with_groups): +def test_only_with_dependency_groups(package_with_groups: Package): package = package_with_groups.with_dependency_groups(["dev"], only=True) assert len(package.requires) == 0 diff --git a/tests/packages/test_vcs_dependency.py b/tests/packages/test_vcs_dependency.py index e7c759759..1b5814f1d 100644 --- a/tests/packages/test_vcs_dependency.py +++ b/tests/packages/test_vcs_dependency.py @@ -1,3 +1,5 @@ +from typing import List + import pytest from poetry.core.packages.vcs_dependency import VCSDependency @@ -64,7 +66,7 @@ def test_to_pep_508_in_extras(): @pytest.mark.parametrize("groups", [["main"], ["dev"]]) -def test_category(groups): +def test_category(groups: List[str]): dependency = VCSDependency( "poetry", "git", diff --git a/tests/packages/utils/test_utils.py b/tests/packages/utils/test_utils.py index 7f8cfcd7e..59173f456 100644 --- a/tests/packages/utils/test_utils.py +++ b/tests/packages/utils/test_utils.py @@ -37,7 +37,7 @@ def test_convert_markers(): ), ], ) -def test_get_python_constraint_from_marker(marker, constraint): +def test_get_python_constraint_from_marker(marker: str, constraint: str): marker = parse_marker(marker) constraint = parse_constraint(constraint) assert constraint == get_python_constraint_from_marker(marker) diff --git a/tests/packages/utils/test_utils_link.py b/tests/packages/utils/test_utils_link.py index 5751ed59a..1cde87da1 100644 --- a/tests/packages/utils/test_utils_link.py +++ b/tests/packages/utils/test_utils_link.py @@ -5,7 +5,7 @@ from poetry.core.packages.utils.link import Link -def make_url(ext): +def make_url(ext: str) -> Link: checksum = sha256(str(uuid.uuid4()).encode()) return Link( "https://files.pythonhosted.org/packages/16/52/dead/" diff --git a/tests/packages/utils/test_utils_urls.py b/tests/packages/utils/test_utils_urls.py index bbbb610bc..0aaabd5d5 100644 --- a/tests/packages/utils/test_utils_urls.py +++ b/tests/packages/utils/test_utils_urls.py @@ -4,6 +4,7 @@ import sys from pathlib import Path +from typing import Optional import pytest @@ -40,7 +41,7 @@ def test_path_to_url_win(): ("file:///c:/tmp/file", r"C:\tmp\file", "/c:/tmp/file"), ], ) -def test_url_to_path(url, win_expected, non_win_expected): +def test_url_to_path(url: str, win_expected: str, non_win_expected: Optional[str]): if sys.platform == "win32": expected_path = win_expected else: diff --git a/tests/pyproject/test_pyproject_toml.py b/tests/pyproject/test_pyproject_toml.py index 7ca621ad8..97f5afcb6 100644 --- a/tests/pyproject/test_pyproject_toml.py +++ b/tests/pyproject/test_pyproject_toml.py @@ -11,12 +11,14 @@ from poetry.core.pyproject.toml import PyProjectTOML -def test_pyproject_toml_simple(pyproject_toml, build_system_section, poetry_section): +def test_pyproject_toml_simple( + pyproject_toml: Path, build_system_section: str, poetry_section: str +): data = TOMLFile(pyproject_toml.as_posix()).read() assert PyProjectTOML(pyproject_toml).data == data -def test_pyproject_toml_no_poetry_config(pyproject_toml): +def test_pyproject_toml_no_poetry_config(pyproject_toml: Path): pyproject = PyProjectTOML(pyproject_toml) assert not pyproject.is_poetry_project() @@ -29,7 +31,7 @@ def test_pyproject_toml_no_poetry_config(pyproject_toml): ) in str(excval.value) -def test_pyproject_toml_poetry_config(pyproject_toml, poetry_section): +def test_pyproject_toml_poetry_config(pyproject_toml: Path, poetry_section: str): pyproject = PyProjectTOML(pyproject_toml) config = TOMLFile(pyproject_toml.as_posix()).read()["tool"]["poetry"] @@ -53,13 +55,13 @@ def test_pyproject_toml_no_build_system_defaults(): assert build_system.dependencies[1].to_pep_508() == "Cython (>=0.29.6,<0.30.0)" -def test_pyproject_toml_build_requires_as_dependencies(pyproject_toml): +def test_pyproject_toml_build_requires_as_dependencies(pyproject_toml: Path): build_system = PyProjectTOML(pyproject_toml).build_system assert build_system.requires == ["setuptools", "wheel"] assert build_system.build_backend == "setuptools.build_meta:__legacy__" -def test_pyproject_toml_non_existent(pyproject_toml): +def test_pyproject_toml_non_existent(pyproject_toml: Path): pyproject_toml.unlink() pyproject = PyProjectTOML(pyproject_toml) build_system = pyproject.build_system @@ -69,7 +71,7 @@ def test_pyproject_toml_non_existent(pyproject_toml): assert build_system.build_backend == "poetry.core.masonry.api" -def test_pyproject_toml_reload(pyproject_toml, poetry_section): +def test_pyproject_toml_reload(pyproject_toml: Path, poetry_section: str): pyproject = PyProjectTOML(pyproject_toml) name_original = pyproject.poetry_config["name"] name_new = str(uuid.uuid4()) @@ -81,7 +83,9 @@ def test_pyproject_toml_reload(pyproject_toml, poetry_section): assert pyproject.poetry_config["name"] == name_original -def test_pyproject_toml_save(pyproject_toml, poetry_section, build_system_section): +def test_pyproject_toml_save( + pyproject_toml: Path, poetry_section: str, build_system_section: str +): pyproject = PyProjectTOML(pyproject_toml) name = str(uuid.uuid4()) diff --git a/tests/pyproject/test_pyproject_toml_file.py b/tests/pyproject/test_pyproject_toml_file.py index a146a79f2..8d468069e 100644 --- a/tests/pyproject/test_pyproject_toml_file.py +++ b/tests/pyproject/test_pyproject_toml_file.py @@ -1,11 +1,17 @@ +from typing import TYPE_CHECKING + import pytest from poetry.core.exceptions import PoetryCoreException from poetry.core.toml import TOMLFile +if TYPE_CHECKING: + from pathlib import Path + + def test_old_pyproject_toml_file_deprecation( - pyproject_toml, build_system_section, poetry_section + pyproject_toml: "Path", build_system_section: str, poetry_section: str ): from poetry.core.utils.toml_file import TomlFile @@ -16,7 +22,7 @@ def test_old_pyproject_toml_file_deprecation( assert data == TOMLFile(pyproject_toml).read() -def test_pyproject_toml_file_invalid(pyproject_toml): +def test_pyproject_toml_file_invalid(pyproject_toml: "Path"): with pyproject_toml.open(mode="a") as f: f.write("<<<<<<<<<<<") @@ -26,6 +32,6 @@ def test_pyproject_toml_file_invalid(pyproject_toml): assert "Invalid TOML file {}".format(pyproject_toml.as_posix()) in str(excval.value) -def test_pyproject_toml_file_getattr(tmp_path, pyproject_toml): +def test_pyproject_toml_file_getattr(tmp_path: "Path", pyproject_toml: "Path"): file = TOMLFile(pyproject_toml) assert file.parent == tmp_path diff --git a/tests/semver/test_helpers.py b/tests/semver/test_helpers.py index be8fc4aa1..c0054e984 100644 --- a/tests/semver/test_helpers.py +++ b/tests/semver/test_helpers.py @@ -1,3 +1,6 @@ +from typing import List +from typing import Union + import pytest from poetry.core.semver.helpers import parse_constraint @@ -31,7 +34,7 @@ ), # Issue 206 ], ) -def test_parse_constraint(input, constraint): +def test_parse_constraint(input: str, constraint: Union[Version, VersionRange]): assert parse_constraint(input) == constraint @@ -91,7 +94,7 @@ def test_parse_constraint(input, constraint): ("0.x", VersionRange(max=Version.from_parts(1, 0, 0))), ], ) -def test_parse_constraint_wildcard(input, constraint): +def test_parse_constraint_wildcard(input: str, constraint: VersionRange): assert parse_constraint(input) == constraint @@ -178,7 +181,7 @@ def test_parse_constraint_wildcard(input, constraint): ), # PEP 440 ], ) -def test_parse_constraint_tilde(input, constraint): +def test_parse_constraint_tilde(input: str, constraint: VersionRange): assert parse_constraint(input) == constraint @@ -244,7 +247,7 @@ def test_parse_constraint_tilde(input, constraint): ), ], ) -def test_parse_constraint_caret(input, constraint): +def test_parse_constraint_caret(input: str, constraint: VersionRange): assert parse_constraint(input) == constraint @@ -263,7 +266,7 @@ def test_parse_constraint_caret(input, constraint): " > 2.0 , <= 3.0 ", ], ) -def test_parse_constraint_multi(input): +def test_parse_constraint_multi(input: str): assert parse_constraint(input) == VersionRange( Version.from_parts(2, 0, 0), Version.from_parts(3, 0, 0), @@ -276,7 +279,7 @@ def test_parse_constraint_multi(input): "input", [">=2.7,!=3.0.*,!=3.1.*", ">=2.7, !=3.0.*, !=3.1.*", ">= 2.7, != 3.0.*, != 3.1.*"], ) -def test_parse_constraint_multi_wilcard(input): +def test_parse_constraint_multi_wilcard(input: str): assert parse_constraint(input) == VersionUnion( VersionRange( Version.from_parts(2, 7, 0), Version.from_parts(3, 0, 0), True, False @@ -310,7 +313,7 @@ def test_parse_constraint_multi_wilcard(input): ("!=0.*.*", VersionRange(Version.parse("1.0"), include_min=True)), ], ) -def test_parse_constraints_negative_wildcard(input, constraint): +def test_parse_constraints_negative_wildcard(input: str, constraint: VersionRange): assert parse_constraint(input) == constraint @@ -331,7 +334,7 @@ def test_parse_constraints_negative_wildcard(input, constraint): ("~1.0.0", ">=1.0.0,<1.1.0"), ], ) -def test_constraints_keep_version_precision(input, expected): +def test_constraints_keep_version_precision(input: str, expected: str): assert str(parse_constraint(input)) == expected @@ -346,7 +349,7 @@ def test_constraints_keep_version_precision(input, expected): (["1.0.0rc2", "1.0.0b1"], ["1.0.0b1", "1.0.0rc2"]), ], ) -def test_versions_are_sortable(unsorted, sorted_): +def test_versions_are_sortable(unsorted: List[str], sorted_: List[str]): unsorted = [parse_constraint(u) for u in unsorted] sorted_ = [parse_constraint(s) for s in sorted_] diff --git a/tests/semver/test_parse_constraint.py b/tests/semver/test_parse_constraint.py index 0bd999f92..769b24a7b 100644 --- a/tests/semver/test_parse_constraint.py +++ b/tests/semver/test_parse_constraint.py @@ -1,3 +1,5 @@ +from typing import Union + import pytest from poetry.core.semver.helpers import parse_constraint @@ -206,5 +208,5 @@ ), ], ) -def test_parse_constraint(constraint, version): +def test_parse_constraint(constraint: str, version: Union[VersionRange, VersionUnion]): assert parse_constraint(constraint) == version diff --git a/tests/semver/test_version.py b/tests/semver/test_version.py index eb7734a69..0d18a1c51 100644 --- a/tests/semver/test_version.py +++ b/tests/semver/test_version.py @@ -1,3 +1,6 @@ +from typing import List +from typing import Optional + import pytest from poetry.core.semver.empty_constraint import EmptyConstraint @@ -27,7 +30,7 @@ ("0.6pre", Version.from_parts(0, 6, 0, pre=ReleaseTag("preview", 0))), ], ) -def test_parse_valid(text, version): +def test_parse_valid(text: str, version: Version): parsed = Version.parse(text) assert parsed == version @@ -35,7 +38,7 @@ def test_parse_valid(text, version): @pytest.mark.parametrize("value", [None, "example"]) -def test_parse_invalid(value): +def test_parse_invalid(value: Optional[str]): with pytest.raises(InvalidVersion): Version.parse(value) @@ -84,7 +87,7 @@ def test_parse_invalid(value): ], ], ) -def test_comparison(versions): +def test_comparison(versions: List[str]): for i in range(len(versions)): for j in range(len(versions)): a = Version.parse(versions[i]) diff --git a/tests/semver/test_version_range.py b/tests/semver/test_version_range.py index d2363d5b4..19fc8ca48 100644 --- a/tests/semver/test_version_range.py +++ b/tests/semver/test_version_range.py @@ -6,72 +6,72 @@ @pytest.fixture() -def v003(): +def v003() -> Version: return Version.parse("0.0.3") @pytest.fixture() -def v010(): +def v010() -> Version: return Version.parse("0.1.0") @pytest.fixture() -def v080(): +def v080() -> Version: return Version.parse("0.8.0") @pytest.fixture() -def v072(): +def v072() -> Version: return Version.parse("0.7.2") @pytest.fixture() -def v114(): +def v114() -> Version: return Version.parse("1.1.4") @pytest.fixture() -def v123(): +def v123() -> Version: return Version.parse("1.2.3") @pytest.fixture() -def v124(): +def v124() -> Version: return Version.parse("1.2.4") @pytest.fixture() -def v130(): +def v130() -> Version: return Version.parse("1.3.0") @pytest.fixture() -def v140(): +def v140() -> Version: return Version.parse("1.4.0") @pytest.fixture() -def v200(): +def v200() -> Version: return Version.parse("2.0.0") @pytest.fixture() -def v234(): +def v234() -> Version: return Version.parse("2.3.4") @pytest.fixture() -def v250(): +def v250() -> Version: return Version.parse("2.5.0") @pytest.fixture() -def v300(): +def v300() -> Version: return Version.parse("3.0.0") @pytest.fixture() -def v300b1(): +def v300b1() -> Version: return Version.parse("3.0.0b1") @@ -84,7 +84,7 @@ def v300b1(): ), ], ) -def test_allows_post_releases_with_max(base, other): +def test_allows_post_releases_with_max(base: Version, other: Version): range = VersionRange(max=base, include_max=True) assert range.allows(other) @@ -98,7 +98,7 @@ def test_allows_post_releases_with_max(base, other): ), ], ) -def test_allows_post_releases_with_min(base, other): +def test_allows_post_releases_with_min(base: Version, other: Version): range = VersionRange(min=base, include_min=True) assert range.allows(other) @@ -166,7 +166,9 @@ def test_allows_post_releases_with_post_and_local_max(): ), ], ) -def test_allows_post_releases_explicit_with_max(base, one, two): +def test_allows_post_releases_explicit_with_max( + base: Version, one: Version, two: Version +): range = VersionRange(max=one, include_max=True) assert range.allows(base) assert not range.allows(two) @@ -193,7 +195,9 @@ def test_allows_post_releases_explicit_with_max(base, one, two): ), ], ) -def test_allows_post_releases_explicit_with_min(base, one, two): +def test_allows_post_releases_explicit_with_min( + base: Version, one: Version, two: Version +): range = VersionRange(min=one, include_min=True) assert not range.allows(base) assert range.allows(two) @@ -203,7 +207,9 @@ def test_allows_post_releases_explicit_with_min(base, one, two): assert not range.allows(one) -def test_allows_all(v123, v124, v140, v250, v300): +def test_allows_all( + v123: Version, v124: Version, v140: Version, v250: Version, v300: Version +): assert VersionRange(v123, v250).allows_all(EmptyConstraint()) range = VersionRange(v123, v250, include_max=True) @@ -213,7 +219,9 @@ def test_allows_all(v123, v124, v140, v250, v300): assert not range.allows_all(v300) -def test_allows_all_with_no_min(v080, v140, v250, v300): +def test_allows_all_with_no_min( + v080: Version, v140: Version, v250: Version, v300: Version +): range = VersionRange(max=v250) assert range.allows_all(VersionRange(v080, v140)) assert not range.allows_all(VersionRange(v080, v300)) @@ -223,7 +231,9 @@ def test_allows_all_with_no_min(v080, v140, v250, v300): assert not range.allows_all(VersionRange()) -def test_allows_all_with_no_max(v003, v010, v080, v140): +def test_allows_all_with_no_max( + v003: Version, v010: Version, v080: Version, v140: Version +): range = VersionRange(min=v010) assert range.allows_all(VersionRange(v080, v140)) assert not range.allows_all(VersionRange(v003, v140)) @@ -233,7 +243,7 @@ def test_allows_all_with_no_max(v003, v010, v080, v140): assert not range.allows_all(VersionRange()) -def test_allows_all_bordering_range_not_more_inclusive(v010, v250): +def test_allows_all_bordering_range_not_more_inclusive(v010: Version, v250: Version): # Allows bordering range that is not more inclusive exclusive = VersionRange(v010, v250) inclusive = VersionRange(v010, v250, True, True) @@ -243,7 +253,15 @@ def test_allows_all_bordering_range_not_more_inclusive(v010, v250): assert exclusive.allows_all(exclusive) -def test_allows_all_contained_unions(v010, v114, v123, v124, v140, v200, v234): +def test_allows_all_contained_unions( + v010: Version, + v114: Version, + v123: Version, + v124: Version, + v140: Version, + v200: Version, + v234: Version, +): # Allows unions that are completely contained range = VersionRange(v114, v200) assert range.allows_all(VersionRange(v123, v124).union(v140)) @@ -252,7 +270,18 @@ def test_allows_all_contained_unions(v010, v114, v123, v124, v140, v200, v234): def test_allows_any( - v003, v010, v072, v080, v114, v123, v124, v140, v200, v234, v250, v300 + v003: Version, + v010: Version, + v072: Version, + v080: Version, + v114: Version, + v123: Version, + v124: Version, + v140: Version, + v200: Version, + v234: Version, + v250: Version, + v300: Version, ): # disallows an empty constraint assert not VersionRange(v123, v250).allows_any(EmptyConstraint()) @@ -316,7 +345,14 @@ def test_allows_any( ) -def test_intersect(v114, v123, v124, v200, v250, v300): +def test_intersect( + v114: Version, + v123: Version, + v124: Version, + v200: Version, + v250: Version, + v300: Version, +): # two overlapping ranges assert VersionRange(v123, v250).intersect(VersionRange(v200, v300)) == VersionRange( v200, v250 @@ -349,7 +385,19 @@ def test_intersect(v114, v123, v124, v200, v250, v300): def test_union( - v003, v010, v072, v080, v114, v123, v124, v130, v140, v200, v234, v250, v300 + v003: Version, + v010: Version, + v072: Version, + v080: Version, + v114: Version, + v123: Version, + v124: Version, + v130: Version, + v140: Version, + v200: Version, + v234: Version, + v250: Version, + v300: Version, ): # with a version returns the range if it contains the version range = VersionRange(v114, v124) @@ -394,7 +442,7 @@ def test_union( assert result == VersionRange(v003, v200) -def test_include_max_prerelease(v200, v300, v300b1): +def test_include_max_prerelease(v200: Version, v300: Version, v300b1: Version): result = VersionRange(v200, v300) assert not result.allows(v300b1) diff --git a/tests/utils/test_helpers.py b/tests/utils/test_helpers.py index b07e6730a..eeac12797 100644 --- a/tests/utils/test_helpers.py +++ b/tests/utils/test_helpers.py @@ -63,7 +63,7 @@ def test_parse_requires(): @pytest.mark.parametrize("raw", ["a-b-c", "a_b-c", "a_b_c", "a-b_c"]) -def test_utils_helpers_canonical_names(raw): +def test_utils_helpers_canonical_names(raw: str): assert canonicalize_name(raw) == "a-b-c" diff --git a/tests/vcs/test_vcs.py b/tests/vcs/test_vcs.py index a8fe77c21..bbe506ac8 100644 --- a/tests/vcs/test_vcs.py +++ b/tests/vcs/test_vcs.py @@ -1,6 +1,10 @@ import subprocess from pathlib import Path +from typing import TYPE_CHECKING +from typing import Any +from typing import List +from typing import Union import pytest @@ -12,6 +16,10 @@ from poetry.core.vcs.git import _reset_executable +if TYPE_CHECKING: + from pytest_mock import MockerFixture + + @pytest.mark.parametrize( "url, normalized", [ @@ -96,7 +104,7 @@ ), ], ) -def test_normalize_url(url, normalized): +def test_normalize_url(url: str, normalized: GitUrl): assert normalized == Git.normalize_url(url) @@ -338,7 +346,7 @@ def test_normalize_url(url, normalized): ), ], ) -def test_parse_url(url, parsed): +def test_parse_url(url: str, parsed: ParsedUrl): result = ParsedUrl.parse(url) assert parsed.name == result.name assert parsed.pathname == result.pathname @@ -376,10 +384,10 @@ def test_git_rev_parse_raises_error_on_invalid_repository(): not WINDOWS, reason="Retrieving the complete path to git is only necessary on Windows, for security reasons", ) -def test_ensure_absolute_path_to_git(mocker): +def test_ensure_absolute_path_to_git(mocker: "MockerFixture"): _reset_executable() - def checkout_output(cmd, *args, **kwargs): + def checkout_output(cmd: List[str], *args: Any, **kwargs: Any) -> Union[str, bytes]: if Path(cmd[0]).name == "where.exe": return "\n".join( [ @@ -404,7 +412,7 @@ def checkout_output(cmd, *args, **kwargs): not WINDOWS, reason="Retrieving the complete path to git is only necessary on Windows, for security reasons", ) -def test_ensure_existing_git_executable_is_found(mocker): +def test_ensure_existing_git_executable_is_found(mocker: "MockerFixture"): mock = mocker.patch.object(subprocess, "check_output", return_value=b"") Git().run("config") diff --git a/tests/version/test_markers.py b/tests/version/test_markers.py index 389d25c13..c8465f92c 100644 --- a/tests/version/test_markers.py +++ b/tests/version/test_markers.py @@ -1,5 +1,9 @@ import os +from typing import Dict +from typing import List +from typing import Optional + import pytest from poetry.core.version.markers import MarkerUnion @@ -526,7 +530,9 @@ def test_multi_marker_removes_duplicates(): ), ], ) -def test_validate(marker_string, environment, expected): +def test_validate( + marker_string: str, environment: Optional[Dict[str, str]], expected: bool +): m = parse_marker(marker_string) assert m.validate(environment) is expected @@ -541,7 +547,7 @@ def test_validate(marker_string, environment, expected): ) ], ) -def test_parse_version_like_markers(marker, env): +def test_parse_version_like_markers(marker: str, env: Dict[str, str]): m = parse_marker(marker) assert m.validate(env) @@ -570,7 +576,7 @@ def test_parse_version_like_markers(marker, env): ), ], ) -def test_without_extras(marker, expected): +def test_without_extras(marker: str, expected: str): m = parse_marker(marker) assert expected == str(m.without_extras()) @@ -608,7 +614,7 @@ def test_without_extras(marker, expected): ), ], ) -def test_exclude(marker, excluded, expected): +def test_exclude(marker: str, excluded: str, expected: str): m = parse_marker(marker) if expected == "*": @@ -653,7 +659,7 @@ def test_exclude(marker, excluded, expected): ), ], ) -def test_only(marker, only, expected): +def test_only(marker: str, only: List[str], expected: str): m = parse_marker(marker) assert expected == str(m.only(*only)) @@ -695,7 +701,7 @@ def test_union_of_a_single_marker_is_the_single_marker(): ), ], ) -def test_invert(marker, inverse): +def test_invert(marker: str, inverse: str): m = parse_marker(marker) assert parse_marker(inverse) == m.invert() @@ -710,7 +716,9 @@ def test_invert(marker, inverse): ), ], ) -def test_union_should_drop_markers_if_their_complement_is_present(marker, expected): +def test_union_should_drop_markers_if_their_complement_is_present( + marker: str, expected: str +): m = parse_marker(marker) assert parse_marker(expected) == m diff --git a/tests/version/test_requirements.py b/tests/version/test_requirements.py index c806d0bfd..1cca51792 100644 --- a/tests/version/test_requirements.py +++ b/tests/version/test_requirements.py @@ -1,5 +1,10 @@ import re +from typing import TYPE_CHECKING +from typing import Dict +from typing import List +from typing import Optional + import pytest from poetry.core.semver.helpers import parse_constraint @@ -7,7 +12,18 @@ from poetry.core.version.requirements import Requirement -def assert_requirement(req, name, url=None, extras=None, constraint="*", marker=None): +if TYPE_CHECKING: + from poetry.core.version.markers import MarkerTypes + + +def assert_requirement( + req: Requirement, + name: str, + url: Optional[str] = None, + extras: Optional[List[str]] = None, + constraint: str = "*", + marker: Optional["MarkerTypes"] = None, +): if extras is None: extras = [] @@ -90,7 +106,7 @@ def assert_requirement(req, name, url=None, extras=None, constraint="*", marker= ), ], ) -def test_requirement(string, expected): +def test_requirement(string: str, expected: Dict[str, str]): req = Requirement(string) assert_requirement(req, **expected) @@ -105,7 +121,7 @@ def test_requirement(string, expected): ("name @ file:/.", "invalid URL"), ], ) -def test_invalid_requirement(string, exception): +def test_invalid_requirement(string: str, exception: str): with pytest.raises( InvalidRequirement, match=re.escape("The requirement is invalid: {}".format(exception)), diff --git a/tests/version/test_version_pep440.py b/tests/version/test_version_pep440.py index 029b5f5dc..2c88c90cf 100644 --- a/tests/version/test_version_pep440.py +++ b/tests/version/test_version_pep440.py @@ -1,3 +1,6 @@ +from typing import Optional +from typing import Tuple + import pytest from poetry.core.version.exceptions import InvalidVersion @@ -18,7 +21,7 @@ ((1, 2, 3, 4, 5, 6), Release(1, 2, 3, (4, 5, 6))), ], ) -def test_pep440_release_segment_from_parts(parts, result): +def test_pep440_release_segment_from_parts(parts: Tuple[int, ...], result: Release): assert Release.from_parts(*parts) == result @@ -37,7 +40,9 @@ def test_pep440_release_segment_from_parts(parts, result): (("r", 1), ReleaseTag("rev", 1)), ], ) -def test_pep440_release_tag_normalisation(parts, result): +def test_pep440_release_tag_normalisation( + parts: Tuple[str, Optional[int]], result: ReleaseTag +): tag = ReleaseTag(*parts) assert tag == result assert tag.to_string() == result.to_string() @@ -55,14 +60,14 @@ def test_pep440_release_tag_normalisation(parts, result): (("dev",), None), ], ) -def test_pep440_release_tag_next_phase(parts, result): +def test_pep440_release_tag_next_phase(parts: Tuple[str], result: Optional[ReleaseTag]): assert ReleaseTag(*parts).next_phase() == result @pytest.mark.parametrize( "phase", list({*RELEASE_PHASES.keys(), *RELEASE_PHASES_SHORT.keys()}) ) -def test_pep440_release_tag_next(phase): +def test_pep440_release_tag_next(phase: str): tag = ReleaseTag(phase=phase).next() assert tag.phase == ReleaseTag.expand(phase) assert tag.number == 1 @@ -160,13 +165,13 @@ def test_pep440_release_tag_next(phase): ), ], ) -def test_pep440_parse_text(text, result): +def test_pep440_parse_text(text: str, result: PEP440Version): assert PEP440Version.parse(text) == result @pytest.mark.parametrize( "text", ["1.2.3.dev1-1" "example-1" "1.2.3-random1" "1.2.3-1-1"] ) -def test_pep440_parse_text_invalid_versions(text): +def test_pep440_parse_text_invalid_versions(text: str): with pytest.raises(InvalidVersion): assert PEP440Version.parse(text) From 75d6ef6a565a54421dab6e62ba4e52b342465594 Mon Sep 17 00:00:00 2001 From: finswimmer Date: Mon, 15 Nov 2021 06:12:00 +0100 Subject: [PATCH 4/5] add missing type hints to stanza --- stanza | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stanza b/stanza index a42173ab0..7798bedc4 100755 --- a/stanza +++ b/stanza @@ -123,7 +123,7 @@ class VendorUpdateCommand(Command): argument("packages", "The packages to vendor.", optional=True, multiple=True) ] - def handle(self): + def handle(self) -> None: packages = self.argument("packages") current_dir = os.getcwd() base = os.path.dirname(__file__) @@ -182,7 +182,7 @@ class VendorCommand(Command): commands = [VendorUpdateCommand()] - def handle(self): + def handle(self) -> int: return self.call("help", self.name) From 38bbcff484512a3d23346944842d8abe7d84ad4f Mon Sep 17 00:00:00 2001 From: finswimmer Date: Mon, 15 Nov 2021 06:13:33 +0100 Subject: [PATCH 5/5] add flake8-annotations to flake8 pre-commit hook --- .flake8 | 20 +++++++++----------- .pre-commit-config.yaml | 7 +------ 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/.flake8 b/.flake8 index f3bacf684..8605de325 100644 --- a/.flake8 +++ b/.flake8 @@ -1,22 +1,20 @@ [flake8] max-line-length = 88 -ignore = E501, E203, W503 -per-file-ignores = __init__.py:F401 +ignore = E501, E203, W503, ANN101, ANN102 +mypy-init-return = True +per-file-ignores = + __init__.py:F401 + tests/test_*:ANN201 + tests/**/test_*:ANN201 exclude = .git __pycache__ - setup.py build dist - releases .venv .tox - .mypy_cache .pytest_cache - .vscode .github - poetry_core/_vendor/ - poetry_core/utils/_compat.py - poetry_core/utils/_typing.py - tests/fixtures/ - tests/masonry/fixtures/ + poetry/core/_vendor/* + tests/fixtures/* + tests/**/fixtures/* diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cf429735c..6f8211b9b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,14 +10,9 @@ repos: hooks: - id: flake8 additional_dependencies: + - flake8-annotations - flake8-bugbear - flake8-comprehensions - exclude: | - (?x)( - ^poetry/core/utils/_typing.py$ - | ^poetry/core/utils/_compat.py$ - | ^poetry/core/_vendor - ) - repo: https://github.com/pre-commit/mirrors-mypy rev: v0.910