-
-
Notifications
You must be signed in to change notification settings - Fork 611
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
pip-sync yields different results depending on pre-installed package set #896
Comments
This comment has been minimized.
This comment has been minimized.
@AndydeCleyre I assume you pinged me because of my thumbs-down vote. What you request would be a complete reversal of how pip-tools works. All the 'smarts' are in Maybe it would be possible for your case to pass your initial (third party generated) |
Thanks, yes, I wanted to encourage discussion here. On the other side, I'd say that installing a requirement's dependencies is part of installing that requirement, and that users should expect any installed package to have its dependencies also installed. I took a look and saw that echo "pytest==5.1.2" > requirements.txt
pip install -r requirements.txt
pip-sync requirements.txt
# pytest remains installed but broken, with dependencies removed
pip-sync /dev/null
pip-sync requirements.txt
# pytest is installed "properly," with its dependencies included In other words, if Here the inconsistency is more simply demonstrated: echo "pytest==5.1.2" > requirements.txt
pip-sync /dev/null
pip-sync requirements.txt
pip freeze | wc -l
# 14
pip-sync requirements.txt
pip freeze | wc -l
# 4 So the environment state that While my position is for not breaking dependencies, either way the project goes on that, I think we can agree that it should behave more consistently in this case. I will submit a pull request for my idea of a fix for this, though I understand that it will likely just be an anchor for continued discussion of "correct" behavior here. |
That's my preferred solution! Perhaps IMO "running |
That's an interesting idea! |
This comment has been minimized.
This comment has been minimized.
What do you think of #907? It brings consistent behavior where we currently have surprises, and it brings in I don't think |
This comment has been minimized.
This comment has been minimized.
Alright, I've rebased #907 onto master, now that we've got $ echo "pytest==5.1.2" > requirements.txt
$ pip-sync /dev/null
$ pip-sync requirements.txt
$ pip freeze | wc -l
12
$ pip-sync requirements.txt
$ pip freeze | wc -l
12
$ pip-sync --pip-args --no-deps requirements.txt
$ pip freeze | wc -l
4
$ pip-sync /dev/null
$ pip-sync --pip-args --no-deps requirements.txt
$ pip freeze | wc -l
4 And here's the behavior in current master, without #907: $ echo "pytest==5.1.2" > requirements.txt
$ pip-sync /dev/null
$ pip-sync requirements.txt
$ pip freeze | wc -l
12
$ pip-sync requirements.txt
$ pip freeze | wc -l
4
$ pip-sync --pip-args --no-deps requirements.txt
$ pip freeze | wc -l
4
$ pip-sync /dev/null
$ pip-sync --pip-args --no-deps requirements.txt
$ pip freeze | wc -l
4 This shows that Please have a look and let me know what you think, @atugushev @Zac-HD @Minkey27 @ulope |
Unfortunately my opinion hasn't changed from when I made my last comment in this issue. For me the whole point of using pip-tools is that the generated requirements.txt exactly describes what the installed virtualenv will look like afterwards. I don't think it's a good idea to change the default (which would also be backwards incompatible as well) and force everyone wanting to retain the current behaviour to pass As for the inconsistency you note in #907 (12 vs 4 packages installed), that seems like a bug to me. It should always behave in the no-deps way and only install 4 packages. So TL;DR: |
I appreciate the feedback @ulope, thanks! |
A year and a half since opening, and I'm still curious if anyone has encountered a workflow that would be broken by #907. I believe some are concerned that existing workflows would be disrupted, but AFAICT that is untrue. There may be good reason to reject this change, so let's not muddy the waters with bugaboos. |
…g sync. By including already-installed matching requirements in the to_install set, dependencies of pinned packages will be installed (after potentially being uninstalled), regardless of environment state at time of sync, for a more consistent, predictable, and practical resulting state. Fixes jazzband#896. Modify tests to expect explicit requirements in the to_install set, to match.
…g sync. By including already-installed matching requirements in the to_install set, dependencies of pinned packages will be installed (after potentially being uninstalled), regardless of environment state at time of sync, for a more consistent, predictable, and practical resulting state. Fixes jazzband#896. Modify tests to expect explicit requirements in the to_install set, to match.
Fixes jazzband#896 By including already-installed matching requirements in the to_install set, dependencies of pinned packages will be installed, after potentially being uninstalled, regardless of environment state at time of sync. The already-installed reqs will still not be reinstalled, thanks to pip's own handling. The resulting state is more consistent, predictable, and practical. Modify tests to expect explicit requirements in the to_install set, to match.
Well, It's been some time so I will close this issue now (and PR) since it didn't get positive feedback (3 nays vs 1 yay). Feel free to reopen if you find broken workflows in a wild due to the issue. Sorry! |
Update: The shape of this issue has changed a bit since creation, due to discoveries in this discussion, and the addition of the
--pip-args
option. I'm renaming it, and adding a new summary:If
pip-sync
has to actively install a requirement, its dependencies will end up in the environment. But if the requirement is already installed whenpip-sync
runs, its dependencies not present in thetxt
will be removed, "breaking" the environment.A
txt
which omits dependencies is, by pip-tools standards, malformed, and thereforepip-sync
's behavior is not currently guaranteed or defined. But:IMO a package is not "properly" installed if its dependencies aren't present, and
pip-sync
should achieve "proper" installs.If a user wants to "break" dependencies, they can explicitly do so with
--pip-args --no-deps
While I don't see an advantage to the current (inconsistent) behavior, having the deps always installed (unless
--no-deps
is specified) would enable users to usepip-sync
without issue ontxt
s that don't come frompip-compile
. Though not officially supported, it's a nice bonus to be able to usepip-sync
uniformly as a complete replacement/wrapper forpip install -r
. Now that Exclude requirements with non-matching markers from pip-sync's merge stage #927 is merged, I don't know of any other obstacle to supporting "foreign"txt
s (in practice, if not policy).My idea of a solution is #907, which keeps already-installed packages in the to-install set, as
pip
itself will refrain from reinstalling those anyway, and will ensure its dependencies get installed if necessary.Original report:
I looked but didn't find an existing issue for this.
What's the problem this feature will solve?
I would like to use
pip-sync
onrequirements.txt
files that are not generated bypip-compile
, for arbitrary (other folks') Python projects. In fact I had been doing so, and I guess I have been getting lucky, as I only recently came to a case where this failed, and was surprised to find when re-readingpip-tools
's README:The failure I notice is that
pip-sync
will uninstall hard dependencies of packages listed in therequirements.txt
. I don't know if there are further problems.Describe the solution you'd like
Until/unless there are other specifically identified problems for externally crafted
requirements.txt
files, the solution would seem to be forpip-sync
to refrain from uninstalling dependencies of explicitly listed packages. This might be as simple as doing all the uninstalling before any of the installing.This would enable
pip-tools
users to continue to usepip-sync
across all Python projects they work on, even if they are not in a position to enforce use ofpip-compile
to manage those projects'requirements.txt
generation.Alternative Solutions
Alternatively, of course, users can just use
pip install -r requirements.txt
. That however does not have the advantage of stripping the environment of non-required packages. Although I guess the solution could then be as simple aspip-sync requirements.txt && pip install -r requirements.txt
.Additional context
Simple demonstration of the problem:
The result is a broken installation of
pytest
.The text was updated successfully, but these errors were encountered: