-
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
Add support for command plugins #2329
Conversation
Hmm, last time this was discussed, using entry points was an issue because it added a dependency on setuptools (which is problematic because tools like virtualenv use pip without setuptools to install from wheels only). But now we vendor Some comments:
|
My opinion on allowing to register plugins is basically that unless we provide an API to pip itself the only real benefits is that a user can type something like |
similar to what I did last year, but we didn't merge: #1409 |
I guess I kind of see @dstufft's point that as-is, this doesn't give you a ton of new functionality. But I do think there's some value in being able to unify stuff. E.g.: to type The interesting question here is what API should pip provide. I think pip has seen itself as a tool rather than an API so the API has never been a focus and there are not a ton of tools that I know of that try to use pip -- with It is a different focus for sure. Historically, pip has done everything it wanted to do itself. If time is invested in APIs, then it enables a wider set of people to do features and to move more quickly. APIs are hard though for sure. And I don't yet know what these APIs would look like. |
beyond the command entry point itself, many plugins would most likely need additional entry points to plug in additional types or steps in various places. If it were just me, I'd be inclined to just start adding extension points with no promises and see where it went. |
Having just looked at writing a simple pip-query command, it does seem to me that a plugin system is worth it. It allows you to copy one of pip's built in commands and get argument handling for free, as well as being able to concentrate on your command's logic rather than UI stuff. We should make it 100% clear that because we allow people to write plugins that use the internal API, does not mean that we guarantee any sort of stability, but that's fine. It will encourage people to experiment externally with new command suggestions (there are a few such issues open at the moment) and the resulting code will be that much easier to include in core pip should we later decide to do so, just because it will use the standard command conventions. |
OK, it's definitely worth it IMO. Took me 30 minutes to write a new command by cloning an existing one. I'd previously tried to write a standalone script, and gave up pretty fast having done nothing but try to get basic arg parsing working, working out how to set up a finder with a suitable session. I never even got close to supporting options like Let's just do it and see how it goes. @msabramo Could you fix the pep8 failures and add some minimal docs? |
So one other thing that might make us want to hold off is that I'm currently experimenting using click in the virtualenv rewrite. If it works out well there then I think it's reasonable to switch pip itself to use click. If we do that then that's going to be a major break in the API of creating a command right around the time we release the entrypoint which seems less than ideal (even if technically allowed). |
Hmm, possibly. On the fifteenth hand (!) a 3rd party plugin (and even more so a personal one) can be less "perfect" than a pip builtin command. So, for example, I have knocked up a "pip query" command that I'd really like to try out - the output isn't perfect and there are a lot of rough edges yet, but installing a plugin while I work on that is much easier than using a personal build of pip. We obviously have different opinions, so it'd be good if others chimed in. @pypa/pip-developers anyone else have a view? |
Well I don't really mean that we shouldn't add it (I don't feel strongly enough to say absolutely not) just that if we're going to add it we might want to hold off until we see if click works out for virtualenv and if we're going to switch pip to it so that we don't go "hey you can make pip plugins!" and then immediately turn around and break anyone who uses that by making a major change to the command infrastructure. |
Yeah, same for me the other way round, it's not super-urgent as it's no benefit till it's in a released pip anyway. It sounds like the virtualenv rewrite (and hence a decision on click) is going pretty well, so it's probably not as far off as I was assuming. No need to panic about a decision. |
I am using click for some internal tools at work and I love it! So I'd be up for delaying this for that 😄 |
95193dd
to
d1191a1
Compare
Just pushed an update just to fix PEP 8 and rebase on Has anyone tried playing with click yet? I didn't see a branch for it, but maybe someone is playing with it locally? |
Simply register a Command class with the new `pip.command.v1` entry point.
d1191a1
to
63019ed
Compare
I just played with click a bit in the context of pip. I must say that although I have loved working with click on a few recent green field projects, I feel like click is probably not a great fit for an existing tool like pip. I attempted to convert the |
I took a different approach with |
I think if there's one lesson to learn from distutils, it's that subclassing based plugin APIs are not a good way to go :) An approach I've seen (and used) that provides a much cleaner separation of concerns is dependency injection: the containing applications provides the scaffolding to run the plugin, and then passes the plugin an API object that defines the supported interface. This has the combined benefit of making plugins easier to test (since you can pass in a mock API object), as well as making it easier to evolve the API exposed to plugins (since as long as plugins are versioned, you can ensure they receive the correct kind of API object). And this is where I think switching to click could be valuable in terms of offering a more sustainable plugin API: http://click.pocoo.org/5/complex/#complex-applications The key there is the support that click has for managing command contexts. While the example in the click docs focuses on how that can be used to pass context to subcommands, and https://pypi.python.org/pypi/click-plugins supports adding new subcommands that parallel existing ones, the context concept can also be reused for passing information and APIs to plugins. |
Accidentally closed this, reopening. Sorry! |
Hello! As part of an effort to ease the contribution process and adopt a more standard workflow pip has switched to doing development on the If you do nothing, this Pull Request will be automatically closed by @BrownTruck since it cannot be merged. If this pull request is still valid, please rebase it against If you choose to rebase/merge and resubmit this Pull Request, here is an example message that you can copy and paste:
|
This Pull Request was closed because it cannot be automatically reparented to the Please feel free to re-open it or re-submit it if it is still valid and you have rebased it onto |
@msabramo Are you planning to reopen it? |
@szepeviktor: Yep, see #4166. |
This introduces a new concept to pip called "command plugins". This allows a user to implement new features but do them outside pip itself. This means that people can do interesting experimental and/or custom features and implement these features outside of pip so that it doesn't clutter up the core code of pip and it doesn't require the time of pip maintainers to review it.
This might also be an alternative to simply ripping out features of pip that maybe aren't used a ton and are deemed not worth the effort to maintain them (e.g.:
pip [un]zip
,pip bundle
, etc.). Perhaps evenpip wheel
could be made into a plugin (although I feel that it is probably used much more than the previously mentioned commands, but maybe sincepip wheel
requires thewheel
package anyway, maybe it makes sense to just have thewheel
package implement a pip plugin?). Such features could be removed from pip itself, but put into a separate plugin package and maintained by a 3rd party, so that they are not a time burden on PyPA developers.To create a plugin command, simply:
pip.basecommand.Command
class (example).pip.command.v1
entry point in thesetup.py
of your distribution (example).An example plugin is available at https:/msabramo/pipdeptree/tree/pip_plugin -- in this branch I've forked an already existing
pipdeptree
project that implements a separatepipdeptree
command -- in my fork I've put in the necessary bits so thatpipdeptree
is a pip plugin.Showing how it works...
Cc: @dstufft, @pfmoore, @naiquevin, @therealprologic
Refs: tox-dev/pipdeptree#1