Skip to content

Commit 4bb38dd

Browse files
Zain Dana Harperclaude
authored andcommitted
Raise ModuleNotPresent for absent modules in direct-import queries
find_modules_that_directly_import silently returned an empty set (and the underlying Rust call panics) for a module not in the graph, and find_modules_directly_imported_by had no guard at all. Apply the existing ModuleNotPresent guard pattern used by squash_module/is_module_squashed to both, add docstrings, and cover with regression tests. Fixes #113. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 5287b3d commit 4bb38dd

3 files changed

Lines changed: 37 additions & 5 deletions

File tree

CHANGELOG.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ latest
1010
* Tweak Just commands for running version-specific Python tests.
1111
* Remove `typing-extensions` as a dependency.
1212
* Make package FIPS compatible by marking blake2 hashing with `usedforsecurity=False`.
13+
* Raise `ModuleNotPresent` instead of an unclear error when `find_modules_that_directly_import` or
14+
`find_modules_directly_imported_by` is called with a module that is not in the graph.
15+
(https://github.com/python-grimp/grimp/issues/113)
1316

1417
3.14 (2025-12-10)
1518
-----------------

src/grimp/application/graph.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,13 +217,26 @@ def direct_import_exists(
217217
)
218218

219219
def find_modules_directly_imported_by(self, module: str) -> set[str]:
220+
"""
221+
Find all modules that are directly imported by the supplied module.
222+
223+
If the module is not present in the graph, grimp.exceptions.ModuleNotPresent will be raised.
224+
"""
225+
if not self._rustgraph.contains_module(module):
226+
msg = f'"{module}" not present in the graph.'
227+
raise ModuleNotPresent(msg)
220228
return self._rustgraph.find_modules_directly_imported_by(module)
221229

222230
def find_modules_that_directly_import(self, module: str) -> set[str]:
223-
if self._rustgraph.contains_module(module):
224-
# TODO panics if module isn't in modules.
225-
return self._rustgraph.find_modules_that_directly_import(module)
226-
return set()
231+
"""
232+
Find all modules that directly import the supplied module.
233+
234+
If the module is not present in the graph, grimp.exceptions.ModuleNotPresent will be raised.
235+
"""
236+
if not self._rustgraph.contains_module(module):
237+
msg = f'"{module}" not present in the graph.'
238+
raise ModuleNotPresent(msg)
239+
return self._rustgraph.find_modules_that_directly_import(module)
227240

228241
def get_import_details(self, *, importer: str, imported: str) -> list[DetailedImport]:
229242
"""

tests/unit/application/graph/test_direct_imports.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import pytest
44

55
from grimp.application.graph import ImportGraph
6-
from grimp.exceptions import InvalidImportExpression
6+
from grimp.exceptions import InvalidImportExpression, ModuleNotPresent
77

88

99
def test_find_modules_directly_imported_by():
@@ -34,6 +34,22 @@ def test_find_modules_that_directly_import():
3434
assert {a, f} == graph.find_modules_that_directly_import("bar")
3535

3636

37+
def test_find_modules_directly_imported_by_raises_module_not_present():
38+
graph = ImportGraph()
39+
graph.add_module("foo")
40+
41+
with pytest.raises(ModuleNotPresent, match=re.escape('"bar" not present in the graph.')):
42+
graph.find_modules_directly_imported_by("bar")
43+
44+
45+
def test_find_modules_that_directly_import_raises_module_not_present():
46+
graph = ImportGraph()
47+
graph.add_module("foo")
48+
49+
with pytest.raises(ModuleNotPresent, match=re.escape('"bar" not present in the graph.')):
50+
graph.find_modules_that_directly_import("bar")
51+
52+
3753
@pytest.mark.parametrize(
3854
"importer, imported, as_packages, expected_result",
3955
(

0 commit comments

Comments
 (0)