Repository: jazzband/pip-tools

Issue:
index-url option help misleading
Help message describing pip-compile index-url option does not seem compliant with the expected behavior if I refer to #208: the default could be different of PyPI in that case.

Am I right? 


Discussion:
As i can see it works like a charm. 

Here's the list `index_urls`:
https://github.com/jazzband/pip-tools/blob/master/piptools/repositories/pypi.py#L53-L55

Let's assume user did non pass `--index-url`, so first element `pip_options.index_url` would contain a value provided by `pip`. Pip provides a value from `pip.conf` or default `PyPI.simple_url`.

Could you write a test to demonstrate your assumption?
Thanks for your answer. Probably I was not clear enough: I was speaking of the help message which is misleading when there is a custom pip configuration.
```
>pip-compile --help
Usage: pip-compile [OPTIONS] [SRC_FILES]...

  Compiles requirements.txt from requirements.in specs.

Options:
...
  -i, --index-url TEXT            Change index URL (defaults to PyPI)
```



`(defaults to PyPI)`  is hardcoded:
https://github.com/jazzband/pip-tools/blob/master/piptools/scripts/compile.py#L39

In the case where a `pip.ini` or `pip.conf` file is provided to pip (at the root of a virtualenv for instance), this message is wrong.

This message could be: ` (defaults to PyPI except if you specified an 'index-url' field in pip configuration)`, or something like that. But it is a bit long.
A better option would be to dynamically provide the true default coming from pip configuration. I have dug into the code but did not find a simple way to do it. Using pip.index.PackageFinder (as done in PyPIRepository class) should certainly do  the job, but I cannot figure out how to call it prior to all the Click stuff.

Got your point. I'm not sure it's worth it. Anyways, the description could be rephrased.

Resolving patch:
diff --git a/piptools/pip.py b/piptools/pip.py
new file mode 100644
--- /dev/null
+++ b/piptools/pip.py
@@ -0,0 +1,30 @@
+import optparse
+
+from ._compat import Command, cmdoptions
+
+
+class PipCommand(Command):
+    name = 'PipCommand'
+
+
+def get_pip_command():
+    # Use pip's parser for pip.conf management and defaults.
+    # General options (find_links, index_url, extra_index_url, trusted_host,
+    # and pre) are defered to pip.
+    pip_command = PipCommand()
+    pip_command.parser.add_option(cmdoptions.no_binary())
+    pip_command.parser.add_option(cmdoptions.only_binary())
+    index_opts = cmdoptions.make_option_group(
+        cmdoptions.index_group,
+        pip_command.parser,
+    )
+    pip_command.parser.insert_option_group(0, index_opts)
+    pip_command.parser.add_option(optparse.Option('--pre', action='store_true', default=False))
+
+    return pip_command
+
+
+pip_command = get_pip_command()
+
+# Get default values of the pip's options (including options from pip.conf).
+pip_defaults = pip_command.parser.get_default_values()
diff --git a/piptools/scripts/compile.py b/piptools/scripts/compile.py
--- a/piptools/scripts/compile.py
+++ b/piptools/scripts/compile.py
@@ -2,7 +2,6 @@
 from __future__ import (absolute_import, division, print_function,
                         unicode_literals)
 
-import optparse
 import os
 import sys
 import tempfile
@@ -10,13 +9,12 @@
 from .._compat import (
     install_req_from_line,
     parse_requirements,
-    cmdoptions,
-    Command,
 )
 
 from .. import click
 from ..exceptions import PipToolsError
 from ..logging import log
+from ..pip import get_pip_command, pip_defaults
 from ..repositories import LocalRequirementsRepository, PyPIRepository
 from ..resolver import Resolver
 from ..utils import (dedup, is_pinned_requirement, key_from_req, UNSAFE_PACKAGES)
@@ -25,10 +23,6 @@
 DEFAULT_REQUIREMENTS_FILE = 'requirements.in'
 
 
-class PipCommand(Command):
-    name = 'PipCommand'
-
-
 @click.command()
 @click.version_option()
 @click.option('-v', '--verbose', count=True, help="Show more output")
@@ -37,7 +31,7 @@ class PipCommand(Command):
 @click.option('-p', '--pre', is_flag=True, default=None, help="Allow resolving to prereleases (default is not)")
 @click.option('-r', '--rebuild', is_flag=True, help="Clear any caches upfront, rebuild from scratch")
 @click.option('-f', '--find-links', multiple=True, help="Look for archives in this directory or on this HTML page", envvar='PIP_FIND_LINKS')  # noqa
