seddonym / import-linter

Import Linter allows you to define and enforce rules for the internal and external imports within your Python project.
https://import-linter.readthedocs.io/
BSD 2-Clause "Simplified" License
664 stars 45 forks source link

Proposal: Allow configuring sibling independence #208

Closed Peter554 closed 8 months ago

Peter554 commented 9 months ago

In layer contracts it is possible to define sibling layers. These sibling layers are always required to be independent. I believe it would be helpful to allow sibling independence to be configured, on a per layer basis. This would allow us to express contracts where we don't care about inter-layer imports.

The existing syntax for independent sibling layers is:

foo | bar | baz

A possible/proposed syntax for non-independent sibling layers could be:

foo : bar : baz

A mixed syntax would be disallowed and cause an error

// not allowed
foo | bar : baz

The work of enforcing layer contracts is mostly handed in grimp, so work to achieve this would have to start there. A draft / proof of concept can be found here -> https://github.com/seddonym/grimp/pull/136. If this proposal is approved I would be happy to polish those grimp changes and then afterwards make the appropriate importlinter changes.

seddonym commented 9 months ago

Thanks for this. I'm not sure... having potential circular dependencies between three modules doesn't sound like the kind of contract I'd personally want. On the other hand, perhaps Import Linter shouldn't be too opinionated about things like that.

I'll have a think about it.

Peter554 commented 9 months ago

Thanks. My imagined use case is something like:

foo : bar : baz
application
domain1 : domain2
data

Where:

Without allowing the option to configure sibling independence, it makes it difficult to create layered contracts that are exhaustive and capture all the information we want. Of course, in an ideal world and starting a project from scratch, one would probably not choose the architecture above, but for an existing project of size that has something like this going on, I think it's better to have some contract than none, and ideally the most expressive and powerful one we can have. From my perspective I think importlinter should not really be too opinionated about good vs. bad architecture, since we can't know the (perhaps-good) reasons why users projects have the strange architectures they have, but should rather just provide a tool to enforce a configured architecture.

seddonym commented 9 months ago

I think you make a good case for this! I also like the : syntax. Happy to consider a PR for it, and let me know if you want to discuss implementation at all.

Peter554 commented 9 months ago

I think you make a good case for this! I also like the : syntax.

Great 😃

Happy to consider a PR for it, and let me know if you want to discuss implementation at all.

I've had a go at the implementation in grimp here => https://github.com/seddonym/grimp/pull/136 It's ready for review 🤞.

seddonym commented 8 months ago

This is now released in Import Linter v2.0. Thanks for all your help!

Peter554 commented 8 months ago

This is now released in Import Linter v2.0. Thanks for all your help!

Great, thanks very much for taking the time to support with this 🙂