예제 #1
0
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)
예제 #2
0
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)
예제 #5
0
    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