-
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
Splitting a package into two packages leads pip to corrupt the packages when upgrading to the new versions #8509
Comments
System package managers fix this issue by keeping track of what files are owned by the packages being installed in the "transaction" (a transaction is roughly, all the packages that are being installed and uninstalled as a result of what the user requested at the command line). Then, when they uninstall any older versions of the packages, they know not to uninstall the files which were freshly installed as part of the transaction. |
Just one more note... I didn't really expect it to help but I tried |
The reason for this will be the sequence of events pip goes through:
Step 3 will remove stuff that's been moved from ansible to ansible-base. The easiest workaround, as you've discovered, is to uninstall and do a clean install. Pip can't easily address this with its current architecture, as it treats each install independently. The only approach I can see that might work is to do all the uninstalls first, then the installs. And keep everything as one transaction, so a failed install in one package can back everything out cleanly. But my gut feeling is that this would be quite a major change. |
Yep. And uninstalling everything first opens up a different class of bugs (Probably smaller but they do exist). Any package which would require one of the uninstalled packages in order to install could fail to install. System packages need deps installed for pre and post scripts. I can't remember if those have finally been approved for python packages or not, though. python packages would additionally need deps installed for building the package from an sdist in some cases but perhaps that's mitigated by the isolated build feature? System package managers do all the installs first and then do all the uninstalls so that they don't have to deal with the above problems. But they use the transaction to record what files have just been installed so they don't erase them in the uninstall step. Without a transaction concept right now, this would be an even bigger change to pip than merely doing all the uninstalls before the installs. |
That sounds more like a bug in the project's |
It is related to the solution. But I'm not sure how much of a system packager knowledge maps to what python packaging currently or in the near future, does.
If neither of those use cases is an issue than moving uninstall to the front of a transaction work queue should work just as well as tracking the files to prevent uninstallation of ones that were installed in this transaction. I just wanted to point them out because I lack the knowledge of whether either of those use cases exist or not. |
Build time dependencies specified in |
Cool. So yes, we should be able to add a simple transaction concept where uninstall of everything in the transaction is the first step and then install is the second step. (i say simple in comparison to system package manager's transaction concept but I do acknowledge that it's a big change from what pip currently does). |
I think the first step here would be to get pip to error out on file conflicts. This seems fairly easy, just read |
Uh, it’s not that simple, since file-overwriting is a needed feature for |
Hello all, a quick FYI - the current way to reproduce this bug is
Because of ansible/ansible#70529 |
|
@bmillemathias yes, but the previous repro doesn't fully demonstrate the problem anymore. And so @fbidu has correctly posted the new reproducer for whoever attempts to dig into it in the future. |
@bmillemathias yes, what @webknjaz said. I'm participating on the packaging sprint at EuroPython and was studying this issue to try to come up with a failing test case for #8579 |
Now that we dropped Python 2 (for a while now!) maybe it’s time to revisit this. There are two routes to take here:
Option 1 is obviously simpler, but also more restrictive and would potentially break existing use cases and cause user frustration. |
@uranusjr I'm convinced that the better fix would be implementing transactions and splitting the removal stage from the installation. This way, when it's pre-calculated which packages need to be removed from disk, they all could be deleted first and only after that, the new package versions would be placed there. |
@webknjaz Having properly transactional behaviour almost certainly would be an improvement. I hinted at that option in a previous comment, but as I said there, I suspect it would be a pretty large change. I don't know of anyone currently working on that, though, and I feel that we shouldn't dismiss the possibility of making a simpler fix in the meantime. |
FWIW, if we ever end up working on this, I reckon we'd also want to consider how this interacts with #4625 -- it might make sense to solve them together. |
Here's another repro, if useful: #12574 |
(Forgive me if this is a duplicate... It seems like a problem that should have been reported in the past [I've heard that the transition from docker-py to docker resulted in similar problems]. I couldn't find any search terms that found an existing bug report so I'm opening a new one)
Environment
Description
The ansible-2.9.x package is one large, monolithic package. ansible-2.10.x splits this package into two:
The ansible-2.10.x package has a dependency on the ansible-base packages. This way people who only need the minimal functionality can
pip install ansible-base
(>=2.10.0b1). People who just want to get the same experience as ansible-2.9.x canpip install ansible
(>=2.10.0a1) .A clean install works fine:
The problem is upgrades:
Expected behavior
I expect that upgrading the package will lead to a system where both new packages are installed with all of the files that the new packages include.
How to Reproduce
Output
The text was updated successfully, but these errors were encountered: