97 lines
2.8 KiB
Python
97 lines
2.8 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Line Counter for Python Files - counts total lines, code lines, comment lines, and blank lines.
|
|
"""
|
|
import sys
|
|
import ast
|
|
from pathlib import Path
|
|
|
|
def count_python_lines(filepath: str) -> dict:
|
|
"""Analyze a Python file and count line types."""
|
|
result = {
|
|
"file": filepath,
|
|
"total": 0,
|
|
"code": 0,
|
|
"comment": 0,
|
|
"blank": 0
|
|
}
|
|
|
|
try:
|
|
with open(filepath, 'r') as f:
|
|
lines = f.readlines()
|
|
except Exception as e:
|
|
result["error"] = str(e)
|
|
return result
|
|
|
|
in_docstring = False
|
|
in_multiline_string = False
|
|
docstring_char = None
|
|
|
|
for line in lines:
|
|
stripped = line.strip()
|
|
result["total"] += 1
|
|
|
|
if not stripped:
|
|
result["blank"] += 1
|
|
continue
|
|
|
|
if stripped.startswith('#'):
|
|
result["comment"] += 1
|
|
continue
|
|
|
|
if stripped.startswith('"""') or stripped.startswith("'''"):
|
|
if in_docstring:
|
|
in_docstring = False
|
|
in_multiline_string = False
|
|
docstring_char = None
|
|
else:
|
|
in_docstring = True
|
|
in_multiline_string = True
|
|
docstring_char = stripped[:3]
|
|
result["comment"] += 1
|
|
continue
|
|
|
|
if in_docstring and docstring_char and stripped.endswith(docstring_char):
|
|
in_docstring = False
|
|
in_multiline_string = False
|
|
result["comment"] += 1
|
|
continue
|
|
|
|
if in_docstring:
|
|
result["comment"] += 1
|
|
continue
|
|
|
|
result["code"] += 1
|
|
|
|
return result
|
|
|
|
def count_python_files(directory: str) -> dict:
|
|
"""Count lines for all Python files in directory."""
|
|
dir_path = Path(directory)
|
|
if not dir_path.exists():
|
|
return {"error": f"Directory not found: {directory}"}
|
|
|
|
totals = {"total": 0, "code": 0, "comment": 0, "blank": 0}
|
|
files = []
|
|
|
|
for py_file in sorted(dir_path.glob("*.py")):
|
|
result = count_python_lines(str(py_file))
|
|
files.append(result)
|
|
totals["total"] += result["total"]
|
|
totals["code"] += result["code"]
|
|
totals["comment"] += result["comment"]
|
|
totals["blank"] += result["blank"]
|
|
|
|
return {"files": files, "totals": totals}
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) < 2:
|
|
print("Usage: python count_python_lines.py <file.py> [file2.py] ...", file=sys.stderr)
|
|
sys.exit(2)
|
|
|
|
for filepath in sys.argv[1:]:
|
|
result = count_python_lines(filepath)
|
|
if "error" in result:
|
|
print(f"ERROR: {result['error']}")
|
|
else:
|
|
print(f"{result['file']}: total={result['total']}, code={result['code']}, comment={result['comment']}, blank={result['blank']}") |