Skip to content

Commit 3e5bb04

Browse files
committed
Don't drill down into invalid identifier directories
This stops us from discovering Python modules that aren't importable.
1 parent 2ac244b commit 3e5bb04

2 files changed

Lines changed: 56 additions & 3 deletions

File tree

src/grimp/adaptors/modulefinder.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def _get_python_files_and_namespace_dirs_inside_package(
7474
# a Python file somewhere within it.
7575
candidate_namespace_dirs.append(dirpath)
7676

77-
# Don't include hidden directories.
77+
# Don't include directories that aren't valid identifiers.
7878
dirs_to_remove = [d for d in dirs if self._should_ignore_dir(d)]
7979
for d in dirs_to_remove:
8080
dirs.remove(d)
@@ -91,8 +91,7 @@ def _is_in_portion(self, directory: str, portions: Set[str]) -> bool:
9191

9292
def _should_ignore_dir(self, directory: str) -> bool:
9393
# TODO: make this configurable.
94-
# Skip adding directories that are hidden.
95-
return directory.startswith(".")
94+
return not directory.isidentifier()
9695

9796
def _determine_namespace_dirs(
9897
self, candidates: Iterable[str], python_files: Iterable[str]

tests/unit/adaptors/test_modulefinder.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,60 @@ def test_ignores_orphaned_python_files():
181181
)
182182

183183

184+
def test_ignores_invalid_identifier_directories():
185+
# Python files in directories that don't contain an __init__.py should not be discovered.
186+
module_finder = ModuleFinder()
187+
188+
file_system = FakeFileSystem(
189+
contents="""
190+
/path/to/namespacepackage/
191+
foo/
192+
valid_underscore_name/
193+
__init__.py
194+
mod.py
195+
invalid-hyphenated-name/
196+
__init__.py
197+
mod.py
198+
1nvalid-number-prefixed/
199+
__init__.py
200+
mod.py
201+
valid_non_àscii/
202+
__init__.py
203+
mod.py
204+
invalid_non_😃scii/
205+
__init__.py
206+
mod.py
207+
bar/
208+
__init__.py
209+
mod.py
210+
"""
211+
)
212+
213+
result = module_finder.find_package(
214+
package_name="namespacepackage",
215+
package_directory="/path/to/namespacepackage",
216+
file_system=file_system,
217+
)
218+
219+
module_files = {
220+
ModuleFile(module=Module(name), mtime=DEFAULT_MTIME)
221+
for name in {
222+
"namespacepackage.foo.valid_underscore_name",
223+
"namespacepackage.foo.valid_underscore_name.mod",
224+
"namespacepackage.foo.valid_non_àscii",
225+
"namespacepackage.foo.valid_non_àscii.mod",
226+
"namespacepackage.bar",
227+
"namespacepackage.bar.mod",
228+
}
229+
}
230+
assert result == FoundPackage(
231+
name="namespacepackage",
232+
directory="/path/to/namespacepackage",
233+
module_files=module_files,
234+
namespace_packages=frozenset({"namespacepackage", "namespacepackage.foo"}),
235+
)
236+
237+
184238
@pytest.mark.parametrize(
185239
"extension, should_warn",
186240
(

0 commit comments

Comments
 (0)