"""File utility functions for common operations.""" import json import os from pathlib import Path from typing import Any def read_json(filepath: str | Path) -> dict[str, Any]: """Read and parse a JSON file.""" path = Path(filepath) if not path.exists(): raise FileNotFoundError(f"File not found: {path}") with path.open("r", encoding="utf-8") as f: return json.load(f) def write_json(filepath: str | Path, data: dict, indent: int = 2) -> None: """Write data to a JSON file with pretty printing.""" path = Path(filepath) path.parent.mkdir(parents=True, exist_ok=True) with path.open("w", encoding="utf-8") as f: json.dump(data, f, indent=indent, ensure_ascii=False) f.write("\n") # Trailing newline. def find_files( directory: str | Path, pattern: str = "*", recursive: bool = True, ) -> list[Path]: """Find files matching a glob pattern in a directory.""" path = Path(directory) if not path.is_dir(): raise NotADirectoryError(f"Not a directory: {path}") method = path.rglob if recursive else path.glob return sorted(method(pattern)) def human_readable_size(size_bytes: int) -> str: """Convert bytes to human-readable format.""" for unit in ("B", "KB", "MB", "GB", "TB"): if abs(size_bytes) < 1024: return f"{size_bytes:.1f} {unit}" size_bytes /= 1024 return f"{size_bytes:.1f} PB" if __name__ == "__main__": # Example: list all Python files in current directory. for f in find_files(".", "*.py"): size = human_readable_size(f.stat().st_size) print(f" {f} ({size})")