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

Upgrade pip to version 20.3.3 #4

Merged
merged 5 commits into from
Dec 19, 2020
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
4 changes: 2 additions & 2 deletions rules/dependencies.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
def pip_rules_dependencies():
_remote_wheel(
name = "pip",
url = "https://files.pythonhosted.org/packages/d8/f3/413bab4ff08e1fc4828dfc59996d721917df8e8583ea85385d51125dceff/pip-19.0.3-py2.py3-none-any.whl",
sha256 = "bd812612bbd8ba84159d9ddc0266b7fbce712fc9bc98c82dee5750546ec8ec64",
url = "https://files.pythonhosted.org/packages/54/eb/4a3642e971f404d69d4f6fa3885559d67562801b99d7592487f1ecc4e017/pip-20.3.3-py2.py3-none-any.whl",
sha256 = "fab098c8a1758295dd9f57413c199f23571e8fde6cc39c22c78c961b4ac6286d",
)

_remote_wheel(
Expand Down
4 changes: 2 additions & 2 deletions src/bin/lock_pip_requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def main():

lock_file = lockfile.load(lock_file_path or '')

requirement_set = requirements.collect_and_condense(
requirement_list = requirements.collect_and_condense(
pip_session,
lock_file,
args.requirements_files,
Expand All @@ -35,7 +35,7 @@ def main():
)

resolved_requirements = resolve.resolve_requirement_set(
requirement_set,
requirement_list,
pip_session,
index_urls,
wheel_directory,
Expand Down
26 changes: 15 additions & 11 deletions src/piprules/pipcompat.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import logging

from pip._internal.exceptions import InvalidWheelFilename
from pip._internal.download import path_to_url, unpack_url, PipSession
from pip._internal.index import PackageFinder
from pip._internal.network.session import PipSession
from pip._internal.utils.urls import path_to_url
from pip._internal.index.package_finder import PackageFinder
from pip._internal.index.collector import LinkCollector
from pip._internal.models.link import Link
from pip._internal.operations.prepare import make_abstract_dist, RequirementPreparer
from pip._internal.req import (
parse_requirements,
InstallRequirement,
RequirementSet,
)
from pip._internal.req.req_tracker import RequirementTracker
from pip._internal.resolve import Resolver
from pip._internal.wheel import Wheel, WheelBuilder
from pip._internal.models.search_scope import SearchScope
from pip._internal.models.selection_prefs import SelectionPreferences
from pip._internal.operations.prepare import make_distribution_for_install_requirement, RequirementPreparer
from pip._internal.req import parse_requirements, InstallRequirement
from pip._internal.req.constructors import install_req_from_req_string, install_req_from_parsed_requirement
from pip._internal.req.req_tracker import get_requirement_tracker
from pip._internal.resolution.legacy.resolver import Resolver
from pip._internal.wheel_builder import build, should_build_for_wheel_command
from pip._internal.models.wheel import Wheel
from pip._internal.cache import WheelCache
from pip._internal.utils.temp_dir import global_tempdir_manager
from pip._vendor.packaging.requirements import Requirement
from pip._vendor.packaging.utils import canonicalize_name

Expand Down
19 changes: 6 additions & 13 deletions src/piprules/requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,24 +72,16 @@ def add_from_lock_file(self, lock_file, packages_to_update=None):
def add_from_requirements_file(self, path, pip_session):
LOG.debug("Adding requirements from file %s to collection", path)

for requirement in pipcompat.parse_requirements(path, session=pip_session):
for parsed_requirement in pipcompat.parse_requirements(path, session=pip_session):
requirement = pipcompat.install_req_from_parsed_requirement(parsed_requirement)
LOG.debug("Adding direct requirement %s", requirement)
requirement.is_direct = True
requirement.rules_pip_is_direct = True
self.add(requirement)

def condense(self):
LOG.debug("Condensing requirement collection into a set")

condensed_set = pipcompat.RequirementSet()

for requirement in self._generate_condensed_requirements():
condensed_set.add_requirement(
requirement,
# This is required for indirect requirements, but isn't really used
parent_req_name=(None if requirement.is_direct else "dummy"),
)

return condensed_set
return [requirement for requirement in self._generate_condensed_requirements()]

def _generate_condensed_requirements(self):
for name, group in self._iterate_grouped_requirements():
Expand Down Expand Up @@ -120,7 +112,8 @@ def _create_locked_requirement(name, extras, version, is_direct):
constraint,
comes_from="lock file",
)
requirement.is_direct = is_direct
requirement.is_direct = True
requirement.rules_pip_is_direct = is_direct
return requirement


Expand Down
145 changes: 58 additions & 87 deletions src/piprules/resolve.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import contextlib
import functools
import logging
import os
import shutil
Expand All @@ -15,13 +16,14 @@ class Error(Exception):
"""Base exception for the resolve module"""


def resolve_requirement_set(requirement_set, pip_session, index_urls, wheel_dir):
def resolve_requirement_set(requirement_list, pip_session, index_urls, wheel_dir):
LOG.info("Resolving dependencies and building wheels")

resolver_factory = ResolverFactory(pip_session, index_urls, wheel_dir)

with resolver_factory.make_resolver() as resolver:
return resolver.resolve(requirement_set)
with pipcompat.global_tempdir_manager():
with resolver_factory.make_resolver() as resolver:
return resolver.resolve(requirement_list)


class ResolverFactory(object):
Expand All @@ -33,65 +35,66 @@ def __init__(self, pip_session, index_urls, wheel_dir):

@contextlib.contextmanager
def make_resolver(self):
with pipcompat.RequirementTracker() as requirement_tracker:
with pipcompat.get_requirement_tracker() as requirement_tracker:
with _WorkDirs(tempfile.mkdtemp()) as work_dirs:
finder = self._make_finder()
preparer = self._make_preparer(requirement_tracker, work_dirs)
preparer = self._make_preparer(requirement_tracker, work_dirs, finder)
pip_resolver = self._make_pip_resolver(finder, preparer)
wheel_builder = self._make_wheel_builder(finder, preparer)

yield Resolver(
self.pip_session,
pip_resolver,
wheel_builder,
work_dirs,
self.wheel_dir,
)

def _make_finder(self):
return pipcompat.PackageFinder(
find_links=[],
index_urls=self.index_urls,
session=self.pip_session,
prefer_binary=True,
return pipcompat.PackageFinder.create(
link_collector=pipcompat.LinkCollector(
session=self.pip_session,
search_scope=pipcompat.SearchScope.create(
find_links=[],
index_urls=self.index_urls,
),
),
selection_prefs=pipcompat.SelectionPreferences(
allow_yanked=False,
prefer_binary=True,
),
)

def _make_preparer(self, requirement_tracker, work_dirs):
def _make_preparer(self, requirement_tracker, work_dirs, finder):
return pipcompat.RequirementPreparer(
build_dir=work_dirs.build,
download_dir=work_dirs.wheel,
src_dir=work_dirs.src,
download_dir=None,
wheel_download_dir=work_dirs.wheel,
build_isolation=True,
req_tracker=requirement_tracker,
session=self.pip_session,
progress_bar="off",
build_isolation=True,
finder=finder,
require_hashes=False,
use_user_site=False,
lazy_wheel=False,
)

def _make_pip_resolver(self, finder, preparer):
return pipcompat.Resolver(
finder=finder,
preparer=preparer,
session=self.pip_session,
ignore_installed=True,
finder=finder,
wheel_cache=None,
make_install_req = functools.partial(
pipcompat.install_req_from_req_string,
isolated=True,
),
use_user_site=False,
ignore_dependencies=False,
ignore_installed=True,
ignore_requires_python=True,
force_reinstall=False,
isolated=True,
upgrade_strategy="to-satisfy-only",
)

def _make_wheel_builder(self, finder, preparer):
return pipcompat.WheelBuilder(
finder,
preparer,
None,
build_options=[],
global_options=[],
no_clean=True,
)


class _WorkDirs(object):

Expand Down Expand Up @@ -128,47 +131,54 @@ def delete_all(self):

class Resolver(object):

def __init__(self, session, pip_resolver, wheel_builder, work_dirs, wheel_dir):
def __init__(self, session, pip_resolver, work_dirs, wheel_dir):
self._session = session
self._pip_resolver = pip_resolver
self._wheel_builder = wheel_builder
self._work_dirs = work_dirs
self._wheel_dir = wheel_dir

def resolve(self, requirement_set):
self._pip_resolver.resolve(requirement_set)
def resolve(self, requirement_list):
requirement_set = self._pip_resolver.resolve(
requirement_list,
check_supported_wheels=True,
)

requirements = requirement_set.requirements.values()

self._build_wheels_if_necessary(requirements)
built_wheels = self._build_wheels_if_necessary(requirements)

return [
self._create_resolved_requirement(requirement)
for requirement in requirements
self._create_resolved_requirement(requirement, False)
for requirement in requirements if requirements not in built_wheels
] + [
self._create_resolved_requirement(requirement, True)
for requirement in built_wheels
]

def _build_wheels_if_necessary(self, requirements):
build_failures = self._wheel_builder.build(
requirements,
session=self._session,
build_successes, build_failures = pipcompat.build(
requirements=[req for req in requirements if pipcompat.should_build_for_wheel_command(req)],
wheel_cache=pipcompat.WheelCache(None, None),
build_options=[],
global_options=[],
)
if build_failures:
raise WheelBuildError(build_failures)
return build_successes

def _create_resolved_requirement(self, requirement):

def _create_resolved_requirement(self, requirement, use_local_wheel_source):
LOG.debug("Creating resolved requirement for %s", requirement.name)

abstract_dist = pipcompat.make_abstract_dist(requirement)
dist = abstract_dist.dist()
abstract_dist = pipcompat.make_distribution_for_install_requirement(requirement)
dist = abstract_dist.get_pkg_resources_distribution()

dependencies = [
pipcompat.canonicalize_name(dep.name)
for dep in dist.requires(requirement.extras)
]
version = dist.version

use_local_wheel_source = not requirement.link.is_wheel

if use_local_wheel_source:
self._set_link_to_local_wheel(requirement)

Expand All @@ -185,34 +195,22 @@ def _create_resolved_requirement(self, requirement):
pipcompat.canonicalize_name(requirement.name),
version,
source,
is_direct=requirement.is_direct,
is_direct=requirement.rules_pip_is_direct,
dependencies=dependencies,
extras=requirement.extras,
)

def _set_link_to_local_wheel(self, requirement):
temp_wheel_path = _find_wheel(self._work_dirs.wheel, requirement.name)
temp_wheel_path = requirement.local_file_path
wheel_path = _copy_file_if_missing(temp_wheel_path, self._wheel_dir)
url = pipcompat.path_to_url(wheel_path)

LOG.debug("Setting source of %s to %s", requirement.name, url)
requirement.link = pipcompat.Link(url, comes_from=wheel_path)

# This is necessary for the make_abstract_dist step, which relies on an
# unpacked wheel that looks like an installed distribution
requirement.ensure_has_source_dir(self._work_dirs.build)
pipcompat.unpack_url(
requirement.link,
requirement.source_dir,
None,
False,
session=self._session,
)

def _compute_sha256_sum(self, requirement):
LOG.debug("Computing sha256 sum for %s", requirement.name)
temp_wheel_path = _find_wheel(self._work_dirs.wheel, requirement.name)
return util.compute_file_hash(temp_wheel_path)
return util.compute_file_hash(requirement.local_file_path)


class WheelBuildError(Error):
Expand All @@ -224,33 +222,6 @@ def __init__(self, failures):
self.failures = failures


def _find_wheel(directory, name):
canon_name = pipcompat.canonicalize_name(name)
for filename in os.listdir(directory):
path = os.path.join(directory, filename)
if os.path.isfile(path):
try:
wheel = pipcompat.Wheel(filename)
except pipcompat.InvalidWheelFilename:
continue
if pipcompat.canonicalize_name(wheel.name) == canon_name:
return path

raise WheelFindError(name)


class WheelFindError(Error):

"""Failed to find a wheel file"""

def __init__(self, name):
super(WheelFindError, self).__init__()
self.name = name

def __str__(self):
return 'Could not find wheel matching name "{}"'.format(self.name)


def _copy_file_if_missing(source_path, directory):
base_name = os.path.basename(source_path)
dest_path = os.path.join(directory, base_name)
Expand Down