Open dreua opened 4 years ago
Sounds reasonable. I’d suggest not listing the alias in help to avoid clutter, but having the alias itself is fine.
How do we add an alias to a command? I am not sure about it.
IMHO it's as trivial as
diff --git a/src/pip/_internal/commands/__init__.py b/src/pip/_internal/commands/__init__.py
index 6825fa6e..defcf967 100644
--- a/src/pip/_internal/commands/__init__.py
+++ b/src/pip/_internal/commands/__init__.py
@@ -44,6 +44,10 @@ commands_dict = OrderedDict([
'pip._internal.commands.uninstall', 'UninstallCommand',
'Uninstall packages.',
)),
+ ('remove', CommandInfo(
+ 'pip._internal.commands.uninstall', 'UninstallCommand',
+ 'Uninstall packages.',
+ )),
('freeze', CommandInfo(
'pip._internal.commands.freeze', 'FreezeCommand',
'Output installed packages in requirements format.',
I'm trying to work on this because I thought it's easy but had to come here to ask about testing strategy :smile:
Thanks, @McSinyx! Please go ahead, no issue :)
As for testing, the approach I can think of is to parametrize the tests which involve uninstall
command with remove
command as well. IMO, this would test all the cases involve with uninstall
command.
parametrize the tests which involve
uninstall
command withremove
command as well
That's brilliant (kudos to pytest
devs for making little convenient things like this possible too). I'm a bit worried about redundancy but first class command may need first class supports.
IMHO it's as trivial as
This might cause remove
to be listed in pip help
, which I think we want to avoid as per https://github.com/pypa/pip/issues/8130#issuecomment-619339279
$ pip help
Usage:
pip <command> [options]
Commands:
install Install packages.
download Download packages.
uninstall Uninstall packages.
remove Uninstall packages.
freeze Output installed packages in requirements format.
list List installed packages.
show Show information about installed packages.
check Verify installed packages have compatible dependencies.
config Manage local and global configuration.
search Search PyPI for packages.
cache Inspect and manage pip's wheel cache.
wheel Build wheels from your requirements.
hash Compute hashes of package archives.
completion A helper command used for command completion.
debug Show information useful for debugging.
help Show help for commands.
I was thinking along the lines of implementing get_alias_commands
which looks for a mapping between alias and it's commands (in this case it will be remove
-> install
) and call it at https://github.com/pypa/pip/blob/master/src/pip/_internal/cli/main_parser.py#L87
@deveshks, thank you for the heads up, that looks like a much better idea.
Personally I on board with the alias command or some similar settings. (like what git has)
I’d suggest not listing the alias in help to avoid clutter, but having the alias itself is fine.
I think if we're adding aliases, we definitely want them to be visible to the user via help. That said, we should avoid any amount of clutter that we can. So, I agree that just adding "remove" with the same CommandInfo
as uninstall is not what we want to do here.
I'd say, we should aim to have a uniform and proper way to provide aliases to users, allowing for multiple aliases for multiple commands, such that it's not difficult to add another alias for a command (similar to how adding a command is a matter of manipulating a single list).
Of course, this means we'd have to get a bit more fancy with how our command parser works, figure out how help should know about the command names and all that... but I much prefer that to something more "bolted on" / invisible to the users.
I'd imagine aliases could look like this:
$ pip help
Usage:
pip <command> [options]
Commands:
i, add, install Install packages.
download Download packages.
u, rm, remove, uninstall Uninstall packages.
...
Or... we could do what npm
does in their docs/help:
npm install (with no args, in package dir)
[snip, bunch more examples]
aliases: npm i, npm add
common options: [snip]
Even though I'm using them in the example above... I'm a -1 on adding a "remove" alias for uninstall, without a counterpart "add" alias for install and... I'm a -0 on adding them both together. I don't know how useful this, on it's own, would be to the general audience of pip users. I'm personally a lot more interested in adding shorthands for "most common commands", like I hinted at in the example above, which would be similar to npm i
.
All that said, there's also the risk of "too many ways to do the same thing", which... is really the last thing I'd want to start messing about with pip's CLI today. I think we should wait until we move away from optparse to something else (see #4659), where it's easier to do these things properly without adding significantly more technical debt / complexity to the fairly complex/fragile CLI setup we have today.
As for testing, the approach I can think of is to parametrize the tests which involve
uninstall
command withremove
command as well.
Doubling the number of tests (which doubles test execution times) is not a good idea. I'd much rather have a unit test that mocks out the actual implementation of the commands, and checks that various aliases hit the same Command.run
block.
That's 1 extra unit test to run after adding an alias, which is significantly better than running 30+ tests w/ subprocesses and virtual environments being created for isolating them.
I'm also somewhat concerned about the precedent this sets. I'm sure there are plenty of other places where pip's commands don't quite match those of other package managers. Should we add aliases for all of those? Why aren't other package managers adding aliases to match pip's commands?
A user-defined alias mechanism like git has might be useful, but explicitly adding code to pip for each alias that someone feels would be useful isn't scalable (or IMO advisable).
Thank you @pradyunsg and @pfmoore for your thoughtful comments. Given no(t yet any) consensus on the execution, I'll mark my PR as draft until I figured out a clean way to resolve your requests al(most)together, to avoid discussion without concrete code for reference.
Edit: to add to the concerns above, personally I'm neither certain about the representation of subcommand docs, e.g. for uninstall should the usage section be
Usage:
pip uninstall [options]
Neither looks visually pleasing to me personally.
the representation of subcommand docs
Usage:
pip uninstall [options] <package> ...
pip uninstall [options] -r <requirements file> ...
Aliases: pip remove
@pradyunsg, could you please see if the behavior in GH-8137 fits your vision. I'd be happy with your new suggestion though, just wanna make sure you've seen it.
Thank you all for your comments and especially @McSinyx for the PR. I like the proposed behavior and it would make my life (and probably others' too) a bit easier by not having to spend brain cycles to figure out whether you need to type uninstall
or remove
. Is there anything else I can do to get this merged and shipped?
I just searched for this issue after using remove and add for the umpteenth time :)
I'd like to propose making the following changes
Any other commands that people mis-remember and use?
The search/find which is undergo a UX refactor which group everything together (I think @pradyunsg may explain this better to you, he's been planning it for a while now), but the other two are included in my linked PR (GH-8137).
I've added this issue to the UX team's research list.
Under #8516 I will conduct a command audit and find out what commands users currently struggle to remember. Under #8515 @ei8fdb will compare pip's commands against other packaging tools.
OK, I'm on board for adding i
as an alias for install
and u
as an alias for uninstall
.
If someone wants to file a PR implementing this (based of off #8137, ideally), please feel welcome to. That isn't to say the PR would be guaranteed to merge; but it would help move us forward on this front! ^.^
in response there is: https://github.com/pypa/pip/pull/12828#issuecomment-2248375174 (design)
I agree with the confusion about which commands are used by newer developers, but if we take this literally, no functionality would be released as one version would have access to the functionality and another would not.
but your comment is really useful and makes me think about the consequences of such a direct and visible implementation (being displayed with the --help command), taking this into account I thought we could implement this subtly in a gradual way and using just simple aliases ( i,u,ls) we would basically implement the aliases without displaying it in --help and after 4/5 years when most developers already have the version with support for aliases then yes we could display this
following the discussion, I think the most sensible way to go about this issue would be to implement a "remove" command... only to raise a useful error message that the remove command does not exist
# now in main
pip remove
ERROR: unknown command "remove"
# better
pip remove
ERROR: unknown command "pip remove", did you mean "pip uninstall"?
I think the issue is very specific to the uninstall command because it's only used once in a while. I myself can never remember if it's pip remove or pip delete, I try both and it's neither :D
pip install does not need any assistance IMO
What's the problem this feature will solve?
As a software developer and package maintainer, I often install and remove software packages with different package managers. With pip I often run into this error:
Describe the solution you'd like
Have a
remove
command that does exactly the same asuninstall
.Alternative Solutions
pip
in general but not forpip remove
.)Additional context
Package managers which use remove and don't know uninstall:
Package managers which have both: