55 lines
1.9 KiB
Python
55 lines
1.9 KiB
Python
"""
|
|
Pre-commit hook to check for missing `__init__.py` files in mlflow and tests directories.
|
|
|
|
This script ensures that all directories under the mlflow package and tests directory that contain
|
|
Python files also have an `__init__.py` file. This prevents `setuptools` from excluding these
|
|
directories during package build and ensures test modules are properly structured.
|
|
|
|
Usage:
|
|
uv run dev/check_init_py.py
|
|
|
|
Requirements:
|
|
- If `mlflow/foo/bar.py` exists, `mlflow/foo/__init__.py` must exist.
|
|
- If `tests/foo/test_bar.py` exists, `tests/foo/__init__.py` must exist.
|
|
- Only test files (starting with `test_`) in the tests directory are checked.
|
|
- All parent directories of Python files are checked recursively for `__init__.py`.
|
|
- Ignore directories that do not contain any Python files (e.g., `mlflow/server/js`).
|
|
"""
|
|
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
def get_tracked_python_files() -> list[Path]:
|
|
try:
|
|
result = subprocess.check_output(
|
|
["git", "ls-files", "mlflow/**/*.py", "tests/**/*.py"],
|
|
text=True,
|
|
)
|
|
paths = (Path(f) for f in result.splitlines() if f)
|
|
return [p for p in paths if (not p.is_relative_to("tests") or p.name.startswith("test_"))]
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"Error running git ls-files: {e}", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
|
|
def main() -> int:
|
|
python_files = get_tracked_python_files()
|
|
if not python_files:
|
|
return 0
|
|
|
|
python_dirs = {p for f in python_files for p in f.parents if p != Path(".")}
|
|
if missing_init_files := [d for d in python_dirs if not (d / "__init__.py").exists()]:
|
|
print("Error: The following directories contain Python files but lack __init__.py:")
|
|
for d in sorted(missing_init_files):
|
|
print(f" {d.as_posix()}/")
|
|
print("Please add __init__.py files to the directories listed above.")
|
|
return 1
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|