Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Idea - New Resolver/Install Option - One at a Time #12160

Closed
1 task done
notatallshaw opened this issue Jul 17, 2023 · 11 comments
Closed
1 task done

Idea - New Resolver/Install Option - One at a Time #12160

notatallshaw opened this issue Jul 17, 2023 · 11 comments
Labels
type: feature request Request for a new feature

Comments

@notatallshaw
Copy link
Member

notatallshaw commented Jul 17, 2023

What's the problem this feature will solve?

The legacy resolver is coming on being deprecated for three years now, however it seems like there is still significant trepidation in removing it from Pip, the idea would be to offer a new resolver/install option that covered any use cases left but relied on the new resolver code.

Describe the solution you'd like

The resolver/installer option would do the following:

  1. Collect top level user requirements
  2. Take the first user requirement and install it as though it was the only requirement specified, using the top level user requirements as a set of constraints
  3. Take the second user requirement and install it as though it was the only requirement specified, using the top level user requirements as a set of constraints, and as though this and the previous step were two separate install commands
  4. Continue like this until all user requirements have been completed

This would allow conflicting packages to be installed from transitive dependencies, but still force the top level user requirements to be consistent and not broken.

This feature would be documented as:

  • not recommended
  • can install inconsistent environments
  • can fail part way though leaving some packages installed but others not installed

Alternative Solutions

  • Keep legacy resolver forever
  • Remove legacy resolver with no alternative, break some users workflows

Additional context

IMO most users who still have the legacy resolver option enabled probably don't need it and just have it left over for when the current resolver was turned on by default and caused lots of problems.

But I do know two projects that are reliant on the legacy resolver (at least last I checked):

In both cases my understanding is the scale of requirements they have makes it impossible to come to a clean resolution on all packages and ultimately they need to install packages which list themselves as having incompatible requirements (even if in practice there is a functionally working solution). There may be other reasons as well.

Code of Conduct

@notatallshaw notatallshaw added S: needs triage Issues/PRs that need to be triaged type: feature request Request for a new feature labels Jul 17, 2023
@notatallshaw
Copy link
Member Author

notatallshaw commented Jul 18, 2023

FYI, after a bit of sleuthing through issues I found home-assistant were able to move off the legacy resolver earlier this year: home-assistant/core#92124

@uranusjr
Copy link
Member

This needs to also have a strategy for extras. (i.e. what does “top level” mean if the user specifies a requirement with extras?) This is, uncoincidentally, the part where the legacy resolver becomes nonsensical.

If we do this, of course.

@notatallshaw
Copy link
Member Author

notatallshaw commented Jul 18, 2023

IIMO strip the extras part and document that the extras will be installed but other requirements will not be constrained by them.

It's already the case that you can't guarantee an extra across a range of versions if some version doesn't have that extra, this would just be another edge cases.

@notatallshaw
Copy link
Member Author

Also this presupposes the use case is in high enough demand to make this worthwhile. Which I'm unsure, but I'd been thinking of this approach for last few weeks and thought it worth suggesting.

@pfmoore
Copy link
Member

pfmoore commented Jul 18, 2023

-1. This can be implemented by the user simply issuing multiple pip commands. It should be possible to write a proof of concept as a wrapper script which invokes pip, and this script could be offered as the solution for people who have not moved off the legacy resolver.

The inconvenience of a wrapper would also act as an incentive to move to proper use of the new resolver.

(To be explicit, I am not suggesting we use this to avoid fixing genuine problems blocking adoption).

@RonnyPfannschmidt
Copy link
Contributor

As far as I can tell, the feature request boils down to wanting to install mutually exclusive things and the requested approach boils down to let's prevent the resolver from doing its job so we can pretend things are fine

@pradyunsg pradyunsg removed the S: needs triage Issues/PRs that need to be triaged label Jul 18, 2023
@pradyunsg
Copy link
Member

can install inconsistent environments

If we want users doing this, then I'd rather that we look at #8076.

@notatallshaw
Copy link
Member Author

notatallshaw commented Jul 18, 2023

This can be implemented by the user simply issuing multiple pip commands. It should be possible to write a proof of concept as a wrapper script which invokes pip,

I think the non trivial part of this is reimplementing all the logic Pip has of collecting the requirements and keep it in sync with Pip other than directly using Pip's code.

If Pip provided a way to output all the requirements it's detected then it would albe more manageable to do this.

The inconvenience of a wrapper would also act as an incentive to move to proper use of the new resolver.

If the issue was just inconvenience I would agree, but as you can see from the home-assistant, this is a real world example where they had to sacrifice features to move off the legacy resolver.

the feature request boils down to wanting to install mutually exclusive t

Packages that say they are mutually exclusive but functionally are not. This is a highly requested feature already, at the moment users will use the legacy resolver or pip-compile or their own implementation to achieve this.

boils down to let's prevent the resolver from doing its job so we can pretend things are fine

This was an idea on how to keep some of the benefits of the new resolver for the use case of users still using the legacy resolver. At the moment anyone still using the legacy resolver isn't getting any of the benefits of the current resolver.

If we want users doing this, then I'd rather that we look at #8076.

Fair enough, my idea around this was that it should be simpler to implement. There's no new spec required on how to pass in information to Pip, there's no new information that needs to be passed to resolvelib, all the behavior is largely existing in Pip already.

But of course only if it was positively received as a way to transition off the legacy resolver.

@pfmoore
Copy link
Member

pfmoore commented Jul 18, 2023

If Pip provided a way to output all the requirements it's detected then it would albe more manageable to do this.

