Commit 603b398e by David Hotham Committed by GitHub

more type-checking (#7845)

parent 978d435b
......@@ -679,14 +679,14 @@ files = [
[[package]]
name = "importlib-metadata"
version = "6.5.0"
version = "6.6.0"
description = "Read metadata from Python packages"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "importlib_metadata-6.5.0-py3-none-any.whl", hash = "sha256:03ba783c3a2c69d751b109fc0c94a62c51f581b3d6acf8ed1331b6d5729321ff"},
{file = "importlib_metadata-6.5.0.tar.gz", hash = "sha256:7a8bdf1bc3a726297f5cfbc999e6e7ff6b4fa41b26bba4afc580448624460045"},
{file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"},
{file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"},
]
[package.dependencies]
......
......@@ -178,7 +178,7 @@ force-exclude = '''
[tool.mypy]
files = "src"
files = "src, tests"
mypy_path = "src"
namespace_packages = true
explicit_package_bases = true
......@@ -195,17 +195,17 @@ exclude = [
"tests/utils/fixtures"
]
# use of importlib-metadata backport at python3.7 makes it impossible to
# satisfy mypy without some ignores: but we get a different set of ignores at
# different python versions.
#
# <https://github.com/python/mypy/issues/8823>, meanwhile suppress that
# warning.
# use of importlib-metadata backport makes it impossible to satisfy mypy
# without some ignores: but we get different sets of ignores at different
# python versions.
[[tool.mypy.overrides]]
module = [
'poetry.plugins.plugin_manager',
'poetry.repositories.installed_repository',
'poetry.utils.env',
'tests.helpers',
'tests.repositories.test_installed_repository',
'tests.console.commands.self.test_show_plugins'
]
warn_unused_ignores = false
......@@ -222,6 +222,7 @@ module = [
'shellingham.*',
'virtualenv.*',
'xattr.*',
'zipp.*'
]
ignore_missing_imports = true
......
......@@ -147,7 +147,7 @@ class PyPiRepository(HTTPRepository):
def _get_release_info(
self, name: NormalizedName, version: Version
) -> dict[str, str | list[str] | None]:
) -> dict[str, Any]:
from poetry.inspection.info import PackageInfo
self._log(f"Getting info for {name} ({version}) from PyPI", "debug")
......
......@@ -1727,13 +1727,11 @@ class VirtualEnv(Env):
# from inside the virtualenv.
if base is None:
output = self.run_python_script(GET_BASE_PREFIX)
assert isinstance(output, str)
self._base = Path(output.strip())
@property
def sys_path(self) -> list[str]:
output = self.run_python_script(GET_SYS_PATH)
assert isinstance(output, str)
paths: list[str] = json.loads(output)
return paths
......@@ -1749,20 +1747,17 @@ class VirtualEnv(Env):
def get_supported_tags(self) -> list[Tag]:
output = self.run_python_script(GET_SYS_TAGS)
assert isinstance(output, str)
return [Tag(*t) for t in json.loads(output)]
def get_marker_env(self) -> dict[str, Any]:
output = self.run_python_script(GET_ENVIRONMENT_INFO)
assert isinstance(output, str)
env: dict[str, Any] = json.loads(output)
return env
def get_pip_version(self) -> Version:
output = self.run_pip("--version")
assert isinstance(output, str)
output = output.strip()
m = re.match("pip (.+?)(?: from .+)?$", output)
......@@ -1773,7 +1768,6 @@ class VirtualEnv(Env):
def get_paths(self) -> dict[str, str]:
output = self.run_python_script(GET_PATHS)
assert isinstance(output, str)
paths: dict[str, str] = json.loads(output)
return paths
......@@ -1889,7 +1883,6 @@ class GenericEnv(VirtualEnv):
def get_paths(self) -> dict[str, str]:
output = self.run_python_script(GET_PATHS_FOR_GENERIC_ENVS)
assert isinstance(output, str)
paths: dict[str, str] = json.loads(output)
return paths
......
......@@ -19,8 +19,10 @@ if TYPE_CHECKING:
from collections.abc import Callable
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=".")
for k in flattened_config:
......@@ -42,10 +44,12 @@ def test_config_get_processes_depended_on_values(
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)]),
(int_normalizer, [("4", 4), ("2", 2)]),
]:
]
for normalizer, values in data:
for env_value, value in values:
for name in get_options_based_on_normalizer(normalizer=normalizer):
env_var = "POETRY_" + re.sub("[.-]+", "_", name).upper()
......
......@@ -121,7 +121,7 @@ def dummy_keyring() -> DummyBackend:
def with_simple_keyring(dummy_keyring: DummyBackend) -> None:
import keyring
keyring.set_keyring(dummy_keyring)
keyring.set_keyring(dummy_keyring) # type: ignore[no-untyped-call]
@pytest.fixture()
......@@ -130,7 +130,7 @@ def with_fail_keyring() -> None:
from keyring.backends.fail import Keyring
keyring.set_keyring(Keyring())
keyring.set_keyring(Keyring()) # type: ignore[no-untyped-call]
@pytest.fixture()
......@@ -139,31 +139,37 @@ def with_null_keyring() -> None:
from keyring.backends.null import Keyring
keyring.set_keyring(Keyring())
keyring.set_keyring(Keyring()) # type: ignore[no-untyped-call]
@pytest.fixture()
def with_chained_fail_keyring(mocker: MockerFixture) -> None:
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
from keyring.backends.chainer import ChainerBackend
keyring.set_keyring(ChainerBackend())
keyring.set_keyring(ChainerBackend()) # type: ignore[no-untyped-call]
@pytest.fixture()
def with_chained_null_keyring(mocker: MockerFixture) -> None:
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
from keyring.backends.chainer import ChainerBackend
keyring.set_keyring(ChainerBackend())
keyring.set_keyring(ChainerBackend()) # type: ignore[no-untyped-call]
@pytest.fixture
......@@ -203,7 +209,7 @@ def config(
from keyring.backends.fail import Keyring
keyring.set_keyring(Keyring())
keyring.set_keyring(Keyring()) # type: ignore[no-untyped-call]
c = Config()
c.merge(config_source.config)
......
......@@ -4,6 +4,7 @@ import os
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Any
import pytest
import tomlkit
......@@ -83,7 +84,7 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file(
envs_file = TOMLFile(venv_cache / "envs.toml")
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]["patch"] == "3.7.1"
......
......@@ -35,11 +35,6 @@ def _patch_repos(repo: TestRepository, installed: Repository) -> None:
installed.add_package(poetry)
@pytest.fixture(autouse=True)
def save_environ(environ: None) -> Repository:
yield
@pytest.fixture()
def pool(repo: TestRepository) -> RepositoryPool:
return RepositoryPool([repo])
......
from __future__ import annotations
from typing import TYPE_CHECKING
from typing import Any
if TYPE_CHECKING:
from collections.abc import Mapping
import pytest
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.factory import Factory
from tests.console.commands.self.utils import get_self_command_dependencies
......@@ -26,10 +32,10 @@ def tester(command_tester_factory: CommandTesterFactory) -> CommandTester:
def assert_plugin_add_result(
tester: CommandTester,
expected: str,
constraint: str | dict[str, str],
constraint: str | Mapping[str, str | list[str]],
) -> None:
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 dependencies["poetry-plugin"] == constraint
......@@ -128,14 +134,11 @@ Package operations: 3 installs, 0 updates, 0 removals
Writing lock file
"""
assert_plugin_add_result(
tester,
expected,
{
"git": "https://github.com/demo/poetry-plugin.git",
"extras": ["foo"],
},
)
constraint: dict[str, str | list[str]] = {
"git": "https://github.com/demo/poetry-plugin.git",
"extras": ["foo"],
}
assert_plugin_add_result(tester, expected, constraint)
@pytest.mark.parametrize(
......@@ -212,6 +215,7 @@ poetry-plugin = "^1.2.3"
tester.execute("poetry-plugin")
assert isinstance(tester.command, AddCommand)
expected = f"""\
The following packages are already present in the pyproject.toml and will be\
skipped:
......
......@@ -80,10 +80,10 @@ def plugin_distro(plugin_package: Package, tmp_path: Path) -> metadata.Distribut
)
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 MockDistribution()
return MockDistribution() # type: ignore[no-untyped-call]
@pytest.fixture
......@@ -101,10 +101,14 @@ def entry_points(
entry_point_name: str,
entry_point_values_by_group: dict[str, list[str]],
plugin_distro: metadata.Distribution,
) -> Callable[[...], list[metadata.EntryPoint]]:
) -> Callable[..., list[metadata.EntryPoint]]:
by_group = {
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
)
for value in values
......@@ -118,7 +122,9 @@ def entry_points(
if group not in by_group:
return []
return by_group.get(group)
eps: list[metadata.EntryPoint] = by_group[group]
return eps
return _entry_points
......@@ -130,7 +136,7 @@ def mock_metadata_entry_points(
installed: Repository,
mocker: MockerFixture,
tmp_venv: Env,
entry_points: Callable[[...], metadata.EntryPoint],
entry_points: Callable[..., metadata.EntryPoint],
) -> None:
installed.add_package(plugin_package)
......
from __future__ import annotations
from pathlib import Path
from typing import TYPE_CHECKING
from poetry.factory import Factory
from typing import Any
from tomlkit.items import Table as TOMLTable
if TYPE_CHECKING:
from tomlkit.container import Table as TOMLTable
from poetry.factory import Factory
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)
content = poetry.file.read()["tool"]["poetry"]
pyproject: dict[str, Any] = poetry.file.read()
content = pyproject["tool"]["poetry"]
assert "group" in content
assert SelfCommand.ADDITIONAL_PACKAGE_GROUP in content["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
),
)
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:
source = request.getfixturevalue(source_str)
tester_all_types.execute(f"{source.name}")
......
......@@ -8,6 +8,7 @@ from typing import cast
import pytest
from packaging.utils import canonicalize_name
from poetry.core.constraints.version import Version
from poetry.core.packages.package import Package
......@@ -232,7 +233,7 @@ def test_add_constraint_with_extras(
extra_name: str,
) -> None:
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)
cachy1.add_dependency(msgpack_dep)
......@@ -492,14 +493,14 @@ Writing lock file
assert "demo" in content["dependencies"]
expected = {
expected_content: dict[str, Any] = {
"git": "ssh://git@github.com/demo/demo.git",
"rev": "develop",
}
if editable:
expected["develop"] = True
expected_content["develop"] = True
assert content["dependencies"]["demo"] == expected
assert content["dependencies"]["demo"] == expected_content
@pytest.mark.parametrize(
......@@ -519,6 +520,7 @@ def test_add_directory_constraint(
path = "../git/github.com/demo/demo"
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"""\
Updating dependencies
......@@ -527,7 +529,7 @@ Resolving dependencies...
Package operations: 2 installs, 0 updates, 0 removals
• 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
"""
......@@ -541,11 +543,11 @@ Writing lock file
assert "demo" in content["dependencies"]
expected = {"path": path}
expected_content: dict[str, Any] = {"path": path}
if editable:
expected["develop"] = True
expected_content["develop"] = True
assert content["dependencies"]["demo"] == expected
assert content["dependencies"]["demo"] == expected_content
@pytest.mark.parametrize(
......@@ -562,6 +564,7 @@ def test_add_directory_with_poetry(
path = "../git/github.com/demo/pyproject-demo"
tester.execute(f"{path}")
demo_path = app.poetry.file.path.parent.joinpath(path).resolve().as_posix()
expected = f"""\
Updating dependencies
......@@ -570,7 +573,7 @@ Resolving dependencies...
Package operations: 2 installs, 0 updates, 0 removals
• 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
"""
......@@ -595,6 +598,7 @@ def test_add_file_constraint_wheel(
path = "../distributions/demo-0.1.0-py2.py3-none-any.whl"
tester.execute(f"{path}")
demo_path = app.poetry.file.path.parent.joinpath(path).resolve().as_posix()
expected = f"""\
Updating dependencies
......@@ -603,7 +607,7 @@ Resolving dependencies...
Package operations: 2 installs, 0 updates, 0 removals
• 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
"""
......@@ -633,6 +637,7 @@ def test_add_file_constraint_sdist(
path = "../distributions/demo-0.1.0.tar.gz"
tester.execute(f"{path}")
demo_path = app.poetry.file.path.parent.joinpath(path).resolve().as_posix()
expected = f"""\
Updating dependencies
......@@ -641,7 +646,7 @@ Resolving dependencies...
Package operations: 2 installs, 0 updates, 0 removals
• 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
"""
......@@ -665,7 +670,7 @@ def test_add_constraint_with_extras_option(
extra_name: str,
) -> None:
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)
cachy2.add_dependency(msgpack_dep)
......@@ -777,9 +782,9 @@ Package operations: 4 installs, 0 updates, 0 removals
Writing lock file
"""
# 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())
assert output == expected
assert output == expected_lines
assert isinstance(tester.command, InstallerCommand)
assert tester.command.installer.executor.installations_count == 4
......
......@@ -11,6 +11,7 @@ from deepdiff import DeepDiff
from poetry.core.pyproject.exceptions import PyProjectException
from poetry.config.config_source import ConfigSource
from poetry.console.commands.install import InstallCommand
from poetry.factory import Factory
from tests.conftest import Config
......@@ -97,7 +98,7 @@ virtualenvs.prefer-active-python = false
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
......@@ -150,7 +151,7 @@ virtualenvs.prefer-active-python = false
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
......@@ -243,9 +244,9 @@ def test_config_installer_parallel(
tester.execute("--local installer.parallel")
assert tester.io.fetch_output().strip() == "true"
workers = command_tester_factory(
"install"
)._command._installer._executor._max_workers
command = command_tester_factory("install")._command
assert isinstance(command, InstallCommand)
workers = command.installer._executor._max_workers
assert workers > 1
tester.io.clear_output()
......@@ -253,9 +254,9 @@ def test_config_installer_parallel(
tester.execute("--local installer.parallel")
assert tester.io.fetch_output().strip() == "false"
workers = command_tester_factory(
"install"
)._command._installer._executor._max_workers
command = command_tester_factory("install")._command
assert isinstance(command, InstallCommand)
workers = command.installer._executor._max_workers
assert workers == 1
......
......@@ -27,7 +27,10 @@ def tester(command_tester_factory: CommandTesterFactory) -> CommandTester:
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:
package_path = Path(package_path)
assert path.is_dir()
......@@ -203,7 +206,8 @@ def test_respect_prefer_active_on_new(
if GET_PYTHON_VERSION_ONELINER in cmd:
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)
......
from __future__ import annotations
from typing import TYPE_CHECKING
from typing import Any
from typing import cast
import pytest
import tomlkit
......@@ -14,6 +16,7 @@ from tests.helpers import get_package
if TYPE_CHECKING:
from cleo.testers.command_tester import CommandTester
from pytest_mock import MockerFixture
from tomlkit import TOMLDocument
from poetry.poetry import Poetry
from poetry.repositories import Repository
......@@ -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("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]
foo = "^2.0.0"
baz = "^1.0.0"
""")
content["tool"]["poetry"]["dependencies"]["foo"] = "^2.0.0"
content["tool"]["poetry"]["group"] = groups_content["tool"]["poetry"]["group"]
app.poetry.file.write(content)
pyproject["tool"]["poetry"]["dependencies"]["foo"] = "^2.0.0"
pyproject["tool"]["poetry"]["group"] = groups_content["tool"]["poetry"]["group"]
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(
......@@ -78,7 +82,9 @@ baz = "^1.0.0"
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["group"]["bar"]["dependencies"]
assert "baz" in content["group"]["bar"]["dependencies"]
......@@ -89,7 +95,8 @@ 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:
# consistent line endings
expected = expected.replace("\n", "\r\n")
......@@ -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("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]
foo = "^2.0.0"
baz = "^1.0.0"
""")
content["tool"]["poetry"]["dependencies"]["foo"] = "^2.0.0"
content["tool"]["poetry"]["group"] = groups_content["tool"]["poetry"]["group"]
app.poetry.file.write(content)
pyproject["tool"]["poetry"]["dependencies"]["foo"] = "^2.0.0"
pyproject["tool"]["poetry"]["group"] = groups_content["tool"]["poetry"]["group"]
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(
......@@ -133,7 +141,9 @@ baz = "^1.0.0"
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" not in content["group"]["bar"]["dependencies"]
assert "baz" in content["group"]["bar"]["dependencies"]
......@@ -166,9 +176,9 @@ def test_remove_does_not_live_empty_groups(
repo.add_package(Package("foo", "2.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]
foo = "^2.0.0"
baz = "^1.0.0"
......@@ -176,6 +186,7 @@ baz = "^1.0.0"
""")
content["tool"]["poetry"]["dependencies"]["foo"] = "^2.0.0"
content["tool"]["poetry"]["group"] = groups_content["tool"]["poetry"]["group"]
content = cast("TOMLDocument", content)
app.poetry.file.write(content)
app.poetry.package.add_dependency(Factory.create_dependency("foo", "^2.0.0"))
......@@ -188,10 +199,12 @@ baz = "^1.0.0"
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" 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]" not in content.as_string()
......@@ -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("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]
foo-bar = "^2.0.0"
baz = "^1.0.0"
""")
content["tool"]["poetry"]["dependencies"]["foo-bar"] = "^2.0.0"
content["tool"]["poetry"].value._insert_after(
pyproject["tool"]["poetry"]["dependencies"]["foo-bar"] = "^2.0.0"
pyproject["tool"]["poetry"].value._insert_after(
"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(
......@@ -234,7 +248,9 @@ baz = "^1.0.0"
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["group"]["bar"]["dependencies"]
assert "baz" in content["group"]["bar"]["dependencies"]
......@@ -245,7 +261,8 @@ 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:
# consistent line endings
expected = expected.replace("\n", "\r\n")
......
......@@ -7,6 +7,8 @@ from typing import TYPE_CHECKING
import pytest
from poetry.console.commands.shell import ShellCommand
if TYPE_CHECKING:
from cleo.testers.command_tester import CommandTester
......@@ -25,6 +27,7 @@ def test_shell(tester: CommandTester, mocker: MockerFixture) -> None:
tester.execute()
assert isinstance(tester.command, ShellCommand)
expected_output = f"Spawning shell within {tester.command.env.path}\n"
shell_activate.assert_called_once_with(tester.command.env)
......@@ -38,6 +41,7 @@ def test_shell_already_active(tester: CommandTester, mocker: MockerFixture) -> N
tester.execute()
assert isinstance(tester.command, ShellCommand)
expected_output = (
f"Virtual environment already activated: {tester.command.env.path}\n"
)
......@@ -72,6 +76,7 @@ def test__is_venv_activated(
prefix: str,
expected: bool,
) -> None:
assert isinstance(tester.command, ShellCommand)
mocker.patch.object(tester.command.env, "_path", Path("foobar"))
mocker.patch("sys.prefix", prefix)
......
......@@ -10,6 +10,7 @@ from poetry.core.packages.dependency_group import DependencyGroup
from poetry.factory import Factory
from poetry.utils._compat import tomllib
from tests.helpers import MOCK_DEFAULT_GIT_REVISION
from tests.helpers import TestLocker
from tests.helpers import get_package
......@@ -49,6 +50,7 @@ def test_show_basic_with_installed_packages(
installed.add_package(pendulum_200)
installed.add_package(pytest_373)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -125,6 +127,7 @@ def _configure_project_with_groups(poetry: Poetry, installed: Repository) -> Non
installed.add_package(pendulum_200)
installed.add_package(pytest_373)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -267,6 +270,7 @@ def test_show_basic_with_installed_packages_single(
installed.add_package(cachy_010)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -308,6 +312,7 @@ def test_show_basic_with_installed_packages_single_canonicalized(
installed.add_package(foo_bar)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -352,6 +357,8 @@ def test_show_basic_with_not_installed_packages_non_decorated(
pendulum_200.description = "Pendulum package"
installed.add_package(cachy_010)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -406,6 +413,8 @@ def test_show_basic_with_not_installed_packages_decorated(
pendulum_200.description = "Pendulum package"
installed.add_package(cachy_010)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -474,6 +483,7 @@ def test_show_latest_non_decorated(
repo.add_package(pendulum_200)
repo.add_package(pendulum_201)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -542,6 +552,7 @@ def test_show_latest_decorated(
repo.add_package(pendulum_200)
repo.add_package(pendulum_201)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -609,6 +620,7 @@ def test_show_outdated(
repo.add_package(cachy_020)
repo.add_package(pendulum_200)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -661,6 +673,7 @@ def test_show_outdated_with_only_up_to_date_packages(
installed.add_package(cachy_020)
repo.add_package(cachy_020)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -719,6 +732,7 @@ def test_show_outdated_has_prerelease_but_not_allowed(
repo.add_package(cachy_020)
repo.add_package(pendulum_200)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -792,6 +806,7 @@ def test_show_outdated_has_prerelease_and_allowed(
repo.add_package(cachy_020)
repo.add_package(pendulum_200)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -859,6 +874,7 @@ def test_show_outdated_formatting(
repo.add_package(pendulum_200)
repo.add_package(pendulum_201)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -940,6 +956,7 @@ def test_show_outdated_local_dependencies(
repo.add_package(cachy_030)
repo.add_package(pendulum_200)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -1051,6 +1068,7 @@ def test_show_outdated_git_dev_dependency(
repo.add_package(pendulum_200)
repo.add_package(pytest)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -1147,6 +1165,7 @@ def test_show_outdated_no_dev_git_dev_dependency(
repo.add_package(pendulum_200)
repo.add_package(pytest)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -1229,6 +1248,7 @@ def test_show_hides_incompatible_package(
installed.add_package(pendulum_200)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -1283,6 +1303,7 @@ def test_show_all_shows_incompatible_package(
installed.add_package(pendulum_200)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -1338,6 +1359,7 @@ def test_show_hides_incompatible_package_with_duplicate(
Factory.create_dependency("cachy", {"version": "0.1.1", "platform": "darwin"})
)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -1386,6 +1408,7 @@ def test_show_all_shows_all_duplicates(
Factory.create_dependency("cachy", {"version": "0.1.1", "platform": "darwin"})
)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -1444,6 +1467,7 @@ def test_show_non_dev_with_basic_installed_packages(
installed.add_package(pendulum_200)
installed.add_package(pytest_373)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -1516,6 +1540,7 @@ def test_show_with_group_only(
installed.add_package(pendulum_200)
installed.add_package(pytest_373)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -1587,6 +1612,7 @@ def test_show_with_optional_group(
installed.add_package(pendulum_200)
installed.add_package(pytest_373)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -1657,6 +1683,7 @@ def test_show_tree(
installed.add_package(cachy2)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -1714,6 +1741,7 @@ def test_show_tree_no_dev(
pytest = get_package("pytest", "6.1.1")
installed.add_package(pytest)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -1781,6 +1809,7 @@ def test_show_tree_why_package(
c = get_package("c", "0.0.1")
installed.add_package(c)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -1840,6 +1869,7 @@ def test_show_tree_why(
c = get_package("c", "0.0.1")
installed.add_package(c)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -1897,6 +1927,7 @@ def test_show_required_by_deps(
installed.add_package(cachy2)
installed.add_package(pendulum)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -1990,6 +2021,7 @@ def test_show_dependency_installed_from_git_in_dev(
repo.add_package(pendulum_200)
# The git package is the one that gets into the lockfile.
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -2050,6 +2082,7 @@ def test_url_dependency_is_not_outdated_by_repository_package(
demo_100 = get_package("demo", "1.0.0")
repo.add_package(demo_100)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -2092,6 +2125,7 @@ def test_show_top_level(
installed.add_package(cachy2)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -2146,6 +2180,7 @@ def test_show_top_level_with_explicitly_defined_depenancy(
installed.add_package(a)
installed.add_package(b)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(
{
"package": [
......@@ -2218,6 +2253,8 @@ def test_show_outdated_missing_directory_dependency(
) -> None:
with (poetry.pyproject.file.path.parent / "poetry.lock").open(mode="rb") as f:
data = tomllib.load(f)
assert isinstance(poetry.locker, TestLocker)
poetry.locker.mock_lock_data(data)
poetry.package.add_dependency(
......
......@@ -76,6 +76,7 @@ def test_short_version_update(tester: CommandTester) -> None:
def test_dry_run(tester: CommandTester) -> None:
assert isinstance(tester.command, VersionCommand)
old_pyproject = tester.command.poetry.file.path.read_text()
tester.execute("--dry-run major")
......
......@@ -11,6 +11,7 @@ from cleo.testers.application_tester import ApplicationTester
from poetry.console.application import Application
from poetry.console.commands.command import Command
from poetry.plugins.application_plugin import ApplicationPlugin
from poetry.repositories.cached_repository import CachedRepository
from poetry.utils.authenticator import Authenticator
from tests.helpers import mock_metadata_entry_points
......@@ -99,6 +100,7 @@ def test_application_verify_source_cache_flag(disable_cache: bool) -> None:
assert app.poetry.pool.repositories
for repo in app.poetry.pool.repositories:
assert isinstance(repo, CachedRepository)
assert repo._disable_cache == disable_cache
......
......@@ -104,8 +104,10 @@ def mock_clone(
) -> MockDulwichRepo:
# Checking source to determine which folder we need to copy
parsed = ParsedUrl.parse(url)
assert parsed.pathname is not None
path = re.sub(r"(.git)?$", "", parsed.pathname.lstrip("/"))
assert parsed.resource is not None
folder = FIXTURE_PATH / "git" / parsed.resource / path
if not source_root:
......@@ -130,9 +132,9 @@ class TestExecutor(Executor):
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self._installs = []
self._updates = []
self._uninstalls = []
self._installs: list[Package] = []
self._updates: list[Package] = []
self._uninstalls: list[Package] = []
@property
def installations(self) -> list[Package]:
......@@ -146,12 +148,14 @@ class TestExecutor(Executor):
def removals(self) -> list[Package]:
return self._uninstalls
def _do_execute_operation(self, operation: Operation) -> None:
super()._do_execute_operation(operation)
def _do_execute_operation(self, operation: Operation) -> int:
rc = super()._do_execute_operation(operation)
if not operation.skipped:
getattr(self, f"_{operation.job_type}s").append(operation.package)
return rc
def _execute_install(self, operation: Operation) -> int:
return 0
......@@ -168,6 +172,7 @@ class PoetryTestApplication(Application):
self._poetry = poetry
def reset_poetry(self) -> None:
assert self._poetry is not None
poetry = self._poetry
self._poetry = Factory().create_poetry(self._poetry.file.path.parent)
self._poetry.set_pool(poetry.pool)
......@@ -181,7 +186,7 @@ class TestLocker(Locker):
# class name begins 'Test': tell pytest that it does not contain testcases.
__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._local_config = local_config
self._lock_data = None
......@@ -201,7 +206,7 @@ class TestLocker(Locker):
return self
def mock_lock_data(self, data: dict) -> None:
def mock_lock_data(self, data: dict[str, Any]) -> None:
self.locked()
self._lock_data = data
......@@ -256,14 +261,16 @@ def isolated_environment(
def make_entry_point_from_plugin(
name: str, cls: type[Any], dist: metadata.Distribution | None = None
) -> metadata.EntryPoint:
group: str | None = getattr(cls, "group", None)
ep = metadata.EntryPoint(
name=name,
group=getattr(cls, "group", None),
group=group, # type: ignore[arg-type]
value=f"{cls.__module__}:{cls.__name__}",
)
if dist:
return ep._for(dist)
ep = ep._for(dist) # type: ignore[attr-defined,no-untyped-call]
return ep
return ep
......
......@@ -39,6 +39,8 @@ from tests.repositories.test_pypi_repository import MockRepository
if TYPE_CHECKING:
from collections.abc import Iterator
import httpretty
from httpretty.core import HTTPrettyRequest
......@@ -144,7 +146,7 @@ def mock_file_downloads(
) -> None:
def callback(
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
fixture = Path(__file__).parent.parent.joinpath(
......@@ -184,7 +186,7 @@ def copy_wheel(tmp_path: Path, fixture_dir: FixtureDirGetter) -> Callable[[], Pa
@pytest.fixture
def wheel(copy_wheel: Callable[[], Path]) -> Path:
def wheel(copy_wheel: Callable[[], Path]) -> Iterator[Path]:
archive = copy_wheel()
yield archive
......@@ -267,9 +269,9 @@ Package operations: 4 installs, 1 update, 1 removal
• Installing demo (0.1.0 master)
"""
expected = set(expected.splitlines())
output = set(io.fetch_output().splitlines())
assert output == expected
expected_lines = set(expected.splitlines())
output_lines = set(io.fetch_output().splitlines())
assert output_lines == expected_lines
assert wheel_install.call_count == 5
# Two pip uninstalls: one for the remove operation one for the update operation
assert len(env.executed) == 2
......@@ -513,9 +515,9 @@ Package operations: 1 install, 0 updates, 0 removals
• Installing cleo (1.0.0a5)
"""
expected = set(expected.splitlines())
output = set(io_not_decorated.fetch_output().splitlines())
assert output == expected
expected_lines = set(expected.splitlines())
output_lines = set(io_not_decorated.fetch_output().splitlines())
assert output_lines == expected_lines
assert return_code == 0
......@@ -622,10 +624,14 @@ def verify_installed_distribution(
assert metadata["Name"] == package.name
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:
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:
reader = csv.reader(f)
rows = list(reader)
......@@ -855,6 +861,7 @@ def test_executor_should_write_pep610_url_references_for_wheel_urls(
if is_artifact_cached:
download_spy.assert_not_called()
else:
assert package.source_url is not None
download_spy.assert_called_once_with(
mocker.ANY, operation, Link(package.source_url)
)
......@@ -948,6 +955,7 @@ def test_executor_should_write_pep610_url_references_for_non_wheel_urls(
mock_prepare.assert_not_called()
if expect_artifact_download:
assert package.source_url is not None
download_spy.assert_called_once_with(
mocker.ANY, operation, Link(package.source_url)
)
......@@ -1053,6 +1061,7 @@ def test_executor_should_write_pep610_url_references_for_editable_git(
executor = Executor(tmp_venv, pool, config, io)
executor._chef = chef
executor.execute([Install(package)])
assert package.source_url is not None
verify_installed_distribution(
tmp_venv,
package,
......@@ -1218,9 +1227,9 @@ Package operations: 1 install, 0 updates, 0 removals
• Installing simple-project (1.2.3 {directory_package.source_url})
"""
expected = set(expected.splitlines())
output = set(io.fetch_output().splitlines())
assert output == expected
expected_lines = set(expected.splitlines())
output_lines = set(io.fetch_output().splitlines())
assert output_lines == expected_lines
assert return_code == 0
assert mock_create_poetry.call_count == 1
assert mock_sdist_builder.call_count == 0
......@@ -1281,6 +1290,7 @@ Package operations: 1 install, 0 updates, 0 removals
Error on stdout
"""
assert directory_package.source_url is not None
if editable:
pip_command = "pip wheel --use-pep517 --editable"
requirement = directory_package.source_url
......
......@@ -711,6 +711,7 @@ def test_run_install_with_synchronization(
*managed_reserved_package_names,
}
assert isinstance(installer.executor, Executor)
assert {r.name for r in installer.executor.removals} == expected_removals
......@@ -906,6 +907,7 @@ def test_run_with_optional_and_python_restricted_dependencies(
# We should only have 2 installs:
# C,D since python version is not compatible
# with B's python constraint and A is optional
assert isinstance(installer.executor, Executor)
assert installer.executor.installations_count == 2
assert installer.executor.installations[0].name == "d"
assert installer.executor.installations[1].name == "c"
......@@ -953,6 +955,7 @@ def test_run_with_optional_and_platform_restricted_dependencies(
# We should only have 2 installs:
# C,D since the mocked python version is not compatible
# with B's python constraint and A is optional
assert isinstance(installer.executor, Executor)
assert installer.executor.installations_count == 2
assert installer.executor.installations[0].name == "d"
assert installer.executor.installations[1].name == "c"
......@@ -1297,6 +1300,7 @@ def test_run_installs_with_local_poetry_directory_and_skip_directory_flag(
assert locker.written_data == expected
assert isinstance(installer.executor, Executor)
directory_installs = [
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(
assert locker.written_data == expected
assert isinstance(installer.executor, Executor)
installs = installer.executor.installations
assert installer.executor.installations_count == 3
assert installs[0] == package_c12
......@@ -1982,6 +1987,7 @@ def test_installer_required_extras_should_not_be_removed_when_updating_single_de
locker.locked(True)
locker.mock_lock_data(locker.written_data)
assert isinstance(installer.executor, Executor)
for pkg in installer.executor.installations:
installed.add_package(pkg)
......@@ -2240,6 +2246,7 @@ def test_run_installs_with_same_version_url_files(
expected = fixture("with-same-version-url-dependencies")
assert locker.written_data == expected
assert isinstance(installer.executor, Executor)
assert installer.executor.installations_count == 2
demo_package = next(p for p in installer.executor.installations if p.name == "demo")
assert demo_package.source_url == urls[env_platform]
......@@ -2456,6 +2463,7 @@ def test_installer_should_use_the_locked_version_of_git_dependencies(
result = installer.run()
assert result == 0
assert isinstance(installer.executor, Executor)
assert installer.executor.installations[-1] == Package(
"demo",
"0.1.1",
......@@ -2498,6 +2506,7 @@ def test_installer_should_use_the_locked_version_of_git_dependencies_with_extras
result = installer.run()
assert result == 0
assert isinstance(installer.executor, Executor)
assert len(installer.executor.installations) == 3
assert installer.executor.installations[-1] == Package(
"demo",
......@@ -2537,6 +2546,7 @@ def test_installer_should_use_the_locked_version_of_git_dependencies_without_ref
result = installer.run()
assert result == 0
assert isinstance(installer.executor, Executor)
assert len(installer.executor.installations) == 2
assert installer.executor.installations[-1] == Package(
"demo",
......@@ -2640,6 +2650,7 @@ def test_installer_distinguishes_locked_packages_by_source(
)
source_reference = None if env_platform == "darwin" else "pytorch"
assert isinstance(installer.executor, Executor)
assert len(installer.executor.installations) == 1
assert installer.executor.installations[0] == Package(
"torch",
......
......@@ -7,6 +7,7 @@ from copy import deepcopy
from hashlib import sha1
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Iterator
import pytest
......@@ -79,9 +80,11 @@ def source_directory_name(source_url: str) -> str:
@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(
tmp_path_factory.mktemp("src") / source_directory_name, mkdir=True
str(tmp_path_factory.mktemp("src") / source_directory_name), mkdir=True
) as repo:
yield repo
......@@ -103,7 +106,8 @@ def remote_refs(_remote_refs: FetchPackResult) -> FetchPackResult:
@pytest.fixture(scope="module")
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")
......@@ -269,7 +273,11 @@ def test_system_git_fallback_on_http_401(
source_url: str,
) -> None:
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:
path = Path(repo.path)
......
from __future__ import annotations
from pathlib import Path
from typing import Any
from poetry.factory import Factory
from poetry.toml import TOMLFile
......@@ -10,19 +11,21 @@ FIXTURE_DIR = Path(__file__).parent / "fixtures" / "source"
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"]
assert Factory.validate(content) == {"errors": [], "warnings": []}
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"]
assert Factory.validate(content) == {"errors": [], "warnings": []}
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"]
assert Factory.validate(content) == {
"errors": [
......@@ -34,7 +37,7 @@ def test_pyproject_toml_invalid_priority() -> 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"
).read()
content = toml["tool"]["poetry"]
......
......@@ -7,6 +7,7 @@ import shutil
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Iterator
import pytest
......@@ -72,7 +73,7 @@ def env_manager(simple_poetry: Poetry) -> EnvManager:
@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"
env_manager.build_venv(venv_path)
......
......@@ -13,6 +13,7 @@ from typing import TYPE_CHECKING
import pytest
from packaging.utils import canonicalize_name
from poetry.core.constraints.version import Version
from poetry.core.packages.package import Package
from poetry.core.packages.project_package import ProjectPackage
......@@ -234,7 +235,7 @@ content-hash = "c3d07fca33fba542ef2b2a4d75bf5b48d892d21a830e2ad9c952ba5123a52f77
assert len(package.requires) == 3
assert len(package.extras) == 2
lockfile_dep = package.extras["filecache"][0]
lockfile_dep = package.extras[canonicalize_name("filecache")][0]
assert lockfile_dep.name == "lockfile"
......@@ -297,7 +298,7 @@ content-hash = "123456789"
assert len(package.requires) == 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.extras == frozenset({"c"})
......@@ -308,7 +309,7 @@ content-hash = "123456789"
assert len(package.requires) == 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.extras == frozenset()
......@@ -361,7 +362,7 @@ content-hash = "123456789"
assert len(package.requires) == 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"
......@@ -515,7 +516,7 @@ def test_lock_packages_with_null_description(
locker: Locker, root: ProjectPackage
) -> None:
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])
......@@ -551,7 +552,7 @@ def test_lock_file_should_not_have_mixed_types(
Factory.create_dependency("B", {"version": ">=1.0.0", "optional": True})
)
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])
......@@ -723,8 +724,8 @@ def test_root_extras_dependencies_are_ordered(
package_third = Factory.create_dependency("third", "1.0.0", root_dir=fixture_base)
root.extras = {
"C": [package_third, package_second, package_first],
"B": [package_first, package_second, package_third],
canonicalize_name("C"): [package_third, package_second, package_first],
canonicalize_name("B"): [package_first, package_second, package_third],
}
locker.set_lock_data(root, [])
......@@ -733,8 +734,8 @@ def test_root_extras_dependencies_are_ordered(
package = []
[extras]
B = ["first", "second", "third"]
C = ["first", "second", "third"]
b = ["first", "second", "third"]
c = ["first", "second", "third"]
[metadata]
lock-version = "2.0"
......@@ -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_a.extras = {
"C": [package_third, package_second, package_first],
"B": [package_first, package_second, package_third],
canonicalize_name("C"): [package_third, package_second, package_first],
canonicalize_name("B"): [package_first, package_second, package_third],
}
locker.set_lock_data(root, [package_a])
......@@ -972,8 +973,8 @@ python-versions = "*"
files = []
[package.extras]
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)"]
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)"]
[metadata]
lock-version = "2.0"
......
......@@ -6,6 +6,7 @@ from typing import TYPE_CHECKING
import pytest
from cleo.io.buffered_io import BufferedIO
from poetry.core.constraints.version import Version
from poetry.core.packages.project_package import ProjectPackage
from poetry.packages.locker import Locker
......@@ -43,7 +44,7 @@ class MyCommandPlugin(ApplicationPlugin):
class InvalidPlugin:
def activate(self, poetry: Poetry, io: IO) -> None:
io.write_line("Updating version")
poetry.package.version = "9.9.9"
poetry.package.version = Version.parse("9.9.9")
@pytest.fixture
......
......@@ -7,6 +7,7 @@ from typing import Any
import pytest
from cleo.io.null_io import NullIO
from packaging.utils import canonicalize_name
from poetry.core.packages.dependency import Dependency
from poetry.core.packages.directory_dependency import DirectoryDependency
from poetry.core.packages.file_dependency import FileDependency
......@@ -681,7 +682,7 @@ def test_complete_package_with_extras_preserves_source_name(
package_b = Package("B", "1.0")
dep = get_dependency("B", "^1.0", optional=True)
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_b)
......@@ -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.add_dependency(optional_vcs_dependency)
package.extras["foo"] = [optional_vcs_dependency]
package.extras[canonicalize_name("foo")] = [optional_vcs_dependency]
repository.add_package(package)
spy = mocker.spy(provider, "_search_for_vcs")
......
from __future__ import annotations
from collections import namedtuple
from pathlib import Path
from typing import TYPE_CHECKING
from typing import NamedTuple
import pytest
......@@ -26,7 +26,10 @@ INSTALLED_RESULTS = [
metadata.PathDistribution(SITE_PURELIB / "cleo-0.7.6.dist-info"),
metadata.PathDistribution(SRC / "pendulum" / "pendulum.egg-info"),
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 / "editable-2.3.4.dist-info"),
......@@ -69,9 +72,13 @@ def env() -> MockEnv:
@pytest.fixture(autouse=True)
def mock_git_info(mocker: MockerFixture) -> None:
class GitRepoLocalInfo(NamedTuple):
origin: str
revision: str
mocker.patch(
"poetry.vcs.git.Git.info",
return_value=namedtuple("GitRepoLocalInfo", "origin revision")(
return_value=GitRepoLocalInfo(
origin="https://github.com/sdispater/pendulum.git",
revision="bb058f6b78b2d28ef5d9a5e759cfa179a1a713d6",
),
......
......@@ -10,6 +10,7 @@ from typing import Any
import pytest
from packaging.utils import canonicalize_name
from poetry.core.constraints.version import Version
from poetry.core.packages.dependency import Dependency
from requests.exceptions import TooManyRedirects
......@@ -62,7 +63,8 @@ class MockRepository(PyPiRepository):
return None
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:
filename = url.split("/")[-1]
......@@ -129,8 +131,8 @@ def test_package() -> None:
assert package.name == "requests"
assert len(package.requires) == 9
assert len([r for r in package.requires if r.is_optional()]) == 5
assert len(package.extras["security"]) == 3
assert len(package.extras["socks"]) == 2
assert len(package.extras[canonicalize_name("security")]) == 3
assert len(package.extras[canonicalize_name("socks")]) == 2
assert package.files == [
{
......@@ -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.python_versions == "~2.7 || ~2.6"
......@@ -299,7 +301,10 @@ def test_pypi_repository_supports_reading_bz2_files() -> None:
}
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:
......@@ -353,7 +358,9 @@ def test_find_links_for_package_of_supported_types() -> None:
def test_get_release_info_includes_only_supported_types() -> None:
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 release_info["files"][0]["file"] == "hbmqtt-0.9.6.tar.gz"
from __future__ import annotations
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Any
import pytest
......@@ -8,6 +10,7 @@ from cleo.io.buffered_io import BufferedIO
from deepdiff import DeepDiff
from packaging.utils import canonicalize_name
from poetry.core.constraints.version import parse_constraint
from poetry.core.packages.vcs_dependency import VCSDependency
from poetry.exceptions import PoetryException
from poetry.factory import Factory
......@@ -32,7 +35,7 @@ if TYPE_CHECKING:
class MyPlugin(Plugin):
def activate(self, poetry: Poetry, io: IO) -> None:
io.write_line("Setting readmes")
poetry.package.readmes = ("README.md",)
poetry.package.readmes = (Path("README.md"),)
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.description == "Some description."
assert package.authors == ["Sébastien Eustace <sebastien@eustace.io>"]
assert package.license is not None
assert package.license.id == "MIT"
for readme in package.readmes:
......@@ -62,51 +66,52 @@ def test_create_poetry(fixture_dir: FixtureDirGetter) -> None:
for dep in package.requires:
dependencies[dep.name] = dep
cleo = dependencies["cleo"]
cleo = dependencies[canonicalize_name("cleo")]
assert cleo.pretty_constraint == "^0.6"
assert not cleo.is_optional()
pendulum = dependencies["pendulum"]
pendulum = dependencies[canonicalize_name("pendulum")]
assert pendulum.pretty_constraint == "branch 2.0"
assert pendulum.is_vcs()
assert isinstance(pendulum, VCSDependency)
assert pendulum.vcs == "git"
assert pendulum.branch == "2.0"
assert pendulum.source == "https://github.com/sdispater/pendulum.git"
assert pendulum.allows_prereleases()
requests = dependencies["requests"]
requests = dependencies[canonicalize_name("requests")]
assert requests.pretty_constraint == "^2.18"
assert not requests.is_vcs()
assert not requests.allows_prereleases()
assert requests.is_optional()
assert requests.extras == frozenset(["security"])
pathlib2 = dependencies["pathlib2"]
pathlib2 = dependencies[canonicalize_name("pathlib2")]
assert pathlib2.pretty_constraint == "^2.2"
assert parse_constraint(pathlib2.python_versions) == parse_constraint("~2.7")
assert not pathlib2.is_optional()
demo = dependencies["demo"]
demo = dependencies[canonicalize_name("demo")]
assert demo.is_file()
assert not demo.is_vcs()
assert demo.name == "demo"
assert demo.pretty_constraint == "*"
demo = dependencies["my-package"]
demo = dependencies[canonicalize_name("my-package")]
assert not demo.is_file()
assert demo.is_directory()
assert not demo.is_vcs()
assert demo.name == "my-package"
assert demo.pretty_constraint == "*"
simple_project = dependencies["simple-project"]
simple_project = dependencies[canonicalize_name("simple-project")]
assert not simple_project.is_file()
assert simple_project.is_directory()
assert not simple_project.is_vcs()
assert simple_project.name == "simple-project"
assert simple_project.pretty_constraint == "*"
functools32 = dependencies["functools32"]
functools32 = dependencies[canonicalize_name("functools32")]
assert functools32.name == "functools32"
assert functools32.pretty_constraint == "^3.2.3"
assert (
......@@ -153,7 +158,7 @@ def test_create_pyproject_from_package(
poetry = Factory().create_poetry(fixture_dir(project))
package = poetry.package
pyproject = Factory.create_pyproject_from_package(package)
pyproject: dict[str, Any] = Factory.create_pyproject_from_package(package)
result = pyproject["tool"]["poetry"]
expected = poetry.pyproject.poetry_config
......@@ -465,14 +470,16 @@ def test_poetry_with_two_default_sources(
def test_validate(fixture_dir: FixtureDirGetter) -> None:
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": []}
def test_validate_fails(fixture_dir: FixtureDirGetter) -> None:
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"] = ""
expected = (
......@@ -515,7 +522,7 @@ def test_create_poetry_with_plugins(
poetry = Factory().create_poetry(fixture_dir("sample_project"))
assert poetry.package.readmes == ("README.md",)
assert poetry.package.readmes == (Path("README.md"),)
@pytest.mark.parametrize(
......
......@@ -996,7 +996,7 @@ def test_run_with_keyboard_interrupt(
mocker.patch("subprocess.run", side_effect=KeyboardInterrupt())
with pytest.raises(KeyboardInterrupt):
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(
......@@ -1006,7 +1006,7 @@ def test_call_with_input_and_keyboard_interrupt(
kwargs = {"call": True}
with pytest.raises(KeyboardInterrupt):
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(
......@@ -1016,7 +1016,7 @@ def test_call_no_input_with_keyboard_interrupt(
kwargs = {"call": True}
with pytest.raises(KeyboardInterrupt):
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(
......@@ -1030,7 +1030,7 @@ def test_run_with_called_process_error(
)
with pytest.raises(EnvCommandError) as error:
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 error" in str(error.value)
......@@ -1047,7 +1047,7 @@ def test_call_with_input_and_called_process_error(
kwargs = {"call": True}
with pytest.raises(EnvCommandError) as error:
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 error" in str(error.value)
......@@ -1064,7 +1064,7 @@ def test_call_no_input_with_called_process_error(
kwargs = {"call": True}
with pytest.raises(EnvCommandError) as error:
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 error" in str(error.value)
......@@ -1080,7 +1080,7 @@ def test_check_output_with_called_process_error(
)
with pytest.raises(EnvCommandError) as error:
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 error" in str(error.value)
......@@ -1730,7 +1730,7 @@ def test_build_environment_called_build_script_specified(
with build_environment(extended_without_setup_poetry, project_env) as env:
assert env == ephemeral_env
assert env.executed == [
assert env.executed == [ # type: ignore[attr-defined]
[
str(sys.executable),
str(env.pip_embedded),
......@@ -1755,7 +1755,7 @@ def test_build_environment_not_called_without_build_script_specified(
with build_environment(poetry, project_env) as 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(
......
from __future__ import annotations
from typing import TYPE_CHECKING
import pytest
from poetry.core.packages.package import Package
......@@ -8,6 +10,9 @@ from poetry.factory import Factory
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_SPAM = Package("spam", "0.2.0")
_PACKAGE_BAR = Package("bar", "0.3.0")
......@@ -60,8 +65,8 @@ _PACKAGE_QUIX.add_dependency(Factory.create_dependency("baz", "*"))
)
def test_get_extra_package_names(
packages: list[Package],
extras: dict[str, list[str]],
extra_names: list[str],
extras: dict[NormalizedName, list[NormalizedName]],
extra_names: list[NormalizedName],
expected_extra_package_names: set[str],
) -> None:
assert (
......
......@@ -36,6 +36,7 @@ from poetry.utils import patterns
)
def test_wheel_file_re(filename: str, expected: dict[str, str | None]) -> None:
match = patterns.wheel_file_re.match(filename)
assert match is not None
groups = match.groupdict()
assert groups == expected
......@@ -37,4 +37,4 @@ def test_pip_install_with_keyboard_interrupt(
mocker.patch("subprocess.run", side_effect=KeyboardInterrupt())
with pytest.raises(KeyboardInterrupt):
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(
expected_name = "SQLAlchemy"
expected_version = None
expected_install_requires = []
expected_install_requires: list[str] = []
expected_extras_require = {
"mysql": ["mysqlclient"],
"pymysql": ["pymysql"],
......@@ -154,8 +154,8 @@ def test_setup_reader_read_setup_call_in_main(setup: Callable[[str], Path]) -> N
expected_name = "PyYAML"
expected_version = "3.13"
expected_install_requires = []
expected_extras_require = {}
expected_install_requires: list[str] = []
expected_extras_require: dict[str, list[str]] = {}
expected_python_requires = None
assert result["name"] == expected_name
......@@ -172,7 +172,7 @@ def test_setup_reader_read_extras_require_with_variables(
expected_name = "extras_require_with_vars"
expected_version = "0.0.1"
expected_install_requires = []
expected_install_requires: list[str] = []
expected_extras_require = {"test": ["pytest"]}
expected_python_requires = None
......
......@@ -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:
table = Table(Container(), Trivia(), False)
table._value = table_body
table._value = table_body # type: ignore[assignment]
assert source_to_table(source) == table
......@@ -70,5 +70,9 @@ def test_source_legacy_handling(
],
)
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
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