Unable to create simple contract - django models
I am trying to make what I would have thought would be a very simple contract that prohibits one django module from importing the models from another. I am consistently getting an error that is confounding me. Here is my config and the output:
[[tool.importlinter.contracts]]
id = "core"
name = "Prevent cross-app model imports"
type = "forbidden"
source_modules = ["core.*"]
forbidden_modules = ["core.*.models"]
It is able to find the modules and their imports but never succeeds because of the following error:
Modules have shared descendants.
While I understand on the surface what is happening I am unable to create any kind of ignore rule that would work generically.
I rather have a given module be able to import what is below it. I did try the layer approach but it was also requiring the addition of every package.
Essentially we are trying to keep modules from interacting with the data layer of another module to enforce code level interactions rather than direct model access.
Please help!
Thanks for raising the issue!
What's happening here is that because core.*.models are covered by the core.* expression, Import Linter is rejecting it - it doesn't make sense for modules to be forbidden from importing themselves.
There's an argument to say that forbidden contracts could be adjusted to take account of this - I'd need to think about it a bit more though as possibly it would complicate things.
In the meantime you have a couple of options:
- Use the layers approach, as you say. The
exhaustiveoption will force developers to keep the listed layers in sync with the packages in the code base. That would be what I would do in this situation. - Create a custom contract type that does exactly what you want. You could adapt this from the forbidden contract.
Hope that helps!