Repository: jazzband/pip-tools

Issue:
pip-compile generates setup.txt by given explicitly setup.py in a source file
There is a possible wrong behavior on a command `pip-compile setup.py`, because it generates `setup.txt` file instead of `requirements.txt`.

##### Environment Versions

1. OS Type: Any (tested on MacOSX)
1. Python version: 3.7.x
1. pip version:  19.1
1. pip-tools version: 3.3.2

##### Steps to replicate

1. Prepare a `setup.py` file:
```
cat << EOF > setup.py
from setuptools import setup
setup(install_requires=[])
EOF
```
2. Run: `pip-compile setup.py`

##### Expected result

```
#
# This file is autogenerated by pip-compile
# To update, run:
#
#    pip-compile --output-file requirements.txt setup.py
#
```

##### Actual result

```
#
# This file is autogenerated by pip-compile
# To update, run:
#
#    pip-compile --output-file setup.txt setup.py
#
```



Discussion:

Resolving patch:
diff --git a/piptools/scripts/compile.py b/piptools/scripts/compile.py
--- a/piptools/scripts/compile.py
+++ b/piptools/scripts/compile.py
@@ -21,6 +21,7 @@
 from ..writer import OutputWriter
 
 DEFAULT_REQUIREMENTS_FILE = 'requirements.in'
+DEFAULT_REQUIREMENTS_OUTPUT_FILE = 'requirements.txt'
 
 
 @click.command()
@@ -72,15 +73,14 @@ def cli(verbose, quiet, dry_run, pre, rebuild, find_links, index_url, extra_inde
             src_files = (DEFAULT_REQUIREMENTS_FILE,)
         elif os.path.exists('setup.py'):
             src_files = ('setup.py',)
-            if not output_file:
-                output_file = 'requirements.txt'
         else:
             raise click.BadParameter(("If you do not specify an input file, "
                                       "the default is {} or setup.py").format(DEFAULT_REQUIREMENTS_FILE))
 
-    if len(src_files) == 1 and src_files[0] == '-':
-        if not output_file:
-            raise click.BadParameter('--output-file is required if input is from stdin')
+    if src_files == ('-',) and not output_file:
+        raise click.BadParameter('--output-file is required if input is from stdin')
+    elif src_files == ('setup.py',):
+        output_file = DEFAULT_REQUIREMENTS_OUTPUT_FILE
 
     if len(src_files) > 1 and not output_file:
         raise click.BadParameter('--output-file is required if two or more input files are given.')


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
@@ -77,8 +77,11 @@ def test_command_line_overrides_pip_conf(pip_conf):
         assert 'Using indexes:\n  http://override.com' in out.output
 
 
-def test_command_line_setuptools_read(pip_conf):
-
+@pytest.mark.parametrize('cli_args', [
+    [],
+    ['setup.py'],
+])
+def test_command_line_setuptools_read(pip_conf, cli_args):
     runner = CliRunner()
     with runner.isolated_filesystem():
         package = open('setup.py', 'w')
@@ -87,10 +90,11 @@ def test_command_line_setuptools_read(pip_conf):
             setup(install_requires=[])
         """))
         package.close()
-        out = runner.invoke(cli)
+        out = runner.invoke(cli, cli_args)
 
         # check that pip-compile generated a configuration
         assert 'This file is autogenerated by pip-compile' in out.output
+        assert os.path.exists('requirements.txt')
 
 
 def test_find_links_option(pip_conf):
@@ -398,3 +402,15 @@ def test_default_index_url():
         '                                  http://example.com)' + os.linesep
     )
     assert expected in output
+
+
+def test_stdin_without_output_file():
+    """
+    The --output-file option is required for STDIN.
+    """
+    runner = CliRunner()
+    with runner.isolated_filesystem():
+        out = runner.invoke(cli, ['-n', '-'])
+
+        assert out.exit_code == 2
+        assert '--output-file is required if input is from stdin' in out.output