Repository: jazzband/pip-tools

Issue:
Option --pre doesn't work in requirements.in
The option `--pre` set in `requirements.in` doesn't work as expected. Neither `--pre package` or `package==0.0.1 --pre`. If `--pre` passed to the CLI it works like a charm. It seems `PyPIRepository` doesn't respect `PackageFinder.allow_all_prereleases` parameter.

##### Environment Versions

1. OS Type MacOS 10.14.3
2. Python version: 3.7.3
3. pip version:  pip 19.1.1 from /Projects/pip-tools/.venv/lib/python3.7/site-packages/pip (python 3.7)
4. pip-tools version: pip-compile, version 3.7.0

##### Steps to replicate

1. requirements.in:
```
cat << EOF > requirements.in
--pre django
django<2.2rc1 --pre
EOF
```
2. `pip-compile -rqo-`

##### Expected result

```
#
# This file is autogenerated by pip-compile
# To update, run:
#
#    pip-compile --output-file=-
#
django==2.2b1
pytz==2019.1              # via django
sqlparse==0.3.0           # via django
```

##### Actual result

```
#
# This file is autogenerated by pip-compile
# To update, run:
#
#    pip-compile --output-file=-
#
django==2.1.8
pytz==2019.1              # via django
```


##### Works fine with

```
$ pip-compile -rqo- --pre
#
# This file is autogenerated by pip-compile
# To update, run:
#
#    pip-compile --output-file=- --pre
#
django==2.2b1
pytz==2019.1              # via django
sqlparse==0.3.0           # via django
```



Discussion:
@blueyed 

digging in `pip` internals i've found that `--pre` is a global boolean flag. You can't set `--pre` to a specific package, neither in CLI or requirements.txt file, see:

```
$ pip install --pre=django django channels

Usage:
  pip install [options] <requirement specifier> [package-index-options] ...
  pip install [options] -r <requirements file> [package-index-options] ...
  pip install [options] [-e] <vcs project url> ...
  pip install [options] [-e] <local project path> ...
  pip install [options] <archive url/path> ...

--pre option does not take a value
```

So `--pre` can be used only in two ways:
1. As CLI option: `pip install --pre`
2. As file-based option inside `requirements.txt`:
```
$ cat requirements.txt
--pre
django
``` 

Looks like it's not a bug, but in the meantime maybe it's a reason to raise an issue on `pip` side for these points:
- if there is a `--pre django` in `requirements.txt`, `pip` should set `--pre` and install `django`
- if there is a `django --pre` in `requirements.txt`, `pip` should raise "unsupported requirement option"

Cheers!


Resolving patch:
diff --git a/piptools/scripts/compile.py b/piptools/scripts/compile.py
--- a/piptools/scripts/compile.py
+++ b/piptools/scripts/compile.py
@@ -348,7 +348,7 @@ def cli(
         resolver = Resolver(
             constraints,
             repository,
-            prereleases=pre,
+            prereleases=repository.finder.allow_all_prereleases or pre,
             clear_caches=rebuild,
             allow_unsafe=allow_unsafe,
         )


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
@@ -649,22 +649,28 @@ def test_build_isolation_option(MockPyPIRepository, runner, option, expected):
 
 
 @pytest.mark.parametrize(
-    "pre_option, expected_package",
+    "cli_option, infile_option, expected_package",
     [
         # no --pre pip-compile should resolve to the last stable version
-        ([], "small-fake-a==0.2"),
+        (False, False, "small-fake-a==0.2"),
         # pip-compile --pre should resolve to the last pre-released version
-        (["-p"], "small-fake-a==0.3b1"),
+        (True, False, "small-fake-a==0.3b1"),
+        (False, True, "small-fake-a==0.3b1"),
+        (True, True, "small-fake-a==0.3b1"),
     ],
 )
-def test_pre_option(runner, pre_option, expected_package):
+def test_pre_option(runner, cli_option, infile_option, expected_package):
     """
     Tests pip-compile respects --pre option.
     """
     with open("requirements.in", "w") as req_in:
+        if infile_option:
+            req_in.write("--pre\n")
         req_in.write("small-fake-a\n")
 
-    out = runner.invoke(cli, ["-n", "-f", MINIMAL_WHEELS_PATH] + pre_option)
+    out = runner.invoke(
+        cli, ["-n", "-f", MINIMAL_WHEELS_PATH] + (["-p"] if cli_option else [])
+    )
 
     assert out.exit_code == 0, out.output
     assert expected_package in out.output.splitlines(), out.output