From 0470a82248fb3ce22e2cd96d308d7c07b2acf634 Mon Sep 17 00:00:00 2001 From: Devesh Kumar Singh Date: Sat, 11 Apr 2020 02:55:27 +0530 Subject: [PATCH 1/3] Type annotations for help, list and uninstall in commands --- ...D0A87D-0ACD-418E-8C02-4560A99FEB71.trivial | 0 src/pip/_internal/commands/help.py | 9 ++++-- src/pip/_internal/commands/list.py | 32 ++++++++++++++++--- src/pip/_internal/commands/uninstall.py | 13 ++++++-- 4 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 news/9CD0A87D-0ACD-418E-8C02-4560A99FEB71.trivial diff --git a/news/9CD0A87D-0ACD-418E-8C02-4560A99FEB71.trivial b/news/9CD0A87D-0ACD-418E-8C02-4560A99FEB71.trivial new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/pip/_internal/commands/help.py b/src/pip/_internal/commands/help.py index c17d7a457c4..ecd2b4737e3 100644 --- a/src/pip/_internal/commands/help.py +++ b/src/pip/_internal/commands/help.py @@ -1,11 +1,13 @@ -# The following comment should be removed at some point in the future. -# mypy: disallow-untyped-defs=False - from __future__ import absolute_import from pip._internal.cli.base_command import Command from pip._internal.cli.status_codes import SUCCESS from pip._internal.exceptions import CommandError +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List, Any + from optparse import Values class HelpCommand(Command): @@ -16,6 +18,7 @@ class HelpCommand(Command): ignore_require_venv = True def run(self, options, args): + # type: (Values, List[Any]) -> int from pip._internal.commands import ( commands_dict, create_command, get_similar_commands, ) diff --git a/src/pip/_internal/commands/list.py b/src/pip/_internal/commands/list.py index 109ec5c664e..fdfc8ba07b8 100644 --- a/src/pip/_internal/commands/list.py +++ b/src/pip/_internal/commands/list.py @@ -1,6 +1,3 @@ -# The following comment should be removed at some point in the future. -# mypy: disallow-untyped-defs=False - from __future__ import absolute_import import json @@ -10,6 +7,7 @@ from pip._internal.cli import cmdoptions from pip._internal.cli.req_command import IndexGroupCommand +from pip._internal.cli.status_codes import SUCCESS from pip._internal.exceptions import CommandError from pip._internal.index.package_finder import PackageFinder from pip._internal.models.selection_prefs import SelectionPreferences @@ -21,6 +19,14 @@ write_output, ) from pip._internal.utils.packaging import get_installer +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import Any, List, Set, Tuple + + from pip._internal.network.session import PipSession + from pip._vendor.pkg_resources import Distribution logger = logging.getLogger(__name__) @@ -36,6 +42,7 @@ class ListCommand(IndexGroupCommand): %prog [options]""" def __init__(self, *args, **kw): + # type: (*Any, **Any) -> None super(ListCommand, self).__init__(*args, **kw) cmd_opts = self.cmd_opts @@ -116,6 +123,7 @@ def __init__(self, *args, **kw): self.parser.insert_option_group(0, cmd_opts) def _build_package_finder(self, options, session): + # type: (Values, PipSession) -> PackageFinder """ Create a package finder appropriate to this list command. """ @@ -133,6 +141,7 @@ def _build_package_finder(self, options, session): ) def run(self, options, args): + # type: (Values, List[Any]) -> int if options.outdated and options.uptodate: raise CommandError( "Options --outdated and --uptodate cannot be combined.") @@ -160,26 +169,35 @@ def run(self, options, args): packages = self.get_uptodate(packages, options) self.output_package_listing(packages, options) + return SUCCESS def get_outdated(self, packages, options): + # type: (List[Distribution], Values) -> List[Distribution] return [ dist for dist in self.iter_packages_latest_infos(packages, options) if dist.latest_version > dist.parsed_version ] def get_uptodate(self, packages, options): + # type: (List[Distribution], Values) -> List[Distribution] return [ dist for dist in self.iter_packages_latest_infos(packages, options) if dist.latest_version == dist.parsed_version ] def get_not_required(self, packages, options): - dep_keys = set() + # type: (List[Distribution], Values) -> List[Distribution] + dep_keys = set() # type: Set[Distribution] for dist in packages: dep_keys.update(requirement.key for requirement in dist.requires()) - return {pkg for pkg in packages if pkg.key not in dep_keys} + + # Create a set to remove duplicate packages, and cast it to a list + # to keep the return type consistent with get_outdated and + # get_uptodate + return list({pkg for pkg in packages if pkg.key not in dep_keys}) def iter_packages_latest_infos(self, packages, options): + # type: (List[Distribution], Values) -> Distribution with self._build_session(options) as session: finder = self._build_package_finder(options, session) @@ -209,6 +227,7 @@ def iter_packages_latest_infos(self, packages, options): yield dist def output_package_listing(self, packages, options): + # type: (List[Distribution], Values) -> None packages = sorted( packages, key=lambda dist: dist.project_name.lower(), @@ -227,6 +246,7 @@ def output_package_listing(self, packages, options): write_output(format_for_json(packages, options)) def output_package_listing_columns(self, data, header): + # type: (List[List[Any]], List[str]) -> None # insert the header first: we need to know the size of column names if len(data) > 0: data.insert(0, header) @@ -242,6 +262,7 @@ def output_package_listing_columns(self, data, header): def format_for_columns(pkgs, options): + # type: (List[Distribution], Values) -> Tuple[List[List[str]], List[str]] """ Convert the package data into something usable by output_package_listing_columns. @@ -279,6 +300,7 @@ def format_for_columns(pkgs, options): def format_for_json(packages, options): + # type: (List[Distribution], Values) -> str data = [] for dist in packages: info = { diff --git a/src/pip/_internal/commands/uninstall.py b/src/pip/_internal/commands/uninstall.py index 5db4fb46721..d7f96eeb060 100644 --- a/src/pip/_internal/commands/uninstall.py +++ b/src/pip/_internal/commands/uninstall.py @@ -1,12 +1,10 @@ -# The following comment should be removed at some point in the future. -# mypy: disallow-untyped-defs=False - from __future__ import absolute_import from pip._vendor.packaging.utils import canonicalize_name from pip._internal.cli.base_command import Command from pip._internal.cli.req_command import SessionCommandMixin +from pip._internal.cli.status_codes import SUCCESS from pip._internal.exceptions import InstallationError from pip._internal.req import parse_requirements from pip._internal.req.constructors import ( @@ -14,6 +12,11 @@ install_req_from_parsed_requirement, ) from pip._internal.utils.misc import protect_pip_from_modification_on_windows +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import Any, List class UninstallCommand(Command, SessionCommandMixin): @@ -32,6 +35,7 @@ class UninstallCommand(Command, SessionCommandMixin): %prog [options] -r ...""" def __init__(self, *args, **kw): + # type: (*Any, **Any) -> None super(UninstallCommand, self).__init__(*args, **kw) self.cmd_opts.add_option( '-r', '--requirement', @@ -51,6 +55,7 @@ def __init__(self, *args, **kw): self.parser.insert_option_group(0, self.cmd_opts) def run(self, options, args): + # type: (Values, List[Any]) -> int session = self.get_default_session(options) reqs_to_uninstall = {} @@ -87,3 +92,5 @@ def run(self, options, args): ) if uninstall_pathset: uninstall_pathset.commit() + + return SUCCESS From 52f30a1c46dcd9bb80c3b9e57eb93b97ee044c1a Mon Sep 17 00:00:00 2001 From: Devesh Kumar Singh Date: Tue, 14 Apr 2020 16:44:41 +0530 Subject: [PATCH 2/3] Add type for latest_info and fix type for iter_packages_latest_infos --- src/pip/_internal/commands/list.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pip/_internal/commands/list.py b/src/pip/_internal/commands/list.py index 7a0de088da3..4d68af1f240 100644 --- a/src/pip/_internal/commands/list.py +++ b/src/pip/_internal/commands/list.py @@ -25,7 +25,7 @@ if MYPY_CHECK_RUNNING: from optparse import Values - from typing import Any, List, Set, Tuple + from typing import Any, List, Set, Tuple, Iterator from pip._internal.network.session import PipSession from pip._vendor.pkg_resources import Distribution @@ -199,11 +199,12 @@ def get_not_required(self, packages, options): return list({pkg for pkg in packages if pkg.key not in dep_keys}) def iter_packages_latest_infos(self, packages, options): - # type: (List[Distribution], Values) -> Distribution + # type: (List[Distribution], Values) -> Iterator[Distribution] with self._build_session(options) as session: finder = self._build_package_finder(options, session) def latest_info(dist): + # type: (Distribution) -> Distribution typ = 'unknown' all_candidates = finder.find_all_candidates(dist.key) if not options.pre: From 2b6113797d8ce278c4329e5677de8f586cd40d0c Mon Sep 17 00:00:00 2001 From: Devesh Kumar Singh Date: Mon, 20 Apr 2020 03:29:47 +0530 Subject: [PATCH 3/3] Remove Any type from run function --- src/pip/_internal/commands/help.py | 4 ++-- src/pip/_internal/commands/list.py | 4 ++-- src/pip/_internal/commands/uninstall.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pip/_internal/commands/help.py b/src/pip/_internal/commands/help.py index ecd2b4737e3..a2edc29897f 100644 --- a/src/pip/_internal/commands/help.py +++ b/src/pip/_internal/commands/help.py @@ -6,7 +6,7 @@ from pip._internal.utils.typing import MYPY_CHECK_RUNNING if MYPY_CHECK_RUNNING: - from typing import List, Any + from typing import List from optparse import Values @@ -18,7 +18,7 @@ class HelpCommand(Command): ignore_require_venv = True def run(self, options, args): - # type: (Values, List[Any]) -> int + # type: (Values, List[str]) -> int from pip._internal.commands import ( commands_dict, create_command, get_similar_commands, ) diff --git a/src/pip/_internal/commands/list.py b/src/pip/_internal/commands/list.py index 4d68af1f240..81612403d5e 100644 --- a/src/pip/_internal/commands/list.py +++ b/src/pip/_internal/commands/list.py @@ -143,7 +143,7 @@ def _build_package_finder(self, options, session): ) def run(self, options, args): - # type: (Values, List[Any]) -> int + # type: (Values, List[str]) -> int if options.outdated and options.uptodate: raise CommandError( "Options --outdated and --uptodate cannot be combined.") @@ -261,7 +261,7 @@ def output_package_listing(self, packages, options): write_output(format_for_json(packages, options)) def output_package_listing_columns(self, data, header): - # type: (List[List[Any]], List[str]) -> None + # type: (List[List[str]], List[str]) -> None # insert the header first: we need to know the size of column names if len(data) > 0: data.insert(0, header) diff --git a/src/pip/_internal/commands/uninstall.py b/src/pip/_internal/commands/uninstall.py index d7f96eeb060..0542e78c79c 100644 --- a/src/pip/_internal/commands/uninstall.py +++ b/src/pip/_internal/commands/uninstall.py @@ -55,7 +55,7 @@ def __init__(self, *args, **kw): self.parser.insert_option_group(0, self.cmd_opts) def run(self, options, args): - # type: (Values, List[Any]) -> int + # type: (Values, List[str]) -> int session = self.get_default_session(options) reqs_to_uninstall = {}