Skip to content

Commit 2ce6850

Browse files
committed
Fix panic error when scanning imports of nonexistent namespace children
1 parent faab22b commit 2ce6850

3 files changed

Lines changed: 57 additions & 0 deletions

File tree

‎CHANGELOG.rst‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
Changelog
33
=========
44

5+
latest
6+
------
7+
8+
* Fix panic error when scanning imports of nonexistent namespace children
9+
(https://github.com/python-grimp/grimp/issues/308).
10+
511
3.15 (2026-07-03)
612
-----------------
713

‎rust/src/import_scanning.rs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,12 @@ fn _distill_external_module(
330330
while external_path_components[0] == internal_path_components[0] {
331331
external_namespace_components.push(external_path_components.remove(0));
332332
internal_path_components.remove(0);
333+
if internal_path_components.is_empty() {
334+
// The module name is a descendant of the found package, but isn't present
335+
// as a module file. If that's the case, don't add it to the graph, as it's
336+
// a missing module.
337+
return None;
338+
};
333339
}
334340
external_namespace_components.push(external_path_components[0]);
335341

‎tests/unit/application/test_scanning.py‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,51 @@ def test_t_string_syntax():
971971
}
972972

973973

974+
@pytest.mark.parametrize(
975+
"import_statement",
976+
(
977+
"from namespace.portion.nonexistent import something",
978+
"from .nonexistent import something",
979+
"from ..nonexistent import something",
980+
),
981+
)
982+
def test_missing_module_in_dotted_root_package_is_ignored(import_statement: str):
983+
"""
984+
When a dotted root package (namespace package) contains an import of a missing module
985+
within that same package, and include_external_packages=True, the Rust code should not
986+
panic with an index-out-of-bounds error.
987+
988+
Regression test for https://github.com/python-grimp/grimp/issues/308.
989+
"""
990+
module_to_scan = Module("namespace.portion.subpackage.importer")
991+
module_file_to_scan = _module_to_module_file(module_to_scan)
992+
all_modules = {
993+
Module("namespace.portion"),
994+
Module("namespace.portion.subpackage"),
995+
module_to_scan,
996+
}
997+
file_system = rust.FakeBasicFileSystem(
998+
content_map={"/path/to/namespace/portion/subpackage/importer.py": import_statement},
999+
)
1000+
found_packages = {
1001+
FoundPackage(
1002+
name="namespace.portion",
1003+
directory="/path/to/namespace/portion",
1004+
module_files=_modules_to_module_files(all_modules),
1005+
)
1006+
}
1007+
1008+
with override_settings(FILE_SYSTEM=file_system):
1009+
result = scanning.scan_imports(
1010+
{module_file_to_scan},
1011+
found_packages=found_packages,
1012+
include_external_packages=True,
1013+
exclude_type_checking_imports=False, # Required field, not relevant.
1014+
)
1015+
1016+
assert result == {module_file_to_scan: set()}
1017+
1018+
9741019
def _module_to_module_file(module: Module) -> ModuleFile:
9751020
some_mtime = 100933.4
9761021
return ModuleFile(module=module, mtime=some_mtime)

0 commit comments

Comments
 (0)