Commit 5c328a36 by finswimmer Committed by GitHub

Add missing type hints - Part 2 (#4801)

* add typehints to tests.inspection

* change several yield statements in fixtures to return

* add typehints to tests.installation.test_chef, tests.installation.test_chooser, tests.installation.test_executor

* add typehints to tests.installation.test_installer

* add typehints to tests.installation.test_installer_old

* add typehints to tests.installation.test_pip_installer

* add typehints to tests.masonry

* add typehints to tests.mixology

* add typehints to tests.packages

* add typehints to tests.plugins
parent 2b92a33a
......@@ -424,5 +424,5 @@ def do_lock(command_tester_factory: "CommandTesterFactory", poetry: "Poetry") ->
@pytest.fixture
def project_root():
def project_root() -> Path:
return Path(__file__).parent.parent
......@@ -22,7 +22,7 @@ if TYPE_CHECKING:
@pytest.fixture
def source_dir(tmp_path: Path) -> Path:
yield Path(tmp_path.as_posix())
return Path(tmp_path.as_posix())
@pytest.fixture
......
from pathlib import Path
from subprocess import CalledProcessError
from typing import TYPE_CHECKING
from typing import Set
import pytest
......@@ -11,6 +12,9 @@ from poetry.utils.env import EnvCommandError
from poetry.utils.env import VirtualEnv
if TYPE_CHECKING:
from pytest_mock import MockerFixture
FIXTURE_DIR_BASE = Path(__file__).parent.parent / "fixtures"
FIXTURE_DIR_INSPECTIONS = FIXTURE_DIR_BASE / "inspection"
......@@ -32,7 +36,7 @@ def demo_wheel() -> Path:
@pytest.fixture
def source_dir(tmp_path: Path) -> Path:
yield Path(tmp_path.as_posix())
return Path(tmp_path.as_posix())
@pytest.fixture
......@@ -46,7 +50,7 @@ def demo_setup(source_dir: Path) -> Path:
'install_requires=["package"])'
)
)
yield source_dir
return source_dir
@pytest.fixture
......@@ -65,7 +69,7 @@ def demo_setup_cfg(source_dir: Path) -> Path:
)
)
)
yield source_dir
return source_dir
@pytest.fixture
......@@ -79,7 +83,7 @@ def demo_setup_complex(source_dir: Path) -> Path:
'install_requires=[i for i in ["package"]])'
)
)
yield source_dir
return source_dir
@pytest.fixture
......@@ -88,7 +92,7 @@ def demo_setup_complex_pep517_legacy(demo_setup_complex: Path) -> Path:
pyproject_toml.write_text(
decode("[build-system]\n" 'requires = ["setuptools", "wheel"]')
)
yield demo_setup_complex
return demo_setup_complex
def demo_check_info(info: PackageInfo, requires_dist: Set[str] = None) -> None:
......@@ -104,17 +108,17 @@ def demo_check_info(info: PackageInfo, requires_dist: Set[str] = None) -> None:
assert set(info.requires_dist) == requires_dist
def test_info_from_sdist(demo_sdist):
def test_info_from_sdist(demo_sdist: Path):
info = PackageInfo.from_sdist(demo_sdist)
demo_check_info(info)
def test_info_from_wheel(demo_wheel):
def test_info_from_wheel(demo_wheel: Path):
info = PackageInfo.from_wheel(demo_wheel)
demo_check_info(info)
def test_info_from_bdist(demo_wheel):
def test_info_from_bdist(demo_wheel: Path):
info = PackageInfo.from_bdist(demo_wheel)
demo_check_info(info)
......@@ -133,12 +137,12 @@ def test_info_from_requires_txt():
demo_check_info(info)
def test_info_from_setup_py(demo_setup):
def test_info_from_setup_py(demo_setup: Path):
info = PackageInfo.from_setup_files(demo_setup)
demo_check_info(info, requires_dist={"package"})
def test_info_from_setup_cfg(demo_setup_cfg):
def test_info_from_setup_cfg(demo_setup_cfg: Path):
info = PackageInfo.from_setup_files(demo_setup_cfg)
demo_check_info(info, requires_dist={"package"})
......@@ -153,26 +157,28 @@ def test_info_no_setup_pkg_info_no_deps():
assert info.requires_dist is None
def test_info_setup_simple(mocker, demo_setup):
def test_info_setup_simple(mocker: "MockerFixture", demo_setup: Path):
spy = mocker.spy(VirtualEnv, "run")
info = PackageInfo.from_directory(demo_setup)
assert spy.call_count == 0
demo_check_info(info, requires_dist={"package"})
def test_info_setup_cfg(mocker, demo_setup_cfg):
def test_info_setup_cfg(mocker: "MockerFixture", demo_setup_cfg: Path):
spy = mocker.spy(VirtualEnv, "run")
info = PackageInfo.from_directory(demo_setup_cfg)
assert spy.call_count == 0
demo_check_info(info, requires_dist={"package"})
def test_info_setup_complex(demo_setup_complex):
def test_info_setup_complex(demo_setup_complex: Path):
info = PackageInfo.from_directory(demo_setup_complex)
demo_check_info(info, requires_dist={"package"})
def test_info_setup_complex_pep517_error(mocker, demo_setup_complex):
def test_info_setup_complex_pep517_error(
mocker: "MockerFixture", demo_setup_complex: Path
):
mocker.patch(
"poetry.utils.env.VirtualEnv.run",
autospec=True,
......@@ -183,12 +189,14 @@ def test_info_setup_complex_pep517_error(mocker, demo_setup_complex):
PackageInfo.from_directory(demo_setup_complex)
def test_info_setup_complex_pep517_legacy(demo_setup_complex_pep517_legacy):
def test_info_setup_complex_pep517_legacy(demo_setup_complex_pep517_legacy: Path):
info = PackageInfo.from_directory(demo_setup_complex_pep517_legacy)
demo_check_info(info, requires_dist={"package"})
def test_info_setup_complex_disable_build(mocker, demo_setup_complex):
def test_info_setup_complex_disable_build(
mocker: "MockerFixture", demo_setup_complex: Path
):
spy = mocker.spy(VirtualEnv, "run")
info = PackageInfo.from_directory(demo_setup_complex, disable_build=True)
assert spy.call_count == 0
......@@ -199,7 +207,7 @@ def test_info_setup_complex_disable_build(mocker, demo_setup_complex):
@pytest.mark.parametrize("missing", ["version", "name", "install_requires"])
def test_info_setup_missing_mandatory_should_trigger_pep517(
mocker, source_dir, missing
mocker: "MockerFixture", source_dir: Path, missing: str
):
setup = "from setuptools import setup; "
setup += "setup("
......
from pathlib import Path
from typing import TYPE_CHECKING
from packaging.tags import Tag
......@@ -7,7 +8,13 @@ from poetry.installation.chef import Chef
from poetry.utils.env import MockEnv
def test_get_cached_archive_for_link(config, mocker):
if TYPE_CHECKING:
from pytest_mock import MockerFixture
from tests.conftest import Config
def test_get_cached_archive_for_link(config: "Config", mocker: "MockerFixture"):
chef = Chef(
config,
MockEnv(
......@@ -38,7 +45,7 @@ def test_get_cached_archive_for_link(config, mocker):
assert Link("file:///foo/demo-0.1.0-cp38-cp38-macosx_10_15_x86_64.whl") == archive
def test_get_cached_archives_for_link(config, mocker):
def test_get_cached_archives_for_link(config: "Config", mocker: "MockerFixture"):
chef = Chef(
config,
MockEnv(
......@@ -63,7 +70,7 @@ def test_get_cached_archives_for_link(config, mocker):
}
def test_get_cache_directory_for_link(config, config_cache_dir):
def test_get_cache_directory_for_link(config: "Config", config_cache_dir: Path):
chef = Chef(
config,
MockEnv(
......
import re
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Any
from typing import Dict
from typing import List
from typing import Optional
from typing import Type
from typing import Union
import pytest
......@@ -14,6 +21,12 @@ from poetry.repositories.pypi_repository import PyPiRepository
from poetry.utils.env import MockEnv
if TYPE_CHECKING:
import httpretty
from httpretty.core import HTTPrettyRequest
JSON_FIXTURES = (
Path(__file__).parent.parent / "repositories" / "fixtures" / "pypi.org" / "json"
)
......@@ -22,7 +35,7 @@ LEGACY_FIXTURES = Path(__file__).parent.parent / "repositories" / "fixtures" / "
@pytest.fixture()
def env():
def env() -> MockEnv:
return MockEnv(
supported_tags=[
Tag("cp37", "cp37", "macosx_10_15_x86_64"),
......@@ -32,8 +45,10 @@ def env():
@pytest.fixture()
def mock_pypi(http):
def callback(request, uri, headers):
def mock_pypi(http: Type["httpretty.httpretty"]) -> None:
def callback(
request: "HTTPrettyRequest", uri: str, headers: Dict[str, Any]
) -> Optional[List[Union[int, Dict[str, Any], str]]]:
parts = uri.rsplit("/")
name = parts[-3]
......@@ -57,8 +72,10 @@ def mock_pypi(http):
@pytest.fixture()
def mock_legacy(http):
def callback(request, uri, headers):
def mock_legacy(http: Type["httpretty.httpretty"]) -> None:
def callback(
request: "HTTPrettyRequest", uri: str, headers: Dict[str, Any]
) -> List[Union[int, Dict[str, Any], str]]:
parts = uri.rsplit("/")
name = parts[-2]
......@@ -75,7 +92,7 @@ def mock_legacy(http):
@pytest.fixture()
def pool():
def pool() -> Pool:
pool = Pool()
pool.add_repository(PyPiRepository(disable_cache=True))
......@@ -88,7 +105,7 @@ def pool():
@pytest.mark.parametrize("source_type", ["", "legacy"])
def test_chooser_chooses_universal_wheel_link_if_available(
env, mock_pypi, mock_legacy, source_type, pool
env: MockEnv, mock_pypi: None, mock_legacy: None, source_type: str, pool: Pool
):
chooser = Chooser(pool, env)
......@@ -109,7 +126,7 @@ def test_chooser_chooses_universal_wheel_link_if_available(
@pytest.mark.parametrize("source_type", ["", "legacy"])
def test_chooser_chooses_specific_python_universal_wheel_link_if_available(
env, mock_pypi, mock_legacy, source_type, pool
env: MockEnv, mock_pypi: None, mock_legacy: None, source_type: str, pool: Pool
):
chooser = Chooser(pool, env)
......@@ -130,7 +147,7 @@ def test_chooser_chooses_specific_python_universal_wheel_link_if_available(
@pytest.mark.parametrize("source_type", ["", "legacy"])
def test_chooser_chooses_system_specific_wheel_link_if_available(
mock_pypi, mock_legacy, source_type, pool
mock_pypi: None, mock_legacy: None, source_type: str, pool: Pool
):
env = MockEnv(
supported_tags=[Tag("cp37", "cp37m", "win32"), Tag("py3", "none", "any")]
......@@ -154,11 +171,11 @@ def test_chooser_chooses_system_specific_wheel_link_if_available(
@pytest.mark.parametrize("source_type", ["", "legacy"])
def test_chooser_chooses_sdist_if_no_compatible_wheel_link_is_available(
env,
mock_pypi,
mock_legacy,
source_type,
pool,
env: MockEnv,
mock_pypi: None,
mock_legacy: None,
source_type: str,
pool: Pool,
):
chooser = Chooser(pool, env)
......@@ -179,11 +196,11 @@ def test_chooser_chooses_sdist_if_no_compatible_wheel_link_is_available(
@pytest.mark.parametrize("source_type", ["", "legacy"])
def test_chooser_chooses_distributions_that_match_the_package_hashes(
env,
mock_pypi,
mock_legacy,
source_type,
pool,
env: MockEnv,
mock_pypi: None,
mock_legacy: None,
source_type: str,
pool: Pool,
):
chooser = Chooser(pool, env)
......@@ -212,11 +229,11 @@ def test_chooser_chooses_distributions_that_match_the_package_hashes(
@pytest.mark.parametrize("source_type", ["", "legacy"])
def test_chooser_throws_an_error_if_package_hashes_do_not_match(
env,
mock_pypi,
mock_legacy,
source_type,
pool,
env: MockEnv,
mock_pypi: None,
mock_legacy: None,
source_type: None,
pool: Pool,
):
chooser = Chooser(pool, env)
......
......@@ -3,6 +3,14 @@ import re
import shutil
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Any
from typing import Callable
from typing import Dict
from typing import List
from typing import Optional
from typing import Type
from typing import Union
import pytest
......@@ -22,8 +30,17 @@ from poetry.utils.env import MockEnv
from tests.repositories.test_pypi_repository import MockRepository
if TYPE_CHECKING:
import httpretty
from httpretty.core import HTTPrettyRequest
from pytest_mock import MockerFixture
from poetry.utils.env import VirtualEnv
@pytest.fixture
def env(tmp_dir):
def env(tmp_dir: str) -> MockEnv:
path = Path(tmp_dir) / ".venv"
path.mkdir(parents=True)
......@@ -31,7 +48,7 @@ def env(tmp_dir):
@pytest.fixture()
def io():
def io() -> BufferedIO:
io = BufferedIO()
io.output.formatter.set_style("c1_dark", Style("cyan", options=["dark"]))
io.output.formatter.set_style("c2_dark", Style("default", options=["bold", "dark"]))
......@@ -42,7 +59,7 @@ def io():
@pytest.fixture()
def io_decorated():
def io_decorated() -> BufferedIO:
io = BufferedIO(decorated=True)
io.output.formatter.set_style("c1", Style("cyan"))
io.output.formatter.set_style("success", Style("green"))
......@@ -51,14 +68,14 @@ def io_decorated():
@pytest.fixture()
def io_not_decorated():
def io_not_decorated() -> BufferedIO:
io = BufferedIO(decorated=False)
return io
@pytest.fixture()
def pool():
def pool() -> Pool:
pool = Pool()
pool.add_repository(MockRepository())
......@@ -66,8 +83,10 @@ def pool():
@pytest.fixture()
def mock_file_downloads(http):
def callback(request, uri, headers):
def mock_file_downloads(http: Type["httpretty.httpretty"]) -> None:
def callback(
request: "HTTPrettyRequest", uri: str, headers: Dict[str, Any]
) -> List[Union[int, Dict[str, Any], str]]:
fixture = Path(__file__).parent.parent.joinpath(
"fixtures/distributions/demo-0.1.0-py2.py3-none-any.whl"
)
......@@ -83,7 +102,13 @@ def mock_file_downloads(http):
def test_execute_executes_a_batch_of_operations(
mocker, config, pool, io, tmp_dir, mock_file_downloads, env
mocker: "MockerFixture",
config: Config,
pool: Pool,
io: BufferedIO,
tmp_dir: str,
mock_file_downloads: None,
env: MockEnv,
):
pip_editable_install = mocker.patch(
"poetry.installation.executor.pip_editable_install", unsafe=not PY36
......@@ -159,7 +184,7 @@ Package operations: 4 installs, 1 update, 1 removal
def test_execute_shows_skipped_operations_if_verbose(
config, pool, io, config_cache_dir, env
config: Config, pool: Pool, io: BufferedIO, config_cache_dir: Path, env: MockEnv
):
config = Config()
config.merge({"cache-dir": config_cache_dir.as_posix()})
......@@ -180,7 +205,9 @@ Package operations: 0 installs, 0 updates, 0 removals, 1 skipped
assert 0 == len(env.executed)
def test_execute_should_show_errors(config, mocker, io, env):
def test_execute_should_show_errors(
config: Config, pool: Pool, mocker: "MockerFixture", io: BufferedIO, env: MockEnv
):
executor = Executor(env, pool, config, io)
executor.verbose()
......@@ -202,7 +229,13 @@ Package operations: 1 install, 0 updates, 0 removals
def test_execute_works_with_ansi_output(
mocker, config, pool, io_decorated, tmp_dir, mock_file_downloads, env
mocker: "MockerFixture",
config: Config,
pool: Pool,
io_decorated: BufferedIO,
tmp_dir: str,
mock_file_downloads: None,
env: MockEnv,
):
config = Config()
config.merge({"cache-dir": tmp_dir})
......@@ -236,7 +269,13 @@ def test_execute_works_with_ansi_output(
def test_execute_works_with_no_ansi_output(
mocker, config, pool, io_not_decorated, tmp_dir, mock_file_downloads, env
mocker: "MockerFixture",
config: Config,
pool: Pool,
io_not_decorated: BufferedIO,
tmp_dir: str,
mock_file_downloads: None,
env: MockEnv,
):
config = Config()
config.merge({"cache-dir": tmp_dir})
......@@ -266,7 +305,7 @@ Package operations: 1 install, 0 updates, 0 removals
def test_execute_should_show_operation_as_cancelled_on_subprocess_keyboard_interrupt(
config, mocker, io, env
config: Config, pool: Pool, mocker: "MockerFixture", io: BufferedIO, env: MockEnv
):
executor = Executor(env, pool, config, io)
executor.verbose()
......@@ -286,13 +325,15 @@ Package operations: 1 install, 0 updates, 0 removals
assert expected == io.fetch_output()
def test_execute_should_gracefully_handle_io_error(config, mocker, io, env):
def test_execute_should_gracefully_handle_io_error(
config: Config, pool: Pool, mocker: "MockerFixture", io: BufferedIO, env: MockEnv
):
executor = Executor(env, pool, config, io)
executor.verbose()
original_write_line = executor._io.write_line
def write_line(string, **kwargs):
def write_line(string: str, **kwargs: Any) -> None:
# Simulate UnicodeEncodeError
string.encode("ascii")
original_write_line(string, **kwargs)
......@@ -312,7 +353,13 @@ Package operations: 1 install, 0 updates, 0 removals
def test_executor_should_delete_incomplete_downloads(
config, io, tmp_dir, mocker, pool, mock_file_downloads, env
config: Config,
io: BufferedIO,
tmp_dir: str,
mocker: "MockerFixture",
pool: Pool,
mock_file_downloads: None,
env: MockEnv,
):
fixture = Path(__file__).parent.parent.joinpath(
"fixtures/distributions/demo-0.1.0-py2.py3-none-any.whl"
......@@ -343,7 +390,9 @@ def test_executor_should_delete_incomplete_downloads(
assert not destination_fixture.exists()
def verify_installed_distribution(venv, package, url_reference=None):
def verify_installed_distribution(
venv: "VirtualEnv", package: Package, url_reference: Optional[Dict[str, Any]] = None
):
distributions = list(venv.site_packages.distributions(name=package.name))
assert len(distributions) == 1
......@@ -368,7 +417,7 @@ def verify_installed_distribution(venv, package, url_reference=None):
def test_executor_should_write_pep610_url_references_for_files(
tmp_venv, pool, config, io
tmp_venv: "VirtualEnv", pool: Pool, config: Config, io: BufferedIO
):
url = (
Path(__file__)
......@@ -387,7 +436,7 @@ def test_executor_should_write_pep610_url_references_for_files(
def test_executor_should_write_pep610_url_references_for_directories(
tmp_venv, pool, config, io
tmp_venv: "VirtualEnv", pool: Pool, config: Config, io: BufferedIO
):
url = Path(__file__).parent.parent.joinpath("fixtures/simple_project").resolve()
package = Package(
......@@ -402,7 +451,7 @@ def test_executor_should_write_pep610_url_references_for_directories(
def test_executor_should_write_pep610_url_references_for_editable_directories(
tmp_venv, pool, config, io
tmp_venv: "VirtualEnv", pool: Pool, config: Config, io: BufferedIO
):
url = Path(__file__).parent.parent.joinpath("fixtures/simple_project").resolve()
package = Package(
......@@ -421,7 +470,11 @@ def test_executor_should_write_pep610_url_references_for_editable_directories(
def test_executor_should_write_pep610_url_references_for_urls(
tmp_venv, pool, config, io, mock_file_downloads
tmp_venv: "VirtualEnv",
pool: Pool,
config: Config,
io: BufferedIO,
mock_file_downloads: None,
):
package = Package(
"demo",
......@@ -438,7 +491,11 @@ def test_executor_should_write_pep610_url_references_for_urls(
def test_executor_should_write_pep610_url_references_for_git(
tmp_venv, pool, config, io, mock_file_downloads
tmp_venv: "VirtualEnv",
pool: Pool,
config: Config,
io: BufferedIO,
mock_file_downloads: None,
):
package = Package(
"demo",
......@@ -466,7 +523,12 @@ def test_executor_should_write_pep610_url_references_for_git(
def test_executor_should_use_cached_link_and_hash(
tmp_venv, pool, config, io, mocker, fixture_dir
tmp_venv: "VirtualEnv",
pool: Pool,
config: Config,
io: BufferedIO,
mocker: "MockerFixture",
fixture_dir: Callable[[str], Path],
):
# Produce a file:/// URI that is a valid link
link_cached = Link(
......
......@@ -2,6 +2,14 @@ import itertools
import json
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Any
from typing import Callable
from typing import Dict
from typing import List
from typing import Optional
from typing import Tuple
from typing import Union
import pytest
......@@ -34,90 +42,100 @@ from tests.repositories.test_legacy_repository import (
from tests.repositories.test_pypi_repository import MockRepository
if TYPE_CHECKING:
from pytest_mock import MockerFixture
from poetry.installation.operations import OperationTypes
from poetry.packages import DependencyPackage
from poetry.utils.env import Env
from tests.conftest import Config
RESERVED_PACKAGES = ("pip", "setuptools", "wheel")
class Installer(BaseInstaller):
def _get_installer(self):
def _get_installer(self) -> NoopInstaller:
return NoopInstaller()
class Executor(BaseExecutor):
def __init__(self, *args, **kwargs):
def __init__(self, *args: Any, **kwargs: Any):
super().__init__(*args, **kwargs)
self._installs = []
self._updates = []
self._uninstalls = []
self._installs: List["DependencyPackage"] = []
self._updates: List["DependencyPackage"] = []
self._uninstalls: List["DependencyPackage"] = []
@property
def installations(self):
def installations(self) -> List["DependencyPackage"]:
return self._installs
@property
def updates(self):
def updates(self) -> List["DependencyPackage"]:
return self._updates
@property
def removals(self):
def removals(self) -> List["DependencyPackage"]:
return self._uninstalls
def _do_execute_operation(self, operation):
def _do_execute_operation(self, operation: "OperationTypes") -> None:
super()._do_execute_operation(operation)
if not operation.skipped:
getattr(self, f"_{operation.job_type}s").append(operation.package)
def _execute_install(self, operation):
def _execute_install(self, operation: "OperationTypes") -> int:
return 0
def _execute_update(self, operation):
def _execute_update(self, operation: "OperationTypes") -> int:
return 0
def _execute_uninstall(self, operation):
def _execute_uninstall(self, operation: "OperationTypes") -> int:
return 0
class CustomInstalledRepository(InstalledRepository):
@classmethod
def load(cls, env):
def load(
cls, env: "Env", with_dependencies: bool = False
) -> "CustomInstalledRepository":
return cls()
class Locker(BaseLocker):
def __init__(self, lock_path):
def __init__(self, lock_path: Union[str, Path]):
self._lock = TOMLFile(Path(lock_path).joinpath("poetry.lock"))
self._written_data = None
self._locked = False
self._content_hash = self._get_content_hash()
@property
def written_data(self):
def written_data(self) -> Optional[Dict]:
return self._written_data
def set_lock_path(self, lock):
def set_lock_path(self, lock: Union[str, Path]) -> "Locker":
self._lock = TOMLFile(Path(lock).joinpath("poetry.lock"))
return self
def locked(self, is_locked=True):
def locked(self, is_locked: bool = True) -> "Locker":
self._locked = is_locked
return self
def mock_lock_data(self, data):
def mock_lock_data(self, data: Dict) -> None:
self._lock_data = data
def is_locked(self):
def is_locked(self) -> bool:
return self._locked
def is_fresh(self):
def is_fresh(self) -> bool:
return True
def _get_content_hash(self):
def _get_content_hash(self) -> str:
return "123456789"
def _write_lock_data(self, data):
def _write_lock_data(self, data: Dict) -> None:
for package in data["package"]:
python_versions = str(package["python-versions"])
package["python-versions"] = python_versions
......@@ -127,7 +145,7 @@ class Locker(BaseLocker):
@pytest.fixture()
def package():
def package() -> ProjectPackage:
p = ProjectPackage("root", "1.0")
p.root_dir = Path.cwd()
......@@ -135,12 +153,12 @@ def package():
@pytest.fixture()
def repo():
def repo() -> Repository:
return Repository()
@pytest.fixture()
def pool(repo):
def pool(repo: Repository) -> Pool:
pool = Pool()
pool.add_repository(repo)
......@@ -148,22 +166,29 @@ def pool(repo):
@pytest.fixture()
def installed():
def installed() -> CustomInstalledRepository:
return CustomInstalledRepository()
@pytest.fixture()
def locker(project_root):
def locker(project_root: Path) -> Locker:
return Locker(lock_path=project_root)
@pytest.fixture()
def env():
def env() -> NullEnv:
return NullEnv()
@pytest.fixture()
def installer(package, pool, locker, env, installed, config):
def installer(
package: ProjectPackage,
pool: Pool,
locker: Locker,
env: NullEnv,
installed: CustomInstalledRepository,
config: "Config",
) -> Installer:
installer = Installer(
NullIO(),
env,
......@@ -179,20 +204,22 @@ def installer(package, pool, locker, env, installed, config):
return installer
def fixture(name):
def fixture(name: str) -> Dict:
file = TOMLFile(Path(__file__).parent / "fixtures" / f"{name}.test")
return json.loads(json.dumps(file.read()))
def test_run_no_dependencies(installer, locker):
def test_run_no_dependencies(installer: Installer, locker: Locker):
installer.run()
expected = fixture("no-dependencies")
assert locker.written_data == expected
def test_run_with_dependencies(installer, locker, repo, package):
def test_run_with_dependencies(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.1")
repo.add_package(package_a)
......@@ -208,7 +235,11 @@ def test_run_with_dependencies(installer, locker, repo, package):
def test_run_update_after_removing_dependencies(
installer, locker, repo, package, installed
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
locker.locked(True)
locker.mock_lock_data(
......@@ -276,8 +307,12 @@ def test_run_update_after_removing_dependencies(
def _configure_run_install_dev(
locker, repo, package, installed, with_optional_group=False
):
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
with_optional_group: bool = False,
) -> None:
"""
Perform common test setup for `test_run_install_*dev*()` methods.
"""
......@@ -340,7 +375,13 @@ def _configure_run_install_dev(
package.add_dependency_group(group)
def test_run_install_no_group(installer, locker, repo, package, installed):
def test_run_install_no_group(
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
_configure_run_install_dev(locker, repo, package, installed)
installer.without_groups(["dev"])
......@@ -351,7 +392,13 @@ def test_run_install_no_group(installer, locker, repo, package, installed):
assert 0 == installer.executor.removals_count
def test_run_install_group_only(installer, locker, repo, package, installed):
def test_run_install_group_only(
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
_configure_run_install_dev(locker, repo, package, installed)
installer.only_groups(["dev"])
......@@ -363,7 +410,11 @@ def test_run_install_group_only(installer, locker, repo, package, installed):
def test_run_install_with_optional_group_not_selected(
installer, locker, repo, package, installed
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
_configure_run_install_dev(
locker, repo, package, installed, with_optional_group=True
......@@ -377,7 +428,11 @@ def test_run_install_with_optional_group_not_selected(
def test_run_install_does_not_remove_locked_packages_if_installed_but_not_required(
installer, locker, repo, package, installed
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
package_a = get_package("a", "1.0")
package_b = get_package("b", "1.1")
......@@ -443,7 +498,11 @@ def test_run_install_does_not_remove_locked_packages_if_installed_but_not_requir
def test_run_install_removes_locked_packages_if_installed_and_synchronization_is_required(
installer, locker, repo, package, installed
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
package_a = get_package("a", "1.0")
package_b = get_package("b", "1.1")
......@@ -510,7 +569,11 @@ def test_run_install_removes_locked_packages_if_installed_and_synchronization_is
def test_run_install_removes_no_longer_locked_packages_if_installed(
installer, locker, repo, package, installed
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
package_a = get_package("a", "1.0")
package_b = get_package("b", "1.1")
......@@ -577,7 +640,11 @@ def test_run_install_removes_no_longer_locked_packages_if_installed(
def test_run_install_with_optional_group_selected(
installer, locker, repo, package, installed
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
_configure_run_install_dev(
locker, repo, package, installed, with_optional_group=True
......@@ -601,7 +668,12 @@ def test_run_install_with_optional_group_selected(
),
)
def test_run_install_with_synchronization(
managed_reserved_package_names, installer, locker, repo, package, installed
managed_reserved_package_names: Tuple[str, ...],
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
package_a = get_package("a", "1.0")
package_b = get_package("b", "1.1")
......@@ -672,7 +744,9 @@ def test_run_install_with_synchronization(
assert expected_removals == {r.name for r in installer.executor.removals}
def test_run_whitelist_add(installer, locker, repo, package):
def test_run_whitelist_add(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
locker.locked(True)
locker.mock_lock_data(
{
......@@ -714,7 +788,13 @@ def test_run_whitelist_add(installer, locker, repo, package):
assert locker.written_data == expected
def test_run_whitelist_remove(installer, locker, repo, package, installed):
def test_run_whitelist_remove(
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
locker.locked(True)
locker.mock_lock_data(
{
......@@ -766,7 +846,9 @@ def test_run_whitelist_remove(installer, locker, repo, package, installed):
assert 1 == installer.executor.removals_count
def test_add_with_sub_dependencies(installer, locker, repo, package):
def test_add_with_sub_dependencies(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.1")
package_c = get_package("C", "1.2")
......@@ -788,7 +870,9 @@ def test_add_with_sub_dependencies(installer, locker, repo, package):
assert locker.written_data == expected
def test_run_with_python_versions(installer, locker, repo, package):
def test_run_with_python_versions(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
package.python_versions = "~2.7 || ^3.4"
package_a = get_package("A", "1.0")
......@@ -814,7 +898,7 @@ def test_run_with_python_versions(installer, locker, repo, package):
def test_run_with_optional_and_python_restricted_dependencies(
installer, locker, repo, package
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
package.python_versions = "~2.7 || ^3.4"
......@@ -856,7 +940,11 @@ def test_run_with_optional_and_python_restricted_dependencies(
def test_run_with_optional_and_platform_restricted_dependencies(
installer, locker, repo, package, mocker
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
mocker: "MockerFixture",
):
mocker.patch("sys.platform", "darwin")
......@@ -897,7 +985,9 @@ def test_run_with_optional_and_platform_restricted_dependencies(
assert "c" == installer.executor.installations[1].name
def test_run_with_dependencies_extras(installer, locker, repo, package):
def test_run_with_dependencies_extras(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
package_c = get_package("C", "1.0")
......@@ -922,7 +1012,9 @@ def test_run_with_dependencies_extras(installer, locker, repo, package):
assert locker.written_data == expected
def test_run_with_dependencies_nested_extras(installer, locker, repo, package):
def test_run_with_dependencies_nested_extras(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
package_c = get_package("C", "1.0")
......@@ -951,7 +1043,9 @@ def test_run_with_dependencies_nested_extras(installer, locker, repo, package):
assert locker.written_data == expected
def test_run_does_not_install_extras_if_not_requested(installer, locker, repo, package):
def test_run_does_not_install_extras_if_not_requested(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
package.extras["foo"] = [get_dependency("D")]
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
......@@ -980,7 +1074,9 @@ def test_run_does_not_install_extras_if_not_requested(installer, locker, repo, p
assert 3 == installer.executor.installations_count # A, B, C
def test_run_installs_extras_if_requested(installer, locker, repo, package):
def test_run_installs_extras_if_requested(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
package.extras["foo"] = [get_dependency("D")]
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
......@@ -1010,7 +1106,9 @@ def test_run_installs_extras_if_requested(installer, locker, repo, package):
assert 4 == installer.executor.installations_count # A, B, C, D
def test_run_installs_extras_with_deps_if_requested(installer, locker, repo, package):
def test_run_installs_extras_with_deps_if_requested(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
package.extras["foo"] = [get_dependency("C")]
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
......@@ -1042,7 +1140,7 @@ def test_run_installs_extras_with_deps_if_requested(installer, locker, repo, pac
def test_run_installs_extras_with_deps_if_requested_locked(
installer, locker, repo, package
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
locker.locked(True)
locker.mock_lock_data(fixture("extras-with-dependencies"))
......@@ -1072,7 +1170,12 @@ def test_run_installs_extras_with_deps_if_requested_locked(
assert 4 == installer.executor.installations_count # A, B, C, D
def test_installer_with_pypi_repository(package, locker, installed, config):
def test_installer_with_pypi_repository(
package: ProjectPackage,
locker: Locker,
installed: CustomInstalledRepository,
config: "Config",
):
pool = Pool()
pool.add_repository(MockRepository())
......@@ -1087,7 +1190,13 @@ def test_installer_with_pypi_repository(package, locker, installed, config):
assert not DeepDiff(expected, locker.written_data, ignore_order=True)
def test_run_installs_with_local_file(installer, locker, repo, package, fixture_dir):
def test_run_installs_with_local_file(
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
fixture_dir: Callable[[str], Path],
):
file_path = fixture_dir("distributions/demo-0.1.0-py2.py3-none-any.whl")
package.add_dependency(Factory.create_dependency("demo", {"file": str(file_path)}))
......@@ -1102,7 +1211,11 @@ def test_run_installs_with_local_file(installer, locker, repo, package, fixture_
def test_run_installs_wheel_with_no_requires_dist(
installer, locker, repo, package, fixture_dir
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
fixture_dir: Callable[[str], Path],
):
file_path = fixture_dir(
"wheel_with_no_requires_dist/demo-0.1.0-py2.py3-none-any.whl"
......@@ -1119,7 +1232,12 @@ def test_run_installs_wheel_with_no_requires_dist(
def test_run_installs_with_local_poetry_directory_and_extras(
installer, locker, repo, package, tmpdir, fixture_dir
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
tmpdir: Path,
fixture_dir: Callable[[str], Path],
):
file_path = fixture_dir("project_with_extras")
package.add_dependency(
......@@ -1139,7 +1257,12 @@ def test_run_installs_with_local_poetry_directory_and_extras(
def test_run_installs_with_local_poetry_directory_transitive(
installer, locker, repo, package, tmpdir, fixture_dir
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
tmpdir: Path,
fixture_dir: Callable[[str], Path],
):
root_dir = fixture_dir("directory")
package.root_dir = root_dir
......@@ -1166,7 +1289,12 @@ def test_run_installs_with_local_poetry_directory_transitive(
def test_run_installs_with_local_poetry_file_transitive(
installer, locker, repo, package, tmpdir, fixture_dir
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
tmpdir: str,
fixture_dir: Callable[[str], Path],
):
root_dir = fixture_dir("directory")
package.root_dir = root_dir
......@@ -1195,7 +1323,12 @@ def test_run_installs_with_local_poetry_file_transitive(
def test_run_installs_with_local_setuptools_directory(
installer, locker, repo, package, tmpdir, fixture_dir
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
tmpdir: Path,
fixture_dir: Callable[[str], Path],
):
file_path = fixture_dir("project_with_setup/")
package.add_dependency(
......@@ -1213,7 +1346,9 @@ def test_run_installs_with_local_setuptools_directory(
assert 3 == installer.executor.installations_count
def test_run_with_prereleases(installer, locker, repo, package):
def test_run_with_prereleases(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
locker.locked(True)
locker.mock_lock_data(
{
......@@ -1255,7 +1390,9 @@ def test_run_with_prereleases(installer, locker, repo, package):
assert locker.written_data == expected
def test_run_changes_category_if_needed(installer, locker, repo, package):
def test_run_changes_category_if_needed(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
locker.locked(True)
locker.mock_lock_data(
{
......@@ -1300,7 +1437,9 @@ def test_run_changes_category_if_needed(installer, locker, repo, package):
assert locker.written_data == expected
def test_run_update_all_with_lock(installer, locker, repo, package):
def test_run_update_all_with_lock(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
locker.locked(True)
locker.mock_lock_data(
{
......@@ -1337,7 +1476,9 @@ def test_run_update_all_with_lock(installer, locker, repo, package):
assert locker.written_data == expected
def test_run_update_with_locked_extras(installer, locker, repo, package):
def test_run_update_with_locked_extras(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
locker.locked(True)
locker.mock_lock_data(
{
......@@ -1409,7 +1550,7 @@ def test_run_update_with_locked_extras(installer, locker, repo, package):
def test_run_install_duplicate_dependencies_different_constraints(
installer, locker, repo, package
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
package.add_dependency(Factory.create_dependency("A", "*"))
......@@ -1452,7 +1593,7 @@ def test_run_install_duplicate_dependencies_different_constraints(
def test_run_install_duplicate_dependencies_different_constraints_with_lock(
installer, locker, repo, package
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
locker.locked(True)
locker.mock_lock_data(
......@@ -1559,7 +1700,11 @@ def test_run_install_duplicate_dependencies_different_constraints_with_lock(
def test_run_update_uninstalls_after_removal_transient_dependency(
installer, locker, repo, package, installed
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
locker.locked(True)
locker.mock_lock_data(
......@@ -1617,7 +1762,11 @@ def test_run_update_uninstalls_after_removal_transient_dependency(
def test_run_install_duplicate_dependencies_different_constraints_with_lock_update(
installer, locker, repo, package, installed
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
locker.locked(True)
locker.mock_lock_data(
......@@ -1725,7 +1874,11 @@ def test_run_install_duplicate_dependencies_different_constraints_with_lock_upda
"This is not working at the moment due to limitations in the resolver"
)
def test_installer_test_solver_finds_compatible_package_for_dependency_python_not_fully_compatible_with_package_python(
installer, locker, repo, package, installed
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
package.python_versions = "~2.7 || ^3.4"
package.add_dependency(
......@@ -1749,7 +1902,14 @@ def test_installer_test_solver_finds_compatible_package_for_dependency_python_no
def test_installer_required_extras_should_not_be_removed_when_updating_single_dependency(
installer, locker, repo, package, installed, env, pool, config
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
env: NullEnv,
pool: Pool,
config: "Config",
):
package.add_dependency(Factory.create_dependency("A", {"version": "^1.0"}))
......@@ -1809,7 +1969,13 @@ def test_installer_required_extras_should_not_be_removed_when_updating_single_de
def test_installer_required_extras_should_not_be_removed_when_updating_single_dependency_pypi_repository(
locker, repo, package, installed, env, mocker, config
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
env: NullEnv,
mocker: "MockerFixture",
config: "Config",
):
mocker.patch("sys.platform", "darwin")
......@@ -1867,7 +2033,12 @@ def test_installer_required_extras_should_not_be_removed_when_updating_single_de
def test_installer_required_extras_should_be_installed(
locker, repo, package, installed, env, config
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
env: NullEnv,
config: "Config",
):
pool = Pool()
pool.add_repository(MockRepository())
......@@ -1921,7 +2092,7 @@ def test_installer_required_extras_should_be_installed(
def test_update_multiple_times_with_split_dependencies_is_idempotent(
installer, locker, repo, package
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
locker.locked(True)
locker.mock_lock_data(
......@@ -2000,7 +2171,11 @@ def test_update_multiple_times_with_split_dependencies_is_idempotent(
def test_installer_can_install_dependencies_from_forced_source(
locker, package, installed, env, config
locker: Locker,
package: Package,
installed: CustomInstalledRepository,
env: NullEnv,
config: "Config",
):
package.python_versions = "^3.7"
package.add_dependency(
......@@ -2031,7 +2206,9 @@ def test_installer_can_install_dependencies_from_forced_source(
assert 0 == installer.executor.removals_count
def test_run_installs_with_url_file(installer, locker, repo, package):
def test_run_installs_with_url_file(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
url = "https://python-poetry.org/distributions/demo-0.1.0-py2.py3-none-any.whl"
package.add_dependency(Factory.create_dependency("demo", {"url": url}))
......@@ -2047,7 +2224,7 @@ def test_run_installs_with_url_file(installer, locker, repo, package):
def test_installer_uses_prereleases_if_they_are_compatible(
installer, locker, package, repo
installer: Installer, locker: Locker, package: ProjectPackage, repo: Repository
):
package.python_versions = "~2.7 || ^3.4"
package.add_dependency(
......@@ -2077,7 +2254,12 @@ def test_installer_uses_prereleases_if_they_are_compatible(
def test_installer_can_handle_old_lock_files(
installer, locker, package, repo, installed, config
installer: Installer,
locker: Locker,
package: ProjectPackage,
repo: Repository,
installed: CustomInstalledRepository,
config: "Config",
):
pool = Pool()
pool.add_repository(MockRepository())
......@@ -2149,7 +2331,13 @@ def test_installer_can_handle_old_lock_files(
@pytest.mark.parametrize("quiet", [True, False])
def test_run_with_dependencies_quiet(installer, locker, repo, package, quiet):
def test_run_with_dependencies_quiet(
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
quiet: bool,
):
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.1")
repo.add_package(package_a)
......@@ -2174,7 +2362,7 @@ def test_run_with_dependencies_quiet(installer, locker, repo, package, quiet):
def test_installer_should_use_the_locked_version_of_git_dependencies(
installer, locker, package, repo
installer: Installer, locker: Locker, package: ProjectPackage, repo: Repository
):
locker.locked(True)
locker.mock_lock_data(
......
import itertools
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Callable
from typing import Dict
from typing import Optional
from typing import Tuple
from typing import Union
import pytest
......@@ -26,54 +32,63 @@ from tests.repositories.test_legacy_repository import (
from tests.repositories.test_pypi_repository import MockRepository
if TYPE_CHECKING:
from pytest_mock import MockerFixture
from poetry.utils.env import Env
from tests.conftest import Config
RESERVED_PACKAGES = ("pip", "setuptools", "wheel")
class Installer(BaseInstaller):
def _get_installer(self):
def _get_installer(self) -> NoopInstaller:
return NoopInstaller()
class CustomInstalledRepository(InstalledRepository):
@classmethod
def load(cls, env):
def load(
cls, env: "Env", with_dependencies: bool = False
) -> "CustomInstalledRepository":
return cls()
class Locker(BaseLocker):
def __init__(self, lock_path):
def __init__(self, lock_path: Union[str, Path]):
self._lock = TOMLFile(Path(lock_path).joinpath("poetry.lock"))
self._written_data = None
self._locked = False
self._content_hash = self._get_content_hash()
@property
def written_data(self):
def written_data(self) -> Optional[Dict]:
return self._written_data
def set_lock_path(self, lock):
def set_lock_path(self, lock: Union[str, Path]) -> "Locker":
self._lock = TOMLFile(Path(lock).joinpath("poetry.lock"))
return self
def locked(self, is_locked=True):
def locked(self, is_locked: bool = True) -> "Locker":
self._locked = is_locked
return self
def mock_lock_data(self, data):
def mock_lock_data(self, data: Dict) -> None:
self._lock_data = data
def is_locked(self):
def is_locked(self) -> bool:
return self._locked
def is_fresh(self):
def is_fresh(self) -> bool:
return True
def _get_content_hash(self):
def _get_content_hash(self) -> str:
return "123456789"
def _write_lock_data(self, data):
def _write_lock_data(self, data: Dict) -> None:
for package in data["package"]:
python_versions = str(package["python-versions"])
package["python-versions"] = python_versions
......@@ -83,7 +98,7 @@ class Locker(BaseLocker):
@pytest.fixture()
def package():
def package() -> ProjectPackage:
p = ProjectPackage("root", "1.0")
p.root_dir = Path.cwd()
......@@ -91,12 +106,12 @@ def package():
@pytest.fixture()
def repo():
def repo() -> Repository:
return Repository()
@pytest.fixture()
def pool(repo):
def pool(repo: Repository) -> Pool:
pool = Pool()
pool.add_repository(repo)
......@@ -104,39 +119,48 @@ def pool(repo):
@pytest.fixture()
def installed():
def installed() -> CustomInstalledRepository:
return CustomInstalledRepository()
@pytest.fixture()
def locker(project_root):
def locker(project_root: Path) -> Locker:
return Locker(lock_path=project_root)
@pytest.fixture()
def env():
def env() -> NullEnv:
return NullEnv()
@pytest.fixture()
def installer(package, pool, locker, env, installed, config):
def installer(
package: ProjectPackage,
pool: Pool,
locker: Locker,
env: NullEnv,
installed: CustomInstalledRepository,
config: "Config",
):
return Installer(NullIO(), env, package, locker, pool, config, installed=installed)
def fixture(name):
def fixture(name: str) -> str:
file = TOMLFile(Path(__file__).parent / "fixtures" / f"{name}.test")
return file.read()
def test_run_no_dependencies(installer, locker):
def test_run_no_dependencies(installer: Installer, locker: Locker):
installer.run()
expected = fixture("no-dependencies")
assert locker.written_data == expected
def test_run_with_dependencies(installer, locker, repo, package):
def test_run_with_dependencies(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.1")
repo.add_package(package_a)
......@@ -152,7 +176,11 @@ def test_run_with_dependencies(installer, locker, repo, package):
def test_run_update_after_removing_dependencies(
installer, locker, repo, package, installed
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
locker.locked(True)
locker.mock_lock_data(
......@@ -224,7 +252,13 @@ def test_run_update_after_removing_dependencies(
assert len(removals) == 1
def test_run_install_no_group(installer, locker, repo, package, installed):
def test_run_install_no_group(
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
locker.locked(True)
locker.mock_lock_data(
{
......@@ -303,7 +337,12 @@ def test_run_install_no_group(installer, locker, repo, package, installed):
),
)
def test_run_install_with_synchronization(
managed_reserved_package_names, installer, locker, repo, package, installed
managed_reserved_package_names: Tuple[str, ...],
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
package_a = get_package("a", "1.0")
package_b = get_package("b", "1.1")
......@@ -377,7 +416,9 @@ def test_run_install_with_synchronization(
assert {r.name for r in removals} == expected_removals
def test_run_whitelist_add(installer, locker, repo, package):
def test_run_whitelist_add(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
locker.locked(True)
locker.mock_lock_data(
{
......@@ -419,7 +460,13 @@ def test_run_whitelist_add(installer, locker, repo, package):
assert locker.written_data == expected
def test_run_whitelist_remove(installer, locker, repo, package, installed):
def test_run_whitelist_remove(
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
locker.locked(True)
locker.mock_lock_data(
{
......@@ -471,7 +518,9 @@ def test_run_whitelist_remove(installer, locker, repo, package, installed):
assert len(installer.installer.removals) == 1
def test_add_with_sub_dependencies(installer, locker, repo, package):
def test_add_with_sub_dependencies(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.1")
package_c = get_package("C", "1.2")
......@@ -493,7 +542,9 @@ def test_add_with_sub_dependencies(installer, locker, repo, package):
assert locker.written_data == expected
def test_run_with_python_versions(installer, locker, repo, package):
def test_run_with_python_versions(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
package.python_versions = "~2.7 || ^3.4"
package_a = get_package("A", "1.0")
......@@ -519,7 +570,7 @@ def test_run_with_python_versions(installer, locker, repo, package):
def test_run_with_optional_and_python_restricted_dependencies(
installer, locker, repo, package
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
package.python_versions = "~2.7 || ^3.4"
......@@ -562,7 +613,11 @@ def test_run_with_optional_and_python_restricted_dependencies(
def test_run_with_optional_and_platform_restricted_dependencies(
installer, locker, repo, package, mocker
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
mocker: "MockerFixture",
):
mocker.patch("sys.platform", "darwin")
......@@ -604,7 +659,9 @@ def test_run_with_optional_and_platform_restricted_dependencies(
assert installer.installs[1].name == "c"
def test_run_with_dependencies_extras(installer, locker, repo, package):
def test_run_with_dependencies_extras(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
package_c = get_package("C", "1.0")
......@@ -629,7 +686,9 @@ def test_run_with_dependencies_extras(installer, locker, repo, package):
assert locker.written_data == expected
def test_run_does_not_install_extras_if_not_requested(installer, locker, repo, package):
def test_run_does_not_install_extras_if_not_requested(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
package.extras["foo"] = [get_dependency("D")]
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
......@@ -659,7 +718,9 @@ def test_run_does_not_install_extras_if_not_requested(installer, locker, repo, p
assert len(installer.installs) == 3 # A, B, C
def test_run_installs_extras_if_requested(installer, locker, repo, package):
def test_run_installs_extras_if_requested(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
package.extras["foo"] = [get_dependency("D")]
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
......@@ -690,7 +751,9 @@ def test_run_installs_extras_if_requested(installer, locker, repo, package):
assert len(installer.installs) == 4 # A, B, C, D
def test_run_installs_extras_with_deps_if_requested(installer, locker, repo, package):
def test_run_installs_extras_with_deps_if_requested(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
package.extras["foo"] = [get_dependency("C")]
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
......@@ -723,7 +786,7 @@ def test_run_installs_extras_with_deps_if_requested(installer, locker, repo, pac
def test_run_installs_extras_with_deps_if_requested_locked(
installer, locker, repo, package
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
locker.locked(True)
locker.mock_lock_data(fixture("extras-with-dependencies"))
......@@ -754,7 +817,12 @@ def test_run_installs_extras_with_deps_if_requested_locked(
assert len(installer.installs) == 4 # A, B, C, D
def test_installer_with_pypi_repository(package, locker, installed, config):
def test_installer_with_pypi_repository(
package: ProjectPackage,
locker: Locker,
installed: CustomInstalledRepository,
config: "Config",
):
pool = Pool()
pool.add_repository(MockRepository())
......@@ -769,7 +837,13 @@ def test_installer_with_pypi_repository(package, locker, installed, config):
assert not DeepDiff(expected, locker.written_data, ignore_order=True)
def test_run_installs_with_local_file(installer, locker, repo, package, fixture_dir):
def test_run_installs_with_local_file(
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
fixture_dir: Callable[[str], Path],
):
file_path = fixture_dir("distributions/demo-0.1.0-py2.py3-none-any.whl")
package.add_dependency(Factory.create_dependency("demo", {"file": str(file_path)}))
......@@ -785,7 +859,11 @@ def test_run_installs_with_local_file(installer, locker, repo, package, fixture_
def test_run_installs_wheel_with_no_requires_dist(
installer, locker, repo, package, fixture_dir
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
fixture_dir: Callable[[str], Path],
):
file_path = fixture_dir(
"wheel_with_no_requires_dist/demo-0.1.0-py2.py3-none-any.whl"
......@@ -802,7 +880,12 @@ def test_run_installs_wheel_with_no_requires_dist(
def test_run_installs_with_local_poetry_directory_and_extras(
installer, locker, repo, package, tmpdir, fixture_dir
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
tmpdir: Path,
fixture_dir: Callable[[str], Path],
):
file_path = fixture_dir("project_with_extras")
package.add_dependency(
......@@ -823,7 +906,12 @@ def test_run_installs_with_local_poetry_directory_and_extras(
def test_run_installs_with_local_poetry_directory_transitive(
installer, locker, repo, package, tmpdir, fixture_dir
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
tmpdir: Path,
fixture_dir: Callable[[str], Path],
):
root_dir = fixture_dir("directory")
package.root_dir = root_dir
......@@ -850,7 +938,12 @@ def test_run_installs_with_local_poetry_directory_transitive(
def test_run_installs_with_local_poetry_file_transitive(
installer, locker, repo, package, tmpdir, fixture_dir
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
tmpdir: Path,
fixture_dir: Callable[[str], Path],
):
root_dir = fixture_dir("directory")
package.root_dir = root_dir
......@@ -877,7 +970,12 @@ def test_run_installs_with_local_poetry_file_transitive(
def test_run_installs_with_local_setuptools_directory(
installer, locker, repo, package, tmpdir, fixture_dir
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
tmpdir: Path,
fixture_dir: Callable[[str], Path],
):
file_path = fixture_dir("project_with_setup/")
package.add_dependency(
......@@ -896,7 +994,9 @@ def test_run_installs_with_local_setuptools_directory(
assert len(installer.installer.installs) == 3
def test_run_with_prereleases(installer, locker, repo, package):
def test_run_with_prereleases(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
locker.locked(True)
locker.mock_lock_data(
{
......@@ -938,7 +1038,9 @@ def test_run_with_prereleases(installer, locker, repo, package):
assert locker.written_data == expected
def test_run_changes_category_if_needed(installer, locker, repo, package):
def test_run_changes_category_if_needed(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
locker.locked(True)
locker.mock_lock_data(
{
......@@ -983,7 +1085,9 @@ def test_run_changes_category_if_needed(installer, locker, repo, package):
assert locker.written_data == expected
def test_run_update_all_with_lock(installer, locker, repo, package):
def test_run_update_all_with_lock(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
locker.locked(True)
locker.mock_lock_data(
{
......@@ -1020,7 +1124,9 @@ def test_run_update_all_with_lock(installer, locker, repo, package):
assert locker.written_data == expected
def test_run_update_with_locked_extras(installer, locker, repo, package):
def test_run_update_with_locked_extras(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
locker.locked(True)
locker.mock_lock_data(
{
......@@ -1092,7 +1198,7 @@ def test_run_update_with_locked_extras(installer, locker, repo, package):
def test_run_install_duplicate_dependencies_different_constraints(
installer, locker, repo, package
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
package.add_dependency(Factory.create_dependency("A", "*"))
......@@ -1137,7 +1243,7 @@ def test_run_install_duplicate_dependencies_different_constraints(
def test_run_install_duplicate_dependencies_different_constraints_with_lock(
installer, locker, repo, package
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
locker.locked(True)
locker.mock_lock_data(
......@@ -1247,7 +1353,11 @@ def test_run_install_duplicate_dependencies_different_constraints_with_lock(
def test_run_update_uninstalls_after_removal_transient_dependency(
installer, locker, repo, package, installed
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
locker.locked(True)
locker.mock_lock_data(
......@@ -1308,7 +1418,11 @@ def test_run_update_uninstalls_after_removal_transient_dependency(
def test_run_install_duplicate_dependencies_different_constraints_with_lock_update(
installer, locker, repo, package, installed
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
locker.locked(True)
locker.mock_lock_data(
......@@ -1419,7 +1533,11 @@ def test_run_install_duplicate_dependencies_different_constraints_with_lock_upda
"This is not working at the moment due to limitations in the resolver"
)
def test_installer_test_solver_finds_compatible_package_for_dependency_python_not_fully_compatible_with_package_python(
installer, locker, repo, package, installed
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
):
package.python_versions = "~2.7 || ^3.4"
package.add_dependency(
......@@ -1445,7 +1563,14 @@ def test_installer_test_solver_finds_compatible_package_for_dependency_python_no
def test_installer_required_extras_should_not_be_removed_when_updating_single_dependency(
installer, locker, repo, package, installed, env, pool, config
installer: Installer,
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
env: NullEnv,
pool: Pool,
config: "Config",
):
package.add_dependency(Factory.create_dependency("A", {"version": "^1.0"}))
......@@ -1497,7 +1622,13 @@ def test_installer_required_extras_should_not_be_removed_when_updating_single_de
def test_installer_required_extras_should_not_be_removed_when_updating_single_dependency_pypi_repository(
locker, repo, package, installed, env, mocker, config
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
env: NullEnv,
mocker: "MockerFixture",
config: "Config",
):
mocker.patch("sys.platform", "darwin")
......@@ -1539,7 +1670,12 @@ def test_installer_required_extras_should_not_be_removed_when_updating_single_de
def test_installer_required_extras_should_be_installed(
locker, repo, package, installed, env, config
locker: Locker,
repo: Repository,
package: ProjectPackage,
installed: CustomInstalledRepository,
env: NullEnv,
config: "Config",
):
pool = Pool()
pool.add_repository(MockRepository())
......@@ -1577,7 +1713,7 @@ def test_installer_required_extras_should_be_installed(
def test_update_multiple_times_with_split_dependencies_is_idempotent(
installer, locker, repo, package
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
locker.locked(True)
locker.mock_lock_data(
......@@ -1656,7 +1792,11 @@ def test_update_multiple_times_with_split_dependencies_is_idempotent(
def test_installer_can_install_dependencies_from_forced_source(
locker, package, installed, env, config
locker: Locker,
package: ProjectPackage,
installed: CustomInstalledRepository,
env: NullEnv,
config: "Config",
):
package.python_versions = "^3.7"
package.add_dependency(
......@@ -1679,7 +1819,9 @@ def test_installer_can_install_dependencies_from_forced_source(
assert len(installer.installer.removals) == 0
def test_run_installs_with_url_file(installer, locker, repo, package):
def test_run_installs_with_url_file(
installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage
):
url = "https://python-poetry.org/distributions/demo-0.1.0-py2.py3-none-any.whl"
package.add_dependency(Factory.create_dependency("demo", {"url": url}))
......@@ -1695,7 +1837,7 @@ def test_run_installs_with_url_file(installer, locker, repo, package):
def test_installer_uses_prereleases_if_they_are_compatible(
installer, locker, package, repo
installer: Installer, locker: Locker, package: ProjectPackage, repo: Repository
):
package.python_versions = "~2.7 || ^3.4"
package.add_dependency(
......@@ -1725,7 +1867,12 @@ def test_installer_uses_prereleases_if_they_are_compatible(
def test_installer_can_handle_old_lock_files(
installer, locker, package, repo, installed, config
installer: Installer,
locker: Locker,
package: ProjectPackage,
repo: Repository,
installed: CustomInstalledRepository,
config: "Config",
):
pool = Pool()
pool.add_repository(MockRepository())
......
......@@ -2,6 +2,7 @@ import re
import shutil
from pathlib import Path
from typing import TYPE_CHECKING
import pytest
......@@ -14,8 +15,14 @@ from poetry.repositories.pool import Pool
from poetry.utils.env import NullEnv
if TYPE_CHECKING:
from pytest_mock import MockerFixture
from poetry.utils.env import VirtualEnv
@pytest.fixture
def package_git():
def package_git() -> Package:
package = Package(
"demo",
"1.0.0",
......@@ -28,16 +35,16 @@ def package_git():
@pytest.fixture
def pool():
def pool() -> Pool:
return Pool()
@pytest.fixture
def installer(pool):
def installer(pool: Pool) -> PipInstaller:
return PipInstaller(NullEnv(), NullIO(), pool)
def test_requirement(installer):
def test_requirement(installer: PipInstaller):
package = Package("ipython", "7.5.0")
package.files = [
{"file": "foo-0.1.0.tar.gz", "hash": "md5:dbdc53e3918f28fa335a173432402a00"},
......@@ -74,7 +81,7 @@ def test_requirement_source_type_url():
assert expected == result
def test_requirement_git_develop_false(installer, package_git):
def test_requirement_git_develop_false(installer: PipInstaller, package_git: Package):
package_git.develop = False
result = installer.requirement(package_git)
expected = "git+git@github.com:demo/demo.git@master#egg=demo"
......@@ -82,7 +89,7 @@ def test_requirement_git_develop_false(installer, package_git):
assert expected == result
def test_install_with_non_pypi_default_repository(pool, installer):
def test_install_with_non_pypi_default_repository(pool: Pool, installer: PipInstaller):
default = LegacyRepository("default", "https://default.com")
another = LegacyRepository("another", "https://another.com")
......@@ -170,7 +177,7 @@ def test_install_with_client_cert():
assert cmd[cert_index + 1] == str(Path(client_path))
def test_requirement_git_develop_true(installer, package_git):
def test_requirement_git_develop_true(installer: PipInstaller, package_git: Package):
package_git.develop = True
result = installer.requirement(package_git)
expected = ["-e", "git+git@github.com:demo/demo.git@master#egg=demo"]
......@@ -178,7 +185,9 @@ def test_requirement_git_develop_true(installer, package_git):
assert expected == result
def test_uninstall_git_package_nspkg_pth_cleanup(mocker, tmp_venv, pool):
def test_uninstall_git_package_nspkg_pth_cleanup(
mocker: "MockerFixture", tmp_venv: "VirtualEnv", pool: Pool
):
# this test scenario requires a real installation using the pip installer
installer = PipInstaller(tmp_venv, NullIO(), pool)
......@@ -194,7 +203,7 @@ def test_uninstall_git_package_nspkg_pth_cleanup(mocker, tmp_venv, pool):
# in order to reproduce the scenario where the git source is removed prior to proper
# clean up of nspkg.pth file, we need to make sure the fixture is copied and not
# symlinked into the git src directory
def copy_only(source, dest):
def copy_only(source: Path, dest: Path) -> None:
if dest.exists():
dest.unlink()
......
......@@ -2,6 +2,7 @@ import os
import shutil
from pathlib import Path
from typing import TYPE_CHECKING
import pytest
......@@ -14,8 +15,14 @@ from poetry.utils.env import MockEnv
from poetry.utils.env import VirtualEnv
if TYPE_CHECKING:
from pytest_mock import MockerFixture
from poetry.poetry import Poetry
@pytest.fixture()
def simple_poetry():
def simple_poetry() -> "Poetry":
poetry = Factory().create_poetry(
Path(__file__).parent.parent.parent / "fixtures" / "simple_project"
)
......@@ -24,7 +31,7 @@ def simple_poetry():
@pytest.fixture()
def project_with_include():
def project_with_include() -> "Poetry":
poetry = Factory().create_poetry(
Path(__file__).parent.parent.parent / "fixtures" / "with-include"
)
......@@ -33,7 +40,7 @@ def project_with_include():
@pytest.fixture()
def extended_poetry():
def extended_poetry() -> "Poetry":
poetry = Factory().create_poetry(
Path(__file__).parent.parent.parent / "fixtures" / "extended_project"
)
......@@ -42,7 +49,7 @@ def extended_poetry():
@pytest.fixture()
def extended_without_setup_poetry():
def extended_without_setup_poetry() -> "Poetry":
poetry = Factory().create_poetry(
Path(__file__).parent.parent.parent
/ "fixtures"
......@@ -53,12 +60,12 @@ def extended_without_setup_poetry():
@pytest.fixture()
def env_manager(simple_poetry):
def env_manager(simple_poetry: "Poetry") -> EnvManager:
return EnvManager(simple_poetry)
@pytest.fixture
def tmp_venv(tmp_dir, env_manager):
def tmp_venv(tmp_dir: str, env_manager: EnvManager) -> VirtualEnv:
venv_path = Path(tmp_dir) / "venv"
env_manager.build_venv(str(venv_path))
......@@ -69,7 +76,9 @@ def tmp_venv(tmp_dir, env_manager):
shutil.rmtree(str(venv.path))
def test_builder_installs_proper_files_for_standard_packages(simple_poetry, tmp_venv):
def test_builder_installs_proper_files_for_standard_packages(
simple_poetry: "Poetry", tmp_venv: VirtualEnv
):
builder = EditableBuilder(simple_poetry, tmp_venv, NullIO())
builder.build()
......@@ -184,7 +193,7 @@ if __name__ == '__main__':
def test_builder_falls_back_on_setup_and_pip_for_packages_with_build_scripts(
mocker, extended_poetry, tmp_dir
mocker: "MockerFixture", extended_poetry: "Poetry", tmp_dir: str
):
pip_editable_install = mocker.patch(
"poetry.masonry.builders.editable.pip_editable_install"
......@@ -200,7 +209,7 @@ def test_builder_falls_back_on_setup_and_pip_for_packages_with_build_scripts(
def test_builder_installs_proper_files_when_packages_configured(
project_with_include, tmp_venv
project_with_include: "Poetry", tmp_venv: VirtualEnv
):
builder = EditableBuilder(project_with_include, tmp_venv, NullIO())
builder.build()
......@@ -224,7 +233,9 @@ def test_builder_installs_proper_files_when_packages_configured(
assert len(paths) == len(expected)
def test_builder_should_execute_build_scripts(extended_without_setup_poetry, tmp_dir):
def test_builder_should_execute_build_scripts(
extended_without_setup_poetry: "Poetry", tmp_dir: str
):
env = MockEnv(path=Path(tmp_dir) / "foo")
builder = EditableBuilder(extended_without_setup_poetry, env, NullIO())
......
from typing import TYPE_CHECKING
from typing import Dict
from typing import List
from typing import Optional
from poetry.core.packages.package import Package
from poetry.factory import Factory
from poetry.mixology.failure import SolveFailure
......@@ -5,7 +10,19 @@ from poetry.mixology.version_solver import VersionSolver
from poetry.packages import DependencyPackage
def add_to_repo(repository, name, version, deps=None, python=None):
if TYPE_CHECKING:
from poetry.packages.project_package import ProjectPackage
from poetry.repositories import Repository
from tests.mixology.version_solver.conftest import Provider
def add_to_repo(
repository: "Repository",
name: str,
version: str,
deps: Optional[Dict[str, str]] = None,
python: Optional[str] = None,
) -> None:
package = Package(name, version)
if python:
package.python_versions = python
......@@ -18,8 +35,14 @@ def add_to_repo(repository, name, version, deps=None, python=None):
def check_solver_result(
root, provider, result=None, error=None, tries=None, locked=None, use_latest=None
):
root: "ProjectPackage",
provider: "Provider",
result: Optional[Dict[str, str]] = None,
error: Optional[str] = None,
tries: Optional[int] = None,
locked: Optional[Dict[str, Package]] = None,
use_latest: Optional[List[str]] = None,
) -> None:
if locked is not None:
locked = {k: DependencyPackage(l.to_dependency(), l) for k, l in locked.items()}
......
from typing import TYPE_CHECKING
import pytest
from cleo.io.null_io import NullIO
......@@ -8,19 +10,23 @@ from poetry.repositories import Pool
from poetry.repositories import Repository
if TYPE_CHECKING:
from tests.helpers import TestRepository
class Provider(BaseProvider):
def set_package_python_versions(self, python_versions):
def set_package_python_versions(self, python_versions: str) -> None:
self._package.python_versions = python_versions
self._python_constraint = self._package.python_constraint
@pytest.fixture
def repo():
def repo() -> Repository:
return Repository()
@pytest.fixture
def pool(repo):
def pool(repo: "TestRepository") -> Pool:
pool = Pool()
pool.add_repository(repo)
......@@ -28,10 +34,10 @@ def pool(repo):
@pytest.fixture
def root():
def root() -> ProjectPackage:
return ProjectPackage("myapp", "0.0.0")
@pytest.fixture
def provider(pool, root):
def provider(pool: Pool, root: ProjectPackage) -> Provider:
return Provider(root, pool, NullIO())
from typing import TYPE_CHECKING
from poetry.factory import Factory
from tests.mixology.helpers import add_to_repo
from tests.mixology.helpers import check_solver_result
def test_circular_dependency_on_older_version(root, provider, repo):
if TYPE_CHECKING:
from poetry.packages.project_package import ProjectPackage
from poetry.repositories import Repository
from tests.mixology.version_solver.conftest import Provider
def test_circular_dependency_on_older_version(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
root.add_dependency(Factory.create_dependency("a", ">=1.0.0"))
add_to_repo(repo, "a", "1.0.0")
......@@ -13,7 +23,9 @@ def test_circular_dependency_on_older_version(root, provider, repo):
check_solver_result(root, provider, {"a": "1.0.0"}, tries=2)
def test_diamond_dependency_graph(root, provider, repo):
def test_diamond_dependency_graph(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
root.add_dependency(Factory.create_dependency("a", "*"))
root.add_dependency(Factory.create_dependency("b", "*"))
......@@ -30,7 +42,9 @@ def test_diamond_dependency_graph(root, provider, repo):
check_solver_result(root, provider, {"a": "1.0.0", "b": "2.0.0", "c": "3.0.0"})
def test_backjumps_after_partial_satisfier(root, provider, repo):
def test_backjumps_after_partial_satisfier(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
# c 2.0.0 is incompatible with y 2.0.0 because it requires x 1.0.0, but that
# requirement only exists because of both a and b. The solver should be able
# to deduce c 2.0.0's incompatibility and select c 1.0.0 instead.
......@@ -53,7 +67,9 @@ def test_backjumps_after_partial_satisfier(root, provider, repo):
check_solver_result(root, provider, {"c": "1.0.0", "y": "2.0.0"}, tries=2)
def test_rolls_back_leaf_versions_first(root, provider, repo):
def test_rolls_back_leaf_versions_first(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
# The latest versions of a and b disagree on c. An older version of either
# will resolve the problem. This test validates that b, which is farther
# in the dependency graph from myapp is downgraded first.
......@@ -69,7 +85,9 @@ def test_rolls_back_leaf_versions_first(root, provider, repo):
check_solver_result(root, provider, {"a": "2.0.0", "b": "1.0.0", "c": "2.0.0"})
def test_simple_transitive(root, provider, repo):
def test_simple_transitive(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
# Only one version of baz, so foo and bar will have to downgrade
# until they reach it
root.add_dependency(Factory.create_dependency("foo", "*"))
......@@ -89,7 +107,9 @@ def test_simple_transitive(root, provider, repo):
)
def test_backjump_to_nearer_unsatisfied_package(root, provider, repo):
def test_backjump_to_nearer_unsatisfied_package(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
# This ensures it doesn't exhaustively search all versions of b when it's
# a-2.0.0 whose dependency on c-2.0.0-nonexistent led to the problem. We
# make sure b has more versions than a so that the solver tries a first
......@@ -109,7 +129,9 @@ def test_backjump_to_nearer_unsatisfied_package(root, provider, repo):
)
def test_traverse_into_package_with_fewer_versions_first(root, provider, repo):
def test_traverse_into_package_with_fewer_versions_first(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
# Dependencies are ordered so that packages with fewer versions are tried
# first. Here, there are two valid solutions (either a or b must be
# downgraded once). The chosen one depends on which dep is traversed first.
......@@ -133,7 +155,9 @@ def test_traverse_into_package_with_fewer_versions_first(root, provider, repo):
check_solver_result(root, provider, {"a": "4.0.0", "b": "4.0.0", "c": "2.0.0"})
def test_backjump_past_failed_package_on_disjoint_constraint(root, provider, repo):
def test_backjump_past_failed_package_on_disjoint_constraint(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
root.add_dependency(Factory.create_dependency("a", "*"))
root.add_dependency(Factory.create_dependency("foo", ">2.0.0"))
......
from typing import TYPE_CHECKING
from poetry.factory import Factory
from tests.mixology.helpers import add_to_repo
from tests.mixology.helpers import check_solver_result
def test_simple_dependencies(root, provider, repo):
if TYPE_CHECKING:
from poetry.packages.project_package import ProjectPackage
from poetry.repositories import Repository
from tests.mixology.version_solver.conftest import Provider
def test_simple_dependencies(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
root.add_dependency(Factory.create_dependency("a", "1.0.0"))
root.add_dependency(Factory.create_dependency("b", "1.0.0"))
......@@ -28,7 +38,9 @@ def test_simple_dependencies(root, provider, repo):
)
def test_shared_dependencies_with_overlapping_constraints(root, provider, repo):
def test_shared_dependencies_with_overlapping_constraints(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
root.add_dependency(Factory.create_dependency("a", "1.0.0"))
root.add_dependency(Factory.create_dependency("b", "1.0.0"))
......@@ -44,7 +56,7 @@ def test_shared_dependencies_with_overlapping_constraints(root, provider, repo):
def test_shared_dependency_where_dependent_version_affects_other_dependencies(
root, provider, repo
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
root.add_dependency(Factory.create_dependency("foo", "<=1.0.2"))
root.add_dependency(Factory.create_dependency("bar", "1.0.0"))
......@@ -63,7 +75,9 @@ def test_shared_dependency_where_dependent_version_affects_other_dependencies(
)
def test_circular_dependency(root, provider, repo):
def test_circular_dependency(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
root.add_dependency(Factory.create_dependency("foo", "1.0.0"))
add_to_repo(repo, "foo", "1.0.0", deps={"bar": "1.0.0"})
......
from typing import TYPE_CHECKING
from poetry.factory import Factory
from tests.mixology.helpers import add_to_repo
from tests.mixology.helpers import check_solver_result
def test_dependency_does_not_match_root_python_constraint(root, provider, repo):
if TYPE_CHECKING:
from poetry.packages.project_package import ProjectPackage
from poetry.repositories import Repository
from tests.mixology.version_solver.conftest import Provider
def test_dependency_does_not_match_root_python_constraint(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
provider.set_package_python_versions("^3.6")
root.add_dependency(Factory.create_dependency("foo", "*"))
......
from typing import TYPE_CHECKING
from poetry.factory import Factory
from tests.mixology.helpers import add_to_repo
from tests.mixology.helpers import check_solver_result
def test_no_version_matching_constraint(root, provider, repo):
if TYPE_CHECKING:
from poetry.packages.project_package import ProjectPackage
from poetry.repositories import Repository
from tests.mixology.version_solver.conftest import Provider
def test_no_version_matching_constraint(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
root.add_dependency(Factory.create_dependency("foo", "^1.0"))
add_to_repo(repo, "foo", "2.0.0")
......@@ -19,7 +29,9 @@ def test_no_version_matching_constraint(root, provider, repo):
)
def test_no_version_that_matches_combined_constraints(root, provider, repo):
def test_no_version_that_matches_combined_constraints(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
root.add_dependency(Factory.create_dependency("foo", "1.0.0"))
root.add_dependency(Factory.create_dependency("bar", "1.0.0"))
......@@ -37,7 +49,9 @@ So, because myapp depends on both foo (1.0.0) and bar (1.0.0), version solving f
check_solver_result(root, provider, error=error)
def test_disjoint_constraints(root, provider, repo):
def test_disjoint_constraints(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
root.add_dependency(Factory.create_dependency("foo", "1.0.0"))
root.add_dependency(Factory.create_dependency("bar", "1.0.0"))
......@@ -55,7 +69,9 @@ So, because myapp depends on both foo (1.0.0) and bar (1.0.0), version solving f
check_solver_result(root, provider, error=error)
def test_disjoint_root_constraints(root, provider, repo):
def test_disjoint_root_constraints(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
root.add_dependency(Factory.create_dependency("foo", "1.0.0"))
root.add_dependency(Factory.create_dependency("foo", "2.0.0"))
......@@ -68,7 +84,9 @@ Because myapp depends on both foo (1.0.0) and foo (2.0.0), version solving faile
check_solver_result(root, provider, error=error)
def test_no_valid_solution(root, provider, repo):
def test_no_valid_solution(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
root.add_dependency(Factory.create_dependency("a", "*"))
root.add_dependency(Factory.create_dependency("b", "*"))
......
from typing import TYPE_CHECKING
from poetry.factory import Factory
from tests.helpers import get_package
from tests.mixology.helpers import add_to_repo
from tests.mixology.helpers import check_solver_result
def test_with_compatible_locked_dependencies(root, provider, repo):
if TYPE_CHECKING:
from poetry.packages.project_package import ProjectPackage
from poetry.repositories import Repository
from tests.mixology.version_solver.conftest import Provider
def test_with_compatible_locked_dependencies(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
root.add_dependency(Factory.create_dependency("foo", "*"))
add_to_repo(repo, "foo", "1.0.0", deps={"bar": "1.0.0"})
......@@ -22,7 +32,9 @@ def test_with_compatible_locked_dependencies(root, provider, repo):
)
def test_with_incompatible_locked_dependencies(root, provider, repo):
def test_with_incompatible_locked_dependencies(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
root.add_dependency(Factory.create_dependency("foo", ">1.0.1"))
add_to_repo(repo, "foo", "1.0.0", deps={"bar": "1.0.0"})
......@@ -40,7 +52,9 @@ def test_with_incompatible_locked_dependencies(root, provider, repo):
)
def test_with_unrelated_locked_dependencies(root, provider, repo):
def test_with_unrelated_locked_dependencies(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
root.add_dependency(Factory.create_dependency("foo", "*"))
add_to_repo(repo, "foo", "1.0.0", deps={"bar": "1.0.0"})
......@@ -60,7 +74,7 @@ def test_with_unrelated_locked_dependencies(root, provider, repo):
def test_unlocks_dependencies_if_necessary_to_ensure_that_a_new_dependency_is_statisfied(
root, provider, repo
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
root.add_dependency(Factory.create_dependency("foo", "*"))
root.add_dependency(Factory.create_dependency("newdep", "2.0.0"))
......@@ -94,7 +108,9 @@ def test_unlocks_dependencies_if_necessary_to_ensure_that_a_new_dependency_is_st
)
def test_with_compatible_locked_dependencies_use_latest(root, provider, repo):
def test_with_compatible_locked_dependencies_use_latest(
root: "ProjectPackage", provider: "Provider", repo: "Repository"
):
root.add_dependency(Factory.create_dependency("foo", "*"))
root.add_dependency(Factory.create_dependency("baz", "*"))
......
......@@ -2,6 +2,7 @@ import logging
import tempfile
from pathlib import Path
from typing import TYPE_CHECKING
import pytest
import tomlkit
......@@ -15,8 +16,13 @@ from tests.helpers import get_dependency
from tests.helpers import get_package
if TYPE_CHECKING:
from _pytest.logging import LogCaptureFixture
from pytest_mock import MockerFixture
@pytest.fixture
def locker():
def locker() -> Locker:
with tempfile.NamedTemporaryFile() as f:
f.close()
locker = Locker(f.name, {})
......@@ -25,11 +31,11 @@ def locker():
@pytest.fixture
def root():
def root() -> ProjectPackage:
return ProjectPackage("root", "1.2.3")
def test_lock_file_data_is_ordered(locker, root):
def test_lock_file_data_is_ordered(locker: Locker, root: ProjectPackage):
package_a = get_package("A", "1.0.0")
package_a.add_dependency(Factory.create_dependency("B", "^1.0"))
package_a.files = [{"file": "foo", "hash": "456"}, {"file": "bar", "hash": "123"}]
......@@ -99,7 +105,7 @@ git-package = []
assert expected == content
def test_locker_properly_loads_extras(locker):
def test_locker_properly_loads_extras(locker: Locker):
content = """\
[[package]]
name = "cachecontrol"
......@@ -144,7 +150,7 @@ cachecontrol = []
assert lockfile_dep.name == "lockfile"
def test_locker_properly_loads_nested_extras(locker):
def test_locker_properly_loads_nested_extras(locker: Locker):
content = """\
[[package]]
name = "a"
......@@ -224,7 +230,7 @@ content-hash = "123456789"
assert len(packages) == 1
def test_locker_properly_loads_extras_legacy(locker):
def test_locker_properly_loads_extras_legacy(locker: Locker):
content = """\
[[package]]
name = "a"
......@@ -274,7 +280,7 @@ content-hash = "123456789"
assert dependency_b.name == "b"
def test_lock_packages_with_null_description(locker, root):
def test_lock_packages_with_null_description(locker: Locker, root: ProjectPackage):
package_a = get_package("A", "1.0.0")
package_a.description = None
......@@ -303,7 +309,7 @@ A = []
assert expected == content
def test_lock_file_should_not_have_mixed_types(locker, root):
def test_lock_file_should_not_have_mixed_types(locker: Locker, root: ProjectPackage):
package_a = get_package("A", "1.0.0")
package_a.add_dependency(Factory.create_dependency("B", "^1.0.0"))
package_a.add_dependency(
......@@ -346,7 +352,7 @@ A = []
assert expected == content
def test_reading_lock_file_should_raise_an_error_on_invalid_data(locker):
def test_reading_lock_file_should_raise_an_error_on_invalid_data(locker: Locker):
content = """[[package]]
name = "A"
version = "1.0.0"
......@@ -378,7 +384,9 @@ A = []
assert "Unable to read the lock file" in str(e.value)
def test_locking_legacy_repository_package_should_include_source_section(root, locker):
def test_locking_legacy_repository_package_should_include_source_section(
root: ProjectPackage, locker: Locker
):
package_a = Package(
"A",
"1.0.0",
......@@ -419,7 +427,7 @@ A = []
def test_locker_should_emit_warnings_if_lock_version_is_newer_but_allowed(
locker, caplog
locker: Locker, caplog: "LogCaptureFixture"
):
content = """\
[metadata]
......@@ -453,7 +461,7 @@ regenerate the lock file with the `poetry lock` command.\
def test_locker_should_raise_an_error_if_lock_version_is_newer_and_not_allowed(
locker, caplog
locker: Locker, caplog: "LogCaptureFixture"
):
content = """\
[metadata]
......@@ -471,7 +479,7 @@ content-hash = "c3d07fca33fba542ef2b2a4d75bf5b48d892d21a830e2ad9c952ba5123a52f77
_ = locker.lock_data
def test_extras_dependencies_are_ordered(locker, root):
def test_extras_dependencies_are_ordered(locker: Locker, root: ProjectPackage):
package_a = get_package("A", "1.0.0")
package_a.add_dependency(
Factory.create_dependency(
......@@ -509,7 +517,7 @@ A = []
def test_locker_should_neither_emit_warnings_nor_raise_error_for_lower_compatible_versions(
locker, caplog
locker: Locker, caplog: "LogCaptureFixture"
):
current_version = Version.parse(Locker._VERSION)
older_version = ".".join(
......@@ -534,7 +542,9 @@ content-hash = "c3d07fca33fba542ef2b2a4d75bf5b48d892d21a830e2ad9c952ba5123a52f77
assert 0 == len(caplog.records)
def test_locker_dumps_dependency_information_correctly(locker, root):
def test_locker_dumps_dependency_information_correctly(
locker: Locker, root: ProjectPackage
):
root_dir = Path(__file__).parent.parent.joinpath("fixtures")
package_a = get_package("A", "1.0.0")
package_a.add_dependency(
......@@ -599,7 +609,9 @@ A = []
assert expected == content
def test_locked_repository_uses_root_dir_of_package(locker, mocker):
def test_locked_repository_uses_root_dir_of_package(
locker: Locker, mocker: "MockerFixture"
):
content = """\
[[package]]
name = "lib-a"
......
from pathlib import Path
from typing import TYPE_CHECKING
from typing import List
import pytest
......@@ -11,31 +13,42 @@ from poetry.plugins import ApplicationPlugin
from poetry.plugins import Plugin
from poetry.plugins.plugin_manager import PluginManager
from poetry.poetry import Poetry
from tests.compat import Protocol
if TYPE_CHECKING:
from pytest_mock import MockerFixture
from tests.conftest import Config
CWD = Path(__file__).parent.parent / "fixtures" / "simple_project"
class ManagerFactory(Protocol):
def __call__(self, type: str = "plugin") -> PluginManager:
...
class MyPlugin(Plugin):
def activate(self, poetry, io):
def activate(self, poetry: Poetry, io: BufferedIO) -> None:
io.write_line("Updating version")
poetry.package.set_version("9.9.9")
class MyCommandPlugin(ApplicationPlugin):
@property
def commands(self):
def commands(self) -> List[str]:
return []
class InvalidPlugin:
def activate(self, poetry, io):
def activate(self, poetry: Poetry, io: BufferedIO) -> None:
io.write_line("Updating version")
poetry.package.version = "9.9.9"
@pytest.fixture()
def poetry(tmp_dir, config):
def poetry(tmp_dir: str, config: "Config") -> Poetry:
poetry = Poetry(
CWD / "pyproject.toml",
{},
......@@ -48,24 +61,29 @@ def poetry(tmp_dir, config):
@pytest.fixture()
def io():
def io() -> BufferedIO:
return BufferedIO()
@pytest.fixture()
def manager_factory(poetry, io):
def _manager(type="plugin"):
def manager_factory(poetry: Poetry, io: BufferedIO) -> ManagerFactory:
def _manager(type: str = "plugin") -> PluginManager:
return PluginManager(type)
return _manager
@pytest.fixture()
def no_plugin_manager(poetry, io):
def no_plugin_manager(poetry: Poetry, io: BufferedIO) -> PluginManager:
return PluginManager("plugin", disable_plugins=True)
def test_load_plugins_and_activate(manager_factory, poetry, io, mocker):
def test_load_plugins_and_activate(
manager_factory: ManagerFactory,
poetry: Poetry,
io: BufferedIO,
mocker: "MockerFixture",
):
manager = manager_factory()
mocker.patch(
......@@ -82,7 +100,12 @@ def test_load_plugins_and_activate(manager_factory, poetry, io, mocker):
assert "Updating version\n" == io.fetch_output()
def test_load_plugins_with_invalid_plugin(manager_factory, poetry, io, mocker):
def test_load_plugins_with_invalid_plugin(
manager_factory: ManagerFactory,
poetry: Poetry,
io: BufferedIO,
mocker: "MockerFixture",
):
manager = manager_factory()
mocker.patch(
......@@ -98,7 +121,12 @@ def test_load_plugins_with_invalid_plugin(manager_factory, poetry, io, mocker):
manager.load_plugins()
def test_load_plugins_with_plugins_disabled(no_plugin_manager, poetry, io, mocker):
def test_load_plugins_with_plugins_disabled(
no_plugin_manager: PluginManager,
poetry: Poetry,
io: BufferedIO,
mocker: "MockerFixture",
):
mocker.patch(
"entrypoints.get_group_all",
return_value=[
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment