-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Milestone 10 — CLI generate/inspect/validate commands #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a27d9a4
4fe7c7e
cb0d87b
c0e97c0
99ff9ec
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,14 +1,81 @@ | ||||||
| """leadforge inspect command.""" | ||||||
|
|
||||||
| from __future__ import annotations | ||||||
|
|
||||||
| from pathlib import Path | ||||||
| from typing import Any | ||||||
|
|
||||||
| import typer | ||||||
|
|
||||||
| from leadforge.core.exceptions import LeadforgeError | ||||||
| from leadforge.core.serialization import load_json | ||||||
|
|
||||||
|
|
||||||
| def inspect( | ||||||
| bundle_path: str = typer.Argument(..., help="Path to a generated bundle directory."), | ||||||
| ) -> None: | ||||||
| """Inspect a generated dataset bundle and print a summary.""" | ||||||
| typer.echo( | ||||||
| "The 'inspect' command is not yet implemented. Coming in v0.4.0.", | ||||||
| err=True, | ||||||
| ) | ||||||
| raise typer.Exit(1) | ||||||
| root = Path(bundle_path) | ||||||
|
|
||||||
| if not root.exists(): | ||||||
| typer.echo(f"Error: path does not exist: {root}", err=True) | ||||||
| raise typer.Exit(1) | ||||||
| if not root.is_dir(): | ||||||
| typer.echo(f"Error: not a directory (expected a bundle dir): {root}", err=True) | ||||||
| raise typer.Exit(1) | ||||||
|
|
||||||
| manifest_path = root / "manifest.json" | ||||||
| if not manifest_path.exists(): | ||||||
| typer.echo(f"Error: no manifest.json found in {root}", err=True) | ||||||
| raise typer.Exit(1) | ||||||
|
|
||||||
| try: | ||||||
| manifest = load_json(manifest_path) | ||||||
| except LeadforgeError as exc: | ||||||
| typer.echo(f"Error: {exc}", err=True) | ||||||
| raise typer.Exit(1) from None | ||||||
|
|
||||||
| if not isinstance(manifest, dict): | ||||||
| typer.echo("Error: manifest.json is not a JSON object", err=True) | ||||||
| raise typer.Exit(1) | ||||||
|
|
||||||
| typer.echo(f"Bundle: {root}") | ||||||
| typer.echo(f" Recipe: {manifest.get('recipe_id', '?')}") | ||||||
| typer.echo(f" Seed: {manifest.get('seed', '?')}") | ||||||
| typer.echo(f" Mode: {manifest.get('exposure_mode', '?')}") | ||||||
| typer.echo(f" Difficulty: {manifest.get('difficulty', '?')}") | ||||||
| typer.echo(f" Horizon days: {manifest.get('horizon_days', '?')}") | ||||||
| typer.echo(f" Generated at: {manifest.get('generation_timestamp', '?')}") | ||||||
| typer.echo(f" Package: leadforge {manifest.get('package_version', '?')}") | ||||||
| typer.echo(f" Schema ver: {manifest.get('bundle_schema_version', '?')}") | ||||||
| typer.echo(f" Motif family: {manifest.get('motif_family', '?')}") | ||||||
|
|
||||||
| typer.echo("") | ||||||
| typer.echo("Tables:") | ||||||
| tables = manifest.get("tables", {}) | ||||||
| if isinstance(tables, dict): | ||||||
| for name, info in tables.items(): | ||||||
| row_count = _safe_get(info, "row_count", "?") | ||||||
| typer.echo(f" {name:25s} {row_count:>8} rows") | ||||||
|
||||||
| typer.echo(f" {name:25s} {row_count:>8} rows") | |
| typer.echo(f" {name:25s} {str(row_count):>8} rows") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,42 @@ | ||
| """leadforge validate command.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from pathlib import Path | ||
|
|
||
| import typer | ||
|
|
||
| from leadforge.core.exceptions import LeadforgeError | ||
|
|
||
|
|
||
| def validate( | ||
| bundle_path: str = typer.Argument(..., help="Path to a generated bundle directory."), | ||
| ) -> None: | ||
| """Run schema and artifact validation on a generated bundle.""" | ||
| typer.echo( | ||
| "The 'validate' command is not yet implemented. Coming in v0.5.0.", | ||
| err=True, | ||
| ) | ||
| raise typer.Exit(1) | ||
| from leadforge.validation.bundle_checks import validate_bundle | ||
|
|
||
| root = Path(bundle_path) | ||
|
|
||
| if not root.exists(): | ||
| typer.echo(f"FAIL: path does not exist: {root}", err=True) | ||
| raise typer.Exit(1) | ||
| if not root.is_dir(): | ||
| typer.echo(f"FAIL: not a directory: {root}", err=True) | ||
| raise typer.Exit(1) | ||
| if not (root / "manifest.json").exists(): | ||
| typer.echo(f"FAIL: no manifest.json in {root}", err=True) | ||
| raise typer.Exit(1) | ||
|
|
||
| try: | ||
| errors = validate_bundle(root) | ||
| except LeadforgeError as exc: | ||
| typer.echo(f"FAIL: {exc}", err=True) | ||
| raise typer.Exit(1) from None | ||
|
|
||
| if errors: | ||
| typer.echo(f"FAIL: {len(errors)} validation error(s):", err=True) | ||
| for e in errors: | ||
| typer.echo(f" - {e}", err=True) | ||
| raise typer.Exit(1) | ||
|
|
||
| typer.echo(f"OK: bundle at {root} passed all checks.") |
Uh oh!
There was an error while loading. Please reload this page.