Maybe I've misunderstood you. Aren't we just talking about what's on the command line? If it is more than that, then why not propose a pip subcommand to just determine and list the inputs to the resolver? I'm not at all against adding features that make it easier to use pip in a scripted wrapper. Although I am disappointed at how resistant people are when told that their pet pip feature request can be implemented as a simple wrapper script. That doesn't persuade me to stop advocating that approach, though.

If the issue was just inconvenience I would agree, but as you can see from the home-assistant, this is a real world example where they had to sacrifice features to move off the legacy resolver.

I'll admit I didn't look at that case in any detail. I thought you'd said they had fixed the issue that kept them on the old resolver?

Packages that say they are mutually exclusive but functionally are not. This is a highly requested feature already, at the moment users will use the legacy resolver or pip-compile or their own implementation to achieve this.

I'm sorry for repeating myself, but this is explicitly going against the stated constraints of those packages. I'm not sure that's a use case pip1 wants to support. It can be solved by getting the packages to change their dependency metadata, and if they aren't willing to do that, then isn't that equivalent to them saying they aren't willing to support your use case? And in that situation, while I'm fine with pip not stopping you from doing what you want, I am uncomfortable about helping you do something that's explicitly been rejected by the package author.

That's ignoring the "I can't wait for the package to release a fix" situation, which I know is real. But that's about offering temporary workarounds, and I don't think that "install things bit by bit, exploiting the fact that pip doesn't refuse to install if the environment is consistent" is an unreasonable option here. Yes, it's painful. But if it's too easy, the evidence is that people just ignore the underlying problems (that's why they still use the legacy resolver, after all, because it's an easy fix).

But of course only if it was positively received as a way to transition off the legacy resolver.

My biggest worry is that it's not a transition, at least no more so than --use-deprecated=legacy-resolver. People will enable it, and then just carry on. And when we remove it, we're back in exactly the same situation. And if we don't remove it, we're explicitly supporting the creation of broken environments forever, and that's one of the key things the new resolver was supposed to fix.

For me, a "transition" has to be good enough to work for now, but either painful enough to make people work to implement a better solution, or visibly temporary enough to remind people they still had a problem to address. We tried the "gentle reminder" approach, and that encouraged most of our users to switch. Now it's time to get (at least somewhat) stricter.

Footnotes

  1. It's not a use case I want to support, but I don't think there's consensus among the pip maintainers on this yet.

@notatallshaw
Copy link
Member Author

notatallshaw commented Jul 19, 2023

Aren't we just talking about what's on the command line?

I did not just mean via the command line, I meant the same requirements that Pip collects to do an initial pass to resolve on. I'm not 100% sure I know all the places Pip could possibly get these from, but it's at least cli and requirements files (and perhaps local package installs? And maybe pyproject.toml files in the future?)

I know in the case of the projects I linked we are talking hundreds to thousands of top level requirements, so I don't even think they could fit on the CLI.

If it is more than that, then why not propose a pip subcommand to just determine and list the inputs to the resolver?

Because I hadn't thought of that when I first wrote this! I will definitely follow up with that idea, as yes, then making a script like this will be much more practical.

I'll admit I didn't look at that case in any detail. I thought you'd said they had fixed the issue that kept them on the old resolver?

They fixed it by removing packages, this meant there were three smart home ecosystems they stopped supporting.

While those packages was no longer being actively supported the code itself still worked, and people still have smart devices in those ecosystems. The issue as I understand it is the requirements for those packages were pinned too specifically, not because the authors originally intended them to only work against an unmoving set of requirements forever but because the authors didn't foresee the future of the Pip resolver nor that they would stop working on the project.

I'm sorry for repeating myself, but this is explicitly going against the stated constraints of those packages. I'm not sure that's a use case pip1 wants to support. It can be solved by getting the packages to change their dependency metadata, and if they aren't willing to do that, then isn't that equivalent to them saying they aren't willing to support your use case? And in that situation, while I'm fine with pip not stopping you from doing what you want, I am uncomfortable about helping you do something that's explicitly been rejected by the package author.

I understand your view point, but I think it too strongly takes the position that users of open source software must have explicit support from every package they use.

Taking this real world example, home assistant is not asking for support from the package authors, they have their own test suite, and the package authors are not denying any support explicitly. The package authors have incorrectly understood how to specify package requirements (something that can happen to the best of us) and now the authors are no longer capable of updating the requirements for whatever reason.

My biggest worry is that it's not a transition, at least no more so than --use-deprecated=legacy-resolver.

Ah the benefit I was considering was not the right or wrong way to use Pip or install packages, but to remove the legacy resolver code from Pip and use the new resolver code in all places instead. As this release has shown the legacy resolver can be broken by changes seemingly unrelated to it and therefore makes Pip more fragile overall.

And the main reason I suggested it instead of revisiting #8076 was that I think it would be much simpler to implement, certainly that could be a much more complete approach to this problem.

The other way to do this is of course just to remove the legacy resolver without any workaround to use Pip directly and tell users who still have this use case to develop their own resolution system, either by wrapping Pip or some other Python package installer, or building their own.

@notatallshaw
Copy link
Member Author

notatallshaw commented Jan 30, 2024

Closing due to expressed non-interest from Pip maintainers.

I am of the opinion that Pip maintainers have spent probably spent more effort discussing with users on why Pip shouldn't have an a convenient workflow to install overriding requirements at install time than would have cost to accept a PR and support it's consequences.

Especially given the current situation isn't that much better, because there are no guarantees from Pip that two seperate installs won't create a broken environment.

But I don't have to maintain Pip, I would be far more happy to let users shoot themselves in the foot with big warning signs saying "We don't take responsability for shooting yourself in the foot, but if you really need to do that to get your job done here's the weapon".

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 29, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
type: feature request Request for a new feature
Projects
None yet
Development

No branches or pull requests

5 participants