58 lines
1.5 KiB
Python
58 lines
1.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Validate that Python files have module-level docstrings.
|
|
|
|
Usage: python validate_docstrings.py <directory>
|
|
Returns: exit code 0 if all .py files have docstrings, 1 otherwise.
|
|
"""
|
|
|
|
import ast
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
def has_module_docstring(file_path: Path) -> bool:
|
|
"""Check if a Python file has a module-level docstring."""
|
|
try:
|
|
content = file_path.read_text()
|
|
tree = ast.parse(content)
|
|
return (
|
|
tree.body
|
|
and isinstance(tree.body[0], ast.Expr)
|
|
and isinstance(tree.body[0].value, ast.Constant)
|
|
and isinstance(tree.body[0].value.value, str)
|
|
)
|
|
except SyntaxError:
|
|
return False
|
|
|
|
|
|
def validate_directory(directory: str) -> list[str]:
|
|
"""Validate all Python files in directory have docstrings.
|
|
|
|
Returns list of files missing docstrings.
|
|
"""
|
|
dir_path = Path(directory)
|
|
missing = []
|
|
for py_file in dir_path.rglob("*.py"):
|
|
if not has_module_docstring(py_file):
|
|
missing.append(str(py_file))
|
|
return missing
|
|
|
|
|
|
def main():
|
|
if len(sys.argv) != 2:
|
|
print("Usage: python validate_docstrings.py <directory>")
|
|
sys.exit(2)
|
|
|
|
missing = validate_directory(sys.argv[1])
|
|
if missing:
|
|
print("Files missing module docstrings:")
|
|
for f in missing:
|
|
print(f" {f}")
|
|
sys.exit(1)
|
|
else:
|
|
print(f"All Python files in {sys.argv[1]} have module docstrings.")
|
|
sys.exit(0)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |