#!/usr/bin/env python3 """Compile Protocol Buffer definitions to Python code. This script compiles the .proto files in the protos/ directory to Python code in the src/protos/ directory. Usage: uv run python scripts/compile_protos.py Requirements: Install the proto optional dependencies: uv pip install -e ".[proto]" """ from __future__ import annotations import subprocess import sys from pathlib import Path def main() -> int: """Compile proto files to Python.""" project_root = Path(__file__).parent.parent protos_dir = project_root / "protos" output_dir = project_root / "src" / "protos" # Ensure directories exist protos_dir.mkdir(exist_ok=True) output_dir.mkdir(exist_ok=True) # Find all .proto files proto_files = list(protos_dir.glob("*.proto")) if not proto_files: print("No .proto files found in protos/ directory") return 1 print(f"Found {len(proto_files)} proto file(s):") for pf in proto_files: print(f" - {pf.name}") # Compile each proto file for proto_file in proto_files: print(f"\nCompiling {proto_file.name}...") cmd = [ sys.executable, "-m", "grpc_tools.protoc", f"--proto_path={protos_dir}", # Include Google protobuf well-known types f"--proto_path={_get_protobuf_include_path()}", f"--python_out={output_dir}", f"--pyi_out={output_dir}", # Generate type stubs str(proto_file), ] try: result = subprocess.run(cmd, capture_output=True, text=True, check=False) if result.returncode != 0: print(f"Error compiling {proto_file.name}:") print(result.stderr) return result.returncode print(f" Generated: {proto_file.stem}_pb2.py") print(f" Generated: {proto_file.stem}_pb2.pyi") except FileNotFoundError: print("Error: grpc_tools not found. Install with:") print(' uv pip install -e ".[proto]"') return 1 print("\nProto compilation complete!") return 0 def _get_protobuf_include_path() -> str: """Get the path to protobuf well-known types.""" try: import grpc_tools.protoc grpc_tools_path = Path(grpc_tools.protoc.__file__).parent # The _proto directory contains google/protobuf/*.proto proto_path = grpc_tools_path / "_proto" if proto_path.exists(): return str(proto_path) except ImportError: pass # Fallback: try to find in site-packages try: import google.protobuf protobuf_path = Path(google.protobuf.__file__).parent.parent return str(protobuf_path) except ImportError: pass # Last resort: return empty string and let protoc find it return "" if __name__ == "__main__": sys.exit(main())