Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ignore installed packages during solving #9851

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 9 additions & 54 deletions src/poetry/puzzle/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
from poetry.packages.direct_origin import DirectOrigin
from poetry.packages.package_collection import PackageCollection
from poetry.puzzle.exceptions import OverrideNeededError
from poetry.repositories.exceptions import PackageNotFoundError
from poetry.utils.helpers import get_file_hash


Expand Down Expand Up @@ -115,7 +114,6 @@ def __init__(
pool: RepositoryPool,
io: IO,
*,
installed: list[Package] | None = None,
locked: list[Package] | None = None,
) -> None:
self._package = package
Expand All @@ -129,7 +127,6 @@ def __init__(
self._deferred_cache: dict[Dependency, Package] = {}
self._load_deferred = True
self._source_root: Path | None = None
self._installed_packages = installed if installed is not None else []
self._direct_origin_packages: dict[str, Package] = {}
self._locked: dict[NormalizedName, list[DependencyPackage]] = defaultdict(list)
self._use_latest: Collection[NormalizedName] = []
Expand Down Expand Up @@ -205,36 +202,6 @@ def validate_package_for_dependency(
f" package's name: {package.name}"
)

def search_for_installed_packages(
self,
dependency: Dependency,
) -> list[Package]:
"""
Search for installed packages, when available, that satisfy the given
dependency.

This is useful when dealing with packages that are under development, not
published on package sources and/or only available via system installations.
"""
if not self._installed_packages:
return []

logger.debug(
"Falling back to installed packages to discover metadata for <c2>%s</>",
dependency.complete_name,
)
packages = [
package
for package in self._installed_packages
if package.satisfies(dependency, ignore_source_type=True)
]
logger.debug(
"Found <c2>%d</> compatible packages for <c2>%s</>",
len(packages),
dependency.complete_name,
)
return packages

def search_for_direct_origin_dependency(self, dependency: Dependency) -> Package:
package = self._deferred_cache.get(dependency)
if package is not None:
Expand Down Expand Up @@ -308,9 +275,6 @@ def search_for(self, dependency: Dependency) -> list[DependencyPackage]:
reverse=True,
)

if not packages:
packages = self.search_for_installed_packages(dependency)

return PackageCollection(dependency, packages)

def _search_for_vcs(self, dependency: VCSDependency) -> Package:
Expand Down Expand Up @@ -483,24 +447,15 @@ def complete_package(
elif package.is_direct_origin():
requires = package.requires
else:
try:
dependency_package = DependencyPackage(
dependency,
self._pool.package(
package.pretty_name,
package.version,
extras=list(dependency.extras),
repository_name=dependency.source_name,
),
)
except PackageNotFoundError as e:
try:
dependency_package = next(
DependencyPackage(dependency, pkg)
for pkg in self.search_for_installed_packages(dependency)
)
except StopIteration:
raise e from e
dependency_package = DependencyPackage(
dependency,
self._pool.package(
package.pretty_name,
package.version,
extras=list(dependency.extras),
repository_name=dependency.source_name,
),
)

package = dependency_package.package
dependency = dependency_package.dependency
Expand Down
4 changes: 1 addition & 3 deletions src/poetry/puzzle/solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,7 @@ def __init__(
self._locked_packages = locked
self._io = io

self._provider = Provider(
self._package, self._pool, self._io, installed=installed, locked=locked
)
self._provider = Provider(self._package, self._pool, self._io, locked=locked)
self._overrides: list[dict[Package, dict[str, Dependency]]] = []

@property
Expand Down
18 changes: 4 additions & 14 deletions tests/puzzle/test_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def test_install_non_existing_package_fail(
solver.solve()


def test_install_unpublished_package_does_not_fail(
def test_install_unpublished_package_fails(
package: ProjectPackage, repo: Repository, pool: RepositoryPool, io: NullIO
) -> None:
package.add_dependency(Factory.create_dependency("B", "1"))
Expand All @@ -151,20 +151,10 @@ def test_install_unpublished_package_does_not_fail(

repo.add_package(package_a)

# Even though B is installed, it is unpublished and cannot be used during solving.
solver = Solver(package, pool, [package_b], [], io)
transaction = solver.solve()

check_solver_result(
transaction,
[
{"job": "install", "package": package_a},
{
"job": "install",
"package": package_b,
"skipped": True, # already installed
},
],
)
with pytest.raises(SolverProblemError):
solver.solve()


def test_solver_with_deps(
Expand Down
Loading