Tach - Python Modular Architecture Tool
Tach is a Python CLI tool (implemented in Rust) designed to enforce modular design and control dependencies between Python modules within a project. It enables developers to define explicit module boundaries, prevent deep coupling, enforce public interfaces, and detect circular dependencies. Actively maintained with frequent releases, the current version is 0.34.1, requiring Python 3.9 or higher.
Warnings
- breaking Tach dropped official support for Python 3.8 in version `0.34.0`. Users on older Python versions must use `tach < 0.34.0` or upgrade their Python environment.
- gotcha The `tach test` command and its pytest plugin have undergone several changes and fixes, particularly around auto-loading and default behaviors since `v0.33.0`. Earlier versions might have experienced issues like the plugin being registered twice, leading to `ValueError`, or incorrect test skipping. Ensure you are on the latest `tach` version for the most stable pytest integration.
- gotcha Tach performs static analysis of your codebase by analyzing the Abstract Syntax Tree (AST). This means it will not detect or enforce rules for dynamic imports (e.g., those using `importlib`), as these are only resolved at runtime.
- gotcha From `v0.33.1`, a `layers_explicit_depends_on` flag was added to `tach.toml`. If set to `true`, modules in higher layers must explicitly declare dependencies on lower layers, even if implicitly allowed by the layer hierarchy. By default, higher layers can depend on lower layers without explicit declaration.
Install
-
pip install tach
Quickstart
import os
import textwrap
# Create a dummy project structure
os.makedirs("my_project/src/app", exist_ok=True)
os.makedirs("my_project/src/utils", exist_ok=True)
with open("my_project/src/app/__init__.py", "w") as f:
f.write("")
with open("my_project/src/app/main.py", "w") as f:
f.write("from src.utils.helpers import greet\n\ndef run():\n print(greet('World'))\n")
with open("my_project/src/utils/__init__.py", "w") as f:
f.write(""
)
with open("my_project/src/utils/helpers.py", "w") as f:
f.write("def greet(name):\n return f'Hello, {name}'\n")
tach_toml_content = textwrap.dedent("""
[[layers]]
name = "app"
path = "src/app"
dependencies = ["utils"]
[[layers]]
name = "utils"
path = "src/utils"
dependencies = []
""")
with open("my_project/tach.toml", "w") as f:
f.write(tach_toml_content)
print("Project structure and tach.toml created in 'my_project' directory.")
print("Navigate to 'my_project' and run 'tach check' to validate boundaries.")