In short
Sometimes what a class is matters more than where it lives. This targets classes by their base class / Protocol / ABC — e.g. 'anything subclassing Repository must be named *Repository and live in infrastructure', regardless of file path.
Problem
Rules often target a role defined by a base class/Protocol/ABC, not a path: 'subclasses of Repository must be named *_repository.py and live in infrastructure/**', 'only api/** may subclass BaseView'. ArchUnitPython matches names and paths but not subclass/Protocol relationships.
Proposal
Add type-graph predicates onto the existing project_files(...) chain — .that_are_subclasses_of("Repository"), .that_implement_protocol("SupportsRead") — usable with the existing naming/placement/dependency assertions.
Acceptance criteria
In short
Sometimes what a class is matters more than where it lives. This targets classes by their base class / Protocol / ABC — e.g. 'anything subclassing
Repositorymust be named*Repositoryand live in infrastructure', regardless of file path.Problem
Rules often target a role defined by a base class/Protocol/ABC, not a path: 'subclasses of
Repositorymust be named*_repository.pyand live ininfrastructure/**', 'onlyapi/**may subclassBaseView'. ArchUnitPython matches names and paths but not subclass/Protocol relationships.Proposal
Add type-graph predicates onto the existing
project_files(...)chain —.that_are_subclasses_of("Repository"),.that_implement_protocol("SupportsRead")— usable with the existing naming/placement/dependency assertions.Acceptance criteria
project_files("src/").that_are_subclasses_of("Repository").should().have_name("*_repository.py")fails on a mis-named subclass.typing.Protocolare handled.