@@ -345,6 +345,61 @@ def _validate_import_names(
345345 f"Import names found in both import-names and import-namespaces: { ', ' .join (duplicates )} "
346346 )
347347
348+ cls ._validate_shortest_import_names (
349+ import_names = import_names ,
350+ import_namespaces = import_namespaces ,
351+ result = result ,
352+ )
353+
354+ @classmethod
355+ def _validate_shortest_import_names (
356+ cls ,
357+ import_names : set [str ],
358+ import_namespaces : set [str ],
359+ result : dict [str , list [str ]],
360+ ) -> None :
361+ """
362+ Ensure import names and namespaces include their parent packages.
363+
364+ For entries in `import-names`, any parent package may be listed in
365+ either `import-names` or `import-namespaces`. For entries in
366+ `import-namespaces`, any parent package must be listed in
367+ `import-namespaces` only.
368+ """
369+ for import_name in import_names :
370+ if "." in import_name :
371+ parent : str | None = import_name .rsplit ("." , maxsplit = 1 )[0 ]
372+
373+ while parent :
374+ if parent not in import_names and parent not in import_namespaces :
375+ base = parent .split ("." , maxsplit = 1 )[0 ]
376+ result ["warnings" ].append (
377+ f"Import name '{ import_name } ' should have all its parents up to '{ base } '"
378+ f" included in import-names or import-namespaces."
379+ )
380+ break
381+
382+ parent = (
383+ parent .rsplit ("." , maxsplit = 1 )[0 ] if "." in parent else None
384+ )
385+
386+ for import_namespace in import_namespaces :
387+ if "." in import_namespace :
388+ parent = import_namespace .rsplit ("." , maxsplit = 1 )[0 ]
389+
390+ while parent :
391+ if parent not in import_namespaces :
392+ base = parent .split ("." , maxsplit = 1 )[0 ]
393+ result ["warnings" ].append (
394+ f"Import namespace '{ import_namespace } ' should have all its parents up to '{ base } '"
395+ f" included in import-namespaces."
396+ )
397+ break
398+
399+ parent = (
400+ parent .rsplit ("." , maxsplit = 1 )[0 ] if "." in parent else None
401+ )
402+
348403 @classmethod
349404 def _configure_entry_points (
350405 cls ,
0 commit comments