|
31 | 31 | from importlib import import_module |
32 | 32 | from importlib.abc import MetaPathFinder |
33 | 33 | from itertools import starmap |
34 | | -from typing import List, Mapping, Optional, cast |
| 34 | +from typing import Iterable, Iterator, List, Mapping, Optional, cast |
35 | 35 |
|
36 | 36 |
|
37 | 37 | __all__ = [ |
@@ -961,10 +961,32 @@ def _top_level_declared(dist): |
961 | 961 | return (dist.read_text('top_level.txt') or '').split() |
962 | 962 |
|
963 | 963 |
|
| 964 | +def _walk_dirs(package_paths: Iterable[PackagePath]) -> Iterator[PackagePath]: |
| 965 | + for package_path in package_paths: |
| 966 | + |
| 967 | + def make_file(name): |
| 968 | + result = PackagePath(name) |
| 969 | + result.hash = None |
| 970 | + result.size = None |
| 971 | + result.dist = package_path.dist |
| 972 | + return result |
| 973 | + |
| 974 | + real_path = package_path.locate() |
| 975 | + real_sitedir = package_path.dist.locate_file("") # type: ignore |
| 976 | + if real_path.is_dir() and real_path.is_symlink(): |
| 977 | + # .files only mentions symlink, we must recurse into it ourselves: |
| 978 | + for root, dirs, files in os.walk(real_path): |
| 979 | + for filename in files: |
| 980 | + real_file = pathlib.Path(root, filename) |
| 981 | + yield make_file(real_file.relative_to(real_sitedir)) |
| 982 | + else: |
| 983 | + yield package_path |
| 984 | + |
| 985 | + |
964 | 986 | def _top_level_inferred(dist): |
965 | 987 | opt_names = { |
966 | 988 | f.parts[0] if len(f.parts) > 1 else inspect.getmodulename(f) |
967 | | - for f in always_iterable(dist.files) |
| 989 | + for f in _walk_dirs(always_iterable(dist.files)) |
968 | 990 | } |
969 | 991 |
|
970 | 992 | @pass_none |
|
0 commit comments