Open neilmacintyre opened 10 months ago
Interesting issue!
As I understand it, what you're expecting to happen is that because Python executes the __init__.py
of parents when importing a module, Import Linter should treat those as imports too. Or to put it another way, any module implicitly imports its parent - e.g. src.module1.test
implicitly imports src.module1
.
This is - at the moment at least - by design. Import Linter (and, under the hood, Grimp) models the import graph based on explicit imports. So src.module1
is not a dependency of src.module1.test
.
We could change this, but it's a fairly fundamental change of what imports mean, so right now I'm reluctant to. For me, there's a simplicity in just considering explicitly defined imports. Import Linter is a static analysis library and so it isn't trying to model what happens at runtime anyway.
If we were to do it, the easiest option would be to provide an additional top-level argument when building the graph, along these lines:
[importlinter]
root_package = mypackage
add_parent_imports = True
I'm on the fence as to whether that would be a good change though. If you really need this functionality you could create your own custom contract type based on the forbidden contract, which manually adds an import from every child to its parent using graph.add_import.
Thanks again. That makes sense and the suggestion to make a custom contract type sounds like a good idea.
If
__init__.py
imports a forbidden model (or imports a modules that imports a forbidden model) when I import another module from that package, the forbidden model will be imported but import-linter does not detect it.For example if I have the following contract:
And a project with the following structure:
Where
src/__init__.py
andsrc/module1/test.py
are empty andsrc/module2/__init__.py
is:and
src/module1/__init__.py
is:Running
python -X importtime -c "import src.module2"
, we see thatsrc.module2
importsmath
but when I runlint-imports
it does not show any contracts being broken.