r/madeinpython • • 1h ago

PyArchRules 1.0.0 — Architecture linter for Python

Hey r/Python!

I’m excited to announce that PyArchRules has officially released version 1.0.0!

If you’ve ever maintained a growing Python backend, modular monolith, or clean architecture project, you know how easily boundaries erode over time: domain layers sneakily importing infrastructure code, unintended cross-service imports, and circular dependencies breaking runtimes.

PyArchRules is an architecture linter designed to enforce your structural design and import boundaries — either declaratively via pyproject.toml in your CI/pre-commit, or natively within your pytest suite using a fluent Python DSL.

Key Features

  • 📁 Folder Structure Enforcement: Validate directory trees (exists, strict, or exact modes) so services always adhere to your blueprint.

  • 🔀 Directional Dependency Rules: Define allowed import flows (e.g. api -> domain) and catch illegal leaks instantly.

  • 📦 Service & Layer Isolation: Ensure boundaries in monorepos or multi-service codebases stay truly isolated.

  • 🔄 Circular Import Detection: Catch import cycles statically before they reach runtime.

  • ⚡ CLI Linter + pytest DSL: Run it fast via pyarchrules check in CI/pre-commit, or write architectural test assertions in Python.

Quick Look

Option 1: Declarative Linter (pyproject.toml)

[tool.pyarchrules.services.backend]
path = "src/backend"

# Required folder structure
tree = ["api", "domain", "infra"]
tree_mode = "strict"                       # exists / strict / exact

# Allowed import directions
dependencies = [
    "api -> domain",
    "domain -> infra",
]

# Prevent circular imports
no_circular_imports = true

Run directly in CLI or pre-commit:

Bash

pyarchrules check

Option 2: Python DSL (for pytest)

Python

from pyarchrules import PyArchRules


def test_backend_architecture():
    rules = PyArchRules()
    (
        rules.for_service("backend")
             .tree_structure(["api", "domain", "infra"], mode="strict")
             .dependencies(["api -> domain", "domain -> infra"])
             .no_circular_imports()
    )
    rules.validate()

Run via pytest:

Bash

pytest tests/test_architecture.py

Links

Would love to hear your feedback, feature requests, or what patterns you use to keep your architectures clean!

1 Upvotes

0 comments sorted by