tach
repository·main·Indexed 25 days ago
https://github.com/tach-org/tachA Python tool written in Rust designed to enforce architectural boundaries. Tach ensures imports follow declared dependencies, cross-module calls use public interfaces, and no dependency cycles exist in the graph. It provides a CLI for initializing projects, interactively defining module boundaries, syncing constraints, and visualizing dependency graphs, as well as a VS Code extension for real-time validation.
What's inside tach
- Tach is a tool designed to control dependencies between Python modules. It enables developers to define explicit public interfaces for modules, which helps prevent deep coupling and promotes a more modular architecture. Tach works by verifying that no module imports from another module unless that dependency is explicitly listed. If a module defines a public interface, any import that bypasses that interface will trigger an error from Tach. Additionally, dependencies can be marked as 'deprecated' to surface their usage without causing errors.
Understand Tach dependency management
mainTach is a CLI tool used to control and enforce dependencies between Python modules. It helps prevent deep coupling by allowing you to:
- Define module boundaries and dependencies.
- Define explicit public interfaces to restrict how modules interact.
- Mark dependencies as
deprecatedto surface usage without triggering errors. - Enforce these rules via CI checks or pre-commit hooks.
Tach is designed to be adopted incrementally and has no runtime impact on your Python code.
Understand how Tach caching works
mainTach uses a 'computation cache' to speed up tasks like
tach test. Caching is applied at the command level: a single invocation of a command results in either a complete cache hit or a complete cache miss. Individual sub-tasks (like individual tests within a test suite) are not cached separately.When a cache hit occurs, the terminal output is wrapped in the following markers:
============ Cached results found! ============ ... ============ END Cached results ============Understand the purpose of Tach for Python modularity
mainTach is a tool designed to manage and enforce modularity in Python codebases. It addresses the complexity of large-scale projects by providing mechanisms to:
- Define module boundaries: Establish clear separations between different areas of your code.
- Control dependencies: Manage and restrict how modules depend on one another to prevent messy or opaque dependency webs.
- Define explicit public interfaces: Prevent deep coupling by requiring modules to interact through defined APIs.
- Gradual adoption: Allows for incremental implementation in existing, complex projects.
- Workflow integration: Can be integrated into CI/CD pipelines and pre-commit hooks to enforce architectural rules automatically.
Document ignore reasons with `tach-ignore`
mainYou can include a reason for ignoring an import by adding a message in parentheses immediately following the
tach-ignoredirective. This helps document why a specific rule is being bypassed.# tach-ignore(Alternative API not yet available 11/26/24) private_api from core.api import private_apiIgnore imports using the `tach-ignore` directive
mainTo allow a specific import unconditionally, use the
# tach-ignorecomment directive. You can apply this to an entire import line or specify a particular name to ignore when importing multiple items from the same module.Important: When specifying names, use the alias as it appears in the import line, not the full module path from the project root.
# Ignore the entire line # tach-ignore from core.main import private_function # Ignore a specific name in a multi-import line from core.api import private_calculation, public_service # tach-ignore private_calculation # Ignore a specific name within a parenthesized import block from core.package import ( # tach-ignore service_two service_one, service_two )Install Tach via pip
mainInstall the Tach package using pip to get access to the CLI tools.
pip install tachReport security vulnerabilities privately
mainDo not report security vulnerabilities through public GitHub issues. To report a security issue privately, use one of the following methods:
- Discord: Send a Direct Message (DM) to
caeleanornashsandovia the Tach Discord server. - Email: Contact
caelean@gauge.shorevan@gauge.sh.
Significant security issues may be eligible for a bounty.
- Discord: Send a Direct Message (DM) to
Define public interfaces in tach.toml
mainYou can prevent modules from coupling to implementation details by defining a public interface in
tach.toml. When a module has a public interface, Tach will only allow imports that match the specifiedexposepatterns. Any import not explicitly listed in theexposearray for that module will causetach checkto fail.[[modules]] path = "domain" depends_on = [ "core" ] [[modules]] path = "core" depends_on = [] [[interfaces]] expose = ["get_data"] from = ["core"]Configure module boundaries with tach mod
mainRun
tach modto open an interactive terminal editor for defining module boundaries.Interactive Controls:
- Arrow keys: Navigate the directory tree.
- Enter: Mark an individual module.
- Ctrl + a: Mark all siblings as modules.
- s: Mark Python source roots (helps Tach identify first-party imports).
- u: Mark a module as a utility (e.g.,
utils/) that can be freely used by other code. - Ctrl + s: Save changes.
- Ctrl + c: Exit without saving.
Note: After making changes with
tach mod, you must runtach syncto update dependency rules.Sync dependencies with `tach sync`
mainAfter defining boundaries, runtach syncto analyze your codebase. This command automatically adds dependency rules to yourtach.tomlfile based on your actual code imports.tach syncSetup the Tach VS Code Extension
mainTo use Tach in VS Code, follow these steps:
- Install the extension: Once installed, Tach will automatically highlight invalid imports as errors when you save a file.
- Configure arguments: If you need to pass specific arguments to Tach, navigate to
Extensions > Tachin your VS Code settings. - Restart the server: If the extension is not behaving as expected, open the Command Palette (
CMD+SHFT+Pon macOS orCtrl+Shift+Pon Windows/Linux) and run the commandTach: Restart Server.