Purpose¶
You want to introduce dependency linting to an existing project without fixing all violations at once.
Strategy 1: Start with deny rules¶
Instead of a strict allowlist, start by denying only the most problematic dependencies:
rules:
- name: no-orm-in-domain
modules: my_app.domain
deny:
third_party: [sqlalchemy, django]
This catches new violations without flagging existing ones that don't match the deny list.
Strategy 2: Scope with include¶
Lint only new or well-structured parts of your codebase:
include:
- my_app/new_module
rules:
- name: new-module-rules
modules: my_app.new_module
allow:
standard_library: ["*"]
third_party: [pydantic]
local: [my_app.new_module, my_app.shared]
Expand the include list as you clean up more modules.
Strategy 3: Use inline ignore for known violations¶
Add # pdl: ignore to existing violations you plan to fix later, so the linter passes in CI:
import sqlalchemy # pdl: ignore[no-orm-in-domain]
Then remove the ignore comments as you refactor.
Strategy 4: One rule at a time¶
Start with the most important boundary (usually domain isolation) and add rules incrementally:
# Week 1: Just domain isolation
rules:
- name: domain-isolation
modules: my_app.domain
allow:
standard_library: ["*"]
third_party: []
local: [my_app.domain]
# Week 2: Add application layer
rules:
- name: domain-isolation
modules: my_app.domain
allow:
standard_library: ["*"]
third_party: []
local: [my_app.domain]
- name: application-layer
modules: my_app.application
allow:
standard_library: ["*"]
third_party: [pydantic]
local: [my_app.application, my_app.domain]
Result¶
With Strategy 1, only the specific denied imports are flagged:
my_app/domain/repo.py:1
[no-orm-in-domain] my_app.domain.repo → sqlalchemy (third_party)
Found 1 violation(s).
Other third-party imports in domain are still allowed until you switch to a stricter allowlist.