From 8328e4697e03af00e3f140220524016737a6c4dc Mon Sep 17 00:00:00 2001 From: Varun Chawla Date: Sat, 7 Feb 2026 23:09:56 -0800 Subject: [PATCH] Add --include-vendored flag and warning for skipped vendor modules This change addresses the issue where stubgen silently skips directories named 'vendor', 'vendored', '_vendor', etc., even when they are legitimate user packages rather than vendored third-party code. Changes: - Added --include-vendored flag to allow generating stubs for vendored packages - Modified remove_blacklisted_modules() to print a warning message when skipping vendored modules (unless --quiet is specified) - Updated Options class to include the include_vendored parameter Now users who have legitimate packages named 'vendor' can: 1. Use --include-vendored flag to generate stubs for them 2. See a clear warning message when modules are being skipped Fixes #9599 --- mypy/stubgen.py | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/mypy/stubgen.py b/mypy/stubgen.py index 5d6149b97507a..2149d9fb5319a 100755 --- a/mypy/stubgen.py +++ b/mypy/stubgen.py @@ -214,6 +214,7 @@ def __init__( quiet: bool, export_less: bool, include_docstrings: bool, + include_vendored: bool, ) -> None: # See parse_options for descriptions of the flags. self.pyversion = pyversion @@ -234,6 +235,7 @@ def __init__( self.quiet = quiet self.export_less = export_less self.include_docstrings = include_docstrings + self.include_vendored = include_vendored class StubSource: @@ -1543,10 +1545,15 @@ def get_qualified_name(o: Expression) -> str: return ERROR_MARKER -def remove_blacklisted_modules(modules: list[StubSource]) -> list[StubSource]: - return [ - module for module in modules if module.path is None or not is_blacklisted_path(module.path) - ] +def remove_blacklisted_modules(modules: list[StubSource], quiet: bool = False) -> list[StubSource]: + """Remove blacklisted modules and optionally warn about them.""" + result = [] + for module in modules: + if module.path is None or not is_blacklisted_path(module.path): + result.append(module) + elif not quiet: + print(f"Skipping vendored module: {module.module}") + return result def split_pyc_from_py(modules: list[StubSource]) -> tuple[list[StubSource], list[StubSource]]: @@ -1595,7 +1602,8 @@ def collect_build_targets( py_modules = [StubSource(m.module, m.path) for m in source_list] c_modules = [] - py_modules = remove_blacklisted_modules(py_modules) + if not options.include_vendored: + py_modules = remove_blacklisted_modules(py_modules, options.quiet) pyc_mod, py_mod = split_pyc_from_py(py_modules) return py_mod, pyc_mod, c_modules @@ -1947,6 +1955,11 @@ def parse_options(args: list[str]) -> Options: action="store_true", help="include existing docstrings with the stubs", ) + parser.add_argument( + "--include-vendored", + action="store_true", + help="generate stubs for vendored packages (e.g., packages in 'vendor', '_vendor', etc.)", + ) parser.add_argument("-v", "--verbose", action="store_true", help="show more verbose messages") parser.add_argument("-q", "--quiet", action="store_true", help="show fewer messages") parser.add_argument( @@ -2033,6 +2046,7 @@ def parse_options(args: list[str]) -> Options: quiet=ns.quiet, export_less=ns.export_less, include_docstrings=ns.include_docstrings, + include_vendored=ns.include_vendored, )