-
Notifications
You must be signed in to change notification settings - Fork 3k
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
added upgrade-all command #10491
base: main
Are you sure you want to change the base?
added upgrade-all command #10491
Conversation
I just have a question: Is it |
@DiddiLeija I had an error in my commit message indeed, thx for pointing this out. It is |
This probably needs more comprehensive documentation. In particular "does exactly what this Unix one-liner does" is not going to be helpful for a lot of people (Windows users, people unused to command line tools, etc). In fact, I am familiar with command line tools, and I know that xargs combines arguments "up to some system defined limit" - so it's not necessarily equivalent to upgrading everything in one invocation (some people have environments with really huge numbers of packages installed...) I'd rather see the docs explain the behaviour clearly without assuming a background in CLI tools. Regarding tests, start with some basic ones, like installing an old version of one package, then checking that upgrade-all upgrades it. Then try 2 packages A 1.0 and B 1.0, where A 2.0 and B 2.0 are on the index, and A (both versions) depends on B 1.0, check that upgrade-all upgrades A but not B. Do a few of these "check that the things you'd expect to work, do" tests. Then add some tests for nasty things that might happen to make sure that the code doesn't break. For example, you have A 1.0 and B 1.0 installed. On the index, though, there's no B 1.0 (let's say it was installed from a local directory). Does upgrade-all correctly leave B unchanged? What if the installed packages fail IMO this is a pretty complex feature, and making sure we have good test coverage of the behaviour will be very important. TBH, I'm not actually sure anyone has even thought about a lot of questions like this, generally people say "we want upgrade-all" thinking only of the very basic case, and they leave it to whoever develops the feature to catch all the weird edge cases 🙁 |
I'm confused about the difference between this and #10040. Can you start with an overview of what the approach is here, how it addresses the issues discussed on #10040, and summarise all of the discussion in one place? As things stand, there's loads of context scattered across various issues and PRs. |
I’ll try to address some of the issues
the issue is that the underlying lower level components all rely on having the options object with all options available. But this approach ada the options explicitly and parses them. Whereas the previous pr would just magically start implementing all options of the install and list command.
is there an easy list command for this?
Does it not do this yet if we give it all packages in the environment?
Should this happen by default? Can this be a separate “auto clean” command ? ( like apt autoremove is seperate from apt upgrade)
I figured the resolver would take care of this?
what happens now if you run ‘pip install a -U’ |
Yes, it does, but I wanted some feedback on the approach first. The current approach boils down to: where all options of pip install that are needed by the lower level functions will keep working. |
I thought a lot of this had been covered in previous discussions, but part of the problem I have is that I'm not entirely clear we've even pinned down what people want when they say they want upgrade-all. This feature has been stuck for a long time because at a bare minimum we needed the new resolver, which ensures (hopefully!) that the upgraded environment will not contain conflicts. But I don't think that was the only thing that was blocking it. In reality, when I say "I want to upgrade everything" what I most likely mean is "I want to upgrade all of the top-level packages that I installed, and I want a consistent set of dependencies for them that's as up to date as possible". In 99% of cases, this is identical to "grab everything that's installed, and upgrade them all" - but there are cases where the two differ. For example, the em-keyboard package recently switched from depending on xerox to depending on pyperclip. Both provide the same functionality (clipboard support). If I upgrade an environment that contains em-keyboard, then I don't want xerox to be upgraded and pyperclip added as well. What I want is for em-keyboard to be upgraded, xerox removed, and pyperclip added. Unless, of course, something else in the environment still depends on xerox... Or I manually installed xerox because I use it for one of my scripts that I run by hand. It's very hard to discuss the upgrade-all command without coming back to the need to categorise installed packages as "user requested" vs "installed as a dependency". And that's a distinction that's near-impossible to make accurately as environments get modified over time. Arguably, having a manually maintained Which is why I'm saying we need to clearly explain what the upgrade-all command is intended to do. I need to be able to read the docs, and understand that it won't do the right thing in the |
How did pip install -U em-keyboard handle this case? This implementation will follow the same semantics. If the current implementation of pip install -U is not behaving as wanted, I can make a pr to fix it if someone gives a few good example cases in how it should behave. Will this case of removing “hanging packages”be solved by adding an auto-remove command? Personally I am against deleting packages without confirmation/ a second command. What if I had em-keyboard installed and wrote a script that uses xerox. I never had the need to manually install xerox because it was available on my system. I would not expect the xerox package to go away because I updated em-keyboard, unless I explicitly asked for a deletion. But indeed, I do plan to document with a good number of examples how this behaves once the implementation is agreed upon. |
Depends on the upgrade strategy. (The example isn't something I actually did, I had em-keyboard installed via pipx which does its own thing - upgrade left xerox around, reinstall rebuilt the lot). But
Well, "same" if you specify the same requirements to install -U as upgrade-all generated. And again, I'm not disputing that's what it does, I'm asking whether it should. If we're adding a whole new command just to save piping the output of
See? You understand precisely why this case is complex. And what I'm saying is that a command that left me with both pyperclip and xerox in the environment wouldn't be of any use to me. I'm questioning here whether we even need an upgrade-all command if this is the best we can manage (and to be clear, I was someone who argued for such a command originally, before I'd appreciated the complexities involved). Looking back at the history in #59, note the comment here:
We're at the point now where #988 is done. But we haven't really had a discussion on the functionality yet - we seem to have gone straight to implementing something based on one comment that suggested that 🤷 I don't really have the energy for an extended debate on this right now. Let's just say I'm -1 on the proposal as it stands. You'll need to convince at least one pip maintainer that this is a good idea before it can proceed, but I doubt that is going to be me. |
Thank you for the extensive feedback! I mainly made this pr to give an idea how I would like to see it implemented and as such an example of how it could be implemented and get the discussion started again ;) So please, discuss away! |
I just did notice some issues with this approach, I'm not sure where they're comming from, pip upgrade-all will upgrade celery to latest version 5.1.2 whilst I have django-task-api installed that requests a celery==4.*
|
hi! any update on this? |
Hi @pfmoore, so I take it first of all, there is a need to define semantically what means "upgrade-all" for pip ? |
It doesn't need a PEP, as it's a pip-specific matter. It "just" needs someone to actually think through all of the possibilities, and not just the obvious ones or the ones where what the user intends is clear. |
End goal : User upgrades all its pip packages. So far, I believe that an "all-upgrade" should :
Maybe in order to achieve this, I don't know but maybe building 2 graphs/list of all dependencies (older ones and newer ones required) and then do some kind of diff between the 2, to see new dependencies introduced and older that are removed.
There is this, which I'm not sure exactly what it is about, PEP 376 mentions this : https://peps.python.org/pep-0376/#implementation-details is this anything of concern ? I also don't see the REQUIRED file mentioned in PEP 376 but only :
I also read the test cases needed, I do agree that extensive testing should be done. @pfmoore is there anything that isn't clearly defined or a design decision that has not yet been answered that would hinder implementing this feature ? |
Lots. If I have A 1.0 installed, and B 1.0 installed, and A 2.0 and B 2.0 exist, but A 2.0 depends on B<2.0, and B 2.0 depends on A<2.0, which of A or B should an I can probably think of many other similar cases with a little more time, but to be blunt, this is the point. I don't have the time to spend looking for exceptional cases like this, which is why the responsibility is on a contributor to think about all these sorts of possibility, and come up with a proposal that addresses them. No-one's expecting a first-draft proposal to be perfect, but it must reflect the fact that this idea has been round for over 12 years, and if no-one has come up with a solution yet, it's very unlikely that a simplistic answer will work 🙁 |
@pfmoore what is wrong with the current semantics of There is currently already the option to run If you meant the order of |
In backtracking this is done by eventually falling back to the original user order of requirements, as I understand the intention of this PR it's equivalent to taking the output of pip list as the user requirements, and I believe that is in alphabetical order(?) so I think A would be prioritized over B.
In general I think users would find this surprising, if I had to support this logic I would prefer the equivalent of this Unix Shell script so that packages don't downgrade: pip freeze --exclude-editable --quiet | sed 's/==/\>=/g' > upgrade-all.txt
pip install -r upgrade-all.txt --upgrade Both choices (priority order) and whether a package can downgrade should obviously be documented. |
Ah but |
Thanks for mentioning the ordering @notatallshaw, I was not currently aware that made difference, (this explains the issue I saw in #10491 (comment) ) I guess indeed this needs to be documented and perhaps allow for other orderings, e.g. put the most behind packages first, or put the most up to date packages first, another option needs to be not to take any dependencies into account and just update every package to the latest possible version. If this means some things break, so be it, I'll fix the breaks and create a pr to the package and bump their dependency. |
There are several other discussions about implementing similar behavior for the use case where the user wants to potentially install a "broken" environment: |
Thanks for this. I didn't particularly intend that to be a complicated or difficult example, just something that needs to be considered, and which any proposal needs to have an answer for. The proposal by @AkechiShiro didn't cover it, that's all. The key point here is that there's just a bunch of rather tedious but important thinking about edge cases to be done. So far the history has been one of people posting ideas, and then others saying "but what about X?" It's not proved a very productive approach, as people nearly always get tired of responding to such questions1 long before they've got enough of the detail sorted out to write a PR. I'm suggesting that it would be more productive for someone to do this thinking (and also researching the historical discussion on this feature) before putting together a proposal - one that's more complete than just a paragraph or two here sketching an idea2. I may be wrong, such an approach may also end up going nowhere, but at least it's better than just trying the same approach over and over again 🙂 Footnotes
|
I think the issue here is Pip isn't a package or environment manager, it's just a package installer, so there's no precedent for what one chooses in these edge cases. And "upgrade-all" is more in the realm of package or environment management than "just" package installation. For example in @AkechiShiro proposal it states:
Pip has no way of knowing what is needed, Poetry has a golden source of requirements and Conda knows exactly how it built the environment, so in both cases there are more natural answers to "what is needed" but Pip has nothing. E.g. taking the ever hard example of extras, at any time you can just run Or a more simple example, what if you use and installed |
Yes, that's a really important point that I hadn't properly thought about. In fact, it's arguable based on that view that This is probably also why this issue has lingered for so long. People who want this functionality end up using an environment manager that provides it directly, so they no longer care that much that pip doesn't provide it. |
fixes #4551
I'm a new contributor to pip, so any hints on what kinds of tests to add for this command?
If this is more the direction you would like to go in I'll spend some time to fixing the #TODO's and refactor the code a little bit so a lot less copy pasting is going on between install command and update-all command.