test_solver.py (poetry-1.1.15) | : | test_solver.py (poetry-1.2.0) | ||
---|---|---|---|---|
import pytest | from __future__ import annotations | |||
from pathlib import Path | ||||
from typing import TYPE_CHECKING | ||||
from typing import Any | ||||
from clikit.io import NullIO | import pytest | |||
from poetry.core.packages import Package | from cleo.io.buffered_io import BufferedIO | |||
from poetry.core.packages import ProjectPackage | from cleo.io.null_io import NullIO | |||
from poetry.core.packages import dependency_from_pep_508 | from poetry.core.packages.dependency import Dependency | |||
from poetry.core.packages.package import Package | ||||
from poetry.core.packages.project_package import ProjectPackage | ||||
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.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 | |||
from poetry.puzzle.provider import Provider as BaseProvider | from poetry.puzzle.provider import Provider as BaseProvider | |||
from poetry.repositories.installed_repository import InstalledRepository | from poetry.repositories.installed_repository import InstalledRepository | |||
from poetry.repositories.pool import Pool | from poetry.repositories.pool import Pool | |||
from poetry.repositories.repository import Repository | from poetry.repositories.repository import Repository | |||
from poetry.utils._compat import Path | ||||
from poetry.utils.env import MockEnv | from poetry.utils.env import MockEnv | |||
from tests.helpers import MOCK_DEFAULT_GIT_REVISION | ||||
from tests.helpers import get_dependency | from tests.helpers import get_dependency | |||
from tests.helpers import get_package | from tests.helpers import get_package | |||
from tests.repositories.test_legacy_repository import ( | from tests.repositories.test_legacy_repository import ( | |||
MockRepository as MockLegacyRepository, | MockRepository as MockLegacyRepository, | |||
) | ) | |||
from tests.repositories.test_pypi_repository import MockRepository as MockPyPIRe pository | from tests.repositories.test_pypi_repository import MockRepository as MockPyPIRe pository | |||
if TYPE_CHECKING: | ||||
import httpretty | ||||
from poetry.installation.operations.operation import Operation | ||||
from poetry.puzzle.transaction import Transaction | ||||
DEFAULT_SOURCE_REF = ( | ||||
VCSDependency("poetry", "git", "git@github.com:python-poetry/poetry.git").br | ||||
anch | ||||
or "HEAD" | ||||
) | ||||
class Provider(BaseProvider): | class Provider(BaseProvider): | |||
def set_package_python_versions(self, python_versions): | def set_package_python_versions(self, python_versions: str) -> None: | |||
self._package.python_versions = python_versions | self._package.python_versions = python_versions | |||
self._python_constraint = self._package.python_constraint | self._python_constraint = self._package.python_constraint | |||
@pytest.fixture() | @pytest.fixture() | |||
def io(): | def io() -> NullIO: | |||
return NullIO() | return NullIO() | |||
@pytest.fixture() | @pytest.fixture() | |||
def package(): | def package() -> ProjectPackage: | |||
return ProjectPackage("root", "1.0") | return ProjectPackage("root", "1.0") | |||
@pytest.fixture() | @pytest.fixture() | |||
def installed(): | def installed() -> InstalledRepository: | |||
return InstalledRepository() | return InstalledRepository() | |||
@pytest.fixture() | @pytest.fixture() | |||
def locked(): | def locked() -> Repository: | |||
return Repository() | return Repository("locked") | |||
@pytest.fixture() | @pytest.fixture() | |||
def repo(): | def repo() -> Repository: | |||
return Repository() | return Repository("repo") | |||
@pytest.fixture() | @pytest.fixture() | |||
def pool(repo): | def pool(repo: Repository) -> Pool: | |||
return Pool([repo]) | return Pool([repo]) | |||
@pytest.fixture() | @pytest.fixture() | |||
def solver(package, pool, installed, locked, io): | def solver( | |||
package: ProjectPackage, | ||||
pool: Pool, | ||||
installed: InstalledRepository, | ||||
locked: Repository, | ||||
io: NullIO, | ||||
) -> Solver: | ||||
return Solver( | return Solver( | |||
package, pool, installed, locked, io, provider=Provider(package, pool, i | package, | |||
o) | pool, | |||
installed.packages, | ||||
locked.packages, | ||||
io, | ||||
provider=Provider(package, pool, io, installed=installed.packages), | ||||
) | ) | |||
def check_solver_result(ops, expected): | def check_solver_result( | |||
transaction: Transaction, | ||||
expected: list[dict[str, Any]], | ||||
synchronize: bool = False, | ||||
) -> list[Operation]: | ||||
for e in expected: | for e in expected: | |||
if "skipped" not in e: | if "skipped" not in e: | |||
e["skipped"] = False | e["skipped"] = False | |||
result = [] | result = [] | |||
ops = transaction.calculate_operations(synchronize=synchronize) | ||||
for op in ops: | for op in ops: | |||
if "update" == op.job_type: | if op.job_type == "update": | |||
result.append( | result.append( | |||
{ | { | |||
"job": "update", | "job": "update", | |||
"from": op.initial_package, | "from": op.initial_package, | |||
"to": op.target_package, | "to": op.target_package, | |||
"skipped": op.skipped, | "skipped": op.skipped, | |||
} | } | |||
) | ) | |||
else: | else: | |||
job = "install" | job = "install" | |||
if op.job_type == "uninstall": | if op.job_type == "uninstall": | |||
job = "remove" | job = "remove" | |||
result.append({"job": job, "package": op.package, "skipped": op.skip ped}) | result.append({"job": job, "package": op.package, "skipped": op.skip ped}) | |||
assert expected == result | assert result == expected | |||
def test_solver_install_single(solver, repo, package): | return ops | |||
def test_solver_install_single( | ||||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
ops = solver.solve([get_dependency("A")]) | transaction = solver.solve([get_dependency("A")]) | |||
check_solver_result(ops, [{"job": "install", "package": package_a}]) | check_solver_result(transaction, [{"job": "install", "package": package_a}]) | |||
def test_solver_remove_if_no_longer_locked(solver, locked, installed): | def test_solver_remove_if_no_longer_locked( | |||
solver: Solver, locked: Repository, installed: InstalledRepository | ||||
): | ||||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
installed.add_package(package_a) | installed.add_package(package_a) | |||
locked.add_package(package_a) | locked.add_package(package_a) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result(ops, [{"job": "remove", "package": package_a}]) | check_solver_result(transaction, [{"job": "remove", "package": package_a}]) | |||
def test_remove_non_installed(solver, repo, locked): | def test_remove_non_installed(solver: Solver, repo: Repository, locked: Reposito ry): | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
locked.add_package(package_a) | locked.add_package(package_a) | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
request = [] | request = [] | |||
ops = solver.solve(request) | transaction = solver.solve(request) | |||
check_solver_result(ops, [{"job": "remove", "package": package_a, "skipped": True}]) | check_solver_result(transaction, []) | |||
def test_install_non_existing_package_fail(solver, repo, package): | def test_install_non_existing_package_fail( | |||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
package.add_dependency(Factory.create_dependency("B", "1")) | package.add_dependency(Factory.create_dependency("B", "1")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
with pytest.raises(SolverProblemError): | with pytest.raises(SolverProblemError): | |||
solver.solve() | solver.solve() | |||
def test_solver_with_deps(solver, repo, package): | def test_install_unpublished_package_does_not_fail( | |||
installed: InstalledRepository, | ||||
solver: Solver, | ||||
repo: Repository, | ||||
package: ProjectPackage, | ||||
): | ||||
package.add_dependency(Factory.create_dependency("B", "1")) | ||||
package_a = get_package("A", "1.0") | ||||
package_b = get_package("B", "1") | ||||
package_b.add_dependency(Factory.create_dependency("A", "1.0")) | ||||
repo.add_package(package_a) | ||||
installed.add_package(package_b) | ||||
transaction = solver.solve() | ||||
check_solver_result( | ||||
transaction, | ||||
[ | ||||
{"job": "install", "package": package_a}, | ||||
{ | ||||
"job": "install", | ||||
"package": package_b, | ||||
"skipped": True, # already installed | ||||
}, | ||||
], | ||||
) | ||||
def test_solver_with_deps(solver: Solver, repo: Repository, package: ProjectPack | ||||
age): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
package_b = get_package("B", "1.0") | package_b = get_package("B", "1.0") | |||
new_package_b = get_package("B", "1.1") | new_package_b = get_package("B", "1.1") | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(new_package_b) | repo.add_package(new_package_b) | |||
package_a.requires.append(get_dependency("B", "<1.1")) | package_a.add_dependency(get_dependency("B", "<1.1")) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
], | ], | |||
) | ) | |||
def test_install_honours_not_equal(solver, repo, package): | def test_install_honours_not_equal( | |||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
package_b = get_package("B", "1.0") | package_b = get_package("B", "1.0") | |||
new_package_b11 = get_package("B", "1.1") | new_package_b11 = get_package("B", "1.1") | |||
new_package_b12 = get_package("B", "1.2") | new_package_b12 = get_package("B", "1.2") | |||
new_package_b13 = get_package("B", "1.3") | new_package_b13 = get_package("B", "1.3") | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(new_package_b11) | repo.add_package(new_package_b11) | |||
repo.add_package(new_package_b12) | repo.add_package(new_package_b12) | |||
repo.add_package(new_package_b13) | repo.add_package(new_package_b13) | |||
package_a.requires.append(get_dependency("B", "<=1.3,!=1.3,!=1.2")) | package_a.add_dependency(get_dependency("B", "<=1.3,!=1.3,!=1.2")) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": new_package_b11}, | {"job": "install", "package": new_package_b11}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
], | ], | |||
) | ) | |||
def test_install_with_deps_in_order(solver, repo, package): | def test_install_with_deps_in_order( | |||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package.add_dependency(Factory.create_dependency("B", "*")) | package.add_dependency(Factory.create_dependency("B", "*")) | |||
package.add_dependency(Factory.create_dependency("C", "*")) | package.add_dependency(Factory.create_dependency("C", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
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") | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(package_c) | repo.add_package(package_c) | |||
package_b.requires.append(get_dependency("A", ">=1.0")) | package_b.add_dependency(get_dependency("A", ">=1.0")) | |||
package_b.requires.append(get_dependency("C", ">=1.0")) | package_b.add_dependency(get_dependency("C", ">=1.0")) | |||
package_c.requires.append(get_dependency("A", ">=1.0")) | package_c.add_dependency(get_dependency("A", ">=1.0")) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
{"job": "install", "package": package_c}, | {"job": "install", "package": package_c}, | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
], | ], | |||
) | ) | |||
def test_install_installed(solver, repo, installed, package): | def test_install_installed( | |||
solver: Solver, | ||||
repo: Repository, | ||||
installed: InstalledRepository, | ||||
package: ProjectPackage, | ||||
): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
installed.add_package(package_a) | installed.add_package(package_a) | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, [{"job": "install", "package": package_a, "skipped": True}] | transaction, [{"job": "install", "package": package_a, "skipped": True}] | |||
) | ) | |||
def test_update_installed(solver, repo, installed, package): | def test_update_installed( | |||
solver: Solver, | ||||
repo: Repository, | ||||
installed: InstalledRepository, | ||||
package: ProjectPackage, | ||||
): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
installed.add_package(get_package("A", "1.0")) | installed.add_package(get_package("A", "1.0")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
new_package_a = get_package("A", "1.1") | new_package_a = get_package("A", "1.1") | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(new_package_a) | repo.add_package(new_package_a) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, [{"job": "update", "from": package_a, "to": new_package_a}] | transaction, [{"job": "update", "from": package_a, "to": new_package_a}] | |||
) | ) | |||
def test_update_with_use_latest(solver, repo, installed, package, locked): | def test_update_with_use_latest( | |||
solver: Solver, | ||||
repo: Repository, | ||||
installed: InstalledRepository, | ||||
package: ProjectPackage, | ||||
locked: Repository, | ||||
): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package.add_dependency(Factory.create_dependency("B", "*")) | package.add_dependency(Factory.create_dependency("B", "*")) | |||
installed.add_package(get_package("A", "1.0")) | installed.add_package(get_package("A", "1.0")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
new_package_a = get_package("A", "1.1") | new_package_a = get_package("A", "1.1") | |||
package_b = get_package("B", "1.0") | package_b = get_package("B", "1.0") | |||
new_package_b = get_package("B", "1.1") | new_package_b = get_package("B", "1.1") | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(new_package_a) | repo.add_package(new_package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(new_package_b) | repo.add_package(new_package_b) | |||
locked.add_package(package_a) | locked.add_package(package_a) | |||
locked.add_package(package_b) | locked.add_package(package_b) | |||
ops = solver.solve(use_latest=[package_b.name]) | transaction = solver.solve(use_latest=[package_b.name]) | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_a, "skipped": True}, | {"job": "install", "package": package_a, "skipped": True}, | |||
{"job": "install", "package": new_package_b}, | {"job": "install", "package": new_package_b}, | |||
], | ], | |||
) | ) | |||
def test_solver_sets_categories(solver, repo, package): | def test_solver_sets_groups(solver: Solver, repo: Repository, package: ProjectPa ckage): | |||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package.add_dependency(Factory.create_dependency("B", "*", category="dev")) | package.add_dependency(Factory.create_dependency("B", "*", groups=["dev"])) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
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.add_dependency(Factory.create_dependency("C", "~1.0")) | package_b.add_dependency(Factory.create_dependency("C", "~1.0")) | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(package_c) | repo.add_package(package_c) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_c}, | {"job": "install", "package": package_c}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
], | ], | |||
) | ) | |||
assert ops[0].package.category == "dev" | assert ops[0].package.category == "dev" | |||
assert ops[2].package.category == "dev" | assert ops[2].package.category == "dev" | |||
assert ops[1].package.category == "main" | assert ops[1].package.category == "main" | |||
def test_solver_respects_root_package_python_versions(solver, repo, package): | def test_solver_respects_root_package_python_versions( | |||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
solver.provider.set_package_python_versions("~3.4") | solver.provider.set_package_python_versions("~3.4") | |||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package.add_dependency(Factory.create_dependency("B", "*")) | package.add_dependency(Factory.create_dependency("B", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
package_b = get_package("B", "1.0") | package_b = get_package("B", "1.0") | |||
package_b.python_versions = "^3.3" | package_b.python_versions = "^3.3" | |||
package_c = get_package("C", "1.0") | package_c = get_package("C", "1.0") | |||
package_c.python_versions = "^3.4" | package_c.python_versions = "^3.4" | |||
package_c11 = get_package("C", "1.1") | package_c11 = get_package("C", "1.1") | |||
package_c11.python_versions = "^3.6" | package_c11.python_versions = "^3.6" | |||
package_b.add_dependency(Factory.create_dependency("C", "^1.0")) | package_b.add_dependency(Factory.create_dependency("C", "^1.0")) | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(package_c) | repo.add_package(package_c) | |||
repo.add_package(package_c11) | repo.add_package(package_c11) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_c}, | {"job": "install", "package": package_c}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
], | ], | |||
) | ) | |||
def test_solver_fails_if_mismatch_root_python_versions(solver, repo, package): | def test_solver_fails_if_mismatch_root_python_versions( | |||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
solver.provider.set_package_python_versions("^3.4") | solver.provider.set_package_python_versions("^3.4") | |||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package.add_dependency(Factory.create_dependency("B", "*")) | package.add_dependency(Factory.create_dependency("B", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
package_b = get_package("B", "1.0") | package_b = get_package("B", "1.0") | |||
package_b.python_versions = "^3.6" | package_b.python_versions = "^3.6" | |||
package_c = get_package("C", "1.0") | package_c = get_package("C", "1.0") | |||
package_c.python_versions = "~3.3" | package_c.python_versions = "~3.3" | |||
package_b.add_dependency(Factory.create_dependency("C", "~1.0")) | package_b.add_dependency(Factory.create_dependency("C", "~1.0")) | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(package_c) | repo.add_package(package_c) | |||
with pytest.raises(SolverProblemError): | with pytest.raises(SolverProblemError): | |||
solver.solve() | solver.solve() | |||
def test_solver_solves_optional_and_compatible_packages(solver, repo, package): | def test_solver_ignores_python_restricted_if_mismatch_root_package_python_versio | |||
ns( | ||||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
solver.provider.set_package_python_versions("~3.8") | ||||
package.add_dependency( | ||||
Factory.create_dependency("A", {"version": "1.0", "python": "<3.8"}) | ||||
) | ||||
package.add_dependency( | ||||
Factory.create_dependency( | ||||
"B", {"version": "1.0", "markers": "python_version < '3.8'"} | ||||
) | ||||
) | ||||
package_a = get_package("A", "1.0") | ||||
package_b = get_package("B", "1.0") | ||||
repo.add_package(package_a) | ||||
repo.add_package(package_b) | ||||
transaction = solver.solve() | ||||
check_solver_result(transaction, []) | ||||
def test_solver_solves_optional_and_compatible_packages( | ||||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
solver.provider.set_package_python_versions("~3.4") | solver.provider.set_package_python_versions("~3.4") | |||
package.extras["foo"] = [get_dependency("B")] | package.extras["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"}) | |||
) | ) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("B", {"version": "*", "optional": True}) | Factory.create_dependency("B", {"version": "*", "optional": True}) | |||
) | ) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
package_b = get_package("B", "1.0") | package_b = get_package("B", "1.0") | |||
package_b.python_versions = "^3.3" | package_b.python_versions = "^3.3" | |||
package_c = get_package("C", "1.0") | package_c = get_package("C", "1.0") | |||
package_c.python_versions = "^3.4" | package_c.python_versions = "^3.4" | |||
package_b.add_dependency(Factory.create_dependency("C", "^1.0")) | package_b.add_dependency(Factory.create_dependency("C", "^1.0")) | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(package_c) | repo.add_package(package_c) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_c}, | {"job": "install", "package": package_c}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
], | ], | |||
) | ) | |||
def test_solver_does_not_return_extras_if_not_requested(solver, repo, package): | def test_solver_does_not_return_extras_if_not_requested( | |||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package.add_dependency(Factory.create_dependency("B", "*")) | package.add_dependency(Factory.create_dependency("B", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
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 = {"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) | |||
repo.add_package(package_c) | repo.add_package(package_c) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
], | ], | |||
) | ) | |||
def test_solver_returns_extras_if_requested(solver, repo, package): | def test_solver_returns_extras_if_requested( | |||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("B", {"version": "*", "extras": ["foo"]}) | Factory.create_dependency("B", {"version": "*", "extras": ["foo"]}) | |||
) | ) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
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") | |||
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 = {"foo": [dep]} | |||
package_b.requires.append(dep) | package_b.add_dependency(dep) | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(package_c) | repo.add_package(package_c) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_c}, | {"job": "install", "package": package_c}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
], | ], | |||
) | ) | |||
assert ops[-1].package.marker.is_any() | assert ops[-1].package.marker.is_any() | |||
assert ops[0].package.marker.is_any() | assert ops[0].package.marker.is_any() | |||
@pytest.mark.parametrize(("enabled_extra",), [("one",), ("two",), (None,)]) | @pytest.mark.parametrize("enabled_extra", ["one", "two", None]) | |||
def test_solver_returns_extras_only_requested(solver, repo, package, enabled_ext | def test_solver_returns_extras_only_requested( | |||
ra): | solver: Solver, | |||
repo: Repository, | ||||
package: ProjectPackage, | ||||
enabled_extra: bool | None, | ||||
): | ||||
extras = [enabled_extra] if enabled_extra is not None else [] | extras = [enabled_extra] if enabled_extra is not None else [] | |||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("B", {"version": "*", "extras": extras}) | Factory.create_dependency("B", {"version": "*", "extras": extras}) | |||
) | ) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
package_b = get_package("B", "1.0") | package_b = get_package("B", "1.0") | |||
package_c10 = get_package("C", "1.0") | package_c10 = get_package("C", "1.0") | |||
skipping to change at line 450 | skipping to change at line 581 | |||
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("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("two") | |||
dep20.marker = parse_marker("extra == 'two'") | dep20.marker = parse_marker("extra == 'two'") | |||
package_b.extras = {"one": [dep10], "two": [dep20]} | package_b.extras = {"one": [dep10], "two": [dep20]} | |||
package_b.requires.append(dep10) | package_b.add_dependency(dep10) | |||
package_b.requires.append(dep20) | package_b.add_dependency(dep20) | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(package_c10) | repo.add_package(package_c10) | |||
repo.add_package(package_c20) | repo.add_package(package_c20) | |||
ops = solver.solve() | transaction = solver.solve() | |||
expected = [ | expected = [ | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
] | ] | |||
if enabled_extra is not None: | if enabled_extra is not None: | |||
expected.insert( | expected.insert( | |||
0, | 0, | |||
{ | { | |||
"job": "install", | "job": "install", | |||
"package": package_c10 if enabled_extra == "one" else package_c2 0, | "package": package_c10 if enabled_extra == "one" else package_c2 0, | |||
}, | }, | |||
) | ) | |||
check_solver_result( | ops = check_solver_result( | |||
ops, expected, | transaction, | |||
expected, | ||||
) | ) | |||
assert ops[-1].package.marker.is_any() | assert ops[-1].package.marker.is_any() | |||
assert ops[0].package.marker.is_any() | assert ops[0].package.marker.is_any() | |||
@pytest.mark.parametrize(("enabled_extra",), [("one",), ("two",), (None,)]) | @pytest.mark.parametrize("enabled_extra", ["one", "two", None]) | |||
def test_solver_returns_extras_when_multiple_extras_use_same_dependency( | def test_solver_returns_extras_when_multiple_extras_use_same_dependency( | |||
solver, repo, package, enabled_extra | solver: Solver, | |||
repo: Repository, | ||||
package: ProjectPackage, | ||||
enabled_extra: bool | None, | ||||
): | ): | |||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
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") | |||
dep = get_dependency("C", "*", optional=True) | dep = get_dependency("C", "*", optional=True) | |||
dep._in_extras.append("one") | dep._in_extras.append("one") | |||
dep._in_extras.append("two") | dep._in_extras.append("two") | |||
package_b.extras = {"one": [dep], "two": [dep]} | package_b.extras = {"one": [dep], "two": [dep]} | |||
package_b.requires.append(dep) | package_b.add_dependency(dep) | |||
extras = [enabled_extra] if enabled_extra is not None else [] | extras = [enabled_extra] if enabled_extra is not None else [] | |||
package_a.add_dependency( | package_a.add_dependency( | |||
Factory.create_dependency("B", {"version": "*", "extras": extras}) | Factory.create_dependency("B", {"version": "*", "extras": extras}) | |||
) | ) | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(package_c) | repo.add_package(package_c) | |||
ops = solver.solve() | transaction = solver.solve() | |||
expected = [ | expected = [ | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
] | ] | |||
if enabled_extra is not None: | if enabled_extra is not None: | |||
expected.insert(0, {"job": "install", "package": package_c}) | expected.insert(0, {"job": "install", "package": package_c}) | |||
check_solver_result( | ops = check_solver_result( | |||
ops, expected, | transaction, | |||
expected, | ||||
) | ) | |||
assert ops[-1].package.marker.is_any() | assert ops[-1].package.marker.is_any() | |||
assert ops[0].package.marker.is_any() | assert ops[0].package.marker.is_any() | |||
@pytest.mark.parametrize(("enabled_extra",), [("one",), ("two",), (None,)]) | @pytest.mark.parametrize("enabled_extra", ["one", "two", None]) | |||
def test_solver_returns_extras_only_requested_nested( | def test_solver_returns_extras_only_requested_nested( | |||
solver, repo, package, enabled_extra | solver: Solver, | |||
repo: Repository, | ||||
package: ProjectPackage, | ||||
enabled_extra: bool | None, | ||||
): | ): | |||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
package_b = get_package("B", "1.0") | package_b = get_package("B", "1.0") | |||
package_c10 = get_package("C", "1.0") | package_c10 = get_package("C", "1.0") | |||
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("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("two") | |||
dep20.marker = parse_marker("extra == 'two'") | dep20.marker = parse_marker("extra == 'two'") | |||
package_b.extras = {"one": [dep10], "two": [dep20]} | package_b.extras = {"one": [dep10], "two": [dep20]} | |||
package_b.requires.append(dep10) | package_b.add_dependency(dep10) | |||
package_b.requires.append(dep20) | package_b.add_dependency(dep20) | |||
extras = [enabled_extra] if enabled_extra is not None else [] | extras = [enabled_extra] if enabled_extra is not None else [] | |||
package_a.add_dependency( | package_a.add_dependency( | |||
Factory.create_dependency("B", {"version": "*", "extras": extras}) | Factory.create_dependency("B", {"version": "*", "extras": extras}) | |||
) | ) | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(package_c10) | repo.add_package(package_c10) | |||
repo.add_package(package_c20) | repo.add_package(package_c20) | |||
ops = solver.solve() | transaction = solver.solve() | |||
expected = [ | expected = [ | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
] | ] | |||
if enabled_extra is not None: | if enabled_extra is not None: | |||
expected.insert( | expected.insert( | |||
0, | 0, | |||
{ | { | |||
"job": "install", | "job": "install", | |||
"package": package_c10 if enabled_extra == "one" else package_c2 0, | "package": package_c10 if enabled_extra == "one" else package_c2 0, | |||
}, | }, | |||
) | ) | |||
check_solver_result(ops, expected) | ops = check_solver_result(transaction, expected) | |||
assert ops[-1].package.marker.is_any() | assert ops[-1].package.marker.is_any() | |||
assert ops[0].package.marker.is_any() | assert ops[0].package.marker.is_any() | |||
def test_solver_returns_prereleases_if_requested(solver, repo, package): | def test_solver_finds_extras_next_to_non_extras( | |||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
# Root depends on A[foo] | ||||
package.add_dependency( | ||||
Factory.create_dependency("A", {"version": "*", "extras": ["foo"]}) | ||||
) | ||||
package_a = get_package("A", "1.0") | ||||
package_b = get_package("B", "1.0") | ||||
package_c = get_package("C", "1.0") | ||||
package_d = get_package("D", "1.0") | ||||
# A depends on B; A[foo] depends on B[bar]. | ||||
package_a.add_dependency(Factory.create_dependency("B", "*")) | ||||
package_a.add_dependency( | ||||
Factory.create_dependency( | ||||
"B", {"version": "*", "extras": ["bar"], "markers": "extra == 'foo'" | ||||
} | ||||
) | ||||
) | ||||
package_a.extras = {"foo": [get_dependency("B", "*")]} | ||||
# B depends on C; B[bar] depends on D. | ||||
package_b.add_dependency(Factory.create_dependency("C", "*")) | ||||
package_b.add_dependency( | ||||
Factory.create_dependency("D", {"version": "*", "markers": 'extra == "ba | ||||
r"'}) | ||||
) | ||||
package_b.extras = {"bar": [get_dependency("D", "*")]} | ||||
repo.add_package(package_a) | ||||
repo.add_package(package_b) | ||||
repo.add_package(package_c) | ||||
repo.add_package(package_d) | ||||
transaction = solver.solve() | ||||
check_solver_result( | ||||
transaction, | ||||
[ | ||||
{"job": "install", "package": package_c}, | ||||
{"job": "install", "package": package_d}, | ||||
{"job": "install", "package": package_b}, | ||||
{"job": "install", "package": package_a}, | ||||
], | ||||
) | ||||
def test_solver_merge_extras_into_base_package_multiple_repos_fixes_5727( | ||||
solver: Solver, repo: Repository, pool: Pool, package: ProjectPackage | ||||
): | ||||
package.add_dependency( | ||||
Factory.create_dependency("A", {"version": "*", "source": "legacy"}) | ||||
) | ||||
package.add_dependency(Factory.create_dependency("B", {"version": "*"})) | ||||
package_a = get_package("A", "1.0") | ||||
package_a.extras = {"foo": []} | ||||
repo.add_package(package_a) | ||||
package_b = Package("B", "1.0", source_type="legacy") | ||||
package_b.add_dependency(package_a.with_features(["foo"]).to_dependency()) | ||||
package_a = Package("A", "1.0", source_type="legacy") | ||||
package_a.extras = {"foo": []} | ||||
repo = Repository("legacy") | ||||
repo.add_package(package_a) | ||||
repo.add_package(package_b) | ||||
pool.add_repository(repo) | ||||
transaction = solver.solve() | ||||
ops = transaction.calculate_operations(synchronize=True) | ||||
assert len(ops[0].package.requires) == 0, "a should not require itself" | ||||
def test_solver_returns_prereleases_if_requested( | ||||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package.add_dependency(Factory.create_dependency("B", "*")) | package.add_dependency(Factory.create_dependency("B", "*")) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("C", {"version": "*", "allow-prereleases": Tru e}) | Factory.create_dependency("C", {"version": "*", "allow-prereleases": Tru e}) | |||
) | ) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
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_c_dev = get_package("C", "1.1-beta.1") | package_c_dev = get_package("C", "1.1-beta.1") | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(package_c) | repo.add_package(package_c) | |||
repo.add_package(package_c_dev) | repo.add_package(package_c_dev) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
{"job": "install", "package": package_c_dev}, | {"job": "install", "package": package_c_dev}, | |||
], | ], | |||
) | ) | |||
def test_solver_does_not_return_prereleases_if_not_requested(solver, repo, packa | def test_solver_does_not_return_prereleases_if_not_requested( | |||
ge): | solver: Solver, repo: Repository, package: ProjectPackage | |||
): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package.add_dependency(Factory.create_dependency("B", "*")) | package.add_dependency(Factory.create_dependency("B", "*")) | |||
package.add_dependency(Factory.create_dependency("C", "*")) | package.add_dependency(Factory.create_dependency("C", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
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_c_dev = get_package("C", "1.1-beta.1") | package_c_dev = get_package("C", "1.1-beta.1") | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(package_c) | repo.add_package(package_c) | |||
repo.add_package(package_c_dev) | repo.add_package(package_c_dev) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
{"job": "install", "package": package_c}, | {"job": "install", "package": package_c}, | |||
], | ], | |||
) | ) | |||
def test_solver_sub_dependencies_with_requirements(solver, repo, package): | def test_solver_sub_dependencies_with_requirements( | |||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package.add_dependency(Factory.create_dependency("B", "*")) | package.add_dependency(Factory.create_dependency("B", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
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_d = get_package("D", "1.0") | package_d = get_package("D", "1.0") | |||
package_c.add_dependency( | package_c.add_dependency( | |||
Factory.create_dependency("D", {"version": "^1.0", "python": "<4.0"}) | Factory.create_dependency("D", {"version": "^1.0", "python": "<4.0"}) | |||
) | ) | |||
package_a.add_dependency(Factory.create_dependency("C", "*")) | package_a.add_dependency(Factory.create_dependency("C", "*")) | |||
package_b.add_dependency(Factory.create_dependency("D", "^1.0")) | package_b.add_dependency(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) | |||
repo.add_package(package_c) | repo.add_package(package_c) | |||
repo.add_package(package_d) | repo.add_package(package_d) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_d}, | {"job": "install", "package": package_d}, | |||
{"job": "install", "package": package_c}, | {"job": "install", "package": package_c}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
], | ], | |||
) | ) | |||
op = ops[1] | op = ops[1] | |||
assert op.package.marker.is_any() | assert op.package.marker.is_any() | |||
def test_solver_sub_dependencies_with_requirements_complex(solver, repo, package | def test_solver_sub_dependencies_with_requirements_complex( | |||
): | solver: Solver, repo: Repository, package: ProjectPackage | |||
): | ||||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("A", {"version": "^1.0", "python": "<5.0"}) | Factory.create_dependency("A", {"version": "^1.0", "python": "<5.0"}) | |||
) | ) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("B", {"version": "^1.0", "python": "<5.0"}) | Factory.create_dependency("B", {"version": "^1.0", "python": "<5.0"}) | |||
) | ) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("C", {"version": "^1.0", "python": "<4.0"}) | Factory.create_dependency("C", {"version": "^1.0", "python": "<4.0"}) | |||
) | ) | |||
skipping to change at line 711 | skipping to change at line 935 | |||
) | ) | |||
package_d.add_dependency(Factory.create_dependency("F", "*")) | package_d.add_dependency(Factory.create_dependency("F", "*")) | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(package_c) | repo.add_package(package_c) | |||
repo.add_package(package_d) | repo.add_package(package_d) | |||
repo.add_package(package_e) | repo.add_package(package_e) | |||
repo.add_package(package_f) | repo.add_package(package_f) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_e}, | {"job": "install", "package": package_e}, | |||
{"job": "install", "package": package_f}, | {"job": "install", "package": package_f}, | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
{"job": "install", "package": package_d}, | {"job": "install", "package": package_d}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
{"job": "install", "package": package_c}, | {"job": "install", "package": package_c}, | |||
], | ], | |||
) | ) | |||
def test_solver_sub_dependencies_with_not_supported_python_version( | def test_solver_sub_dependencies_with_not_supported_python_version( | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
solver.provider.set_package_python_versions("^3.5") | solver.provider.set_package_python_versions("^3.5") | |||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
package_b = get_package("B", "1.0") | package_b = get_package("B", "1.0") | |||
package_b.python_versions = "<2.0" | package_b.python_versions = "<2.0" | |||
package_a.add_dependency( | package_a.add_dependency( | |||
Factory.create_dependency("B", {"version": "^1.0", "python": "<2.0"}) | Factory.create_dependency("B", {"version": "^1.0", "python": "<2.0"}) | |||
) | ) | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result(ops, [{"job": "install", "package": package_a}]) | check_solver_result(transaction, [{"job": "install", "package": package_a}]) | |||
def test_solver_sub_dependencies_with_not_supported_python_version_transitive( | ||||
solver: Solver, repo: Repository, package: Package | ||||
): | ||||
solver.provider.set_package_python_versions("^3.4") | ||||
package.add_dependency( | ||||
Factory.create_dependency("httpx", {"version": "^0.17.1", "python": "^3. | ||||
6"}) | ||||
) | ||||
httpx = get_package("httpx", "0.17.1") | ||||
httpx.python_versions = ">=3.6" | ||||
httpcore = get_package("httpcore", "0.12.3") | ||||
httpcore.python_versions = ">=3.6" | ||||
sniffio_1_1_0 = get_package("sniffio", "1.1.0") | ||||
sniffio_1_1_0.python_versions = ">=3.5" | ||||
sniffio = get_package("sniffio", "1.2.0") | ||||
sniffio.python_versions = ">=3.5" | ||||
httpx.add_dependency( | ||||
Factory.create_dependency("httpcore", {"version": ">=0.12.1,<0.13"}) | ||||
) | ||||
httpx.add_dependency(Factory.create_dependency("sniffio", {"version": "*"})) | ||||
httpcore.add_dependency(Factory.create_dependency("sniffio", {"version": "== | ||||
1.*"})) | ||||
repo.add_package(httpx) | ||||
repo.add_package(httpcore) | ||||
repo.add_package(sniffio) | ||||
repo.add_package(sniffio_1_1_0) | ||||
transaction = solver.solve() | ||||
check_solver_result( | ||||
transaction, | ||||
[ | ||||
{"job": "install", "package": sniffio, "skipped": False}, | ||||
{"job": "install", "package": httpcore, "skipped": False}, | ||||
{"job": "install", "package": httpx, "skipped": False}, | ||||
], | ||||
) | ||||
def test_solver_with_dependency_in_both_main_and_dev_dependencies( | def test_solver_with_dependency_in_both_main_and_dev_dependencies( | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
solver.provider.set_package_python_versions("^3.5") | solver.provider.set_package_python_versions("^3.5") | |||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency( | Factory.create_dependency( | |||
"A", {"version": "*", "extras": ["foo"]}, category="dev" | "A", {"version": "*", "extras": ["foo"]}, groups=["dev"] | |||
) | ) | |||
) | ) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
package_a.extras["foo"] = [get_dependency("C")] | package_a.extras["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}) | |||
) | ) | |||
package_a.add_dependency(Factory.create_dependency("B", {"version": "^1.0"}) ) | package_a.add_dependency(Factory.create_dependency("B", {"version": "^1.0"}) ) | |||
skipping to change at line 776 | skipping to change at line 1043 | |||
package_c = get_package("C", "1.0") | package_c = get_package("C", "1.0") | |||
package_c.add_dependency(Factory.create_dependency("D", "^1.0")) | package_c.add_dependency(Factory.create_dependency("D", "^1.0")) | |||
package_d = get_package("D", "1.0") | package_d = get_package("D", "1.0") | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(package_c) | repo.add_package(package_c) | |||
repo.add_package(package_d) | repo.add_package(package_d) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_d}, | {"job": "install", "package": package_d}, | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
{"job": "install", "package": package_c}, | {"job": "install", "package": package_c}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
], | ], | |||
) | ) | |||
d = ops[0].package | ||||
b = ops[1].package | b = ops[1].package | |||
c = ops[2].package | c = ops[2].package | |||
d = ops[0].package | ||||
a = ops[3].package | a = ops[3].package | |||
assert d.category == "dev" | assert d.category == "dev" | |||
assert c.category == "dev" | ||||
assert b.category == "main" | assert b.category == "main" | |||
assert c.category == "dev" | ||||
assert a.category == "main" | assert a.category == "main" | |||
def test_solver_with_dependency_in_both_main_and_dev_dependencies_with_one_more_ | def test_solver_with_dependency_in_both_main_and_dev_dependencies_with_one_more_ | |||
dependent( | dependent( # noqa: E501 | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package.add_dependency(Factory.create_dependency("E", "*")) | package.add_dependency(Factory.create_dependency("E", "*")) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency( | Factory.create_dependency( | |||
"A", {"version": "*", "extras": ["foo"]}, category="dev" | "A", {"version": "*", "extras": ["foo"]}, groups=["dev"] | |||
) | ) | |||
) | ) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
package_a.extras["foo"] = [get_dependency("C")] | package_a.extras["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}) | |||
) | ) | |||
package_a.add_dependency(Factory.create_dependency("B", {"version": "^1.0"}) ) | package_a.add_dependency(Factory.create_dependency("B", {"version": "^1.0"}) ) | |||
skipping to change at line 832 | skipping to change at line 1099 | |||
package_e = get_package("E", "1.0") | package_e = get_package("E", "1.0") | |||
package_e.add_dependency(Factory.create_dependency("A", "^1.0")) | package_e.add_dependency(Factory.create_dependency("A", "^1.0")) | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(package_c) | repo.add_package(package_c) | |||
repo.add_package(package_d) | repo.add_package(package_d) | |||
repo.add_package(package_e) | repo.add_package(package_e) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
{"job": "install", "package": package_d}, | {"job": "install", "package": package_d}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
{"job": "install", "package": package_c}, | {"job": "install", "package": package_c}, | |||
{"job": "install", "package": package_e}, | {"job": "install", "package": package_e}, | |||
], | ], | |||
) | ) | |||
b = ops[0].package | b = ops[0].package | |||
c = ops[3].package | ||||
d = ops[1].package | d = ops[1].package | |||
a = ops[2].package | a = ops[2].package | |||
c = ops[3].package | ||||
e = ops[4].package | e = ops[4].package | |||
assert d.category == "dev" | ||||
assert c.category == "dev" | ||||
assert b.category == "main" | assert b.category == "main" | |||
assert d.category == "dev" | ||||
assert a.category == "main" | assert a.category == "main" | |||
assert c.category == "dev" | ||||
assert e.category == "main" | assert e.category == "main" | |||
def test_solver_with_dependency_and_prerelease_sub_dependencies(solver, repo, pa | def test_solver_with_dependency_and_prerelease_sub_dependencies( | |||
ckage): | solver: Solver, repo: Repository, package: ProjectPackage | |||
): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
package_a.add_dependency(Factory.create_dependency("B", ">=1.0.0.dev2")) | package_a.add_dependency(Factory.create_dependency("B", ">=1.0.0.dev2")) | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(get_package("B", "0.9.0")) | repo.add_package(get_package("B", "0.9.0")) | |||
repo.add_package(get_package("B", "1.0.0.dev1")) | repo.add_package(get_package("B", "1.0.0.dev1")) | |||
repo.add_package(get_package("B", "1.0.0.dev2")) | repo.add_package(get_package("B", "1.0.0.dev2")) | |||
repo.add_package(get_package("B", "1.0.0.dev3")) | repo.add_package(get_package("B", "1.0.0.dev3")) | |||
package_b = get_package("B", "1.0.0.dev4") | package_b = get_package("B", "1.0.0.dev4") | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
], | ], | |||
) | ) | |||
def test_solver_circular_dependency(solver, repo, package): | def test_solver_circular_dependency( | |||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
package_a.add_dependency(Factory.create_dependency("B", "^1.0")) | package_a.add_dependency(Factory.create_dependency("B", "^1.0")) | |||
package_b = get_package("B", "1.0") | package_b = get_package("B", "1.0") | |||
package_b.add_dependency(Factory.create_dependency("A", "^1.0")) | package_b.add_dependency(Factory.create_dependency("A", "^1.0")) | |||
package_b.add_dependency(Factory.create_dependency("C", "^1.0")) | package_b.add_dependency(Factory.create_dependency("C", "^1.0")) | |||
package_c = get_package("C", "1.0") | package_c = get_package("C", "1.0") | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(package_c) | repo.add_package(package_c) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_c}, | {"job": "install", "package": package_c}, | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
], | ], | |||
) | ) | |||
assert "main" == ops[0].package.category | assert ops[0].package.category == "main" | |||
def test_solver_circular_dependency_chain(solver, repo, package): | def test_solver_circular_dependency_chain( | |||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
package_a.add_dependency(Factory.create_dependency("B", "^1.0")) | package_a.add_dependency(Factory.create_dependency("B", "^1.0")) | |||
package_b = get_package("B", "1.0") | package_b = get_package("B", "1.0") | |||
package_b.add_dependency(Factory.create_dependency("C", "^1.0")) | package_b.add_dependency(Factory.create_dependency("C", "^1.0")) | |||
package_c = get_package("C", "1.0") | package_c = get_package("C", "1.0") | |||
package_c.add_dependency(Factory.create_dependency("D", "^1.0")) | package_c.add_dependency(Factory.create_dependency("D", "^1.0")) | |||
package_d = get_package("D", "1.0") | package_d = get_package("D", "1.0") | |||
package_d.add_dependency(Factory.create_dependency("B", "^1.0")) | package_d.add_dependency(Factory.create_dependency("B", "^1.0")) | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(package_c) | repo.add_package(package_c) | |||
repo.add_package(package_d) | repo.add_package(package_d) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_d}, | {"job": "install", "package": package_d}, | |||
{"job": "install", "package": package_c}, | {"job": "install", "package": package_c}, | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
], | ], | |||
) | ) | |||
assert "main" == ops[0].package.category | assert ops[0].package.category == "main" | |||
def test_solver_dense_dependencies(solver, repo, package): | def test_solver_dense_dependencies( | |||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
# The root package depends on packages A0...An-1, | # The root package depends on packages A0...An-1, | |||
# And package Ai depends on packages A0...Ai-1 | # And package Ai depends on packages A0...Ai-1 | |||
# This graph is a transitive tournament | # This graph is a transitive tournament | |||
packages = [] | packages = [] | |||
n = 22 | n = 22 | |||
for i in range(n): | for i in range(n): | |||
package_ai = get_package("a" + str(i), "1.0") | package_ai = get_package("a" + str(i), "1.0") | |||
repo.add_package(package_ai) | repo.add_package(package_ai) | |||
packages.append(package_ai) | packages.append(package_ai) | |||
package.add_dependency(Factory.create_dependency("a" + str(i), "^1.0")) | package.add_dependency(Factory.create_dependency("a" + str(i), "^1.0")) | |||
for j in range(i): | for j in range(i): | |||
package_ai.add_dependency(Factory.create_dependency("a" + str(j), "^ 1.0")) | package_ai.add_dependency(Factory.create_dependency("a" + str(j), "^ 1.0")) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, [{"job": "install", "package": packages[i]} for i in range(n)] | transaction, [{"job": "install", "package": packages[i]} for i in range( n)] | |||
) | ) | |||
def test_solver_duplicate_dependencies_same_constraint(solver, repo, package): | def test_solver_duplicate_dependencies_same_constraint( | |||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
package_a.add_dependency( | package_a.add_dependency( | |||
Factory.create_dependency("B", {"version": "^1.0", "python": "2.7"}) | Factory.create_dependency("B", {"version": "^1.0", "python": "2.7"}) | |||
) | ) | |||
package_a.add_dependency( | package_a.add_dependency( | |||
Factory.create_dependency("B", {"version": "^1.0", "python": ">=3.4"}) | Factory.create_dependency("B", {"version": "^1.0", "python": ">=3.4"}) | |||
) | ) | |||
package_b = get_package("B", "1.0") | package_b = get_package("B", "1.0") | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
], | ], | |||
) | ) | |||
def test_solver_duplicate_dependencies_different_constraints(solver, repo, packa | def test_solver_duplicate_dependencies_different_constraints( | |||
ge): | solver: Solver, repo: Repository, package: ProjectPackage | |||
): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
package_a.add_dependency( | package_a.add_dependency( | |||
Factory.create_dependency("B", {"version": "^1.0", "python": "<3.4"}) | Factory.create_dependency("B", {"version": "^1.0", "python": "<3.4"}) | |||
) | ) | |||
package_a.add_dependency( | package_a.add_dependency( | |||
Factory.create_dependency("B", {"version": "^2.0", "python": ">=3.4"}) | Factory.create_dependency("B", {"version": "^2.0", "python": ">=3.4"}) | |||
) | ) | |||
package_b10 = get_package("B", "1.0") | package_b10 = get_package("B", "1.0") | |||
package_b20 = get_package("B", "2.0") | package_b20 = get_package("B", "2.0") | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b10) | repo.add_package(package_b10) | |||
repo.add_package(package_b20) | repo.add_package(package_b20) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_b10}, | {"job": "install", "package": package_b10}, | |||
{"job": "install", "package": package_b20}, | {"job": "install", "package": package_b20}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
], | ], | |||
) | ) | |||
def test_solver_duplicate_dependencies_different_constraints_same_requirements( | def test_solver_duplicate_dependencies_different_constraints_same_requirements( | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
package_a.add_dependency(Factory.create_dependency("B", {"version": "^1.0"}) ) | package_a.add_dependency(Factory.create_dependency("B", {"version": "^1.0"}) ) | |||
package_a.add_dependency(Factory.create_dependency("B", {"version": "^2.0"}) ) | package_a.add_dependency(Factory.create_dependency("B", {"version": "^2.0"}) ) | |||
package_b10 = get_package("B", "1.0") | package_b10 = get_package("B", "1.0") | |||
package_b20 = get_package("B", "2.0") | package_b20 = get_package("B", "2.0") | |||
skipping to change at line 1045 | skipping to change at line 1324 | |||
with pytest.raises(SolverProblemError) as e: | with pytest.raises(SolverProblemError) as e: | |||
solver.solve() | solver.solve() | |||
expected = """\ | expected = """\ | |||
Because a (1.0) depends on both B (^1.0) and B (^2.0), a is forbidden. | Because a (1.0) depends on both B (^1.0) and B (^2.0), a is forbidden. | |||
So, because no versions of a match !=1.0 | So, because no versions of a match !=1.0 | |||
and root depends on A (*), version solving failed.""" | and root depends on A (*), version solving failed.""" | |||
assert str(e.value) == expected | assert str(e.value) == expected | |||
def test_solver_duplicate_dependencies_sub_dependencies(solver, repo, package): | def test_solver_duplicate_dependencies_different_constraints_merge_by_marker( | |||
solver: Solver, repo: Repository, package: Package | ||||
): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | ||||
package_a = get_package("A", "1.0") | ||||
package_a.add_dependency( | ||||
Factory.create_dependency("B", {"version": "^1.0", "python": "<3.4"}) | ||||
) | ||||
package_a.add_dependency( | ||||
Factory.create_dependency("B", {"version": "^2.0", "python": ">=3.4"}) | ||||
) | ||||
package_a.add_dependency( | ||||
Factory.create_dependency("B", {"version": "!=1.1", "python": "<3.4"}) | ||||
) | ||||
package_b10 = get_package("B", "1.0") | ||||
package_b11 = get_package("B", "1.1") | ||||
package_b20 = get_package("B", "2.0") | ||||
repo.add_package(package_a) | ||||
repo.add_package(package_b10) | ||||
repo.add_package(package_b11) | ||||
repo.add_package(package_b20) | ||||
transaction = solver.solve() | ||||
check_solver_result( | ||||
transaction, | ||||
[ | ||||
{"job": "install", "package": package_b10}, | ||||
{"job": "install", "package": package_b20}, | ||||
{"job": "install", "package": package_a}, | ||||
], | ||||
) | ||||
def test_solver_duplicate_dependencies_different_sources_types_are_preserved( | ||||
solver: Solver, repo: Repository, package: Package | ||||
): | ||||
pendulum = get_package("pendulum", "2.0.3") | ||||
repo.add_package(pendulum) | ||||
repo.add_package(get_package("cleo", "1.0.0")) | ||||
repo.add_package(get_package("demo", "0.1.0")) | ||||
dependency_pypi = Factory.create_dependency("demo", ">=0.1.0") | ||||
dependency_git = Factory.create_dependency( | ||||
"demo", {"git": "https://github.com/demo/demo.git"}, groups=["dev"] | ||||
) | ||||
package.add_dependency(dependency_git) | ||||
package.add_dependency(dependency_pypi) | ||||
demo = Package( | ||||
"demo", | ||||
"0.1.2", | ||||
source_type="git", | ||||
source_url="https://github.com/demo/demo.git", | ||||
source_reference=DEFAULT_SOURCE_REF, | ||||
source_resolved_reference=MOCK_DEFAULT_GIT_REVISION, | ||||
) | ||||
transaction = solver.solve() | ||||
ops = check_solver_result( | ||||
transaction, | ||||
[{"job": "install", "package": pendulum}, {"job": "install", "package": | ||||
demo}], | ||||
) | ||||
op = ops[1] | ||||
assert op.package.source_type == demo.source_type | ||||
assert op.package.source_reference == DEFAULT_SOURCE_REF | ||||
assert op.package.source_resolved_reference.startswith( | ||||
demo.source_resolved_reference | ||||
) | ||||
complete_package = solver.provider.complete_package( | ||||
DependencyPackage(package.to_dependency(), package) | ||||
) | ||||
assert len(complete_package.package.all_requires) == 2 | ||||
pypi, git = complete_package.package.all_requires | ||||
assert isinstance(pypi, Dependency) | ||||
assert pypi == dependency_pypi | ||||
assert isinstance(git, VCSDependency) | ||||
assert git.constraint | ||||
assert git.constraint != dependency_git.constraint | ||||
assert (git.name, git.source_type, git.source_url, git.source_reference) == | ||||
( | ||||
dependency_git.name, | ||||
dependency_git.source_type, | ||||
dependency_git.source_url, | ||||
DEFAULT_SOURCE_REF, | ||||
) | ||||
def test_solver_duplicate_dependencies_different_constraints_merge_no_markers( | ||||
solver: Solver, repo: Repository, package: Package | ||||
): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | ||||
package.add_dependency(Factory.create_dependency("B", "1.0")) | ||||
package_a10 = get_package("A", "1.0") | ||||
package_a10.add_dependency(Factory.create_dependency("C", {"version": "^1.0" | ||||
})) | ||||
package_a20 = get_package("A", "2.0") | ||||
package_a20.add_dependency( | ||||
Factory.create_dependency("C", {"version": "^2.0"}) # incompatible with | ||||
B | ||||
) | ||||
package_a20.add_dependency( | ||||
Factory.create_dependency("C", {"version": "!=2.1", "python": "3.10"}) | ||||
) | ||||
package_b = get_package("B", "1.0") | ||||
package_b.add_dependency(Factory.create_dependency("C", {"version": "<2.0"}) | ||||
) | ||||
package_c10 = get_package("C", "1.0") | ||||
package_c20 = get_package("C", "2.0") | ||||
package_c21 = get_package("C", "2.1") | ||||
repo.add_package(package_a10) | ||||
repo.add_package(package_a20) | ||||
repo.add_package(package_b) | ||||
repo.add_package(package_c10) | ||||
repo.add_package(package_c20) | ||||
repo.add_package(package_c21) | ||||
transaction = solver.solve() | ||||
check_solver_result( | ||||
transaction, | ||||
[ | ||||
{"job": "install", "package": package_c10}, | ||||
{"job": "install", "package": package_a10}, # only a10, not a20 | ||||
{"job": "install", "package": package_b}, | ||||
], | ||||
) | ||||
def test_solver_duplicate_dependencies_ignore_overrides_with_empty_marker_inters | ||||
ection( | ||||
solver: Solver, repo: Repository, package: Package | ||||
): | ||||
""" | ||||
Distinct requirements per marker: | ||||
* Python 2.7: A (which requires B) and B | ||||
* Python 3.6: same as Python 2.7 but with different versions | ||||
* Python 3.7: only A | ||||
* Python 3.8: only B | ||||
""" | ||||
package.add_dependency( | ||||
Factory.create_dependency("A", {"version": "1.0", "python": "~2.7"}) | ||||
) | ||||
package.add_dependency( | ||||
Factory.create_dependency("A", {"version": "2.0", "python": "~3.6"}) | ||||
) | ||||
package.add_dependency( | ||||
Factory.create_dependency("A", {"version": "3.0", "python": "~3.7"}) | ||||
) | ||||
package.add_dependency( | ||||
Factory.create_dependency("B", {"version": "1.0", "python": "~2.7"}) | ||||
) | ||||
package.add_dependency( | ||||
Factory.create_dependency("B", {"version": "2.0", "python": "~3.6"}) | ||||
) | ||||
package.add_dependency( | ||||
Factory.create_dependency("B", {"version": "3.0", "python": "~3.8"}) | ||||
) | ||||
package_a10 = get_package("A", "1.0") | ||||
package_a10.add_dependency( | ||||
Factory.create_dependency("B", {"version": "^1.0", "python": "~2.7"}) | ||||
) | ||||
package_a20 = get_package("A", "2.0") | ||||
package_a20.add_dependency( | ||||
Factory.create_dependency("B", {"version": "^2.0", "python": "~3.6"}) | ||||
) | ||||
package_a30 = get_package("A", "3.0") # no dep to B | ||||
package_b10 = get_package("B", "1.0") | ||||
package_b11 = get_package("B", "1.1") | ||||
package_b20 = get_package("B", "2.0") | ||||
package_b21 = get_package("B", "2.1") | ||||
package_b30 = get_package("B", "3.0") | ||||
repo.add_package(package_a10) | ||||
repo.add_package(package_a20) | ||||
repo.add_package(package_a30) | ||||
repo.add_package(package_b10) | ||||
repo.add_package(package_b11) | ||||
repo.add_package(package_b20) | ||||
repo.add_package(package_b21) | ||||
repo.add_package(package_b30) | ||||
transaction = solver.solve() | ||||
check_solver_result( | ||||
transaction, | ||||
[ | ||||
{"job": "install", "package": package_b10}, | ||||
{"job": "install", "package": package_b20}, | ||||
{"job": "install", "package": package_a10}, | ||||
{"job": "install", "package": package_a20}, | ||||
{"job": "install", "package": package_a30}, | ||||
{"job": "install", "package": package_b30}, | ||||
], | ||||
) | ||||
def test_solver_duplicate_dependencies_ignore_overrides_with_empty_marker_inters | ||||
ection2( | ||||
solver: Solver, repo: Repository, package: Package | ||||
): | ||||
""" | ||||
Empty intersection between top level dependency and transient dependency. | ||||
""" | ||||
package.add_dependency(Factory.create_dependency("A", {"version": "1.0"})) | ||||
package.add_dependency( | ||||
Factory.create_dependency("B", {"version": ">=2.0", "python": ">=3.7"}) | ||||
) | ||||
package.add_dependency( | ||||
Factory.create_dependency("B", {"version": "*", "python": "<3.7"}) | ||||
) | ||||
package_a10 = get_package("A", "1.0") | ||||
package_a10.add_dependency( | ||||
Factory.create_dependency("B", {"version": ">=2.0", "python": ">=3.7"}) | ||||
) | ||||
package_a10.add_dependency( | ||||
Factory.create_dependency("B", {"version": "*", "python": "<3.7"}) | ||||
) | ||||
package_b10 = get_package("B", "1.0") | ||||
package_b10.python_versions = "<3.7" | ||||
package_b20 = get_package("B", "2.0") | ||||
package_b20.python_versions = ">=3.7" | ||||
repo.add_package(package_a10) | ||||
repo.add_package(package_b10) | ||||
repo.add_package(package_b20) | ||||
transaction = solver.solve() | ||||
check_solver_result( | ||||
transaction, | ||||
[ | ||||
{"job": "install", "package": package_b10}, | ||||
{"job": "install", "package": package_b20}, | ||||
{"job": "install", "package": package_a10}, | ||||
], | ||||
) | ||||
def test_solver_duplicate_dependencies_sub_dependencies( | ||||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
package_a.add_dependency( | package_a.add_dependency( | |||
Factory.create_dependency("B", {"version": "^1.0", "python": "<3.4"}) | Factory.create_dependency("B", {"version": "^1.0", "python": "<3.4"}) | |||
) | ) | |||
package_a.add_dependency( | package_a.add_dependency( | |||
Factory.create_dependency("B", {"version": "^2.0", "python": ">=3.4"}) | Factory.create_dependency("B", {"version": "^2.0", "python": ">=3.4"}) | |||
) | ) | |||
skipping to change at line 1070 | skipping to change at line 1601 | |||
package_c12 = get_package("C", "1.2") | package_c12 = get_package("C", "1.2") | |||
package_c15 = get_package("C", "1.5") | package_c15 = get_package("C", "1.5") | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b10) | repo.add_package(package_b10) | |||
repo.add_package(package_b20) | repo.add_package(package_b20) | |||
repo.add_package(package_c12) | repo.add_package(package_c12) | |||
repo.add_package(package_c15) | repo.add_package(package_c15) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_c12}, | {"job": "install", "package": package_c12}, | |||
{"job": "install", "package": package_c15}, | {"job": "install", "package": package_c15}, | |||
{"job": "install", "package": package_b10}, | {"job": "install", "package": package_b10}, | |||
{"job": "install", "package": package_b20}, | {"job": "install", "package": package_b20}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
], | ], | |||
) | ) | |||
def test_solver_fails_if_dependency_name_does_not_match_package(solver, repo, pa | def test_duplicate_path_dependencies(solver: Solver, package: ProjectPackage) -> | |||
ckage): | None: | |||
solver.provider.set_package_python_versions("^3.7") | ||||
fixtures = Path(__file__).parent.parent / "fixtures" | ||||
project_dir = fixtures / "with_conditional_path_deps" | ||||
path1 = (project_dir / "demo_one").as_posix() | ||||
demo1 = Package("demo", "1.2.3", source_type="directory", source_url=path1) | ||||
package.add_dependency( | ||||
Factory.create_dependency( | ||||
"demo", {"path": path1, "markers": "sys_platform == 'linux'"} | ||||
) | ||||
) | ||||
path2 = (project_dir / "demo_two").as_posix() | ||||
demo2 = Package("demo", "1.2.3", source_type="directory", source_url=path2) | ||||
package.add_dependency( | ||||
Factory.create_dependency( | ||||
"demo", {"path": path2, "markers": "sys_platform == 'win32'"} | ||||
) | ||||
) | ||||
transaction = solver.solve() | ||||
check_solver_result( | ||||
transaction, | ||||
[ | ||||
{"job": "install", "package": demo1}, | ||||
{"job": "install", "package": demo2}, | ||||
], | ||||
) | ||||
def test_duplicate_path_dependencies_same_path( | ||||
solver: Solver, package: ProjectPackage | ||||
) -> None: | ||||
solver.provider.set_package_python_versions("^3.7") | ||||
fixtures = Path(__file__).parent.parent / "fixtures" | ||||
project_dir = fixtures / "with_conditional_path_deps" | ||||
path1 = (project_dir / "demo_one").as_posix() | ||||
demo1 = Package("demo", "1.2.3", source_type="directory", source_url=path1) | ||||
package.add_dependency( | ||||
Factory.create_dependency( | ||||
"demo", {"path": path1, "markers": "sys_platform == 'linux'"} | ||||
) | ||||
) | ||||
package.add_dependency( | ||||
Factory.create_dependency( | ||||
"demo", {"path": path1, "markers": "sys_platform == 'win32'"} | ||||
) | ||||
) | ||||
transaction = solver.solve() | ||||
check_solver_result(transaction, [{"job": "install", "package": demo1}]) | ||||
def test_solver_fails_if_dependency_name_does_not_match_package( | ||||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency( | Factory.create_dependency( | |||
"my-demo", {"git": "https://github.com/demo/demo.git"} | "my-demo", {"git": "https://github.com/demo/demo.git"} | |||
) | ) | |||
) | ) | |||
with pytest.raises(RuntimeError): | with pytest.raises(RuntimeError): | |||
solver.solve() | solver.solve() | |||
def test_solver_does_not_get_stuck_in_recursion_on_circular_dependency( | def test_solver_does_not_get_stuck_in_recursion_on_circular_dependency( | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
package_a.add_dependency(Factory.create_dependency("B", "^1.0")) | package_a.add_dependency(Factory.create_dependency("B", "^1.0")) | |||
package_b = get_package("B", "1.0") | package_b = get_package("B", "1.0") | |||
package_b.add_dependency(Factory.create_dependency("C", "^1.0")) | package_b.add_dependency(Factory.create_dependency("C", "^1.0")) | |||
package_c = get_package("C", "1.0") | package_c = get_package("C", "1.0") | |||
package_c.add_dependency(Factory.create_dependency("B", "^1.0")) | package_c.add_dependency(Factory.create_dependency("B", "^1.0")) | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(package_c) | repo.add_package(package_c) | |||
package.add_dependency(Factory.create_dependency("A", "^1.0")) | package.add_dependency(Factory.create_dependency("A", "^1.0")) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_c}, | {"job": "install", "package": package_c}, | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
], | ], | |||
) | ) | |||
def test_solver_can_resolve_git_dependencies(solver, repo, package): | def test_solver_can_resolve_git_dependencies( | |||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
pendulum = get_package("pendulum", "2.0.3") | pendulum = get_package("pendulum", "2.0.3") | |||
cleo = get_package("cleo", "1.0.0") | cleo = get_package("cleo", "1.0.0") | |||
repo.add_package(pendulum) | repo.add_package(pendulum) | |||
repo.add_package(cleo) | repo.add_package(cleo) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("demo", {"git": "https://github.com/demo/demo. git"}) | Factory.create_dependency("demo", {"git": "https://github.com/demo/demo. git"}) | |||
) | ) | |||
ops = solver.solve() | transaction = solver.solve() | |||
demo = Package( | demo = Package( | |||
"demo", | "demo", | |||
"0.1.2", | "0.1.2", | |||
source_type="git", | source_type="git", | |||
source_url="https://github.com/demo/demo.git", | source_url="https://github.com/demo/demo.git", | |||
source_reference="master", | source_reference=DEFAULT_SOURCE_REF, | |||
source_resolved_reference="9cf87a285a2d3fbb0b9fa621997b3acc3631ed24", | source_resolved_reference=MOCK_DEFAULT_GIT_REVISION, | |||
) | ) | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[{"job": "install", "package": pendulum}, {"job": "install", "package": demo}], | [{"job": "install", "package": pendulum}, {"job": "install", "package": demo}], | |||
) | ) | |||
op = ops[1] | op = ops[1] | |||
assert op.package.source_type == "git" | assert op.package.source_type == "git" | |||
assert op.package.source_reference == "master" | assert op.package.source_reference == DEFAULT_SOURCE_REF | |||
assert op.package.source_resolved_reference.startswith("9cf87a2") | assert op.package.source_resolved_reference.startswith("9cf87a2") | |||
def test_solver_can_resolve_git_dependencies_with_extras(solver, repo, package): | def test_solver_can_resolve_git_dependencies_with_extras( | |||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
pendulum = get_package("pendulum", "2.0.3") | pendulum = get_package("pendulum", "2.0.3") | |||
cleo = get_package("cleo", "1.0.0") | cleo = get_package("cleo", "1.0.0") | |||
repo.add_package(pendulum) | repo.add_package(pendulum) | |||
repo.add_package(cleo) | repo.add_package(cleo) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency( | Factory.create_dependency( | |||
"demo", {"git": "https://github.com/demo/demo.git", "extras": ["foo" ]} | "demo", {"git": "https://github.com/demo/demo.git", "extras": ["foo" ]} | |||
) | ) | |||
) | ) | |||
ops = solver.solve() | transaction = solver.solve() | |||
demo = Package( | demo = Package( | |||
"demo", | "demo", | |||
"0.1.2", | "0.1.2", | |||
source_type="git", | source_type="git", | |||
source_url="https://github.com/demo/demo.git", | source_url="https://github.com/demo/demo.git", | |||
source_reference="master", | source_reference=DEFAULT_SOURCE_REF, | |||
source_resolved_reference="9cf87a285a2d3fbb0b9fa621997b3acc3631ed24", | source_resolved_reference=MOCK_DEFAULT_GIT_REVISION, | |||
) | ) | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": cleo}, | {"job": "install", "package": cleo}, | |||
{"job": "install", "package": pendulum}, | {"job": "install", "package": pendulum}, | |||
{"job": "install", "package": demo}, | {"job": "install", "package": demo}, | |||
], | ], | |||
) | ) | |||
@pytest.mark.parametrize( | @pytest.mark.parametrize( | |||
"ref", | "ref", | |||
[{"branch": "a-branch"}, {"tag": "a-tag"}, {"rev": "9cf8"}], | [{"branch": "a-branch"}, {"tag": "a-tag"}, {"rev": "9cf8"}], | |||
ids=["branch", "tag", "rev"], | ids=["branch", "tag", "rev"], | |||
) | ) | |||
def test_solver_can_resolve_git_dependencies_with_ref(solver, repo, package, ref | def test_solver_can_resolve_git_dependencies_with_ref( | |||
): | solver: Solver, repo: Repository, package: Package, ref: dict[str, str] | |||
): | ||||
pendulum = get_package("pendulum", "2.0.3") | pendulum = get_package("pendulum", "2.0.3") | |||
cleo = get_package("cleo", "1.0.0") | cleo = get_package("cleo", "1.0.0") | |||
repo.add_package(pendulum) | repo.add_package(pendulum) | |||
repo.add_package(cleo) | repo.add_package(cleo) | |||
demo = Package( | demo = Package( | |||
"demo", | "demo", | |||
"0.1.2", | "0.1.2", | |||
source_type="git", | source_type="git", | |||
source_url="https://github.com/demo/demo.git", | source_url="https://github.com/demo/demo.git", | |||
source_reference=ref[list(ref.keys())[0]], | source_reference=ref[list(ref.keys())[0]], | |||
source_resolved_reference="9cf87a285a2d3fbb0b9fa621997b3acc3631ed24", | source_resolved_reference=MOCK_DEFAULT_GIT_REVISION, | |||
) | ) | |||
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)) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[{"job": "install", "package": pendulum}, {"job": "install", "package": demo}], | [{"job": "install", "package": pendulum}, {"job": "install", "package": demo}], | |||
) | ) | |||
op = ops[1] | op = ops[1] | |||
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.startswith("9cf87a2") | assert op.package.source_resolved_reference.startswith("9cf87a2") | |||
def test_solver_does_not_trigger_conflict_for_python_constraint_if_python_requir | def test_solver_does_not_trigger_conflict_for_python_constraint_if_python_requir | |||
ement_is_compatible( | ement_is_compatible( # noqa: E501 | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
solver.provider.set_package_python_versions("~2.7 || ^3.4") | solver.provider.set_package_python_versions("~2.7 || ^3.4") | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("A", {"version": "^1.0", "python": "^3.6"}) | Factory.create_dependency("A", {"version": "^1.0", "python": "^3.6"}) | |||
) | ) | |||
package_a = get_package("A", "1.0.0") | package_a = get_package("A", "1.0.0") | |||
package_a.python_versions = ">=3.6" | package_a.python_versions = ">=3.6" | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result(ops, [{"job": "install", "package": package_a}]) | check_solver_result(transaction, [{"job": "install", "package": package_a}]) | |||
def test_solver_does_not_trigger_conflict_for_python_constraint_if_python_requir | def test_solver_does_not_trigger_conflict_for_python_constraint_if_python_requir | |||
ement_is_compatible_multiple( | ement_is_compatible_multiple( # noqa: E501 | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
solver.provider.set_package_python_versions("~2.7 || ^3.4") | solver.provider.set_package_python_versions("~2.7 || ^3.4") | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("A", {"version": "^1.0", "python": "^3.6"}) | Factory.create_dependency("A", {"version": "^1.0", "python": "^3.6"}) | |||
) | ) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("B", {"version": "^1.0", "python": "^3.5.3"}) | Factory.create_dependency("B", {"version": "^1.0", "python": "^3.5.3"}) | |||
) | ) | |||
package_a = get_package("A", "1.0.0") | package_a = get_package("A", "1.0.0") | |||
package_a.python_versions = ">=3.6" | package_a.python_versions = ">=3.6" | |||
package_a.add_dependency(Factory.create_dependency("B", "^1.0")) | package_a.add_dependency(Factory.create_dependency("B", "^1.0")) | |||
package_b = get_package("B", "1.0.0") | package_b = get_package("B", "1.0.0") | |||
package_b.python_versions = ">=3.5.3" | package_b.python_versions = ">=3.5.3" | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
], | ], | |||
) | ) | |||
def test_solver_triggers_conflict_for_dependency_python_not_fully_compatible_wit | def test_solver_triggers_conflict_for_dependency_python_not_fully_compatible_wit | |||
h_package_python( | h_package_python( # noqa: E501 | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
solver.provider.set_package_python_versions("~2.7 || ^3.4") | solver.provider.set_package_python_versions("~2.7 || ^3.4") | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("A", {"version": "^1.0", "python": "^3.5"}) | Factory.create_dependency("A", {"version": "^1.0", "python": "^3.5"}) | |||
) | ) | |||
package_a = get_package("A", "1.0.0") | package_a = get_package("A", "1.0.0") | |||
package_a.python_versions = ">=3.6" | package_a.python_versions = ">=3.6" | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
with pytest.raises(SolverProblemError): | with pytest.raises(SolverProblemError): | |||
solver.solve() | solver.solve() | |||
def test_solver_finds_compatible_package_for_dependency_python_not_fully_compati | def test_solver_finds_compatible_package_for_dependency_python_not_fully_compati | |||
ble_with_package_python( | ble_with_package_python( # noqa: E501 | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
solver.provider.set_package_python_versions("~2.7 || ^3.4") | solver.provider.set_package_python_versions("~2.7 || ^3.4") | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("A", {"version": "^1.0", "python": "^3.5"}) | Factory.create_dependency("A", {"version": "^1.0", "python": "^3.5"}) | |||
) | ) | |||
package_a101 = get_package("A", "1.0.1") | package_a101 = get_package("A", "1.0.1") | |||
package_a101.python_versions = ">=3.6" | package_a101.python_versions = ">=3.6" | |||
package_a100 = get_package("A", "1.0.0") | package_a100 = get_package("A", "1.0.0") | |||
package_a100.python_versions = ">=3.5" | package_a100.python_versions = ">=3.5" | |||
repo.add_package(package_a100) | repo.add_package(package_a100) | |||
repo.add_package(package_a101) | repo.add_package(package_a101) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result(ops, [{"job": "install", "package": package_a100}]) | check_solver_result(transaction, [{"job": "install", "package": package_a100 }]) | |||
def test_solver_does_not_trigger_new_resolution_on_duplicate_dependencies_if_onl | def test_solver_does_not_trigger_new_resolution_on_duplicate_dependencies_if_onl | |||
y_extras( | y_extras( # noqa: E501 | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
dep1 = dependency_from_pep_508('B (>=1.0); extra == "foo"') | dep1 = Dependency.create_from_pep_508('B (>=1.0); extra == "foo"') | |||
dep1.activate() | dep1.activate() | |||
dep2 = dependency_from_pep_508('B (>=2.0); extra == "bar"') | dep2 = Dependency.create_from_pep_508('B (>=2.0); extra == "bar"') | |||
dep2.activate() | dep2.activate() | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("A", {"version": "^1.0", "extras": ["foo", "ba r"]}) | Factory.create_dependency("A", {"version": "^1.0", "extras": ["foo", "ba r"]}) | |||
) | ) | |||
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 = {"foo": [dep1], "bar": [dep2]} | |||
package_a.requires.append(dep1) | package_a.add_dependency(dep1) | |||
package_a.requires.append(dep2) | package_a.add_dependency(dep2) | |||
package_b2 = get_package("B", "2.0.0") | package_b2 = get_package("B", "2.0.0") | |||
package_b1 = get_package("B", "1.0.0") | package_b1 = get_package("B", "1.0.0") | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b1) | repo.add_package(package_b1) | |||
repo.add_package(package_b2) | repo.add_package(package_b2) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_b2}, | {"job": "install", "package": package_b2}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
], | ], | |||
) | ) | |||
assert str(ops[0].package.marker) == "" | assert str(ops[0].package.marker) == "" | |||
assert str(ops[1].package.marker) == "" | assert str(ops[1].package.marker) == "" | |||
def test_solver_does_not_raise_conflict_for_locked_conditional_dependencies( | def test_solver_does_not_raise_conflict_for_locked_conditional_dependencies( | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
solver.provider.set_package_python_versions("~2.7 || ^3.4") | solver.provider.set_package_python_versions("~2.7 || ^3.4") | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("A", {"version": "^1.0", "python": "^3.6"}) | Factory.create_dependency("A", {"version": "^1.0", "python": "^3.6"}) | |||
) | ) | |||
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") | |||
package_a.python_versions = ">=3.6" | package_a.python_versions = ">=3.6" | |||
package_a.marker = parse_marker( | package_a.marker = parse_marker( | |||
'python_version >= "3.6" and python_version < "4.0"' | 'python_version >= "3.6" and python_version < "4.0"' | |||
) | ) | |||
package_b = get_package("B", "1.0.0") | package_b = get_package("B", "1.0.0") | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
solver._locked = Repository([package_a]) | solver._locked = Repository("locked", [package_a]) | |||
ops = solver.solve(use_latest=[package_b.name]) | transaction = solver.solve(use_latest=[package_b.name]) | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
], | ], | |||
) | ) | |||
def test_solver_returns_extras_if_requested_in_dependencies_and_not_in_root_pack age( | def test_solver_returns_extras_if_requested_in_dependencies_and_not_in_root_pack age( | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
package.add_dependency(Factory.create_dependency("A", "*")) | package.add_dependency(Factory.create_dependency("A", "*")) | |||
package.add_dependency(Factory.create_dependency("B", "*")) | package.add_dependency(Factory.create_dependency("B", "*")) | |||
package.add_dependency(Factory.create_dependency("C", "*")) | package.add_dependency(Factory.create_dependency("C", "*")) | |||
package_a = get_package("A", "1.0") | package_a = get_package("A", "1.0") | |||
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_d = get_package("D", "1.0") | package_d = get_package("D", "1.0") | |||
skipping to change at line 1400 | skipping to change at line 1994 | |||
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 = {"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) | |||
repo.add_package(package_c) | repo.add_package(package_c) | |||
repo.add_package(package_d) | repo.add_package(package_d) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_d}, | {"job": "install", "package": package_d}, | |||
{"job": "install", "package": package_c}, | {"job": "install", "package": package_c}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
{"job": "install", "package": package_b}, | {"job": "install", "package": package_b}, | |||
], | ], | |||
) | ) | |||
def test_solver_should_not_resolve_prerelease_version_if_not_requested( | def test_solver_should_not_resolve_prerelease_version_if_not_requested( | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
package.add_dependency(Factory.create_dependency("A", "~1.8.0")) | package.add_dependency(Factory.create_dependency("A", "~1.8.0")) | |||
package.add_dependency(Factory.create_dependency("B", "^0.5.0")) | package.add_dependency(Factory.create_dependency("B", "^0.5.0")) | |||
package_a185 = get_package("A", "1.8.5") | package_a185 = get_package("A", "1.8.5") | |||
package_a19b1 = get_package("A", "1.9b1") | package_a19b1 = get_package("A", "1.9b1") | |||
package_b = get_package("B", "0.5.0") | package_b = get_package("B", "0.5.0") | |||
package_b.add_dependency(Factory.create_dependency("A", ">=1.9b1")) | package_b.add_dependency(Factory.create_dependency("A", ">=1.9b1")) | |||
repo.add_package(package_a185) | repo.add_package(package_a185) | |||
repo.add_package(package_a19b1) | repo.add_package(package_a19b1) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
with pytest.raises(SolverProblemError): | with pytest.raises(SolverProblemError): | |||
solver.solve() | solver.solve() | |||
def test_solver_ignores_dependencies_with_incompatible_python_full_version_marke r( | def test_solver_ignores_dependencies_with_incompatible_python_full_version_marke r( | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
solver.provider.set_package_python_versions("^3.6") | solver.provider.set_package_python_versions("^3.6") | |||
package.add_dependency(Factory.create_dependency("A", "^1.0")) | package.add_dependency(Factory.create_dependency("A", "^1.0")) | |||
package.add_dependency(Factory.create_dependency("B", "^2.0")) | package.add_dependency(Factory.create_dependency("B", "^2.0")) | |||
package_a = get_package("A", "1.0.0") | package_a = get_package("A", "1.0.0") | |||
package_a.requires.append( | package_a.add_dependency( | |||
dependency_from_pep_508( | Dependency.create_from_pep_508( | |||
'B (<2.0); platform_python_implementation == "PyPy" and python_full_ | 'B (<2.0); platform_python_implementation == "PyPy" and python_full_ | |||
version < "2.7.9"' | version' | |||
' < "2.7.9"' | ||||
) | ) | |||
) | ) | |||
package_b200 = get_package("B", "2.0.0") | package_b200 = get_package("B", "2.0.0") | |||
package_b100 = get_package("B", "1.0.0") | package_b100 = get_package("B", "1.0.0") | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b100) | repo.add_package(package_b100) | |||
repo.add_package(package_b200) | repo.add_package(package_b200) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
{"job": "install", "package": package_b200}, | {"job": "install", "package": package_b200}, | |||
], | ], | |||
) | ) | |||
def test_solver_git_dependencies_update(solver, repo, package, installed): | def test_solver_git_dependencies_update( | |||
solver: Solver, repo: Repository, package: Package, installed: InstalledRepo | ||||
sitory | ||||
): | ||||
pendulum = get_package("pendulum", "2.0.3") | pendulum = get_package("pendulum", "2.0.3") | |||
cleo = get_package("cleo", "1.0.0") | cleo = get_package("cleo", "1.0.0") | |||
repo.add_package(pendulum) | repo.add_package(pendulum) | |||
repo.add_package(cleo) | repo.add_package(cleo) | |||
demo_installed = Package( | demo_installed = Package( | |||
"demo", | "demo", | |||
"0.1.2", | "0.1.2", | |||
source_type="git", | source_type="git", | |||
source_url="https://github.com/demo/demo.git", | source_url="https://github.com/demo/demo.git", | |||
source_reference="master", | source_reference=DEFAULT_SOURCE_REF, | |||
source_resolved_reference="123456", | source_resolved_reference="123456", | |||
) | ) | |||
demo = Package( | demo = Package( | |||
"demo", | "demo", | |||
"0.1.2", | "0.1.2", | |||
source_type="git", | source_type="git", | |||
source_url="https://github.com/demo/demo.git", | source_url="https://github.com/demo/demo.git", | |||
source_reference="master", | source_reference=DEFAULT_SOURCE_REF, | |||
source_resolved_reference="9cf87a285a2d3fbb0b9fa621997b3acc3631ed24", | source_resolved_reference=MOCK_DEFAULT_GIT_REVISION, | |||
) | ) | |||
installed.add_package(demo_installed) | installed.add_package(demo_installed) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("demo", {"git": "https://github.com/demo/demo. git"}) | Factory.create_dependency("demo", {"git": "https://github.com/demo/demo. git"}) | |||
) | ) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": pendulum}, | {"job": "install", "package": pendulum}, | |||
{"job": "update", "from": demo_installed, "to": demo}, | {"job": "update", "from": demo_installed, "to": demo}, | |||
], | ], | |||
) | ) | |||
op = ops[1] | op = ops[1] | |||
assert op.job_type == "update" | assert op.job_type == "update" | |||
assert op.package.source_type == "git" | assert op.package.source_type == "git" | |||
assert op.package.source_reference == "master" | assert op.package.source_reference == DEFAULT_SOURCE_REF | |||
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" | |||
def test_solver_git_dependencies_update_skipped(solver, repo, package, installed | def test_solver_git_dependencies_update_skipped( | |||
): | solver: Solver, repo: Repository, package: Package, installed: InstalledRepo | |||
sitory | ||||
): | ||||
pendulum = get_package("pendulum", "2.0.3") | pendulum = get_package("pendulum", "2.0.3") | |||
cleo = get_package("cleo", "1.0.0") | cleo = get_package("cleo", "1.0.0") | |||
repo.add_package(pendulum) | repo.add_package(pendulum) | |||
repo.add_package(cleo) | repo.add_package(cleo) | |||
demo = Package( | demo = Package( | |||
"demo", | "demo", | |||
"0.1.2", | "0.1.2", | |||
source_type="git", | source_type="git", | |||
source_url="https://github.com/demo/demo.git", | source_url="https://github.com/demo/demo.git", | |||
source_reference="master", | source_reference="master", | |||
source_resolved_reference="9cf87a285a2d3fbb0b9fa621997b3acc3631ed24", | source_resolved_reference=MOCK_DEFAULT_GIT_REVISION, | |||
) | ) | |||
installed.add_package(demo) | installed.add_package(demo) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("demo", {"git": "https://github.com/demo/demo. git"}) | Factory.create_dependency("demo", {"git": "https://github.com/demo/demo. git"}) | |||
) | ) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": pendulum}, | {"job": "install", "package": pendulum}, | |||
{"job": "install", "package": demo, "skipped": True}, | {"job": "install", "package": demo, "skipped": True}, | |||
], | ], | |||
) | ) | |||
def test_solver_git_dependencies_short_hash_update_skipped( | def test_solver_git_dependencies_short_hash_update_skipped( | |||
solver, repo, package, installed | solver: Solver, repo: Repository, package: Package, installed: InstalledRepo sitory | |||
): | ): | |||
pendulum = get_package("pendulum", "2.0.3") | pendulum = get_package("pendulum", "2.0.3") | |||
cleo = get_package("cleo", "1.0.0") | cleo = get_package("cleo", "1.0.0") | |||
repo.add_package(pendulum) | repo.add_package(pendulum) | |||
repo.add_package(cleo) | repo.add_package(cleo) | |||
demo = Package( | demo = Package( | |||
"demo", | "demo", | |||
"0.1.2", | "0.1.2", | |||
source_type="git", | source_type="git", | |||
source_url="https://github.com/demo/demo.git", | source_url="https://github.com/demo/demo.git", | |||
source_reference="master", | source_reference=MOCK_DEFAULT_GIT_REVISION, | |||
source_resolved_reference="9cf87a285a2d3fbb0b9fa621997b3acc3631ed24", | source_resolved_reference=MOCK_DEFAULT_GIT_REVISION, | |||
) | ) | |||
installed.add_package(demo) | installed.add_package(demo) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency( | Factory.create_dependency( | |||
"demo", {"git": "https://github.com/demo/demo.git", "rev": "9cf87a2" } | "demo", {"git": "https://github.com/demo/demo.git", "rev": "9cf87a2" } | |||
) | ) | |||
) | ) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": pendulum}, | {"job": "install", "package": pendulum}, | |||
{ | { | |||
"job": "install", | "job": "install", | |||
"package": Package( | "package": Package( | |||
"demo", | "demo", | |||
"0.1.2", | "0.1.2", | |||
source_type="git", | source_type="git", | |||
source_url="https://github.com/demo/demo.git", | source_url="https://github.com/demo/demo.git", | |||
source_reference="9cf87a285a2d3fbb0b9fa621997b3acc3631ed24", | source_reference=MOCK_DEFAULT_GIT_REVISION, | |||
source_resolved_reference="9cf87a285a2d3fbb0b9fa621997b3acc3 | source_resolved_reference=MOCK_DEFAULT_GIT_REVISION, | |||
631ed24", | ||||
), | ), | |||
"skipped": True, | "skipped": True, | |||
}, | }, | |||
], | ], | |||
) | ) | |||
def test_solver_can_resolve_directory_dependencies(solver, repo, package): | def test_solver_can_resolve_directory_dependencies( | |||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
pendulum = get_package("pendulum", "2.0.3") | pendulum = get_package("pendulum", "2.0.3") | |||
repo.add_package(pendulum) | repo.add_package(pendulum) | |||
path = ( | path = ( | |||
Path(__file__).parent.parent | Path(__file__).parent.parent | |||
/ "fixtures" | / "fixtures" | |||
/ "git" | / "git" | |||
/ "github.com" | / "github.com" | |||
/ "demo" | / "demo" | |||
/ "demo" | / "demo" | |||
).as_posix() | ).as_posix() | |||
package.add_dependency(Factory.create_dependency("demo", {"path": path})) | package.add_dependency(Factory.create_dependency("demo", {"path": path})) | |||
ops = solver.solve() | transaction = solver.solve() | |||
demo = Package("demo", "0.1.2", source_type="directory", source_url=path) | demo = Package("demo", "0.1.2", source_type="directory", source_url=path) | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[{"job": "install", "package": pendulum}, {"job": "install", "package": demo}], | [{"job": "install", "package": pendulum}, {"job": "install", "package": demo}], | |||
) | ) | |||
op = ops[1] | op = ops[1] | |||
assert op.package.name == "demo" | assert op.package.name == "demo" | |||
assert op.package.version.text == "0.1.2" | assert op.package.version.text == "0.1.2" | |||
assert op.package.source_type == "directory" | assert op.package.source_type == "directory" | |||
assert op.package.source_url == path | assert op.package.source_url == path | |||
def test_solver_can_resolve_directory_dependencies_nested_editable( | def test_solver_can_resolve_directory_dependencies_nested_editable( | |||
solver, repo, pool, installed, locked, io | repo: Repository, | |||
pool: Pool, | ||||
installed: InstalledRepository, | ||||
locked: Repository, | ||||
io: NullIO, | ||||
): | ): | |||
base = Path(__file__).parent.parent / "fixtures" / "project_with_nested_loca l" | base = Path(__file__).parent.parent / "fixtures" / "project_with_nested_loca l" | |||
poetry = Factory().create_poetry(cwd=base) | poetry = Factory().create_poetry(cwd=base) | |||
package = poetry.package | package = poetry.package | |||
solver = Solver( | solver = Solver( | |||
package, pool, installed, locked, io, provider=Provider(package, pool, i | package, | |||
o) | pool, | |||
installed.packages, | ||||
locked.packages, | ||||
io, | ||||
provider=Provider(package, pool, io), | ||||
) | ) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{ | { | |||
"job": "install", | "job": "install", | |||
"package": Package( | "package": Package( | |||
"quix", | "quix", | |||
"1.2.3", | "1.2.3", | |||
source_type="directory", | source_type="directory", | |||
source_url=(base / "quix").as_posix(), | source_url=(base / "quix").as_posix(), | |||
), | ), | |||
"skipped": False, | "skipped": False, | |||
skipping to change at line 1666 | skipping to change at line 2276 | |||
), | ), | |||
"skipped": False, | "skipped": False, | |||
}, | }, | |||
], | ], | |||
) | ) | |||
for op in ops: | for op in ops: | |||
assert op.package.source_type == "directory" | assert op.package.source_type == "directory" | |||
assert op.package.develop is True | assert op.package.develop is True | |||
def test_solver_can_resolve_directory_dependencies_with_extras(solver, repo, pac | def test_solver_can_resolve_directory_dependencies_with_extras( | |||
kage): | solver: Solver, repo: Repository, package: ProjectPackage | |||
): | ||||
pendulum = get_package("pendulum", "2.0.3") | pendulum = get_package("pendulum", "2.0.3") | |||
cleo = get_package("cleo", "1.0.0") | cleo = get_package("cleo", "1.0.0") | |||
repo.add_package(pendulum) | repo.add_package(pendulum) | |||
repo.add_package(cleo) | repo.add_package(cleo) | |||
path = ( | path = ( | |||
Path(__file__).parent.parent | Path(__file__).parent.parent | |||
/ "fixtures" | / "fixtures" | |||
/ "git" | / "git" | |||
/ "github.com" | / "github.com" | |||
/ "demo" | / "demo" | |||
/ "demo" | / "demo" | |||
).as_posix() | ).as_posix() | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("demo", {"path": path, "extras": ["foo"]}) | Factory.create_dependency("demo", {"path": path, "extras": ["foo"]}) | |||
) | ) | |||
ops = solver.solve() | transaction = solver.solve() | |||
demo = Package("demo", "0.1.2", source_type="directory", source_url=path) | demo = Package("demo", "0.1.2", source_type="directory", source_url=path) | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": cleo}, | {"job": "install", "package": cleo}, | |||
{"job": "install", "package": pendulum}, | {"job": "install", "package": pendulum}, | |||
{"job": "install", "package": demo}, | {"job": "install", "package": demo}, | |||
], | ], | |||
) | ) | |||
op = ops[2] | op = ops[2] | |||
assert op.package.name == "demo" | assert op.package.name == "demo" | |||
assert op.package.version.text == "0.1.2" | assert op.package.version.text == "0.1.2" | |||
assert op.package.source_type == "directory" | assert op.package.source_type == "directory" | |||
assert op.package.source_url == path | assert op.package.source_url == path | |||
def test_solver_can_resolve_sdist_dependencies(solver, repo, package): | def test_solver_can_resolve_sdist_dependencies( | |||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
pendulum = get_package("pendulum", "2.0.3") | pendulum = get_package("pendulum", "2.0.3") | |||
repo.add_package(pendulum) | repo.add_package(pendulum) | |||
path = ( | path = ( | |||
Path(__file__).parent.parent | Path(__file__).parent.parent | |||
/ "fixtures" | / "fixtures" | |||
/ "distributions" | / "distributions" | |||
/ "demo-0.1.0.tar.gz" | / "demo-0.1.0.tar.gz" | |||
).as_posix() | ).as_posix() | |||
package.add_dependency(Factory.create_dependency("demo", {"path": path})) | package.add_dependency(Factory.create_dependency("demo", {"path": path})) | |||
ops = solver.solve() | transaction = solver.solve() | |||
demo = Package("demo", "0.1.0", source_type="file", source_url=path) | demo = Package("demo", "0.1.0", source_type="file", source_url=path) | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[{"job": "install", "package": pendulum}, {"job": "install", "package": demo}], | [{"job": "install", "package": pendulum}, {"job": "install", "package": demo}], | |||
) | ) | |||
op = ops[1] | op = ops[1] | |||
assert op.package.name == "demo" | assert op.package.name == "demo" | |||
assert op.package.version.text == "0.1.0" | assert op.package.version.text == "0.1.0" | |||
assert op.package.source_type == "file" | assert op.package.source_type == "file" | |||
assert op.package.source_url == path | assert op.package.source_url == path | |||
def test_solver_can_resolve_sdist_dependencies_with_extras(solver, repo, package | def test_solver_can_resolve_sdist_dependencies_with_extras( | |||
): | solver: Solver, repo: Repository, package: ProjectPackage | |||
): | ||||
pendulum = get_package("pendulum", "2.0.3") | pendulum = get_package("pendulum", "2.0.3") | |||
cleo = get_package("cleo", "1.0.0") | cleo = get_package("cleo", "1.0.0") | |||
repo.add_package(pendulum) | repo.add_package(pendulum) | |||
repo.add_package(cleo) | repo.add_package(cleo) | |||
path = ( | path = ( | |||
Path(__file__).parent.parent | Path(__file__).parent.parent | |||
/ "fixtures" | / "fixtures" | |||
/ "distributions" | / "distributions" | |||
/ "demo-0.1.0.tar.gz" | / "demo-0.1.0.tar.gz" | |||
).as_posix() | ).as_posix() | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("demo", {"path": path, "extras": ["foo"]}) | Factory.create_dependency("demo", {"path": path, "extras": ["foo"]}) | |||
) | ) | |||
ops = solver.solve() | transaction = solver.solve() | |||
demo = Package("demo", "0.1.0", source_type="file", source_url=path) | demo = Package("demo", "0.1.0", source_type="file", source_url=path) | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": cleo}, | {"job": "install", "package": cleo}, | |||
{"job": "install", "package": pendulum}, | {"job": "install", "package": pendulum}, | |||
{"job": "install", "package": demo}, | {"job": "install", "package": demo}, | |||
], | ], | |||
) | ) | |||
op = ops[2] | op = ops[2] | |||
assert op.package.name == "demo" | assert op.package.name == "demo" | |||
assert op.package.version.text == "0.1.0" | assert op.package.version.text == "0.1.0" | |||
assert op.package.source_type == "file" | assert op.package.source_type == "file" | |||
assert op.package.source_url == path | assert op.package.source_url == path | |||
def test_solver_can_resolve_wheel_dependencies(solver, repo, package): | def test_solver_can_resolve_wheel_dependencies( | |||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
pendulum = get_package("pendulum", "2.0.3") | pendulum = get_package("pendulum", "2.0.3") | |||
repo.add_package(pendulum) | repo.add_package(pendulum) | |||
path = ( | path = ( | |||
Path(__file__).parent.parent | Path(__file__).parent.parent | |||
/ "fixtures" | / "fixtures" | |||
/ "distributions" | / "distributions" | |||
/ "demo-0.1.0-py2.py3-none-any.whl" | / "demo-0.1.0-py2.py3-none-any.whl" | |||
).as_posix() | ).as_posix() | |||
package.add_dependency(Factory.create_dependency("demo", {"path": path})) | package.add_dependency(Factory.create_dependency("demo", {"path": path})) | |||
ops = solver.solve() | transaction = solver.solve() | |||
demo = Package("demo", "0.1.0", source_type="file", source_url=path) | demo = Package("demo", "0.1.0", source_type="file", source_url=path) | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[{"job": "install", "package": pendulum}, {"job": "install", "package": demo}], | [{"job": "install", "package": pendulum}, {"job": "install", "package": demo}], | |||
) | ) | |||
op = ops[1] | op = ops[1] | |||
assert op.package.name == "demo" | assert op.package.name == "demo" | |||
assert op.package.version.text == "0.1.0" | assert op.package.version.text == "0.1.0" | |||
assert op.package.source_type == "file" | assert op.package.source_type == "file" | |||
assert op.package.source_url == path | assert op.package.source_url == path | |||
def test_solver_can_resolve_wheel_dependencies_with_extras(solver, repo, package | def test_solver_can_resolve_wheel_dependencies_with_extras( | |||
): | solver: Solver, repo: Repository, package: ProjectPackage | |||
): | ||||
pendulum = get_package("pendulum", "2.0.3") | pendulum = get_package("pendulum", "2.0.3") | |||
cleo = get_package("cleo", "1.0.0") | cleo = get_package("cleo", "1.0.0") | |||
repo.add_package(pendulum) | repo.add_package(pendulum) | |||
repo.add_package(cleo) | repo.add_package(cleo) | |||
path = ( | path = ( | |||
Path(__file__).parent.parent | Path(__file__).parent.parent | |||
/ "fixtures" | / "fixtures" | |||
/ "distributions" | / "distributions" | |||
/ "demo-0.1.0-py2.py3-none-any.whl" | / "demo-0.1.0-py2.py3-none-any.whl" | |||
).as_posix() | ).as_posix() | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("demo", {"path": path, "extras": ["foo"]}) | Factory.create_dependency("demo", {"path": path, "extras": ["foo"]}) | |||
) | ) | |||
ops = solver.solve() | transaction = solver.solve() | |||
demo = Package("demo", "0.1.0", source_type="file", source_url=path) | demo = Package("demo", "0.1.0", source_type="file", source_url=path) | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": cleo}, | {"job": "install", "package": cleo}, | |||
{"job": "install", "package": pendulum}, | {"job": "install", "package": pendulum}, | |||
{"job": "install", "package": demo}, | {"job": "install", "package": demo}, | |||
], | ], | |||
) | ) | |||
op = ops[2] | op = ops[2] | |||
assert op.package.name == "demo" | assert op.package.name == "demo" | |||
assert op.package.version.text == "0.1.0" | assert op.package.version.text == "0.1.0" | |||
assert op.package.source_type == "file" | assert op.package.source_type == "file" | |||
assert op.package.source_url == path | assert op.package.source_url == path | |||
def test_solver_can_solve_with_legacy_repository_using_proper_dists( | def test_solver_can_solve_with_legacy_repository_using_proper_dists( | |||
package, installed, locked, io | package: ProjectPackage, | |||
installed: InstalledRepository, | ||||
locked: Repository, | ||||
io: NullIO, | ||||
): | ): | |||
repo = MockLegacyRepository() | repo = MockLegacyRepository() | |||
pool = Pool([repo]) | pool = Pool([repo]) | |||
solver = Solver(package, pool, installed, locked, io) | solver = Solver(package, pool, installed.packages, locked.packages, io) | |||
package.add_dependency(Factory.create_dependency("isort", "4.3.4")) | package.add_dependency(Factory.create_dependency("isort", "4.3.4")) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{ | { | |||
"job": "install", | "job": "install", | |||
"package": Package( | "package": Package( | |||
"futures", | "futures", | |||
"3.2.0", | "3.2.0", | |||
source_type="legacy", | source_type="legacy", | |||
source_url=repo.url, | source_url=repo.url, | |||
source_reference=repo.name, | source_reference=repo.name, | |||
), | ), | |||
skipping to change at line 1879 | skipping to change at line 2502 | |||
source_reference=repo.name, | source_reference=repo.name, | |||
), | ), | |||
}, | }, | |||
], | ], | |||
) | ) | |||
futures = ops[0].package | futures = ops[0].package | |||
assert futures.python_versions == ">=2.6, <3" | assert futures.python_versions == ">=2.6, <3" | |||
def test_solver_can_solve_with_legacy_repository_using_proper_python_compatible_ dists( | def test_solver_can_solve_with_legacy_repository_using_proper_python_compatible_ dists( | |||
package, installed, locked, io | package: ProjectPackage, | |||
installed: InstalledRepository, | ||||
locked: Repository, | ||||
io: NullIO, | ||||
): | ): | |||
package.python_versions = "^3.7" | package.python_versions = "^3.7" | |||
repo = MockLegacyRepository() | repo = MockLegacyRepository() | |||
pool = Pool([repo]) | pool = Pool([repo]) | |||
solver = Solver(package, pool, installed, locked, io) | solver = Solver(package, pool, installed.packages, locked.packages, io) | |||
package.add_dependency(Factory.create_dependency("isort", "4.3.4")) | package.add_dependency(Factory.create_dependency("isort", "4.3.4")) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{ | { | |||
"job": "install", | "job": "install", | |||
"package": Package( | "package": Package( | |||
"isort", | "isort", | |||
"4.3.4", | "4.3.4", | |||
source_type="legacy", | source_type="legacy", | |||
source_url=repo.url, | source_url=repo.url, | |||
source_reference=repo.name, | source_reference=repo.name, | |||
), | ), | |||
} | } | |||
], | ], | |||
) | ) | |||
def test_solver_skips_invalid_versions(package, installed, locked, io): | def test_solver_skips_invalid_versions( | |||
package: ProjectPackage, | ||||
installed: InstalledRepository, | ||||
locked: Repository, | ||||
io: NullIO, | ||||
): | ||||
package.python_versions = "^3.7" | package.python_versions = "^3.7" | |||
repo = MockPyPIRepository() | repo = MockPyPIRepository() | |||
pool = Pool([repo]) | pool = Pool([repo]) | |||
solver = Solver(package, pool, installed, locked, io) | solver = Solver(package, pool, installed.packages, locked.packages, io) | |||
package.add_dependency(Factory.create_dependency("trackpy", "^0.4")) | package.add_dependency(Factory.create_dependency("trackpy", "^0.4")) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, [{"job": "install", "package": get_package("trackpy", "0.4.1")}] | transaction, [{"job": "install", "package": get_package("trackpy", "0.4. 1")}] | |||
) | ) | |||
def test_multiple_constraints_on_root(package, solver, repo): | def test_multiple_constraints_on_root( | |||
package: ProjectPackage, solver: Solver, repo: Repository | ||||
): | ||||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("foo", {"version": "^1.0", "python": "^2.7"}) | Factory.create_dependency("foo", {"version": "^1.0", "python": "^2.7"}) | |||
) | ) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("foo", {"version": "^2.0", "python": "^3.7"}) | Factory.create_dependency("foo", {"version": "^2.0", "python": "^3.7"}) | |||
) | ) | |||
foo15 = get_package("foo", "1.5.0") | foo15 = get_package("foo", "1.5.0") | |||
foo25 = get_package("foo", "2.5.0") | foo25 = get_package("foo", "2.5.0") | |||
repo.add_package(foo15) | repo.add_package(foo15) | |||
repo.add_package(foo25) | repo.add_package(foo25) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[{"job": "install", "package": foo15}, {"job": "install", "package": foo 25}], | [{"job": "install", "package": foo15}, {"job": "install", "package": foo 25}], | |||
) | ) | |||
def test_solver_chooses_most_recent_version_amongst_repositories( | def test_solver_chooses_most_recent_version_amongst_repositories( | |||
package, installed, locked, io | package: ProjectPackage, | |||
installed: InstalledRepository, | ||||
locked: Repository, | ||||
io: NullIO, | ||||
): | ): | |||
package.python_versions = "^3.7" | package.python_versions = "^3.7" | |||
package.add_dependency(Factory.create_dependency("tomlkit", {"version": "^0. 5"})) | package.add_dependency(Factory.create_dependency("tomlkit", {"version": "^0. 5"})) | |||
repo = MockLegacyRepository() | repo = MockLegacyRepository() | |||
pool = Pool([repo, MockPyPIRepository()]) | pool = Pool([repo, MockPyPIRepository()]) | |||
solver = Solver(package, pool, installed, locked, io) | solver = Solver(package, pool, installed.packages, locked.packages, io) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | ops = check_solver_result( | |||
ops, [{"job": "install", "package": get_package("tomlkit", "0.5.3")}] | transaction, [{"job": "install", "package": get_package("tomlkit", "0.5. | |||
3")}] | ||||
) | ) | |||
assert ops[0].package.source_type is None | assert ops[0].package.source_type is None | |||
assert ops[0].package.source_url is None | assert ops[0].package.source_url is None | |||
def test_solver_chooses_from_correct_repository_if_forced( | def test_solver_chooses_from_correct_repository_if_forced( | |||
package, installed, locked, io | package: ProjectPackage, | |||
installed: InstalledRepository, | ||||
locked: Repository, | ||||
io: NullIO, | ||||
): | ): | |||
package.python_versions = "^3.7" | package.python_versions = "^3.7" | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("tomlkit", {"version": "^0.5", "source": "lega cy"}) | Factory.create_dependency("tomlkit", {"version": "^0.5", "source": "lega cy"}) | |||
) | ) | |||
repo = MockLegacyRepository() | repo = MockLegacyRepository() | |||
pool = Pool([repo, MockPyPIRepository()]) | pool = Pool([repo, MockPyPIRepository()]) | |||
solver = Solver(package, pool, installed, locked, io) | solver = Solver(package, pool, installed.packages, locked.packages, io) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{ | { | |||
"job": "install", | "job": "install", | |||
"package": Package( | "package": Package( | |||
"tomlkit", | "tomlkit", | |||
"0.5.2", | "0.5.2", | |||
source_type="legacy", | source_type="legacy", | |||
source_url=repo.url, | source_url=repo.url, | |||
source_reference=repo.name, | source_reference=repo.name, | |||
), | ), | |||
} | } | |||
], | ], | |||
) | ) | |||
assert "http://legacy.foo.bar" == ops[0].package.source_url | assert ops[0].package.source_url == "http://legacy.foo.bar" | |||
def test_solver_chooses_from_correct_repository_if_forced_and_transitive_depende ncy( | def test_solver_chooses_from_correct_repository_if_forced_and_transitive_depende ncy( | |||
package, installed, locked, io | package: ProjectPackage, | |||
installed: InstalledRepository, | ||||
locked: Repository, | ||||
io: NullIO, | ||||
): | ): | |||
package.python_versions = "^3.7" | package.python_versions = "^3.7" | |||
package.add_dependency(Factory.create_dependency("foo", "^1.0")) | package.add_dependency(Factory.create_dependency("foo", "^1.0")) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("tomlkit", {"version": "^0.5", "source": "lega cy"}) | Factory.create_dependency("tomlkit", {"version": "^0.5", "source": "lega cy"}) | |||
) | ) | |||
repo = Repository() | repo = Repository("repo") | |||
foo = get_package("foo", "1.0.0") | foo = get_package("foo", "1.0.0") | |||
foo.add_dependency(Factory.create_dependency("tomlkit", "^0.5.0")) | foo.add_dependency(Factory.create_dependency("tomlkit", "^0.5.0")) | |||
repo.add_package(foo) | repo.add_package(foo) | |||
pool = Pool([MockLegacyRepository(), repo, MockPyPIRepository()]) | pool = Pool([MockLegacyRepository(), repo, MockPyPIRepository()]) | |||
solver = Solver(package, pool, installed, locked, io) | solver = Solver(package, pool, installed.packages, locked.packages, io) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{ | { | |||
"job": "install", | "job": "install", | |||
"package": Package( | "package": Package( | |||
"tomlkit", | "tomlkit", | |||
"0.5.2", | "0.5.2", | |||
source_type="legacy", | source_type="legacy", | |||
source_url="http://legacy.foo.bar", | source_url="http://legacy.foo.bar", | |||
source_reference="legacy", | source_reference="legacy", | |||
), | ), | |||
}, | }, | |||
{"job": "install", "package": foo}, | {"job": "install", "package": foo}, | |||
], | ], | |||
) | ) | |||
assert "http://legacy.foo.bar" == ops[0].package.source_url | assert ops[0].package.source_url == "http://legacy.foo.bar" | |||
assert ops[1].package.source_type is None | assert ops[1].package.source_type is None | |||
assert ops[1].package.source_url is None | assert ops[1].package.source_url is None | |||
def test_solver_does_not_choose_from_secondary_repository_by_default( | def test_solver_does_not_choose_from_secondary_repository_by_default( | |||
package, installed, locked, io | package: ProjectPackage, | |||
installed: InstalledRepository, | ||||
locked: Repository, | ||||
io: NullIO, | ||||
): | ): | |||
package.python_versions = "^3.7" | package.python_versions = "^3.7" | |||
package.add_dependency(Factory.create_dependency("clikit", {"version": "^0.2 .0"})) | package.add_dependency(Factory.create_dependency("clikit", {"version": "^0.2 .0"})) | |||
pool = Pool() | pool = Pool() | |||
pool.add_repository(MockPyPIRepository(), secondary=True) | pool.add_repository(MockPyPIRepository(), secondary=True) | |||
pool.add_repository(MockLegacyRepository()) | pool.add_repository(MockLegacyRepository()) | |||
solver = Solver(package, pool, installed, locked, io) | solver = Solver(package, pool, installed.packages, locked.packages, io) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{ | { | |||
"job": "install", | "job": "install", | |||
"package": Package( | "package": Package( | |||
"pastel", | "pastel", | |||
"0.1.0", | "0.1.0", | |||
source_type="legacy", | source_type="legacy", | |||
source_url="http://legacy.foo.bar", | source_url="http://legacy.foo.bar", | |||
source_reference="legacy", | source_reference="legacy", | |||
), | ), | |||
skipping to change at line 2080 | skipping to change at line 2725 | |||
"clikit", | "clikit", | |||
"0.2.4", | "0.2.4", | |||
source_type="legacy", | source_type="legacy", | |||
source_url="http://legacy.foo.bar", | source_url="http://legacy.foo.bar", | |||
source_reference="legacy", | source_reference="legacy", | |||
), | ), | |||
}, | }, | |||
], | ], | |||
) | ) | |||
assert "http://legacy.foo.bar" == ops[0].package.source_url | assert ops[0].package.source_url == "http://legacy.foo.bar" | |||
assert ops[1].package.source_type is None | assert ops[1].package.source_type is None | |||
assert ops[1].package.source_url is None | assert ops[1].package.source_url is None | |||
assert "http://legacy.foo.bar" == ops[2].package.source_url | assert ops[2].package.source_url == "http://legacy.foo.bar" | |||
def test_solver_chooses_from_secondary_if_explicit(package, installed, locked, i | def test_solver_chooses_from_secondary_if_explicit( | |||
o): | package: ProjectPackage, | |||
installed: InstalledRepository, | ||||
locked: Repository, | ||||
io: NullIO, | ||||
): | ||||
package.python_versions = "^3.7" | package.python_versions = "^3.7" | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("clikit", {"version": "^0.2.0", "source": "PyP I"}) | Factory.create_dependency("clikit", {"version": "^0.2.0", "source": "PyP I"}) | |||
) | ) | |||
pool = Pool() | pool = Pool() | |||
pool.add_repository(MockPyPIRepository(), secondary=True) | pool.add_repository(MockPyPIRepository(), secondary=True) | |||
pool.add_repository(MockLegacyRepository()) | pool.add_repository(MockLegacyRepository()) | |||
solver = Solver(package, pool, installed, locked, io) | solver = Solver(package, pool, installed.packages, locked.packages, io) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | ops = check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{ | { | |||
"job": "install", | "job": "install", | |||
"package": Package( | "package": Package( | |||
"pastel", | "pastel", | |||
"0.1.0", | "0.1.0", | |||
source_type="legacy", | source_type="legacy", | |||
source_url="http://legacy.foo.bar", | source_url="http://legacy.foo.bar", | |||
source_reference="legacy", | source_reference="legacy", | |||
), | ), | |||
}, | }, | |||
{"job": "install", "package": get_package("pylev", "1.3.0")}, | {"job": "install", "package": get_package("pylev", "1.3.0")}, | |||
{"job": "install", "package": get_package("clikit", "0.2.4")}, | {"job": "install", "package": get_package("clikit", "0.2.4")}, | |||
], | ], | |||
) | ) | |||
assert "http://legacy.foo.bar" == ops[0].package.source_url | assert ops[0].package.source_url == "http://legacy.foo.bar" | |||
assert ops[1].package.source_type is None | assert ops[1].package.source_type is None | |||
assert ops[1].package.source_url is None | assert ops[1].package.source_url is None | |||
assert ops[2].package.source_type is None | assert ops[2].package.source_type is None | |||
assert ops[2].package.source_url is None | assert ops[2].package.source_url is None | |||
def test_solver_discards_packages_with_empty_markers( | def test_solver_discards_packages_with_empty_markers( | |||
package, installed, locked, io, pool, repo | package: ProjectPackage, | |||
installed: InstalledRepository, | ||||
locked: Repository, | ||||
io: NullIO, | ||||
pool: Pool, | ||||
repo: Repository, | ||||
): | ): | |||
package.python_versions = "~2.7 || ^3.4" | package.python_versions = "~2.7 || ^3.4" | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency( | Factory.create_dependency( | |||
"a", {"version": "^0.1.0", "markers": "python_version >= '3.4'"} | "a", {"version": "^0.1.0", "markers": "python_version >= '3.4'"} | |||
) | ) | |||
) | ) | |||
package_a = get_package("a", "0.1.0") | package_a = get_package("a", "0.1.0") | |||
package_a.add_dependency( | package_a.add_dependency( | |||
skipping to change at line 2146 | skipping to change at line 2801 | |||
"b", {"version": "^0.1.0", "markers": "python_version < '3.2'"} | "b", {"version": "^0.1.0", "markers": "python_version < '3.2'"} | |||
) | ) | |||
) | ) | |||
package_a.add_dependency(Factory.create_dependency("c", "^0.2.0")) | package_a.add_dependency(Factory.create_dependency("c", "^0.2.0")) | |||
package_b = get_package("b", "0.1.0") | package_b = get_package("b", "0.1.0") | |||
package_c = get_package("c", "0.2.0") | package_c = get_package("c", "0.2.0") | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b) | repo.add_package(package_b) | |||
repo.add_package(package_c) | repo.add_package(package_c) | |||
solver = Solver(package, pool, installed, locked, io) | solver = Solver(package, pool, installed.packages, locked.packages, io) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_c}, | {"job": "install", "package": package_c}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
], | ], | |||
) | ) | |||
def test_solver_does_not_raise_conflict_for_conditional_dev_dependencies( | def test_solver_does_not_raise_conflict_for_conditional_dev_dependencies( | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
solver.provider.set_package_python_versions("~2.7 || ^3.5") | solver.provider.set_package_python_versions("~2.7 || ^3.5") | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency( | Factory.create_dependency( | |||
"A", {"version": "^1.0", "python": "~2.7"}, category="dev" | "A", {"version": "^1.0", "python": "~2.7"}, groups=["dev"] | |||
) | ) | |||
) | ) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency( | Factory.create_dependency( | |||
"A", {"version": "^2.0", "python": "^3.5"}, category="dev" | "A", {"version": "^2.0", "python": "^3.5"}, groups=["dev"] | |||
) | ) | |||
) | ) | |||
package_a100 = get_package("A", "1.0.0") | package_a100 = get_package("A", "1.0.0") | |||
package_a200 = get_package("A", "2.0.0") | package_a200 = get_package("A", "2.0.0") | |||
repo.add_package(package_a100) | repo.add_package(package_a100) | |||
repo.add_package(package_a200) | repo.add_package(package_a200) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_a100}, | {"job": "install", "package": package_a100}, | |||
{"job": "install", "package": package_a200}, | {"job": "install", "package": package_a200}, | |||
], | ], | |||
) | ) | |||
def test_solver_does_not_loop_indefinitely_on_duplicate_constraints_with_extras( | def test_solver_does_not_loop_indefinitely_on_duplicate_constraints_with_extras( | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
solver.provider.set_package_python_versions("~2.7 || ^3.5") | solver.provider.set_package_python_versions("~2.7 || ^3.5") | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency( | Factory.create_dependency( | |||
"requests", {"version": "^2.22.0", "extras": ["security"]} | "requests", {"version": "^2.22.0", "extras": ["security"]} | |||
) | ) | |||
) | ) | |||
requests = get_package("requests", "2.22.0") | requests = get_package("requests", "2.22.0") | |||
requests.add_dependency(Factory.create_dependency("idna", ">=2.5,<2.9")) | requests.add_dependency(Factory.create_dependency("idna", ">=2.5,<2.9")) | |||
skipping to change at line 2212 | skipping to change at line 2867 | |||
Factory.create_dependency( | Factory.create_dependency( | |||
"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["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) | |||
repo.add_package(idna) | repo.add_package(idna) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[{"job": "install", "package": idna}, {"job": "install", "package": requ ests}], | [{"job": "install", "package": idna}, {"job": "install", "package": requ ests}], | |||
) | ) | |||
def test_solver_does_not_fail_with_locked_git_and_non_git_dependencies( | def test_solver_does_not_fail_with_locked_git_and_non_git_dependencies( | |||
solver, repo, package, locked, pool, installed, io | repo: Repository, | |||
package: Package, | ||||
locked: Repository, | ||||
pool: Pool, | ||||
installed: InstalledRepository, | ||||
io: NullIO, | ||||
): | ): | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("demo", {"git": "https://github.com/demo/demo. git"}) | Factory.create_dependency("demo", {"git": "https://github.com/demo/demo. git"}) | |||
) | ) | |||
package.add_dependency(Factory.create_dependency("a", "^1.2.3")) | package.add_dependency(Factory.create_dependency("a", "^1.2.3")) | |||
git_package = Package( | git_package = Package( | |||
"demo", | "demo", | |||
"0.1.2", | "0.1.2", | |||
source_type="git", | source_type="git", | |||
source_url="https://github.com/demo/demo.git", | source_url="https://github.com/demo/demo.git", | |||
source_reference="master", | source_reference=DEFAULT_SOURCE_REF, | |||
source_resolved_reference="commit", | source_resolved_reference=MOCK_DEFAULT_GIT_REVISION, | |||
) | ) | |||
installed.add_package(git_package) | installed.add_package(git_package) | |||
locked.add_package(get_package("a", "1.2.3")) | locked.add_package(get_package("a", "1.2.3")) | |||
locked.add_package(git_package) | locked.add_package(git_package) | |||
repo.add_package(get_package("a", "1.2.3")) | repo.add_package(get_package("a", "1.2.3")) | |||
repo.add_package(Package("pendulum", "2.1.2")) | repo.add_package(Package("pendulum", "2.1.2")) | |||
solver = Solver(package, pool, installed, locked, io) | solver = Solver(package, pool, installed.packages, locked.packages, io) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": get_package("a", "1.2.3")}, | {"job": "install", "package": get_package("a", "1.2.3")}, | |||
{"job": "install", "package": git_package, "skipped": True}, | {"job": "install", "package": git_package, "skipped": True}, | |||
], | ], | |||
) | ) | |||
def test_ignore_python_constraint_no_overlap_dependencies(solver, repo, package) | def test_ignore_python_constraint_no_overlap_dependencies( | |||
: | solver: Solver, repo: Repository, package: ProjectPackage | |||
): | ||||
pytest = get_package("demo", "1.0.0") | pytest = get_package("demo", "1.0.0") | |||
pytest.add_dependency( | pytest.add_dependency( | |||
Factory.create_dependency( | Factory.create_dependency( | |||
"configparser", {"version": "^1.2.3", "python": "<3.2"} | "configparser", {"version": "^1.2.3", "python": "<3.2"} | |||
) | ) | |||
) | ) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("demo", {"version": "^1.0.0", "python": "^3.6" }) | Factory.create_dependency("demo", {"version": "^1.0.0", "python": "^3.6" }) | |||
) | ) | |||
repo.add_package(pytest) | repo.add_package(pytest) | |||
repo.add_package(get_package("configparser", "1.2.3")) | repo.add_package(get_package("configparser", "1.2.3")) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, [{"job": "install", "package": pytest}], | transaction, | |||
[{"job": "install", "package": pytest}], | ||||
) | ) | |||
def test_solver_should_not_go_into_an_infinite_loop_on_duplicate_dependencies( | def test_solver_should_not_go_into_an_infinite_loop_on_duplicate_dependencies( | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
solver.provider.set_package_python_versions("~2.7 || ^3.5") | solver.provider.set_package_python_versions("~2.7 || ^3.5") | |||
package.add_dependency(Factory.create_dependency("A", "^1.0")) | package.add_dependency(Factory.create_dependency("A", "^1.0")) | |||
package_a = get_package("A", "1.0.0") | package_a = get_package("A", "1.0.0") | |||
package_a.add_dependency(Factory.create_dependency("B", "*")) | package_a.add_dependency(Factory.create_dependency("B", "*")) | |||
package_a.add_dependency( | package_a.add_dependency( | |||
Factory.create_dependency( | Factory.create_dependency( | |||
"B", {"version": "^1.0", "markers": "implementation_name == 'pypy'"} | "B", {"version": "^1.0", "markers": "implementation_name == 'pypy'"} | |||
) | ) | |||
) | ) | |||
package_b20 = get_package("B", "2.0.0") | package_b20 = get_package("B", "2.0.0") | |||
package_b10 = get_package("B", "1.0.0") | package_b10 = get_package("B", "1.0.0") | |||
repo.add_package(package_a) | repo.add_package(package_a) | |||
repo.add_package(package_b10) | repo.add_package(package_b10) | |||
repo.add_package(package_b20) | repo.add_package(package_b20) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_b10}, | {"job": "install", "package": package_b10}, | |||
{"job": "install", "package": package_b20}, | {"job": "install", "package": package_b20}, | |||
{"job": "install", "package": package_a}, | {"job": "install", "package": package_a}, | |||
], | ], | |||
) | ) | |||
def test_solver_remove_untracked_single(package, pool, installed, locked, io): | def test_solver_synchronize_single( | |||
solver = Solver(package, pool, installed, locked, io, remove_untracked=True) | package: ProjectPackage, | |||
pool: Pool, | ||||
installed: InstalledRepository, | ||||
locked: Repository, | ||||
io: NullIO, | ||||
): | ||||
solver = Solver(package, pool, installed.packages, locked.packages, io) | ||||
package_a = get_package("a", "1.0") | package_a = get_package("a", "1.0") | |||
installed.add_package(package_a) | installed.add_package(package_a) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result(ops, [{"job": "remove", "package": package_a}]) | check_solver_result( | |||
transaction, [{"job": "remove", "package": package_a}], synchronize=True | ||||
) | ||||
def test_solver_remove_untracked_keeps_critical_package( | @pytest.mark.skip(reason="Poetry no longer has critical package requirements") | |||
package, pool, installed, locked, io | def test_solver_with_synchronization_keeps_critical_package( | |||
package: ProjectPackage, | ||||
pool: Pool, | ||||
installed: InstalledRepository, | ||||
locked: Repository, | ||||
io: NullIO, | ||||
): | ): | |||
solver = Solver(package, pool, installed, locked, io, remove_untracked=True) | solver = Solver(package, pool, installed.packages, locked.packages, io) | |||
package_pip = get_package("pip", "1.0") | package_pip = get_package("setuptools", "1.0") | |||
installed.add_package(package_pip) | installed.add_package(package_pip) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result(ops, []) | check_solver_result(transaction, []) | |||
def test_solver_cannot_choose_another_version_for_directory_dependencies( | def test_solver_cannot_choose_another_version_for_directory_dependencies( | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
pendulum = get_package("pendulum", "2.0.3") | pendulum = get_package("pendulum", "2.0.3") | |||
demo = get_package("demo", "0.1.0") | demo = get_package("demo", "0.1.0") | |||
foo = get_package("foo", "1.2.3") | foo = get_package("foo", "1.2.3") | |||
foo.add_dependency(Factory.create_dependency("demo", "<0.1.2")) | foo.add_dependency(Factory.create_dependency("demo", "<0.1.2")) | |||
repo.add_package(foo) | repo.add_package(foo) | |||
repo.add_package(demo) | repo.add_package(demo) | |||
repo.add_package(pendulum) | repo.add_package(pendulum) | |||
path = ( | path = ( | |||
skipping to change at line 2358 | skipping to change at line 3034 | |||
package.add_dependency(Factory.create_dependency("demo", {"path": path})) | package.add_dependency(Factory.create_dependency("demo", {"path": path})) | |||
package.add_dependency(Factory.create_dependency("foo", "^1.2.3")) | package.add_dependency(Factory.create_dependency("foo", "^1.2.3")) | |||
# This is not solvable since the demo version is pinned | # This is not solvable since the demo version is pinned | |||
# via the directory dependency | # via the directory dependency | |||
with pytest.raises(SolverProblemError): | with pytest.raises(SolverProblemError): | |||
solver.solve() | solver.solve() | |||
def test_solver_cannot_choose_another_version_for_file_dependencies( | def test_solver_cannot_choose_another_version_for_file_dependencies( | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
pendulum = get_package("pendulum", "2.0.3") | pendulum = get_package("pendulum", "2.0.3") | |||
demo = get_package("demo", "0.0.8") | demo = get_package("demo", "0.0.8") | |||
foo = get_package("foo", "1.2.3") | foo = get_package("foo", "1.2.3") | |||
foo.add_dependency(Factory.create_dependency("demo", "<0.1.0")) | foo.add_dependency(Factory.create_dependency("demo", "<0.1.0")) | |||
repo.add_package(foo) | repo.add_package(foo) | |||
repo.add_package(demo) | repo.add_package(demo) | |||
repo.add_package(pendulum) | repo.add_package(pendulum) | |||
path = ( | path = ( | |||
skipping to change at line 2384 | skipping to change at line 3060 | |||
package.add_dependency(Factory.create_dependency("demo", {"path": path})) | package.add_dependency(Factory.create_dependency("demo", {"path": path})) | |||
package.add_dependency(Factory.create_dependency("foo", "^1.2.3")) | package.add_dependency(Factory.create_dependency("foo", "^1.2.3")) | |||
# This is not solvable since the demo version is pinned | # This is not solvable since the demo version is pinned | |||
# via the file dependency | # via the file dependency | |||
with pytest.raises(SolverProblemError): | with pytest.raises(SolverProblemError): | |||
solver.solve() | solver.solve() | |||
def test_solver_cannot_choose_another_version_for_git_dependencies( | def test_solver_cannot_choose_another_version_for_git_dependencies( | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
pendulum = get_package("pendulum", "2.0.3") | pendulum = get_package("pendulum", "2.0.3") | |||
demo = get_package("demo", "0.0.8") | demo = get_package("demo", "0.0.8") | |||
foo = get_package("foo", "1.2.3") | foo = get_package("foo", "1.2.3") | |||
foo.add_dependency(Factory.create_dependency("demo", "<0.1.0")) | foo.add_dependency(Factory.create_dependency("demo", "<0.1.0")) | |||
repo.add_package(foo) | repo.add_package(foo) | |||
repo.add_package(demo) | repo.add_package(demo) | |||
repo.add_package(pendulum) | repo.add_package(pendulum) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("demo", {"git": "https://github.com/demo/demo. git"}) | Factory.create_dependency("demo", {"git": "https://github.com/demo/demo. git"}) | |||
) | ) | |||
package.add_dependency(Factory.create_dependency("foo", "^1.2.3")) | package.add_dependency(Factory.create_dependency("foo", "^1.2.3")) | |||
# This is not solvable since the demo version is pinned | # This is not solvable since the demo version is pinned | |||
# via the file dependency | # via the file dependency | |||
with pytest.raises(SolverProblemError): | with pytest.raises(SolverProblemError): | |||
solver.solve() | solver.solve() | |||
def test_solver_cannot_choose_another_version_for_url_dependencies( | def test_solver_cannot_choose_another_version_for_url_dependencies( | |||
solver, repo, package, http | solver: Solver, | |||
repo: Repository, | ||||
package: Package, | ||||
http: type[httpretty.httpretty], | ||||
): | ): | |||
path = ( | path = ( | |||
Path(__file__).parent.parent | Path(__file__).parent.parent | |||
/ "fixtures" | / "fixtures" | |||
/ "distributions" | / "distributions" | |||
/ "demo-0.1.0-py2.py3-none-any.whl" | / "demo-0.1.0-py2.py3-none-any.whl" | |||
) | ) | |||
http.register_uri( | http.register_uri( | |||
"GET", | "GET", | |||
skipping to change at line 2442 | skipping to change at line 3121 | |||
) | ) | |||
) | ) | |||
package.add_dependency(Factory.create_dependency("foo", "^1.2.3")) | package.add_dependency(Factory.create_dependency("foo", "^1.2.3")) | |||
# This is not solvable since the demo version is pinned | # This is not solvable since the demo version is pinned | |||
# via the git dependency | # via the git dependency | |||
with pytest.raises(SolverProblemError): | with pytest.raises(SolverProblemError): | |||
solver.solve() | solver.solve() | |||
def test_solver_should_not_update_same_version_packages_if_installed_has_no_sour ce_type( | def test_solver_should_not_update_same_version_packages_if_installed_has_no_sour ce_type( | |||
solver, repo, package, installed | solver: Solver, repo: Repository, package: Package, installed: InstalledRepo sitory | |||
): | ): | |||
package.add_dependency(Factory.create_dependency("foo", "1.0.0")) | package.add_dependency(Factory.create_dependency("foo", "1.0.0")) | |||
foo = Package( | foo = Package( | |||
"foo", | "foo", | |||
"1.0.0", | "1.0.0", | |||
source_type="legacy", | source_type="legacy", | |||
source_url="https://foo.bar", | source_url="https://foo.bar", | |||
source_reference="custom", | source_reference="custom", | |||
) | ) | |||
repo.add_package(foo) | repo.add_package(foo) | |||
installed.add_package(get_package("foo", "1.0.0")) | installed.add_package(get_package("foo", "1.0.0")) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result(ops, [{"job": "install", "package": foo, "skipped": True | check_solver_result( | |||
}]) | transaction, [{"job": "install", "package": foo, "skipped": True}] | |||
) | ||||
def test_solver_should_use_the_python_constraint_from_the_environment_if_availab le( | def test_solver_should_use_the_python_constraint_from_the_environment_if_availab le( | |||
solver, repo, package, installed | solver: Solver, repo: Repository, package: Package, installed: InstalledRepo sitory | |||
): | ): | |||
solver.provider.set_package_python_versions("~2.7 || ^3.5") | solver.provider.set_package_python_versions("~2.7 || ^3.5") | |||
package.add_dependency(Factory.create_dependency("A", "^1.0")) | package.add_dependency(Factory.create_dependency("A", "^1.0")) | |||
a = get_package("A", "1.0.0") | a = get_package("A", "1.0.0") | |||
a.add_dependency( | a.add_dependency( | |||
Factory.create_dependency( | Factory.create_dependency( | |||
"B", {"version": "^1.0.0", "markers": 'python_version < "3.2"'} | "B", {"version": "^1.0.0", "markers": 'python_version < "3.2"'} | |||
) | ) | |||
) | ) | |||
b = get_package("B", "1.0.0") | b = get_package("B", "1.0.0") | |||
b.python_versions = ">=2.6, <3" | b.python_versions = ">=2.6, <3" | |||
repo.add_package(a) | repo.add_package(a) | |||
repo.add_package(b) | repo.add_package(b) | |||
with solver.use_environment(MockEnv((2, 7, 18))): | with solver.use_environment(MockEnv((2, 7, 18))): | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, [{"job": "install", "package": b}, {"job": "install", "package": a} | transaction, | |||
], | [{"job": "install", "package": b}, {"job": "install", "package": a}], | |||
) | ) | |||
def test_solver_should_resolve_all_versions_for_multiple_duplicate_dependencies( | def test_solver_should_resolve_all_versions_for_multiple_duplicate_dependencies( | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
package.python_versions = "~2.7 || ^3.5" | package.python_versions = "~2.7 || ^3.5" | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency( | Factory.create_dependency( | |||
"A", {"version": "^1.0", "markers": "python_version < '3.5'"} | "A", {"version": "^1.0", "markers": "python_version < '3.5'"} | |||
) | ) | |||
) | ) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency( | Factory.create_dependency( | |||
"A", {"version": "^2.0", "markers": "python_version >= '3.5'"} | "A", {"version": "^2.0", "markers": "python_version >= '3.5'"} | |||
skipping to change at line 2520 | skipping to change at line 3202 | |||
package_a10 = get_package("A", "1.0.0") | package_a10 = get_package("A", "1.0.0") | |||
package_a20 = get_package("A", "2.0.0") | package_a20 = get_package("A", "2.0.0") | |||
package_b30 = get_package("B", "3.0.0") | package_b30 = get_package("B", "3.0.0") | |||
package_b40 = get_package("B", "4.0.0") | package_b40 = get_package("B", "4.0.0") | |||
repo.add_package(package_a10) | repo.add_package(package_a10) | |||
repo.add_package(package_a20) | repo.add_package(package_a20) | |||
repo.add_package(package_b30) | repo.add_package(package_b30) | |||
repo.add_package(package_b40) | repo.add_package(package_b40) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": package_a10}, | {"job": "install", "package": package_a10}, | |||
{"job": "install", "package": package_a20}, | {"job": "install", "package": package_a20}, | |||
{"job": "install", "package": package_b30}, | {"job": "install", "package": package_b30}, | |||
{"job": "install", "package": package_b40}, | {"job": "install", "package": package_b40}, | |||
], | ], | |||
) | ) | |||
def test_solver_should_not_raise_errors_for_irrelevant_python_constraints( | def test_solver_should_not_raise_errors_for_irrelevant_python_constraints( | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
package.python_versions = "^3.6" | package.python_versions = "^3.6" | |||
solver.provider.set_package_python_versions("^3.6") | solver.provider.set_package_python_versions("^3.6") | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("dataclasses", {"version": "^0.7", "python": " <3.7"}) | Factory.create_dependency("dataclasses", {"version": "^0.7", "python": " <3.7"}) | |||
) | ) | |||
dataclasses = get_package("dataclasses", "0.7") | dataclasses = get_package("dataclasses", "0.7") | |||
dataclasses.python_versions = ">=3.6, <3.7" | dataclasses.python_versions = ">=3.6, <3.7" | |||
repo.add_package(dataclasses) | repo.add_package(dataclasses) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result(ops, [{"job": "install", "package": dataclasses}]) | check_solver_result(transaction, [{"job": "install", "package": dataclasses} ]) | |||
def test_solver_can_resolve_transitive_extras(solver, repo, package): | def test_solver_can_resolve_transitive_extras( | |||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
package.add_dependency(Factory.create_dependency("requests", "^2.24.0")) | package.add_dependency(Factory.create_dependency("requests", "^2.24.0")) | |||
package.add_dependency(Factory.create_dependency("PyOTA", "^2.1.0")) | package.add_dependency(Factory.create_dependency("PyOTA", "^2.1.0")) | |||
requests = get_package("requests", "2.24.0") | requests = get_package("requests", "2.24.0") | |||
requests.add_dependency(Factory.create_dependency("certifi", ">=2017.4.17")) | requests.add_dependency(Factory.create_dependency("certifi", ">=2017.4.17")) | |||
dep = get_dependency("PyOpenSSL", ">=0.14") | dep = get_dependency("PyOpenSSL", ">=0.14") | |||
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["security"] = [dep] | |||
skipping to change at line 2572 | skipping to change at line 3256 | |||
Factory.create_dependency( | Factory.create_dependency( | |||
"requests", {"version": ">=2.24.0", "extras": ["security"]} | "requests", {"version": ">=2.24.0", "extras": ["security"]} | |||
) | ) | |||
) | ) | |||
repo.add_package(requests) | repo.add_package(requests) | |||
repo.add_package(pyota) | repo.add_package(pyota) | |||
repo.add_package(get_package("certifi", "2017.4.17")) | repo.add_package(get_package("certifi", "2017.4.17")) | |||
repo.add_package(get_package("pyopenssl", "0.14")) | repo.add_package(get_package("pyopenssl", "0.14")) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": get_package("certifi", "2017.4.17")}, | {"job": "install", "package": get_package("certifi", "2017.4.17")}, | |||
{"job": "install", "package": get_package("pyopenssl", "0.14")}, | {"job": "install", "package": get_package("pyopenssl", "0.14")}, | |||
{"job": "install", "package": requests}, | {"job": "install", "package": requests}, | |||
{"job": "install", "package": pyota}, | {"job": "install", "package": pyota}, | |||
], | ], | |||
) | ) | |||
def test_solver_can_resolve_for_packages_with_missing_extras(solver, repo, packa | def test_solver_can_resolve_for_packages_with_missing_extras( | |||
ge): | solver: Solver, repo: Repository, package: ProjectPackage | |||
): | ||||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency( | Factory.create_dependency( | |||
"django-anymail", {"version": "^6.0", "extras": ["postmark"]} | "django-anymail", {"version": "^6.0", "extras": ["postmark"]} | |||
) | ) | |||
) | ) | |||
django_anymail = get_package("django-anymail", "6.1.0") | django_anymail = get_package("django-anymail", "6.1.0") | |||
django_anymail.add_dependency(Factory.create_dependency("django", ">=2.0")) | django_anymail.add_dependency(Factory.create_dependency("django", ">=2.0")) | |||
django_anymail.add_dependency(Factory.create_dependency("requests", ">=2.4.3 ")) | django_anymail.add_dependency(Factory.create_dependency("requests", ">=2.4.3 ")) | |||
django_anymail.add_dependency( | django_anymail.add_dependency( | |||
skipping to change at line 2607 | skipping to change at line 3293 | |||
django_anymail.extras["amazon_ses"] = [Factory.create_dependency("boto3", "* ")] | django_anymail.extras["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") | |||
repo.add_package(django_anymail) | repo.add_package(django_anymail) | |||
repo.add_package(django) | repo.add_package(django) | |||
repo.add_package(boto3) | repo.add_package(boto3) | |||
repo.add_package(requests) | repo.add_package(requests) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": django}, | {"job": "install", "package": django}, | |||
{"job": "install", "package": requests}, | {"job": "install", "package": requests}, | |||
{"job": "install", "package": django_anymail}, | {"job": "install", "package": django_anymail}, | |||
], | ], | |||
) | ) | |||
def test_solver_can_resolve_python_restricted_package_dependencies( | def test_solver_can_resolve_python_restricted_package_dependencies( | |||
solver, repo, package, locked | solver: Solver, repo: Repository, package: Package, locked: Repository | |||
): | ): | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("futures", {"version": "^3.3.0", "python": "~2 .7"}) | Factory.create_dependency("futures", {"version": "^3.3.0", "python": "~2 .7"}) | |||
) | ) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("pre-commit", {"version": "^2.6", "python": "^ 3.6.1"}) | Factory.create_dependency("pre-commit", {"version": "^2.6", "python": "^ 3.6.1"}) | |||
) | ) | |||
futures = Package("futures", "3.3.0") | futures = Package("futures", "3.3.0") | |||
futures.python_versions = ">=2.6, <3" | futures.python_versions = ">=2.6, <3" | |||
pre_commit = Package("pre-commit", "2.7.1") | pre_commit = Package("pre-commit", "2.7.1") | |||
pre_commit.python_versions = ">=3.6.1" | pre_commit.python_versions = ">=3.6.1" | |||
locked.add_package(futures) | locked.add_package(futures) | |||
locked.add_package(pre_commit) | locked.add_package(pre_commit) | |||
repo.add_package(futures) | repo.add_package(futures) | |||
repo.add_package(pre_commit) | repo.add_package(pre_commit) | |||
ops = solver.solve(use_latest=["pre-commit"]) | transaction = solver.solve(use_latest=["pre-commit"]) | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": futures}, | {"job": "install", "package": futures}, | |||
{"job": "install", "package": pre_commit}, | {"job": "install", "package": pre_commit}, | |||
], | ], | |||
) | ) | |||
def test_solver_should_not_raise_errors_for_irrelevant_transitive_python_constra ints( | def test_solver_should_not_raise_errors_for_irrelevant_transitive_python_constra ints( | |||
solver, repo, package | solver: Solver, repo: Repository, package: Package | |||
): | ): | |||
package.python_versions = "~2.7 || ^3.5" | package.python_versions = "~2.7 || ^3.5" | |||
solver.provider.set_package_python_versions("~2.7 || ^3.5") | solver.provider.set_package_python_versions("~2.7 || ^3.5") | |||
package.add_dependency(Factory.create_dependency("virtualenv", "^20.4.3")) | package.add_dependency(Factory.create_dependency("virtualenv", "^20.4.3")) | |||
package.add_dependency( | package.add_dependency( | |||
Factory.create_dependency("pre-commit", {"version": "^2.6", "python": "^ 3.6.1"}) | Factory.create_dependency("pre-commit", {"version": "^2.6", "python": "^ 3.6.1"}) | |||
) | ) | |||
virtualenv = get_package("virtualenv", "20.4.3") | virtualenv = get_package("virtualenv", "20.4.3") | |||
virtualenv.python_versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" | virtualenv.python_versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" | |||
skipping to change at line 2688 | skipping to change at line 3374 | |||
importlib_resources_3_2_1 = get_package("importlib-resources", "3.2.1") | importlib_resources_3_2_1 = get_package("importlib-resources", "3.2.1") | |||
importlib_resources_3_2_1.python_versions = ( | importlib_resources_3_2_1.python_versions = ( | |||
"!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" | "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" | |||
) | ) | |||
repo.add_package(virtualenv) | repo.add_package(virtualenv) | |||
repo.add_package(pre_commit) | repo.add_package(pre_commit) | |||
repo.add_package(importlib_resources) | repo.add_package(importlib_resources) | |||
repo.add_package(importlib_resources_3_2_1) | repo.add_package(importlib_resources_3_2_1) | |||
ops = solver.solve() | transaction = solver.solve() | |||
check_solver_result( | check_solver_result( | |||
ops, | transaction, | |||
[ | [ | |||
{"job": "install", "package": importlib_resources_3_2_1}, | {"job": "install", "package": importlib_resources_3_2_1}, | |||
{"job": "install", "package": pre_commit}, | {"job": "install", "package": pre_commit}, | |||
{"job": "install", "package": virtualenv}, | {"job": "install", "package": virtualenv}, | |||
], | ], | |||
) | ) | |||
@pytest.mark.parametrize("is_locked", [False, True]) | ||||
def test_solver_keeps_multiple_locked_dependencies_for_same_package( | ||||
solver: Solver, | ||||
repo: Repository, | ||||
package: Package, | ||||
locked: Repository, | ||||
is_locked: bool, | ||||
): | ||||
solver.provider.set_package_python_versions("^3.6") | ||||
package.add_dependency( | ||||
Factory.create_dependency("A", {"version": "~1.1", "python": "<3.7"}) | ||||
) | ||||
package.add_dependency( | ||||
Factory.create_dependency("A", {"version": "~1.2", "python": ">=3.7"}) | ||||
) | ||||
a11 = Package("A", "1.1") | ||||
a12 = Package("A", "1.2") | ||||
a11.add_dependency(Factory.create_dependency("B", {"version": ">=0.3"})) | ||||
a12.add_dependency(Factory.create_dependency("B", {"version": ">=0.3"})) | ||||
b03 = Package("B", "0.3") | ||||
b04 = Package("B", "0.4") | ||||
b04.python_versions = ">=3.6.2,<4.0.0" | ||||
repo.add_package(a11) | ||||
repo.add_package(a12) | ||||
repo.add_package(b03) | ||||
repo.add_package(b04) | ||||
if is_locked: | ||||
a11_locked = a11.clone() | ||||
a11_locked.python_versions = "<3.7" | ||||
locked.add_package(a11_locked) | ||||
a12_locked = a12.clone() | ||||
a12_locked.python_versions = ">=3.7" | ||||
locked.add_package(a12_locked) | ||||
locked.add_package(b03.clone()) | ||||
locked.add_package(b04.clone()) | ||||
transaction = solver.solve() | ||||
check_solver_result( | ||||
transaction, | ||||
[ | ||||
{"job": "install", "package": b03}, | ||||
{"job": "install", "package": b04}, | ||||
{"job": "install", "package": a11}, | ||||
{"job": "install", "package": a12}, | ||||
], | ||||
) | ||||
def test_solver_direct_origin_dependency_with_extras_requested_by_other_package( | ||||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
""" | ||||
Another package requires the same dependency with extras that is required | ||||
by the project as direct origin dependency without any extras. | ||||
""" | ||||
pendulum = get_package("pendulum", "2.0.3") # required by demo | ||||
cleo = get_package("cleo", "1.0.0") # required by demo[foo] | ||||
demo_foo = get_package("demo-foo", "1.2.3") | ||||
demo_foo.add_dependency( | ||||
Factory.create_dependency("demo", {"version": ">=0.1", "extras": ["foo"] | ||||
}) | ||||
) | ||||
repo.add_package(demo_foo) | ||||
repo.add_package(pendulum) | ||||
repo.add_package(cleo) | ||||
path = ( | ||||
Path(__file__).parent.parent | ||||
/ "fixtures" | ||||
/ "git" | ||||
/ "github.com" | ||||
/ "demo" | ||||
/ "demo" | ||||
).as_posix() | ||||
# project requires path dependency of demo while demo-foo requires demo[foo] | ||||
package.add_dependency(Factory.create_dependency("demo", {"path": path})) | ||||
package.add_dependency(Factory.create_dependency("demo-foo", "^1.2.3")) | ||||
transaction = solver.solve() | ||||
demo = Package("demo", "0.1.2", source_type="directory", source_url=path) | ||||
ops = check_solver_result( | ||||
transaction, | ||||
[ | ||||
{"job": "install", "package": cleo}, | ||||
{"job": "install", "package": pendulum}, | ||||
{"job": "install", "package": demo}, | ||||
{"job": "install", "package": demo_foo}, | ||||
], | ||||
) | ||||
op = ops[2] | ||||
assert op.package.name == "demo" | ||||
assert op.package.version.text == "0.1.2" | ||||
assert op.package.source_type == "directory" | ||||
assert op.package.source_url == path | ||||
def test_solver_incompatible_dependency_with_and_without_extras( | ||||
solver: Solver, repo: Repository, package: ProjectPackage | ||||
): | ||||
""" | ||||
The solver first encounters a requirement for google-auth and then later an | ||||
incompatible requirement for google-auth[aiohttp]. | ||||
Testcase derived from https://github.com/python-poetry/poetry/issues/6054. | ||||
""" | ||||
# Incompatible requirements from foo and bar2. | ||||
foo = get_package("foo", "1.0.0") | ||||
foo.add_dependency(Factory.create_dependency("google-auth", {"version": "^1" | ||||
})) | ||||
bar = get_package("bar", "1.0.0") | ||||
bar2 = get_package("bar", "2.0.0") | ||||
bar2.add_dependency( | ||||
Factory.create_dependency( | ||||
"google-auth", {"version": "^2", "extras": ["aiohttp"]} | ||||
) | ||||
) | ||||
baz = get_package("baz", "1.0.0") # required by google-auth[aiohttp] | ||||
google_auth = get_package("google-auth", "1.2.3") | ||||
google_auth.extras = {"aiohttp": [get_dependency("baz", "^1.0")]} | ||||
google_auth2 = get_package("google-auth", "2.3.4") | ||||
google_auth2.extras = {"aiohttp": [get_dependency("baz", "^1.0")]} | ||||
repo.add_package(foo) | ||||
repo.add_package(bar) | ||||
repo.add_package(bar2) | ||||
repo.add_package(baz) | ||||
repo.add_package(google_auth) | ||||
repo.add_package(google_auth2) | ||||
package.add_dependency(Factory.create_dependency("foo", ">=1")) | ||||
package.add_dependency(Factory.create_dependency("bar", ">=1")) | ||||
transaction = solver.solve() | ||||
check_solver_result( | ||||
transaction, | ||||
[ | ||||
{"job": "install", "package": google_auth}, | ||||
{"job": "install", "package": bar}, | ||||
{"job": "install", "package": foo}, | ||||
], | ||||
) | ||||
def test_update_with_prerelease_and_no_solution( | ||||
solver: Solver, | ||||
repo: Repository, | ||||
installed: InstalledRepository, | ||||
package: ProjectPackage, | ||||
locked: Repository, | ||||
): | ||||
# Locked and installed: cleo which depends on an old version of crashtest. | ||||
cleo = get_package("cleo", "1.0.0a5") | ||||
crashtest = get_package("crashtest", "0.3.0") | ||||
cleo.add_dependency(Factory.create_dependency("crashtest", {"version": "<0.4 | ||||
.0"})) | ||||
locked.add_package(cleo) | ||||
locked.add_package(crashtest) | ||||
installed.add_package(cleo) | ||||
installed.add_package(crashtest) | ||||
# Try to upgrade to a new version of crashtest, this will be disallowed by t | ||||
he | ||||
# dependency from cleo. | ||||
package.add_dependency(Factory.create_dependency("cleo", "^1.0.0a5")) | ||||
package.add_dependency(Factory.create_dependency("crashtest", "^0.4.0")) | ||||
newer_crashtest = get_package("crashtest", "0.4.0") | ||||
even_newer_crashtest = get_package("crashtest", "0.4.1") | ||||
repo.add_package(cleo) | ||||
repo.add_package(crashtest) | ||||
repo.add_package(newer_crashtest) | ||||
repo.add_package(even_newer_crashtest) | ||||
with pytest.raises(SolverProblemError): | ||||
solver.solve() | ||||
def test_solver_yanked_warning( | ||||
package: ProjectPackage, | ||||
installed: InstalledRepository, | ||||
locked: Repository, | ||||
pool: Pool, | ||||
repo: Repository, | ||||
) -> None: | ||||
package.add_dependency(Factory.create_dependency("foo", "==1")) | ||||
package.add_dependency(Factory.create_dependency("bar", "==2")) | ||||
package.add_dependency(Factory.create_dependency("baz", "==3")) | ||||
foo = get_package("foo", "1", yanked=False) | ||||
bar = get_package("bar", "2", yanked=True) | ||||
baz = get_package("baz", "3", yanked="just wrong") | ||||
repo.add_package(foo) | ||||
repo.add_package(bar) | ||||
repo.add_package(baz) | ||||
io = BufferedIO(decorated=False) | ||||
solver = Solver(package, pool, installed.packages, locked.packages, io) | ||||
transaction = solver.solve() | ||||
check_solver_result( | ||||
transaction, | ||||
[ | ||||
{"job": "install", "package": bar}, | ||||
{"job": "install", "package": baz}, | ||||
{"job": "install", "package": foo}, | ||||
], | ||||
) | ||||
error = io.fetch_error() | ||||
assert "foo" not in error | ||||
assert "The locked version 2 for bar is a yanked version." in error | ||||
assert ( | ||||
"The locked version 3 for baz is a yanked version. Reason for being yank | ||||
ed:" | ||||
" just wrong" | ||||
in error | ||||
) | ||||
assert error.count("is a yanked version") == 2 | ||||
assert error.count("Reason for being yanked") == 1 | ||||
End of changes. 322 change blocks. | ||||
391 lines changed or deleted | 1076 lines changed or added |