Commit 9e4fb44b by Arun Babu Neelicattu

provider: allow fallback to installed packages

parent 2d8ea84a
...@@ -35,6 +35,7 @@ from poetry.mixology.term import Term ...@@ -35,6 +35,7 @@ from poetry.mixology.term import Term
from poetry.packages import DependencyPackage from poetry.packages import DependencyPackage
from poetry.packages.package_collection import PackageCollection from poetry.packages.package_collection import PackageCollection
from poetry.puzzle.exceptions import OverrideNeeded from poetry.puzzle.exceptions import OverrideNeeded
from poetry.repositories.exceptions import PackageNotFound
from poetry.utils.helpers import download_file from poetry.utils.helpers import download_file
from poetry.vcs.git import Git from poetry.vcs.git import Git
...@@ -46,10 +47,12 @@ if TYPE_CHECKING: ...@@ -46,10 +47,12 @@ if TYPE_CHECKING:
from poetry.core.packages.dependency import Dependency from poetry.core.packages.dependency import Dependency
from poetry.core.packages.package import Package from poetry.core.packages.package import Package
from poetry.core.packages.specification import PackageSpecification
from poetry.core.semver.version_constraint import VersionConstraint from poetry.core.semver.version_constraint import VersionConstraint
from poetry.core.version.markers import BaseMarker from poetry.core.version.markers import BaseMarker
from poetry.repositories import Pool from poetry.repositories import Pool
from poetry.repositories import Repository
from poetry.utils.env import Env from poetry.utils.env import Env
...@@ -124,6 +127,7 @@ class Provider: ...@@ -124,6 +127,7 @@ class Provider:
pool: Pool, pool: Pool,
io: Any, io: Any,
env: Env | None = None, env: Env | None = None,
installed: Repository | None = None,
) -> None: ) -> None:
self._package = package self._package = package
self._pool = pool self._pool = pool
...@@ -136,6 +140,7 @@ class Provider: ...@@ -136,6 +140,7 @@ class Provider:
self._deferred_cache: dict[Dependency, Package] = {} self._deferred_cache: dict[Dependency, Package] = {}
self._load_deferred = True self._load_deferred = True
self._source_root: Path | None = None self._source_root: Path | None = None
self._installed = installed
@property @property
def pool(self) -> Pool: def pool(self) -> Pool:
...@@ -185,6 +190,36 @@ class Provider: ...@@ -185,6 +190,36 @@ class Provider:
f" package's name: {package.name}" f" package's name: {package.name}"
) )
def search_for_installed_packages(
self,
specification: PackageSpecification,
) -> list[Package]:
"""
Search for installed packages, when available, that provides the given
specification.
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:
return []
logger.debug(
"Falling back to installed packages to discover metadata for <c2>%s</>",
specification.complete_name,
)
packages = [
package
for package in self._installed.packages
if package.provides(specification)
]
logger.debug(
"Found <c2>%d</> compatible packages for <c2>%s</>",
len(packages),
specification.complete_name,
)
return packages
def search_for( def search_for(
self, self,
dependency: ( dependency: (
...@@ -227,6 +262,9 @@ class Provider: ...@@ -227,6 +262,9 @@ class Provider:
reverse=True, reverse=True,
) )
if not packages:
packages = self.search_for_installed_packages(dependency)
return PackageCollection(dependency, packages) return PackageCollection(dependency, packages)
def search_for_vcs(self, dependency: VCSDependency) -> list[Package]: def search_for_vcs(self, dependency: VCSDependency) -> list[Package]:
...@@ -478,15 +516,29 @@ class Provider: ...@@ -478,15 +516,29 @@ class Provider:
"url", "url",
"git", "git",
}: }:
package = DependencyPackage( try:
package.dependency, package = DependencyPackage(
self._pool.package( package.dependency,
package.name, self._pool.package(
package.version.text, package.name,
extras=list(package.dependency.extras), package.version.text,
repository=package.dependency.source_name, extras=list(package.dependency.extras),
), repository=package.dependency.source_name,
) ),
)
except PackageNotFound as e:
try:
package = next(
DependencyPackage(
package.dependency,
pkg,
)
for pkg in self.search_for_installed_packages(
package.dependency
)
)
except StopIteration:
raise e from e
requires = package.requires requires = package.requires
else: else:
requires = package.requires requires = package.requires
......
...@@ -58,7 +58,9 @@ class Solver: ...@@ -58,7 +58,9 @@ class Solver:
self._io = io self._io = io
if provider is None: if provider is None:
provider = Provider(self._package, self._pool, self._io) provider = Provider(
self._package, self._pool, self._io, installed=installed
)
self._provider = provider self._provider = provider
self._overrides: list[dict[DependencyPackage, dict[str, Dependency]]] = [] self._overrides: list[dict[DependencyPackage, dict[str, Dependency]]] = []
......
...@@ -87,7 +87,12 @@ def solver( ...@@ -87,7 +87,12 @@ def solver(
io: NullIO, io: NullIO,
) -> Solver: ) -> Solver:
return Solver( return Solver(
package, pool, installed, locked, io, provider=Provider(package, pool, io) package,
pool,
installed,
locked,
io,
provider=Provider(package, pool, io, installed=installed),
) )
...@@ -174,6 +179,36 @@ def test_install_non_existing_package_fail( ...@@ -174,6 +179,36 @@ def test_install_non_existing_package_fail(
solver.solve() solver.solve()
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: ProjectPackage): def test_solver_with_deps(solver: Solver, repo: Repository, package: ProjectPackage):
package.add_dependency(Factory.create_dependency("A", "*")) package.add_dependency(Factory.create_dependency("A", "*"))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment