Iterates through all packages and sub-packages in the given list. This uses runtime imports (in another process) to find both Python and C modules. For Python packages we simply pass the __path__ attribute to pkgutil.walk_packages() to get the content of the package (all subpackages and
(
inspect: ModuleInspect, packages: list[str], verbose: bool = False
)
| 61 | |
| 62 | |
| 63 | def walk_packages( |
| 64 | inspect: ModuleInspect, packages: list[str], verbose: bool = False |
| 65 | ) -> Iterator[str]: |
| 66 | """Iterates through all packages and sub-packages in the given list. |
| 67 | |
| 68 | This uses runtime imports (in another process) to find both Python and C modules. |
| 69 | For Python packages we simply pass the __path__ attribute to pkgutil.walk_packages() to |
| 70 | get the content of the package (all subpackages and modules). However, packages in C |
| 71 | extensions do not have this attribute, so we have to roll out our own logic: recursively |
| 72 | find all modules imported in the package that have matching names. |
| 73 | """ |
| 74 | for package_name in packages: |
| 75 | if package_name in NOT_IMPORTABLE_MODULES: |
| 76 | print(f"{package_name}: Skipped (blacklisted)") |
| 77 | continue |
| 78 | if verbose: |
| 79 | print(f"Trying to import {package_name!r} for runtime introspection") |
| 80 | try: |
| 81 | prop = inspect.get_package_properties(package_name) |
| 82 | except InspectError: |
| 83 | if verbose: |
| 84 | tb = traceback.format_exc() |
| 85 | sys.stderr.write(tb) |
| 86 | report_missing(package_name) |
| 87 | continue |
| 88 | yield prop.name |
| 89 | if prop.is_c_module: |
| 90 | # Recursively iterate through the subpackages |
| 91 | yield from walk_packages(inspect, prop.subpackages, verbose) |
| 92 | else: |
| 93 | yield from prop.subpackages |
| 94 | |
| 95 | |
| 96 | def find_module_path_using_sys_path(module: str, sys_path: list[str]) -> str | None: |
searching dependent graphs…