1
- # The following comment should be removed at some point in the future.
2
- # mypy: disallow-untyped-defs=False
3
-
4
1
from __future__ import absolute_import
5
2
6
3
import json
10
7
11
8
from pip ._internal .cli import cmdoptions
12
9
from pip ._internal .cli .req_command import IndexGroupCommand
10
+ from pip ._internal .cli .status_codes import SUCCESS
13
11
from pip ._internal .exceptions import CommandError
14
12
from pip ._internal .index .package_finder import PackageFinder
15
13
from pip ._internal .models .selection_prefs import SelectionPreferences
21
19
write_output ,
22
20
)
23
21
from pip ._internal .utils .packaging import get_installer
22
+ from pip ._internal .utils .typing import MYPY_CHECK_RUNNING
23
+
24
+ if MYPY_CHECK_RUNNING :
25
+ from optparse import Values
26
+ from typing import Any , List , Set , Tuple , Iterator
27
+
28
+ from pip ._internal .network .session import PipSession
29
+ from pip ._vendor .pkg_resources import Distribution
24
30
25
31
logger = logging .getLogger (__name__ )
26
32
@@ -36,6 +42,7 @@ class ListCommand(IndexGroupCommand):
36
42
%prog [options]"""
37
43
38
44
def __init__ (self , * args , ** kw ):
45
+ # type: (*Any, **Any) -> None
39
46
super (ListCommand , self ).__init__ (* args , ** kw )
40
47
41
48
cmd_opts = self .cmd_opts
@@ -116,6 +123,7 @@ def __init__(self, *args, **kw):
116
123
self .parser .insert_option_group (0 , cmd_opts )
117
124
118
125
def _build_package_finder (self , options , session ):
126
+ # type: (Values, PipSession) -> PackageFinder
119
127
"""
120
128
Create a package finder appropriate to this list command.
121
129
"""
@@ -133,6 +141,7 @@ def _build_package_finder(self, options, session):
133
141
)
134
142
135
143
def run (self , options , args ):
144
+ # type: (Values, List[str]) -> int
136
145
if options .outdated and options .uptodate :
137
146
raise CommandError (
138
147
"Options --outdated and --uptodate cannot be combined." )
@@ -160,30 +169,40 @@ def run(self, options, args):
160
169
packages = self .get_uptodate (packages , options )
161
170
162
171
self .output_package_listing (packages , options )
172
+ return SUCCESS
163
173
164
174
def get_outdated (self , packages , options ):
175
+ # type: (List[Distribution], Values) -> List[Distribution]
165
176
return [
166
177
dist for dist in self .iter_packages_latest_infos (packages , options )
167
178
if dist .latest_version > dist .parsed_version
168
179
]
169
180
170
181
def get_uptodate (self , packages , options ):
182
+ # type: (List[Distribution], Values) -> List[Distribution]
171
183
return [
172
184
dist for dist in self .iter_packages_latest_infos (packages , options )
173
185
if dist .latest_version == dist .parsed_version
174
186
]
175
187
176
188
def get_not_required (self , packages , options ):
177
- dep_keys = set ()
189
+ # type: (List[Distribution], Values) -> List[Distribution]
190
+ dep_keys = set () # type: Set[Distribution]
178
191
for dist in packages :
179
192
dep_keys .update (requirement .key for requirement in dist .requires ())
180
- return {pkg for pkg in packages if pkg .key not in dep_keys }
193
+
194
+ # Create a set to remove duplicate packages, and cast it to a list
195
+ # to keep the return type consistent with get_outdated and
196
+ # get_uptodate
197
+ return list ({pkg for pkg in packages if pkg .key not in dep_keys })
181
198
182
199
def iter_packages_latest_infos (self , packages , options ):
200
+ # type: (List[Distribution], Values) -> Iterator[Distribution]
183
201
with self ._build_session (options ) as session :
184
202
finder = self ._build_package_finder (options , session )
185
203
186
204
def latest_info (dist ):
205
+ # type: (Distribution) -> Distribution
187
206
typ = 'unknown'
188
207
all_candidates = finder .find_all_candidates (dist .key )
189
208
if not options .pre :
@@ -213,6 +232,7 @@ def latest_info(dist):
213
232
yield dist
214
233
215
234
def output_package_listing (self , packages , options ):
235
+ # type: (List[Distribution], Values) -> None
216
236
packages = sorted (
217
237
packages ,
218
238
key = lambda dist : dist .project_name .lower (),
@@ -231,6 +251,7 @@ def output_package_listing(self, packages, options):
231
251
write_output (format_for_json (packages , options ))
232
252
233
253
def output_package_listing_columns (self , data , header ):
254
+ # type: (List[List[str]], List[str]) -> None
234
255
# insert the header first: we need to know the size of column names
235
256
if len (data ) > 0 :
236
257
data .insert (0 , header )
@@ -246,6 +267,7 @@ def output_package_listing_columns(self, data, header):
246
267
247
268
248
269
def format_for_columns (pkgs , options ):
270
+ # type: (List[Distribution], Values) -> Tuple[List[List[str]], List[str]]
249
271
"""
250
272
Convert the package data into something usable
251
273
by output_package_listing_columns.
@@ -283,6 +305,7 @@ def format_for_columns(pkgs, options):
283
305
284
306
285
307
def format_for_json (packages , options ):
308
+ # type: (List[Distribution], Values) -> str
286
309
data = []
287
310
for dist in packages :
288
311
info = {
0 commit comments