def _pyi_pkgutil_iter_modules(path=None, prefix=''): # Use original implementation to discover on-filesystem # modules (binary extensions in regular builds, or both binary # extensions and compiled pyc modules in noarchive debug builds) yield from _orig_pkgutil_iter_modules(path, prefix) # Find the instance of PyInstaller's FrozenImporter for importer in pkgutil.iter_importers(): if isinstance(importer, FrozenImporter): break else: return if not path: # Search for all top-level packages/modules. These will have # no dots in their entry names for entry in importer.toc: if entry.count('.') != 0: continue is_pkg = importer.is_package(entry) yield pkgutil.ModuleInfo(importer, prefix + entry, is_pkg) else: # Declare SYS_PREFIX locally, to avoid clash with eponymous # global symbol from pyi_rth_pkgutil hook. SYS_PREFIX = sys._MEIPASS + os.path.sep SYS_PREFIXLEN = len(SYS_PREFIX) # Only single path is supported, and it must start with # sys._MEIPASS pkg_path = os.path.normpath(path[0]) # Remove this for compatibility with pluginpath # assert pkg_path.startswith(SYS_PREFIX) # Construct package prefix from path... pkg_prefix = pkg_path[SYS_PREFIXLEN:] pkg_prefix = pkg_prefix.replace(os.path.sep, '.') # ... and ensure it ends with a dot (so we can directly filter # out the package itself) if not pkg_prefix.endswith('.'): pkg_prefix += '.' pkg_prefix_len = len(pkg_prefix) for entry in importer.toc: if not entry.startswith(pkg_prefix): continue name = entry[pkg_prefix_len:] if name.count('.') != 0: continue is_pkg = importer.is_package(entry) yield pkgutil.ModuleInfo(importer, prefix + name, is_pkg)
def parse_specs(modules: Sequence[Union[Path, str]]) -> dict[str, None]: """ This function processes a list of module specifications and returns the list of module names, including all submodules, that should be processed by pdoc. """ module_index: dict[str, None] = {} for spec in modules: modname = parse_spec(spec) try: with mock_some_common_side_effects(): modspec = importlib.util.find_spec(modname) if modspec is None: raise ModuleNotFoundError(modname) except AnyException: warnings.warn( f"Cannot find spec for {modname} (from {spec}):\n{traceback.format_exc()}", RuntimeWarning, stacklevel=2, ) else: mod_info = pkgutil.ModuleInfo( None, # type: ignore name=modname, ispkg=bool(modspec.submodule_search_locations), ) for m in walk_packages2([mod_info]): module_index[m.name] = None if not module_index: raise ValueError( f"Module not found: {', '.join(str(x) for x in modules)}.") return module_index
def _build_module_info(name): loader = pkgutil.get_loader(name) path = os.path.dirname(loader.path) return pkgutil.ModuleInfo( pkgutil.get_importer(path), name, loader.is_package(name), )
def iter_packages(path, prefix, onerror=None): """ Find packages recursively, including PEP420 packages """ yield from pkgutil.walk_packages(path, prefix, onerror) namespace_packages = {} for path_root in path: for sub_path in Path(path_root).iterdir(): if sub_path.is_dir() and not (sub_path / '__init__.py').exists(): ns_paths = namespace_packages.setdefault( prefix + sub_path.name, []) ns_paths.append(str(sub_path)) for name, paths in namespace_packages.items(): yield pkgutil.ModuleInfo(None, name, True) yield from iter_packages(paths, name + '.', onerror)
def __init__(self, pkg_dir): pkg_dir = Path(pkg_dir) packages = find_packages(where=pkg_dir.parent.as_posix()) package_infos = [ (p, (pkg_dir.parent / p.replace(".", os.path.sep)).as_posix()) for p in packages ] # Get the `__init__.py` # first_mod = next(pkgutil.iter_modules(["/tmp/pkg"])) # root_init_mod = first_mod.module_finder.find_module("__init__") self.fullnames_to_modules = OrderedDict() self.filenames_to_modules = OrderedDict() self.packages_to_modules = OrderedDict() self.packages_to_paths = OrderedDict() self.paths_to_packages = OrderedDict() self.fullnames_to_packages = OrderedDict() for package_name, package_path in package_infos: self.packages_to_paths[package_name] = Path(package_path) self.paths_to_packages[Path(package_path)] = package_name pkg_modinfos = [] for old_modinfo in pkgutil.iter_modules([package_path]): mod_fullname = f"{package_name}.{old_modinfo.name}" mod_filename = Path( old_modinfo.module_finder.find_module( old_modinfo.name).get_filename()) # This `ModuleInfo` uses the module's full name new_modinfo = pkgutil.ModuleInfo(old_modinfo.module_finder, mod_fullname, old_modinfo.ispkg) pkg_modinfos.append(new_modinfo) self.filenames_to_modules[mod_filename] = new_modinfo self.fullnames_to_modules[mod_fullname] = new_modinfo self.fullnames_to_packages[mod_fullname] = package_name self.packages_to_modules[package_name] = pkg_modinfos