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

Add support for pip>=21.3 #1501

Merged
merged 3 commits into from Oct 12, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 23 additions & 4 deletions piptools/scripts/sync.py
Expand Up @@ -9,7 +9,8 @@
from pip._internal.commands import create_command
from pip._internal.commands.install import InstallCommand
from pip._internal.index.package_finder import PackageFinder
from pip._internal.utils.misc import get_installed_distributions
from pip._internal.metadata import get_environment
from pip._vendor.pkg_resources import Distribution

from .. import sync
from .._compat import IS_CLICK_VER_8_PLUS, parse_requirements
Expand Down Expand Up @@ -152,9 +153,10 @@ def cli(
if python_executable is None
else get_sys_path_for_python_executable(python_executable)
)

installed_dists = get_installed_distributions(
skip=[], user_only=user_only, paths=paths, local_only=python_executable is None
installed_dists = _get_installed_distributions(
user_only=user_only,
local_only=python_executable is None,
paths=paths,
)
to_install, to_uninstall = sync.diff(merged_requirements, installed_dists)

Expand Down Expand Up @@ -268,3 +270,20 @@ def _compose_install_flags(
result.extend(["--client-cert", client_cert])

return result


def _get_installed_distributions(
local_only: bool = True,
user_only: bool = False,
paths: Optional[List[str]] = None,
) -> List[Distribution]:
"""Return a list of installed Distribution objects."""
from pip._internal.metadata.pkg_resources import Distribution as _Dist

env = get_environment(paths)
dists = env.iter_installed_distributions(
local_only=local_only,
user_only=user_only,
skip=[],
)
return [cast(_Dist, dist)._dist for dist in dists]
10 changes: 5 additions & 5 deletions piptools/sync.py
Expand Up @@ -19,7 +19,7 @@
from pip._internal.commands.freeze import DEV_PKGS
from pip._internal.req import InstallRequirement
from pip._internal.utils.compat import stdlib_pkgs
from pip._vendor.packaging.requirements import Requirement
from pip._vendor.pkg_resources import Distribution

from .exceptions import IncompatibleRequirements
from .logging import log
Expand All @@ -44,7 +44,7 @@


def dependency_tree(
installed_keys: Mapping[str, Requirement], root_key: str
installed_keys: Mapping[str, Distribution], root_key: str
) -> Set[str]:
"""
Calculate the dependency tree for the package `root_key` and return
Expand All @@ -55,7 +55,7 @@ def dependency_tree(
`root_key` should be the key to return the dependency tree for.
"""
dependencies = set()
queue: Deque[Requirement] = collections.deque()
queue: Deque[Distribution] = collections.deque()

if root_key in installed_keys:
dep = installed_keys[root_key]
Expand All @@ -80,7 +80,7 @@ def dependency_tree(
return dependencies


def get_dists_to_ignore(installed: Iterable[Requirement]) -> List[str]:
def get_dists_to_ignore(installed: Iterable[Distribution]) -> List[str]:
"""
Returns a collection of package names to ignore when performing pip-sync,
based on the currently installed environment. For example, when pip-tools
Expand Down Expand Up @@ -142,7 +142,7 @@ def diff_key_from_ireq(ireq: InstallRequirement) -> str:

def diff(
compiled_requirements: Iterable[InstallRequirement],
installed_dists: Iterable[Requirement],
installed_dists: Iterable[Distribution],
) -> Tuple[Set[InstallRequirement], Set[str]]:
"""
Calculate which packages should be installed or uninstalled, given a set
Expand Down
7 changes: 5 additions & 2 deletions piptools/utils.py
Expand Up @@ -3,6 +3,7 @@
import json
import os
import shlex
import typing
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know I'm late, but importing typing directly (and later using typing.Union rather than just Union) seems unnecessary.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you 👍🏻

from typing import (
Callable,
Dict,
Expand All @@ -26,7 +27,7 @@
from pip._vendor.packaging.markers import Marker
from pip._vendor.packaging.specifiers import SpecifierSet
from pip._vendor.packaging.version import Version
from pip._vendor.pkg_resources import get_distribution
from pip._vendor.pkg_resources import Distribution, Requirement, get_distribution

from piptools.subprocess_utils import run_python_snippet

Expand Down Expand Up @@ -56,7 +57,9 @@ def key_from_ireq(ireq: InstallRequirement) -> str:
return key_from_req(ireq.req)


def key_from_req(req: InstallRequirement) -> str:
def key_from_req(
req: typing.Union[InstallRequirement, Distribution, Requirement]
) -> str:
"""Get an all-lowercase version of the requirement's name."""
if hasattr(req, "key"):
# from pkg_resources, such as installed dists for pip-sync
Expand Down