-@click.option('-i', '--index-url', help="Change index URL (defaults to PyPI)", envvar='PIP_INDEX_URL')
+@click.option('-i', '--index-url', help="Change index URL (defaults to {})".format(pip_defaults.index_url), envvar='PIP_INDEX_URL')  # noqa
 @click.option('--extra-index-url', multiple=True, help="Add additional index URL to search", envvar='PIP_EXTRA_INDEX_URL')  # noqa
 @click.option('--cert', help="Path to alternate CA bundle.")
 @click.option('--client-cert', help="Path to SSL client certificate, a single file containing the private key and the certificate in PEM format.")  # noqa
@@ -254,20 +248,3 @@ def cli(verbose, quiet, dry_run, pre, rebuild, find_links, index_url, extra_inde
 
     if dry_run:
         log.warning('Dry-run, so nothing updated.')
-
-
-def get_pip_command():
-    # Use pip's parser for pip.conf management and defaults.
-    # General options (find_links, index_url, extra_index_url, trusted_host,
-    # and pre) are defered to pip.
-    pip_command = PipCommand()
-    pip_command.parser.add_option(cmdoptions.no_binary())
-    pip_command.parser.add_option(cmdoptions.only_binary())
-    index_opts = cmdoptions.make_option_group(
-        cmdoptions.index_group,
-        pip_command.parser,
-    )
-    pip_command.parser.insert_option_group(0, index_opts)
-    pip_command.parser.add_option(optparse.Option('--pre', action='store_true', default=False))
-
-    return pip_command


Test patch:
diff --git a/tests/test_cli_compile.py b/tests/test_cli_compile.py
--- a/tests/test_cli_compile.py
+++ b/tests/test_cli_compile.py
@@ -382,3 +382,19 @@ def test_no_candidates_pre():
 
         assert out.exit_code == 2
         assert 'Tried pre-versions:' in out.output
+
+
+@pytest.mark.usefixtures('pip_conf')
+def test_default_index_url():
+    status, output = invoke([sys.executable, '-m', 'piptools', 'compile', '--help'])
+    output = output.decode('utf-8')
+
+    # Click's subprocess output has \r\r\n line endings on win py27. Fix it.
+    output = output.replace('\r\r', '\r')
+
+    assert status == 0
+    expected = (
+        '  -i, --index-url TEXT            Change index URL (defaults to' + os.linesep +
+        '                                  http://example.com)' + os.linesep
+    )
+    assert expected in output
diff --git a/tests/test_repositories.py b/tests/test_repositories.py
--- a/tests/test_repositories.py
+++ b/tests/test_repositories.py
@@ -4,7 +4,7 @@
 from piptools._compat import PackageFinder, install_req_from_line
 
 from piptools.repositories.pypi import PyPIRepository
-from piptools.scripts.compile import get_pip_command
+from piptools.pip import get_pip_command
 import pytest
 
 
diff --git a/tests/test_repository_local.py b/tests/test_repository_local.py
--- a/tests/test_repository_local.py
+++ b/tests/test_repository_local.py
@@ -1,7 +1,7 @@
-from piptools.scripts.compile import get_pip_command
 from piptools.repositories.local import LocalRequirementsRepository
 from piptools.repositories.pypi import PyPIRepository
 from piptools.utils import name_from_req
+from piptools.pip import get_pip_command
 
 EXPECTED = {
     'sha256:04b133ef629ae2bc05f83d0b079a964494a9cd17914943e690c57209b44aae20',
diff --git a/tests/test_repository_pypi.py b/tests/test_repository_pypi.py
--- a/tests/test_repository_pypi.py
+++ b/tests/test_repository_pypi.py
@@ -1,4 +1,4 @@
-from piptools.scripts.compile import get_pip_command
+from piptools.pip import get_pip_command
 from piptools.repositories.pypi import PyPIRepository
 
 
diff --git a/tests/test_top_level_editable.py b/tests/test_top_level_editable.py
--- a/tests/test_top_level_editable.py
+++ b/tests/test_top_level_editable.py
@@ -2,7 +2,7 @@
 import pytest
 
 from piptools.repositories import PyPIRepository
-from piptools.scripts.compile import get_pip_command
+from piptools.pip import get_pip_command
 
 
 class MockedPyPIRepository(PyPIRepository):