Commit 603b398e by David Hotham Committed by GitHub

more type-checking (#7845)

parent 978d435b
...@@ -679,14 +679,14 @@ files = [ ...@@ -679,14 +679,14 @@ files = [
[[package]] [[package]]
name = "importlib-metadata" name = "importlib-metadata"
version = "6.5.0" version = "6.6.0"
description = "Read metadata from Python packages" description = "Read metadata from Python packages"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "importlib_metadata-6.5.0-py3-none-any.whl", hash = "sha256:03ba783c3a2c69d751b109fc0c94a62c51f581b3d6acf8ed1331b6d5729321ff"}, {file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"},
{file = "importlib_metadata-6.5.0.tar.gz", hash = "sha256:7a8bdf1bc3a726297f5cfbc999e6e7ff6b4fa41b26bba4afc580448624460045"}, {file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"},
] ]
[package.dependencies] [package.dependencies]
......
...@@ -178,7 +178,7 @@ force-exclude = ''' ...@@ -178,7 +178,7 @@ force-exclude = '''
[tool.mypy] [tool.mypy]
files = "src" files = "src, tests"
mypy_path = "src" mypy_path = "src"
namespace_packages = true namespace_packages = true
explicit_package_bases = true explicit_package_bases = true
...@@ -195,17 +195,17 @@ exclude = [ ...@@ -195,17 +195,17 @@ exclude = [
"tests/utils/fixtures" "tests/utils/fixtures"
] ]
# use of importlib-metadata backport at python3.7 makes it impossible to # use of importlib-metadata backport makes it impossible to satisfy mypy
# satisfy mypy without some ignores: but we get a different set of ignores at # without some ignores: but we get different sets of ignores at different
# different python versions. # python versions.
#
# <https://github.com/python/mypy/issues/8823>, meanwhile suppress that
# warning.
[[tool.mypy.overrides]] [[tool.mypy.overrides]]
module = [ module = [
'poetry.plugins.plugin_manager', 'poetry.plugins.plugin_manager',
'poetry.repositories.installed_repository', 'poetry.repositories.installed_repository',
'poetry.utils.env', 'poetry.utils.env',
'tests.helpers',
'tests.repositories.test_installed_repository',
'tests.console.commands.self.test_show_plugins'
] ]
warn_unused_ignores = false warn_unused_ignores = false
...@@ -222,6 +222,7 @@ module = [ ...@@ -222,6 +222,7 @@ module = [
'shellingham.*', 'shellingham.*',
'virtualenv.*', 'virtualenv.*',
'xattr.*', 'xattr.*',
'zipp.*'
] ]
ignore_missing_imports = true ignore_missing_imports = true
......
...@@ -147,7 +147,7 @@ class PyPiRepository(HTTPRepository): ...@@ -147,7 +147,7 @@ class PyPiRepository(HTTPRepository):
def _get_release_info( def _get_release_info(
self, name: NormalizedName, version: Version self, name: NormalizedName, version: Version
) -> dict[str, str | list[str] | None]: ) -> dict[str, Any]:
from poetry.inspection.info import PackageInfo from poetry.inspection.info import PackageInfo
self._log(f"Getting info for {name} ({version}) from PyPI", "debug") self._log(f"Getting info for {name} ({version}) from PyPI", "debug")
......
...@@ -1727,13 +1727,11 @@ class VirtualEnv(Env): ...@@ -1727,13 +1727,11 @@ class VirtualEnv(Env):
# from inside the virtualenv. # from inside the virtualenv.
if base is None: if base is None:
output = self.run_python_script(GET_BASE_PREFIX) output = self.run_python_script(GET_BASE_PREFIX)
assert isinstance(output, str)
self._base = Path(output.strip()) self._base = Path(output.strip())
@property @property
def sys_path(self) -> list[str]: def sys_path(self) -> list[str]:
output = self.run_python_script(GET_SYS_PATH) output = self.run_python_script(GET_SYS_PATH)
assert isinstance(output, str)
paths: list[str] = json.loads(output) paths: list[str] = json.loads(output)
return paths return paths
...@@ -1749,20 +1747,17 @@ class VirtualEnv(Env): ...@@ -1749,20 +1747,17 @@ class VirtualEnv(Env):
def get_supported_tags(self) -> list[Tag]: def get_supported_tags(self) -> list[Tag]:
output = self.run_python_script(GET_SYS_TAGS) output = self.run_python_script(GET_SYS_TAGS)
assert isinstance(output, str)
return [Tag(*t) for t in json.loads(output)] return [Tag(*t) for t in json.loads(output)]
def get_marker_env(self) -> dict[str, Any]: def get_marker_env(self) -> dict[str, Any]:
output = self.run_python_script(GET_ENVIRONMENT_INFO) output = self.run_python_script(GET_ENVIRONMENT_INFO)
assert isinstance(output, str)
env: dict[str, Any] = json.loads(output) env: dict[str, Any] = json.loads(output)
return env return env
def get_pip_version(self) -> Version: def get_pip_version(self) -> Version:
output = self.run_pip("--version") output = self.run_pip("--version")
assert isinstance(output, str)
output = output.strip() output = output.strip()
m = re.match("pip (.+?)(?: from .+)?$", output) m = re.match("pip (.+?)(?: from .+)?$", output)
...@@ -1773,7 +1768,6 @@ class VirtualEnv(Env): ...@@ -1773,7 +1768,6 @@ class VirtualEnv(Env):
def get_paths(self) -> dict[str, str]: def get_paths(self) -> dict[str, str]:
output = self.run_python_script(GET_PATHS) output = self.run_python_script(GET_PATHS)
assert isinstance(output, str)
paths: dict[str, str] = json.loads(output) paths: dict[str, str] = json.loads(output)
return paths return paths
...@@ -1889,7 +1883,6 @@ class GenericEnv(VirtualEnv): ...@@ -1889,7 +1883,6 @@ class GenericEnv(VirtualEnv):
def get_paths(self) -> dict[str, str]: def get_paths(self) -> dict[str, str]:
output = self.run_python_script(GET_PATHS_FOR_GENERIC_ENVS) output = self.run_python_script(GET_PATHS_FOR_GENERIC_ENVS)
assert isinstance(output, str)
paths: dict[str, str] = json.loads(output) paths: dict[str, str] = json.loads(output)
return paths return paths
......
...@@ -19,8 +19,10 @@ if TYPE_CHECKING: ...@@ -19,8 +19,10 @@ if TYPE_CHECKING:
from collections.abc import Callable from collections.abc import Callable
from collections.abc import Iterator from collections.abc import Iterator
Normalizer = Callable[[str], Any]
def get_options_based_on_normalizer(normalizer: Callable[[str], Any]) -> str:
def get_options_based_on_normalizer(normalizer: Normalizer) -> Iterator[str]:
flattened_config = flatten_dict(obj=Config.default_config, delimiter=".") flattened_config = flatten_dict(obj=Config.default_config, delimiter=".")
for k in flattened_config: for k in flattened_config:
...@@ -42,10 +44,12 @@ def test_config_get_processes_depended_on_values( ...@@ -42,10 +44,12 @@ def test_config_get_processes_depended_on_values(
def generate_environment_variable_tests() -> Iterator[tuple[str, str, str, bool]]: def generate_environment_variable_tests() -> Iterator[tuple[str, str, str, bool]]:
for normalizer, values in [ data: list[tuple[Normalizer, list[tuple[str, Any]]]] = [
(boolean_normalizer, [("true", True), ("false", False)]), (boolean_normalizer, [("true", True), ("false", False)]),
(int_normalizer, [("4", 4), ("2", 2)]), (int_normalizer, [("4", 4), ("2", 2)]),
]: ]
for normalizer, values in data:
for env_value, value in values: for env_value, value in values:
for name in get_options_based_on_normalizer(normalizer=normalizer): for name in get_options_based_on_normalizer(normalizer=normalizer):
env_var = "POETRY_" + re.sub("[.-]+", "_", name).upper() env_var = "POETRY_" + re.sub("[.-]+", "_", name).upper()
......
...@@ -121,7 +121,7 @@ def dummy_keyring() -> DummyBackend: ...@@ -121,7 +121,7 @@ def dummy_keyring() -> DummyBackend:
def with_simple_keyring(dummy_keyring: DummyBackend) -> None: def with_simple_keyring(dummy_keyring: DummyBackend) -> None:
import keyring import keyring
keyring.set_keyring(dummy_keyring) keyring.set_keyring(dummy_keyring) # type: ignore[no-untyped-call]
@pytest.fixture() @pytest.fixture()
...@@ -130,7 +130,7 @@ def with_fail_keyring() -> None: ...@@ -130,7 +130,7 @@ def with_fail_keyring() -> None:
from keyring.backends.fail import Keyring from keyring.backends.fail import Keyring
keyring.set_keyring(Keyring()) keyring.set_keyring(Keyring()) # type: ignore[no-untyped-call]
@pytest.fixture() @pytest.fixture()
...@@ -139,31 +139,37 @@ def with_null_keyring() -> None: ...@@ -139,31 +139,37 @@ def with_null_keyring() -> None:
from keyring.backends.null import Keyring from keyring.backends.null import Keyring
keyring.set_keyring(Keyring()) keyring.set_keyring(Keyring()) # type: ignore[no-untyped-call]
@pytest.fixture() @pytest.fixture()
def with_chained_fail_keyring(mocker: MockerFixture) -> None: def with_chained_fail_keyring(mocker: MockerFixture) -> None:
from keyring.backends.fail import Keyring from keyring.backends.fail import Keyring
mocker.patch("keyring.backend.get_all_keyring", lambda: [Keyring()]) mocker.patch(
"keyring.backend.get_all_keyring",
lambda: [Keyring()], # type: ignore[no-untyped-call]
)
import keyring import keyring
from keyring.backends.chainer import ChainerBackend from keyring.backends.chainer import ChainerBackend
keyring.set_keyring(ChainerBackend()) keyring.set_keyring(ChainerBackend()) # type: ignore[no-untyped-call]
@pytest.fixture() @pytest.fixture()
def with_chained_null_keyring(mocker: MockerFixture) -> None: def with_chained_null_keyring(mocker: MockerFixture) -> None:
from keyring.backends.null import Keyring from keyring.backends.null import Keyring
mocker.patch("keyring.backend.get_all_keyring", lambda: [Keyring()]) mocker.patch(
"keyring.backend.get_all_keyring",
lambda: [Keyring()], # type: ignore[no-untyped-call]
)
import keyring import keyring
from keyring.backends.chainer import ChainerBackend from keyring.backends.chainer import ChainerBackend
keyring.set_keyring(ChainerBackend()) keyring.set_keyring(ChainerBackend()) # type: ignore[no-untyped-call]
@pytest.fixture @pytest.fixture
...@@ -203,7 +209,7 @@ def config( ...@@ -203,7 +209,7 @@ def config(
from keyring.backends.fail import Keyring from keyring.backends.fail import Keyring
keyring.set_keyring(Keyring()) keyring.set_keyring(Keyring()) # type: ignore[no-untyped-call]
c = Config() c = Config()
c.merge(config_source.config) c.merge(config_source.config)
......
...@@ -4,6 +4,7 @@ import os ...@@ -4,6 +4,7 @@ import os
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from typing import Any
import pytest import pytest
import tomlkit import tomlkit
...@@ -83,7 +84,7 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file( ...@@ -83,7 +84,7 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file(
envs_file = TOMLFile(venv_cache / "envs.toml") envs_file = TOMLFile(venv_cache / "envs.toml")
assert envs_file.exists() assert envs_file.exists()
envs = envs_file.read() envs: dict[str, Any] = envs_file.read()
assert envs[venv_name]["minor"] == "3.7" assert envs[venv_name]["minor"] == "3.7"
assert envs[venv_name]["patch"] == "3.7.1" assert envs[venv_name]["patch"] == "3.7.1"
......
...@@ -35,11 +35,6 @@ def _patch_repos(repo: TestRepository, installed: Repository) -> None: ...@@ -35,11 +35,6 @@ def _patch_repos(repo: TestRepository, installed: Repository) -> None:
installed.add_package(poetry) installed.add_package(poetry)
@pytest.fixture(autouse=True)
def save_environ(environ: None) -> Repository:
yield
@pytest.fixture() @pytest.fixture()
def pool(repo: TestRepository) -> RepositoryPool: def pool(repo: TestRepository) -> RepositoryPool:
return RepositoryPool([repo]) return RepositoryPool([repo])
......
from __future__ import annotations from __future__ import annotations
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from typing import Any
if TYPE_CHECKING:
from collections.abc import Mapping
import pytest import pytest
from poetry.core.packages.package import Package from poetry.core.packages.package import Package
from poetry.console.commands.add import AddCommand
from poetry.console.commands.self.self_command import SelfCommand from poetry.console.commands.self.self_command import SelfCommand
from poetry.factory import Factory from poetry.factory import Factory
from tests.console.commands.self.utils import get_self_command_dependencies from tests.console.commands.self.utils import get_self_command_dependencies
...@@ -26,10 +32,10 @@ def tester(command_tester_factory: CommandTesterFactory) -> CommandTester: ...@@ -26,10 +32,10 @@ def tester(command_tester_factory: CommandTesterFactory) -> CommandTester:
def assert_plugin_add_result( def assert_plugin_add_result(
tester: CommandTester, tester: CommandTester,
expected: str, expected: str,
constraint: str | dict[str, str], constraint: str | Mapping[str, str | list[str]],
) -> None: ) -> None:
assert tester.io.fetch_output() == expected assert tester.io.fetch_output() == expected
dependencies = get_self_command_dependencies() dependencies: dict[str, Any] = get_self_command_dependencies()
assert "poetry-plugin" in dependencies assert "poetry-plugin" in dependencies
assert dependencies["poetry-plugin"] == constraint assert dependencies["poetry-plugin"] == constraint
...@@ -128,14 +134,11 @@ Package operations: 3 installs, 0 updates, 0 removals ...@@ -128,14 +134,11 @@ Package operations: 3 installs, 0 updates, 0 removals
Writing lock file Writing lock file
""" """
assert_plugin_add_result( constraint: dict[str, str | list[str]] = {
tester, "git": "https://github.com/demo/poetry-plugin.git",
expected, "extras": ["foo"],
{ }
"git": "https://github.com/demo/poetry-plugin.git", assert_plugin_add_result(tester, expected, constraint)
"extras": ["foo"],
},
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
...@@ -212,6 +215,7 @@ poetry-plugin = "^1.2.3" ...@@ -212,6 +215,7 @@ poetry-plugin = "^1.2.3"
tester.execute("poetry-plugin") tester.execute("poetry-plugin")
assert isinstance(tester.command, AddCommand)
expected = f"""\ expected = f"""\
The following packages are already present in the pyproject.toml and will be\ The following packages are already present in the pyproject.toml and will be\
skipped: skipped:
......
...@@ -80,10 +80,10 @@ def plugin_distro(plugin_package: Package, tmp_path: Path) -> metadata.Distribut ...@@ -80,10 +80,10 @@ def plugin_distro(plugin_package: Package, tmp_path: Path) -> metadata.Distribut
) )
return None return None
def locate_file(self, path: PathLike[str]) -> PathLike[str]: def locate_file(self, path: str | PathLike[str]) -> Path:
return tmp_path / path return tmp_path / path
return MockDistribution() return MockDistribution() # type: ignore[no-untyped-call]
@pytest.fixture @pytest.fixture
...@@ -101,10 +101,14 @@ def entry_points( ...@@ -101,10 +101,14 @@ def entry_points(
entry_point_name: str, entry_point_name: str,
entry_point_values_by_group: dict[str, list[str]], entry_point_values_by_group: dict[str, list[str]],
plugin_distro: metadata.Distribution, plugin_distro: metadata.Distribution,
) -> Callable[[...], list[metadata.EntryPoint]]: ) -> Callable[..., list[metadata.EntryPoint]]:
by_group = { by_group = {
key: [ key: [
EntryPoint(name=entry_point_name, group=key, value=value)._for( EntryPoint( # type: ignore[no-untyped-call]
name=entry_point_name,
group=key,
value=value,
)._for( # type: ignore[attr-defined]
plugin_distro plugin_distro
) )
for value in values for value in values
...@@ -118,7 +122,9 @@ def entry_points( ...@@ -118,7 +122,9 @@ def entry_points(
if group not in by_group: if group not in by_group:
return [] return []
return by_group.get(group) eps: list[metadata.EntryPoint] = by_group[group]
return eps
return _entry_points return _entry_points
...@@ -130,7 +136,7 @@ def mock_metadata_entry_points( ...@@ -130,7 +136,7 @@ def mock_metadata_entry_points(
installed: Repository, installed: Repository,
mocker: MockerFixture, mocker: MockerFixture,
tmp_venv: Env, tmp_venv: Env,
entry_points: Callable[[...], metadata.EntryPoint], entry_points: Callable[..., metadata.EntryPoint],
) -> None: ) -> None:
installed.add_package(plugin_package) installed.add_package(plugin_package)
......
from __future__ import annotations from __future__ import annotations
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING from typing import Any
from poetry.factory import Factory
from tomlkit.items import Table as TOMLTable
if TYPE_CHECKING: from poetry.factory import Factory
from tomlkit.container import Table as TOMLTable
def get_self_command_dependencies(locked: bool = True) -> TOMLTable: def get_self_command_dependencies(locked: bool = True) -> TOMLTable:
...@@ -24,10 +22,15 @@ def get_self_command_dependencies(locked: bool = True) -> TOMLTable: ...@@ -24,10 +22,15 @@ def get_self_command_dependencies(locked: bool = True) -> TOMLTable:
poetry = Factory().create_poetry(system_pyproject_file.parent, disable_plugins=True) poetry = Factory().create_poetry(system_pyproject_file.parent, disable_plugins=True)
content = poetry.file.read()["tool"]["poetry"] pyproject: dict[str, Any] = poetry.file.read()
content = pyproject["tool"]["poetry"]
assert "group" in content assert "group" in content
assert SelfCommand.ADDITIONAL_PACKAGE_GROUP in content["group"] assert SelfCommand.ADDITIONAL_PACKAGE_GROUP in content["group"]
assert "dependencies" in content["group"][SelfCommand.ADDITIONAL_PACKAGE_GROUP] assert "dependencies" in content["group"][SelfCommand.ADDITIONAL_PACKAGE_GROUP]
return content["group"][SelfCommand.ADDITIONAL_PACKAGE_GROUP]["dependencies"] dependencies = content["group"][SelfCommand.ADDITIONAL_PACKAGE_GROUP][
"dependencies"
]
assert isinstance(dependencies, TOMLTable)
return dependencies
...@@ -125,7 +125,7 @@ priority : primary ...@@ -125,7 +125,7 @@ priority : primary
), ),
) )
def test_source_show_given_priority( def test_source_show_given_priority(
tester_all_types: CommandTester, source_str: Source, request: pytest.FixtureRequest tester_all_types: CommandTester, source_str: str, request: pytest.FixtureRequest
) -> None: ) -> None:
source = request.getfixturevalue(source_str) source = request.getfixturevalue(source_str)
tester_all_types.execute(f"{source.name}") tester_all_types.execute(f"{source.name}")
......
...@@ -8,6 +8,7 @@ from typing import cast ...@@ -8,6 +8,7 @@ from typing import cast
import pytest import pytest
from packaging.utils import canonicalize_name
from poetry.core.constraints.version import Version from poetry.core.constraints.version import Version
from poetry.core.packages.package import Package from poetry.core.packages.package import Package
...@@ -232,7 +233,7 @@ def test_add_constraint_with_extras( ...@@ -232,7 +233,7 @@ def test_add_constraint_with_extras(
extra_name: str, extra_name: str,
) -> None: ) -> None:
cachy1 = get_package("cachy", "0.1.0") cachy1 = get_package("cachy", "0.1.0")
cachy1.extras = {"msgpack": [get_dependency("msgpack-python")]} cachy1.extras = {canonicalize_name("msgpack"): [get_dependency("msgpack-python")]}
msgpack_dep = get_dependency("msgpack-python", ">=0.5 <0.6", optional=True) msgpack_dep = get_dependency("msgpack-python", ">=0.5 <0.6", optional=True)
cachy1.add_dependency(msgpack_dep) cachy1.add_dependency(msgpack_dep)
...@@ -492,14 +493,14 @@ Writing lock file ...@@ -492,14 +493,14 @@ Writing lock file
assert "demo" in content["dependencies"] assert "demo" in content["dependencies"]
expected = { expected_content: dict[str, Any] = {
"git": "ssh://git@github.com/demo/demo.git", "git": "ssh://git@github.com/demo/demo.git",
"rev": "develop", "rev": "develop",
} }
if editable: if editable:
expected["develop"] = True expected_content["develop"] = True
assert content["dependencies"]["demo"] == expected assert content["dependencies"]["demo"] == expected_content
@pytest.mark.parametrize( @pytest.mark.parametrize(
...@@ -519,6 +520,7 @@ def test_add_directory_constraint( ...@@ -519,6 +520,7 @@ def test_add_directory_constraint(
path = "../git/github.com/demo/demo" path = "../git/github.com/demo/demo"
tester.execute(f"{path}" if not editable else f"-e {path}") tester.execute(f"{path}" if not editable else f"-e {path}")
demo_path = app.poetry.file.path.parent.joinpath(path).resolve().as_posix()
expected = f"""\ expected = f"""\
Updating dependencies Updating dependencies
...@@ -527,7 +529,7 @@ Resolving dependencies... ...@@ -527,7 +529,7 @@ Resolving dependencies...
Package operations: 2 installs, 0 updates, 0 removals Package operations: 2 installs, 0 updates, 0 removals
• Installing pendulum (1.4.4) • Installing pendulum (1.4.4)
• Installing demo (0.1.2 {app.poetry.file.parent.joinpath(path).resolve().as_posix()}) • Installing demo (0.1.2 {demo_path})
Writing lock file Writing lock file
""" """
...@@ -541,11 +543,11 @@ Writing lock file ...@@ -541,11 +543,11 @@ Writing lock file
assert "demo" in content["dependencies"] assert "demo" in content["dependencies"]
expected = {"path": path} expected_content: dict[str, Any] = {"path": path}
if editable: if editable:
expected["develop"] = True expected_content["develop"] = True
assert content["dependencies"]["demo"] == expected assert content["dependencies"]["demo"] == expected_content
@pytest.mark.parametrize( @pytest.mark.parametrize(
...@@ -562,6 +564,7 @@ def test_add_directory_with_poetry( ...@@ -562,6 +564,7 @@ def test_add_directory_with_poetry(
path = "../git/github.com/demo/pyproject-demo" path = "../git/github.com/demo/pyproject-demo"
tester.execute(f"{path}") tester.execute(f"{path}")
demo_path = app.poetry.file.path.parent.joinpath(path).resolve().as_posix()
expected = f"""\ expected = f"""\
Updating dependencies Updating dependencies
...@@ -570,7 +573,7 @@ Resolving dependencies... ...@@ -570,7 +573,7 @@ Resolving dependencies...
Package operations: 2 installs, 0 updates, 0 removals Package operations: 2 installs, 0 updates, 0 removals
• Installing pendulum (1.4.4) • Installing pendulum (1.4.4)
• Installing demo (0.1.2 {app.poetry.file.parent.joinpath(path).resolve().as_posix()}) • Installing demo (0.1.2 {demo_path})
Writing lock file Writing lock file
""" """
...@@ -595,6 +598,7 @@ def test_add_file_constraint_wheel( ...@@ -595,6 +598,7 @@ def test_add_file_constraint_wheel(
path = "../distributions/demo-0.1.0-py2.py3-none-any.whl" path = "../distributions/demo-0.1.0-py2.py3-none-any.whl"
tester.execute(f"{path}") tester.execute(f"{path}")
demo_path = app.poetry.file.path.parent.joinpath(path).resolve().as_posix()
expected = f"""\ expected = f"""\
Updating dependencies Updating dependencies
...@@ -603,7 +607,7 @@ Resolving dependencies... ...@@ -603,7 +607,7 @@ Resolving dependencies...
Package operations: 2 installs, 0 updates, 0 removals Package operations: 2 installs, 0 updates, 0 removals
• Installing pendulum (1.4.4) • Installing pendulum (1.4.4)
• Installing demo (0.1.0 {app.poetry.file.parent.joinpath(path).resolve().as_posix()}) • Installing demo (0.1.0 {demo_path})
Writing lock file Writing lock file
""" """
...@@ -633,6 +637,7 @@ def test_add_file_constraint_sdist( ...@@ -633,6 +637,7 @@ def test_add_file_constraint_sdist(
path = "../distributions/demo-0.1.0.tar.gz" path = "../distributions/demo-0.1.0.tar.gz"
tester.execute(f"{path}") tester.execute(f"{path}")
demo_path = app.poetry.file.path.parent.joinpath(path).resolve().as_posix()
expected = f"""\ expected = f"""\
Updating dependencies Updating dependencies
...@@ -641,7 +646,7 @@ Resolving dependencies... ...@@ -641,7 +646,7 @@ Resolving dependencies...
Package operations: 2 installs, 0 updates, 0 removals Package operations: 2 installs, 0 updates, 0 removals
• Installing pendulum (1.4.4) • Installing pendulum (1.4.4)
• Installing demo (0.1.0 {app.poetry.file.parent.joinpath(path).resolve().as_posix()}) • Installing demo (0.1.0 {demo_path})
Writing lock file Writing lock file
""" """
...@@ -665,7 +670,7 @@ def test_add_constraint_with_extras_option( ...@@ -665,7 +670,7 @@ def test_add_constraint_with_extras_option(
extra_name: str, extra_name: str,
) -> None: ) -> None:
cachy2 = get_package("cachy", "0.2.0") cachy2 = get_package("cachy", "0.2.0")
cachy2.extras = {"msgpack": [get_dependency("msgpack-python")]} cachy2.extras = {canonicalize_name("msgpack"): [get_dependency("msgpack-python")]}
msgpack_dep = get_dependency("msgpack-python", ">=0.5 <0.6", optional=True) msgpack_dep = get_dependency("msgpack-python", ">=0.5 <0.6", optional=True)
cachy2.add_dependency(msgpack_dep) cachy2.add_dependency(msgpack_dep)
...@@ -777,9 +782,9 @@ Package operations: 4 installs, 0 updates, 0 removals ...@@ -777,9 +782,9 @@ Package operations: 4 installs, 0 updates, 0 removals
Writing lock file Writing lock file
""" """
# Order might be different, split into lines and compare the overall output. # Order might be different, split into lines and compare the overall output.
expected = set(expected.splitlines()) expected_lines = set(expected.splitlines())
output = set(tester.io.fetch_output().splitlines()) output = set(tester.io.fetch_output().splitlines())
assert output == expected assert output == expected_lines
assert isinstance(tester.command, InstallerCommand) assert isinstance(tester.command, InstallerCommand)
assert tester.command.installer.executor.installations_count == 4 assert tester.command.installer.executor.installations_count == 4
......
...@@ -11,6 +11,7 @@ from deepdiff import DeepDiff ...@@ -11,6 +11,7 @@ from deepdiff import DeepDiff
from poetry.core.pyproject.exceptions import PyProjectException from poetry.core.pyproject.exceptions import PyProjectException
from poetry.config.config_source import ConfigSource from poetry.config.config_source import ConfigSource
from poetry.console.commands.install import InstallCommand
from poetry.factory import Factory from poetry.factory import Factory
from tests.conftest import Config from tests.conftest import Config
...@@ -97,7 +98,7 @@ virtualenvs.prefer-active-python = false ...@@ -97,7 +98,7 @@ virtualenvs.prefer-active-python = false
virtualenvs.prompt = "{{project_name}}-py{{python_version}}" virtualenvs.prompt = "{{project_name}}-py{{python_version}}"
""" """
assert config.set_config_source.call_count == 0 assert config.set_config_source.call_count == 0 # type: ignore[attr-defined]
assert tester.io.fetch_output() == expected assert tester.io.fetch_output() == expected
...@@ -150,7 +151,7 @@ virtualenvs.prefer-active-python = false ...@@ -150,7 +151,7 @@ virtualenvs.prefer-active-python = false
virtualenvs.prompt = "{{project_name}}-py{{python_version}}" virtualenvs.prompt = "{{project_name}}-py{{python_version}}"
""" """
assert config.set_config_source.call_count == 1 assert config.set_config_source.call_count == 1 # type: ignore[attr-defined]
assert tester.io.fetch_output() == expected assert tester.io.fetch_output() == expected
...@@ -243,9 +244,9 @@ def test_config_installer_parallel( ...@@ -243,9 +244,9 @@ def test_config_installer_parallel(
tester.execute("--local installer.parallel") tester.execute("--local installer.parallel")
assert tester.io.fetch_output().strip() == "true" assert tester.io.fetch_output().strip() == "true"
workers = command_tester_factory( command = command_tester_factory("install")._command
"install" assert isinstance(command, InstallCommand)
)._command._installer._executor._max_workers workers = command.installer._executor._max_workers
assert workers > 1 assert workers > 1
tester.io.clear_output() tester.io.clear_output()
...@@ -253,9 +254,9 @@ def test_config_installer_parallel( ...@@ -253,9 +254,9 @@ def test_config_installer_parallel(
tester.execute("--local installer.parallel") tester.execute("--local installer.parallel")
assert tester.io.fetch_output().strip() == "false" assert tester.io.fetch_output().strip() == "false"
workers = command_tester_factory( command = command_tester_factory("install")._command
"install" assert isinstance(command, InstallCommand)
)._command._installer._executor._max_workers workers = command.installer._executor._max_workers
assert workers == 1 assert workers == 1
......
...@@ -27,7 +27,10 @@ def tester(command_tester_factory: CommandTesterFactory) -> CommandTester: ...@@ -27,7 +27,10 @@ def tester(command_tester_factory: CommandTesterFactory) -> CommandTester:
def verify_project_directory( def verify_project_directory(
path: Path, package_name: str, package_path: str, include_from: str | None = None path: Path,
package_name: str,
package_path: str | Path,
include_from: str | None = None,
) -> Poetry: ) -> Poetry:
package_path = Path(package_path) package_path = Path(package_path)
assert path.is_dir() assert path.is_dir()
...@@ -203,7 +206,8 @@ def test_respect_prefer_active_on_new( ...@@ -203,7 +206,8 @@ def test_respect_prefer_active_on_new(
if GET_PYTHON_VERSION_ONELINER in cmd: if GET_PYTHON_VERSION_ONELINER in cmd:
return "1.1.1" return "1.1.1"
return orig_check_output(cmd, *_, **__) output: str = orig_check_output(cmd, *_, **__)
return output
mocker.patch("subprocess.check_output", side_effect=mock_check_output) mocker.patch("subprocess.check_output", side_effect=mock_check_output)
......
from __future__ import annotations from __future__ import annotations
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from typing import Any
from typing import cast
import pytest import pytest
import tomlkit import tomlkit
...@@ -14,6 +16,7 @@ from tests.helpers import get_package ...@@ -14,6 +16,7 @@ from tests.helpers import get_package
if TYPE_CHECKING: if TYPE_CHECKING:
from cleo.testers.command_tester import CommandTester from cleo.testers.command_tester import CommandTester
from pytest_mock import MockerFixture from pytest_mock import MockerFixture
from tomlkit import TOMLDocument
from poetry.poetry import Poetry from poetry.poetry import Poetry
from poetry.repositories import Repository from poetry.repositories import Repository
...@@ -56,17 +59,18 @@ def test_remove_without_specific_group_removes_from_all_groups( ...@@ -56,17 +59,18 @@ def test_remove_without_specific_group_removes_from_all_groups(
repo.add_package(Package("foo", "2.0.0")) repo.add_package(Package("foo", "2.0.0"))
repo.add_package(Package("baz", "1.0.0")) repo.add_package(Package("baz", "1.0.0"))
content = app.poetry.file.read() pyproject: dict[str, Any] = app.poetry.file.read()
groups_content = tomlkit.parse("""\ groups_content: dict[str, Any] = tomlkit.parse("""\
[tool.poetry.group.bar.dependencies] [tool.poetry.group.bar.dependencies]
foo = "^2.0.0" foo = "^2.0.0"
baz = "^1.0.0" baz = "^1.0.0"
""") """)
content["tool"]["poetry"]["dependencies"]["foo"] = "^2.0.0" pyproject["tool"]["poetry"]["dependencies"]["foo"] = "^2.0.0"
content["tool"]["poetry"]["group"] = groups_content["tool"]["poetry"]["group"] pyproject["tool"]["poetry"]["group"] = groups_content["tool"]["poetry"]["group"]
app.poetry.file.write(content) pyproject = cast("TOMLDocument", pyproject)
app.poetry.file.write(pyproject)
app.poetry.package.add_dependency(Factory.create_dependency("foo", "^2.0.0")) app.poetry.package.add_dependency(Factory.create_dependency("foo", "^2.0.0"))
app.poetry.package.add_dependency( app.poetry.package.add_dependency(
...@@ -78,7 +82,9 @@ baz = "^1.0.0" ...@@ -78,7 +82,9 @@ baz = "^1.0.0"
tester.execute("foo") tester.execute("foo")
content = app.poetry.file.read()["tool"]["poetry"] pyproject = app.poetry.file.read()
pyproject = cast("dict[str, Any]", pyproject)
content = pyproject["tool"]["poetry"]
assert "foo" not in content["dependencies"] assert "foo" not in content["dependencies"]
assert "foo" not in content["group"]["bar"]["dependencies"] assert "foo" not in content["group"]["bar"]["dependencies"]
assert "baz" in content["group"]["bar"]["dependencies"] assert "baz" in content["group"]["bar"]["dependencies"]
...@@ -89,7 +95,8 @@ baz = "^1.0.0" ...@@ -89,7 +95,8 @@ baz = "^1.0.0"
baz = "^1.0.0" baz = "^1.0.0"
""" """
string_content = content.as_string() pyproject = cast("TOMLDocument", pyproject)
string_content = pyproject.as_string()
if "\r\n" in string_content: if "\r\n" in string_content:
# consistent line endings # consistent line endings
expected = expected.replace("\n", "\r\n") expected = expected.replace("\n", "\r\n")
...@@ -111,17 +118,18 @@ def test_remove_without_specific_group_removes_from_specific_groups( ...@@ -111,17 +118,18 @@ def test_remove_without_specific_group_removes_from_specific_groups(
repo.add_package(Package("foo", "2.0.0")) repo.add_package(Package("foo", "2.0.0"))
repo.add_package(Package("baz", "1.0.0")) repo.add_package(Package("baz", "1.0.0"))
content = app.poetry.file.read() pyproject: dict[str, Any] = app.poetry.file.read()
groups_content = tomlkit.parse("""\ groups_content: dict[str, Any] = tomlkit.parse("""\
[tool.poetry.group.bar.dependencies] [tool.poetry.group.bar.dependencies]
foo = "^2.0.0" foo = "^2.0.0"
baz = "^1.0.0" baz = "^1.0.0"
""") """)
content["tool"]["poetry"]["dependencies"]["foo"] = "^2.0.0" pyproject["tool"]["poetry"]["dependencies"]["foo"] = "^2.0.0"
content["tool"]["poetry"]["group"] = groups_content["tool"]["poetry"]["group"] pyproject["tool"]["poetry"]["group"] = groups_content["tool"]["poetry"]["group"]
app.poetry.file.write(content) pyproject = cast("TOMLDocument", pyproject)
app.poetry.file.write(pyproject)
app.poetry.package.add_dependency(Factory.create_dependency("foo", "^2.0.0")) app.poetry.package.add_dependency(Factory.create_dependency("foo", "^2.0.0"))
app.poetry.package.add_dependency( app.poetry.package.add_dependency(
...@@ -133,7 +141,9 @@ baz = "^1.0.0" ...@@ -133,7 +141,9 @@ baz = "^1.0.0"
tester.execute("foo --group bar") tester.execute("foo --group bar")
content = app.poetry.file.read()["tool"]["poetry"] pyproject = app.poetry.file.read()
pyproject = cast("dict[str, Any]", pyproject)
content = pyproject["tool"]["poetry"]
assert "foo" in content["dependencies"] assert "foo" in content["dependencies"]
assert "foo" not in content["group"]["bar"]["dependencies"] assert "foo" not in content["group"]["bar"]["dependencies"]
assert "baz" in content["group"]["bar"]["dependencies"] assert "baz" in content["group"]["bar"]["dependencies"]
...@@ -166,9 +176,9 @@ def test_remove_does_not_live_empty_groups( ...@@ -166,9 +176,9 @@ def test_remove_does_not_live_empty_groups(
repo.add_package(Package("foo", "2.0.0")) repo.add_package(Package("foo", "2.0.0"))
repo.add_package(Package("baz", "1.0.0")) repo.add_package(Package("baz", "1.0.0"))
content = app.poetry.file.read() content: dict[str, Any] = app.poetry.file.read()
groups_content = tomlkit.parse("""\ groups_content: dict[str, Any] = tomlkit.parse("""\
[tool.poetry.group.bar.dependencies] [tool.poetry.group.bar.dependencies]
foo = "^2.0.0" foo = "^2.0.0"
baz = "^1.0.0" baz = "^1.0.0"
...@@ -176,6 +186,7 @@ baz = "^1.0.0" ...@@ -176,6 +186,7 @@ baz = "^1.0.0"
""") """)
content["tool"]["poetry"]["dependencies"]["foo"] = "^2.0.0" content["tool"]["poetry"]["dependencies"]["foo"] = "^2.0.0"
content["tool"]["poetry"]["group"] = groups_content["tool"]["poetry"]["group"] content["tool"]["poetry"]["group"] = groups_content["tool"]["poetry"]["group"]
content = cast("TOMLDocument", content)
app.poetry.file.write(content) app.poetry.file.write(content)
app.poetry.package.add_dependency(Factory.create_dependency("foo", "^2.0.0")) app.poetry.package.add_dependency(Factory.create_dependency("foo", "^2.0.0"))
...@@ -188,10 +199,12 @@ baz = "^1.0.0" ...@@ -188,10 +199,12 @@ baz = "^1.0.0"
tester.execute("foo baz --group bar") tester.execute("foo baz --group bar")
content = app.poetry.file.read()["tool"]["poetry"] pyproject: dict[str, Any] = app.poetry.file.read()
content = pyproject["tool"]["poetry"]
assert "foo" in content["dependencies"] assert "foo" in content["dependencies"]
assert "foo" not in content["group"]["bar"]["dependencies"] assert "foo" not in content["group"]["bar"]["dependencies"]
assert "baz" not in content["group"]["bar"]["dependencies"] assert "baz" not in content["group"]["bar"]["dependencies"]
content = cast("TOMLDocument", content)
assert "[tool.poetry.group.bar]" not in content.as_string() assert "[tool.poetry.group.bar]" not in content.as_string()
assert "[tool.poetry.group]" not in content.as_string() assert "[tool.poetry.group]" not in content.as_string()
...@@ -210,19 +223,20 @@ def test_remove_canonicalized_named_removes_dependency_correctly( ...@@ -210,19 +223,20 @@ def test_remove_canonicalized_named_removes_dependency_correctly(
repo.add_package(Package("foo-bar", "2.0.0")) repo.add_package(Package("foo-bar", "2.0.0"))
repo.add_package(Package("baz", "1.0.0")) repo.add_package(Package("baz", "1.0.0"))
content = app.poetry.file.read() pyproject: dict[str, Any] = app.poetry.file.read()
groups_content = tomlkit.parse("""\ groups_content: dict[str, Any] = tomlkit.parse("""\
[tool.poetry.group.bar.dependencies] [tool.poetry.group.bar.dependencies]
foo-bar = "^2.0.0" foo-bar = "^2.0.0"
baz = "^1.0.0" baz = "^1.0.0"
""") """)
content["tool"]["poetry"]["dependencies"]["foo-bar"] = "^2.0.0" pyproject["tool"]["poetry"]["dependencies"]["foo-bar"] = "^2.0.0"
content["tool"]["poetry"].value._insert_after( pyproject["tool"]["poetry"].value._insert_after(
"dependencies", "group", groups_content["tool"]["poetry"]["group"] "dependencies", "group", groups_content["tool"]["poetry"]["group"]
) )
app.poetry.file.write(content) pyproject = cast("TOMLDocument", pyproject)
app.poetry.file.write(pyproject)
app.poetry.package.add_dependency(Factory.create_dependency("foo-bar", "^2.0.0")) app.poetry.package.add_dependency(Factory.create_dependency("foo-bar", "^2.0.0"))
app.poetry.package.add_dependency( app.poetry.package.add_dependency(
...@@ -234,7 +248,9 @@ baz = "^1.0.0" ...@@ -234,7 +248,9 @@ baz = "^1.0.0"
tester.execute("Foo_Bar") tester.execute("Foo_Bar")
content = app.poetry.file.read()["tool"]["poetry"] pyproject = app.poetry.file.read()
pyproject = cast("dict[str, Any]", pyproject)
content = pyproject["tool"]["poetry"]
assert "foo-bar" not in content["dependencies"] assert "foo-bar" not in content["dependencies"]
assert "foo-bar" not in content["group"]["bar"]["dependencies"] assert "foo-bar" not in content["group"]["bar"]["dependencies"]
assert "baz" in content["group"]["bar"]["dependencies"] assert "baz" in content["group"]["bar"]["dependencies"]
...@@ -245,7 +261,8 @@ baz = "^1.0.0" ...@@ -245,7 +261,8 @@ baz = "^1.0.0"
baz = "^1.0.0" baz = "^1.0.0"
""" """
string_content = content.as_string() pyproject = cast("TOMLDocument", pyproject)
string_content = pyproject.as_string()
if "\r\n" in string_content: if "\r\n" in string_content:
# consistent line endings # consistent line endings
expected = expected.replace("\n", "\r\n") expected = expected.replace("\n", "\r\n")
......
...@@ -7,6 +7,8 @@ from typing import TYPE_CHECKING ...@@ -7,6 +7,8 @@ from typing import TYPE_CHECKING
import pytest import pytest
from poetry.console.commands.shell import ShellCommand
if TYPE_CHECKING: if TYPE_CHECKING:
from cleo.testers.command_tester import CommandTester from cleo.testers.command_tester import CommandTester
...@@ -25,6 +27,7 @@ def test_shell(tester: CommandTester, mocker: MockerFixture) -> None: ...@@ -25,6 +27,7 @@ def test_shell(tester: CommandTester, mocker: MockerFixture) -> None:
tester.execute() tester.execute()
assert isinstance(tester.command, ShellCommand)
expected_output = f"Spawning shell within {tester.command.env.path}\n" expected_output = f"Spawning shell within {tester.command.env.path}\n"
shell_activate.assert_called_once_with(tester.command.env) shell_activate.assert_called_once_with(tester.command.env)
...@@ -38,6 +41,7 @@ def test_shell_already_active(tester: CommandTester, mocker: MockerFixture) -> N ...@@ -38,6 +41,7 @@ def test_shell_already_active(tester: CommandTester, mocker: MockerFixture) -> N
tester.execute() tester.execute()
assert isinstance(tester.command, ShellCommand)
expected_output = ( expected_output = (
f"Virtual environment already activated: {tester.command.env.path}\n" f"Virtual environment already activated: {tester.command.env.path}\n"
) )
...@@ -72,6 +76,7 @@ def test__is_venv_activated( ...@@ -72,6 +76,7 @@ def test__is_venv_activated(
prefix: str, prefix: str,
expected: bool, expected: bool,
) -> None: ) -> None:
assert isinstance(tester.command, ShellCommand)
mocker.patch.object(tester.command.env, "_path", Path("foobar")) mocker.patch.object(tester.command.env, "_path", Path("foobar"))
mocker.patch("sys.prefix", prefix) mocker.patch("sys.prefix", prefix)
......
...@@ -10,6 +10,7 @@ from poetry.core.packages.dependency_group import DependencyGroup ...@@ -10,6 +10,7 @@ from poetry.core.packages.dependency_group import DependencyGroup
from poetry.factory import Factory from poetry.factory import Factory
from poetry.utils._compat import tomllib from poetry.utils._compat import tomllib
from tests.helpers import MOCK_DEFAULT_GIT_REVISION from tests.helpers import MOCK_DEFAULT_GIT_REVISION
from tests.helpers import TestLocker
from tests.helpers import get_package from tests.helpers import get_package
...@@ -49,6 +50,7 @@ def test_show_basic_with_installed_packages( ...@@ -49,6 +50,7 @@ def test_show_basic_with_installed_packages(
installed.add_package(pendulum_200) installed.add_package(pendulum_200)
installed.add_package(pytest_373) installed.add_package(pytest_373)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -125,6 +127,7 @@ def _configure_project_with_groups(poetry: Poetry, installed: Repository) -> Non ...@@ -125,6 +127,7 @@ def _configure_project_with_groups(poetry: Poetry, installed: Repository) -> Non
installed.add_package(pendulum_200) installed.add_package(pendulum_200)
installed.add_package(pytest_373) installed.add_package(pytest_373)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -267,6 +270,7 @@ def test_show_basic_with_installed_packages_single( ...@@ -267,6 +270,7 @@ def test_show_basic_with_installed_packages_single(
installed.add_package(cachy_010) installed.add_package(cachy_010)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -308,6 +312,7 @@ def test_show_basic_with_installed_packages_single_canonicalized( ...@@ -308,6 +312,7 @@ def test_show_basic_with_installed_packages_single_canonicalized(
installed.add_package(foo_bar) installed.add_package(foo_bar)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -352,6 +357,8 @@ def test_show_basic_with_not_installed_packages_non_decorated( ...@@ -352,6 +357,8 @@ def test_show_basic_with_not_installed_packages_non_decorated(
pendulum_200.description = "Pendulum package" pendulum_200.description = "Pendulum package"
installed.add_package(cachy_010) installed.add_package(cachy_010)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -406,6 +413,8 @@ def test_show_basic_with_not_installed_packages_decorated( ...@@ -406,6 +413,8 @@ def test_show_basic_with_not_installed_packages_decorated(
pendulum_200.description = "Pendulum package" pendulum_200.description = "Pendulum package"
installed.add_package(cachy_010) installed.add_package(cachy_010)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -474,6 +483,7 @@ def test_show_latest_non_decorated( ...@@ -474,6 +483,7 @@ def test_show_latest_non_decorated(
repo.add_package(pendulum_200) repo.add_package(pendulum_200)
repo.add_package(pendulum_201) repo.add_package(pendulum_201)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -542,6 +552,7 @@ def test_show_latest_decorated( ...@@ -542,6 +552,7 @@ def test_show_latest_decorated(
repo.add_package(pendulum_200) repo.add_package(pendulum_200)
repo.add_package(pendulum_201) repo.add_package(pendulum_201)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -609,6 +620,7 @@ def test_show_outdated( ...@@ -609,6 +620,7 @@ def test_show_outdated(
repo.add_package(cachy_020) repo.add_package(cachy_020)
repo.add_package(pendulum_200) repo.add_package(pendulum_200)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -661,6 +673,7 @@ def test_show_outdated_with_only_up_to_date_packages( ...@@ -661,6 +673,7 @@ def test_show_outdated_with_only_up_to_date_packages(
installed.add_package(cachy_020) installed.add_package(cachy_020)
repo.add_package(cachy_020) repo.add_package(cachy_020)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -719,6 +732,7 @@ def test_show_outdated_has_prerelease_but_not_allowed( ...@@ -719,6 +732,7 @@ def test_show_outdated_has_prerelease_but_not_allowed(
repo.add_package(cachy_020) repo.add_package(cachy_020)
repo.add_package(pendulum_200) repo.add_package(pendulum_200)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -792,6 +806,7 @@ def test_show_outdated_has_prerelease_and_allowed( ...@@ -792,6 +806,7 @@ def test_show_outdated_has_prerelease_and_allowed(
repo.add_package(cachy_020) repo.add_package(cachy_020)
repo.add_package(pendulum_200) repo.add_package(pendulum_200)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -859,6 +874,7 @@ def test_show_outdated_formatting( ...@@ -859,6 +874,7 @@ def test_show_outdated_formatting(
repo.add_package(pendulum_200) repo.add_package(pendulum_200)
repo.add_package(pendulum_201) repo.add_package(pendulum_201)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -940,6 +956,7 @@ def test_show_outdated_local_dependencies( ...@@ -940,6 +956,7 @@ def test_show_outdated_local_dependencies(
repo.add_package(cachy_030) repo.add_package(cachy_030)
repo.add_package(pendulum_200) repo.add_package(pendulum_200)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -1051,6 +1068,7 @@ def test_show_outdated_git_dev_dependency( ...@@ -1051,6 +1068,7 @@ def test_show_outdated_git_dev_dependency(
repo.add_package(pendulum_200) repo.add_package(pendulum_200)
repo.add_package(pytest) repo.add_package(pytest)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -1147,6 +1165,7 @@ def test_show_outdated_no_dev_git_dev_dependency( ...@@ -1147,6 +1165,7 @@ def test_show_outdated_no_dev_git_dev_dependency(
repo.add_package(pendulum_200) repo.add_package(pendulum_200)
repo.add_package(pytest) repo.add_package(pytest)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -1229,6 +1248,7 @@ def test_show_hides_incompatible_package( ...@@ -1229,6 +1248,7 @@ def test_show_hides_incompatible_package(
installed.add_package(pendulum_200) installed.add_package(pendulum_200)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -1283,6 +1303,7 @@ def test_show_all_shows_incompatible_package( ...@@ -1283,6 +1303,7 @@ def test_show_all_shows_incompatible_package(
installed.add_package(pendulum_200) installed.add_package(pendulum_200)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -1338,6 +1359,7 @@ def test_show_hides_incompatible_package_with_duplicate( ...@@ -1338,6 +1359,7 @@ def test_show_hides_incompatible_package_with_duplicate(
Factory.create_dependency("cachy", {"version": "0.1.1", "platform": "darwin"}) Factory.create_dependency("cachy", {"version": "0.1.1", "platform": "darwin"})
) )
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -1386,6 +1408,7 @@ def test_show_all_shows_all_duplicates( ...@@ -1386,6 +1408,7 @@ def test_show_all_shows_all_duplicates(
Factory.create_dependency("cachy", {"version": "0.1.1", "platform": "darwin"}) Factory.create_dependency("cachy", {"version": "0.1.1", "platform": "darwin"})
) )
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -1444,6 +1467,7 @@ def test_show_non_dev_with_basic_installed_packages( ...@@ -1444,6 +1467,7 @@ def test_show_non_dev_with_basic_installed_packages(
installed.add_package(pendulum_200) installed.add_package(pendulum_200)
installed.add_package(pytest_373) installed.add_package(pytest_373)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -1516,6 +1540,7 @@ def test_show_with_group_only( ...@@ -1516,6 +1540,7 @@ def test_show_with_group_only(
installed.add_package(pendulum_200) installed.add_package(pendulum_200)
installed.add_package(pytest_373) installed.add_package(pytest_373)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -1587,6 +1612,7 @@ def test_show_with_optional_group( ...@@ -1587,6 +1612,7 @@ def test_show_with_optional_group(
installed.add_package(pendulum_200) installed.add_package(pendulum_200)
installed.add_package(pytest_373) installed.add_package(pytest_373)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -1657,6 +1683,7 @@ def test_show_tree( ...@@ -1657,6 +1683,7 @@ def test_show_tree(
installed.add_package(cachy2) installed.add_package(cachy2)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -1714,6 +1741,7 @@ def test_show_tree_no_dev( ...@@ -1714,6 +1741,7 @@ def test_show_tree_no_dev(
pytest = get_package("pytest", "6.1.1") pytest = get_package("pytest", "6.1.1")
installed.add_package(pytest) installed.add_package(pytest)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -1781,6 +1809,7 @@ def test_show_tree_why_package( ...@@ -1781,6 +1809,7 @@ def test_show_tree_why_package(
c = get_package("c", "0.0.1") c = get_package("c", "0.0.1")
installed.add_package(c) installed.add_package(c)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -1840,6 +1869,7 @@ def test_show_tree_why( ...@@ -1840,6 +1869,7 @@ def test_show_tree_why(
c = get_package("c", "0.0.1") c = get_package("c", "0.0.1")
installed.add_package(c) installed.add_package(c)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -1897,6 +1927,7 @@ def test_show_required_by_deps( ...@@ -1897,6 +1927,7 @@ def test_show_required_by_deps(
installed.add_package(cachy2) installed.add_package(cachy2)
installed.add_package(pendulum) installed.add_package(pendulum)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -1990,6 +2021,7 @@ def test_show_dependency_installed_from_git_in_dev( ...@@ -1990,6 +2021,7 @@ def test_show_dependency_installed_from_git_in_dev(
repo.add_package(pendulum_200) repo.add_package(pendulum_200)
# The git package is the one that gets into the lockfile. # The git package is the one that gets into the lockfile.
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -2050,6 +2082,7 @@ def test_url_dependency_is_not_outdated_by_repository_package( ...@@ -2050,6 +2082,7 @@ def test_url_dependency_is_not_outdated_by_repository_package(
demo_100 = get_package("demo", "1.0.0") demo_100 = get_package("demo", "1.0.0")
repo.add_package(demo_100) repo.add_package(demo_100)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -2092,6 +2125,7 @@ def test_show_top_level( ...@@ -2092,6 +2125,7 @@ def test_show_top_level(
installed.add_package(cachy2) installed.add_package(cachy2)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -2146,6 +2180,7 @@ def test_show_top_level_with_explicitly_defined_depenancy( ...@@ -2146,6 +2180,7 @@ def test_show_top_level_with_explicitly_defined_depenancy(
installed.add_package(a) installed.add_package(a)
installed.add_package(b) installed.add_package(b)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
...@@ -2218,6 +2253,8 @@ def test_show_outdated_missing_directory_dependency( ...@@ -2218,6 +2253,8 @@ def test_show_outdated_missing_directory_dependency(
) -> None: ) -> None:
with (poetry.pyproject.file.path.parent / "poetry.lock").open(mode="rb") as f: with (poetry.pyproject.file.path.parent / "poetry.lock").open(mode="rb") as f:
data = tomllib.load(f) data = tomllib.load(f)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(data) poetry.locker.mock_lock_data(data)
poetry.package.add_dependency( poetry.package.add_dependency(
......
...@@ -76,6 +76,7 @@ def test_short_version_update(tester: CommandTester) -> None: ...@@ -76,6 +76,7 @@ def test_short_version_update(tester: CommandTester) -> None:
def test_dry_run(tester: CommandTester) -> None: def test_dry_run(tester: CommandTester) -> None:
assert isinstance(tester.command, VersionCommand)
old_pyproject = tester.command.poetry.file.path.read_text() old_pyproject = tester.command.poetry.file.path.read_text()
tester.execute("--dry-run major") tester.execute("--dry-run major")
......
...@@ -11,6 +11,7 @@ from cleo.testers.application_tester import ApplicationTester ...@@ -11,6 +11,7 @@ from cleo.testers.application_tester import ApplicationTester
from poetry.console.application import Application from poetry.console.application import Application
from poetry.console.commands.command import Command from poetry.console.commands.command import Command
from poetry.plugins.application_plugin import ApplicationPlugin from poetry.plugins.application_plugin import ApplicationPlugin
from poetry.repositories.cached_repository import CachedRepository
from poetry.utils.authenticator import Authenticator from poetry.utils.authenticator import Authenticator
from tests.helpers import mock_metadata_entry_points from tests.helpers import mock_metadata_entry_points
...@@ -99,6 +100,7 @@ def test_application_verify_source_cache_flag(disable_cache: bool) -> None: ...@@ -99,6 +100,7 @@ def test_application_verify_source_cache_flag(disable_cache: bool) -> None:
assert app.poetry.pool.repositories assert app.poetry.pool.repositories
for repo in app.poetry.pool.repositories: for repo in app.poetry.pool.repositories:
assert isinstance(repo, CachedRepository)
assert repo._disable_cache == disable_cache assert repo._disable_cache == disable_cache
......
...@@ -104,8 +104,10 @@ def mock_clone( ...@@ -104,8 +104,10 @@ def mock_clone(
) -> MockDulwichRepo: ) -> MockDulwichRepo:
# Checking source to determine which folder we need to copy # Checking source to determine which folder we need to copy
parsed = ParsedUrl.parse(url) parsed = ParsedUrl.parse(url)
assert parsed.pathname is not None
path = re.sub(r"(.git)?$", "", parsed.pathname.lstrip("/")) path = re.sub(r"(.git)?$", "", parsed.pathname.lstrip("/"))
assert parsed.resource is not None
folder = FIXTURE_PATH / "git" / parsed.resource / path folder = FIXTURE_PATH / "git" / parsed.resource / path
if not source_root: if not source_root:
...@@ -130,9 +132,9 @@ class TestExecutor(Executor): ...@@ -130,9 +132,9 @@ class TestExecutor(Executor):
def __init__(self, *args: Any, **kwargs: Any) -> None: def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self._installs = [] self._installs: list[Package] = []
self._updates = [] self._updates: list[Package] = []
self._uninstalls = [] self._uninstalls: list[Package] = []
@property @property
def installations(self) -> list[Package]: def installations(self) -> list[Package]:
...@@ -146,12 +148,14 @@ class TestExecutor(Executor): ...@@ -146,12 +148,14 @@ class TestExecutor(Executor):
def removals(self) -> list[Package]: def removals(self) -> list[Package]:
return self._uninstalls return self._uninstalls
def _do_execute_operation(self, operation: Operation) -> None: def _do_execute_operation(self, operation: Operation) -> int:
super()._do_execute_operation(operation) rc = super()._do_execute_operation(operation)
if not operation.skipped: if not operation.skipped:
getattr(self, f"_{operation.job_type}s").append(operation.package) getattr(self, f"_{operation.job_type}s").append(operation.package)
return rc
def _execute_install(self, operation: Operation) -> int: def _execute_install(self, operation: Operation) -> int:
return 0 return 0
...@@ -168,6 +172,7 @@ class PoetryTestApplication(Application): ...@@ -168,6 +172,7 @@ class PoetryTestApplication(Application):
self._poetry = poetry self._poetry = poetry
def reset_poetry(self) -> None: def reset_poetry(self) -> None:
assert self._poetry is not None
poetry = self._poetry poetry = self._poetry
self._poetry = Factory().create_poetry(self._poetry.file.path.parent) self._poetry = Factory().create_poetry(self._poetry.file.path.parent)
self._poetry.set_pool(poetry.pool) self._poetry.set_pool(poetry.pool)
...@@ -181,7 +186,7 @@ class TestLocker(Locker): ...@@ -181,7 +186,7 @@ class TestLocker(Locker):
# class name begins 'Test': tell pytest that it does not contain testcases. # class name begins 'Test': tell pytest that it does not contain testcases.
__test__ = False __test__ = False
def __init__(self, lock: Path, local_config: dict) -> None: def __init__(self, lock: Path, local_config: dict[str, Any]) -> None:
self._lock = lock self._lock = lock
self._local_config = local_config self._local_config = local_config
self._lock_data = None self._lock_data = None
...@@ -201,7 +206,7 @@ class TestLocker(Locker): ...@@ -201,7 +206,7 @@ class TestLocker(Locker):
return self return self
def mock_lock_data(self, data: dict) -> None: def mock_lock_data(self, data: dict[str, Any]) -> None:
self.locked() self.locked()
self._lock_data = data self._lock_data = data
...@@ -256,14 +261,16 @@ def isolated_environment( ...@@ -256,14 +261,16 @@ def isolated_environment(
def make_entry_point_from_plugin( def make_entry_point_from_plugin(
name: str, cls: type[Any], dist: metadata.Distribution | None = None name: str, cls: type[Any], dist: metadata.Distribution | None = None
) -> metadata.EntryPoint: ) -> metadata.EntryPoint:
group: str | None = getattr(cls, "group", None)
ep = metadata.EntryPoint( ep = metadata.EntryPoint(
name=name, name=name,
group=getattr(cls, "group", None), group=group, # type: ignore[arg-type]
value=f"{cls.__module__}:{cls.__name__}", value=f"{cls.__module__}:{cls.__name__}",
) )
if dist: if dist:
return ep._for(dist) ep = ep._for(dist) # type: ignore[attr-defined,no-untyped-call]
return ep
return ep return ep
......
...@@ -39,6 +39,8 @@ from tests.repositories.test_pypi_repository import MockRepository ...@@ -39,6 +39,8 @@ from tests.repositories.test_pypi_repository import MockRepository
if TYPE_CHECKING: if TYPE_CHECKING:
from collections.abc import Iterator
import httpretty import httpretty
from httpretty.core import HTTPrettyRequest from httpretty.core import HTTPrettyRequest
...@@ -144,7 +146,7 @@ def mock_file_downloads( ...@@ -144,7 +146,7 @@ def mock_file_downloads(
) -> None: ) -> None:
def callback( def callback(
request: HTTPrettyRequest, uri: str, headers: dict[str, Any] request: HTTPrettyRequest, uri: str, headers: dict[str, Any]
) -> list[int | dict[str, Any] | str]: ) -> list[int | dict[str, Any] | bytes]:
name = Path(urlparse(uri).path).name name = Path(urlparse(uri).path).name
fixture = Path(__file__).parent.parent.joinpath( fixture = Path(__file__).parent.parent.joinpath(
...@@ -184,7 +186,7 @@ def copy_wheel(tmp_path: Path, fixture_dir: FixtureDirGetter) -> Callable[[], Pa ...@@ -184,7 +186,7 @@ def copy_wheel(tmp_path: Path, fixture_dir: FixtureDirGetter) -> Callable[[], Pa
@pytest.fixture @pytest.fixture
def wheel(copy_wheel: Callable[[], Path]) -> Path: def wheel(copy_wheel: Callable[[], Path]) -> Iterator[Path]:
archive = copy_wheel() archive = copy_wheel()
yield archive yield archive
...@@ -267,9 +269,9 @@ Package operations: 4 installs, 1 update, 1 removal ...@@ -267,9 +269,9 @@ Package operations: 4 installs, 1 update, 1 removal
• Installing demo (0.1.0 master) • Installing demo (0.1.0 master)
""" """
expected = set(expected.splitlines()) expected_lines = set(expected.splitlines())
output = set(io.fetch_output().splitlines()) output_lines = set(io.fetch_output().splitlines())
assert output == expected assert output_lines == expected_lines
assert wheel_install.call_count == 5 assert wheel_install.call_count == 5
# Two pip uninstalls: one for the remove operation one for the update operation # Two pip uninstalls: one for the remove operation one for the update operation
assert len(env.executed) == 2 assert len(env.executed) == 2
...@@ -513,9 +515,9 @@ Package operations: 1 install, 0 updates, 0 removals ...@@ -513,9 +515,9 @@ Package operations: 1 install, 0 updates, 0 removals
• Installing cleo (1.0.0a5) • Installing cleo (1.0.0a5)
""" """
expected = set(expected.splitlines()) expected_lines = set(expected.splitlines())
output = set(io_not_decorated.fetch_output().splitlines()) output_lines = set(io_not_decorated.fetch_output().splitlines())
assert output == expected assert output_lines == expected_lines
assert return_code == 0 assert return_code == 0
...@@ -622,10 +624,14 @@ def verify_installed_distribution( ...@@ -622,10 +624,14 @@ def verify_installed_distribution(
assert metadata["Name"] == package.name assert metadata["Name"] == package.name
assert metadata["Version"] == package.version.text assert metadata["Version"] == package.version.text
direct_url_file = distribution._path.joinpath("direct_url.json") direct_url_file = distribution._path.joinpath( # type: ignore[attr-defined]
"direct_url.json"
)
if url_reference is not None: if url_reference is not None:
record_file = distribution._path.joinpath("RECORD") record_file = distribution._path.joinpath( # type: ignore[attr-defined]
"RECORD"
)
with open(record_file, encoding="utf-8", newline="") as f: with open(record_file, encoding="utf-8", newline="") as f:
reader = csv.reader(f) reader = csv.reader(f)
rows = list(reader) rows = list(reader)
...@@ -855,6 +861,7 @@ def test_executor_should_write_pep610_url_references_for_wheel_urls( ...@@ -855,6 +861,7 @@ def test_executor_should_write_pep610_url_references_for_wheel_urls(
if is_artifact_cached: if is_artifact_cached:
download_spy.assert_not_called() download_spy.assert_not_called()
else: else:
assert package.source_url is not None
download_spy.assert_called_once_with( download_spy.assert_called_once_with(
mocker.ANY, operation, Link(package.source_url) mocker.ANY, operation, Link(package.source_url)
) )
...@@ -948,6 +955,7 @@ def test_executor_should_write_pep610_url_references_for_non_wheel_urls( ...@@ -948,6 +955,7 @@ def test_executor_should_write_pep610_url_references_for_non_wheel_urls(
mock_prepare.assert_not_called() mock_prepare.assert_not_called()
if expect_artifact_download: if expect_artifact_download:
assert package.source_url is not None
download_spy.assert_called_once_with( download_spy.assert_called_once_with(
mocker.ANY, operation, Link(package.source_url) mocker.ANY, operation, Link(package.source_url)
) )
...@@ -1053,6 +1061,7 @@ def test_executor_should_write_pep610_url_references_for_editable_git( ...@@ -1053,6 +1061,7 @@ def test_executor_should_write_pep610_url_references_for_editable_git(
executor = Executor(tmp_venv, pool, config, io) executor = Executor(tmp_venv, pool, config, io)
executor._chef = chef executor._chef = chef
executor.execute([Install(package)]) executor.execute([Install(package)])
assert package.source_url is not None
verify_installed_distribution( verify_installed_distribution(
tmp_venv, tmp_venv,
package, package,
...@@ -1218,9 +1227,9 @@ Package operations: 1 install, 0 updates, 0 removals ...@@ -1218,9 +1227,9 @@ Package operations: 1 install, 0 updates, 0 removals
• Installing simple-project (1.2.3 {directory_package.source_url}) • Installing simple-project (1.2.3 {directory_package.source_url})
""" """
expected = set(expected.splitlines()) expected_lines = set(expected.splitlines())
output = set(io.fetch_output().splitlines()) output_lines = set(io.fetch_output().splitlines())
assert output == expected assert output_lines == expected_lines
assert return_code == 0 assert return_code == 0
assert mock_create_poetry.call_count == 1 assert mock_create_poetry.call_count == 1
assert mock_sdist_builder.call_count == 0 assert mock_sdist_builder.call_count == 0
...@@ -1281,6 +1290,7 @@ Package operations: 1 install, 0 updates, 0 removals ...@@ -1281,6 +1290,7 @@ Package operations: 1 install, 0 updates, 0 removals
Error on stdout Error on stdout
""" """
assert directory_package.source_url is not None
if editable: if editable:
pip_command = "pip wheel --use-pep517 --editable" pip_command = "pip wheel --use-pep517 --editable"
requirement = directory_package.source_url requirement = directory_package.source_url
......
...@@ -711,6 +711,7 @@ def test_run_install_with_synchronization( ...@@ -711,6 +711,7 @@ def test_run_install_with_synchronization(
*managed_reserved_package_names, *managed_reserved_package_names,
} }
assert isinstance(installer.executor, Executor)
assert {r.name for r in installer.executor.removals} == expected_removals assert {r.name for r in installer.executor.removals} == expected_removals
...@@ -906,6 +907,7 @@ def test_run_with_optional_and_python_restricted_dependencies( ...@@ -906,6 +907,7 @@ def test_run_with_optional_and_python_restricted_dependencies(
# We should only have 2 installs: # We should only have 2 installs:
# C,D since python version is not compatible # C,D since python version is not compatible
# with B's python constraint and A is optional # with B's python constraint and A is optional
assert isinstance(installer.executor, Executor)
assert installer.executor.installations_count == 2 assert installer.executor.installations_count == 2
assert installer.executor.installations[0].name == "d" assert installer.executor.installations[0].name == "d"
assert installer.executor.installations[1].name == "c" assert installer.executor.installations[1].name == "c"
...@@ -953,6 +955,7 @@ def test_run_with_optional_and_platform_restricted_dependencies( ...@@ -953,6 +955,7 @@ def test_run_with_optional_and_platform_restricted_dependencies(
# We should only have 2 installs: # We should only have 2 installs:
# C,D since the mocked python version is not compatible # C,D since the mocked python version is not compatible
# with B's python constraint and A is optional # with B's python constraint and A is optional
assert isinstance(installer.executor, Executor)
assert installer.executor.installations_count == 2 assert installer.executor.installations_count == 2
assert installer.executor.installations[0].name == "d" assert installer.executor.installations[0].name == "d"
assert installer.executor.installations[1].name == "c" assert installer.executor.installations[1].name == "c"
...@@ -1297,6 +1300,7 @@ def test_run_installs_with_local_poetry_directory_and_skip_directory_flag( ...@@ -1297,6 +1300,7 @@ def test_run_installs_with_local_poetry_directory_and_skip_directory_flag(
assert locker.written_data == expected assert locker.written_data == expected
assert isinstance(installer.executor, Executor)
directory_installs = [ directory_installs = [
p.name for p in installer.executor.installations if p.source_type == "directory" p.name for p in installer.executor.installations if p.source_type == "directory"
] ]
...@@ -1564,6 +1568,7 @@ def test_run_install_duplicate_dependencies_different_constraints( ...@@ -1564,6 +1568,7 @@ def test_run_install_duplicate_dependencies_different_constraints(
assert locker.written_data == expected assert locker.written_data == expected
assert isinstance(installer.executor, Executor)
installs = installer.executor.installations installs = installer.executor.installations
assert installer.executor.installations_count == 3 assert installer.executor.installations_count == 3
assert installs[0] == package_c12 assert installs[0] == package_c12
...@@ -1982,6 +1987,7 @@ def test_installer_required_extras_should_not_be_removed_when_updating_single_de ...@@ -1982,6 +1987,7 @@ def test_installer_required_extras_should_not_be_removed_when_updating_single_de
locker.locked(True) locker.locked(True)
locker.mock_lock_data(locker.written_data) locker.mock_lock_data(locker.written_data)
assert isinstance(installer.executor, Executor)
for pkg in installer.executor.installations: for pkg in installer.executor.installations:
installed.add_package(pkg) installed.add_package(pkg)
...@@ -2240,6 +2246,7 @@ def test_run_installs_with_same_version_url_files( ...@@ -2240,6 +2246,7 @@ def test_run_installs_with_same_version_url_files(
expected = fixture("with-same-version-url-dependencies") expected = fixture("with-same-version-url-dependencies")
assert locker.written_data == expected assert locker.written_data == expected
assert isinstance(installer.executor, Executor)
assert installer.executor.installations_count == 2 assert installer.executor.installations_count == 2
demo_package = next(p for p in installer.executor.installations if p.name == "demo") demo_package = next(p for p in installer.executor.installations if p.name == "demo")
assert demo_package.source_url == urls[env_platform] assert demo_package.source_url == urls[env_platform]
...@@ -2456,6 +2463,7 @@ def test_installer_should_use_the_locked_version_of_git_dependencies( ...@@ -2456,6 +2463,7 @@ def test_installer_should_use_the_locked_version_of_git_dependencies(
result = installer.run() result = installer.run()
assert result == 0 assert result == 0
assert isinstance(installer.executor, Executor)
assert installer.executor.installations[-1] == Package( assert installer.executor.installations[-1] == Package(
"demo", "demo",
"0.1.1", "0.1.1",
...@@ -2498,6 +2506,7 @@ def test_installer_should_use_the_locked_version_of_git_dependencies_with_extras ...@@ -2498,6 +2506,7 @@ def test_installer_should_use_the_locked_version_of_git_dependencies_with_extras
result = installer.run() result = installer.run()
assert result == 0 assert result == 0
assert isinstance(installer.executor, Executor)
assert len(installer.executor.installations) == 3 assert len(installer.executor.installations) == 3
assert installer.executor.installations[-1] == Package( assert installer.executor.installations[-1] == Package(
"demo", "demo",
...@@ -2537,6 +2546,7 @@ def test_installer_should_use_the_locked_version_of_git_dependencies_without_ref ...@@ -2537,6 +2546,7 @@ def test_installer_should_use_the_locked_version_of_git_dependencies_without_ref
result = installer.run() result = installer.run()
assert result == 0 assert result == 0
assert isinstance(installer.executor, Executor)
assert len(installer.executor.installations) == 2 assert len(installer.executor.installations) == 2
assert installer.executor.installations[-1] == Package( assert installer.executor.installations[-1] == Package(
"demo", "demo",
...@@ -2640,6 +2650,7 @@ def test_installer_distinguishes_locked_packages_by_source( ...@@ -2640,6 +2650,7 @@ def test_installer_distinguishes_locked_packages_by_source(
) )
source_reference = None if env_platform == "darwin" else "pytorch" source_reference = None if env_platform == "darwin" else "pytorch"
assert isinstance(installer.executor, Executor)
assert len(installer.executor.installations) == 1 assert len(installer.executor.installations) == 1
assert installer.executor.installations[0] == Package( assert installer.executor.installations[0] == Package(
"torch", "torch",
......
...@@ -7,6 +7,7 @@ from copy import deepcopy ...@@ -7,6 +7,7 @@ from copy import deepcopy
from hashlib import sha1 from hashlib import sha1
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from typing import Iterator
import pytest import pytest
...@@ -79,9 +80,11 @@ def source_directory_name(source_url: str) -> str: ...@@ -79,9 +80,11 @@ def source_directory_name(source_url: str) -> str:
@pytest.fixture(scope="module") @pytest.fixture(scope="module")
def local_repo(tmp_path_factory: TempPathFactory, source_directory_name: str) -> Repo: def local_repo(
tmp_path_factory: TempPathFactory, source_directory_name: str
) -> Iterator[Repo]:
with Repo.init( with Repo.init(
tmp_path_factory.mktemp("src") / source_directory_name, mkdir=True str(tmp_path_factory.mktemp("src") / source_directory_name), mkdir=True
) as repo: ) as repo:
yield repo yield repo
...@@ -103,7 +106,8 @@ def remote_refs(_remote_refs: FetchPackResult) -> FetchPackResult: ...@@ -103,7 +106,8 @@ def remote_refs(_remote_refs: FetchPackResult) -> FetchPackResult:
@pytest.fixture(scope="module") @pytest.fixture(scope="module")
def remote_default_ref(_remote_refs: FetchPackResult) -> bytes: def remote_default_ref(_remote_refs: FetchPackResult) -> bytes:
return _remote_refs.symrefs[b"HEAD"] ref: bytes = _remote_refs.symrefs[b"HEAD"]
return ref
@pytest.fixture(scope="module") @pytest.fixture(scope="module")
...@@ -269,7 +273,11 @@ def test_system_git_fallback_on_http_401( ...@@ -269,7 +273,11 @@ def test_system_git_fallback_on_http_401(
source_url: str, source_url: str,
) -> None: ) -> None:
spy = mocker.spy(Git, "_clone_legacy") spy = mocker.spy(Git, "_clone_legacy")
mocker.patch.object(Git, "_clone", side_effect=HTTPUnauthorized(None, None)) mocker.patch.object(
Git,
"_clone",
side_effect=HTTPUnauthorized(None, None), # type: ignore[no-untyped-call]
)
with Git.clone(url=source_url, branch="0.1") as repo: with Git.clone(url=source_url, branch="0.1") as repo:
path = Path(repo.path) path = Path(repo.path)
......
from __future__ import annotations from __future__ import annotations
from pathlib import Path from pathlib import Path
from typing import Any
from poetry.factory import Factory from poetry.factory import Factory
from poetry.toml import TOMLFile from poetry.toml import TOMLFile
...@@ -10,19 +11,21 @@ FIXTURE_DIR = Path(__file__).parent / "fixtures" / "source" ...@@ -10,19 +11,21 @@ FIXTURE_DIR = Path(__file__).parent / "fixtures" / "source"
def test_pyproject_toml_valid_legacy() -> None: def test_pyproject_toml_valid_legacy() -> None:
toml = TOMLFile(FIXTURE_DIR / "complete_valid_legacy.toml").read() toml: dict[str, Any] = TOMLFile(FIXTURE_DIR / "complete_valid_legacy.toml").read()
content = toml["tool"]["poetry"] content = toml["tool"]["poetry"]
assert Factory.validate(content) == {"errors": [], "warnings": []} assert Factory.validate(content) == {"errors": [], "warnings": []}
def test_pyproject_toml_valid() -> None: def test_pyproject_toml_valid() -> None:
toml = TOMLFile(FIXTURE_DIR / "complete_valid.toml").read() toml: dict[str, Any] = TOMLFile(FIXTURE_DIR / "complete_valid.toml").read()
content = toml["tool"]["poetry"] content = toml["tool"]["poetry"]
assert Factory.validate(content) == {"errors": [], "warnings": []} assert Factory.validate(content) == {"errors": [], "warnings": []}
def test_pyproject_toml_invalid_priority() -> None: def test_pyproject_toml_invalid_priority() -> None:
toml = TOMLFile(FIXTURE_DIR / "complete_invalid_priority.toml").read() toml: dict[str, Any] = TOMLFile(
FIXTURE_DIR / "complete_invalid_priority.toml"
).read()
content = toml["tool"]["poetry"] content = toml["tool"]["poetry"]
assert Factory.validate(content) == { assert Factory.validate(content) == {
"errors": [ "errors": [
...@@ -34,7 +37,7 @@ def test_pyproject_toml_invalid_priority() -> None: ...@@ -34,7 +37,7 @@ def test_pyproject_toml_invalid_priority() -> None:
def test_pyproject_toml_invalid_priority_legacy_and_new() -> None: def test_pyproject_toml_invalid_priority_legacy_and_new() -> None:
toml = TOMLFile( toml: dict[str, Any] = TOMLFile(
FIXTURE_DIR / "complete_invalid_priority_legacy_and_new.toml" FIXTURE_DIR / "complete_invalid_priority_legacy_and_new.toml"
).read() ).read()
content = toml["tool"]["poetry"] content = toml["tool"]["poetry"]
......
...@@ -7,6 +7,7 @@ import shutil ...@@ -7,6 +7,7 @@ import shutil
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from typing import Iterator
import pytest import pytest
...@@ -72,7 +73,7 @@ def env_manager(simple_poetry: Poetry) -> EnvManager: ...@@ -72,7 +73,7 @@ def env_manager(simple_poetry: Poetry) -> EnvManager:
@pytest.fixture @pytest.fixture
def tmp_venv(tmp_path: Path, env_manager: EnvManager) -> VirtualEnv: def tmp_venv(tmp_path: Path, env_manager: EnvManager) -> Iterator[VirtualEnv]:
venv_path = tmp_path / "venv" venv_path = tmp_path / "venv"
env_manager.build_venv(venv_path) env_manager.build_venv(venv_path)
......
...@@ -13,6 +13,7 @@ from typing import TYPE_CHECKING ...@@ -13,6 +13,7 @@ from typing import TYPE_CHECKING
import pytest import pytest
from packaging.utils import canonicalize_name
from poetry.core.constraints.version import Version from poetry.core.constraints.version import Version
from poetry.core.packages.package import Package from poetry.core.packages.package import Package
from poetry.core.packages.project_package import ProjectPackage from poetry.core.packages.project_package import ProjectPackage
...@@ -234,7 +235,7 @@ content-hash = "c3d07fca33fba542ef2b2a4d75bf5b48d892d21a830e2ad9c952ba5123a52f77 ...@@ -234,7 +235,7 @@ content-hash = "c3d07fca33fba542ef2b2a4d75bf5b48d892d21a830e2ad9c952ba5123a52f77
assert len(package.requires) == 3 assert len(package.requires) == 3
assert len(package.extras) == 2 assert len(package.extras) == 2
lockfile_dep = package.extras["filecache"][0] lockfile_dep = package.extras[canonicalize_name("filecache")][0]
assert lockfile_dep.name == "lockfile" assert lockfile_dep.name == "lockfile"
...@@ -297,7 +298,7 @@ content-hash = "123456789" ...@@ -297,7 +298,7 @@ content-hash = "123456789"
assert len(package.requires) == 1 assert len(package.requires) == 1
assert len(package.extras) == 1 assert len(package.extras) == 1
dependency_b = package.extras["b"][0] dependency_b = package.extras[canonicalize_name("b")][0]
assert dependency_b.name == "b" assert dependency_b.name == "b"
assert dependency_b.extras == frozenset({"c"}) assert dependency_b.extras == frozenset({"c"})
...@@ -308,7 +309,7 @@ content-hash = "123456789" ...@@ -308,7 +309,7 @@ content-hash = "123456789"
assert len(package.requires) == 1 assert len(package.requires) == 1
assert len(package.extras) == 1 assert len(package.extras) == 1
dependency_c = package.extras["c"][0] dependency_c = package.extras[canonicalize_name("c")][0]
assert dependency_c.name == "c" assert dependency_c.name == "c"
assert dependency_c.extras == frozenset() assert dependency_c.extras == frozenset()
...@@ -361,7 +362,7 @@ content-hash = "123456789" ...@@ -361,7 +362,7 @@ content-hash = "123456789"
assert len(package.requires) == 1 assert len(package.requires) == 1
assert len(package.extras) == 1 assert len(package.extras) == 1
dependency_b = package.extras["b"][0] dependency_b = package.extras[canonicalize_name("b")][0]
assert dependency_b.name == "b" assert dependency_b.name == "b"
...@@ -515,7 +516,7 @@ def test_lock_packages_with_null_description( ...@@ -515,7 +516,7 @@ def test_lock_packages_with_null_description(
locker: Locker, root: ProjectPackage locker: Locker, root: ProjectPackage
) -> None: ) -> None:
package_a = get_package("A", "1.0.0") package_a = get_package("A", "1.0.0")
package_a.description = None package_a.description = None # type: ignore[assignment]
locker.set_lock_data(root, [package_a]) locker.set_lock_data(root, [package_a])
...@@ -551,7 +552,7 @@ def test_lock_file_should_not_have_mixed_types( ...@@ -551,7 +552,7 @@ def test_lock_file_should_not_have_mixed_types(
Factory.create_dependency("B", {"version": ">=1.0.0", "optional": True}) Factory.create_dependency("B", {"version": ">=1.0.0", "optional": True})
) )
package_a.requires[-1].activate() package_a.requires[-1].activate()
package_a.extras["foo"] = [get_dependency("B", ">=1.0.0")] package_a.extras[canonicalize_name("foo")] = [get_dependency("B", ">=1.0.0")]
locker.set_lock_data(root, [package_a]) locker.set_lock_data(root, [package_a])
...@@ -723,8 +724,8 @@ def test_root_extras_dependencies_are_ordered( ...@@ -723,8 +724,8 @@ def test_root_extras_dependencies_are_ordered(
package_third = Factory.create_dependency("third", "1.0.0", root_dir=fixture_base) package_third = Factory.create_dependency("third", "1.0.0", root_dir=fixture_base)
root.extras = { root.extras = {
"C": [package_third, package_second, package_first], canonicalize_name("C"): [package_third, package_second, package_first],
"B": [package_first, package_second, package_third], canonicalize_name("B"): [package_first, package_second, package_third],
} }
locker.set_lock_data(root, []) locker.set_lock_data(root, [])
...@@ -733,8 +734,8 @@ def test_root_extras_dependencies_are_ordered( ...@@ -733,8 +734,8 @@ def test_root_extras_dependencies_are_ordered(
package = [] package = []
[extras] [extras]
B = ["first", "second", "third"] b = ["first", "second", "third"]
C = ["first", "second", "third"] c = ["first", "second", "third"]
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
...@@ -951,8 +952,8 @@ def test_locker_dumps_dependency_extras_in_correct_order( ...@@ -951,8 +952,8 @@ def test_locker_dumps_dependency_extras_in_correct_order(
package_third = Factory.create_dependency("third", "1.0.0", root_dir=fixture_base) package_third = Factory.create_dependency("third", "1.0.0", root_dir=fixture_base)
package_a.extras = { package_a.extras = {
"C": [package_third, package_second, package_first], canonicalize_name("C"): [package_third, package_second, package_first],
"B": [package_first, package_second, package_third], canonicalize_name("B"): [package_first, package_second, package_third],
} }
locker.set_lock_data(root, [package_a]) locker.set_lock_data(root, [package_a])
...@@ -972,8 +973,8 @@ python-versions = "*" ...@@ -972,8 +973,8 @@ python-versions = "*"
files = [] files = []
[package.extras] [package.extras]
B = ["first (==1.0.0)", "second (==1.0.0)", "third (==1.0.0)"] b = ["first (==1.0.0)", "second (==1.0.0)", "third (==1.0.0)"]
C = ["first (==1.0.0)", "second (==1.0.0)", "third (==1.0.0)"] c = ["first (==1.0.0)", "second (==1.0.0)", "third (==1.0.0)"]
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
......
...@@ -6,6 +6,7 @@ from typing import TYPE_CHECKING ...@@ -6,6 +6,7 @@ from typing import TYPE_CHECKING
import pytest import pytest
from cleo.io.buffered_io import BufferedIO from cleo.io.buffered_io import BufferedIO
from poetry.core.constraints.version import Version
from poetry.core.packages.project_package import ProjectPackage from poetry.core.packages.project_package import ProjectPackage
from poetry.packages.locker import Locker from poetry.packages.locker import Locker
...@@ -43,7 +44,7 @@ class MyCommandPlugin(ApplicationPlugin): ...@@ -43,7 +44,7 @@ class MyCommandPlugin(ApplicationPlugin):
class InvalidPlugin: class InvalidPlugin:
def activate(self, poetry: Poetry, io: IO) -> None: def activate(self, poetry: Poetry, io: IO) -> None:
io.write_line("Updating version") io.write_line("Updating version")
poetry.package.version = "9.9.9" poetry.package.version = Version.parse("9.9.9")
@pytest.fixture @pytest.fixture
......
...@@ -7,6 +7,7 @@ from typing import Any ...@@ -7,6 +7,7 @@ from typing import Any
import pytest import pytest
from cleo.io.null_io import NullIO from cleo.io.null_io import NullIO
from packaging.utils import canonicalize_name
from poetry.core.packages.dependency import Dependency from poetry.core.packages.dependency import Dependency
from poetry.core.packages.directory_dependency import DirectoryDependency from poetry.core.packages.directory_dependency import DirectoryDependency
from poetry.core.packages.file_dependency import FileDependency from poetry.core.packages.file_dependency import FileDependency
...@@ -681,7 +682,7 @@ def test_complete_package_with_extras_preserves_source_name( ...@@ -681,7 +682,7 @@ def test_complete_package_with_extras_preserves_source_name(
package_b = Package("B", "1.0") package_b = Package("B", "1.0")
dep = get_dependency("B", "^1.0", optional=True) dep = get_dependency("B", "^1.0", optional=True)
package_a.add_dependency(dep) package_a.add_dependency(dep)
package_a.extras = {"foo": [dep]} package_a.extras = {canonicalize_name("foo"): [dep]}
repository.add_package(package_a) repository.add_package(package_a)
repository.add_package(package_b) repository.add_package(package_b)
...@@ -710,7 +711,7 @@ def test_complete_package_fetches_optional_vcs_dependency_only_if_requested( ...@@ -710,7 +711,7 @@ def test_complete_package_fetches_optional_vcs_dependency_only_if_requested(
) )
package = Package("A", "1.0", features=["foo"] if with_extra else []) package = Package("A", "1.0", features=["foo"] if with_extra else [])
package.add_dependency(optional_vcs_dependency) package.add_dependency(optional_vcs_dependency)
package.extras["foo"] = [optional_vcs_dependency] package.extras[canonicalize_name("foo")] = [optional_vcs_dependency]
repository.add_package(package) repository.add_package(package)
spy = mocker.spy(provider, "_search_for_vcs") spy = mocker.spy(provider, "_search_for_vcs")
......
...@@ -17,6 +17,7 @@ from poetry.core.packages.vcs_dependency import VCSDependency ...@@ -17,6 +17,7 @@ from poetry.core.packages.vcs_dependency import VCSDependency
from poetry.core.version.markers import parse_marker from poetry.core.version.markers import parse_marker
from poetry.factory import Factory from poetry.factory import Factory
from poetry.installation.operations import Update
from poetry.packages import DependencyPackage from poetry.packages import DependencyPackage
from poetry.puzzle import Solver from poetry.puzzle import Solver
from poetry.puzzle.exceptions import SolverProblemError from poetry.puzzle.exceptions import SolverProblemError
...@@ -93,6 +94,7 @@ def check_solver_result( ...@@ -93,6 +94,7 @@ def check_solver_result(
ops = transaction.calculate_operations(synchronize=synchronize) ops = transaction.calculate_operations(synchronize=synchronize)
for op in ops: for op in ops:
if op.job_type == "update": if op.job_type == "update":
assert isinstance(op, Update)
result.append( result.append(
{ {
"job": "update", "job": "update",
...@@ -449,7 +451,7 @@ def test_solver_solves_optional_and_compatible_packages( ...@@ -449,7 +451,7 @@ def test_solver_solves_optional_and_compatible_packages(
solver: Solver, repo: Repository, package: ProjectPackage solver: Solver, repo: Repository, package: ProjectPackage
) -> None: ) -> None:
set_package_python_versions(solver.provider, "~3.4") set_package_python_versions(solver.provider, "~3.4")
package.extras["foo"] = [get_dependency("B")] package.extras[canonicalize_name("foo")] = [get_dependency("B")]
package.add_dependency( package.add_dependency(
Factory.create_dependency("A", {"version": "*", "python": "^3.4"}) Factory.create_dependency("A", {"version": "*", "python": "^3.4"})
) )
...@@ -490,7 +492,7 @@ def test_solver_does_not_return_extras_if_not_requested( ...@@ -490,7 +492,7 @@ def test_solver_does_not_return_extras_if_not_requested(
package_b = get_package("B", "1.0") package_b = get_package("B", "1.0")
package_c = get_package("C", "1.0") package_c = get_package("C", "1.0")
package_b.extras = {"foo": [get_dependency("C", "^1.0")]} package_b.extras = {canonicalize_name("foo"): [get_dependency("C", "^1.0")]}
repo.add_package(package_a) repo.add_package(package_a)
repo.add_package(package_b) repo.add_package(package_b)
...@@ -521,7 +523,7 @@ def test_solver_returns_extras_if_requested( ...@@ -521,7 +523,7 @@ def test_solver_returns_extras_if_requested(
dep = get_dependency("C", "^1.0", optional=True) dep = get_dependency("C", "^1.0", optional=True)
dep.marker = parse_marker("extra == 'foo'") dep.marker = parse_marker("extra == 'foo'")
package_b.extras = {"foo": [dep]} package_b.extras = {canonicalize_name("foo"): [dep]}
package_b.add_dependency(dep) package_b.add_dependency(dep)
repo.add_package(package_a) repo.add_package(package_a)
...@@ -548,7 +550,7 @@ def test_solver_returns_extras_only_requested( ...@@ -548,7 +550,7 @@ def test_solver_returns_extras_only_requested(
solver: Solver, solver: Solver,
repo: Repository, repo: Repository,
package: ProjectPackage, package: ProjectPackage,
enabled_extra: bool | None, enabled_extra: str | None,
) -> None: ) -> None:
extras = [enabled_extra] if enabled_extra is not None else [] extras = [enabled_extra] if enabled_extra is not None else []
...@@ -563,14 +565,17 @@ def test_solver_returns_extras_only_requested( ...@@ -563,14 +565,17 @@ def test_solver_returns_extras_only_requested(
package_c20 = get_package("C", "2.0") package_c20 = get_package("C", "2.0")
dep10 = get_dependency("C", "1.0", optional=True) dep10 = get_dependency("C", "1.0", optional=True)
dep10._in_extras.append("one") dep10._in_extras.append(canonicalize_name("one"))
dep10.marker = parse_marker("extra == 'one'") dep10.marker = parse_marker("extra == 'one'")
dep20 = get_dependency("C", "2.0", optional=True) dep20 = get_dependency("C", "2.0", optional=True)
dep20._in_extras.append("two") dep20._in_extras.append(canonicalize_name("two"))
dep20.marker = parse_marker("extra == 'two'") dep20.marker = parse_marker("extra == 'two'")
package_b.extras = {"one": [dep10], "two": [dep20]} package_b.extras = {
canonicalize_name("one"): [dep10],
canonicalize_name("two"): [dep20],
}
package_b.add_dependency(dep10) package_b.add_dependency(dep10)
package_b.add_dependency(dep20) package_b.add_dependency(dep20)
...@@ -619,10 +624,13 @@ def test_solver_returns_extras_when_multiple_extras_use_same_dependency( ...@@ -619,10 +624,13 @@ def test_solver_returns_extras_when_multiple_extras_use_same_dependency(
package_c = get_package("C", "1.0") package_c = get_package("C", "1.0")
dep = get_dependency("C", "*", optional=True) dep = get_dependency("C", "*", optional=True)
dep._in_extras.append("one") dep._in_extras.append(canonicalize_name("one"))
dep._in_extras.append("two") dep._in_extras.append(canonicalize_name("two"))
package_b.extras = {"one": [dep], "two": [dep]} package_b.extras = {
canonicalize_name("one"): [dep],
canonicalize_name("two"): [dep],
}
package_b.add_dependency(dep) package_b.add_dependency(dep)
...@@ -659,7 +667,7 @@ def test_solver_returns_extras_only_requested_nested( ...@@ -659,7 +667,7 @@ def test_solver_returns_extras_only_requested_nested(
solver: Solver, solver: Solver,
repo: Repository, repo: Repository,
package: ProjectPackage, package: ProjectPackage,
enabled_extra: bool | None, enabled_extra: str | None,
) -> None: ) -> None:
package.add_dependency(Factory.create_dependency("A", "*")) package.add_dependency(Factory.create_dependency("A", "*"))
...@@ -669,14 +677,17 @@ def test_solver_returns_extras_only_requested_nested( ...@@ -669,14 +677,17 @@ def test_solver_returns_extras_only_requested_nested(
package_c20 = get_package("C", "2.0") package_c20 = get_package("C", "2.0")
dep10 = get_dependency("C", "1.0", optional=True) dep10 = get_dependency("C", "1.0", optional=True)
dep10._in_extras.append("one") dep10._in_extras.append(canonicalize_name("one"))
dep10.marker = parse_marker("extra == 'one'") dep10.marker = parse_marker("extra == 'one'")
dep20 = get_dependency("C", "2.0", optional=True) dep20 = get_dependency("C", "2.0", optional=True)
dep20._in_extras.append("two") dep20._in_extras.append(canonicalize_name("two"))
dep20.marker = parse_marker("extra == 'two'") dep20.marker = parse_marker("extra == 'two'")
package_b.extras = {"one": [dep10], "two": [dep20]} package_b.extras = {
canonicalize_name("one"): [dep10],
canonicalize_name("two"): [dep20],
}
package_b.add_dependency(dep10) package_b.add_dependency(dep10)
package_b.add_dependency(dep20) package_b.add_dependency(dep20)
...@@ -733,14 +744,14 @@ def test_solver_finds_extras_next_to_non_extras( ...@@ -733,14 +744,14 @@ def test_solver_finds_extras_next_to_non_extras(
"B", {"version": "*", "extras": ["bar"], "markers": "extra == 'foo'"} "B", {"version": "*", "extras": ["bar"], "markers": "extra == 'foo'"}
) )
) )
package_a.extras = {"foo": [get_dependency("B", "*")]} package_a.extras = {canonicalize_name("foo"): [get_dependency("B", "*")]}
# B depends on C; B[bar] depends on D. # B depends on C; B[bar] depends on D.
package_b.add_dependency(Factory.create_dependency("C", "*")) package_b.add_dependency(Factory.create_dependency("C", "*"))
package_b.add_dependency( package_b.add_dependency(
Factory.create_dependency("D", {"version": "*", "markers": 'extra == "bar"'}) Factory.create_dependency("D", {"version": "*", "markers": 'extra == "bar"'})
) )
package_b.extras = {"bar": [get_dependency("D", "*")]} package_b.extras = {canonicalize_name("bar"): [get_dependency("D", "*")]}
repo.add_package(package_a) repo.add_package(package_a)
repo.add_package(package_b) repo.add_package(package_b)
...@@ -769,7 +780,7 @@ def test_solver_merge_extras_into_base_package_multiple_repos_fixes_5727( ...@@ -769,7 +780,7 @@ def test_solver_merge_extras_into_base_package_multiple_repos_fixes_5727(
package.add_dependency(Factory.create_dependency("B", {"version": "*"})) package.add_dependency(Factory.create_dependency("B", {"version": "*"}))
package_a = get_package("A", "1.0") package_a = get_package("A", "1.0")
package_a.extras = {"foo": []} package_a.extras = {canonicalize_name("foo"): []}
repo.add_package(package_a) repo.add_package(package_a)
...@@ -777,7 +788,7 @@ def test_solver_merge_extras_into_base_package_multiple_repos_fixes_5727( ...@@ -777,7 +788,7 @@ def test_solver_merge_extras_into_base_package_multiple_repos_fixes_5727(
package_b.add_dependency(package_a.with_features(["foo"]).to_dependency()) package_b.add_dependency(package_a.with_features(["foo"]).to_dependency())
package_a = Package("A", "1.0", source_type="legacy") package_a = Package("A", "1.0", source_type="legacy")
package_a.extras = {"foo": []} package_a.extras = {canonicalize_name("foo"): []}
repo = Repository("legacy") repo = Repository("legacy")
repo.add_package(package_a) repo.add_package(package_a)
...@@ -810,7 +821,7 @@ def test_solver_returns_extras_if_excluded_by_markers_without_extras( ...@@ -810,7 +821,7 @@ def test_solver_returns_extras_if_excluded_by_markers_without_extras(
# optional dependency with same constraint and no marker except for extra # optional dependency with same constraint and no marker except for extra
dep = get_dependency("B", "^1.0", optional=True) dep = get_dependency("B", "^1.0", optional=True)
dep.marker = parse_marker("extra == 'foo'") dep.marker = parse_marker("extra == 'foo'")
package_a.extras = {"foo": [dep]} package_a.extras = {canonicalize_name("foo"): [dep]}
package_a.add_dependency(dep) package_a.add_dependency(dep)
repo.add_package(package_a) repo.add_package(package_a)
...@@ -1066,7 +1077,7 @@ def test_solver_with_dependency_in_both_main_and_dev_dependencies( ...@@ -1066,7 +1077,7 @@ def test_solver_with_dependency_in_both_main_and_dev_dependencies(
) )
package_a = get_package("A", "1.0") package_a = get_package("A", "1.0")
package_a.extras["foo"] = [get_dependency("C")] package_a.extras[canonicalize_name("foo")] = [get_dependency("C")]
package_a.add_dependency( package_a.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "optional": True}) Factory.create_dependency("C", {"version": "^1.0", "optional": True})
) )
...@@ -1109,7 +1120,7 @@ def test_solver_with_dependency_in_both_main_and_dev_dependencies_with_one_more_ ...@@ -1109,7 +1120,7 @@ def test_solver_with_dependency_in_both_main_and_dev_dependencies_with_one_more_
) )
package_a = get_package("A", "1.0") package_a = get_package("A", "1.0")
package_a.extras["foo"] = [get_dependency("C")] package_a.extras[canonicalize_name("foo")] = [get_dependency("C")]
package_a.add_dependency( package_a.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "optional": True}) Factory.create_dependency("C", {"version": "^1.0", "optional": True})
) )
...@@ -1425,6 +1436,8 @@ def test_solver_duplicate_dependencies_different_sources_types_are_preserved( ...@@ -1425,6 +1436,8 @@ def test_solver_duplicate_dependencies_different_sources_types_are_preserved(
assert op.package.source_type == demo.source_type assert op.package.source_type == demo.source_type
assert op.package.source_reference == DEFAULT_SOURCE_REF assert op.package.source_reference == DEFAULT_SOURCE_REF
assert op.package.source_resolved_reference is not None
assert demo.source_resolved_reference is not None
assert op.package.source_resolved_reference.startswith( assert op.package.source_resolved_reference.startswith(
demo.source_resolved_reference demo.source_resolved_reference
) )
...@@ -1444,7 +1457,6 @@ def test_solver_duplicate_dependencies_different_sources_types_are_preserved( ...@@ -1444,7 +1457,6 @@ def test_solver_duplicate_dependencies_different_sources_types_are_preserved(
assert pypi == dependency_pypi assert pypi == dependency_pypi
assert isinstance(git, VCSDependency) assert isinstance(git, VCSDependency)
assert git.constraint
assert git.constraint != dependency_git.constraint assert git.constraint != dependency_git.constraint
assert (git.name, git.source_type, git.source_url, git.source_reference) == ( assert (git.name, git.source_type, git.source_url, git.source_reference) == (
dependency_git.name, dependency_git.name,
...@@ -1940,6 +1952,7 @@ def test_solver_can_resolve_git_dependencies( ...@@ -1940,6 +1952,7 @@ def test_solver_can_resolve_git_dependencies(
assert op.package.source_type == "git" assert op.package.source_type == "git"
assert op.package.source_reference == DEFAULT_SOURCE_REF assert op.package.source_reference == DEFAULT_SOURCE_REF
assert op.package.source_resolved_reference is not None
assert op.package.source_resolved_reference.startswith("9cf87a2") assert op.package.source_resolved_reference.startswith("9cf87a2")
...@@ -2000,6 +2013,8 @@ def test_solver_can_resolve_git_dependencies_with_ref( ...@@ -2000,6 +2013,8 @@ def test_solver_can_resolve_git_dependencies_with_ref(
source_resolved_reference=MOCK_DEFAULT_GIT_REVISION, source_resolved_reference=MOCK_DEFAULT_GIT_REVISION,
) )
assert demo.source_type is not None
assert demo.source_url is not None
git_config = {demo.source_type: demo.source_url} git_config = {demo.source_type: demo.source_url}
git_config.update(ref) git_config.update(ref)
package.add_dependency(Factory.create_dependency("demo", git_config)) package.add_dependency(Factory.create_dependency("demo", git_config))
...@@ -2015,6 +2030,7 @@ def test_solver_can_resolve_git_dependencies_with_ref( ...@@ -2015,6 +2030,7 @@ def test_solver_can_resolve_git_dependencies_with_ref(
assert op.package.source_type == "git" assert op.package.source_type == "git"
assert op.package.source_reference == ref[list(ref.keys())[0]] assert op.package.source_reference == ref[list(ref.keys())[0]]
assert op.package.source_resolved_reference is not None
assert op.package.source_resolved_reference.startswith("9cf87a2") assert op.package.source_resolved_reference.startswith("9cf87a2")
...@@ -2120,7 +2136,10 @@ def test_solver_does_not_trigger_new_resolution_on_duplicate_dependencies_if_onl ...@@ -2120,7 +2136,10 @@ def test_solver_does_not_trigger_new_resolution_on_duplicate_dependencies_if_onl
) )
package_a = get_package("A", "1.0.0") package_a = get_package("A", "1.0.0")
package_a.extras = {"foo": [dep1], "bar": [dep2]} package_a.extras = {
canonicalize_name("foo"): [dep1],
canonicalize_name("bar"): [dep2],
}
package_a.add_dependency(dep1) package_a.add_dependency(dep1)
package_a.add_dependency(dep2) package_a.add_dependency(dep2)
...@@ -2149,9 +2168,8 @@ def test_solver_does_not_raise_conflict_for_locked_conditional_dependencies( ...@@ -2149,9 +2168,8 @@ def test_solver_does_not_raise_conflict_for_locked_conditional_dependencies(
solver: Solver, repo: Repository, package: ProjectPackage solver: Solver, repo: Repository, package: ProjectPackage
) -> None: ) -> None:
set_package_python_versions(solver.provider, "~2.7 || ^3.4") set_package_python_versions(solver.provider, "~2.7 || ^3.4")
package.add_dependency( dependency_a = Factory.create_dependency("A", {"version": "^1.0", "python": "^3.6"})
Factory.create_dependency("A", {"version": "^1.0", "python": "^3.6"}) package.add_dependency(dependency_a)
)
package.add_dependency(Factory.create_dependency("B", "^1.0")) package.add_dependency(Factory.create_dependency("B", "^1.0"))
package_a = get_package("A", "1.0.0") package_a = get_package("A", "1.0.0")
...@@ -2165,7 +2183,8 @@ def test_solver_does_not_raise_conflict_for_locked_conditional_dependencies( ...@@ -2165,7 +2183,8 @@ def test_solver_does_not_raise_conflict_for_locked_conditional_dependencies(
repo.add_package(package_a) repo.add_package(package_a)
repo.add_package(package_b) repo.add_package(package_b)
solver._locked = Repository("locked", [package_a]) dep_package_a = DependencyPackage(dependency_a, package_a)
solver.provider._locked = {canonicalize_name("A"): [dep_package_a]}
transaction = solver.solve(use_latest=[package_b.name]) transaction = solver.solve(use_latest=[package_b.name])
check_solver_result( check_solver_result(
...@@ -2196,7 +2215,9 @@ def test_solver_returns_extras_if_requested_in_dependencies_and_not_in_root_pack ...@@ -2196,7 +2215,9 @@ def test_solver_returns_extras_if_requested_in_dependencies_and_not_in_root_pack
package_c.add_dependency( package_c.add_dependency(
Factory.create_dependency("D", {"version": "^1.0", "optional": True}) Factory.create_dependency("D", {"version": "^1.0", "optional": True})
) )
package_c.extras = {"foo": [Factory.create_dependency("D", "^1.0")]} package_c.extras = {
canonicalize_name("foo"): [Factory.create_dependency("D", "^1.0")]
}
repo.add_package(package_a) repo.add_package(package_a)
repo.add_package(package_b) repo.add_package(package_b)
...@@ -2311,8 +2332,10 @@ def test_solver_git_dependencies_update( ...@@ -2311,8 +2332,10 @@ def test_solver_git_dependencies_update(
op = ops[1] op = ops[1]
assert op.job_type == "update" assert op.job_type == "update"
assert isinstance(op, Update)
assert op.package.source_type == "git" assert op.package.source_type == "git"
assert op.package.source_reference == DEFAULT_SOURCE_REF assert op.package.source_reference == DEFAULT_SOURCE_REF
assert op.package.source_resolved_reference is not None
assert op.package.source_resolved_reference.startswith("9cf87a2") assert op.package.source_resolved_reference.startswith("9cf87a2")
assert op.initial_package.source_resolved_reference == "123456" assert op.initial_package.source_resolved_reference == "123456"
...@@ -3110,7 +3133,7 @@ def test_solver_does_not_loop_indefinitely_on_duplicate_constraints_with_extras( ...@@ -3110,7 +3133,7 @@ def test_solver_does_not_loop_indefinitely_on_duplicate_constraints_with_extras(
"idna", {"version": ">=2.0.0", "markers": "extra == 'security'"} "idna", {"version": ">=2.0.0", "markers": "extra == 'security'"}
) )
) )
requests.extras["security"] = [get_dependency("idna", ">=2.0.0")] requests.extras[canonicalize_name("security")] = [get_dependency("idna", ">=2.0.0")]
idna = get_package("idna", "2.8") idna = get_package("idna", "2.8")
repo.add_package(requests) repo.add_package(requests)
...@@ -3483,7 +3506,7 @@ def test_solver_can_resolve_transitive_extras( ...@@ -3483,7 +3506,7 @@ def test_solver_can_resolve_transitive_extras(
requests.add_dependency( requests.add_dependency(
Factory.create_dependency("PyOpenSSL", {"version": ">=0.14", "optional": True}) Factory.create_dependency("PyOpenSSL", {"version": ">=0.14", "optional": True})
) )
requests.extras["security"] = [dep] requests.extras[canonicalize_name("security")] = [dep]
pyota = get_package("PyOTA", "2.1.0") pyota = get_package("PyOTA", "2.1.0")
pyota.add_dependency( pyota.add_dependency(
Factory.create_dependency( Factory.create_dependency(
...@@ -3524,7 +3547,9 @@ def test_solver_can_resolve_for_packages_with_missing_extras( ...@@ -3524,7 +3547,9 @@ def test_solver_can_resolve_for_packages_with_missing_extras(
django_anymail.add_dependency( django_anymail.add_dependency(
Factory.create_dependency("boto3", {"version": "*", "optional": True}) Factory.create_dependency("boto3", {"version": "*", "optional": True})
) )
django_anymail.extras["amazon_ses"] = [Factory.create_dependency("boto3", "*")] django_anymail.extras[canonicalize_name("amazon_ses")] = [
Factory.create_dependency("boto3", "*")
]
django = get_package("django", "2.2.0") django = get_package("django", "2.2.0")
boto3 = get_package("boto3", "1.0.0") boto3 = get_package("boto3", "1.0.0")
requests = get_package("requests", "2.24.0") requests = get_package("requests", "2.24.0")
...@@ -3845,10 +3870,12 @@ def test_solver_incompatible_dependency_with_and_without_extras( ...@@ -3845,10 +3870,12 @@ def test_solver_incompatible_dependency_with_and_without_extras(
baz = get_package("baz", "1.0.0") # required by google-auth[aiohttp] baz = get_package("baz", "1.0.0") # required by google-auth[aiohttp]
google_auth = get_package("google-auth", "1.2.3") google_auth = get_package("google-auth", "1.2.3")
google_auth.extras = {"aiohttp": [get_dependency("baz", "^1.0")]} google_auth.extras = {canonicalize_name("aiohttp"): [get_dependency("baz", "^1.0")]}
google_auth2 = get_package("google-auth", "2.3.4") google_auth2 = get_package("google-auth", "2.3.4")
google_auth2.extras = {"aiohttp": [get_dependency("baz", "^1.0")]} google_auth2.extras = {
canonicalize_name("aiohttp"): [get_dependency("baz", "^1.0")]
}
repo.add_package(foo) repo.add_package(foo)
repo.add_package(bar) repo.add_package(bar)
......
from __future__ import annotations from __future__ import annotations
from collections import namedtuple
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from typing import NamedTuple
import pytest import pytest
...@@ -26,7 +26,10 @@ INSTALLED_RESULTS = [ ...@@ -26,7 +26,10 @@ INSTALLED_RESULTS = [
metadata.PathDistribution(SITE_PURELIB / "cleo-0.7.6.dist-info"), metadata.PathDistribution(SITE_PURELIB / "cleo-0.7.6.dist-info"),
metadata.PathDistribution(SRC / "pendulum" / "pendulum.egg-info"), metadata.PathDistribution(SRC / "pendulum" / "pendulum.egg-info"),
metadata.PathDistribution( metadata.PathDistribution(
zipfile.Path(str(SITE_PURELIB / "foo-0.1.0-py3.8.egg"), "EGG-INFO") zipfile.Path( # type: ignore[arg-type]
str(SITE_PURELIB / "foo-0.1.0-py3.8.egg"),
"EGG-INFO",
)
), ),
metadata.PathDistribution(SITE_PURELIB / "standard-1.2.3.dist-info"), metadata.PathDistribution(SITE_PURELIB / "standard-1.2.3.dist-info"),
metadata.PathDistribution(SITE_PURELIB / "editable-2.3.4.dist-info"), metadata.PathDistribution(SITE_PURELIB / "editable-2.3.4.dist-info"),
...@@ -69,9 +72,13 @@ def env() -> MockEnv: ...@@ -69,9 +72,13 @@ def env() -> MockEnv:
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def mock_git_info(mocker: MockerFixture) -> None: def mock_git_info(mocker: MockerFixture) -> None:
class GitRepoLocalInfo(NamedTuple):
origin: str
revision: str
mocker.patch( mocker.patch(
"poetry.vcs.git.Git.info", "poetry.vcs.git.Git.info",
return_value=namedtuple("GitRepoLocalInfo", "origin revision")( return_value=GitRepoLocalInfo(
origin="https://github.com/sdispater/pendulum.git", origin="https://github.com/sdispater/pendulum.git",
revision="bb058f6b78b2d28ef5d9a5e759cfa179a1a713d6", revision="bb058f6b78b2d28ef5d9a5e759cfa179a1a713d6",
), ),
......
...@@ -10,6 +10,7 @@ from typing import Any ...@@ -10,6 +10,7 @@ from typing import Any
import pytest import pytest
from packaging.utils import canonicalize_name
from poetry.core.constraints.version import Version from poetry.core.constraints.version import Version
from poetry.core.packages.dependency import Dependency from poetry.core.packages.dependency import Dependency
from requests.exceptions import TooManyRedirects from requests.exceptions import TooManyRedirects
...@@ -62,7 +63,8 @@ class MockRepository(PyPiRepository): ...@@ -62,7 +63,8 @@ class MockRepository(PyPiRepository):
return None return None
with fixture.open(encoding="utf-8") as f: with fixture.open(encoding="utf-8") as f:
return json.loads(f.read()) data: dict[str, Any] = json.load(f)
return data
def _download(self, url: str, dest: Path) -> None: def _download(self, url: str, dest: Path) -> None:
filename = url.split("/")[-1] filename = url.split("/")[-1]
...@@ -129,8 +131,8 @@ def test_package() -> None: ...@@ -129,8 +131,8 @@ def test_package() -> None:
assert package.name == "requests" assert package.name == "requests"
assert len(package.requires) == 9 assert len(package.requires) == 9
assert len([r for r in package.requires if r.is_optional()]) == 5 assert len([r for r in package.requires if r.is_optional()]) == 5
assert len(package.extras["security"]) == 3 assert len(package.extras[canonicalize_name("security")]) == 3
assert len(package.extras["socks"]) == 2 assert len(package.extras[canonicalize_name("socks")]) == 2
assert package.files == [ assert package.files == [
{ {
...@@ -143,7 +145,7 @@ def test_package() -> None: ...@@ -143,7 +145,7 @@ def test_package() -> None:
}, },
] ]
win_inet = package.extras["socks"][0] win_inet = package.extras[canonicalize_name("socks")][0]
assert win_inet.name == "win-inet-pton" assert win_inet.name == "win-inet-pton"
assert win_inet.python_versions == "~2.7 || ~2.6" assert win_inet.python_versions == "~2.7 || ~2.6"
...@@ -299,7 +301,10 @@ def test_pypi_repository_supports_reading_bz2_files() -> None: ...@@ -299,7 +301,10 @@ def test_pypi_repository_supports_reading_bz2_files() -> None:
} }
for name, expected_extra in expected_extras.items(): for name, expected_extra in expected_extras.items():
assert sorted(package.extras[name], key=lambda r: r.name) == expected_extra assert (
sorted(package.extras[canonicalize_name(name)], key=lambda r: r.name)
== expected_extra
)
def test_invalid_versions_ignored() -> None: def test_invalid_versions_ignored() -> None:
...@@ -353,7 +358,9 @@ def test_find_links_for_package_of_supported_types() -> None: ...@@ -353,7 +358,9 @@ def test_find_links_for_package_of_supported_types() -> None:
def test_get_release_info_includes_only_supported_types() -> None: def test_get_release_info_includes_only_supported_types() -> None:
repo = MockRepository() repo = MockRepository()
release_info = repo._get_release_info(name="hbmqtt", version="0.9.6") release_info = repo._get_release_info(
name=canonicalize_name("hbmqtt"), version=Version.parse("0.9.6")
)
assert len(release_info["files"]) == 1 assert len(release_info["files"]) == 1
assert release_info["files"][0]["file"] == "hbmqtt-0.9.6.tar.gz" assert release_info["files"][0]["file"] == "hbmqtt-0.9.6.tar.gz"
from __future__ import annotations from __future__ import annotations
from pathlib import Path
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from typing import Any
import pytest import pytest
...@@ -8,6 +10,7 @@ from cleo.io.buffered_io import BufferedIO ...@@ -8,6 +10,7 @@ from cleo.io.buffered_io import BufferedIO
from deepdiff import DeepDiff from deepdiff import DeepDiff
from packaging.utils import canonicalize_name from packaging.utils import canonicalize_name
from poetry.core.constraints.version import parse_constraint from poetry.core.constraints.version import parse_constraint
from poetry.core.packages.vcs_dependency import VCSDependency
from poetry.exceptions import PoetryException from poetry.exceptions import PoetryException
from poetry.factory import Factory from poetry.factory import Factory
...@@ -32,7 +35,7 @@ if TYPE_CHECKING: ...@@ -32,7 +35,7 @@ if TYPE_CHECKING:
class MyPlugin(Plugin): class MyPlugin(Plugin):
def activate(self, poetry: Poetry, io: IO) -> None: def activate(self, poetry: Poetry, io: IO) -> None:
io.write_line("Setting readmes") io.write_line("Setting readmes")
poetry.package.readmes = ("README.md",) poetry.package.readmes = (Path("README.md"),)
def test_create_poetry(fixture_dir: FixtureDirGetter) -> None: def test_create_poetry(fixture_dir: FixtureDirGetter) -> None:
...@@ -44,6 +47,7 @@ def test_create_poetry(fixture_dir: FixtureDirGetter) -> None: ...@@ -44,6 +47,7 @@ def test_create_poetry(fixture_dir: FixtureDirGetter) -> None:
assert package.version.text == "1.2.3" assert package.version.text == "1.2.3"
assert package.description == "Some description." assert package.description == "Some description."
assert package.authors == ["Sébastien Eustace <sebastien@eustace.io>"] assert package.authors == ["Sébastien Eustace <sebastien@eustace.io>"]
assert package.license is not None
assert package.license.id == "MIT" assert package.license.id == "MIT"
for readme in package.readmes: for readme in package.readmes:
...@@ -62,51 +66,52 @@ def test_create_poetry(fixture_dir: FixtureDirGetter) -> None: ...@@ -62,51 +66,52 @@ def test_create_poetry(fixture_dir: FixtureDirGetter) -> None:
for dep in package.requires: for dep in package.requires:
dependencies[dep.name] = dep dependencies[dep.name] = dep
cleo = dependencies["cleo"] cleo = dependencies[canonicalize_name("cleo")]
assert cleo.pretty_constraint == "^0.6" assert cleo.pretty_constraint == "^0.6"
assert not cleo.is_optional() assert not cleo.is_optional()
pendulum = dependencies["pendulum"] pendulum = dependencies[canonicalize_name("pendulum")]
assert pendulum.pretty_constraint == "branch 2.0" assert pendulum.pretty_constraint == "branch 2.0"
assert pendulum.is_vcs() assert pendulum.is_vcs()
assert isinstance(pendulum, VCSDependency)
assert pendulum.vcs == "git" assert pendulum.vcs == "git"
assert pendulum.branch == "2.0" assert pendulum.branch == "2.0"
assert pendulum.source == "https://github.com/sdispater/pendulum.git" assert pendulum.source == "https://github.com/sdispater/pendulum.git"
assert pendulum.allows_prereleases() assert pendulum.allows_prereleases()
requests = dependencies["requests"] requests = dependencies[canonicalize_name("requests")]
assert requests.pretty_constraint == "^2.18" assert requests.pretty_constraint == "^2.18"
assert not requests.is_vcs() assert not requests.is_vcs()
assert not requests.allows_prereleases() assert not requests.allows_prereleases()
assert requests.is_optional() assert requests.is_optional()
assert requests.extras == frozenset(["security"]) assert requests.extras == frozenset(["security"])
pathlib2 = dependencies["pathlib2"] pathlib2 = dependencies[canonicalize_name("pathlib2")]
assert pathlib2.pretty_constraint == "^2.2" assert pathlib2.pretty_constraint == "^2.2"
assert parse_constraint(pathlib2.python_versions) == parse_constraint("~2.7") assert parse_constraint(pathlib2.python_versions) == parse_constraint("~2.7")
assert not pathlib2.is_optional() assert not pathlib2.is_optional()
demo = dependencies["demo"] demo = dependencies[canonicalize_name("demo")]
assert demo.is_file() assert demo.is_file()
assert not demo.is_vcs() assert not demo.is_vcs()
assert demo.name == "demo" assert demo.name == "demo"
assert demo.pretty_constraint == "*" assert demo.pretty_constraint == "*"
demo = dependencies["my-package"] demo = dependencies[canonicalize_name("my-package")]
assert not demo.is_file() assert not demo.is_file()
assert demo.is_directory() assert demo.is_directory()
assert not demo.is_vcs() assert not demo.is_vcs()
assert demo.name == "my-package" assert demo.name == "my-package"
assert demo.pretty_constraint == "*" assert demo.pretty_constraint == "*"
simple_project = dependencies["simple-project"] simple_project = dependencies[canonicalize_name("simple-project")]
assert not simple_project.is_file() assert not simple_project.is_file()
assert simple_project.is_directory() assert simple_project.is_directory()
assert not simple_project.is_vcs() assert not simple_project.is_vcs()
assert simple_project.name == "simple-project" assert simple_project.name == "simple-project"
assert simple_project.pretty_constraint == "*" assert simple_project.pretty_constraint == "*"
functools32 = dependencies["functools32"] functools32 = dependencies[canonicalize_name("functools32")]
assert functools32.name == "functools32" assert functools32.name == "functools32"
assert functools32.pretty_constraint == "^3.2.3" assert functools32.pretty_constraint == "^3.2.3"
assert ( assert (
...@@ -153,7 +158,7 @@ def test_create_pyproject_from_package( ...@@ -153,7 +158,7 @@ def test_create_pyproject_from_package(
poetry = Factory().create_poetry(fixture_dir(project)) poetry = Factory().create_poetry(fixture_dir(project))
package = poetry.package package = poetry.package
pyproject = Factory.create_pyproject_from_package(package) pyproject: dict[str, Any] = Factory.create_pyproject_from_package(package)
result = pyproject["tool"]["poetry"] result = pyproject["tool"]["poetry"]
expected = poetry.pyproject.poetry_config expected = poetry.pyproject.poetry_config
...@@ -465,14 +470,16 @@ def test_poetry_with_two_default_sources( ...@@ -465,14 +470,16 @@ def test_poetry_with_two_default_sources(
def test_validate(fixture_dir: FixtureDirGetter) -> None: def test_validate(fixture_dir: FixtureDirGetter) -> None:
complete = TOMLFile(fixture_dir("complete.toml")) complete = TOMLFile(fixture_dir("complete.toml"))
content = complete.read()["tool"]["poetry"] pyproject: dict[str, Any] = complete.read()
content = pyproject["tool"]["poetry"]
assert Factory.validate(content) == {"errors": [], "warnings": []} assert Factory.validate(content) == {"errors": [], "warnings": []}
def test_validate_fails(fixture_dir: FixtureDirGetter) -> None: def test_validate_fails(fixture_dir: FixtureDirGetter) -> None:
complete = TOMLFile(fixture_dir("complete.toml")) complete = TOMLFile(fixture_dir("complete.toml"))
content = complete.read()["tool"]["poetry"] pyproject: dict[str, Any] = complete.read()
content = pyproject["tool"]["poetry"]
content["this key is not in the schema"] = "" content["this key is not in the schema"] = ""
expected = ( expected = (
...@@ -515,7 +522,7 @@ def test_create_poetry_with_plugins( ...@@ -515,7 +522,7 @@ def test_create_poetry_with_plugins(
poetry = Factory().create_poetry(fixture_dir("sample_project")) poetry = Factory().create_poetry(fixture_dir("sample_project"))
assert poetry.package.readmes == ("README.md",) assert poetry.package.readmes == (Path("README.md"),)
@pytest.mark.parametrize( @pytest.mark.parametrize(
......
...@@ -996,7 +996,7 @@ def test_run_with_keyboard_interrupt( ...@@ -996,7 +996,7 @@ def test_run_with_keyboard_interrupt(
mocker.patch("subprocess.run", side_effect=KeyboardInterrupt()) mocker.patch("subprocess.run", side_effect=KeyboardInterrupt())
with pytest.raises(KeyboardInterrupt): with pytest.raises(KeyboardInterrupt):
tmp_venv.run("python", "-", input_=MINIMAL_SCRIPT) tmp_venv.run("python", "-", input_=MINIMAL_SCRIPT)
subprocess.run.assert_called_once() subprocess.run.assert_called_once() # type: ignore[attr-defined]
def test_call_with_input_and_keyboard_interrupt( def test_call_with_input_and_keyboard_interrupt(
...@@ -1006,7 +1006,7 @@ def test_call_with_input_and_keyboard_interrupt( ...@@ -1006,7 +1006,7 @@ def test_call_with_input_and_keyboard_interrupt(
kwargs = {"call": True} kwargs = {"call": True}
with pytest.raises(KeyboardInterrupt): with pytest.raises(KeyboardInterrupt):
tmp_venv.run("python", "-", input_=MINIMAL_SCRIPT, **kwargs) tmp_venv.run("python", "-", input_=MINIMAL_SCRIPT, **kwargs)
subprocess.run.assert_called_once() subprocess.run.assert_called_once() # type: ignore[attr-defined]
def test_call_no_input_with_keyboard_interrupt( def test_call_no_input_with_keyboard_interrupt(
...@@ -1016,7 +1016,7 @@ def test_call_no_input_with_keyboard_interrupt( ...@@ -1016,7 +1016,7 @@ def test_call_no_input_with_keyboard_interrupt(
kwargs = {"call": True} kwargs = {"call": True}
with pytest.raises(KeyboardInterrupt): with pytest.raises(KeyboardInterrupt):
tmp_venv.run("python", "-", **kwargs) tmp_venv.run("python", "-", **kwargs)
subprocess.check_call.assert_called_once() subprocess.check_call.assert_called_once() # type: ignore[attr-defined]
def test_run_with_called_process_error( def test_run_with_called_process_error(
...@@ -1030,7 +1030,7 @@ def test_run_with_called_process_error( ...@@ -1030,7 +1030,7 @@ def test_run_with_called_process_error(
) )
with pytest.raises(EnvCommandError) as error: with pytest.raises(EnvCommandError) as error:
tmp_venv.run("python", "-", input_=MINIMAL_SCRIPT) tmp_venv.run("python", "-", input_=MINIMAL_SCRIPT)
subprocess.run.assert_called_once() subprocess.run.assert_called_once() # type: ignore[attr-defined]
assert "some output" in str(error.value) assert "some output" in str(error.value)
assert "some error" in str(error.value) assert "some error" in str(error.value)
...@@ -1047,7 +1047,7 @@ def test_call_with_input_and_called_process_error( ...@@ -1047,7 +1047,7 @@ def test_call_with_input_and_called_process_error(
kwargs = {"call": True} kwargs = {"call": True}
with pytest.raises(EnvCommandError) as error: with pytest.raises(EnvCommandError) as error:
tmp_venv.run("python", "-", input_=MINIMAL_SCRIPT, **kwargs) tmp_venv.run("python", "-", input_=MINIMAL_SCRIPT, **kwargs)
subprocess.run.assert_called_once() subprocess.run.assert_called_once() # type: ignore[attr-defined]
assert "some output" in str(error.value) assert "some output" in str(error.value)
assert "some error" in str(error.value) assert "some error" in str(error.value)
...@@ -1064,7 +1064,7 @@ def test_call_no_input_with_called_process_error( ...@@ -1064,7 +1064,7 @@ def test_call_no_input_with_called_process_error(
kwargs = {"call": True} kwargs = {"call": True}
with pytest.raises(EnvCommandError) as error: with pytest.raises(EnvCommandError) as error:
tmp_venv.run("python", "-", **kwargs) tmp_venv.run("python", "-", **kwargs)
subprocess.check_call.assert_called_once() subprocess.check_call.assert_called_once() # type: ignore[attr-defined]
assert "some output" in str(error.value) assert "some output" in str(error.value)
assert "some error" in str(error.value) assert "some error" in str(error.value)
...@@ -1080,7 +1080,7 @@ def test_check_output_with_called_process_error( ...@@ -1080,7 +1080,7 @@ def test_check_output_with_called_process_error(
) )
with pytest.raises(EnvCommandError) as error: with pytest.raises(EnvCommandError) as error:
tmp_venv.run("python", "-") tmp_venv.run("python", "-")
subprocess.check_output.assert_called_once() subprocess.check_output.assert_called_once() # type: ignore[attr-defined]
assert "some output" in str(error.value) assert "some output" in str(error.value)
assert "some error" in str(error.value) assert "some error" in str(error.value)
...@@ -1730,7 +1730,7 @@ def test_build_environment_called_build_script_specified( ...@@ -1730,7 +1730,7 @@ def test_build_environment_called_build_script_specified(
with build_environment(extended_without_setup_poetry, project_env) as env: with build_environment(extended_without_setup_poetry, project_env) as env:
assert env == ephemeral_env assert env == ephemeral_env
assert env.executed == [ assert env.executed == [ # type: ignore[attr-defined]
[ [
str(sys.executable), str(sys.executable),
str(env.pip_embedded), str(env.pip_embedded),
...@@ -1755,7 +1755,7 @@ def test_build_environment_not_called_without_build_script_specified( ...@@ -1755,7 +1755,7 @@ def test_build_environment_not_called_without_build_script_specified(
with build_environment(poetry, project_env) as env: with build_environment(poetry, project_env) as env:
assert env == project_env assert env == project_env
assert not env.executed assert not env.executed # type: ignore[attr-defined]
def test_create_venv_project_name_empty_sets_correct_prompt( def test_create_venv_project_name_empty_sets_correct_prompt(
......
from __future__ import annotations from __future__ import annotations
from typing import TYPE_CHECKING
import pytest import pytest
from poetry.core.packages.package import Package from poetry.core.packages.package import Package
...@@ -8,6 +10,9 @@ from poetry.factory import Factory ...@@ -8,6 +10,9 @@ from poetry.factory import Factory
from poetry.utils.extras import get_extra_package_names from poetry.utils.extras import get_extra_package_names
if TYPE_CHECKING:
from packaging.utils import NormalizedName
_PACKAGE_FOO = Package("foo", "0.1.0") _PACKAGE_FOO = Package("foo", "0.1.0")
_PACKAGE_SPAM = Package("spam", "0.2.0") _PACKAGE_SPAM = Package("spam", "0.2.0")
_PACKAGE_BAR = Package("bar", "0.3.0") _PACKAGE_BAR = Package("bar", "0.3.0")
...@@ -60,8 +65,8 @@ _PACKAGE_QUIX.add_dependency(Factory.create_dependency("baz", "*")) ...@@ -60,8 +65,8 @@ _PACKAGE_QUIX.add_dependency(Factory.create_dependency("baz", "*"))
) )
def test_get_extra_package_names( def test_get_extra_package_names(
packages: list[Package], packages: list[Package],
extras: dict[str, list[str]], extras: dict[NormalizedName, list[NormalizedName]],
extra_names: list[str], extra_names: list[NormalizedName],
expected_extra_package_names: set[str], expected_extra_package_names: set[str],
) -> None: ) -> None:
assert ( assert (
......
...@@ -36,6 +36,7 @@ from poetry.utils import patterns ...@@ -36,6 +36,7 @@ from poetry.utils import patterns
) )
def test_wheel_file_re(filename: str, expected: dict[str, str | None]) -> None: def test_wheel_file_re(filename: str, expected: dict[str, str | None]) -> None:
match = patterns.wheel_file_re.match(filename) match = patterns.wheel_file_re.match(filename)
assert match is not None
groups = match.groupdict() groups = match.groupdict()
assert groups == expected assert groups == expected
...@@ -37,4 +37,4 @@ def test_pip_install_with_keyboard_interrupt( ...@@ -37,4 +37,4 @@ def test_pip_install_with_keyboard_interrupt(
mocker.patch("subprocess.run", side_effect=KeyboardInterrupt()) mocker.patch("subprocess.run", side_effect=KeyboardInterrupt())
with pytest.raises(KeyboardInterrupt): with pytest.raises(KeyboardInterrupt):
pip_install(file_path, tmp_venv) pip_install(file_path, tmp_venv)
subprocess.run.assert_called_once() subprocess.run.assert_called_once() # type: ignore[attr-defined]
...@@ -90,7 +90,7 @@ def test_setup_reader_read_sub_level_setup_call_with_direct_types( ...@@ -90,7 +90,7 @@ def test_setup_reader_read_sub_level_setup_call_with_direct_types(
expected_name = "SQLAlchemy" expected_name = "SQLAlchemy"
expected_version = None expected_version = None
expected_install_requires = [] expected_install_requires: list[str] = []
expected_extras_require = { expected_extras_require = {
"mysql": ["mysqlclient"], "mysql": ["mysqlclient"],
"pymysql": ["pymysql"], "pymysql": ["pymysql"],
...@@ -154,8 +154,8 @@ def test_setup_reader_read_setup_call_in_main(setup: Callable[[str], Path]) -> N ...@@ -154,8 +154,8 @@ def test_setup_reader_read_setup_call_in_main(setup: Callable[[str], Path]) -> N
expected_name = "PyYAML" expected_name = "PyYAML"
expected_version = "3.13" expected_version = "3.13"
expected_install_requires = [] expected_install_requires: list[str] = []
expected_extras_require = {} expected_extras_require: dict[str, list[str]] = {}
expected_python_requires = None expected_python_requires = None
assert result["name"] == expected_name assert result["name"] == expected_name
...@@ -172,7 +172,7 @@ def test_setup_reader_read_extras_require_with_variables( ...@@ -172,7 +172,7 @@ def test_setup_reader_read_extras_require_with_variables(
expected_name = "extras_require_with_vars" expected_name = "extras_require_with_vars"
expected_version = "0.0.1" expected_version = "0.0.1"
expected_install_requires = [] expected_install_requires: list[str] = []
expected_extras_require = {"test": ["pytest"]} expected_extras_require = {"test": ["pytest"]}
expected_python_requires = None expected_python_requires = None
......
...@@ -34,7 +34,7 @@ from poetry.utils.source import source_to_table ...@@ -34,7 +34,7 @@ from poetry.utils.source import source_to_table
) )
def test_source_to_table(source: Source, table_body: dict[str, str | bool]) -> None: def test_source_to_table(source: Source, table_body: dict[str, str | bool]) -> None:
table = Table(Container(), Trivia(), False) table = Table(Container(), Trivia(), False)
table._value = table_body table._value = table_body # type: ignore[assignment]
assert source_to_table(source) == table assert source_to_table(source) == table
...@@ -70,5 +70,9 @@ def test_source_legacy_handling( ...@@ -70,5 +70,9 @@ def test_source_legacy_handling(
], ],
) )
def test_source_priority_as_string(priority: str, expected_priority: Priority) -> None: def test_source_priority_as_string(priority: str, expected_priority: Priority) -> None:
source = Source("foo", "https://example.com", priority=priority) source = Source(
"foo",
"https://example.com",
priority=priority, # type: ignore[arg-type]
)
assert source.priority == Priority.SECONDARY assert source.priority == Priority.SECONDARY
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