Skip to content

Commit

Permalink
Merge pull request #864
Browse files Browse the repository at this point in the history
Add compatibility with the pip master (upcoming pip==19.3)
  • Loading branch information
atugushev authored Sep 19, 2019
2 parents d6d631e + 8b05751 commit 53c0742
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 19 deletions.
8 changes: 8 additions & 0 deletions .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ environment:
PIP: 19.0.3
- TOXENV: py27-pip19.1
PIP: 19.1
- TOXENV: py27-pip19.3
PIP: 19.3
- TOXENV: py27-pipmaster
PIP: master
- TOXENV: py27-piplatest-coverage
Expand All @@ -36,6 +38,8 @@ environment:
PIP: 19.0.3
- TOXENV: py35-pip19.1
PIP: 19.1
- TOXENV: py35-pip19.3
PIP: 19.3
- TOXENV: py35-pipmaster
PIP: master
- TOXENV: py35-piplatest
Expand All @@ -55,6 +59,8 @@ environment:
PIP: 19.0.3
- TOXENV: py36-pip19.1
PIP: 19.1
- TOXENV: py36-pip19.3
PIP: 19.3
- TOXENV: py36-pipmaster
PIP: master
- TOXENV: py36-piplatest
Expand All @@ -74,6 +80,8 @@ environment:
PIP: 19.0.3
- TOXENV: py37-pip19.1-coverage
PIP: 19.1
- TOXENV: py37-pip19.3
PIP: 19.3
- TOXENV: py37-pipmaster-coverage
PIP: master
- TOXENV: py37-piplatest-coverage
Expand Down
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ env:
- PIP=18.0
- PIP=19.0.3
- PIP=19.1
- PIP=19.3
- PIP=latest
- PIP=master

