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

Backport caching improvements to 1.1 branch #6129

Closed
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
19 changes: 16 additions & 3 deletions poetry/mixology/version_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from poetry.core.packages import ProjectPackage
from poetry.core.semver import Version
from poetry.core.semver import VersionRange
from poetry.packages.dependency_package import DependencyPackage

from .failure import SolveFailure
from .incompatibility import Incompatibility
Expand Down Expand Up @@ -386,6 +387,16 @@ def _get_min(dependency):
except IndexError:
version = None

if dependency.name not in self._use_latest:
# prefer locked version of compatible (not exact same) dependency;
# required in order to not unnecessarily update dependencies with
# extras, e.g. "coverage" vs. "coverage[toml]"
locked = self._get_locked(dependency, allow_similar=True)
if locked is not None:
version = next(
(p for p in packages if p.version == locked.version), None
)

if version is None:
# If there are no versions that satisfy the constraint,
# add an incompatibility that indicates that.
Expand Down Expand Up @@ -458,18 +469,20 @@ def _add_incompatibility(self, incompatibility): # type: (Incompatibility) -> N
incompatibility
)

def _get_locked(self, dependency): # type: (Dependency) -> Union[Package, None]
def _get_locked(
self, dependency, allow_similar: bool = False
): # type: (Dependency, bool) -> Union[DependencyPackage, None]
if dependency.name in self._use_latest:
return

locked = self._locked.get(dependency.name)
if not locked:
return

if not dependency.is_same_package_as(locked):
if not (allow_similar or dependency.is_same_package_as(locked)):
return

return locked
return DependencyPackage(dependency, locked)

def _log(self, text):
self._provider.debug(text, self._solution.attempted_solutions)
6 changes: 5 additions & 1 deletion poetry/packages/package_collection.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
from typing import Union

from poetry.core.packages import Package

from .dependency_package import DependencyPackage


Expand All @@ -13,7 +17,7 @@ def __init__(self, dependency, packages=None):
for package in packages:
self.append(package)

def append(self, package):
def append(self, package): # type: (Union[Package, DependencyPackage]) -> None
if isinstance(package, DependencyPackage):
package = package.package

Expand Down
50 changes: 36 additions & 14 deletions poetry/puzzle/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from typing import Any
from typing import List
from typing import Optional
from typing import cast

from clikit.ui.components import ProgressIndicator

Expand Down Expand Up @@ -95,7 +96,7 @@ def use_environment(self, env): # type: (Env) -> Provider
self._env = original_env
self._python_constraint = original_python_constraint

def search_for(self, dependency): # type: (Dependency) -> List[Package]
def search_for(self, dependency): # type: (Dependency) -> List[DependencyPackage]
"""
Search for the specifications that match the given dependency.

Expand Down Expand Up @@ -128,13 +129,13 @@ def search_for(self, dependency): # type: (Dependency) -> List[Package]
return PackageCollection(dependency, packages)

if dependency.is_vcs():
packages = self.search_for_vcs(dependency)
packages = self.search_for_vcs(cast(VCSDependency, dependency))
elif dependency.is_file():
packages = self.search_for_file(dependency)
packages = self.search_for_file(cast(FileDependency, dependency))
elif dependency.is_directory():
packages = self.search_for_directory(dependency)
packages = self.search_for_directory(cast(DirectoryDependency, dependency))
elif dependency.is_url():
packages = self.search_for_url(dependency)
packages = self.search_for_url(cast(URLDependency, dependency))
else:
packages = self._pool.find_packages(dependency)

Expand All @@ -150,15 +151,33 @@ def search_for(self, dependency): # type: (Dependency) -> List[Package]

return PackageCollection(dependency, packages)

def _get_from_deferred_cache(
self, dependency
): # type (Dependency) -> Optional[Package]
if dependency not in self._deferred_cache:
return None

package = self._deferred_cache[dependency]
dependency._constraint = package.version
dependency._pretty_constraint = package.version.text

if not dependency._source_reference:
dependency._source_reference = package.source_reference
if not dependency._source_resolved_reference:
dependency._source_resolved_reference = package.source_resolved_reference

return package

def search_for_vcs(self, dependency): # type: (VCSDependency) -> List[Package]
"""
Search for the specifications that match the given VCS dependency.

