@@ -149,10 +149,7 @@ class MypyDistConf(NamedTuple):
149
149
# disallow_untyped_defs = true
150
150
151
151
152
- def add_configuration (configurations , seen_dist_configs , distribution ):
153
- if distribution in seen_dist_configs :
154
- return
155
-
152
+ def add_configuration (configurations : list [MypyDistConf ], distribution : str ) -> None :
156
153
with open (os .path .join ("stubs" , distribution , "METADATA.toml" )) as f :
157
154
data = dict (tomli .loads (f .read ()))
158
155
@@ -173,7 +170,6 @@ def add_configuration(configurations, seen_dist_configs, distribution):
173
170
assert isinstance (values , dict ), "values should be a section"
174
171
175
172
configurations .append (MypyDistConf (module_name , values .copy ()))
176
- seen_dist_configs .add (distribution )
177
173
178
174
179
175
def run_mypy (args , configurations , major , minor , files , * , custom_typeshed = False ):
@@ -225,6 +221,75 @@ def run_mypy(args, configurations, major, minor, files, *, custom_typeshed=False
225
221
return 0
226
222
227
223
224
+ def read_dependencies (distribution : str ) -> list [str ]:
225
+ with open (os .path .join ("stubs" , distribution , "METADATA.toml" )) as f :
226
+ data = dict (tomli .loads (f .read ()))
227
+ requires = data .get ("requires" , [])
228
+ assert isinstance (requires , list )
229
+ dependencies = []
230
+ for dependency in requires :
231
+ assert isinstance (dependency , str )
232
+ assert dependency .startswith ("types-" )
233
+ dependencies .append (dependency [6 :])
234
+ return dependencies
235
+
236
+
237
+ def add_third_party_files (
238
+ distribution : str ,
239
+ major : int ,
240
+ files : list [str ],
241
+ args ,
242
+ exclude_list : re .Pattern [str ],
243
+ configurations : list [MypyDistConf ],
244
+ seen_dists : set [str ],
245
+ ) -> None :
246
+ if distribution in seen_dists :
247
+ return
248
+ seen_dists .add (distribution )
249
+
250
+ dependencies = read_dependencies (distribution )
251
+ for dependency in dependencies :
252
+ add_third_party_files (dependency , major , files , args , exclude_list , configurations , seen_dists )
253
+
254
+ if major == 2 and os .path .isdir (os .path .join ("stubs" , distribution , "@python2" )):
255
+ root = os .path .join ("stubs" , distribution , "@python2" )
256
+ else :
257
+ root = os .path .join ("stubs" , distribution )
258
+ for name in os .listdir (root ):
259
+ if name == "@python2" :
260
+ continue
261
+ mod , _ = os .path .splitext (name )
262
+ if mod .startswith ("." ):
263
+ continue
264
+ add_files (files , set (), root , name , args , exclude_list )
265
+ add_configuration (configurations , distribution )
266
+
267
+
268
+ def test_third_party_distribution (
269
+ distribution : str , major : int , minor : int , args , exclude_list : re .Pattern [str ]
270
+ ) -> tuple [int , int ]:
271
+ """Test the stubs of a third-party distribution.
272
+
273
+ Return a tuple, where the first element indicates mypy's return code
274
+ and the second element is the number of checked files.
275
+ """
276
+
277
+ print (f"testing { distribution } with Python { major } .{ minor } ..." )
278
+
279
+ files : list [str ] = []
280
+ configurations : list [MypyDistConf ] = []
281
+ seen_dists : set [str ] = set ()
282
+ add_third_party_files (distribution , major , files , args , exclude_list , configurations , seen_dists )
283
+
284
+ if not files :
285
+ print ("--- no files found ---" )
286
+ sys .exit (1 )
287
+
288
+ # TODO: remove custom_typeshed after mypy 0.920 is released
289
+ code = run_mypy (args , configurations , major , minor , files , custom_typeshed = True )
290
+ return code , len (files )
291
+
292
+
228
293
def main ():
229
294
args = parser .parse_args ()
230
295
@@ -239,11 +304,9 @@ def main():
239
304
sys .exit (1 )
240
305
241
306
code = 0
242
- runs = 0
307
+ files_checked = 0
243
308
for major , minor in versions :
244
309
seen = {"__builtin__" , "builtins" , "typing" } # Always ignore these.
245
- configurations = []
246
- seen_dist_configs = set ()
247
310
248
311
# Test standard library files.
249
312
files = []
@@ -265,40 +328,26 @@ def main():
265
328
add_files (files , seen , root , name , args , exclude_list )
266
329
267
330
if files :
268
- this_code = run_mypy (args , configurations , major , minor , files , custom_typeshed = True )
331
+ this_code = run_mypy (args , [] , major , minor , files , custom_typeshed = True )
269
332
code = max (code , this_code )
270
- runs += 1
333
+ files_checked += len ( files )
271
334
272
335
# Test files of all third party distributions.
273
- files = []
274
- for distribution in os .listdir ("stubs" ):
336
+ for distribution in sorted (os .listdir ("stubs" )):
275
337
if not is_supported (distribution , major ):
276
338
continue
277
- if major == 2 and os .path .isdir (os .path .join ("stubs" , distribution , "@python2" )):
278
- root = os .path .join ("stubs" , distribution , "@python2" )
279
- else :
280
- root = os .path .join ("stubs" , distribution )
281
- for name in os .listdir (root ):
282
- if name == "@python2" :
283
- continue
284
- mod , _ = os .path .splitext (name )
285
- if mod in seen or mod .startswith ("." ):
286
- continue
287
- add_files (files , seen , root , name , args , exclude_list )
288
- add_configuration (configurations , seen_dist_configs , distribution )
289
339
290
- if files :
291
- # TODO: remove custom_typeshed after mypy 0.920 is released
292
- this_code = run_mypy (args , configurations , major , minor , files , custom_typeshed = True )
340
+ this_code , checked = test_third_party_distribution (distribution , major , minor , args , exclude_list )
293
341
code = max (code , this_code )
294
- runs += 1
342
+ files_checked += checked
295
343
296
344
if code :
297
- print ("--- exit status" , code , " ---" )
345
+ print (f "--- exit status { code } , { files_checked } files checked ---" )
298
346
sys .exit (code )
299
- if not runs :
347
+ if not files_checked :
300
348
print ("--- nothing to do; exit 1 ---" )
301
349
sys .exit (1 )
350
+ print (f"--- success, { files_checked } files checked ---" )
302
351
303
352
304
353
if __name__ == "__main__" :
0 commit comments