sizmailov / pybind11-stubgen

Generate stubs for python modules
Other
218 stars 44 forks source link

compatable for `ModuleStubsGenerator` #224

Closed bowen-xu closed 1 month ago

bowen-xu commented 1 month ago

Hi @sizmailov,

I switch from 0.16.2 to the latest version, but it raises errors, because I use the ModuleStubsGenerator class. I wonder how to do similar things with the latest version.

Here is my code:

from pybind11_stubgen import ModuleStubsGenerator
import os
import sys
import argparse
from pathlib import Path
import importlib

def list_modules(module_path: Path, package_path: Path):
    package_name = '.'+'.'.join(str(module_path).split('/'))
    package_path = package_path.absolute()
    sys.path.append(str(package_path.parent))
    module_path = os.path.dirname(importlib.import_module(
        package_name, str(package_path.stem)).__file__)
    modules = []
    for root, dirs, files in os.walk(module_path, topdown=True):
        for file in files:
            dirs[:] = [d for d in dirs if d not in ["build", "__pycache__"]] # exclude `build` directories, to avoid repeating .so files.
            if file.endswith(".so"):
                file = file.split('.')[0]
                module_name = os.path.splitext(os.path.relpath(os.path.join(
                    root, file), module_path))[0].replace(os.path.sep, ".")
                module_name = f"{package_name}.{module_name}"
                module = importlib.import_module(
                    module_name, str(package_path.stem))
                modules.append((module, module_name, root))
    return modules

parser = argparse.ArgumentParser()
parser.add_argument('-p', help='package path')
parser.add_argument('--root', help='module path')

args = parser.parse_args()
p = Path(args.p)
root = Path(args.root)

modules = list_modules(p, root)
for _module, module_name, module_path in modules:
    module_name: str
    module = ModuleStubsGenerator(_module)
    module.parse()
    module_name = module_name.split('.')[-1]
    with open(str(Path(module_path)/f"{module_name}.pyi"), 'w') as f:
        f.write("#\n# Automaticall generated file, do not edit!\n#\n\n")
        f.write("\n".join(module.to_lines()))
bowen-xu commented 1 month ago

Solved.

import os
import sys
import argparse
from pathlib import Path
import importlib

def list_modules(module_path: Path, package_path: Path):
    package_name = '.'+'.'.join(str(module_path).split('/'))
    package_path = package_path.absolute()
    sys.path.append(str(package_path.parent))
    module_path = os.path.dirname(importlib.import_module(
        package_name, str(package_path.stem)).__file__)
    modules = []
    for root, dirs, files in os.walk(module_path, topdown=True):
        for file in files:
            dirs[:] = [d for d in dirs if d not in ["build", "__pycache__"]] # exclude `build` directories, to avoid repeating .so files.
            if file.endswith(".so"):
                file = file.split('.')[0]
                module_name = os.path.splitext(os.path.relpath(os.path.join(
                    root, file), module_path))[0].replace(os.path.sep, ".")
                module_name = f"{package_name}.{module_name}"
                module = importlib.import_module(
                    module_name, str(package_path.stem))
                module_name = f"{str(package_path.stem)}{module_name}"
                modules.append((module, module_name, root))
    return modules

def stub(module_name: str):
    import logging
    from pybind11_stubgen import CLIArgs, stub_parser_from_args, Printer, to_output_and_subdir, run, Writer
    logging.basicConfig(
        level=logging.INFO,
        format="%(name)s - [%(levelname)7s] %(message)s",
    )
    args = CLIArgs(
        module_name=module_name,
        output_dir='./',
        stub_extension="pyi",
        # default ags:
        root_suffix=None,
        ignore_all_errors=False,
        ignore_invalid_identifiers=None,
        ignore_invalid_expressions=None,
        ignore_unresolved_names=None,
        exit_code=False,
        numpy_array_wrap_with_annotated=False,
        numpy_array_use_type_var=False,
        numpy_array_remove_parameters=False,
        enum_class_locations=[],
        print_safe_value_reprs=None,
        print_invalid_expressions_as_is=False,
        dry_run=False)

    parser = stub_parser_from_args(args)
    printer = Printer(invalid_expr_as_ellipses=not args.print_invalid_expressions_as_is)

    out_dir, sub_dir = to_output_and_subdir(
        output_dir=args.output_dir,
        module_name=args.module_name,
        root_suffix=args.root_suffix,
    )

    run(
        parser,
        printer,
        args.module_name,
        out_dir,
        sub_dir=sub_dir,
        dry_run=args.dry_run,
        writer=Writer(stub_ext=args.stub_extension),
    )

parser = argparse.ArgumentParser()
parser.add_argument('-p', help='package path')
parser.add_argument('--root', help='module path')

args = parser.parse_args()
p = Path(args.p)
root = Path(args.root)

modules = list_modules(p, root)
for _module, module_name, _module_path in modules:
    module_name: str
    stub(module_name)