uninstall.py 3.4 KB

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