Basically, we clone the repository in a temporary directory
and get the information we need by checking out the specified reference.
"""
if dependency in self._deferred_cache:
return [self._deferred_cache[dependency]]
cached = self._get_from_deferred_cache(dependency)
if cached is not None:
return [cached]

package = self.get_package_from_vcs(
dependency.vcs,
Expand All @@ -180,7 +199,7 @@ def search_for_vcs(self, dependency): # type: (VCSDependency) -> List[Package]
@classmethod
def get_package_from_vcs(
cls, vcs, url, branch=None, tag=None, rev=None, name=None
): # type: (str, str, Optional[str], Optional[str]) -> Package
): # type: (str, str, Optional[str], Optional[str], Optional[str], Optional[str]) -> Package
if vcs != "git":
raise ValueError("Unsupported VCS dependency {}".format(vcs))

Expand Down Expand Up @@ -212,8 +231,9 @@ def get_package_from_vcs(
return package

def search_for_file(self, dependency): # type: (FileDependency) -> List[Package]
if dependency in self._deferred_cache:
dependency, _package = self._deferred_cache[dependency]
cached = self._get_from_deferred_cache(dependency)
if cached is not None:
dependency, _package = cached

package = _package.clone()
else:
Expand Down Expand Up @@ -257,8 +277,9 @@ def get_package_from_file(cls, file_path): # type: (Path) -> Package
def search_for_directory(
self, dependency
): # type: (DirectoryDependency) -> List[Package]
if dependency in self._deferred_cache:
dependency, _package = self._deferred_cache[dependency]
cached = self._get_from_deferred_cache(dependency)
if cached is not None:
dependency, _package = cached

package = _package.clone()
else:
Expand Down Expand Up @@ -297,8 +318,9 @@ def get_package_from_directory(
return package

def search_for_url(self, dependency): # type: (URLDependency) -> List[Package]
if dependency in self._deferred_cache:
return [self._deferred_cache[dependency]]
cached = self._get_from_deferred_cache(dependency)
if cached is not None:
return [cached]

package = self.get_package_from_url(dependency.url)

Expand Down
14 changes: 11 additions & 3 deletions poetry/repositories/base_repository.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
from typing import List
from typing import Optional

from poetry.core.packages.package import Package


class BaseRepository(object):
def __init__(self):
self._packages = []
self._packages = [] # type: List[Package]

@property
def packages(self):
def packages(self): # type: () -> List[Package]
return self._packages

def has_package(self, package):
raise NotImplementedError()

def package(self, name, version, extras=None):
def package(
self, name, version, extras=None
): # type: (str, str, Optional[List[str]]) -> Package
raise NotImplementedError()

def find_packages(self, dependency):
Expand Down
2 changes: 1 addition & 1 deletion poetry/repositories/pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def has_package(self, package):

def package(
self, name, version, extras=None, repository=None
): # type: (str, str, List[str], str) -> Package
): # type: (str, str, Optional[List[str]], Optional[str]) -> Package
if repository is not None:
repository = repository.lower()

Expand Down
8 changes: 7 additions & 1 deletion poetry/repositories/repository.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
from typing import List
from typing import Optional

from poetry.core.packages.package import Package
from poetry.core.semver import VersionConstraint
from poetry.core.semver import VersionRange
from poetry.core.semver import parse_constraint
Expand All @@ -21,7 +25,9 @@ def __init__(self, packages=None, name=None):
def name(self):
return self._name

def package(self, name, version, extras=None):
def package(
self, name, version, extras=None
): # type: (str, str, Optional[List[str]]) -> Package
name = name.lower()

for package in self.packages:
Expand Down