uninstall.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import logging
  2. from optparse import Values
  3. from typing import List
  4. from pip._vendor.packaging.utils import canonicalize_name
  5. from pip._internal.cli import cmdoptions
  6. from pip._internal.cli.base_command import Command
  7. from pip._internal.cli.index_command import SessionCommandMixin
  8. from pip._internal.cli.status_codes import SUCCESS
  9. from pip._internal.exceptions import InstallationError
  10. from pip._internal.req import parse_requirements
  11. from pip._internal.req.constructors import (
  12. install_req_from_line,
  13. install_req_from_parsed_requirement,
  14. )
  15. from pip._internal.utils.misc import (
  16. check_externally_managed,
  17. protect_pip_from_modification_on_windows,
  18. warn_if_run_as_root,
  19. )
  20. logger = logging.getLogger(__name__)
  21. class UninstallCommand(Command, SessionCommandMixin):
  22. """
  23. Uninstall packages.
  24. pip is able to uninstall most installed packages. Known exceptions are:
  25. - Pure distutils packages installed with ``python setup.py install``, which
  26. leave behind no metadata to determine what files were installed.
  27. - Script wrappers installed by ``python setup.py develop``.
  28. """
  29. usage = """
  30. %prog [options] <package> ...
  31. %prog [options] -r <requirements file> ..."""
  32. def add_options(self) -> None:
  33. self.cmd_opts.add_option(
  34. "-r",
  35. "--requirement",
  36. dest="requirements",
  37. action="append",
  38. default=[],
  39. metavar="file",
  40. help=(
  41. "Uninstall all the packages listed in the given requirements "
  42. "file. This option can be used multiple times."
  43. ),
  44. )
  45. self.cmd_opts.add_option(
  46. "-y",
  47. "--yes",
  48. dest="yes",
  49. action="store_true",
  50. help="Don't ask for confirmation of uninstall deletions.",
  51. )
  52. self.cmd_opts.add_option(cmdoptions.root_user_action())
  53. self.cmd_opts.add_option(cmdoptions.override_externally_managed())
  54. self.parser.insert_option_group(0, self.cmd_opts)
  55. def run(self, options: Values, args: List[str]) -> int:
  56. session = self.get_default_session(options)
  57. reqs_to_uninstall = {}
  58. for name in args:
  59. req = install_req_from_line(
  60. name,
  61. isolated=options.isolated_mode,
  62. )
  63. if req.name:
  64. reqs_to_uninstall[canonicalize_name(req.name)] = req
  65. else:
  66. logger.warning(
  67. "Invalid requirement: %r ignored -"
  68. " the uninstall command expects named"
  69. " requirements.",
  70. name,
  71. )
  72. for filename in options.requirements:
  73. for parsed_req in parse_requirements(
  74. filename, options=options, session=session
  75. ):
  76. req = install_req_from_parsed_requirement(
  77. parsed_req, isolated=options.isolated_mode
  78. )
  79. if req.name:
  80. reqs_to_uninstall[canonicalize_name(req.name)] = req
  81. if not reqs_to_uninstall:
  82. raise InstallationError(
  83. f"You must give at least one requirement to {self.name} (see "
  84. f'"pip help {self.name}")'
  85. )
  86. if not options.override_externally_managed:
  87. check_externally_managed()
  88. protect_pip_from_modification_on_windows(
  89. modifying_pip="pip" in reqs_to_uninstall
  90. )
  91. for req in reqs_to_uninstall.values():
  92. uninstall_pathset = req.uninstall(
  93. auto_confirm=options.yes,
  94. verbose=self.verbosity > 0,
  95. )
  96. if uninstall_pathset:
  97. uninstall_pathset.commit()
  98. if options.root_user_action == "warn":
  99. warn_if_run_as_root()
  100. return SUCCESS