trainer_validate_view.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. # -*- coding: utf-8 -*-
  2. """
  3. Trainer SubView: Validate (F5).
  4. Fuehrt eine Validierung durch und zeigt Ergebnisse:
  5. Fehler, Warnungen und GPU-Informationen.
  6. """
  7. from __future__ import annotations
  8. from textual.app import ComposeResult
  9. from textual.containers import Vertical
  10. from textual.widgets import Static, Button
  11. from trixy_core.tui.views.base import MainView
  12. from trixy_core.tui.widgets.status_table import StatusTable
  13. class TrainerValidateView(MainView):
  14. """F5 im Trainer-Kontext: Validierung."""
  15. TITLE = "Validierung"
  16. VIEW_ID = "trainer_validate"
  17. def __init__(self, **kwargs) -> None:
  18. super().__init__(**kwargs)
  19. self._trainer_data: dict = {}
  20. def set_trainer(self, trainer_data: dict) -> None:
  21. """Setzt die Trainer-Basisdaten."""
  22. self._trainer_data = trainer_data
  23. def compose(self) -> ComposeResult:
  24. with Vertical(classes="trainer-section"):
  25. yield Static(
  26. "[bold]Trainings-Validierung[/bold]\n"
  27. "Prueft Einstellungen, Dataset und GPU-Verfuegbarkeit.",
  28. classes="trainer-section-header",
  29. )
  30. yield Button("Validierung starten", id="trainer-validate-btn", variant="primary")
  31. with Vertical(id="trainer-validate-result", classes="trainer-section"):
  32. yield Static("", id="trainer-validate-status")
  33. yield StatusTable(id="trainer-validate-gpu")
  34. yield Static("", id="trainer-validate-errors")
  35. yield Static("", id="trainer-validate-warnings")
  36. async def on_activate(self) -> None:
  37. """Zuruecksetzen bei Aktivierung."""
  38. self.query_one("#trainer-validate-status", Static).update("")
  39. self.query_one("#trainer-validate-errors", Static).update("")
  40. self.query_one("#trainer-validate-warnings", Static).update("")
  41. self.query_one("#trainer-validate-gpu", StatusTable).update_data([])
  42. async def on_button_pressed(self, event: Button.Pressed) -> None:
  43. """Validierung starten."""
  44. if event.button.id != "trainer-validate-btn":
  45. return
  46. await self._run_validation()
  47. async def _run_validation(self) -> None:
  48. """Fuehrt die Validierung durch."""
  49. status = self.query_one("#trainer-validate-status", Static)
  50. errors_widget = self.query_one("#trainer-validate-errors", Static)
  51. warnings_widget = self.query_one("#trainer-validate-warnings", Static)
  52. gpu_table = self.query_one("#trainer-validate-gpu", StatusTable)
  53. if not self.connection:
  54. status.update("[red]Keine Verbindung[/red]")
  55. return
  56. trainer_id = self._trainer_data.get("trainer_id", "")
  57. if not trainer_id:
  58. status.update("[red]Kein Trainer ausgewaehlt[/red]")
  59. return
  60. # Erst Settings speichern (falls Settings-View Aenderungen hat)
  61. settings_view = self.app._view_map.get("trainer_settings") # type: ignore[attr-defined]
  62. if settings_view and hasattr(settings_view, "collect_settings"):
  63. settings = settings_view.collect_settings()
  64. if settings:
  65. await self.connection.write_trainer_settings(trainer_id, settings)
  66. status.update("[yellow]Validierung laeuft...[/yellow]")
  67. try:
  68. result = await self.connection.validate_trainer(trainer_id)
  69. except Exception as e:
  70. status.update(f"[red]Fehler: {e}[/red]")
  71. return
  72. if result is None:
  73. status.update("[red]Keine Antwort vom Server[/red]")
  74. return
  75. # Ergebnis anzeigen
  76. if result.valid:
  77. status.update("[green bold]Validierung erfolgreich[/green bold]")
  78. else:
  79. status.update("[red bold]Validierung fehlgeschlagen[/red bold]")
  80. # Fehler
  81. if result.errors:
  82. lines = "\n".join(f" [red]\u2718[/red] {e}" for e in result.errors)
  83. errors_widget.update(f"[bold]Fehler:[/bold]\n{lines}")
  84. else:
  85. errors_widget.update("")
  86. # Warnungen
  87. if result.warnings:
  88. lines = "\n".join(f" [yellow]\u26A0[/yellow] {w}" for w in result.warnings)
  89. warnings_widget.update(f"[bold]Warnungen:[/bold]\n{lines}")
  90. else:
  91. warnings_widget.update("")
  92. # GPU-Info
  93. gpu_rows = []
  94. if result.gpu_available:
  95. gpu_rows.append(("GPU", f"[green]{result.gpu_name}[/green]"))
  96. gpu_rows.append(("GPU-Speicher", f"{result.gpu_memory_mb:.0f} MB"))
  97. else:
  98. gpu_rows.append(("GPU", "[yellow]Nicht verfuegbar[/yellow]"))
  99. gpu_table.update_data(gpu_rows)