Repository: jazzband/pip-tools (python)

Issue:
pip-compile broken with pip 19.0
Describe the issue briefly here.

##### Environment Versions

1. OS Type
darwin
1. Python version: `$ python -V` 
Python 2.7.15
1. pip version:  `$ pip --version`
pip 19.0 from /Users/brandon/src/images/.venv/lib/python2.7/site-packages/pip (python 2.7)
1. pip-tools version: `$ pip-compile --version`
pip-compile, version 3.2.0

##### Steps to replicate

```sh
$ pip-compile --generate-hashes --upgrade --header --index --annotate --output-file $@ $<
Traceback (most recent call last):
  File "/Users/brandon/src/images/.venv/bin/pip-compile", line 10, in <module>
    sys.exit(cli())
  File "/Users/brandon/src/images/.venv/lib/python2.7/site-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/Users/brandon/src/images/.venv/lib/python2.7/site-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/Users/brandon/src/images/.venv/lib/python2.7/site-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/Users/brandon/src/images/.venv/lib/python2.7/site-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/Users/brandon/src/images/.venv/lib/python2.7/site-packages/piptools/scripts/compile.py", line 130, in cli
    repository = PyPIRepository(pip_options, session)
  File "/Users/brandon/src/images/.venv/lib/python2.7/site-packages/piptools/repositories/pypi.py", line 62, in __init__
    process_dependency_links=pip_options.process_dependency_links,
AttributeError: Values instance has no attribute 'process_dependency_links'


Pull request description:
Support pip 19.0
- remove `process_dependency_links` mention (see https://github.com/pypa/pip/pull/6060)
- fix tests
- add pip 19.0 to travis and appveyor
- fix #714 

**Changelog-friendly one-liner**: Support pip 19.0

##### Contributor checklist

- [x] Provided the tests for the changes
- [X] Requested (or received) a review from another contributor
- [X] Gave a clear one-line description in the PR (that the maintainers can add to CHANGELOG.md afterwards).


Patch:
diff --git a/.appveyor.yml b/.appveyor.yml
index 1672ebe..13f7f5c 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -11,6 +11,8 @@ environment:
           PIP: 10.0.1
         - TOXENV: py27-pip18.0
           PIP: 18.0
+        - TOXENV: py27-pip19.0
+          PIP: 19.0
         - TOXENV: py27-pipmaster
           PIP: master
         - TOXENV: py27-piplatest
@@ -25,6 +27,8 @@ environment:
           PIP: 10.0.1
         - TOXENV: py34-pip18.0
           PIP: 18.0
+        - TOXENV: py34-pip19.0
+          PIP: 19.0
         - TOXENV: py34-pipmaster
           PIP: master
         - TOXENV: py34-piplatest
@@ -39,6 +43,8 @@ environment:
           PIP: 10.0.1
         - TOXENV: py35-pip18.0
           PIP: 18.0
+        - TOXENV: py35-pip19.0
+          PIP: 19.0
         - TOXENV: py35-pipmaster
           PIP: master
         - TOXENV: py35-piplatest
@@ -53,6 +59,8 @@ environment:
           PIP: 10.0.1
         - TOXENV: py36-pip18.0
           PIP: 18.0
+        - TOXENV: py36-pip19.0
+          PIP: 19.0
         - TOXENV: py36-pipmaster
           PIP: master
         - TOXENV: py36-piplatest
@@ -67,6 +75,8 @@ environment:
           PIP: 10.0.1
         - TOXENV: py37-pip18.0
           PIP: 18.0
+        - TOXENV: py37-pip19.0
+          PIP: 19.0
         - TOXENV: py37-pipmaster
           PIP: master
         - TOXENV: py37-piplatest
diff --git a/.travis.yml b/.travis.yml
index 91fb392..5571f6e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,6 +16,7 @@ env:
   - PIP=9.0.3
   - PIP=10.0.1
   - PIP=18.0
+  - PIP=19.0
   - PIP=latest
   - PIP=master
 
diff --git a/piptools/_compat/pip_compat.py b/piptools/_compat/pip_compat.py
index 28da51f..187c6ea 100644
--- a/piptools/_compat/pip_compat.py
+++ b/piptools/_compat/pip_compat.py
@@ -27,6 +27,7 @@ RequirementSet = do_import('req.req_set', 'RequirementSet')
 user_cache_dir = do_import('utils.appdirs', 'user_cache_dir')
 FAVORITE_HASH = do_import('utils.hashes', 'FAVORITE_HASH')
 is_file_url = do_import('download', 'is_file_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')
diff --git a/piptools/repositories/pypi.py b/piptools/repositories/pypi.py
index bf69803..7a2bd85 100644
--- a/piptools/repositories/pypi.py
+++ b/piptools/repositories/pypi.py
@@ -7,6 +7,9 @@ import os
 from contextlib import contextmanager
 from shutil import rmtree
 
+import pip
+import pkg_resources
+
 from .._compat import (
     is_file_url,
     url_to_path,
@@ -54,14 +57,19 @@ class PyPIRepository(BaseRepository):
         if pip_options.no_index:
             index_urls = []
 
-        self.finder = PackageFinder(
-            find_links=pip_options.find_links,
-            index_urls=index_urls,
-            trusted_hosts=pip_options.trusted_hosts,
-            allow_all_prereleases=pip_options.pre,
-            process_dependency_links=pip_options.process_dependency_links,
-            session=self.session,
-        )
+        finder_kwargs = {
+            "find_links": pip_options.find_links,
+            "index_urls": index_urls,
+            "trusted_hosts": pip_options.trusted_hosts,
+            "allow_all_prereleases": pip_options.pre,
+            "session": self.session,
+        }
+
+        # pip 19.0 has removed process_dependency_links from the PackageFinder constructor
+        if pkg_resources.parse_version(pip.__version__) < pkg_resources.parse_version('19.0'):
+            finder_kwargs["process_dependency_links"] = pip_options.process_dependency_links
+
+        self.finder = PackageFinder(**finder_kwargs)
 
         # Caches
         # stores project_name => InstallationCandidate mappings for all
diff --git a/tox.ini b/tox.ini
index c41a2bc..8138d21 100644
--- a/tox.ini
+++ b/tox.ini
@@ -14,6 +14,7 @@ deps =
     pip9.0.3: pip==9.0.3
     pip10.0.1: pip==10.0.1
     pip18.0: pip==18.0
+    pip19.0: pip==19.0
     coverage
     mock
     pytest
@@ -25,6 +26,7 @@ setenv =
     pip9.0.3: PIP=9.0.3
     pip10.0.1: PIP=10.0.1
     pip18.0: PIP=18.0
+    pip19.0: PIP==19.0
 install_command= python -m pip install {opts} {packages}
 commands =
     pip --version
@@ -48,5 +50,6 @@ PIP =
     9.0.3: pip9.0.3
     10.0.1: pip10.0.1
     18.0: pip18.0
+    19.0: pip19.0
     latest: piplatest
     master: pipmaster


Test patch:
diff --git a/tests/test_cli.py b/tests/test_cli.py
index ca8c18f..6319a93 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -1,6 +1,5 @@
 import os
 from textwrap import dedent
-from six.moves.urllib.request import pathname2url
 import subprocess
 import sys
 import mock
@@ -9,6 +8,7 @@ from click.testing import CliRunner
 
 import pytest
 
+from piptools._compat.pip_compat import path_to_url
 from piptools.repositories import PyPIRepository
 from piptools.scripts.compile import cli
 from piptools.scripts.sync import cli as sync_cli
@@ -242,7 +242,7 @@ def test_sync_quiet(tmpdir):
 def test_editable_package(tmpdir):
     """ piptools can compile an editable """
     fake_package_dir = os.path.join(os.path.split(__file__)[0], 'test_data', 'small_fake_package')
-    fake_package_dir = 'file:' + pathname2url(fake_package_dir)
+    fake_package_dir = path_to_url(fake_package_dir)
     runner = CliRunner()
     with runner.isolated_filesystem():
         with open('requirements.in', 'w') as req_in:
@@ -278,7 +278,7 @@ def test_locally_available_editable_package_is_not_archived_in_cache_dir(tmpdir)
     cache_dir = tmpdir.mkdir('cache_dir')
 
     fake_package_dir = os.path.join(os.path.split(__file__)[0], 'test_data', 'small_fake_package')
-    fake_package_dir = 'file:' + pathname2url(fake_package_dir)
+    fake_package_dir = path_to_url(fake_package_dir)
 
     with mock.patch('piptools.repositories.pypi.CACHE_DIR', new=str(cache_dir)):
         runner = CliRunner()
@@ -360,7 +360,7 @@ def test_upgrade_packages_version_option(tmpdir):
 def test_generate_hashes_with_editable():
     small_fake_package_dir = os.path.join(
         os.path.split(__file__)[0], 'test_data', 'small_fake_package')
-    small_fake_package_url = 'file:' + pathname2url(small_fake_package_dir)
+    small_fake_package_url = path_to_url(small_fake_package_dir)
     runner = CliRunner()
     with runner.isolated_filesystem():
         with open('requirements.in', 'w') as fp: