Skip to content

Commit

Permalink
Deprecate --index/--no-index in pip-compile (#1130)
Browse files Browse the repository at this point in the history
  • Loading branch information
atugushev authored May 27, 2020
1 parent 008865a commit 304d7ad
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 19 deletions.
9 changes: 9 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,15 @@ Other useful tools
.. _requirements.txt.vim: https://github.com/raimon49/requirements.txt.vim
.. _Python extension for VS Code: https://marketplace.visualstudio.com/items?itemName=ms-python.python


Deprecations
============

This section lists ``pip-tools`` features that are currently deprecated.

- ``--index/--no-index`` command-line options, use instead
``--emit-index-url/--no-emit-index-url`` (since 5.2.0).

Versions and compatibility
==========================

Expand Down
49 changes: 46 additions & 3 deletions piptools/scripts/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import shlex
import sys
import tempfile
import warnings

from click import Command
from click.utils import safecall
from pip._internal.commands import create_command
from pip._internal.req.constructors import install_req_from_line
Expand Down Expand Up @@ -36,7 +38,28 @@ def _get_default_option(option_name):
return getattr(default_values, option_name)


@click.command()
class BaseCommand(Command):
_os_args = None

def parse_args(self, ctx, args):
"""
Override base `parse_args` to store the argument part of `sys.argv`.
"""
self._os_args = set(args)
return super(BaseCommand, self).parse_args(ctx, args)

def has_arg(self, arg_name):
"""
Detect whether a given arg name (including negative counterparts
to the arg, e.g. --no-arg) is present in the argument part of `sys.argv`.
"""
command_options = {option.name: option for option in self.params}
option = command_options[arg_name]
args = set(option.opts + option.secondary_opts)
return bool(self._os_args & args)


@click.command(cls=BaseCommand)
@click.version_option()
@click.pass_context
@click.option("-v", "--verbose", count=True, help="Show more output")
Expand Down Expand Up @@ -104,7 +127,7 @@ def _get_default_option(option_name):
"--index/--no-index",
is_flag=True,
default=True,
help="Add index URL to generated file",
help="DEPRECATED: Add index URL to generated file",
)
@click.option(
"--emit-trusted-host/--no-emit-trusted-host",
Expand Down Expand Up @@ -188,6 +211,12 @@ def _get_default_option(option_name):
type=click.Path(file_okay=False, writable=True),
)
@click.option("--pip-args", help="Arguments to pass directly to the pip command.")
@click.option(
"--emit-index-url/--no-emit-index-url",
is_flag=True,
default=True,
help="Add index URL to generated file",
)
def cli(
ctx,
verbose,
Expand Down Expand Up @@ -216,6 +245,7 @@ def cli(
emit_find_links,
cache_dir,
pip_args,
emit_index_url,
):
"""Compiles requirements.txt from requirements.in specs."""
log.verbosity = verbose - quiet
Expand Down Expand Up @@ -255,6 +285,19 @@ def cli(
# Close the file at the end of the context execution
ctx.call_on_close(safecall(output_file.close_intelligently))

if cli.has_arg("index") and cli.has_arg("emit_index_url"):
raise click.BadParameter(
"--index/--no-index and --emit-index-url/--no-emit-index-url "
"are mutually exclusive."
)
elif cli.has_arg("index"):
warnings.warn(
"--index and --no-index are deprecated and will be removed "
"in future versions. Use --emit-index-url/--no-emit-index-url instead.",
category=FutureWarning,
)
emit_index_url = index

###
# Setup
###
Expand Down Expand Up @@ -419,7 +462,7 @@ def cli(
click_ctx=ctx,
dry_run=dry_run,
emit_header=header,
emit_index=index,
emit_index_url=emit_index_url,
emit_trusted_host=emit_trusted_host,
annotate=annotate,
generate_hashes=generate_hashes,
Expand Down
6 changes: 3 additions & 3 deletions piptools/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def __init__(
click_ctx,
dry_run,
emit_header,
emit_index,
emit_index_url,
emit_trusted_host,
annotate,
generate_hashes,
Expand All @@ -73,7 +73,7 @@ def __init__(
self.click_ctx = click_ctx
self.dry_run = dry_run
self.emit_header = emit_header
self.emit_index = emit_index
self.emit_index_url = emit_index_url
self.emit_trusted_host = emit_trusted_host
self.annotate = annotate
self.generate_hashes = generate_hashes
Expand Down Expand Up @@ -101,7 +101,7 @@ def write_header(self):
yield comment("#")

def write_index_options(self):
if self.emit_index:
if self.emit_index_url:
for index, index_url in enumerate(dedup(self.index_urls)):
if index_url.rstrip("/") == self.default_index_url:
continue
Expand Down
61 changes: 53 additions & 8 deletions tests/test_cli_compile.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import itertools
import os
import subprocess
import sys
Expand Down Expand Up @@ -176,20 +177,64 @@ def test_trusted_host(pip_conf, runner):
assert "--trusted-host example.com\n" "--trusted-host example2.com\n" in out.stderr


def test_trusted_host_no_emit(pip_conf, runner):
@pytest.mark.parametrize(
"options",
(
pytest.param(
["--trusted-host", "example.com", "--no-emit-trusted-host"],
id="trusted host",
),
pytest.param(
["--find-links", "wheels", "--no-emit-find-links"], id="find links"
),
pytest.param(
["--index-url", "https://index-url", "--no-emit-index-url"], id="index url"
),
),
)
def test_all_no_emit_options(runner, options):
with open("requirements.in", "w"):
pass
out = runner.invoke(cli, ["--no-header"] + options)
assert out.stderr.strip().splitlines() == []


@pytest.mark.parametrize(
("option", "expected_output"),
(
pytest.param("--index", ["--index-url https://index-url"], id="index url"),
pytest.param("--no-index", [], id="no index"),
),
)
def test_index_option(runner, option, expected_output):
with open("requirements.in", "w"):
pass
out = runner.invoke(
cli, ["-v", "--trusted-host", "example.com", "--no-emit-trusted-host"]
)
assert "--trusted-host example.com" not in out.stderr

with pytest.warns(FutureWarning, match="--index and --no-index are deprecated"):
out = runner.invoke(
cli, ["--no-header", "--index-url", "https://index-url", option]
)

assert out.stderr.strip().splitlines() == expected_output

def test_find_links_no_emit(pip_conf, runner):

@pytest.mark.parametrize(
"options",
itertools.product(
("--index", "--no-index"), ("--emit-index-url", "--no-emit-index-url")
),
)
def test_mutual_exclusive_index_options(runner, options):
with open("requirements.in", "w"):
pass
out = runner.invoke(cli, ["-v", "--no-emit-find-links"])
assert "--find-links" not in out.stderr

out = runner.invoke(cli, options)

assert out.exit_code == 2
assert (
"--index/--no-index and --emit-index-url/--no-emit-index-url "
"are mutually exclusive"
) in out.stderr


@pytest.mark.network
Expand Down
6 changes: 4 additions & 2 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,12 +247,14 @@ def test_force_text(value, expected_text):
(["--allow-unsafe"], "pip-compile --allow-unsafe"),
# Check negative flags
(["--no-index"], "pip-compile --no-index"),
(["--no-emit-index-url"], "pip-compile --no-emit-index-url"),
(["--no-emit-trusted-host"], "pip-compile --no-emit-trusted-host"),
(["--no-annotate"], "pip-compile --no-annotate"),
# Check that default values will be removed from the command
(["--emit-trusted-host"], "pip-compile"),
(["--annotate"], "pip-compile"),
(["--index"], "pip-compile"),
(["--emit-index-url"], "pip-compile"),
(["--max-rounds=10"], "pip-compile"),
(["--build-isolation"], "pip-compile"),
# Check options with multiple values
Expand Down Expand Up @@ -337,7 +339,7 @@ def test_get_compile_command_sort_args(tmpdir_cwd):
pass

args = [
"--no-index",
"--no-emit-index-url",
"--no-emit-trusted-host",
"--no-annotate",
"setup.py",
Expand All @@ -350,6 +352,6 @@ def test_get_compile_command_sort_args(tmpdir_cwd):
with compile_cli.make_context("pip-compile", args) as ctx:
assert get_compile_command(ctx) == (
"pip-compile --find-links=bar --find-links=foo "
"--no-annotate --no-emit-trusted-host --no-index "
"--no-annotate --no-emit-index-url --no-emit-trusted-host "
"requirements.in setup.py"
)
7 changes: 4 additions & 3 deletions tests/test_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def writer(tmpdir_cwd):
click_ctx=ctx,
dry_run=True,
emit_header=True,
emit_index=True,
emit_index_url=True,
emit_trusted_host=True,
annotate=True,
generate_hashes=False,
Expand Down Expand Up @@ -318,9 +318,10 @@ def test_write_index_options(writer, index_urls, expected_lines):

def test_write_index_options_no_emit_index(writer):
"""
There should not be --index-url/--extra-index-url options if emit_index is False.
There should not be --index-url/--extra-index-url options
if emit_index_url is False.
"""
writer.emit_index = False
writer.emit_index_url = False
with pytest.raises(StopIteration):
next(writer.write_index_options())

Expand Down

0 comments on commit 304d7ad

Please sign in to comment.