beta_leet.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. from __future__ import annotations
  2. import dataclasses
  3. import os
  4. import pathlib
  5. import subprocess
  6. import sys
  7. import click
  8. from typing_extensions import Never
  9. from wandb.analytics import get_sentry
  10. from wandb.env import error_reporting_enabled, is_debug
  11. from wandb.sdk import wandb_setup
  12. from wandb.util import get_core_path
  13. @dataclasses.dataclass(frozen=True)
  14. class LaunchConfig:
  15. """Configuration for launching LEET."""
  16. wandb_dir: str
  17. run_file: str | None = None
  18. def _fatal(message: str) -> Never:
  19. """Print an error message and exit with code 1."""
  20. click.echo(f"Error: {message}", err=True)
  21. sys.exit(1)
  22. def _find_wandb_file_in_dir(dir_path: pathlib.Path) -> pathlib.Path | None:
  23. """Find a run-*.wandb file in the given directory.
  24. Returns None if not found or multiple found.
  25. """
  26. wandb_files = list(dir_path.glob("run-*.wandb"))
  27. if len(wandb_files) == 1:
  28. return wandb_files[0]
  29. return None
  30. def _resolve_path(path: str | None) -> LaunchConfig:
  31. """Resolve the given path into a LaunchConfig.
  32. Behavior:
  33. - No path: Use default wandb_dir (workspace mode)
  34. - .wandb file: Parent's parent as wandb_dir, file as run_file
  35. - Run directory: Parent as wandb_dir, found .wandb as run_file
  36. - Other directory: Treat as wandb_dir (workspace mode)
  37. """
  38. if not path:
  39. wandb_dir = wandb_setup.singleton().settings.wandb_dir
  40. return LaunchConfig(wandb_dir=str(wandb_dir))
  41. resolved = pathlib.Path(path).resolve()
  42. if resolved.is_file():
  43. if resolved.suffix == ".wandb":
  44. run_dir = resolved.parent
  45. wandb_dir = run_dir.parent
  46. return LaunchConfig(wandb_dir=str(wandb_dir), run_file=str(resolved))
  47. else:
  48. _fatal(f"Not a .wandb file: {resolved}")
  49. if resolved.is_dir():
  50. wandb_file = _find_wandb_file_in_dir(resolved)
  51. if wandb_file:
  52. wandb_dir = resolved.parent
  53. return LaunchConfig(wandb_dir=str(wandb_dir), run_file=str(wandb_file))
  54. else:
  55. return LaunchConfig(wandb_dir=str(resolved))
  56. _fatal(f"Path does not exist: {resolved}")
  57. def _base_args() -> list[str]:
  58. """Build the common base arguments for wandb-core leet commands."""
  59. args = [get_core_path(), "leet"]
  60. if not error_reporting_enabled():
  61. args.append("--no-observability")
  62. if is_debug(default="False"):
  63. args.extend(["--log-level", "-4"])
  64. return args
  65. def _run_core(args: list[str]) -> Never:
  66. """Run wandb-core with the given arguments and exit with its return code."""
  67. try:
  68. result = subprocess.run(args, env=os.environ, close_fds=True)
  69. sys.exit(result.returncode)
  70. except Exception as e:
  71. get_sentry().reraise(e)
  72. def launch(path: str | None, pprof: str) -> Never:
  73. """Launch the LEET TUI."""
  74. get_sentry().configure_scope(process_context="leet")
  75. config = _resolve_path(path)
  76. args = _base_args()
  77. if config.run_file:
  78. args.extend(["--run-file", config.run_file])
  79. if pprof:
  80. args.extend(["--pprof", pprof])
  81. args.append(config.wandb_dir)
  82. _run_core(args)
  83. def launch_config() -> Never:
  84. """Launch the LEET configuration editor."""
  85. get_sentry().configure_scope(process_context="leet-config")
  86. args = _base_args()
  87. args.append("--config")
  88. _run_core(args)
  89. def launch_symon(pprof: str = "", interval: str = "") -> Never:
  90. """Launch the standalone system monitor."""
  91. get_sentry().configure_scope(process_context="leet-symon")
  92. args = _base_args()
  93. args.append("--symon")
  94. if pprof:
  95. args.extend(["--pprof", pprof])
  96. if interval:
  97. args.extend(["--interval", interval])
  98. _run_core(args)