Expand Down
1 change: 1 addition & 0 deletions piptools/_compat/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from .pip_compat import (
DEV_PKGS,
FAVORITE_HASH,
PIP_VERSION,
FormatControl,
InstallationCandidate,
InstallCommand,
Expand Down
15 changes: 12 additions & 3 deletions piptools/_compat/pip_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import pip
from pip._vendor.packaging.version import parse as parse_version

PIP_VERSION = tuple(map(int, parse_version(pip.__version__).base_version.split(".")))


def do_import(module_path, subimport=None, old_path=None):
old_path = old_path or module_path
Expand Down Expand Up @@ -34,13 +36,12 @@ def do_import(module_path, subimport=None, old_path=None):
FAVORITE_HASH = do_import("utils.hashes", "FAVORITE_HASH")
is_file_url = do_import("download", "is_file_url")
is_dir_url = do_import("download", "is_dir_url")
is_vcs_url = do_import("download", "is_vcs_url")
path_to_url = do_import("download", "path_to_url")
url_to_path = do_import("download", "url_to_path")
PackageFinder = do_import("index", "PackageFinder")
FormatControl = do_import("index", "FormatControl")
Wheel = do_import("wheel", "Wheel")
InstallCommand = do_import("commands.install", "InstallCommand")
Wheel = do_import("wheel", "Wheel")
cmdoptions = do_import("cli.cmdoptions", old_path="cmdoptions")
get_installed_distributions = do_import(
"utils.misc", "get_installed_distributions", old_path="utils"
Expand All @@ -53,11 +54,19 @@ def do_import(module_path, subimport=None, old_path=None):
Resolver = do_import("legacy_resolve", "Resolver", old_path="resolve")

# pip 18.1 has refactored InstallRequirement constructors use by pip-tools.
if parse_version(pip.__version__) < parse_version("18.1"):
if PIP_VERSION < (18, 1):
install_req_from_line = InstallRequirement.from_line
install_req_from_editable = InstallRequirement.from_editable
else:
install_req_from_line = do_import("req.constructors", "install_req_from_line")
install_req_from_editable = do_import(
"req.constructors", "install_req_from_editable"
)


def is_vcs_url(link):
if PIP_VERSION < (19, 3):
_is_vcs_url = do_import("download", "is_vcs_url")
return _is_vcs_url(link)

return link.is_vcs
30 changes: 24 additions & 6 deletions piptools/repositories/pypi.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
import hashlib
import os
from contextlib import contextmanager
from functools import partial
from shutil import rmtree

from .._compat import (
FAVORITE_HASH,
InstallCommand,
Link,
PyPI,
RequirementSet,
Expand All @@ -28,7 +28,7 @@
from ..exceptions import NoCandidateFound
from ..logging import log
from ..utils import (
PIP_VERSION,
create_install_command,
fs_str,
is_pinned_requirement,
is_url_requirement,
Expand All @@ -37,6 +37,8 @@
)
from .base import BaseRepository

from piptools._compat.pip_compat import PIP_VERSION

try:
from pip._internal.req.req_tracker import RequirementTracker
except ImportError:
Expand Down Expand Up @@ -71,7 +73,7 @@ def __init__(self, pip_args, build_isolation=False):
# Use pip's parser for pip.conf management and defaults.
# General options (find_links, index_url, extra_index_url, trusted_host,
# and pre) are deferred to pip.
command = InstallCommand()
command = create_install_command()
self.options, _ = command.parse_args(pip_args)

self.session = command._build_session(self.options)
Expand Down Expand Up @@ -149,9 +151,15 @@ def find_best_match(self, ireq, prereleases=None):
elif PIP_VERSION < (19, 2):
evaluator = self.finder.candidate_evaluator
best_candidate = evaluator.get_best_candidate(matching_candidates)
else:
elif PIP_VERSION < (19, 3):
evaluator = self.finder.make_candidate_evaluator(ireq.name)
best_candidate = evaluator.get_best_candidate(matching_candidates)
else:
evaluator = self.finder.make_candidate_evaluator(ireq.name)
best_candidate_result = evaluator.compute_best_candidate(
matching_candidates
)
best_candidate = best_candidate_result.best_candidate

# Turn the candidate into a pinned InstallRequirement
return make_install_requirement(
Expand Down Expand Up @@ -193,10 +201,20 @@ def resolve_reqs(self, download_dir, ireq, wheel_cache):
"ignore_dependencies": False,
"ignore_requires_python": False,
"ignore_installed": True,
"isolated": False,
"wheel_cache": wheel_cache,
"use_user_site": False,
}
make_install_req_kwargs = {"isolated": False, "wheel_cache": wheel_cache}

if PIP_VERSION < (19, 3):
resolver_kwargs.update(**make_install_req_kwargs)
else:
from pip._internal.req.constructors import install_req_from_req_string

make_install_req = partial(
install_req_from_req_string, **make_install_req_kwargs
)
resolver_kwargs["make_install_req"] = make_install_req

resolver = None
preparer = None
with RequirementTracker() as req_tracker:
Expand Down
6 changes: 4 additions & 2 deletions piptools/scripts/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
from click.utils import safecall

from .. import click
from .._compat import InstallCommand, install_req_from_line, parse_requirements
from .._compat import install_req_from_line, parse_requirements
from ..exceptions import PipToolsError
from ..logging import log
from ..repositories import LocalRequirementsRepository, PyPIRepository
from ..resolver import Resolver
from ..utils import (
UNSAFE_PACKAGES,
create_install_command,
dedup,
is_pinned_requirement,
key_from_ireq,
Expand All @@ -26,7 +27,8 @@
DEFAULT_REQUIREMENTS_OUTPUT_FILE = "requirements.txt"

# Get default values of the pip's options (including options from pip.conf).
pip_defaults = InstallCommand().parser.get_default_values()
install_command = create_install_command()
pip_defaults = install_command.parser.get_default_values()


@click.command()
Expand Down
17 changes: 13 additions & 4 deletions piptools/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,13 @@
from collections import OrderedDict
from itertools import chain, groupby

import pip
import six
from click.utils import LazyFile
from pip._vendor.packaging.version import parse as parse_version
from six.moves import shlex_quote

from ._compat import install_req_from_line
from ._compat import PIP_VERSION, InstallCommand, install_req_from_line
from .click import style

PIP_VERSION = tuple(map(int, parse_version(pip.__version__).base_version.split(".")))
UNSAFE_PACKAGES = {"setuptools", "distribute", "pip"}
COMPILE_EXCLUDE_OPTIONS = {
"--dry-run",
Expand Down Expand Up @@ -371,3 +368,15 @@ def get_compile_command(click_ctx):
)

return " ".join(["pip-compile"] + sorted(left_args) + sorted(right_args))


def create_install_command():
"""
Return an instance of InstallCommand.
"""
if PIP_VERSION < (19, 3):
return InstallCommand()

from pip._internal import create_command

return create_command("install")
3 changes: 1 addition & 2 deletions tests/test_cli_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@

from .utils import invoke

from piptools._compat.pip_compat import path_to_url
from piptools._compat.pip_compat import PIP_VERSION, path_to_url
from piptools.repositories import PyPIRepository
from piptools.scripts.compile import cli
from piptools.utils import PIP_VERSION

TEST_DATA_PATH = os.path.join(os.path.split(__file__)[0], "test_data")
MINIMAL_WHEELS_PATH = os.path.join(TEST_DATA_PATH, "minimal_wheels")
Expand Down
2 changes: 1 addition & 1 deletion tests/test_repositories.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from mock import MagicMock, patch

from piptools._compat import PackageFinder, install_req_from_line
from piptools.utils import PIP_VERSION
from piptools._compat.pip_compat import PIP_VERSION


def test_pypirepo_build_dir_is_str(pypi_repository):
Expand Down
9 changes: 9 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from piptools.scripts.compile import cli as compile_cli
from piptools.utils import (
as_tuple,
create_install_command,
dedup,
flat_map,
force_text,
Expand Down Expand Up @@ -324,3 +325,11 @@ def test_get_compile_command_sort_args(tmpdir_cwd):
"--no-annotate --no-emit-trusted-host --no-index "
"requirements.in setup.py"
)


def test_create_install_command():
"""
Test create_install_command returns an instance of InstallCommand.
"""
install_command = create_install_command()
assert install_command.name == "install"
6 changes: 5 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[tox]
envlist =
# NOTE: keep this in sync with the env list in .travis.yml for tox-travis.
py{27,35,36,37,38,py,py3}-pip{8.1.1,9.0.1,9.0.3,10.0.1,18.0,19.0.3,19.1,latest,master}-coverage
py{27,35,36,37,38,py,py3}-pip{8.1.1,9.0.1,9.0.3,10.0.1,18.0,19.0.3,19.1,19.3,latest,master}-coverage
checkqa
readme
skip_missing_interpreters = True
Expand All @@ -17,6 +17,8 @@ deps =
pip18.0: pip==18.0
pip19.0.3: pip==19.0.3
pip19.1: pip==19.1
# TODO change it to pip==19.3 after pip being released
pip19.3: -e git+https://github.com/pypa/pip.git@master#egg=pip
mock
pytest!=5.1.2
coverage: pytest-cov
Expand All @@ -30,6 +32,7 @@ setenv =
pip18.0: PIP=18.0
pip19.0.3: PIP==19.0.3
pip19.1: PIP==19.1
pip19.3: PIP==19.3

coverage: PYTEST_ADDOPTS=--strict --doctest-modules --cov --cov-report=term-missing {env:PYTEST_ADDOPTS:}
commands_pre =
Expand All @@ -56,5 +59,6 @@ PIP =
18.0: pip18.0
19.0.3: pip19.0.3
19.1: pip19.1
19.3: pip19.3
latest: piplatest
master: pipmaster

0 comments on commit 53c0742

Please sign in to comment.