-
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
--target option causes issues when upgrading or re-installing #1489
Comments
Has anyone had a chance to look at this since January? I just ran across this issue with the newest pip release. |
@dstufft, there seems to be a cluster of issues relating to this one. Has anyone looked at it? |
Hey guys, this issue has been open for some time. Is there anything I can do to help this along? |
@jonparrott Apart from the obvious "patches welcome", not much... The nesting behaviour is really odd. On the other hand, the fact that pip doesn't recognise that requests is installed is understandable (after all, it isn't installed in the sense that Personally, I only ever use To be honest, I could argue that |
@pfmoore thanks for the response!
An 'unpack' command, that still retrieved dependencies, updated in place, etc. could be a workable replacement, but you might want to talk to the folks in that community for feedback. The 'blow away and re-download' approach is what @jonparrott's tool Gaelic does as a workaround, BTW. |
@pfmoore The vendoring use case is exactly what the app engine community is trying to do, as mentioned by @webmaven. The problem stems that even though --target works great for the initial vendoring, running it again just breaks everything. I've even written a tool to do exactly what you described- nuke the target directory and re-"install" everything. Personally I think a command like "unpack" would perfectly suit the app engine community. I'm unfamiliar with pip internals and the particulars behind package installation, but I'm willing to dive in and take a first stab at implementing it. What are your thoughts, @webmaven? Of course, if Google would add proper virtualenv support to app engine we'd be fine where we are. :( |
@webmaven as you say, it's probably the AppEngine community that need to discuss alternative approaches. If we can fix upgrades with |
OK, here is the bare minimum of functionality that I think a notional
A current pain point not yet addressed by pip: deriving a list of installed packages and their versions from a target folder. Because it isn't installing anything, you need an alternate method of creating expanded requirements files that include the unpacked dependencies. Either of the following would work: @jonparrott, can you think of anything else that is required to replace |
All you need to scan a directory for what's installed is: import pkg_resources
env = pkg_resources.Environment([dirname])
for project in env:
for dist in env[project]:
print("{}=={}".format(dist.project_name, dist.version)) That's effectively what you were wanting from |
Oh, and the So it seems to me that you can probably use the "blow away the directory" approach along with the script to generate a requirements file as a workaround. |
@jonparrott, you have more experience than I in this area, but it doesn't seem to me, provided that the local install is in a virtualenv, that the
Of course. But then, you were asking what it would take to replace
Blowing away the contents of the directory only works for |
OK. I just looked at the code. If
So the nesting comes from step (4) as if the destination of The "install into a temp dir" aspect explains most of the other inconsistencies, too. Multiple installs don't say "this is already there" because it isn't. Upgrade won't work because it's not there to upgrade. Editable would probably be a mess, I have no idea how it would work. "Fragile" is the most polite term I can think of for the behaviour... |
Thanks for looking into this Paul and finding the source of one of the problems. I think for App Engine's purposes, fixing upgrade isn't really necessary - if there's a way for us to overwrite anything in the destination directory instead of failing that would be sufficient. I can try to see if I can write a test/PR this weekend for the fix if you don't beat me to it. |
@pfmoore thanks for investigating! Like @jonparrott says, upgrading is desired but not required (desired because it makes using app engine that much more like the rest of the Python ecosystem). If we just get to idempotency for repeated installs, I think we'll both be quite pleased. What happens if you skip steps 2, 4, and 5, and do the install with |
1. Check for the existence of a directory before copying from temporary directory to final target. If it exists, warn the user. 2. If the user specifies the --upgrade option and the directory exists, delete it and continue with installation. 3. Adding tests for above cases. This resolves pypa#1489, pypa#1710 completely and parts of pypa#1833.
PR submitted. It was easier than I expected to get the behavior that we wanted from an app engine perspective, I'm just not sure if it's what pip wants for the behavior of --target. Either way, I think it's an improvement over the broken behavior that's there currently. @pfmoore feel free to let me know if I need to adjust anything here. |
@jonparrot I've just looked at the PR, and it looks good. I'll probably download it and test it a bit locally before merging it, but I don't see any obvious problems. As regards the preferred behaviour of On a somewhat unrelated note, are the |
@pfmoore any problems show up in testing? |
@webmaven sorry I got caught up with RL. Thanks for the ping, I've merged this now. |
Previously we checked that the `request` being sent was an instance of a PreparedRequest. If a user somehow created a PreparedRequest using a different Requests library instance, this check makes the request un-sendable. (This happened recently - unbeknownst to me, my server was running an outdated version of pip, vulnerable to this issue - pypa/pip#1489, which creates multiple subdirectories (src/requests, src/requests/requests) when you rerun pip install --target. So the PreparedRequest was being created in one version of the library and compared against the other version of the library, and throwing this exception, even though they were both PreparedRequest instances!) It would probably be preferable to check the object's behavior (instead of its type), but a PreparedRequest has a lot of behavior, and it wouldn't be really feasible or allow us to provide a helpful error message to check all of it here. Instead flip the conditional to guard against the user sending an unprepared Request, which should still give us most of the benefits of the better error message. Fixes psf#3102
If you install using the "--target" option:
And then repeat the command a second time, it doesn't say "requirement satisfied" it installs it again as a subdirectory of the existing installation (lib/requests/requests and lib/requests-2.2.0.dist-info/requests-2.2.0.dist-info
Repeat the command a third time and it appears the nesting stops but it chokes and still doesn't report "requirement satisfied":
The text was updated successfully, but these errors were encountered: