Repository: jazzband/pip-tools (Python)

Issue:
pip-compile fails on unavailable irrelevant constraint
pip-compile tries to find a match for all constraints, event those that are not a requirement and come from a constraint file.

As a result if a constraints file defines a constraint on a package that is unavailable (be it a typo, a private lib on a currently unavailable repository, or a deprecated version no longer available) pip-compile won't work, even for requirements.in that will not need that package.

#### Steps to replicate
requirements.in:
```
-c constraints.txt
```

constraints.txt:
```
invalid-dependency~=0.0
```

#### Expected result

```
#
# This file is autogenerated by pip-compile
# To update, run:
#
#    pip-compile requirements.in
#
```

#### Actual result
```
Could not find a version that matches invalid-dependency~=0.0 (from -c constraints.txt (line 1))
No versions found
```

This should be fixed by #1175 



Discussion:
Hello @clslgrnc,

Thanks for the issue an the fix! Looks like `pip` doesn't resolve constraints too if they are not presented in `requirements.txt`.
@clslgrnc Thanks for this report - I think I've run into this today, maybe you would consider adding the following as a test case? Or could you confirm that your fix in #1175 will solve this issue?

The reason I'm asking is because the `msgpack` constraint is on a "real" package, but the version of `< 0` is unfulfillable, which is slightly different to the example in your report above.

The second reason I'm asking about this is because it might open the door to another way to solve https://github.com/jazzband/pip-tools/issues/333 < I'm currently trying to install `firebase-admin` keeping `msgpack-python` as a dependency and not updating to the renamed `msgpack`.

### Example files

`requirements.in`:

```
-c constraint.txt
pip-tools
```

`constraint.txt`:

```
msgpack < 0
```

### Current behaviour

With `pip-tools==5.2.1` on Python 3.7, `pip-compile -v` fails:

```
                          ROUND 1                           
Current constraints:
  msgpack<0 (from -c constraint.txt (line 1))
  pip-tools (from -r requirements.in (line 2))

Finding the best candidates:
Could not find a version that matches msgpack<0 (from -c constraint.txt (line 1))
Tried: 0.5.0, 0.5.1, 0.5.2, 0.5.3, 0.5.4, 0.5.5, 0.5.6, 0.6.0, 0.6.0, 0.6.1, 0.6.1, 0.6.2, 0.6.2, 1.0.0, 1.0.0
Skipped pre-versions: 1.0.0rc1, 1.0.0rc1
There are incompatible versions in the resolved dependencies:
```

:point_up: That's the end of the output - there are no resolved dependencies listed.

### Expected behaviour

`pip-tools` doesn't need `msgpack`, so we don't care that there isn't a version `< 0`. Compile should pass with the usual output.
@jamescooke have you tried #1175?
@atugushev No I've been lazy and just typed :disappointed: 
It works with #1175: parsing the constraint does not fail and it does not try to resolve `msgpack<0` since it is not refered to by pip-tools.
I am not sure how it could help solve #333 though.
@atugushev I've given #1175 a go and it works well for the example above :raised_hands: - thanks @clslgrnc for your work on this :+1: 

Now using #1175, I can create an impossible constraint against an existing package with `< 0`. This prevents that package ever being included in the compiled requirements - and the fix in #1175 means that `pip-compile` will pass when the banned package is not included in the requirements.

In this case, constraining with `msgpack<0` (as per the example above) means that no compiled requirements can ever include `msgpack`. The newly named `msgpack` causes a conflict with the originally named package `msgpack-python` so until it can be resolved in the project I'm working on, it needs to be prevented from being installed. I think this is a similar issue to what's described here https://github.com/jazzband/pip-tools/issues/333#issuecomment-245785086 with `enum` and `enum34`.

### Example files

`constraints.txt`:

```
msgpack<0
```

`requirements.in`:

```
-c constraints.txt
firebase-admin<4
```

`pip-compile` gives an error:

```
Could not find a version that matches msgpack<0,>=0.5.2 (from -c constraints.txt (line 1))               
Tried: 0.5.0, 0.5.1, 0.5.2, 0.5.3, 0.5.4, 0.5.5, 0.5.6, 0.6.0, 0.6.0, 0.6.1, 0.6.1, 0.6.2, 0.6.2, 1.0.0, 1.0.0
Skipped pre-versions: 1.0.0rc1, 1.0.0rc1                                                                 
There are incompatible versions in the resolved dependencies:                                            
  msgpack<0 (from -c constraints.txt (line 1))                                                           
  msgpack>=0.5.2 (from cachecontrol==0.12.6->firebase-admin==3.2.1->-r requirements.in (line 2)) 
```

This is great because it's what I'm looking for - `msgpack` is banned.

At this stage, if the resolver had increased search functionality then it might find the solution - but I'm not complaining :blush: ... 

We can get compilation to pass by pinning one of the sub-dependencies:

```
-c constraints.txt
firebase-admin<4
cachecontrol<=0.12.4
```

Now (with #1175) this compilation passes and we get a set of requirements for `firebase-admin` which are guaranteed not to include `msgpack`. :raised_hands: 
@jamescooke 

Cool! Thanks for the detailed feedback! 👍 
Interesting use case @jamescooke thanks for the explanation.



Patch:
diff --git a/piptools/resolver.py b/piptools/resolver.py
index dfd14077f..6e347aae5 100644
--- a/piptools/resolver.py
+++ b/piptools/resolver.py
@@ -323,6 +323,10 @@ def get_best_match(self, ireq):
             # NOTE: it's much quicker to immediately return instead of
             # hitting the index server
             best_match = ireq
+        elif ireq.constraint:
+            # NOTE: This is not a requirement (yet) and does not need
+            # to be resolved
+            best_match = ireq
         else:
             best_match = self.repository.find_best_match(
                 ireq, prereleases=self.prereleases


Test patch:
diff --git a/tests/test_resolver.py b/tests/test_resolver.py
index fe70b1587..d725776e4 100644
--- a/tests/test_resolver.py
+++ b/tests/test_resolver.py
@@ -129,6 +129,18 @@
                     "werkzeug==0.10.4 (from flask==0.10.1)",
                 ],
             ),
+            # We shouldn't fail on invalid irrelevant pip constraints
+            # See: GH-1178
+            (
+                ["Flask", ("missing-dependency<1.0", True), ("itsdangerous", True)],
+                [
+                    "flask==0.10.1",
+                    "itsdangerous==0.24",
+                    "markupsafe==0.23 (from jinja2==2.7.3->flask==0.10.1)",
+                    "jinja2==2.7.3 (from flask==0.10.1)",
+                    "werkzeug==0.10.4 (from flask==0.10.1)",
+                ],
+            ),
             # Unsafe dependencies should be filtered
             (
                 ["setuptools==35.0.0", "anyjson==0.3.3"],