Add export-report CLI command

This commit is contained in:
2026-01-29 18:01:01 +00:00
parent 022223af76
commit 2b92865745

View File

@@ -208,6 +208,127 @@ def list_runs_cmd(
repo.close()
@app.command(name="export-report")
def export_report_cmd(
run_id: Annotated[
str,
typer.Argument(help="Test run ID (short 8-char or full UUID)."),
],
output: Annotated[
str | None,
typer.Option("--output", "-o", help="Output PDF file path."),
] = None,
company: Annotated[
str | None,
typer.Option("--company", help="Company name for report header."),
] = None,
config_file: Annotated[
str | None,
typer.Option("--config", "-c", help="Path to configuration YAML file."),
] = None,
) -> None:
"""Export a PDF report for a test run.
Generate a professional PDF report from test results. The run_id can be
the short 8-character ID shown by list-runs, or the full UUID.
Examples:
py-dvt-ate export-report abc12345
py-dvt-ate export-report abc12345 --output ./my_report.pdf
py-dvt-ate export-report abc12345 --company "My Company"
"""
from pathlib import Path
from uuid import UUID
from rich.console import Console
from py_dvt_ate.app.config import load_config
from py_dvt_ate.data.repository import SQLiteRepository
console = Console()
# Check for reporting dependencies
try:
from py_dvt_ate.reporting import ReportConfig, ReportGenerator
except ImportError:
console.print(
"[red]Error:[/red] Report generation requires additional dependencies.\n"
"Install with: [cyan]pip install py_dvt_ate[reports][/cyan]"
)
raise typer.Exit(1)
# Load config
if config_file is None:
config_path = Path("config/default.yaml")
if config_path.exists():
config_file = str(config_path)
config = load_config(config_file)
# Create repository
repo = SQLiteRepository(
db_path=config.data.database_path,
measurements_dir=config.data.measurements_dir,
)
try:
# Resolve short ID to full UUID
full_run_id: UUID | None = None
if len(run_id) == 8:
# Short ID - need to find full UUID
all_runs = repo.get_all_runs()
matching_runs = [r for r in all_runs if r.id.startswith(run_id)]
if not matching_runs:
console.print(f"[red]Error:[/red] No test run found with ID starting with '{run_id}'")
raise typer.Exit(1)
elif len(matching_runs) > 1:
console.print(f"[red]Error:[/red] Multiple runs match '{run_id}'. Use full UUID.")
for run in matching_runs:
console.print(f" - {run.id} ({run.test_name})")
raise typer.Exit(1)
full_run_id = UUID(matching_runs[0].id)
else:
try:
full_run_id = UUID(run_id)
except ValueError:
console.print(f"[red]Error:[/red] Invalid run ID: '{run_id}'")
raise typer.Exit(1)
# Create report config
report_config = ReportConfig(
company_name=company or config.reporting.company_name,
logo_path=Path(config.reporting.logo_path) if config.reporting.logo_path else None,
include_charts=config.reporting.include_charts,
chart_dpi=config.reporting.chart_dpi,
)
# Create generator
generator = ReportGenerator(
repository=repo,
config=report_config,
reports_dir=Path(config.data.reports_dir),
)
# Generate report
console.print(f"[cyan]Generating report for run {str(full_run_id)[:8]}...[/cyan]")
output_path = Path(output) if output else None
pdf_path = generator.generate(full_run_id, output_path)
console.print(f"[green]Report saved to:[/green] {pdf_path}")
except typer.Exit:
raise
except Exception as e:
console.print(f"[red]Error generating report:[/red] {e}")
raise typer.Exit(1)
finally:
repo.close()
@app.command(name="query")
def query_cmd(
instrument: Annotated[