Commit 34675024 authored by one's avatar one
Browse files

[hytop] Move some options to the root command

parent a927fefb
......@@ -23,10 +23,10 @@ Simple examples:
```bash
# Local node, all GPUs, 5-second rolling window
hytop gpu -n 1 --window 5
hytop -n 1 --window 5 gpu
# Two nodes, monitor only GPU 0 and 1
hytop gpu -H node01,node02 --devices 0,1 -n 1
hytop -H node01,node02 -n 1 gpu --devices 0,1
# Exit with code 0 when all monitored GPUs are available
hytop gpu --devices 0,1 --wait-idle
......@@ -42,12 +42,11 @@ hytop gpu --showpower --showtemp
Queue jobs in shared environments:
```bash
if hytop gpu -H node01,node02 --wait-idle --timeout 300; then
if hytop -H node01,node02 gpu --wait-idle --timeout 300; then
echo "GPUs available, starting workload..."
# YOUR COMMAND HERE (e.g., python train.py)
else
echo "Error: GPUs not available in time, aborting pipeline."
exit 1
fi
```
......
......@@ -4,10 +4,9 @@ from typing import Optional, Set
import typer
from hytop import __version__
from hytop.gpu.metrics import SUPPORTED_SHOW_FLAGS, normalized_show_flags
from hytop.gpu.service import run_monitor
from hytop.gpu.validators import parse_csv_ints, parse_csv_strings, parse_positive_float
from hytop.core.validators import parse_csv_ints
app = typer.Typer(
add_completion=False,
......@@ -17,21 +16,6 @@ app = typer.Typer(
SHOW_FLAG_ORDER_KEY = "show_flag_order"
def version_callback(value: bool) -> None:
"""Handle Typer eager version option.
Args:
value: Whether version flag was provided.
Raises:
typer.Exit: Raised to terminate command after printing version.
"""
if value:
typer.echo(__version__)
raise typer.Exit()
def remember_show_flag_callback(ctx: typer.Context, param: object, value: bool) -> bool:
"""Record --show* flags in parser encounter order."""
......@@ -49,29 +33,12 @@ def remember_show_flag_callback(ctx: typer.Context, param: object, value: bool)
@app.callback(invoke_without_command=True)
def gpu(
ctx: typer.Context,
hosts: str = typer.Option(
"localhost",
"--hosts",
"-H",
help="Comma-separated hosts, e.g. node01,node02. Default: localhost",
),
device_filter: str = typer.Option(
"",
"--devices",
"-d",
help="Comma-separated GPU IDs, e.g. 0,1. Default: all visible GPUs",
),
interval: float = typer.Option(
1.0,
"--interval",
"-n",
help="Polling interval in seconds. Default: 1.0",
),
window: float = typer.Option(
5.0,
"--window",
help="Single rolling window in seconds. Default: 5.0",
),
wait_idle: bool = typer.Option(
False,
"--wait-idle",
......@@ -112,19 +79,17 @@ def gpu(
"--timeout",
help="Max runtime in seconds. Effective only with --wait-idle.",
),
version: bool = typer.Option(
False,
"--version",
"-v",
callback=version_callback,
is_eager=True,
help="Show version and exit.",
),
) -> None:
"""Run GPU monitor."""
"""GPU monitoring commands."""
if ctx.obj is None:
typer.echo("argument error: global options not available", err=True)
raise typer.Exit(code=2)
try:
host_list = parse_csv_strings(hosts, "--hosts")
host_list = ctx.obj["hosts"]
interval = ctx.obj["interval"]
window_value = ctx.obj["window"]
selected_show_flags = {
"showtemp": showtemp,
"showpower": showpower,
......@@ -146,9 +111,8 @@ def gpu(
parsed_device_filter: Optional[Set[int]] = None
if device_filter:
parsed_device_filter = set(parse_csv_ints(device_filter, "--devices"))
window_value = parse_positive_float(str(window), "--window")
timeout_value = (
parse_positive_float(str(timeout), "--timeout")
float(timeout)
if timeout is not None
else None
)
......
from __future__ import annotations
import typer
from hytop import __version__
from hytop.cpu.cli import app as cpu_app
from hytop.gpu.cli import app as gpu_app
from hytop.core.validators import parse_csv_strings, parse_positive_float
app = typer.Typer(help="hytop toolkit command line")
app = typer.Typer(
help="hytop toolkit command line",
context_settings={"help_option_names": ["-h", "--help"]},
)
app.add_typer(cpu_app, name="cpu")
app.add_typer(gpu_app, name="gpu")
def version_callback(value: bool) -> None:
"""Handle Typer eager version option."""
if value:
typer.echo(__version__)
raise typer.Exit()
@app.callback(invoke_without_command=True)
def root(
ctx: typer.Context,
version: bool = typer.Option(
False,
"--version",
"-v",
callback=version_callback,
is_eager=True,
help="Show version and exit.",
),
hosts: str = typer.Option(
"localhost",
"--hosts",
"-H",
help="Comma-separated hosts, e.g. node01,node02. Default: localhost",
),
interval: float = typer.Option(
1.0,
"--interval",
"-n",
help="Polling interval in seconds. Default: 1.0",
),
window: float = typer.Option(
5.0,
"--window",
help="Single rolling window in seconds. Default: 5.0",
),
) -> None:
"""Root callback that parses global options and stores them in context."""
try:
host_list = parse_csv_strings(hosts, "--hosts")
window_value = parse_positive_float(str(window), "--window")
except ValueError as exc:
typer.echo(f"argument error: {exc}", err=True)
raise typer.Exit(code=2) from exc
ctx.obj = {
"hosts": host_list,
"interval": interval,
"window": window_value,
}
def main() -> None:
app()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment