From 7d71289f4efd00ffe8777efdd87c24869adaa735 Mon Sep 17 00:00:00 2001 From: nightcityblade Date: Sun, 11 Oct 2026 13:21:31 +0800 Subject: [PATCH 1/2] Allow valid targets alongside empty directories --- mypy/find_sources.py | 5 ++++- mypy/test/test_find_sources.py | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/mypy/find_sources.py b/mypy/find_sources.py index e1edebe90985b..3053e11e52d5e 100644 --- a/mypy/find_sources.py +++ b/mypy/find_sources.py @@ -38,6 +38,7 @@ def create_source_list( finder = SourceFinder(fscache, options) sources = [] + empty_dirs = [] for path in paths: path = os.path.normpath(path) if path.endswith(PY_EXTENSIONS): @@ -47,11 +48,13 @@ def create_source_list( elif fscache.isdir(path): sub_sources = finder.find_sources_in_dir(path) if not sub_sources and not allow_empty_dir: - raise InvalidSourceList(f"There are no .py[i] files in directory '{path}'") + empty_dirs.append(path) sources.extend(sub_sources) else: mod = os.path.basename(path) if options.scripts_are_modules else None sources.append(BuildSource(path, mod, None)) + if not sources and empty_dirs: + raise InvalidSourceList(f"There are no .py[i] files in directory '{empty_dirs[0]}'") return sources diff --git a/mypy/test/test_find_sources.py b/mypy/test/test_find_sources.py index 321f3405e9991..92ff9a76e0829 100644 --- a/mypy/test/test_find_sources.py +++ b/mypy/test/test_find_sources.py @@ -261,6 +261,14 @@ def test_find_sources_in_dir_namespace_multi_dir(self) -> None: finder = SourceFinder(FakeFSCache({"/a/pkg/a.py", "/b/pkg/b.py"}), options) assert find_sources_in_dir(finder, "/") == [("pkg.a", "/a"), ("pkg.b", "/b")] + def test_find_sources_with_empty_directory(self) -> None: + options = Options() + fscache = FakeFSCache({"/empty/README", "/src/a.py"}) + + assert find_sources(["/empty", "/src"], options, fscache) == [("a", "/src")] + with pytest.raises(InvalidSourceList, match=r"directory '.*[\\/]empty'"): + find_sources(["/empty"], options, fscache) + def test_find_sources_exclude(self) -> None: options = Options() options.namespace_packages = True From 8e3bd564341a0ccf5cc0ceba9a64b5f926471991 Mon Sep 17 00:00:00 2001 From: nightcityblade Date: Mon, 12 Oct 2026 23:10:13 +0800 Subject: [PATCH 2/2] List all empty source directories --- mypy/find_sources.py | 3 ++- mypy/test/test_find_sources.py | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/mypy/find_sources.py b/mypy/find_sources.py index 3053e11e52d5e..af4f7101038c9 100644 --- a/mypy/find_sources.py +++ b/mypy/find_sources.py @@ -54,7 +54,8 @@ def create_source_list( mod = os.path.basename(path) if options.scripts_are_modules else None sources.append(BuildSource(path, mod, None)) if not sources and empty_dirs: - raise InvalidSourceList(f"There are no .py[i] files in directory '{empty_dirs[0]}'") + empty_dirs_str = ", ".join(map(repr, empty_dirs)) + raise InvalidSourceList(f"There are no .py[i] files in directories: {empty_dirs_str}") return sources diff --git a/mypy/test/test_find_sources.py b/mypy/test/test_find_sources.py index 92ff9a76e0829..2236efc985ca3 100644 --- a/mypy/test/test_find_sources.py +++ b/mypy/test/test_find_sources.py @@ -263,11 +263,13 @@ def test_find_sources_in_dir_namespace_multi_dir(self) -> None: def test_find_sources_with_empty_directory(self) -> None: options = Options() - fscache = FakeFSCache({"/empty/README", "/src/a.py"}) + fscache = FakeFSCache({"/empty/README", "/other'empty/README", "/src/a.py"}) assert find_sources(["/empty", "/src"], options, fscache) == [("a", "/src")] - with pytest.raises(InvalidSourceList, match=r"directory '.*[\\/]empty'"): - find_sources(["/empty"], options, fscache) + with pytest.raises(InvalidSourceList, match="directories") as exc_info: + find_sources(["/empty", "/other'empty"], options, fscache) + assert repr(os.path.abspath("/empty")) in str(exc_info.value) + assert repr(os.path.abspath("/other'empty")) in str(exc_info.value) def test_find_sources_exclude(self) -> None: options = Options()