New Resolver Error Reporting (case: ward==0.44.1b0 and py2neo==4.3.0)
Closed this issue · 18 comments
Packages ward and py2neo (as reported via the pip research survey)
Resolver will go all the way down to ward 0.28.0b0
(current version is 0.45.0b0
) to resolve dependency conflicts.
With pinned versions, here is the output:
(pip-exp) [nlh@navi personal]$ pip --version
pip 20.1 from /home/nlh/.virtualenvs/pip-exp/lib/python3.7/site-packages/pip (python 3.7)
(pip-exp) [nlh@navi personal]$ pip install ward==0.44.1b0 py2neo==4.3.0 --unstable-feature=resolver
Collecting https://files.pythonhosted.org/packages/af/41/c2d52a226b560618fe3df213a15e3f1ea3da09b8520a439756b619f3157d/py2neo-4.3.0.tar.gz#sha256=a218ccb4b636e3850faa6b74ebad80f00600217172a57f745cf223d38a219222
Using cached py2neo-4.3.0.tar.gz (71 kB)
Collecting https://files.pythonhosted.org/packages/0b/7e/ca368a8d8e288be1352d4e2df35da1e01f8aaffbf526695df71630bcb8a6/neotime-1.7.4.tar.gz#sha256=4e0477ba0f24e004de2fa79a3236de2bd941f20de0b5db8d976c52a86d7363eb (from py2neo==4.3.0)
Using cached neotime-1.7.4.tar.gz (17 kB)
Collecting ward==0.44.1b0
Using cached ward-0.44.1b0-py3-none-any.whl (28 kB)
Collecting https://files.pythonhosted.org/packages/5b/7c/7bc4b5d74fdf890dadf1ca1057e4ce83d2ae51e89e69aa603310d63c9b07/ward-0.44.1b0.tar.gz#sha256=074fca910d0be929f753575b4657d0b94e0e3da45902bce0e96f9db5ca1d16fb
Using cached ward-0.44.1b0.tar.gz (27 kB)
Installing build dependencies ... done
Getting requirements to build wheel ... done
Preparing wheel metadata ... done
ERROR: Could not find a version that satisfies the requirement pygments~=2.3.1 (from py2neo)
ERROR: Could not find a version that satisfies the requirement pygments<3.0.0,>=2.4.2 (from ward)
ERROR: Could not find a version that satisfies the requirement pygments~=2.3.1 (from py2neo)
ERROR: Could not find a version that satisfies the requirement pygments<3.0.0,>=2.4.2 (from ward)
ERROR: No matching distribution found for pygments, pygments, pygments, pygments
Slightly different output with the latest version of the resolver (20.2b1):
>pip install ward==0.44.1b0 py2neo==4.3.0 --unstable-feature=resolver
Collecting ward==0.44.1b0
Downloading ward-0.44.1b0-py3-none-any.whl (28 kB)
Collecting py2neo==4.3.0
Downloading py2neo-4.3.0.tar.gz (71 kB)
|████████████████████████████████| 71 kB 4.8 MB/s
ERROR: Could not find a version that satisfies the requirement pygments<3.0.0,>=2.4.2 (from ward)
ERROR: Could not find a version that satisfies the requirement pygments~=2.3.1 (from py2neo)
ERROR: No matching distribution found for pygments, pygments
What would you like to see in the way of an error that would help diagnose?
(I also tried using -v
, and the output was many pages of detail, that I don't think is too helpful, so I would not recommend -v
in this case!)
(This install is documented on a gist)
Current error message
ERROR: Could not find a version that satisfies the requirement pygments<3.0.0,>=2.4.2 (from ward)
ERROR: Could not find a version that satisfies the requirement pygments~=2.3.1 (from py2neo)
ERROR: No matching distribution found for pygments, pygments
Verbose explanation
NB: this is just for documentation to make sure I understand the situation correctly.
I can't install the combination of ward v0.44.1b0 and py2neo 4.3.0 because:
- ward needs a version of pygments lower than 3.0.0 but greater or equal to 2.4.2, and
- py2neo needs a version of pygments approximately equal to version 2.3.1
Before you read the error message
The main decision we need to make first is - what format the error message should take.
We are proposing 3 parts to an error message - each of these parts are based on established good user-centred design practice for error messages.
Part 1 What is the error
Give explicit indication of what has gone wrong - precise descriptions of exact problems, rather than vague generalities.
Part 2 - what has caused the error
Provide an explanation about what has caused pip to display this error.
Part 3 - possible ways to solve the error
Provide the user with constructive advice on how to fix the problem.
Proposed error message
So, onto our proposed message for this example. I have included the 3 parts as mentioned above.
pip install ward==0.46.0-beta.0 py2neo==4.3.0
(Part 1 What is the error?)
Cannot install ward v0.44.1b0 and py2neo v4.3.0 because these package versions have conflicting dependencies.
(Part 2 - what has caused the error)
The conflict is caused by:
- ward 0.44.1b0 depends on pygments <3.0.0,>=2.4.2 (lower than 3.0.0 but greater or equal to 2.4.2)
- py2neo 4.3.0 depends on pygments ~=2.3.1 (approximately equal to version 2.3.1)
(Part 3 - possible ways to solve the error)
There are a number of possible solutions. You can try:
- removing package versions from your requirements, and letting pip try to resolve the problem for you
- trying a version of ward that depends on pygments v2.3.1. Try
pip-search ward --dep pygments~=2.3.1
- replacing ward or py2neo with a different package altogether
- patching py2neo to use pygments <3.0.0,>=2.4.2
- force installing (Be aware!)
For instructions on how to do these steps visit: https://pypa.io/SomeLink"
To debug this further you can run pip-tree
to see all of your dependencies.
Minor point: ~=
is Compatible version. It's relevant here because there's context that we have to assume the user understands, about how versions are specified.
So to be 100% explicit, you are proposing that the user should see the following:
>pip install ward==0.44.1b0 py2neo==4.3.0 --unstable-feature=resolver
Collecting ward==0.44.1b0
Downloading ward-0.44.1b0-py3-none-any.whl (28 kB)
Collecting py2neo==4.3.0
Downloading py2neo-4.3.0.tar.gz (71 kB)
|████████████████████████████████| 71 kB 4.8 MB/s
ERROR: Cannot install ward v0.44.1b0 and py2neo v4.3.0 because these package versions have conflicting dependencies.
The conflict is caused by:
ward 0.44.1b0 depends on pygments <3.0.0,>=2.4.2 (lower than 3.0.0 but greater or equal to 2.4.2)
py2neo 4.3.0 depends on pygments ~=2.3.1 (approximately equal to version 2.3.1)
There are a number of possible solutions. You can try:
removing package versions from your requirements, and letting pip try to resolve the problem for you
trying a version of ward that depends on pygments v2.3.1. Try pip-search ward --dep pygments~=2.3.1
replacing ward or py2neo with a different package altogether
patching py2neo to use pygments <3.0.0,>=2.4.2
force installing (Be aware!)
For instructions on how to do these steps visit: https://pypa.io/SomeLink"
To debug this further you can run pip-tree to see all of your dependencies.
That seems... rather verbose? It also has a number of practical issues in the "possible solutions" section.
- How do we determine (from the information pip has) that the advice is reasonable? Or is this all just boilerplate that would be produced for every such error?
- The pip-search tool mentioned doesn't exist (as far as I can see). We should stick to things that are actually available 🙂 I get that this is an example, but at some point we need to pin down the precise text, so I'm suggesting we do that now. Same for the link to the docs. And pip-tree.
- Who is the "patching py2neo" advice aimed at? Most users would likely only be able to go as far as "file a bug report against py2neo and wait"...
In terms of implementability, the following issues need to be considered:
- The exact text to use, as noted above.
- There's no library or code we can use to convert a spec into "human readable" form. I'd suggest that adding human-readable versions be a possible future improvement, rather than something we need right now.
- We need to define what precisely would trigger this particular error - at the moment we do exactly the same for every occurrence of
ResolutionImpossible
, so if we want to be more specific, we need to understand what message applies in which case. I'd suggest that by default we have one message for all occurrences, and see if that works.
That seems... rather verbose? It also has a number of practical issues in the "possible solutions" section.
Whats important is the structure of the message - 3 parts:
- what the error is (i.e. what the user has tried to do)
- what has caused the error
- possible ways to solve the error
I understand you and @pradyunsg are reluctant to provide 3., so l'm ok with testing only providing 1 and 2 with users and see the reaction.
How do we determine (from the information pip has) that the advice is reasonable? Or is this all just boilerplate that would be produced for every such error?
If all ResolutionImpossible error are created in the same way, then the error text is as you say boilerplate (better: consistent).
Same for the link to the docs.
The link to docs was discussed with @pradyunsg @nlhkabu as a way to provide the user with a possible ways to solve the error. The thinking was it is easier and quicker to update a pypa documentation link than roll-out a new version of pip.
Who is the "patching py2neo" advice aimed at? Most users would likely only be able to go as far as "file a bug report against py2neo and wait"...
This advice came from @pradyunsg, as a suggestion about how to solve this issue.
You raise a good point tho' - we've not suggested raising a ticket/bug against the packages the user was trying to install.
There's no library or code we can use to convert a spec into "human readable" form. I'd suggest that adding human-readable versions be a possible future improvement, rather than something we need right now.
I don't understand "use to convert a spec into "human readable" form". Can you explain this more? Will this have an impact on the error message?
We need to define what precisely would trigger this particular error - at the moment we do exactly the same for every occurrence of ResolutionImpossible
so if we want to be more specific, we need to understand what message applies in which case.
I'd suggest that by default we have one message for all occurrences, and see if that works.
As I mention above - if all occurences are triggered the same way then yes keep the message consistent. If not, do we know the other ways it's caused?
If not then I agree with, we should make this the message consistent for the moment.
(I'm going to open a ticket for ResolutionImpossible error message, as I've done for new resolver flag. I'll reference this.)
I don't understand "use to convert a spec into "human readable" form". Can you explain this more? Will this have an impact on the error message?
In <3.0.0,>=2.4.2 (lower than 3.0.0 but greater or equal to 2.4.2)
, the text <3.0.0,>=2.4.2
is directly available to pip from the project metadata. The text "(lower than 3.0.0 but greater or equal to 2.4.2)" is a translation of that into a more "friendly" form. But doing that translation would involve writing code for it, and that code doesn't exist yet.
In general, I'd say:
- Writing good code that translates all the possible forms of dependency data (see PEP 440 for how complex that is!) into natural language would be a pretty big exercise.
- I'd much rather see that handled in a library (maybe
packaging
, maybe something standalone) rather than being an implementation detail of pip. It's a classic example of something lots of people might want to do, and consistency of results is important.
So basically, we don't have a means of generating that parenthesised explanatory text at the moment, and it's a lot of work (I'd say at least multiple days, quite possibly weeks). Do you consider it important enough to warrant that amount of work? My problem is that as a developer, I tend to de-prioritise UI issues too much, so I automatically assume that "fix the obscure test cases so the test suite passes 100%" is more important than this. Hence why we need guidance here on where to invest effort...
@pfmoore Is there not a library that handles changing:
<3.0.0,>=2.4.2
into lower than 3.0.0 but greater or equal to 2.4.2
?
There is not such a library as far as I know.
Ok, could we do this using a dict?
e.g.
human_readable_operators= {
"<": "less than",
"<=": "less than or equal to",
...
}
What is is about the project meta data that makes it more complex than this?
I guess? This will need to handle more complex cases, however, such as ==5.*
, ~=21.0
, etc. Here’s a rundown of possible specifiers: https://www.python.org/dev/peps/pep-0440/#version-specifiers
I think that would be very helpful!
Note that this is addressing my concern that "it may be hard to do this", but I still believe it should be handled in packaging
, (or another library) not in pip, where it cannot be reused by others. Not that making a PR against packaging is that much harder than making one against pip...
@uranusjr https://www.python.org/dev/peps/pep-0440/#version-specifiers
Is this the complete list of possibilities?
@nlhkabu , @pfmoore @uranusjr @pradyunsg I think it's OK to close this ticket. Thoughts?