gauge-sh / tach

A Python tool to enforce dependencies, using modular architecture 🌎 Open source 🐍 Installable via pip 🔧 Able to be adopted incrementally - ⚡ Implemented with no runtime impact ♾️ Interoperable with your existing systems 🦀 Written in rust
https://gauge.sh
MIT License
1.17k stars 36 forks source link

`tach check-external` reports project itself as undeclared dependency if wildcard import is used #433

Closed zed closed 4 days ago

zed commented 6 days ago
% uv run tach check-external
❌: Undeclared dependencies in 'src/dependency_on_itself/__init__.py':
        dependency_on_itself

Add the undeclared dependencies to the corresponding pyproject.toml file, or consider ignoring the dependencies by adding them to the 'external.exclude' list in tach.toml.

where:

% tree src       
src
└── dependency_on_itself
    ├── __init__.py
    └── run.py

and:

% cat src/dependency_on_itself/__init__.py
from .run import *

If * is replaced with a name e.g., main in __init__.py:

from .run import main

then tach check-external passes.

run.py:

% cat src/dependency_on_itself/run.py
def main() -> None:
    print("Hello from dependency-on-itself!")

Project is created with uv init, and main() moved to run.py module.

% cat tach.toml 
interfaces = []
exclude = [
    ".*__pycache__",
    ".*egg-info",
    "docs",
    "tests",
]
source_roots = [
    "src",
]

[[modules]]
path = "dependency_on_itself"
depends_on = [
    { path = "dependency_on_itself.run" },
]

[[modules]]
path = "dependency_on_itself.run"
depends_on = []

The expected behavior: tach check-external passes in both cases from .run import * and from .run import main.