Commit 72497bcb by finswimmer Committed by GitHub

Add missing type hints & Force type hints - Part 3 (#4805)

* add typehints to tests.publishing

* add typehints to tests.puzzle

* add typehints to tests.repositories

* add typehints to tests.utils.test_authenticator, tests.utils.test_env, tests.utils.test_env_site, tests.utils.test_exporter

* add typehints to tests.utils.test_extras, tests.utils.test_helpers, tests.utils.test_password_manager, tests.utils.test_patterns, tests.utils.test_pip, tests.utils.setup_reader

* add typehints to tests.test_factory

* add typehints to tests.helpers

* add remaining missing typehints to tests.conftest

* add flake8-annotations to flake8 pre-commit hook

* create a FixtureDirGetter protocol type

* add comments to .flake8 settings and fix missing typehints after rebase
parent 1a3ecfb8
......@@ -3,6 +3,9 @@ min_python_version = 3.6.0
max-line-length = 88
ban-relative-imports = true
inline-quotes = double
# Allow omission of a return type hint for __init__ if at least one argument is annotated
# used by flake8-annotations
mypy-init-return = true
enable-extensions = TC, TC2
type-checking-exempt-modules = typing, typing-extensions
extend-ignore =
......@@ -12,10 +15,17 @@ extend-ignore =
E203,
# SIM106: Handle error-cases first
SIM106,
# ANN101: Missing type annotation for self in method
ANN101,
# ANN102: Missing type annotation for cls in classmethod
ANN102,
per-file-ignores =
# F401: Module imported by unused (non-implicit modules)
# TC002: Move third-party import '...' into a type-checking block
__init__.py:F401,TC002,
# ANN201: Missing return type annotation for public function
tests/test_*:ANN201
tests/**/test_*:ANN201
extend-exclude =
# Frozen and not subject to change in this repo:
get-poetry.py,
......
......@@ -31,6 +31,7 @@ repos:
hooks:
- id: yesqa
additional_dependencies: &flake8_deps
- flake8-annotations==2.7.0
- flake8-broken-line==0.4.0
- flake8-bugbear==21.9.2
- flake8-comprehensions==3.7.0
......
......@@ -187,7 +187,7 @@ class Executor:
return 1 if self._shutdown else 0
@staticmethod
def _get_max_workers(desired_max_workers: Optional[int] = None):
def _get_max_workers(desired_max_workers: Optional[int] = None) -> int:
# This should be directly handled by ThreadPoolExecutor
# however, on some systems the number of CPUs cannot be determined
# (it raises a NotImplementedError), so, in this case, we assume
......
......@@ -8,10 +8,11 @@ from contextlib import suppress
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Any
from typing import Callable
from typing import Dict
from typing import Iterator
from typing import List
from typing import Optional
from typing import TextIO
from typing import Tuple
from typing import Type
......@@ -42,8 +43,15 @@ from tests.helpers import mock_download
if TYPE_CHECKING:
from pytest_mock import MockerFixture
from poetry.installation.executor import Executor
from poetry.poetry import Poetry
from poetry.utils.env import Env
from poetry.utils.env import MockEnv
from tests.helpers import PoetryTestApplication
from tests.types import CommandTesterFactory
from tests.types import FixtureDirGetter
from tests.types import ProjectFactory
......@@ -68,41 +76,43 @@ class Config(BaseConfig):
class DummyBackend(KeyringBackend):
def __init__(self):
def __init__(self) -> None:
self._passwords = {}
@classmethod
def priority(cls):
def priority(cls) -> int:
return 42
def set_password(self, service, username, password):
def set_password(
self, service: str, username: Optional[str], password: Any
) -> None:
self._passwords[service] = {username: password}
def get_password(self, service, username):
def get_password(self, service: str, username: Optional[str]) -> Any:
return self._passwords.get(service, {}).get(username)
def get_credential(self, service, username):
def get_credential(self, service: str, username: Optional[str]) -> Any:
return self._passwords.get(service, {}).get(username)
def delete_password(self, service, username):
def delete_password(self, service: str, username: Optional[str]) -> None:
if service in self._passwords and username in self._passwords[service]:
del self._passwords[service][username]
@pytest.fixture()
def dummy_keyring():
def dummy_keyring() -> DummyBackend:
return DummyBackend()
@pytest.fixture()
def with_simple_keyring(dummy_keyring):
def with_simple_keyring(dummy_keyring: DummyBackend) -> None:
import keyring
keyring.set_keyring(dummy_keyring)
@pytest.fixture()
def with_fail_keyring():
def with_fail_keyring() -> None:
import keyring
from keyring.backends.fail import Keyring
......@@ -111,7 +121,7 @@ def with_fail_keyring():
@pytest.fixture()
def with_chained_keyring(mocker):
def with_chained_keyring(mocker: "MockerFixture") -> None:
from keyring.backends.fail import Keyring
mocker.patch("keyring.backend.get_all_keyring", [Keyring()])
......@@ -130,12 +140,12 @@ def config_cache_dir(tmp_dir: str) -> Path:
@pytest.fixture
def config_virtualenvs_path(config_cache_dir):
def config_virtualenvs_path(config_cache_dir: Path) -> Path:
return config_cache_dir / "virtualenvs"
@pytest.fixture
def config_source(config_cache_dir):
def config_source(config_cache_dir: Path) -> DictConfigSource:
source = DictConfigSource()
source.add_property("cache-dir", str(config_cache_dir))
......@@ -150,7 +160,11 @@ def auth_config_source() -> DictConfigSource:
@pytest.fixture
def config(config_source, auth_config_source, mocker) -> Config:
def config(
config_source: DictConfigSource,
auth_config_source: DictConfigSource,
mocker: "MockerFixture",
) -> Config:
import keyring
from keyring.backends.fail import Keyring
......@@ -169,7 +183,7 @@ def config(config_source, auth_config_source, mocker) -> Config:
@pytest.fixture(autouse=True)
def mock_user_config_dir(mocker):
def mock_user_config_dir(mocker: "MockerFixture") -> Iterator[None]:
config_dir = tempfile.mkdtemp(prefix="poetry_config_")
mocker.patch("poetry.locations.CONFIG_DIR", new=config_dir)
mocker.patch("poetry.factory.CONFIG_DIR", new=config_dir)
......@@ -178,7 +192,7 @@ def mock_user_config_dir(mocker):
@pytest.fixture(autouse=True)
def download_mock(mocker):
def download_mock(mocker: "MockerFixture") -> None:
# Patch download to not download anything but to just copy from fixtures
mocker.patch("poetry.utils.helpers.download_file", new=mock_download)
mocker.patch("poetry.puzzle.provider.download_file", new=mock_download)
......@@ -186,9 +200,9 @@ def download_mock(mocker):
@pytest.fixture(autouse=True)
def pep517_metadata_mock(mocker):
def pep517_metadata_mock(mocker: "MockerFixture") -> None:
@classmethod
def _pep517_metadata(cls, path):
def _pep517_metadata(cls: PackageInfo, path: Path) -> PackageInfo:
with suppress(PackageInfoError):
return PackageInfo.from_setup_files(path)
return PackageInfo(name="demo", version="0.1.2")
......@@ -210,7 +224,7 @@ def environ() -> Iterator[None]:
@pytest.fixture(autouse=True)
def git_mock(mocker):
def git_mock(mocker: "MockerFixture") -> None:
# Patch git module to not actually clone projects
mocker.patch("poetry.core.vcs.git.Git.clone", new=mock_clone)
mocker.patch("poetry.core.vcs.git.Git.checkout", new=lambda *_: None)
......@@ -235,8 +249,8 @@ def fixture_base() -> Path:
@pytest.fixture
def fixture_dir(fixture_base: Path) -> Callable[[str], Path]:
def _fixture_dir(name: str):
def fixture_dir(fixture_base: Path) -> "FixtureDirGetter":
def _fixture_dir(name: str) -> Path:
return fixture_base / name
return _fixture_dir
......@@ -252,18 +266,18 @@ def tmp_dir() -> Iterator[str]:
@pytest.fixture
def mocked_open_files(mocker):
def mocked_open_files(mocker: "MockerFixture") -> List:
files = []
original = Path.open
def mocked_open(self, *args, **kwargs):
def mocked_open(self: Path, *args: Any, **kwargs: Any) -> TextIO:
if self.name in {"pyproject.toml"}:
return mocker.MagicMock()
return original(self, *args, **kwargs)
mocker.patch("pathlib.Path.open", mocked_open)
yield files
return files
@pytest.fixture
......@@ -376,8 +390,16 @@ def project_factory(
@pytest.fixture
def command_tester_factory(app, env) -> "CommandTesterFactory":
def _tester(command, poetry=None, installer=None, executor=None, environment=None):
def command_tester_factory(
app: "PoetryTestApplication", env: "MockEnv"
) -> "CommandTesterFactory":
def _tester(
command: str,
poetry: Optional["Poetry"] = None,
installer: Optional[Installer] = None,
executor: Optional["Executor"] = None,
environment: Optional["Env"] = None,
) -> CommandTester:
command = app.find(command)
tester = CommandTester(command)
......
......@@ -2,7 +2,6 @@ import json
import os
from typing import TYPE_CHECKING
from typing import Callable
import pytest
......@@ -20,6 +19,7 @@ if TYPE_CHECKING:
from poetry.config.dict_config_source import DictConfigSource
from tests.conftest import Config
from tests.types import CommandTesterFactory
from tests.types import FixtureDirGetter
@pytest.fixture()
......@@ -98,7 +98,7 @@ def test_display_single_setting(tester: "CommandTester", config: "Config"):
def test_display_single_local_setting(
command_tester_factory: "CommandTesterFactory", fixture_dir: Callable[[str], "Path"]
command_tester_factory: "CommandTesterFactory", fixture_dir: "FixtureDirGetter"
):
tester = command_tester_factory(
"config", poetry=Factory().create_poetry(fixture_dir("with_local_config"))
......
......@@ -4,7 +4,6 @@ import sys
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Callable
from typing import Iterator
import pytest
......@@ -22,6 +21,7 @@ if TYPE_CHECKING:
from poetry.poetry import Poetry
from tests.helpers import TestRepository
from tests.types import FixtureDirGetter
@pytest.fixture
......@@ -339,7 +339,7 @@ def test_interactive_with_directory_dependency(
tester: CommandTester,
repo: "TestRepository",
source_dir: Path,
fixture_dir: Callable[[str], Path],
fixture_dir: "FixtureDirGetter",
):
repo.add_package(get_package("pendulum", "2.0.0"))
repo.add_package(get_package("pytest", "3.6.0"))
......@@ -390,7 +390,7 @@ def test_interactive_with_directory_dependency_and_other_name(
tester: CommandTester,
repo: "TestRepository",
source_dir: Path,
fixture_dir: Callable[[str], Path],
fixture_dir: "FixtureDirGetter",
):
repo.add_package(get_package("pendulum", "2.0.0"))
repo.add_package(get_package("pytest", "3.6.0"))
......@@ -442,7 +442,7 @@ def test_interactive_with_file_dependency(
tester: CommandTester,
repo: "TestRepository",
source_dir: Path,
fixture_dir: Callable[[str], Path],
fixture_dir: "FixtureDirGetter",
):
repo.add_package(get_package("pendulum", "2.0.0"))
repo.add_package(get_package("pytest", "3.6.0"))
......
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Callable
from typing import Type
import pytest
......@@ -17,6 +16,7 @@ if TYPE_CHECKING:
from poetry.poetry import Poetry
from tests.helpers import TestRepository
from tests.types import CommandTesterFactory
from tests.types import FixtureDirGetter
from tests.types import ProjectFactory
......@@ -33,7 +33,7 @@ def tester(command_tester_factory: "CommandTesterFactory") -> "CommandTester":
def _project_factory(
fixture_name: str,
project_factory: "ProjectFactory",
fixture_dir: Callable[[str], Path],
fixture_dir: "FixtureDirGetter",
) -> "Poetry":
source = fixture_dir(fixture_name)
pyproject_content = (source / "pyproject.toml").read_text(encoding="utf-8")
......@@ -47,21 +47,21 @@ def _project_factory(
@pytest.fixture
def poetry_with_outdated_lockfile(
project_factory: "ProjectFactory", fixture_dir: Callable[[str], Path]
project_factory: "ProjectFactory", fixture_dir: "FixtureDirGetter"
) -> "Poetry":
return _project_factory("outdated_lock", project_factory, fixture_dir)
@pytest.fixture
def poetry_with_up_to_date_lockfile(
project_factory: "ProjectFactory", fixture_dir: Callable[[str], Path]
project_factory: "ProjectFactory", fixture_dir: "FixtureDirGetter"
) -> "Poetry":
return _project_factory("up_to_date_lock", project_factory, fixture_dir)
@pytest.fixture
def poetry_with_old_lockfile(
project_factory: "ProjectFactory", fixture_dir: Callable[[str], Path]
project_factory: "ProjectFactory", fixture_dir: "FixtureDirGetter"
) -> "Poetry":
return _project_factory("old_lock", project_factory, fixture_dir)
......
......@@ -3,6 +3,12 @@ import shutil
import urllib.parse
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 Union
from poetry.console.application import Application
from poetry.core.masonry.utils.helpers import escape_name
......@@ -19,16 +25,29 @@ from poetry.repositories.exceptions import PackageNotFound
from poetry.utils._compat import WINDOWS
if TYPE_CHECKING:
from tomlkit.toml_document import TOMLDocument
from poetry.core.packages.dependency import Dependency
from poetry.core.packages.types import DependencyTypes
from poetry.core.semver.version import Version
from poetry.installation.operations import OperationTypes
from poetry.poetry import Poetry
FIXTURE_PATH = Path(__file__).parent / "fixtures"
def get_package(name, version):
def get_package(name: str, version: Union[str, "Version"]) -> Package:
return Package(name, version)
def get_dependency(
name, constraint=None, groups=None, optional=False, allows_prereleases=False
):
name: str,
constraint: Optional[Union[str, Dict[str, Any]]] = None,
groups: Optional[List[str]] = None,
optional: bool = False,
allows_prereleases: bool = False,
) -> "DependencyTypes":
if constraint is None:
constraint = "*"
......@@ -41,14 +60,14 @@ def get_dependency(
return Factory.create_dependency(name, constraint or "*", groups=groups)
def fixture(path=None):
def fixture(path: Optional[str] = None) -> Path:
if path:
return FIXTURE_PATH / path
else:
return FIXTURE_PATH
def copy_or_symlink(source, dest):
def copy_or_symlink(source: Path, dest: Path) -> None:
if dest.exists():
if dest.is_symlink():
os.unlink(str(dest))
......@@ -72,7 +91,7 @@ def copy_or_symlink(source, dest):
os.symlink(str(source), str(dest))
def mock_clone(_, source, dest):
def mock_clone(_: Any, source: str, dest: Path) -> None:
# Checking source to determine which folder we need to copy
parsed = ParsedUrl.parse(source)
......@@ -87,7 +106,7 @@ def mock_clone(_, source, dest):
copy_or_symlink(folder, dest)
def mock_download(url, dest, **__):
def mock_download(url: str, dest: str, **__: Any) -> None:
parts = urllib.parse.urlparse(url)
fixtures = Path(__file__).parent / "fixtures"
......@@ -97,7 +116,7 @@ def mock_download(url, dest, **__):
class TestExecutor(Executor):
def __init__(self, *args, **kwargs):
def __init__(self, *args: Any, **kwargs: Any):
super().__init__(*args, **kwargs)
self._installs = []
......@@ -105,39 +124,39 @@ class TestExecutor(Executor):
self._uninstalls = []
@property
def installations(self):
def installations(self) -> List[Package]:
return self._installs
@property
def updates(self):
def updates(self) -> List[Package]:
return self._updates
@property
def removals(self):
def removals(self) -> List[Package]:
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_remove(self, operation):
def _execute_remove(self, operation: "OperationTypes") -> int:
return 0
class PoetryTestApplication(Application):
def __init__(self, poetry):
def __init__(self, poetry: "Poetry"):
super().__init__()
self._poetry = poetry
def reset_poetry(self):
def reset_poetry(self) -> None:
poetry = self._poetry
self._poetry = Factory().create_poetry(self._poetry.file.path.parent)
self._poetry.set_pool(poetry.pool)
......@@ -148,7 +167,7 @@ class PoetryTestApplication(Application):
class TestLocker(Locker):
def __init__(self, lock, local_config):
def __init__(self, lock: Union[str, Path], local_config: Dict):
self._lock = TOMLFile(lock)
self._local_config = local_config
self._lock_data = None
......@@ -157,26 +176,26 @@ class TestLocker(Locker):
self._lock_data = None
self._write = False
def write(self, write=True):
def write(self, write: bool = True) -> None:
self._write = write
def is_locked(self):
def is_locked(self) -> bool:
return self._locked
def locked(self, is_locked=True):
def locked(self, is_locked: bool = True) -> "TestLocker":
self._locked = is_locked
return self
def mock_lock_data(self, data):
def mock_lock_data(self, data: Dict) -> None:
self.locked()
self._lock_data = data
def is_fresh(self):
def is_fresh(self) -> bool:
return True
def _write_lock_data(self, data):
def _write_lock_data(self, data: "TOMLDocument") -> None:
if self._write:
super()._write_lock_data(data)
self._locked = True
......@@ -186,14 +205,14 @@ class TestLocker(Locker):
class TestRepository(Repository):
def find_packages(self, dependency):
def find_packages(self, dependency: "Dependency") -> List[Package]:
packages = super().find_packages(dependency)
if len(packages) == 0:
raise PackageNotFound(f"Package [{dependency.name}] not found.")
return packages
def find_links_for_package(self, package):
def find_links_for_package(self, package: Package) -> List[Link]:
return [
Link(
"https://foo.bar/files/{}-{}-py2.py3-none-any.whl".format(
......
......@@ -5,7 +5,6 @@ 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
......@@ -37,6 +36,7 @@ if TYPE_CHECKING:
from pytest_mock import MockerFixture
from poetry.utils.env import VirtualEnv
from tests.types import FixtureDirGetter
@pytest.fixture
......@@ -531,7 +531,7 @@ def test_executor_should_use_cached_link_and_hash(
config: Config,
io: BufferedIO,
mocker: "MockerFixture",
fixture_dir: Callable[[str], Path],
fixture_dir: "FixtureDirGetter",
):
# Produce a file:/// URI that is a valid link
link_cached = Link(
......@@ -573,15 +573,15 @@ def test_executor_should_use_cached_link_and_hash(
],
)
def test_executor_should_be_initialized_with_correct_workers(
tmp_venv,
pool,
config,
io,
mocker,
max_workers,
cpu_count,
side_effect,
expected_workers,
tmp_venv: "VirtualEnv",
pool: Pool,
config: Config,
io: BufferedIO,
mocker: "MockerFixture",
max_workers: Optional[int],
cpu_count: Optional[int],
side_effect: Optional[Exception],
expected_workers: int,
):
config = Config()
config.merge({"installer": {"max-workers": max_workers}})
......
......@@ -4,7 +4,6 @@ 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
......@@ -49,6 +48,7 @@ if TYPE_CHECKING:
from poetry.packages import DependencyPackage
from poetry.utils.env import Env
from tests.conftest import Config
from tests.types import FixtureDirGetter
RESERVED_PACKAGES = ("pip", "setuptools", "wheel")
......@@ -1195,7 +1195,7 @@ def test_run_installs_with_local_file(
locker: Locker,
repo: Repository,
package: ProjectPackage,
fixture_dir: Callable[[str], Path],
fixture_dir: "FixtureDirGetter",
):
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)}))
......@@ -1215,7 +1215,7 @@ def test_run_installs_wheel_with_no_requires_dist(
locker: Locker,
repo: Repository,
package: ProjectPackage,
fixture_dir: Callable[[str], Path],
fixture_dir: "FixtureDirGetter",
):
file_path = fixture_dir(
"wheel_with_no_requires_dist/demo-0.1.0-py2.py3-none-any.whl"
......@@ -1237,7 +1237,7 @@ def test_run_installs_with_local_poetry_directory_and_extras(
repo: Repository,
package: ProjectPackage,
tmpdir: Path,
fixture_dir: Callable[[str], Path],
fixture_dir: "FixtureDirGetter",
):
file_path = fixture_dir("project_with_extras")
package.add_dependency(
......@@ -1262,7 +1262,7 @@ def test_run_installs_with_local_poetry_directory_transitive(
repo: Repository,
package: ProjectPackage,
tmpdir: Path,
fixture_dir: Callable[[str], Path],
fixture_dir: "FixtureDirGetter",
):
root_dir = fixture_dir("directory")
package.root_dir = root_dir
......@@ -1294,7 +1294,7 @@ def test_run_installs_with_local_poetry_file_transitive(
repo: Repository,
package: ProjectPackage,
tmpdir: str,
fixture_dir: Callable[[str], Path],
fixture_dir: "FixtureDirGetter",
):
root_dir = fixture_dir("directory")
package.root_dir = root_dir
......@@ -1328,7 +1328,7 @@ def test_run_installs_with_local_setuptools_directory(
repo: Repository,
package: ProjectPackage,
tmpdir: Path,
fixture_dir: Callable[[str], Path],
fixture_dir: "FixtureDirGetter",
):
file_path = fixture_dir("project_with_setup/")
package.add_dependency(
......
......@@ -2,7 +2,6 @@ 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
......@@ -37,6 +36,7 @@ if TYPE_CHECKING:
from poetry.utils.env import Env
from tests.conftest import Config
from tests.types import FixtureDirGetter
RESERVED_PACKAGES = ("pip", "setuptools", "wheel")
......@@ -842,7 +842,7 @@ def test_run_installs_with_local_file(
locker: Locker,
repo: Repository,
package: ProjectPackage,
fixture_dir: Callable[[str], Path],
fixture_dir: "FixtureDirGetter",
):
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)}))
......@@ -863,7 +863,7 @@ def test_run_installs_wheel_with_no_requires_dist(
locker: Locker,
repo: Repository,
package: ProjectPackage,
fixture_dir: Callable[[str], Path],
fixture_dir: "FixtureDirGetter",
):
file_path = fixture_dir(
"wheel_with_no_requires_dist/demo-0.1.0-py2.py3-none-any.whl"
......@@ -885,7 +885,7 @@ def test_run_installs_with_local_poetry_directory_and_extras(
repo: Repository,
package: ProjectPackage,
tmpdir: Path,
fixture_dir: Callable[[str], Path],
fixture_dir: "FixtureDirGetter",
):
file_path = fixture_dir("project_with_extras")
package.add_dependency(
......@@ -911,7 +911,7 @@ def test_run_installs_with_local_poetry_directory_transitive(
repo: Repository,
package: ProjectPackage,
tmpdir: Path,
fixture_dir: Callable[[str], Path],
fixture_dir: "FixtureDirGetter",
):
root_dir = fixture_dir("directory")
package.root_dir = root_dir
......@@ -943,7 +943,7 @@ def test_run_installs_with_local_poetry_file_transitive(
repo: Repository,
package: ProjectPackage,
tmpdir: Path,
fixture_dir: Callable[[str], Path],
fixture_dir: "FixtureDirGetter",
):
root_dir = fixture_dir("directory")
package.root_dir = root_dir
......@@ -975,7 +975,7 @@ def test_run_installs_with_local_setuptools_directory(
repo: Repository,
package: ProjectPackage,
tmpdir: Path,
fixture_dir: Callable[[str], Path],
fixture_dir: "FixtureDirGetter",
):
file_path = fixture_dir("project_with_setup/")
package.add_dependency(
......
import os
from pathlib import Path
from typing import TYPE_CHECKING
import pytest
......@@ -11,7 +12,16 @@ from poetry.factory import Factory
from poetry.publishing.publisher import Publisher
def test_publish_publishes_to_pypi_by_default(fixture_dir, mocker, config):
if TYPE_CHECKING:
from pytest_mock import MockerFixture
from tests.conftest import Config
from tests.types import FixtureDirGetter
def test_publish_publishes_to_pypi_by_default(
fixture_dir: "FixtureDirGetter", mocker: "MockerFixture", config: "Config"
):
uploader_auth = mocker.patch("poetry.publishing.uploader.Uploader.auth")
uploader_upload = mocker.patch("poetry.publishing.uploader.Uploader.upload")
poetry = Factory().create_poetry(fixture_dir("sample_project"))
......@@ -30,11 +40,12 @@ def test_publish_publishes_to_pypi_by_default(fixture_dir, mocker, config):
] == uploader_upload.call_args
@pytest.mark.parametrize(
("fixture_name",), [("sample_project",), ("with_default_source",)]
)
@pytest.mark.parametrize("fixture_name", ["sample_project", "with_default_source"])
def test_publish_can_publish_to_given_repository(
fixture_dir, mocker, config, fixture_name
fixture_dir: "FixtureDirGetter",
mocker: "MockerFixture",
config: "Config",
fixture_name: str,
):
uploader_auth = mocker.patch("poetry.publishing.uploader.Uploader.auth")
uploader_upload = mocker.patch("poetry.publishing.uploader.Uploader.upload")
......@@ -62,7 +73,9 @@ def test_publish_can_publish_to_given_repository(
assert "Publishing my-package (1.2.3) to foo" in io.fetch_output()
def test_publish_raises_error_for_undefined_repository(fixture_dir, mocker, config):
def test_publish_raises_error_for_undefined_repository(
fixture_dir: "FixtureDirGetter", config: "Config"
):
poetry = Factory().create_poetry(fixture_dir("sample_project"))
poetry._config = config
poetry.config.merge(
......@@ -74,7 +87,9 @@ def test_publish_raises_error_for_undefined_repository(fixture_dir, mocker, conf
publisher.publish("my-repo", None, None)
def test_publish_uses_token_if_it_exists(fixture_dir, mocker, config):
def test_publish_uses_token_if_it_exists(
fixture_dir: "FixtureDirGetter", mocker: "MockerFixture", config: "Config"
):
uploader_auth = mocker.patch("poetry.publishing.uploader.Uploader.auth")
uploader_upload = mocker.patch("poetry.publishing.uploader.Uploader.upload")
poetry = Factory().create_poetry(fixture_dir("sample_project"))
......@@ -91,7 +106,9 @@ def test_publish_uses_token_if_it_exists(fixture_dir, mocker, config):
] == uploader_upload.call_args
def test_publish_uses_cert(fixture_dir, mocker, config):
def test_publish_uses_cert(
fixture_dir: "FixtureDirGetter", mocker: "MockerFixture", config: "Config"
):
cert = "path/to/ca.pem"
uploader_auth = mocker.patch("poetry.publishing.uploader.Uploader.auth")
uploader_upload = mocker.patch("poetry.publishing.uploader.Uploader.upload")
......@@ -115,7 +132,9 @@ def test_publish_uses_cert(fixture_dir, mocker, config):
] == uploader_upload.call_args
def test_publish_uses_client_cert(fixture_dir, mocker, config):
def test_publish_uses_client_cert(
fixture_dir: "FixtureDirGetter", mocker: "MockerFixture", config: "Config"
):
client_cert = "path/to/client.pem"
uploader_upload = mocker.patch("poetry.publishing.uploader.Uploader.upload")
poetry = Factory().create_poetry(fixture_dir("sample_project"))
......@@ -136,7 +155,12 @@ def test_publish_uses_client_cert(fixture_dir, mocker, config):
] == uploader_upload.call_args
def test_publish_read_from_environment_variable(fixture_dir, environ, mocker, config):
def test_publish_read_from_environment_variable(
fixture_dir: "FixtureDirGetter",
environ: None,
mocker: "MockerFixture",
config: "Config",
):
os.environ["POETRY_REPOSITORIES_FOO_URL"] = "https://foo.bar"
os.environ["POETRY_HTTP_BASIC_FOO_USERNAME"] = "bar"
os.environ["POETRY_HTTP_BASIC_FOO_PASSWORD"] = "baz"
......
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Type
import pytest
......@@ -9,19 +10,22 @@ from poetry.publishing.uploader import Uploader
from poetry.publishing.uploader import UploadError
fixtures_dir = Path(__file__).parent.parent / "fixtures"
if TYPE_CHECKING:
import httpretty
from pytest_mock import MockerFixture
def project(name):
return fixtures_dir / name
from tests.types import FixtureDirGetter
@pytest.fixture
def uploader():
return Uploader(Factory().create_poetry(project("simple_project")), NullIO())
def uploader(fixture_dir: "FixtureDirGetter") -> Uploader:
return Uploader(Factory().create_poetry(fixture_dir("simple_project")), NullIO())
def test_uploader_properly_handles_400_errors(http, uploader):
def test_uploader_properly_handles_400_errors(
http: Type["httpretty.httpretty"], uploader: Uploader
):
http.register_uri(http.POST, "https://foo.com", status=400, body="Bad request")
with pytest.raises(UploadError) as e:
......@@ -30,7 +34,9 @@ def test_uploader_properly_handles_400_errors(http, uploader):
assert str(e.value) == "HTTP Error 400: Bad Request"
def test_uploader_properly_handles_403_errors(http, uploader):
def test_uploader_properly_handles_403_errors(
http: Type["httpretty.httpretty"], uploader: Uploader
):
http.register_uri(http.POST, "https://foo.com", status=403, body="Unauthorized")
with pytest.raises(UploadError) as e:
......@@ -39,7 +45,9 @@ def test_uploader_properly_handles_403_errors(http, uploader):
assert str(e.value) == "HTTP Error 403: Forbidden"
def test_uploader_properly_handles_301_redirects(http, uploader):
def test_uploader_properly_handles_301_redirects(
http: Type["httpretty.httpretty"], uploader: Uploader
):
http.register_uri(http.POST, "https://foo.com", status=301, body="Redirect")
with pytest.raises(UploadError) as e:
......@@ -51,7 +59,9 @@ def test_uploader_properly_handles_301_redirects(http, uploader):
)
def test_uploader_registers_for_appropriate_400_errors(mocker, http, uploader):
def test_uploader_registers_for_appropriate_400_errors(
mocker: "MockerFixture", http: Type["httpretty.httpretty"], uploader: Uploader
):
register = mocker.patch("poetry.publishing.uploader.Uploader._register")
http.register_uri(
http.POST, "https://foo.com", status=400, body="No package was ever registered"
......
import shutil
from pathlib import Path
from typing import TYPE_CHECKING
import pytest
......@@ -10,8 +11,13 @@ try:
except ImportError:
import urlparse
if TYPE_CHECKING:
from pytest_mock import MockerFixture
def mock_clone(self, source, dest):
from poetry.core.vcs import Git
def mock_clone(self: "Git", source: str, dest: Path) -> None:
# Checking source to determine which folder we need to copy
parts = urlparse.urlparse(source)
......@@ -28,11 +34,9 @@ def mock_clone(self, source, dest):
@pytest.fixture(autouse=True)
def setup(mocker):
def setup(mocker: "MockerFixture") -> None:
# Patch git module to not actually clone projects
mocker.patch("poetry.core.vcs.git.Git.clone", new=mock_clone)
mocker.patch("poetry.core.vcs.git.Git.checkout", new=lambda *_: None)
p = mocker.patch("poetry.core.vcs.git.Git.rev_parse")
p.return_value = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24"
yield
from pathlib import Path
from subprocess import CalledProcessError
from typing import TYPE_CHECKING
import pytest
......@@ -18,23 +19,27 @@ from poetry.utils.env import MockEnv as BaseMockEnv
from tests.helpers import get_dependency
if TYPE_CHECKING:
from pytest_mock import MockerFixture
class MockEnv(BaseMockEnv):
def run(self, bin, *args):
def run(self, bin: str, *args: str) -> None:
raise EnvCommandError(CalledProcessError(1, "python", output=""))
@pytest.fixture
def root():
def root() -> ProjectPackage:
return ProjectPackage("root", "1.2.3")
@pytest.fixture
def repository():
def repository() -> Repository:
return Repository()
@pytest.fixture
def pool(repository):
def pool(repository: Repository) -> Pool:
pool = Pool()
pool.add_repository(repository)
......@@ -42,12 +47,12 @@ def pool(repository):
@pytest.fixture
def provider(root, pool):
def provider(root: ProjectPackage, pool: Pool) -> Provider:
return Provider(root, pool, NullIO())
@pytest.mark.parametrize("value", [True, False])
def test_search_for_vcs_retains_develop_flag(provider, value):
def test_search_for_vcs_retains_develop_flag(provider: Provider, value: bool):
dependency = VCSDependency(
"demo", "git", "https://github.com/demo/demo.git", develop=value
)
......@@ -55,7 +60,7 @@ def test_search_for_vcs_retains_develop_flag(provider, value):
assert package.develop == value
def test_search_for_vcs_setup_egg_info(provider):
def test_search_for_vcs_setup_egg_info(provider: Provider):
dependency = VCSDependency("demo", "git", "https://github.com/demo/demo.git")
package = provider.search_for_vcs(dependency)[0]
......@@ -73,7 +78,7 @@ def test_search_for_vcs_setup_egg_info(provider):
}
def test_search_for_vcs_setup_egg_info_with_extras(provider):
def test_search_for_vcs_setup_egg_info_with_extras(provider: Provider):
dependency = VCSDependency(
"demo", "git", "https://github.com/demo/demo.git", extras=["foo"]
)
......@@ -93,7 +98,7 @@ def test_search_for_vcs_setup_egg_info_with_extras(provider):
}
def test_search_for_vcs_read_setup(provider, mocker):
def test_search_for_vcs_read_setup(provider: Provider, mocker: "MockerFixture"):
mocker.patch("poetry.utils.env.EnvManager.get", return_value=MockEnv())
dependency = VCSDependency("demo", "git", "https://github.com/demo/demo.git")
......@@ -113,7 +118,9 @@ def test_search_for_vcs_read_setup(provider, mocker):
}
def test_search_for_vcs_read_setup_with_extras(provider, mocker):
def test_search_for_vcs_read_setup_with_extras(
provider: Provider, mocker: "MockerFixture"
):
mocker.patch("poetry.utils.env.EnvManager.get", return_value=MockEnv())
dependency = VCSDependency(
......@@ -131,7 +138,9 @@ def test_search_for_vcs_read_setup_with_extras(provider, mocker):
assert optional == [get_dependency("tomlkit"), get_dependency("cleo")]
def test_search_for_vcs_read_setup_raises_error_if_no_version(provider, mocker):
def test_search_for_vcs_read_setup_raises_error_if_no_version(
provider: Provider, mocker: "MockerFixture"
):
mocker.patch(
"poetry.inspection.info.PackageInfo._pep517_metadata",
return_value=PackageInfo(name="demo", version=None),
......@@ -144,7 +153,7 @@ def test_search_for_vcs_read_setup_raises_error_if_no_version(provider, mocker):
@pytest.mark.parametrize("directory", ["demo", "non-canonical-name"])
def test_search_for_directory_setup_egg_info(provider, directory):
def test_search_for_directory_setup_egg_info(provider: Provider, directory: str):
dependency = DirectoryDependency(
"demo",
Path(__file__).parent.parent
......@@ -170,7 +179,7 @@ def test_search_for_directory_setup_egg_info(provider, directory):
}
def test_search_for_directory_setup_egg_info_with_extras(provider):
def test_search_for_directory_setup_egg_info_with_extras(provider: Provider):
dependency = DirectoryDependency(
"demo",
Path(__file__).parent.parent
......@@ -198,7 +207,7 @@ def test_search_for_directory_setup_egg_info_with_extras(provider):
@pytest.mark.parametrize("directory", ["demo", "non-canonical-name"])
def test_search_for_directory_setup_with_base(provider, directory):
def test_search_for_directory_setup_with_base(provider: Provider, directory: str):
dependency = DirectoryDependency(
"demo",
Path(__file__).parent.parent
......@@ -238,7 +247,9 @@ def test_search_for_directory_setup_with_base(provider, directory):
)
def test_search_for_directory_setup_read_setup(provider, mocker):
def test_search_for_directory_setup_read_setup(
provider: Provider, mocker: "MockerFixture"
):
mocker.patch("poetry.utils.env.EnvManager.get", return_value=MockEnv())
dependency = DirectoryDependency(
......@@ -266,7 +277,9 @@ def test_search_for_directory_setup_read_setup(provider, mocker):
}
def test_search_for_directory_setup_read_setup_with_extras(provider, mocker):
def test_search_for_directory_setup_read_setup_with_extras(
provider: Provider, mocker: "MockerFixture"
):
mocker.patch("poetry.utils.env.EnvManager.get", return_value=MockEnv())
dependency = DirectoryDependency(
......@@ -295,7 +308,7 @@ def test_search_for_directory_setup_read_setup_with_extras(provider, mocker):
}
def test_search_for_directory_setup_read_setup_with_no_dependencies(provider):
def test_search_for_directory_setup_read_setup_with_no_dependencies(provider: Provider):
dependency = DirectoryDependency(
"demo",
Path(__file__).parent.parent
......@@ -314,7 +327,7 @@ def test_search_for_directory_setup_read_setup_with_no_dependencies(provider):
assert package.extras == {}
def test_search_for_directory_poetry(provider):
def test_search_for_directory_poetry(provider: Provider):
dependency = DirectoryDependency(
"project-with-extras",
Path(__file__).parent.parent / "fixtures" / "project_with_extras",
......@@ -342,7 +355,7 @@ def test_search_for_directory_poetry(provider):
}
def test_search_for_directory_poetry_with_extras(provider):
def test_search_for_directory_poetry_with_extras(provider: Provider):
dependency = DirectoryDependency(
"project-with-extras",
Path(__file__).parent.parent / "fixtures" / "project_with_extras",
......@@ -371,7 +384,7 @@ def test_search_for_directory_poetry_with_extras(provider):
}
def test_search_for_file_sdist(provider):
def test_search_for_file_sdist(provider: Provider):
dependency = FileDependency(
"demo",
Path(__file__).parent.parent
......@@ -402,7 +415,7 @@ def test_search_for_file_sdist(provider):
}
def test_search_for_file_sdist_with_extras(provider):
def test_search_for_file_sdist_with_extras(provider: Provider):
dependency = FileDependency(
"demo",
Path(__file__).parent.parent
......@@ -434,7 +447,7 @@ def test_search_for_file_sdist_with_extras(provider):
}
def test_search_for_file_wheel(provider):
def test_search_for_file_wheel(provider: Provider):
dependency = FileDependency(
"demo",
Path(__file__).parent.parent
......@@ -465,7 +478,7 @@ def test_search_for_file_wheel(provider):
}
def test_search_for_file_wheel_with_extras(provider):
def test_search_for_file_wheel_with_extras(provider: Provider):
dependency = FileDependency(
"demo",
Path(__file__).parent.parent
......
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
import pytest
......@@ -25,6 +31,12 @@ from tests.repositories.test_legacy_repository import (
from tests.repositories.test_pypi_repository import MockRepository as MockPyPIRepository
if TYPE_CHECKING:
import httpretty
from poetry.installation.operations import OperationTypes
from poetry.puzzle.transaction import Transaction
DEFAULT_SOURCE_REF = (
VCSDependency("poetry", "git", "git@github.com:python-poetry/poetry.git").branch
or "HEAD"
......@@ -32,49 +44,59 @@ DEFAULT_SOURCE_REF = (
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 io():
def io() -> NullIO:
return NullIO()
@pytest.fixture()
def package():
def package() -> ProjectPackage:
return ProjectPackage("root", "1.0")
@pytest.fixture()
def installed():
def installed() -> InstalledRepository:
return InstalledRepository()
@pytest.fixture()
def locked():
def locked() -> Repository:
return Repository()
@pytest.fixture()
def repo():
def repo() -> Repository:
return Repository()
@pytest.fixture()
def pool(repo):
def pool(repo: Repository) -> Pool:
return Pool([repo])
@pytest.fixture()
def solver(package, pool, installed, locked, io):
def solver(
package: ProjectPackage,
pool: Pool,
installed: InstalledRepository,
locked: Repository,
io: NullIO,
) -> Solver:
return Solver(
package, pool, installed, locked, io, provider=Provider(package, pool, io)
)
def check_solver_result(transaction, expected, synchronize=False):
def check_solver_result(
transaction: "Transaction",
expected: List[Dict[str, Any]],
synchronize: bool = False,
) -> List["OperationTypes"]:
for e in expected:
if "skipped" not in e:
e["skipped"] = False
......@@ -103,7 +125,9 @@ def check_solver_result(transaction, expected, synchronize=False):
return ops
def test_solver_install_single(solver, repo, package):
def test_solver_install_single(
solver: Solver, repo: Repository, package: ProjectPackage
):
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
......@@ -114,7 +138,9 @@ def test_solver_install_single(solver, repo, package):
check_solver_result(transaction, [{"job": "install", "package": package_a}])
def test_solver_remove_if_no_longer_locked(solver, locked, installed):
def test_solver_remove_if_no_longer_locked(
solver: Solver, locked: Repository, installed: InstalledRepository
):
package_a = get_package("A", "1.0")
installed.add_package(package_a)
locked.add_package(package_a)
......@@ -124,7 +150,7 @@ def test_solver_remove_if_no_longer_locked(solver, locked, installed):
check_solver_result(transaction, [{"job": "remove", "package": package_a}])
def test_remove_non_installed(solver, repo, locked):
def test_remove_non_installed(solver: Solver, repo: Repository, locked: Repository):
package_a = get_package("A", "1.0")
locked.add_package(package_a)
......@@ -137,7 +163,9 @@ def test_remove_non_installed(solver, repo, locked):
check_solver_result(transaction, [])
def test_install_non_existing_package_fail(solver, repo, package):
def test_install_non_existing_package_fail(
solver: Solver, repo: Repository, package: ProjectPackage
):
package.add_dependency(Factory.create_dependency("B", "1"))
package_a = get_package("A", "1.0")
......@@ -147,7 +175,7 @@ def test_install_non_existing_package_fail(solver, repo, package):
solver.solve()
def test_solver_with_deps(solver, repo, package):
def test_solver_with_deps(solver: Solver, repo: Repository, package: ProjectPackage):
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
......@@ -171,7 +199,9 @@ def test_solver_with_deps(solver, repo, package):
)
def test_install_honours_not_equal(solver, repo, package):
def test_install_honours_not_equal(
solver: Solver, repo: Repository, package: ProjectPackage
):
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
......@@ -199,7 +229,9 @@ def test_install_honours_not_equal(solver, repo, package):
)
def test_install_with_deps_in_order(solver, repo, package):
def test_install_with_deps_in_order(
solver: Solver, repo: Repository, package: ProjectPackage
):
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*"))
package.add_dependency(Factory.create_dependency("C", "*"))
......@@ -228,7 +260,12 @@ def test_install_with_deps_in_order(solver, repo, package):
)
def test_install_installed(solver, repo, installed, package):
def test_install_installed(
solver: Solver,
repo: Repository,
installed: InstalledRepository,
package: ProjectPackage,
):
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
......@@ -242,7 +279,12 @@ def test_install_installed(solver, repo, installed, package):
)
def test_update_installed(solver, repo, installed, package):
def test_update_installed(
solver: Solver,
repo: Repository,
installed: InstalledRepository,
package: ProjectPackage,
):
package.add_dependency(Factory.create_dependency("A", "*"))
installed.add_package(get_package("A", "1.0"))
......@@ -259,7 +301,13 @@ def test_update_installed(solver, repo, installed, package):
)
def test_update_with_use_latest(solver, repo, installed, package, locked):
def test_update_with_use_latest(
solver: Solver,
repo: Repository,
installed: InstalledRepository,
package: ProjectPackage,
locked: Repository,
):
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*"))
......@@ -288,7 +336,7 @@ def test_update_with_use_latest(solver, repo, installed, package, locked):
)
def test_solver_sets_groups(solver, repo, package):
def test_solver_sets_groups(solver: Solver, repo: Repository, package: ProjectPackage):
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*", groups=["dev"]))
......@@ -317,7 +365,9 @@ def test_solver_sets_groups(solver, repo, package):
assert ops[1].package.category == "main"
def test_solver_respects_root_package_python_versions(solver, repo, package):
def test_solver_respects_root_package_python_versions(
solver: Solver, repo: Repository, package: ProjectPackage
):
solver.provider.set_package_python_versions("~3.4")
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*"))
......@@ -348,7 +398,9 @@ def test_solver_respects_root_package_python_versions(solver, repo, package):
)
def test_solver_fails_if_mismatch_root_python_versions(solver, repo, package):
def test_solver_fails_if_mismatch_root_python_versions(
solver: Solver, repo: Repository, package: ProjectPackage
):
solver.provider.set_package_python_versions("^3.4")
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*"))
......@@ -368,7 +420,9 @@ def test_solver_fails_if_mismatch_root_python_versions(solver, repo, package):
solver.solve()
def test_solver_solves_optional_and_compatible_packages(solver, repo, package):
def test_solver_solves_optional_and_compatible_packages(
solver: Solver, repo: Repository, package: ProjectPackage
):
solver.provider.set_package_python_versions("~3.4")
package.extras["foo"] = [get_dependency("B")]
package.add_dependency(
......@@ -401,7 +455,9 @@ def test_solver_solves_optional_and_compatible_packages(solver, repo, package):
)
def test_solver_does_not_return_extras_if_not_requested(solver, repo, package):
def test_solver_does_not_return_extras_if_not_requested(
solver: Solver, repo: Repository, package: ProjectPackage
):
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*"))
......@@ -426,7 +482,9 @@ def test_solver_does_not_return_extras_if_not_requested(solver, repo, package):
)
def test_solver_returns_extras_if_requested(solver, repo, package):
def test_solver_returns_extras_if_requested(
solver: Solver, repo: Repository, package: ProjectPackage
):
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(
Factory.create_dependency("B", {"version": "*", "extras": ["foo"]})
......@@ -460,8 +518,13 @@ def test_solver_returns_extras_if_requested(solver, repo, package):
assert ops[0].package.marker.is_any()
@pytest.mark.parametrize(("enabled_extra",), [("one",), ("two",), (None,)])
def test_solver_returns_extras_only_requested(solver, repo, package, enabled_extra):
@pytest.mark.parametrize("enabled_extra", ["one", "two", None])
def test_solver_returns_extras_only_requested(
solver: Solver,
repo: Repository,
package: ProjectPackage,
enabled_extra: Optional[bool],
):
extras = [enabled_extra] if enabled_extra is not None else []
package.add_dependency(Factory.create_dependency("A", "*"))
......@@ -517,9 +580,12 @@ def test_solver_returns_extras_only_requested(solver, repo, package, enabled_ext
assert ops[0].package.marker.is_any()
@pytest.mark.parametrize(("enabled_extra",), [("one",), ("two",), (None,)])
@pytest.mark.parametrize("enabled_extra", ["one", "two", None])
def test_solver_returns_extras_when_multiple_extras_use_same_dependency(
solver, repo, package, enabled_extra
solver: Solver,
repo: Repository,
package: ProjectPackage,
enabled_extra: Optional[bool],
):
package.add_dependency(Factory.create_dependency("A", "*"))
......@@ -563,9 +629,12 @@ def test_solver_returns_extras_when_multiple_extras_use_same_dependency(
assert ops[0].package.marker.is_any()
@pytest.mark.parametrize(("enabled_extra",), [("one",), ("two",), (None,)])
@pytest.mark.parametrize("enabled_extra", ["one", "two", None])
def test_solver_returns_extras_only_requested_nested(
solver, repo, package, enabled_extra
solver: Solver,
repo: Repository,
package: ProjectPackage,
enabled_extra: Optional[bool],
):
package.add_dependency(Factory.create_dependency("A", "*"))
......@@ -619,7 +688,9 @@ def test_solver_returns_extras_only_requested_nested(
assert ops[0].package.marker.is_any()
def test_solver_returns_prereleases_if_requested(solver, repo, package):
def test_solver_returns_prereleases_if_requested(
solver: Solver, repo: Repository, package: ProjectPackage
):
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*"))
package.add_dependency(
......@@ -648,7 +719,9 @@ def test_solver_returns_prereleases_if_requested(solver, repo, package):
)
def test_solver_does_not_return_prereleases_if_not_requested(solver, repo, package):
def test_solver_does_not_return_prereleases_if_not_requested(
solver: Solver, repo: Repository, package: ProjectPackage
):
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*"))
package.add_dependency(Factory.create_dependency("C", "*"))
......@@ -675,7 +748,9 @@ def test_solver_does_not_return_prereleases_if_not_requested(solver, repo, packa
)
def test_solver_sub_dependencies_with_requirements(solver, repo, package):
def test_solver_sub_dependencies_with_requirements(
solver: Solver, repo: Repository, package: ProjectPackage
):
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*"))
......@@ -711,7 +786,9 @@ def test_solver_sub_dependencies_with_requirements(solver, repo, package):
assert op.package.marker.is_any()
def test_solver_sub_dependencies_with_requirements_complex(solver, repo, package):
def test_solver_sub_dependencies_with_requirements_complex(
solver: Solver, repo: Repository, package: ProjectPackage
):
package.add_dependency(
Factory.create_dependency("A", {"version": "^1.0", "python": "<5.0"})
)
......@@ -769,7 +846,7 @@ def test_solver_sub_dependencies_with_requirements_complex(solver, repo, package
def test_solver_sub_dependencies_with_not_supported_python_version(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
solver.provider.set_package_python_versions("^3.5")
package.add_dependency(Factory.create_dependency("A", "*"))
......@@ -791,7 +868,7 @@ def test_solver_sub_dependencies_with_not_supported_python_version(
def test_solver_sub_dependencies_with_not_supported_python_version_transitive(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
solver.provider.set_package_python_versions("^3.4")
......@@ -835,7 +912,7 @@ def test_solver_sub_dependencies_with_not_supported_python_version_transitive(
def test_solver_with_dependency_in_both_default_and_dev_dependencies(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
solver.provider.set_package_python_versions("^3.5")
package.add_dependency(Factory.create_dependency("A", "*"))
......@@ -888,7 +965,7 @@ def test_solver_with_dependency_in_both_default_and_dev_dependencies(
def test_solver_with_dependency_in_both_main_and_dev_dependencies_with_one_more_dependent(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("E", "*"))
......@@ -947,7 +1024,9 @@ def test_solver_with_dependency_in_both_main_and_dev_dependencies_with_one_more_
assert e.category == "main"
def test_solver_with_dependency_and_prerelease_sub_dependencies(solver, repo, package):
def test_solver_with_dependency_and_prerelease_sub_dependencies(
solver: Solver, repo: Repository, package: ProjectPackage
):
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
......@@ -972,7 +1051,9 @@ def test_solver_with_dependency_and_prerelease_sub_dependencies(solver, repo, pa
)
def test_solver_circular_dependency(solver, repo, package):
def test_solver_circular_dependency(
solver: Solver, repo: Repository, package: ProjectPackage
):
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
......@@ -1002,7 +1083,9 @@ def test_solver_circular_dependency(solver, repo, package):
assert ops[0].package.category == "main"
def test_solver_circular_dependency_chain(solver, repo, package):
def test_solver_circular_dependency_chain(
solver: Solver, repo: Repository, package: ProjectPackage
):
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
......@@ -1037,7 +1120,9 @@ def test_solver_circular_dependency_chain(solver, repo, package):
assert ops[0].package.category == "main"
def test_solver_dense_dependencies(solver, repo, package):
def test_solver_dense_dependencies(
solver: Solver, repo: Repository, package: ProjectPackage
):
# The root package depends on packages A0...An-1,
# And package Ai depends on packages A0...Ai-1
# This graph is a transitive tournament
......@@ -1058,7 +1143,9 @@ def test_solver_dense_dependencies(solver, repo, package):
)
def test_solver_duplicate_dependencies_same_constraint(solver, repo, package):
def test_solver_duplicate_dependencies_same_constraint(
solver: Solver, repo: Repository, package: ProjectPackage
):
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
......@@ -1085,7 +1172,9 @@ def test_solver_duplicate_dependencies_same_constraint(solver, repo, package):
)
def test_solver_duplicate_dependencies_different_constraints(solver, repo, package):
def test_solver_duplicate_dependencies_different_constraints(
solver: Solver, repo: Repository, package: ProjectPackage
):
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
......@@ -1116,7 +1205,7 @@ def test_solver_duplicate_dependencies_different_constraints(solver, repo, packa
def test_solver_duplicate_dependencies_different_constraints_same_requirements(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
package.add_dependency(Factory.create_dependency("A", "*"))
......@@ -1143,7 +1232,7 @@ So, because no versions of a match !=1.0
def test_solver_duplicate_dependencies_different_constraints_merge_no_markers(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "1.0"))
......@@ -1185,7 +1274,9 @@ def test_solver_duplicate_dependencies_different_constraints_merge_no_markers(
)
def test_solver_duplicate_dependencies_sub_dependencies(solver, repo, package):
def test_solver_duplicate_dependencies_sub_dependencies(
solver: Solver, repo: Repository, package: ProjectPackage
):
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
......@@ -1224,7 +1315,9 @@ def test_solver_duplicate_dependencies_sub_dependencies(solver, repo, package):
)
def test_solver_fails_if_dependency_name_does_not_match_package(solver, repo, package):
def test_solver_fails_if_dependency_name_does_not_match_package(
solver: Solver, repo: Repository, package: ProjectPackage
):
package.add_dependency(
Factory.create_dependency(
"my-demo", {"git": "https://github.com/demo/demo.git"}
......@@ -1236,7 +1329,7 @@ def test_solver_fails_if_dependency_name_does_not_match_package(solver, repo, pa
def test_solver_does_not_get_stuck_in_recursion_on_circular_dependency(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
package_a = get_package("A", "1.0")
package_a.add_dependency(Factory.create_dependency("B", "^1.0"))
......@@ -1263,7 +1356,9 @@ def test_solver_does_not_get_stuck_in_recursion_on_circular_dependency(
)
def test_solver_can_resolve_git_dependencies(solver, repo, package):
def test_solver_can_resolve_git_dependencies(
solver: Solver, repo: Repository, package: ProjectPackage
):
pendulum = get_package("pendulum", "2.0.3")
cleo = get_package("cleo", "1.0.0")
repo.add_package(pendulum)
......@@ -1296,7 +1391,9 @@ def test_solver_can_resolve_git_dependencies(solver, repo, package):
assert op.package.source_resolved_reference.startswith("9cf87a2")
def test_solver_can_resolve_git_dependencies_with_extras(solver, repo, package):
def test_solver_can_resolve_git_dependencies_with_extras(
solver: Solver, repo: Repository, package: ProjectPackage
):
pendulum = get_package("pendulum", "2.0.3")
cleo = get_package("cleo", "1.0.0")
repo.add_package(pendulum)
......@@ -1334,7 +1431,9 @@ def test_solver_can_resolve_git_dependencies_with_extras(solver, repo, package):
[{"branch": "a-branch"}, {"tag": "a-tag"}, {"rev": "9cf8"}],
ids=["branch", "tag", "rev"],
)
def test_solver_can_resolve_git_dependencies_with_ref(solver, repo, package, ref):
def test_solver_can_resolve_git_dependencies_with_ref(
solver: Solver, repo: Repository, package: Package, ref: Dict[str, str]
):
pendulum = get_package("pendulum", "2.0.3")
cleo = get_package("cleo", "1.0.0")
repo.add_package(pendulum)
......@@ -1368,7 +1467,7 @@ def test_solver_can_resolve_git_dependencies_with_ref(solver, repo, package, ref
def test_solver_does_not_trigger_conflict_for_python_constraint_if_python_requirement_is_compatible(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
solver.provider.set_package_python_versions("~2.7 || ^3.4")
package.add_dependency(
......@@ -1386,7 +1485,7 @@ def test_solver_does_not_trigger_conflict_for_python_constraint_if_python_requir
def test_solver_does_not_trigger_conflict_for_python_constraint_if_python_requirement_is_compatible_multiple(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
solver.provider.set_package_python_versions("~2.7 || ^3.4")
package.add_dependency(
......@@ -1418,7 +1517,7 @@ def test_solver_does_not_trigger_conflict_for_python_constraint_if_python_requir
def test_solver_triggers_conflict_for_dependency_python_not_fully_compatible_with_package_python(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
solver.provider.set_package_python_versions("~2.7 || ^3.4")
package.add_dependency(
......@@ -1435,7 +1534,7 @@ def test_solver_triggers_conflict_for_dependency_python_not_fully_compatible_wit
def test_solver_finds_compatible_package_for_dependency_python_not_fully_compatible_with_package_python(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
solver.provider.set_package_python_versions("~2.7 || ^3.4")
package.add_dependency(
......@@ -1457,7 +1556,7 @@ def test_solver_finds_compatible_package_for_dependency_python_not_fully_compati
def test_solver_does_not_trigger_new_resolution_on_duplicate_dependencies_if_only_extras(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
dep1 = Dependency.create_from_pep_508('B (>=1.0); extra == "foo"')
dep1.activate()
......@@ -1495,7 +1594,7 @@ def test_solver_does_not_trigger_new_resolution_on_duplicate_dependencies_if_onl
def test_solver_does_not_raise_conflict_for_locked_conditional_dependencies(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
solver.provider.set_package_python_versions("~2.7 || ^3.4")
package.add_dependency(
......@@ -1527,7 +1626,7 @@ def test_solver_does_not_raise_conflict_for_locked_conditional_dependencies(
def test_solver_returns_extras_if_requested_in_dependencies_and_not_in_root_package(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*"))
......@@ -1566,7 +1665,7 @@ def test_solver_returns_extras_if_requested_in_dependencies_and_not_in_root_pack
def test_solver_should_not_resolve_prerelease_version_if_not_requested(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
package.add_dependency(Factory.create_dependency("A", "~1.8.0"))
package.add_dependency(Factory.create_dependency("B", "^0.5.0"))
......@@ -1585,7 +1684,7 @@ def test_solver_should_not_resolve_prerelease_version_if_not_requested(
def test_solver_ignores_dependencies_with_incompatible_python_full_version_marker(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
solver.provider.set_package_python_versions("^3.6")
package.add_dependency(Factory.create_dependency("A", "^1.0"))
......@@ -1616,7 +1715,9 @@ def test_solver_ignores_dependencies_with_incompatible_python_full_version_marke
)
def test_solver_git_dependencies_update(solver, repo, package, installed):
def test_solver_git_dependencies_update(
solver: Solver, repo: Repository, package: Package, installed: InstalledRepository
):
pendulum = get_package("pendulum", "2.0.3")
cleo = get_package("cleo", "1.0.0")
repo.add_package(pendulum)
......@@ -1663,7 +1764,9 @@ def test_solver_git_dependencies_update(solver, repo, package, installed):
assert op.initial_package.source_resolved_reference == "123456"
def test_solver_git_dependencies_update_skipped(solver, repo, package, installed):
def test_solver_git_dependencies_update_skipped(
solver: Solver, repo: Repository, package: Package, installed: InstalledRepository
):
pendulum = get_package("pendulum", "2.0.3")
cleo = get_package("cleo", "1.0.0")
repo.add_package(pendulum)
......@@ -1695,7 +1798,7 @@ def test_solver_git_dependencies_update_skipped(solver, repo, package, installed
def test_solver_git_dependencies_short_hash_update_skipped(
solver, repo, package, installed
solver: Solver, repo: Repository, package: Package, installed: InstalledRepository
):
pendulum = get_package("pendulum", "2.0.3")
cleo = get_package("cleo", "1.0.0")
......@@ -1740,7 +1843,9 @@ def test_solver_git_dependencies_short_hash_update_skipped(
)
def test_solver_can_resolve_directory_dependencies(solver, repo, package):
def test_solver_can_resolve_directory_dependencies(
solver: Solver, repo: Repository, package: ProjectPackage
):
pendulum = get_package("pendulum", "2.0.3")
repo.add_package(pendulum)
......@@ -1773,7 +1878,12 @@ def test_solver_can_resolve_directory_dependencies(solver, repo, package):
def test_solver_can_resolve_directory_dependencies_nested_editable(
solver, repo, pool, installed, locked, io
solver: Solver,
repo: Repository,
pool: Pool,
installed: InstalledRepository,
locked: Repository,
io: NullIO,
):
base = Path(__file__).parent.parent / "fixtures" / "project_with_nested_local"
poetry = Factory().create_poetry(cwd=base)
......@@ -1826,7 +1936,9 @@ def test_solver_can_resolve_directory_dependencies_nested_editable(
assert op.package.develop is True
def test_solver_can_resolve_directory_dependencies_with_extras(solver, repo, package):
def test_solver_can_resolve_directory_dependencies_with_extras(
solver: Solver, repo: Repository, package: ProjectPackage
):
pendulum = get_package("pendulum", "2.0.3")
cleo = get_package("cleo", "1.0.0")
repo.add_package(pendulum)
......@@ -1866,7 +1978,9 @@ def test_solver_can_resolve_directory_dependencies_with_extras(solver, repo, pac
assert op.package.source_url == path
def test_solver_can_resolve_sdist_dependencies(solver, repo, package):
def test_solver_can_resolve_sdist_dependencies(
solver: Solver, repo: Repository, package: ProjectPackage
):
pendulum = get_package("pendulum", "2.0.3")
repo.add_package(pendulum)
......@@ -1896,7 +2010,9 @@ def test_solver_can_resolve_sdist_dependencies(solver, repo, package):
assert op.package.source_url == path
def test_solver_can_resolve_sdist_dependencies_with_extras(solver, repo, package):
def test_solver_can_resolve_sdist_dependencies_with_extras(
solver: Solver, repo: Repository, package: ProjectPackage
):
pendulum = get_package("pendulum", "2.0.3")
cleo = get_package("cleo", "1.0.0")
repo.add_package(pendulum)
......@@ -1934,7 +2050,9 @@ def test_solver_can_resolve_sdist_dependencies_with_extras(solver, repo, package
assert op.package.source_url == path
def test_solver_can_resolve_wheel_dependencies(solver, repo, package):
def test_solver_can_resolve_wheel_dependencies(
solver: Solver, repo: Repository, package: ProjectPackage
):
pendulum = get_package("pendulum", "2.0.3")
repo.add_package(pendulum)
......@@ -1964,7 +2082,9 @@ def test_solver_can_resolve_wheel_dependencies(solver, repo, package):
assert op.package.source_url == path
def test_solver_can_resolve_wheel_dependencies_with_extras(solver, repo, package):
def test_solver_can_resolve_wheel_dependencies_with_extras(
solver: Solver, repo: Repository, package: ProjectPackage
):
pendulum = get_package("pendulum", "2.0.3")
cleo = get_package("cleo", "1.0.0")
repo.add_package(pendulum)
......@@ -2003,7 +2123,10 @@ def test_solver_can_resolve_wheel_dependencies_with_extras(solver, repo, package
def test_solver_can_solve_with_legacy_repository_using_proper_dists(
package, installed, locked, io
package: ProjectPackage,
installed: InstalledRepository,
locked: Repository,
io: NullIO,
):
repo = MockLegacyRepository()
pool = Pool([repo])
......@@ -2045,7 +2168,10 @@ def test_solver_can_solve_with_legacy_repository_using_proper_dists(
def test_solver_can_solve_with_legacy_repository_using_proper_python_compatible_dists(
package, installed, locked, io
package: ProjectPackage,
installed: InstalledRepository,
locked: Repository,
io: NullIO,
):
package.python_versions = "^3.7"
......@@ -2075,7 +2201,12 @@ def test_solver_can_solve_with_legacy_repository_using_proper_python_compatible_
)
def test_solver_skips_invalid_versions(package, installed, locked, io):
def test_solver_skips_invalid_versions(
package: ProjectPackage,
installed: InstalledRepository,
locked: Repository,
io: NullIO,
):
package.python_versions = "^3.7"
repo = MockPyPIRepository()
......@@ -2092,7 +2223,9 @@ def test_solver_skips_invalid_versions(package, installed, locked, io):
)
def test_multiple_constraints_on_root(package, solver, repo):
def test_multiple_constraints_on_root(
package: ProjectPackage, solver: Solver, repo: Repository
):
package.add_dependency(
Factory.create_dependency("foo", {"version": "^1.0", "python": "^2.7"})
)
......@@ -2115,7 +2248,10 @@ def test_multiple_constraints_on_root(package, solver, repo):
def test_solver_chooses_most_recent_version_amongst_repositories(
package, installed, locked, io
package: ProjectPackage,
installed: InstalledRepository,
locked: Repository,
io: NullIO,
):
package.python_versions = "^3.7"
package.add_dependency(Factory.create_dependency("tomlkit", {"version": "^0.5"}))
......@@ -2136,7 +2272,10 @@ def test_solver_chooses_most_recent_version_amongst_repositories(
def test_solver_chooses_from_correct_repository_if_forced(
package, installed, locked, io
package: ProjectPackage,
installed: InstalledRepository,
locked: Repository,
io: NullIO,
):
package.python_versions = "^3.7"
package.add_dependency(
......@@ -2170,7 +2309,10 @@ def test_solver_chooses_from_correct_repository_if_forced(
def test_solver_chooses_from_correct_repository_if_forced_and_transitive_dependency(
package, installed, locked, io
package: ProjectPackage,
installed: InstalledRepository,
locked: Repository,
io: NullIO,
):
package.python_versions = "^3.7"
package.add_dependency(Factory.create_dependency("foo", "^1.0"))
......@@ -2212,7 +2354,10 @@ def test_solver_chooses_from_correct_repository_if_forced_and_transitive_depende
def test_solver_does_not_choose_from_secondary_repository_by_default(
package, installed, locked, io
package: ProjectPackage,
installed: InstalledRepository,
locked: Repository,
io: NullIO,
):
package.python_versions = "^3.7"
package.add_dependency(Factory.create_dependency("clikit", {"version": "^0.2.0"}))
......@@ -2258,7 +2403,12 @@ def test_solver_does_not_choose_from_secondary_repository_by_default(
assert ops[2].package.source_url == "http://legacy.foo.bar"
def test_solver_chooses_from_secondary_if_explicit(package, installed, locked, io):
def test_solver_chooses_from_secondary_if_explicit(
package: ProjectPackage,
installed: InstalledRepository,
locked: Repository,
io: NullIO,
):
package.python_versions = "^3.7"
package.add_dependency(
Factory.create_dependency("clikit", {"version": "^0.2.0", "source": "PyPI"})
......@@ -2298,7 +2448,12 @@ def test_solver_chooses_from_secondary_if_explicit(package, installed, locked, i
def test_solver_discards_packages_with_empty_markers(
package, installed, locked, io, pool, repo
package: ProjectPackage,
installed: InstalledRepository,
locked: Repository,
io: NullIO,
pool: Pool,
repo: Repository,
):
package.python_versions = "~2.7 || ^3.4"
package.add_dependency(
......@@ -2334,7 +2489,7 @@ def test_solver_discards_packages_with_empty_markers(
def test_solver_does_not_raise_conflict_for_conditional_dev_dependencies(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
solver.provider.set_package_python_versions("~2.7 || ^3.5")
package.add_dependency(
......@@ -2366,7 +2521,7 @@ def test_solver_does_not_raise_conflict_for_conditional_dev_dependencies(
def test_solver_does_not_loop_indefinitely_on_duplicate_constraints_with_extras(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
solver.provider.set_package_python_versions("~2.7 || ^3.5")
package.add_dependency(
......@@ -2397,7 +2552,13 @@ def test_solver_does_not_loop_indefinitely_on_duplicate_constraints_with_extras(
def test_solver_does_not_fail_with_locked_git_and_non_git_dependencies(
solver, repo, package, locked, pool, installed, io
solver: Solver,
repo: Repository,
package: Package,
locked: Repository,
pool: Pool,
installed: InstalledRepository,
io: NullIO,
):
package.add_dependency(
Factory.create_dependency("demo", {"git": "https://github.com/demo/demo.git"})
......@@ -2434,7 +2595,9 @@ def test_solver_does_not_fail_with_locked_git_and_non_git_dependencies(
)
def test_ignore_python_constraint_no_overlap_dependencies(solver, repo, package):
def test_ignore_python_constraint_no_overlap_dependencies(
solver: Solver, repo: Repository, package: ProjectPackage
):
pytest = get_package("demo", "1.0.0")
pytest.add_dependency(
Factory.create_dependency(
......@@ -2458,7 +2621,7 @@ def test_ignore_python_constraint_no_overlap_dependencies(solver, repo, package)
def test_solver_should_not_go_into_an_infinite_loop_on_duplicate_dependencies(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
solver.provider.set_package_python_versions("~2.7 || ^3.5")
package.add_dependency(Factory.create_dependency("A", "^1.0"))
......@@ -2490,7 +2653,13 @@ def test_solver_should_not_go_into_an_infinite_loop_on_duplicate_dependencies(
)
def test_solver_synchronize_single(package, pool, installed, locked, io):
def test_solver_synchronize_single(
package: ProjectPackage,
pool: Pool,
installed: InstalledRepository,
locked: Repository,
io: NullIO,
):
solver = Solver(package, pool, installed, locked, io)
package_a = get_package("a", "1.0")
installed.add_package(package_a)
......@@ -2504,7 +2673,11 @@ def test_solver_synchronize_single(package, pool, installed, locked, io):
@pytest.mark.skip(reason="Poetry no longer has critical package requirements")
def test_solver_with_synchronization_keeps_critical_package(
package, pool, installed, locked, io
package: ProjectPackage,
pool: Pool,
installed: InstalledRepository,
locked: Repository,
io: NullIO,
):
solver = Solver(package, pool, installed, locked, io)
package_pip = get_package("setuptools", "1.0")
......@@ -2516,7 +2689,7 @@ def test_solver_with_synchronization_keeps_critical_package(
def test_solver_cannot_choose_another_version_for_directory_dependencies(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
pendulum = get_package("pendulum", "2.0.3")
demo = get_package("demo", "0.1.0")
......@@ -2545,7 +2718,7 @@ def test_solver_cannot_choose_another_version_for_directory_dependencies(
def test_solver_cannot_choose_another_version_for_file_dependencies(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
pendulum = get_package("pendulum", "2.0.3")
demo = get_package("demo", "0.0.8")
......@@ -2572,7 +2745,7 @@ def test_solver_cannot_choose_another_version_for_file_dependencies(
def test_solver_cannot_choose_another_version_for_git_dependencies(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
pendulum = get_package("pendulum", "2.0.3")
demo = get_package("demo", "0.0.8")
......@@ -2594,7 +2767,10 @@ def test_solver_cannot_choose_another_version_for_git_dependencies(
def test_solver_cannot_choose_another_version_for_url_dependencies(
solver, repo, package, http
solver: Solver,
repo: Repository,
package: Package,
http: Type["httpretty.httpretty"],
):
path = (
Path(__file__).parent.parent
......@@ -2632,7 +2808,7 @@ def test_solver_cannot_choose_another_version_for_url_dependencies(
def test_solver_should_not_update_same_version_packages_if_installed_has_no_source_type(
solver, repo, package, installed
solver: Solver, repo: Repository, package: Package, installed: InstalledRepository
):
package.add_dependency(Factory.create_dependency("foo", "1.0.0"))
......@@ -2654,7 +2830,7 @@ def test_solver_should_not_update_same_version_packages_if_installed_has_no_sour
def test_solver_should_use_the_python_constraint_from_the_environment_if_available(
solver, repo, package, installed
solver: Solver, repo: Repository, package: Package, installed: InstalledRepository
):
solver.provider.set_package_python_versions("~2.7 || ^3.5")
package.add_dependency(Factory.create_dependency("A", "^1.0"))
......@@ -2681,7 +2857,7 @@ def test_solver_should_use_the_python_constraint_from_the_environment_if_availab
def test_solver_should_resolve_all_versions_for_multiple_duplicate_dependencies(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
package.python_versions = "~2.7 || ^3.5"
package.add_dependency(
......@@ -2729,7 +2905,7 @@ def test_solver_should_resolve_all_versions_for_multiple_duplicate_dependencies(
def test_solver_should_not_raise_errors_for_irrelevant_python_constraints(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
package.python_versions = "^3.6"
solver.provider.set_package_python_versions("^3.6")
......@@ -2746,7 +2922,9 @@ def test_solver_should_not_raise_errors_for_irrelevant_python_constraints(
check_solver_result(transaction, [{"job": "install", "package": dataclasses}])
def test_solver_can_resolve_transitive_extras(solver, repo, package):
def test_solver_can_resolve_transitive_extras(
solver: Solver, repo: Repository, package: ProjectPackage
):
package.add_dependency(Factory.create_dependency("requests", "^2.24.0"))
package.add_dependency(Factory.create_dependency("PyOTA", "^2.1.0"))
......@@ -2782,7 +2960,9 @@ def test_solver_can_resolve_transitive_extras(solver, repo, package):
)
def test_solver_can_resolve_for_packages_with_missing_extras(solver, repo, package):
def test_solver_can_resolve_for_packages_with_missing_extras(
solver: Solver, repo: Repository, package: ProjectPackage
):
package.add_dependency(
Factory.create_dependency(
"django-anymail", {"version": "^6.0", "extras": ["postmark"]}
......@@ -2818,7 +2998,7 @@ def test_solver_can_resolve_for_packages_with_missing_extras(solver, repo, packa
def test_solver_can_resolve_python_restricted_package_dependencies(
solver, repo, package, locked
solver: Solver, repo: Repository, package: Package, locked: Repository
):
package.add_dependency(
Factory.create_dependency("futures", {"version": "^3.3.0", "python": "~2.7"})
......@@ -2851,7 +3031,7 @@ def test_solver_can_resolve_python_restricted_package_dependencies(
def test_solver_should_not_raise_errors_for_irrelevant_transitive_python_constraints(
solver, repo, package
solver: Solver, repo: Repository, package: Package
):
package.python_versions = "~2.7 || ^3.5"
solver.provider.set_package_python_versions("~2.7 || ^3.5")
......
from typing import TYPE_CHECKING
from typing import Any
from typing import Dict
from typing import List
from poetry.core.packages.package import Package
from poetry.puzzle.transaction import Transaction
def check_operations(ops, expected):
if TYPE_CHECKING:
from poetry.installation.operations import OperationTypes
def check_operations(
ops: List["OperationTypes"], expected: List[Dict[str, Any]]
) -> None:
for e in expected:
if "skipped" not in e:
e["skipped"] = False
......
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Dict
from typing import List
from typing import Optional
import pytest
......@@ -45,14 +47,14 @@ INSTALLED_RESULTS = [
class MockEnv(BaseMockEnv):
@property
def paths(self):
def paths(self) -> Dict[str, Path]:
return {
"purelib": SITE_PURELIB,
"platlib": SITE_PLATLIB,
}
@property
def sys_path(self):
def sys_path(self) -> List[Path]:
return [ENV_DIR, SITE_PLATLIB, SITE_PURELIB]
......@@ -91,16 +93,16 @@ def get_package_from_repository(
return None
def test_load_successful(repository):
def test_load_successful(repository: InstalledRepository):
assert len(repository.packages) == len(INSTALLED_RESULTS) - 1
def test_load_ensure_isolation(repository):
def test_load_ensure_isolation(repository: InstalledRepository):
package = get_package_from_repository("attrs", repository)
assert package is None
def test_load_standard_package(repository):
def test_load_standard_package(repository: InstalledRepository):
cleo = get_package_from_repository("cleo", repository)
assert cleo is not None
assert cleo.name == "cleo"
......@@ -115,7 +117,7 @@ def test_load_standard_package(repository):
assert foo.version.text == "0.1.0"
def test_load_git_package(repository):
def test_load_git_package(repository: InstalledRepository):
pendulum = get_package_from_repository("pendulum", repository)
assert pendulum is not None
assert pendulum.name == "pendulum"
......@@ -129,7 +131,7 @@ def test_load_git_package(repository):
assert pendulum.source_reference == "bb058f6b78b2d28ef5d9a5e759cfa179a1a713d6"
def test_load_git_package_pth(repository):
def test_load_git_package_pth(repository: InstalledRepository):
bender = get_package_from_repository("bender", repository)
assert bender is not None
assert bender.name == "bender"
......@@ -137,14 +139,14 @@ def test_load_git_package_pth(repository):
assert bender.source_type == "git"
def test_load_platlib_package(repository):
def test_load_platlib_package(repository: InstalledRepository):
lib64 = get_package_from_repository("lib64", repository)
assert lib64 is not None
assert lib64.name == "lib64"
assert lib64.version.text == "2.3.4"
def test_load_editable_package(repository):
def test_load_editable_package(repository: InstalledRepository):
# test editable package with text .pth file
editable = get_package_from_repository("editable", repository)
assert editable is not None
......@@ -157,7 +159,7 @@ def test_load_editable_package(repository):
)
def test_load_editable_with_import_package(repository):
def test_load_editable_with_import_package(repository: InstalledRepository):
# test editable package with executable .pth file
editable = get_package_from_repository("editable-with-import", repository)
assert editable is not None
......@@ -167,7 +169,7 @@ def test_load_editable_with_import_package(repository):
assert editable.source_url is None
def test_load_standard_package_with_pth_file(repository):
def test_load_standard_package_with_pth_file(repository: InstalledRepository):
# test standard packages with .pth file is not treated as editable
standard = get_package_from_repository("standard", repository)
assert standard is not None
......@@ -177,7 +179,7 @@ def test_load_standard_package_with_pth_file(repository):
assert standard.source_url is None
def test_load_pep_610_compliant_git_packages(repository):
def test_load_pep_610_compliant_git_packages(repository: InstalledRepository):
package = get_package_from_repository("git-pep-610", repository)
assert package is not None
......@@ -189,7 +191,7 @@ def test_load_pep_610_compliant_git_packages(repository):
assert package.source_resolved_reference == "123456"
def test_load_pep_610_compliant_url_packages(repository):
def test_load_pep_610_compliant_url_packages(repository: InstalledRepository):
package = get_package_from_repository("url-pep-610", repository)
assert package is not None
......@@ -202,7 +204,7 @@ def test_load_pep_610_compliant_url_packages(repository):
)
def test_load_pep_610_compliant_file_packages(repository):
def test_load_pep_610_compliant_file_packages(repository: InstalledRepository):
package = get_package_from_repository("file-pep-610", repository)
assert package is not None
......@@ -212,7 +214,7 @@ def test_load_pep_610_compliant_file_packages(repository):
assert package.source_url == "/path/to/distributions/file-pep-610-1.2.3.tar.gz"
def test_load_pep_610_compliant_directory_packages(repository):
def test_load_pep_610_compliant_directory_packages(repository: InstalledRepository):
package = get_package_from_repository("directory-pep-610", repository)
assert package is not None
......@@ -223,7 +225,9 @@ def test_load_pep_610_compliant_directory_packages(repository):
assert not package.develop
def test_load_pep_610_compliant_editable_directory_packages(repository):
def test_load_pep_610_compliant_editable_directory_packages(
repository: InstalledRepository,
):
package = get_package_from_repository("editable-directory-pep-610", repository)
assert package is not None
......
import shutil
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Dict
from typing import Optional
from typing import Type
import pytest
import requests
......@@ -18,15 +22,20 @@ try:
except ImportError:
import urlparse
if TYPE_CHECKING:
import httpretty
from _pytest.monkeypatch import MonkeyPatch
class MockRepository(LegacyRepository):
FIXTURES = Path(__file__).parent / "fixtures" / "legacy"
def __init__(self):
def __init__(self) -> None:
super().__init__("legacy", url="http://legacy.foo.bar", disable_cache=True)
def _get_page(self, endpoint):
def _get_page(self, endpoint: str) -> Optional[Page]:
parts = endpoint.split("/")
name = parts[1]
......@@ -37,7 +46,7 @@ class MockRepository(LegacyRepository):
with fixture.open(encoding="utf-8") as f:
return Page(self._url + endpoint, f.read(), {})
def _download(self, url, dest):
def _download(self, url: str, dest: Path) -> None:
filename = urlparse.urlparse(url).path.rsplit("/")[-1]
filepath = self.FIXTURES.parent / "pypi.org" / "dists" / filename
......@@ -143,8 +152,10 @@ def test_find_packages_no_prereleases():
assert packages[0].source_url == repo.url
@pytest.mark.parametrize("constraint,count", [("*", 1), (">=1", 0), (">=19.0.0a0", 1)])
def test_find_packages_only_prereleases(constraint, count):
@pytest.mark.parametrize(
["constraint", "count"], [("*", 1), (">=1", 0), (">=19.0.0a0", 1)]
)
def test_find_packages_only_prereleases(constraint: str, count: int):
repo = MockRepository()
packages = repo.find_packages(Factory.create_dependency("black", constraint))
......@@ -319,7 +330,7 @@ def test_get_package_retrieves_packages_with_no_hashes():
class MockHttpRepository(LegacyRepository):
def __init__(self, endpoint_responses, http):
def __init__(self, endpoint_responses: Dict, http: Type["httpretty.httpretty"]):
base_url = "http://legacy.foo.bar"
super().__init__("legacy", url=base_url, disable_cache=True)
......@@ -328,31 +339,33 @@ class MockHttpRepository(LegacyRepository):
http.register_uri(http.GET, url, status=response)
def test_get_200_returns_page(http):
def test_get_200_returns_page(http: Type["httpretty.httpretty"]):
repo = MockHttpRepository({"/foo": 200}, http)
assert repo._get_page("/foo")
@pytest.mark.parametrize("status_code", [401, 403, 404])
def test_get_40x_and_returns_none(http, status_code):
def test_get_40x_and_returns_none(http: Type["httpretty.httpretty"], status_code: int):
repo = MockHttpRepository({"/foo": status_code}, http)
assert repo._get_page("/foo") is None
def test_get_5xx_raises(http):
def test_get_5xx_raises(http: Type["httpretty.httpretty"]):
repo = MockHttpRepository({"/foo": 500}, http)
with pytest.raises(RepositoryError):
repo._get_page("/foo")
def test_get_redirected_response_url(http, monkeypatch):
def test_get_redirected_response_url(
http: Type["httpretty.httpretty"], monkeypatch: "MonkeyPatch"
):
repo = MockHttpRepository({"/foo": 200}, http)
redirect_url = "http://legacy.redirect.bar"
def get_mock(url):
def get_mock(url: str) -> requests.Response:
response = requests.Response()
response.status_code = 200
response.url = redirect_url + "/foo"
......
......@@ -3,6 +3,9 @@ import shutil
from io import BytesIO
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Dict
from typing import Optional
import pytest
......@@ -15,15 +18,19 @@ from poetry.repositories.pypi_repository import PyPiRepository
from poetry.utils._compat import encode
if TYPE_CHECKING:
from pytest_mock import MockerFixture
class MockRepository(PyPiRepository):
JSON_FIXTURES = Path(__file__).parent / "fixtures" / "pypi.org" / "json"
DIST_FIXTURES = Path(__file__).parent / "fixtures" / "pypi.org" / "dists"
def __init__(self, fallback=False):
def __init__(self, fallback: bool = False):
super().__init__(url="http://foo.bar", disable_cache=True, fallback=fallback)
def _get(self, url):
def _get(self, url: str) -> Optional[Dict]:
parts = url.split("/")[1:]
name = parts[0]
if len(parts) == 3:
......@@ -44,7 +51,7 @@ class MockRepository(PyPiRepository):
with fixture.open(encoding="utf-8") as f:
return json.loads(f.read())
def _download(self, url, dest):
def _download(self, url: str, dest: Path) -> None:
filename = url.split("/")[-1]
fixture = self.DIST_FIXTURES / filename
......@@ -73,8 +80,10 @@ def test_find_packages_does_not_select_prereleases_if_not_allowed():
assert len(packages) == 1
@pytest.mark.parametrize("constraint,count", [("*", 1), (">=1", 0), (">=19.0.0a0", 1)])
def test_find_packages_only_prereleases(constraint, count):
@pytest.mark.parametrize(
["constraint", "count"], [("*", 1), (">=1", 0), (">=19.0.0a0", 1)]
)
def test_find_packages_only_prereleases(constraint: str, count: int):
repo = MockRepository()
packages = repo.find_packages(Factory.create_dependency("black", constraint))
......@@ -204,7 +213,7 @@ def test_invalid_versions_ignored():
assert len(packages) == 1
def test_get_should_invalid_cache_on_too_many_redirects_error(mocker):
def test_get_should_invalid_cache_on_too_many_redirects_error(mocker: "MockerFixture"):
delete_cache = mocker.patch("cachecontrol.caches.file_cache.FileCache.delete")
response = Response()
......
from pathlib import Path
from typing import TYPE_CHECKING
import pytest
......@@ -12,11 +13,18 @@ from poetry.repositories.legacy_repository import LegacyRepository
from poetry.repositories.pypi_repository import PyPiRepository
if TYPE_CHECKING:
from cleo.io.io import IO
from pytest_mock import MockerFixture
from poetry.poetry import Poetry
from tests.types import FixtureDirGetter
fixtures_dir = Path(__file__).parent / "fixtures"
class MyPlugin(Plugin):
def activate(self, poetry, io):
def activate(self, poetry: "Poetry", io: "IO") -> None:
io.write_line("Updating version")
poetry.package.set_version("9.9.9")
......@@ -153,13 +161,13 @@ def test_create_poetry_with_multi_constraints_dependency():
assert len(package.requires) == 2
def test_poetry_with_default_source(with_simple_keyring):
def test_poetry_with_default_source(with_simple_keyring: None):
poetry = Factory().create_poetry(fixtures_dir / "with_default_source")
assert len(poetry.pool.repositories) == 1
def test_poetry_with_non_default_source(with_simple_keyring):
def test_poetry_with_non_default_source(with_simple_keyring: None):
poetry = Factory().create_poetry(fixtures_dir / "with_non_default_source")
assert len(poetry.pool.repositories) == 2
......@@ -173,7 +181,7 @@ def test_poetry_with_non_default_source(with_simple_keyring):
assert isinstance(poetry.pool.repositories[1], PyPiRepository)
def test_poetry_with_non_default_secondary_source(with_simple_keyring):
def test_poetry_with_non_default_secondary_source(with_simple_keyring: None):
poetry = Factory().create_poetry(fixtures_dir / "with_non_default_secondary_source")
assert len(poetry.pool.repositories) == 2
......@@ -189,7 +197,7 @@ def test_poetry_with_non_default_secondary_source(with_simple_keyring):
assert isinstance(repository, LegacyRepository)
def test_poetry_with_non_default_multiple_secondary_sources(with_simple_keyring):
def test_poetry_with_non_default_multiple_secondary_sources(with_simple_keyring: None):
poetry = Factory().create_poetry(
fixtures_dir / "with_non_default_multiple_secondary_sources"
)
......@@ -211,7 +219,7 @@ def test_poetry_with_non_default_multiple_secondary_sources(with_simple_keyring)
assert isinstance(repository, LegacyRepository)
def test_poetry_with_non_default_multiple_sources(with_simple_keyring):
def test_poetry_with_non_default_multiple_sources(with_simple_keyring: None):
poetry = Factory().create_poetry(fixtures_dir / "with_non_default_multiple_sources")
assert len(poetry.pool.repositories) == 3
......@@ -242,7 +250,7 @@ def test_poetry_with_no_default_source():
assert isinstance(poetry.pool.repositories[0], PyPiRepository)
def test_poetry_with_two_default_sources(with_simple_keyring):
def test_poetry_with_two_default_sources(with_simple_keyring: None):
with pytest.raises(ValueError) as e:
Factory().create_poetry(fixtures_dir / "with_two_default_sources")
......@@ -282,7 +290,7 @@ The Poetry configuration is invalid:
assert expected == str(e.value)
def test_create_poetry_with_local_config(fixture_dir):
def test_create_poetry_with_local_config(fixture_dir: "FixtureDirGetter"):
poetry = Factory().create_poetry(fixture_dir("with_local_config"))
assert not poetry.config.get("virtualenvs.in-project")
......@@ -291,7 +299,7 @@ def test_create_poetry_with_local_config(fixture_dir):
assert not poetry.config.get("virtualenvs.options.system-site-packages")
def test_create_poetry_with_plugins(mocker):
def test_create_poetry_with_plugins(mocker: "MockerFixture"):
mocker.patch(
"entrypoints.get_group_all",
return_value=[EntryPoint("my-plugin", "tests.test_factory", "MyPlugin")],
......
......@@ -6,6 +6,8 @@ from tests.compat import Protocol
if TYPE_CHECKING:
from pathlib import Path
from cleo.io.io import IO
from cleo.testers.command_tester import CommandTester
......@@ -47,3 +49,8 @@ class ProjectFactory(Protocol):
install_deps: bool = True,
) -> "Poetry":
...
class FixtureDirGetter(Protocol):
def __call__(self, name: str) -> "Path":
...
import re
import uuid
from typing import TYPE_CHECKING
from typing import Any
from typing import Dict
from typing import List
from typing import Type
from typing import Union
import httpretty
import pytest
import requests
......@@ -11,6 +18,14 @@ from dataclasses import dataclass
from poetry.utils.authenticator import Authenticator
if TYPE_CHECKING:
from _pytest.monkeypatch import MonkeyPatch
from pytest_mock import MockerFixture
from tests.conftest import Config
from tests.conftest import DummyBackend
@dataclass
class SimpleCredential:
username: str
......@@ -18,14 +33,16 @@ class SimpleCredential:
@pytest.fixture()
def mock_remote(http):
def mock_remote(http: Type[httpretty.httpretty]) -> None:
http.register_uri(
http.GET,
re.compile("^https?://foo.bar/(.+?)$"),
)
def test_authenticator_uses_url_provided_credentials(config, mock_remote, http):
def test_authenticator_uses_url_provided_credentials(
config: "Config", mock_remote: None, http: Type[httpretty.httpretty]
):
config.merge(
{
"repositories": {"foo": {"url": "https://foo.bar/simple/"}},
......@@ -42,7 +59,7 @@ def test_authenticator_uses_url_provided_credentials(config, mock_remote, http):
def test_authenticator_uses_credentials_from_config_if_not_provided(
config, mock_remote, http
config: "Config", mock_remote: None, http: Type[httpretty.httpretty]
):
config.merge(
{
......@@ -60,7 +77,10 @@ def test_authenticator_uses_credentials_from_config_if_not_provided(
def test_authenticator_uses_username_only_credentials(
config, mock_remote, http, with_simple_keyring
config: "Config",
mock_remote: None,
http: Type[httpretty.httpretty],
with_simple_keyring: None,
):
config.merge(
{
......@@ -77,7 +97,9 @@ def test_authenticator_uses_username_only_credentials(
assert request.headers["Authorization"] == "Basic Zm9vMDAxOg=="
def test_authenticator_uses_password_only_credentials(config, mock_remote, http):
def test_authenticator_uses_password_only_credentials(
config: "Config", mock_remote: None, http: Type[httpretty.httpretty]
):
config.merge(
{
"repositories": {"foo": {"url": "https://foo.bar/simple/"}},
......@@ -94,7 +116,10 @@ def test_authenticator_uses_password_only_credentials(config, mock_remote, http)
def test_authenticator_uses_empty_strings_as_default_password(
config, mock_remote, http, with_simple_keyring
config: "Config",
mock_remote: None,
http: Type[httpretty.httpretty],
with_simple_keyring: None,
):
config.merge(
{
......@@ -112,7 +137,7 @@ def test_authenticator_uses_empty_strings_as_default_password(
def test_authenticator_uses_empty_strings_as_default_username(
config, mock_remote, http
config: "Config", mock_remote: None, http: Type[httpretty.httpretty]
):
config.merge(
{
......@@ -130,7 +155,11 @@ def test_authenticator_uses_empty_strings_as_default_username(
def test_authenticator_falls_back_to_keyring_url(
config, mock_remote, http, with_simple_keyring, dummy_keyring
config: "Config",
mock_remote: None,
http: Type[httpretty.httpretty],
with_simple_keyring: None,
dummy_keyring: "DummyBackend",
):
config.merge(
{
......@@ -151,7 +180,11 @@ def test_authenticator_falls_back_to_keyring_url(
def test_authenticator_falls_back_to_keyring_netloc(
config, mock_remote, http, with_simple_keyring, dummy_keyring
config: "Config",
mock_remote: None,
http: Type[httpretty.httpretty],
with_simple_keyring: None,
dummy_keyring: "DummyBackend",
):
config.merge(
{
......@@ -170,13 +203,17 @@ def test_authenticator_falls_back_to_keyring_netloc(
@pytest.mark.filterwarnings("ignore::pytest.PytestUnhandledThreadExceptionWarning")
def test_authenticator_request_retries_on_exception(mocker, config, http):
def test_authenticator_request_retries_on_exception(
mocker: "MockerFixture", config: "Config", http: Type[httpretty.httpretty]
):
sleep = mocker.patch("time.sleep")
sdist_uri = f"https://foo.bar/files/{str(uuid.uuid4())}/foo-0.1.0.tar.gz"
content = str(uuid.uuid4())
seen = []
def callback(request, uri, response_headers):
def callback(
request: requests.Request, uri: str, response_headers: Dict
) -> List[Union[int, Dict, str]]:
if seen.count(uri) < 2:
seen.append(uri)
raise requests.exceptions.ConnectionError("Disconnected")
......@@ -192,12 +229,12 @@ def test_authenticator_request_retries_on_exception(mocker, config, http):
@pytest.mark.filterwarnings("ignore::pytest.PytestUnhandledThreadExceptionWarning")
def test_authenticator_request_raises_exception_when_attempts_exhausted(
mocker, config, http
mocker: "MockerFixture", config: "Config", http: Type[httpretty.httpretty]
):
sleep = mocker.patch("time.sleep")
sdist_uri = f"https://foo.bar/files/{str(uuid.uuid4())}/foo-0.1.0.tar.gz"
def callback(*_, **__):
def callback(*_: Any, **___: Any) -> None:
raise requests.exceptions.ConnectionError(str(uuid.uuid4()))
httpretty.register_uri(httpretty.GET, sdist_uri, body=callback)
......@@ -210,17 +247,32 @@ def test_authenticator_request_raises_exception_when_attempts_exhausted(
@pytest.mark.parametrize(
"status, attempts",
[(400, 0), (401, 0), (403, 0), (404, 0), (500, 0), (502, 5), (503, 5), (504, 5)],
["status", "attempts"],
[
(400, 0),
(401, 0),
(403, 0),
(404, 0),
(500, 0),
(502, 5),
(503, 5),
(504, 5),
],
)
def test_authenticator_request_retries_on_status_code(
mocker, config, http, status, attempts
mocker: "MockerFixture",
config: "Config",
http: Type[httpretty.httpretty],
status: int,
attempts: int,
):
sleep = mocker.patch("time.sleep")
sdist_uri = f"https://foo.bar/files/{str(uuid.uuid4())}/foo-0.1.0.tar.gz"
content = str(uuid.uuid4())
def callback(request, uri, response_headers):
def callback(
request: requests.Request, uri: str, response_headers: Dict
) -> List[Union[int, Dict, str]]:
return [status, response_headers, content]
httpretty.register_uri(httpretty.GET, sdist_uri, body=callback)
......@@ -236,13 +288,17 @@ def test_authenticator_request_retries_on_status_code(
@pytest.fixture
def environment_repository_credentials(monkeypatch):
def environment_repository_credentials(monkeypatch: "MonkeyPatch") -> None:
monkeypatch.setenv("POETRY_HTTP_BASIC_FOO_USERNAME", "bar")
monkeypatch.setenv("POETRY_HTTP_BASIC_FOO_PASSWORD", "baz")
def test_authenticator_uses_env_provided_credentials(
config, environ, mock_remote, http, environment_repository_credentials
config: "Config",
environ: None,
mock_remote: Type[httpretty.httpretty],
http: Type[httpretty.httpretty],
environment_repository_credentials: None,
):
config.merge({"repositories": {"foo": {"url": "https://foo.bar/simple/"}}})
......
......@@ -4,7 +4,12 @@ import subprocess
import sys
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Any
from typing import Callable
from typing import Iterator
from typing import List
from typing import Optional
from typing import Union
import pytest
......@@ -25,6 +30,12 @@ from poetry.utils.env import SystemEnv
from poetry.utils.env import VirtualEnv
if TYPE_CHECKING:
from pytest_mock import MockerFixture
from poetry.poetry import Poetry
from tests.conftest import Config
MINIMAL_SCRIPT = """\
print("Minimal Output"),
......@@ -39,13 +50,18 @@ print("nullpackage loaded"),
class MockVirtualEnv(VirtualEnv):
def __init__(self, path, base=None, sys_path=None):
def __init__(
self,
path: Path,
base: Optional[Path] = None,
sys_path: Optional[List[str]] = None,
):
super().__init__(path, base=base)
self._sys_path = sys_path
@property
def sys_path(self):
def sys_path(self) -> Optional[List[str]]:
if self._sys_path is not None:
return self._sys_path
......@@ -53,7 +69,7 @@ class MockVirtualEnv(VirtualEnv):
@pytest.fixture()
def poetry(config):
def poetry(config: "Config") -> "Poetry":
poetry = Factory().create_poetry(
Path(__file__).parent.parent / "fixtures" / "simple_project"
)
......@@ -63,11 +79,13 @@ def poetry(config):
@pytest.fixture()
def manager(poetry):
def manager(poetry: "Poetry") -> EnvManager:
return EnvManager(poetry)
def test_virtualenvs_with_spaces_in_their_path_work_as_expected(tmp_dir, manager):
def test_virtualenvs_with_spaces_in_their_path_work_as_expected(
tmp_dir: str, manager: EnvManager
):
venv_path = Path(tmp_dir) / "Virtual Env"
manager.build_venv(str(venv_path))
......@@ -77,7 +95,9 @@ def test_virtualenvs_with_spaces_in_their_path_work_as_expected(tmp_dir, manager
assert venv.run("python", "-V", shell=True).startswith("Python")
def test_env_commands_with_spaces_in_their_arg_work_as_expected(tmp_dir, manager):
def test_env_commands_with_spaces_in_their_arg_work_as_expected(
tmp_dir: str, manager: EnvManager
):
venv_path = Path(tmp_dir) / "Virtual Env"
manager.build_venv(str(venv_path))
venv = VirtualEnv(venv_path)
......@@ -87,7 +107,7 @@ def test_env_commands_with_spaces_in_their_arg_work_as_expected(tmp_dir, manager
def test_env_shell_commands_with_stdinput_in_their_arg_work_as_expected(
tmp_dir, manager
tmp_dir: str, manager: EnvManager
):
venv_path = Path(tmp_dir) / "Virtual Env"
manager.build_venv(str(venv_path))
......@@ -100,7 +120,7 @@ def test_env_shell_commands_with_stdinput_in_their_arg_work_as_expected(
@pytest.fixture
def in_project_venv_dir(poetry):
def in_project_venv_dir(poetry: "Poetry") -> Iterator[Path]:
os.environ.pop("VIRTUAL_ENV", None)
venv_dir = poetry.file.parent.joinpath(".venv")
venv_dir.mkdir()
......@@ -112,7 +132,10 @@ def in_project_venv_dir(poetry):
@pytest.mark.parametrize("in_project", [True, False, None])
def test_env_get_venv_with_venv_folder_present(
manager, poetry, in_project_venv_dir, in_project
manager: EnvManager,
poetry: "Poetry",
in_project_venv_dir: Path,
in_project: Optional[bool],
):
poetry.config.config["virtualenvs"]["in-project"] = in_project
venv = manager.get()
......@@ -129,8 +152,10 @@ def build_venv(path: Union[Path, str], **__: Any) -> None:
VERSION_3_7_1 = Version.parse("3.7.1")
def check_output_wrapper(version=VERSION_3_7_1):
def check_output(cmd, *args, **kwargs):
def check_output_wrapper(
version: Version = VERSION_3_7_1,
) -> Callable[[List[str], Any, Any], str]:
def check_output(cmd: List[str], *args: Any, **kwargs: Any) -> str:
if "sys.version_info[:3]" in cmd:
return version.text
elif "sys.version_info[:2]" in cmd:
......@@ -142,7 +167,11 @@ def check_output_wrapper(version=VERSION_3_7_1):
def test_activate_activates_non_existing_virtualenv_no_envs_file(
tmp_dir, manager, poetry, config, mocker
tmp_dir: str,
manager: EnvManager,
poetry: "Poetry",
config: "Config",
mocker: "MockerFixture",
):
if "VIRTUAL_ENV" in os.environ:
del os.environ["VIRTUAL_ENV"]
......@@ -182,7 +211,11 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file(
def test_activate_activates_existing_virtualenv_no_envs_file(
tmp_dir, manager, poetry, config, mocker
tmp_dir: str,
manager: EnvManager,
poetry: "Poetry",
config: "Config",
mocker: "MockerFixture",
):
if "VIRTUAL_ENV" in os.environ:
del os.environ["VIRTUAL_ENV"]
......@@ -218,7 +251,11 @@ def test_activate_activates_existing_virtualenv_no_envs_file(
def test_activate_activates_same_virtualenv_with_envs_file(
tmp_dir, manager, poetry, config, mocker
tmp_dir: str,
manager: EnvManager,
poetry: "Poetry",
config: "Config",
mocker: "MockerFixture",
):
if "VIRTUAL_ENV" in os.environ:
del os.environ["VIRTUAL_ENV"]
......@@ -258,7 +295,11 @@ def test_activate_activates_same_virtualenv_with_envs_file(
def test_activate_activates_different_virtualenv_with_envs_file(
tmp_dir, manager, poetry, config, mocker
tmp_dir: str,
manager: EnvManager,
poetry: "Poetry",
config: "Config",
mocker: "MockerFixture",
):
if "VIRTUAL_ENV" in os.environ:
del os.environ["VIRTUAL_ENV"]
......@@ -304,7 +345,11 @@ def test_activate_activates_different_virtualenv_with_envs_file(
def test_activate_activates_recreates_for_different_patch(
tmp_dir, manager, poetry, config, mocker
tmp_dir: str,
manager: EnvManager,
poetry: "Poetry",
config: "Config",
mocker: "MockerFixture",
):
if "VIRTUAL_ENV" in os.environ:
del os.environ["VIRTUAL_ENV"]
......@@ -363,7 +408,11 @@ def test_activate_activates_recreates_for_different_patch(
def test_activate_does_not_recreate_when_switching_minor(
tmp_dir, manager, poetry, config, mocker
tmp_dir: str,
manager: EnvManager,
poetry: "Poetry",
config: "Config",
mocker: "MockerFixture",
):
if "VIRTUAL_ENV" in os.environ:
del os.environ["VIRTUAL_ENV"]
......@@ -410,7 +459,11 @@ def test_activate_does_not_recreate_when_switching_minor(
def test_deactivate_non_activated_but_existing(
tmp_dir, manager, poetry, config, mocker
tmp_dir: str,
manager: EnvManager,
poetry: "Poetry",
config: "Config",
mocker: "MockerFixture",
):
if "VIRTUAL_ENV" in os.environ:
del os.environ["VIRTUAL_ENV"]
......@@ -438,7 +491,13 @@ def test_deactivate_non_activated_but_existing(
assert Path("/prefix")
def test_deactivate_activated(tmp_dir, manager, poetry, config, mocker):
def test_deactivate_activated(
tmp_dir: str,
manager: EnvManager,
poetry: "Poetry",
config: "Config",
mocker: "MockerFixture",
):
if "VIRTUAL_ENV" in os.environ:
del os.environ["VIRTUAL_ENV"]
......@@ -478,7 +537,11 @@ def test_deactivate_activated(tmp_dir, manager, poetry, config, mocker):
def test_get_prefers_explicitly_activated_virtualenvs_over_env_var(
tmp_dir, manager, poetry, config, mocker
tmp_dir: str,
manager: EnvManager,
poetry: "Poetry",
config: "Config",
mocker: "MockerFixture",
):
os.environ["VIRTUAL_ENV"] = "/environment/prefix"
......@@ -507,7 +570,7 @@ def test_get_prefers_explicitly_activated_virtualenvs_over_env_var(
assert env.base == Path("/prefix")
def test_list(tmp_dir, manager, poetry, config):
def test_list(tmp_dir: str, manager: EnvManager, poetry: "Poetry", config: "Config"):
config.merge({"virtualenvs": {"path": str(tmp_dir)}})
venv_name = manager.generate_env_name("simple-project", str(poetry.file.parent))
......@@ -521,7 +584,13 @@ def test_list(tmp_dir, manager, poetry, config):
assert (Path(tmp_dir) / f"{venv_name}-py3.7") == venvs[1].path
def test_remove_by_python_version(tmp_dir, manager, poetry, config, mocker):
def test_remove_by_python_version(
tmp_dir: str,
manager: EnvManager,
poetry: "Poetry",
config: "Config",
mocker: "MockerFixture",
):
config.merge({"virtualenvs": {"path": str(tmp_dir)}})
venv_name = manager.generate_env_name("simple-project", str(poetry.file.parent))
......@@ -539,7 +608,13 @@ def test_remove_by_python_version(tmp_dir, manager, poetry, config, mocker):
assert not (Path(tmp_dir) / f"{venv_name}-py3.6").exists()
def test_remove_by_name(tmp_dir, manager, poetry, config, mocker):
def test_remove_by_name(
tmp_dir: str,
manager: EnvManager,
poetry: "Poetry",
config: "Config",
mocker: "MockerFixture",
):
config.merge({"virtualenvs": {"path": str(tmp_dir)}})
venv_name = manager.generate_env_name("simple-project", str(poetry.file.parent))
......@@ -557,7 +632,13 @@ def test_remove_by_name(tmp_dir, manager, poetry, config, mocker):
assert not (Path(tmp_dir) / f"{venv_name}-py3.6").exists()
def test_remove_also_deactivates(tmp_dir, manager, poetry, config, mocker):
def test_remove_also_deactivates(
tmp_dir: str,
manager: EnvManager,
poetry: "Poetry",
config: "Config",
mocker: "MockerFixture",
):
config.merge({"virtualenvs": {"path": str(tmp_dir)}})
venv_name = manager.generate_env_name("simple-project", str(poetry.file.parent))
......@@ -583,7 +664,13 @@ def test_remove_also_deactivates(tmp_dir, manager, poetry, config, mocker):
assert venv_name not in envs
def test_remove_keeps_dir_if_not_deleteable(tmp_dir, manager, poetry, config, mocker):
def test_remove_keeps_dir_if_not_deleteable(
tmp_dir: str,
manager: EnvManager,
poetry: "Poetry",
config: "Config",
mocker: "MockerFixture",
):
# Ensure we empty rather than delete folder if its is an active mount point.
# See https://github.com/python-poetry/poetry/pull/2064
config.merge({"virtualenvs": {"path": str(tmp_dir)}})
......@@ -608,7 +695,7 @@ def test_remove_keeps_dir_if_not_deleteable(tmp_dir, manager, poetry, config, mo
original_rmtree = shutil.rmtree
def err_on_rm_venv_only(path, *args, **kwargs):
def err_on_rm_venv_only(path: str, *args: Any, **kwargs: Any) -> None:
if path == str(venv_path):
raise OSError(16, "Test error") # ERRNO 16: Device or resource busy
else:
......@@ -631,17 +718,17 @@ def test_remove_keeps_dir_if_not_deleteable(tmp_dir, manager, poetry, config, mo
@pytest.mark.skipif(os.name == "nt", reason="Symlinks are not support for Windows")
def test_env_has_symlinks_on_nix(tmp_dir, tmp_venv):
def test_env_has_symlinks_on_nix(tmp_dir: str, tmp_venv: VirtualEnv):
assert os.path.islink(tmp_venv.python)
def test_run_with_input(tmp_dir, tmp_venv):
def test_run_with_input(tmp_dir: str, tmp_venv: VirtualEnv):
result = tmp_venv.run("python", "-", input_=MINIMAL_SCRIPT)
assert result == "Minimal Output" + os.linesep
def test_run_with_input_non_zero_return(tmp_dir, tmp_venv):
def test_run_with_input_non_zero_return(tmp_dir: str, tmp_venv: VirtualEnv):
with pytest.raises(EnvCommandError) as process_error:
# Test command that will return non-zero returncode.
......@@ -650,14 +737,18 @@ def test_run_with_input_non_zero_return(tmp_dir, tmp_venv):
assert process_error.value.e.returncode == 1
def test_run_with_keyboard_interrupt(tmp_dir, tmp_venv, mocker):
def test_run_with_keyboard_interrupt(
tmp_dir: str, tmp_venv: VirtualEnv, mocker: "MockerFixture"
):
mocker.patch("subprocess.run", side_effect=KeyboardInterrupt())
with pytest.raises(KeyboardInterrupt):
tmp_venv.run("python", "-", input_=MINIMAL_SCRIPT)
subprocess.run.assert_called_once()
def test_call_with_input_and_keyboard_interrupt(tmp_dir, tmp_venv, mocker):
def test_call_with_input_and_keyboard_interrupt(
tmp_dir: str, tmp_venv: VirtualEnv, mocker: "MockerFixture"
):
mocker.patch("subprocess.run", side_effect=KeyboardInterrupt())
kwargs = {"call": True}
with pytest.raises(KeyboardInterrupt):
......@@ -665,7 +756,9 @@ def test_call_with_input_and_keyboard_interrupt(tmp_dir, tmp_venv, mocker):
subprocess.run.assert_called_once()
def test_call_no_input_with_keyboard_interrupt(tmp_dir, tmp_venv, mocker):
def test_call_no_input_with_keyboard_interrupt(
tmp_dir: str, tmp_venv: VirtualEnv, mocker: "MockerFixture"
):
mocker.patch("subprocess.call", side_effect=KeyboardInterrupt())
kwargs = {"call": True}
with pytest.raises(KeyboardInterrupt):
......@@ -673,7 +766,9 @@ def test_call_no_input_with_keyboard_interrupt(tmp_dir, tmp_venv, mocker):
subprocess.call.assert_called_once()
def test_run_with_called_process_error(tmp_dir, tmp_venv, mocker):
def test_run_with_called_process_error(
tmp_dir: str, tmp_venv: VirtualEnv, mocker: "MockerFixture"
):
mocker.patch(
"subprocess.run", side_effect=subprocess.CalledProcessError(42, "some_command")
)
......@@ -682,7 +777,9 @@ def test_run_with_called_process_error(tmp_dir, tmp_venv, mocker):
subprocess.run.assert_called_once()
def test_call_with_input_and_called_process_error(tmp_dir, tmp_venv, mocker):
def test_call_with_input_and_called_process_error(
tmp_dir: str, tmp_venv: VirtualEnv, mocker: "MockerFixture"
):
mocker.patch(
"subprocess.run", side_effect=subprocess.CalledProcessError(42, "some_command")
)
......@@ -692,7 +789,9 @@ def test_call_with_input_and_called_process_error(tmp_dir, tmp_venv, mocker):
subprocess.run.assert_called_once()
def test_call_no_input_with_called_process_error(tmp_dir, tmp_venv, mocker):
def test_call_no_input_with_called_process_error(
tmp_dir: str, tmp_venv: VirtualEnv, mocker: "MockerFixture"
):
mocker.patch(
"subprocess.call", side_effect=subprocess.CalledProcessError(42, "some_command")
)
......@@ -703,7 +802,11 @@ def test_call_no_input_with_called_process_error(tmp_dir, tmp_venv, mocker):
def test_create_venv_tries_to_find_a_compatible_python_executable_using_generic_ones_first(
manager, poetry, config, mocker, config_virtualenvs_path
manager: EnvManager,
poetry: "Poetry",
config: "Config",
mocker: "MockerFixture",
config_virtualenvs_path: Path,
):
if "VIRTUAL_ENV" in os.environ:
del os.environ["VIRTUAL_ENV"]
......@@ -733,7 +836,11 @@ def test_create_venv_tries_to_find_a_compatible_python_executable_using_generic_
def test_create_venv_tries_to_find_a_compatible_python_executable_using_specific_ones(
manager, poetry, config, mocker, config_virtualenvs_path
manager: EnvManager,
poetry: "Poetry",
config: "Config",
mocker: "MockerFixture",
config_virtualenvs_path: Path,
):
if "VIRTUAL_ENV" in os.environ:
del os.environ["VIRTUAL_ENV"]
......@@ -760,7 +867,7 @@ def test_create_venv_tries_to_find_a_compatible_python_executable_using_specific
def test_create_venv_fails_if_no_compatible_python_version_could_be_found(
manager, poetry, config, mocker
manager: EnvManager, poetry: "Poetry", config: "Config", mocker: "MockerFixture"
):
if "VIRTUAL_ENV" in os.environ:
del os.environ["VIRTUAL_ENV"]
......@@ -786,7 +893,7 @@ def test_create_venv_fails_if_no_compatible_python_version_could_be_found(
def test_create_venv_does_not_try_to_find_compatible_versions_with_executable(
manager, poetry, config, mocker
manager: EnvManager, poetry: "Poetry", config: "Config", mocker: "MockerFixture"
):
if "VIRTUAL_ENV" in os.environ:
del os.environ["VIRTUAL_ENV"]
......@@ -812,7 +919,11 @@ def test_create_venv_does_not_try_to_find_compatible_versions_with_executable(
def test_create_venv_uses_patch_version_to_detect_compatibility(
manager, poetry, config, mocker, config_virtualenvs_path
manager: EnvManager,
poetry: "Poetry",
config: "Config",
mocker: "MockerFixture",
config_virtualenvs_path: Path,
):
if "VIRTUAL_ENV" in os.environ:
del os.environ["VIRTUAL_ENV"]
......@@ -846,7 +957,11 @@ def test_create_venv_uses_patch_version_to_detect_compatibility(
def test_create_venv_uses_patch_version_to_detect_compatibility_with_executable(
manager, poetry, config, mocker, config_virtualenvs_path
manager: EnvManager,
poetry: "Poetry",
config: "Config",
mocker: "MockerFixture",
config_virtualenvs_path: Path,
):
if "VIRTUAL_ENV" in os.environ:
del os.environ["VIRTUAL_ENV"]
......@@ -883,7 +998,11 @@ def test_create_venv_uses_patch_version_to_detect_compatibility_with_executable(
def test_activate_with_in_project_setting_does_not_fail_if_no_venvs_dir(
manager, poetry, config, tmp_dir, mocker
manager: EnvManager,
poetry: "Poetry",
config: "Config",
tmp_dir: str,
mocker: "MockerFixture",
):
if "VIRTUAL_ENV" in os.environ:
del os.environ["VIRTUAL_ENV"]
......@@ -934,10 +1053,10 @@ def test_system_env_has_correct_paths():
@pytest.mark.parametrize(
("enabled",),
[(True,), (False,)],
"enabled",
[True, False],
)
def test_system_env_usersite(mocker, enabled):
def test_system_env_usersite(mocker: "MockerFixture", enabled: bool):
mocker.patch("site.check_enableusersite", return_value=enabled)
env = SystemEnv(Path(sys.prefix))
assert (enabled and env.usersite is not None) or (
......@@ -945,7 +1064,7 @@ def test_system_env_usersite(mocker, enabled):
)
def test_venv_has_correct_paths(tmp_venv):
def test_venv_has_correct_paths(tmp_venv: VirtualEnv):
paths = tmp_venv.paths
assert paths.get("purelib") is not None
......@@ -954,16 +1073,16 @@ def test_venv_has_correct_paths(tmp_venv):
assert tmp_venv.site_packages.path == Path(paths["purelib"])
def test_env_system_packages(tmp_path, config):
def test_env_system_packages(tmp_path: Path, poetry: "Poetry"):
venv_path = tmp_path / "venv"
pyvenv_cfg = venv_path / "pyvenv.cfg"
EnvManager(config).build_venv(path=venv_path, flags={"system-site-packages": True})
EnvManager(poetry).build_venv(path=venv_path, flags={"system-site-packages": True})
assert "include-system-site-packages = true" in pyvenv_cfg.read_text()
def test_env_finds_the_correct_executables(tmp_dir, manager):
def test_env_finds_the_correct_executables(tmp_dir: str, manager: EnvManager):
venv_path = Path(tmp_dir) / "Virtual Env"
manager.build_venv(str(venv_path), with_pip=True)
venv = VirtualEnv(venv_path)
......@@ -999,7 +1118,9 @@ def test_env_finds_the_correct_executables(tmp_dir, manager):
assert Path(venv.pip).name.startswith(expected_pip_executable.split(".")[0])
def test_env_finds_the_correct_executables_for_generic_env(tmp_dir, manager):
def test_env_finds_the_correct_executables_for_generic_env(
tmp_dir: str, manager: EnvManager
):
venv_path = Path(tmp_dir) / "Virtual Env"
child_venv_path = Path(tmp_dir) / "Child Virtual Env"
manager.build_venv(str(venv_path), with_pip=True)
......@@ -1024,7 +1145,9 @@ def test_env_finds_the_correct_executables_for_generic_env(tmp_dir, manager):
assert Path(venv.pip).name == expected_pip_executable
def test_env_finds_fallback_executables_for_generic_env(tmp_dir, manager):
def test_env_finds_fallback_executables_for_generic_env(
tmp_dir: str, manager: EnvManager
):
venv_path = Path(tmp_dir) / "Virtual Env"
child_venv_path = Path(tmp_dir) / "Child Virtual Env"
manager.build_venv(str(venv_path), with_pip=True)
......@@ -1091,7 +1214,11 @@ def test_env_finds_fallback_executables_for_generic_env(tmp_dir, manager):
def test_create_venv_accepts_fallback_version_w_nonzero_patchlevel(
manager, poetry, config, mocker, config_virtualenvs_path
manager: EnvManager,
poetry: "Poetry",
config: "Config",
mocker: "MockerFixture",
config_virtualenvs_path: Path,
):
if "VIRTUAL_ENV" in os.environ:
del os.environ["VIRTUAL_ENV"]
......@@ -1122,7 +1249,7 @@ def test_create_venv_accepts_fallback_version_w_nonzero_patchlevel(
)
def test_generate_env_name_ignores_case_for_case_insensitive_fs(tmp_dir):
def test_generate_env_name_ignores_case_for_case_insensitive_fs(tmp_dir: str):
venv_name1 = EnvManager.generate_env_name("simple-project", "MyDiR")
venv_name2 = EnvManager.generate_env_name("simple-project", "mYdIr")
if sys.platform == "win32":
......
import uuid
from pathlib import Path
from typing import TYPE_CHECKING
from poetry.utils._compat import decode
from poetry.utils.env import SitePackages
def test_env_site_simple(tmp_dir, mocker):
if TYPE_CHECKING:
from pytest_mock import MockerFixture
def test_env_site_simple(tmp_dir: str, mocker: "MockerFixture"):
# emulate permission error when creating directory
mocker.patch("pathlib.Path.mkdir", side_effect=OSError())
site_packages = SitePackages(Path("/non-existent"), fallbacks=[Path(tmp_dir)])
......@@ -24,7 +29,7 @@ def test_env_site_simple(tmp_dir, mocker):
assert not (site_packages.path / "hello.txt").exists()
def test_env_site_select_first(tmp_dir):
def test_env_site_select_first(tmp_dir: str):
path = Path(tmp_dir)
fallback = path / "fallback"
fallback.mkdir(parents=True)
......
import sys
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Any
from typing import Dict
from typing import Iterator
from typing import List
from typing import Optional
from typing import Set
from typing import Union
import pytest
......@@ -12,54 +20,65 @@ from poetry.repositories.legacy_repository import LegacyRepository
from poetry.utils.exporter import Exporter
if TYPE_CHECKING:
from _pytest.capture import CaptureFixture
from pytest_mock import MockerFixture
from poetry.poetry import Poetry
from tests.conftest import Config
from tests.types import FixtureDirGetter
class Locker(BaseLocker):
def __init__(self):
def __init__(self) -> None:
self._lock = TOMLFile(Path.cwd().joinpath("poetry.lock"))
self._locked = True
self._content_hash = self._get_content_hash()
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[str, Any]):
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"
@pytest.fixture
def working_directory():
def working_directory() -> Path:
return Path(__file__).parent.parent.parent
@pytest.fixture(autouse=True)
def mock_path_cwd(mocker, working_directory):
def mock_path_cwd(
mocker: "MockerFixture", working_directory: Path
) -> Iterator["MockerFixture"]:
yield mocker.patch("pathlib.Path.cwd", return_value=working_directory)
@pytest.fixture()
def locker():
def locker() -> Locker:
return Locker()
@pytest.fixture
def poetry(fixture_dir, locker):
def poetry(fixture_dir: "FixtureDirGetter", locker: Locker) -> "Poetry":
p = Factory().create_poetry(fixture_dir("sample_project"))
p._locker = locker
return p
def set_package_requires(poetry, skip=None):
def set_package_requires(poetry: "Poetry", skip: Optional[Set[str]] = None) -> None:
skip = skip or set()
packages = poetry.locker.locked_repository(with_dev_reqs=True).packages
package = poetry.package.with_dependency_groups([], only=True)
......@@ -71,7 +90,7 @@ def set_package_requires(poetry, skip=None):
def test_exporter_can_export_requirements_txt_with_standard_packages(
tmp_dir, poetry, mocker
tmp_dir: str, poetry: "Poetry"
):
poetry.locker.mock_lock_data(
{
......@@ -116,7 +135,7 @@ foo==1.2.3
def test_exporter_can_export_requirements_txt_with_standard_packages_and_markers(
tmp_dir, poetry
tmp_dir: str, poetry: "Poetry"
):
poetry.locker.mock_lock_data(
{
......@@ -171,7 +190,7 @@ foo==1.2.3 ; python_version < "3.7"
assert expected == content
def test_exporter_can_export_requirements_txt_poetry(tmp_dir, poetry):
def test_exporter_can_export_requirements_txt_poetry(tmp_dir: str, poetry: "Poetry"):
"""Regression test for #3254"""
poetry.locker.mock_lock_data(
......@@ -289,7 +308,9 @@ def test_exporter_can_export_requirements_txt_poetry(tmp_dir, poetry):
assert dependency.marker == expected_dependency.marker
def test_exporter_can_export_requirements_txt_pyinstaller(tmp_dir, poetry):
def test_exporter_can_export_requirements_txt_pyinstaller(
tmp_dir: str, poetry: "Poetry"
):
"""Regression test for #3254"""
poetry.locker.mock_lock_data(
......@@ -366,7 +387,7 @@ def test_exporter_can_export_requirements_txt_pyinstaller(tmp_dir, poetry):
def test_exporter_can_export_requirements_txt_with_nested_packages_and_markers(
tmp_dir, poetry
tmp_dir: str, poetry: "Poetry"
):
poetry.locker.mock_lock_data(
{
......@@ -446,11 +467,11 @@ def test_exporter_can_export_requirements_txt_with_nested_packages_and_markers(
@pytest.mark.parametrize(
"dev,lines",
["dev", "lines"],
[(False, ['a==1.2.3 ; python_version < "3.8"']), (True, ["a==1.2.3", "b==4.5.6"])],
)
def test_exporter_can_export_requirements_txt_with_nested_packages_and_markers_any(
tmp_dir, poetry, dev, lines
tmp_dir: str, poetry: "Poetry", dev: bool, lines: List[str]
):
poetry.locker.mock_lock_data(
{
......@@ -503,7 +524,7 @@ def test_exporter_can_export_requirements_txt_with_nested_packages_and_markers_a
def test_exporter_can_export_requirements_txt_with_standard_packages_and_hashes(
tmp_dir, poetry
tmp_dir: str, poetry: "Poetry"
):
poetry.locker.mock_lock_data(
{
......@@ -550,7 +571,7 @@ foo==1.2.3 \\
def test_exporter_can_export_requirements_txt_with_standard_packages_and_hashes_disabled(
tmp_dir, poetry
tmp_dir: str, poetry: "Poetry"
):
poetry.locker.mock_lock_data(
{
......@@ -597,7 +618,7 @@ foo==1.2.3
def test_exporter_exports_requirements_txt_without_dev_packages_by_default(
tmp_dir, poetry
tmp_dir: str, poetry: "Poetry"
):
poetry.locker.mock_lock_data(
{
......@@ -642,7 +663,7 @@ foo==1.2.3 \\
def test_exporter_exports_requirements_txt_with_dev_packages_if_opted_in(
tmp_dir, poetry
tmp_dir: str, poetry: "Poetry"
):
poetry.locker.mock_lock_data(
{
......@@ -688,7 +709,9 @@ foo==1.2.3 \\
assert expected == content
def test_exporter_exports_requirements_txt_without_optional_packages(tmp_dir, poetry):
def test_exporter_exports_requirements_txt_without_optional_packages(
tmp_dir: str, poetry: "Poetry"
):
poetry.locker.mock_lock_data(
{
"package": [
......@@ -732,7 +755,7 @@ foo==1.2.3 \\
@pytest.mark.parametrize(
"extras,lines",
["extras", "lines"],
[
(None, ["foo==1.2.3"]),
(False, ["foo==1.2.3"]),
......@@ -741,7 +764,10 @@ foo==1.2.3 \\
],
)
def test_exporter_exports_requirements_txt_with_optional_packages(
tmp_dir, poetry, extras, lines
tmp_dir: str,
poetry: "Poetry",
extras: Optional[Union[bool, List[str]]],
lines: List[str],
):
poetry.locker.mock_lock_data(
{
......@@ -798,7 +824,9 @@ def test_exporter_exports_requirements_txt_with_optional_packages(
assert content.strip() == expected
def test_exporter_can_export_requirements_txt_with_git_packages(tmp_dir, poetry):
def test_exporter_can_export_requirements_txt_with_git_packages(
tmp_dir: str, poetry: "Poetry"
):
poetry.locker.mock_lock_data(
{
"package": [
......@@ -838,7 +866,9 @@ foo @ git+https://github.com/foo/foo.git@123456
assert expected == content
def test_exporter_can_export_requirements_txt_with_nested_packages(tmp_dir, poetry):
def test_exporter_can_export_requirements_txt_with_nested_packages(
tmp_dir: str, poetry: "Poetry"
):
poetry.locker.mock_lock_data(
{
"package": [
......@@ -888,7 +918,7 @@ foo @ git+https://github.com/foo/foo.git@123456
def test_exporter_can_export_requirements_txt_with_nested_packages_cyclic(
tmp_dir, poetry
tmp_dir: str, poetry: "Poetry"
):
poetry.locker.mock_lock_data(
{
......@@ -944,7 +974,7 @@ foo==1.2.3
def test_exporter_can_export_requirements_txt_with_nested_packages_and_multiple_markers(
tmp_dir, poetry
tmp_dir: str, poetry: "Poetry"
):
poetry.locker.mock_lock_data(
{
......@@ -1017,7 +1047,7 @@ foo==1.2.3
def test_exporter_can_export_requirements_txt_with_git_packages_and_markers(
tmp_dir, poetry
tmp_dir: str, poetry: "Poetry"
):
poetry.locker.mock_lock_data(
{
......@@ -1060,7 +1090,7 @@ foo @ git+https://github.com/foo/foo.git@123456 ; python_version < "3.7"
def test_exporter_can_export_requirements_txt_with_directory_packages(
tmp_dir, poetry, working_directory
tmp_dir: str, poetry: "Poetry", working_directory: Path
):
poetry.locker.mock_lock_data(
{
......@@ -1104,7 +1134,7 @@ foo @ {}/tests/fixtures/sample_project
def test_exporter_can_export_requirements_txt_with_nested_directory_packages(
tmp_dir, poetry, working_directory
tmp_dir: str, poetry: "Poetry", working_directory: Path
):
poetry.locker.mock_lock_data(
{
......@@ -1176,7 +1206,7 @@ foo @ {}/tests/fixtures/sample_project
def test_exporter_can_export_requirements_txt_with_directory_packages_and_markers(
tmp_dir, poetry, working_directory
tmp_dir: str, poetry: "Poetry", working_directory: Path
):
poetry.locker.mock_lock_data(
{
......@@ -1221,7 +1251,7 @@ foo @ {}/tests/fixtures/sample_project ; python_version < "3.7"
def test_exporter_can_export_requirements_txt_with_file_packages(
tmp_dir, poetry, working_directory
tmp_dir: str, poetry: "Poetry", working_directory: Path
):
poetry.locker.mock_lock_data(
{
......@@ -1265,7 +1295,7 @@ foo @ {}/tests/fixtures/distributions/demo-0.1.0.tar.gz
def test_exporter_can_export_requirements_txt_with_file_packages_and_markers(
tmp_dir, poetry, working_directory
tmp_dir: str, poetry: "Poetry", working_directory: Path
):
poetry.locker.mock_lock_data(
{
......@@ -1309,7 +1339,9 @@ foo @ {}/tests/fixtures/distributions/demo-0.1.0.tar.gz ; python_version < "3.7"
assert expected == content
def test_exporter_exports_requirements_txt_with_legacy_packages(tmp_dir, poetry):
def test_exporter_exports_requirements_txt_with_legacy_packages(
tmp_dir: str, poetry: "Poetry"
):
poetry.pool.add_repository(
LegacyRepository(
"custom",
......@@ -1367,7 +1399,9 @@ foo==1.2.3 \\
assert expected == content
def test_exporter_exports_requirements_txt_with_url_false(tmp_dir, poetry):
def test_exporter_exports_requirements_txt_with_url_false(
tmp_dir: str, poetry: "Poetry"
):
poetry.pool.add_repository(
LegacyRepository(
"custom",
......@@ -1426,7 +1460,7 @@ foo==1.2.3 \\
def test_exporter_exports_requirements_txt_with_legacy_packages_trusted_host(
tmp_dir, poetry
tmp_dir: str, poetry: "Poetry"
):
poetry.pool.add_repository(
LegacyRepository(
......@@ -1477,14 +1511,14 @@ bar==4.5.6 \\
@pytest.mark.parametrize(
("dev", "expected"),
["dev", "expected"],
[
(True, ["bar==1.2.2", "baz==1.2.3", "foo==1.2.1"]),
(False, ["bar==1.2.2", "foo==1.2.1"]),
],
)
def test_exporter_exports_requirements_txt_with_dev_extras(
tmp_dir, poetry, dev, expected
tmp_dir: str, poetry: "Poetry", dev: bool, expected: List[str]
):
poetry.locker.mock_lock_data(
{
......@@ -1539,7 +1573,7 @@ def test_exporter_exports_requirements_txt_with_dev_extras(
def test_exporter_exports_requirements_txt_with_legacy_packages_and_duplicate_sources(
tmp_dir, poetry
tmp_dir: str, poetry: "Poetry"
):
poetry.pool.add_repository(
LegacyRepository(
......@@ -1625,7 +1659,7 @@ foo==1.2.3 \\
def test_exporter_exports_requirements_txt_with_legacy_packages_and_credentials(
tmp_dir, poetry, config
tmp_dir: str, poetry: "Poetry", config: "Config"
):
poetry.config.merge(
{
......@@ -1693,7 +1727,9 @@ foo==1.2.3 \\
assert expected == content
def test_exporter_exports_requirements_txt_to_standard_output(tmp_dir, poetry, capsys):
def test_exporter_exports_requirements_txt_to_standard_output(
tmp_dir: str, poetry: "Poetry", capsys: "CaptureFixture"
):
poetry.locker.mock_lock_data(
{
"package": [
......
from typing import Dict
from typing import List
import pytest
from poetry.core.packages.package import Package
......@@ -18,7 +21,7 @@ _PACKAGE_QUIX.add_dependency(Factory.create_dependency("baz", "*"))
@pytest.mark.parametrize(
"packages,extras,extra_names,expected_extra_package_names",
["packages", "extras", "extra_names", "expected_extra_package_names"],
[
# Empty edge case
([], {}, [], []),
......@@ -56,7 +59,10 @@ _PACKAGE_QUIX.add_dependency(Factory.create_dependency("baz", "*"))
],
)
def test_get_extra_package_names(
packages, extras, extra_names, expected_extra_package_names
packages: List[Package],
extras: Dict[str, List[str]],
extra_names: List[str],
expected_extra_package_names: List[str],
):
assert expected_extra_package_names == list(
get_extra_package_names(packages, extras, extra_names)
......
from pathlib import Path
from typing import TYPE_CHECKING
from poetry.core.utils.helpers import parse_requires
from poetry.utils.helpers import get_cert
from poetry.utils.helpers import get_client_cert
if TYPE_CHECKING:
from tests.conftest import Config
def test_parse_requires():
requires = """\
jsonschema>=2.6.0.0,<3.0.0.0
......@@ -58,14 +63,14 @@ isort@ git+git://github.com/timothycrosley/isort.git@e63ae06ec7d70b06df9e5283576
assert result == expected
def test_get_cert(config):
def test_get_cert(config: "Config"):
ca_cert = "path/to/ca.pem"
config.merge({"certificates": {"foo": {"cert": ca_cert}}})
assert get_cert(config, "foo") == Path(ca_cert)
def test_get_client_cert(config):
def test_get_client_cert(config: "Config"):
client_cert = "path/to/client.pem"
config.merge({"certificates": {"foo": {"client-cert": client_cert}}})
......
import os
from typing import TYPE_CHECKING
import pytest
from poetry.utils.password_manager import KeyRing
......@@ -7,7 +9,16 @@ from poetry.utils.password_manager import KeyRingError
from poetry.utils.password_manager import PasswordManager
def test_set_http_password(config, with_simple_keyring, dummy_keyring):
if TYPE_CHECKING:
from pytest_mock import MockerFixture
from tests.conftest import Config
from tests.conftest import DummyBackend
def test_set_http_password(
config: "Config", with_simple_keyring: None, dummy_keyring: "DummyBackend"
):
manager = PasswordManager(config)
assert manager.keyring.is_available()
......@@ -20,7 +31,9 @@ def test_set_http_password(config, with_simple_keyring, dummy_keyring):
assert "password" not in auth
def test_get_http_auth(config, with_simple_keyring, dummy_keyring):
def test_get_http_auth(
config: "Config", with_simple_keyring: None, dummy_keyring: "DummyBackend"
):
dummy_keyring.set_password("poetry-repository-foo", "bar", "baz")
config.auth_config_source.add_property("http-basic.foo", {"username": "bar"})
manager = PasswordManager(config)
......@@ -32,7 +45,9 @@ def test_get_http_auth(config, with_simple_keyring, dummy_keyring):
assert auth["password"] == "baz"
def test_delete_http_password(config, with_simple_keyring, dummy_keyring):
def test_delete_http_password(
config: "Config", with_simple_keyring: None, dummy_keyring: "DummyBackend"
):
dummy_keyring.set_password("poetry-repository-foo", "bar", "baz")
config.auth_config_source.add_property("http-basic.foo", {"username": "bar"})
manager = PasswordManager(config)
......@@ -44,7 +59,9 @@ def test_delete_http_password(config, with_simple_keyring, dummy_keyring):
assert config.get("http-basic.foo") is None
def test_set_pypi_token(config, with_simple_keyring, dummy_keyring):
def test_set_pypi_token(
config: "Config", with_simple_keyring: None, dummy_keyring: "DummyBackend"
):
manager = PasswordManager(config)
assert manager.keyring.is_available()
......@@ -55,7 +72,9 @@ def test_set_pypi_token(config, with_simple_keyring, dummy_keyring):
assert dummy_keyring.get_password("poetry-repository-foo", "__token__") == "baz"
def test_get_pypi_token(config, with_simple_keyring, dummy_keyring):
def test_get_pypi_token(
config: "Config", with_simple_keyring: None, dummy_keyring: "DummyBackend"
):
dummy_keyring.set_password("poetry-repository-foo", "__token__", "baz")
manager = PasswordManager(config)
......@@ -63,7 +82,9 @@ def test_get_pypi_token(config, with_simple_keyring, dummy_keyring):
assert manager.get_pypi_token("foo") == "baz"
def test_delete_pypi_token(config, with_simple_keyring, dummy_keyring):
def test_delete_pypi_token(
config: "Config", with_simple_keyring: None, dummy_keyring: "DummyBackend"
):
dummy_keyring.set_password("poetry-repository-foo", "__token__", "baz")
manager = PasswordManager(config)
......@@ -73,7 +94,9 @@ def test_delete_pypi_token(config, with_simple_keyring, dummy_keyring):
assert dummy_keyring.get_password("poetry-repository-foo", "__token__") is None
def test_set_http_password_with_unavailable_backend(config, with_fail_keyring):
def test_set_http_password_with_unavailable_backend(
config: "Config", with_fail_keyring: None
):
manager = PasswordManager(config)
assert not manager.keyring.is_available()
......@@ -84,7 +107,9 @@ def test_set_http_password_with_unavailable_backend(config, with_fail_keyring):
assert auth["password"] == "baz"
def test_get_http_auth_with_unavailable_backend(config, with_fail_keyring):
def test_get_http_auth_with_unavailable_backend(
config: "Config", with_fail_keyring: None
):
config.auth_config_source.add_property(
"http-basic.foo", {"username": "bar", "password": "baz"}
)
......@@ -97,7 +122,9 @@ def test_get_http_auth_with_unavailable_backend(config, with_fail_keyring):
assert auth["password"] == "baz"
def test_delete_http_password_with_unavailable_backend(config, with_fail_keyring):
def test_delete_http_password_with_unavailable_backend(
config: "Config", with_fail_keyring: None
):
config.auth_config_source.add_property(
"http-basic.foo", {"username": "bar", "password": "baz"}
)
......@@ -109,7 +136,9 @@ def test_delete_http_password_with_unavailable_backend(config, with_fail_keyring
assert config.get("http-basic.foo") is None
def test_set_pypi_token_with_unavailable_backend(config, with_fail_keyring):
def test_set_pypi_token_with_unavailable_backend(
config: "Config", with_fail_keyring: None
):
manager = PasswordManager(config)
assert not manager.keyring.is_available()
......@@ -118,7 +147,9 @@ def test_set_pypi_token_with_unavailable_backend(config, with_fail_keyring):
assert config.get("pypi-token.foo") == "baz"
def test_get_pypi_token_with_unavailable_backend(config, with_fail_keyring):
def test_get_pypi_token_with_unavailable_backend(
config: "Config", with_fail_keyring: None
):
config.auth_config_source.add_property("pypi-token.foo", "baz")
manager = PasswordManager(config)
......@@ -126,7 +157,9 @@ def test_get_pypi_token_with_unavailable_backend(config, with_fail_keyring):
assert manager.get_pypi_token("foo") == "baz"
def test_delete_pypi_token_with_unavailable_backend(config, with_fail_keyring):
def test_delete_pypi_token_with_unavailable_backend(
config: "Config", with_fail_keyring: None
):
config.auth_config_source.add_property("pypi-token.foo", "baz")
manager = PasswordManager(config)
......@@ -136,7 +169,9 @@ def test_delete_pypi_token_with_unavailable_backend(config, with_fail_keyring):
assert config.get("pypi-token.foo") is None
def test_keyring_raises_errors_on_keyring_errors(mocker, with_fail_keyring):
def test_keyring_raises_errors_on_keyring_errors(
mocker: "MockerFixture", with_fail_keyring: None
):
mocker.patch("poetry.utils.password_manager.KeyRing._check")
key_ring = KeyRing("poetry")
......@@ -151,14 +186,16 @@ def test_keyring_raises_errors_on_keyring_errors(mocker, with_fail_keyring):
def test_keyring_with_chainer_backend_and_not_compatible_only_should_be_unavailable(
with_chained_keyring,
with_chained_keyring: None,
):
key_ring = KeyRing("poetry")
assert not key_ring.is_available()
def test_get_http_auth_from_environment_variables(environ, config, with_simple_keyring):
def test_get_http_auth_from_environment_variables(
environ: None, config: "Config", with_simple_keyring: None
):
os.environ["POETRY_HTTP_BASIC_FOO_USERNAME"] = "bar"
os.environ["POETRY_HTTP_BASIC_FOO_PASSWORD"] = "baz"
......
from typing import Dict
from typing import Optional
import pytest
from poetry.utils import patterns
......@@ -32,7 +35,7 @@ from poetry.utils import patterns
),
],
)
def test_wheel_file_re(filename, expected):
def test_wheel_file_re(filename: str, expected: Dict[str, Optional[str]]):
match = patterns.wheel_file_re.match(filename)
groups = match.groupdict()
......
import subprocess
from typing import TYPE_CHECKING
import pytest
from poetry.core.packages.utils.link import Link
......@@ -7,14 +9,25 @@ from poetry.core.packages.utils.utils import path_to_url
from poetry.utils.pip import pip_install
def test_pip_install_successful(tmp_dir, tmp_venv, fixture_dir):
if TYPE_CHECKING:
from pytest_mock import MockerFixture
from poetry.utils.env import VirtualEnv
from tests.types import FixtureDirGetter
def test_pip_install_successful(
tmp_dir: str, tmp_venv: "VirtualEnv", fixture_dir: "FixtureDirGetter"
):
file_path = fixture_dir("distributions/demo-0.1.0-py2.py3-none-any.whl")
result = pip_install(file_path, tmp_venv)
assert "Successfully installed demo-0.1.0" in result
def test_pip_install_link(tmp_dir, tmp_venv, fixture_dir):
def test_pip_install_link(
tmp_dir: str, tmp_venv: "VirtualEnv", fixture_dir: "FixtureDirGetter"
):
file_path = Link(
path_to_url(fixture_dir("distributions/demo-0.1.0-py2.py3-none-any.whl"))
)
......@@ -23,7 +36,12 @@ def test_pip_install_link(tmp_dir, tmp_venv, fixture_dir):
assert "Successfully installed demo-0.1.0" in result
def test_pip_install_with_keyboard_interrupt(tmp_dir, tmp_venv, fixture_dir, mocker):
def test_pip_install_with_keyboard_interrupt(
tmp_dir: str,
tmp_venv: "VirtualEnv",
fixture_dir: "FixtureDirGetter",
mocker: "MockerFixture",
):
file_path = fixture_dir("distributions/demo-0.1.0-py2.py3-none-any.whl")
mocker.patch("subprocess.run", side_effect=KeyboardInterrupt())
with pytest.raises(KeyboardInterrupt):
......
import os
from typing import Callable
import pytest
from poetry.core.version.exceptions import InvalidVersion
......@@ -7,14 +9,16 @@ from poetry.utils.setup_reader import SetupReader
@pytest.fixture()
def setup():
def _setup(name):
def setup() -> Callable[[str], str]:
def _setup(name: str) -> str:
return os.path.join(os.path.dirname(__file__), "fixtures", "setups", name)
return _setup
def test_setup_reader_read_first_level_setup_call_with_direct_types(setup):
def test_setup_reader_read_first_level_setup_call_with_direct_types(
setup: Callable[[str], str]
):
result = SetupReader.read_from_directory(setup("flask"))
expected_name = "Flask"
......@@ -46,7 +50,9 @@ def test_setup_reader_read_first_level_setup_call_with_direct_types(setup):
assert expected_python_requires == result["python_requires"]
def test_setup_reader_read_first_level_setup_call_with_variables(setup):
def test_setup_reader_read_first_level_setup_call_with_variables(
setup: Callable[[str], str]
):
result = SetupReader.read_from_directory(setup("requests"))
expected_name = None
......@@ -71,7 +77,9 @@ def test_setup_reader_read_first_level_setup_call_with_variables(setup):
assert expected_python_requires == result["python_requires"]
def test_setup_reader_read_sub_level_setup_call_with_direct_types(setup):
def test_setup_reader_read_sub_level_setup_call_with_direct_types(
setup: Callable[[str], str]
):
result = SetupReader.read_from_directory(setup("sqlalchemy"))
expected_name = "SQLAlchemy"
......@@ -95,7 +103,7 @@ def test_setup_reader_read_sub_level_setup_call_with_direct_types(setup):
assert result["python_requires"] is None
def test_setup_reader_read_setup_cfg(setup):
def test_setup_reader_read_setup_cfg(setup: Callable[[str], str]):
result = SetupReader.read_from_directory(setup("with-setup-cfg"))
expected_name = "with-setup-cfg"
......@@ -114,12 +122,12 @@ def test_setup_reader_read_setup_cfg(setup):
assert expected_python_requires == result["python_requires"]
def test_setup_reader_read_setup_cfg_with_attr(setup):
def test_setup_reader_read_setup_cfg_with_attr(setup: Callable[[str], str]):
with pytest.raises(InvalidVersion):
SetupReader.read_from_directory(setup("with-setup-cfg-attr"))
def test_setup_reader_read_setup_kwargs(setup):
def test_setup_reader_read_setup_kwargs(setup: Callable[[str], str]):
result = SetupReader.read_from_directory(setup("pendulum"))
expected_name = "pendulum"
......@@ -135,7 +143,7 @@ def test_setup_reader_read_setup_kwargs(setup):
assert expected_python_requires == result["python_requires"]
def test_setup_reader_read_setup_call_in_main(setup):
def test_setup_reader_read_setup_call_in_main(setup: Callable[[str], str]):
result = SetupReader.read_from_directory(setup("pyyaml"))
expected_name = "PyYAML"
......@@ -151,7 +159,7 @@ def test_setup_reader_read_setup_call_in_main(setup):
assert expected_python_requires == result["python_requires"]
def test_setup_reader_read_extras_require_with_variables(setup):
def test_setup_reader_read_extras_require_with_variables(setup: Callable[[str], str]):
result = SetupReader.read_from_directory(setup("extras_require_with_vars"))
expected_name = "extras_require_with_vars"
......@@ -167,7 +175,7 @@ def test_setup_reader_read_extras_require_with_variables(setup):
assert expected_python_requires == result["python_requires"]
def test_setup_reader_setuptools(setup):
def test_setup_reader_setuptools(setup: Callable[[str], str]):
result = SetupReader.read_from_directory(setup("setuptools_setup"))
expected_name = "my_package"
......
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