Skip to content

Commit 4136aef

Browse files
committed
Refactor and add tag listing
1 parent b092d5e commit 4136aef

File tree

4 files changed

+100
-56
lines changed

4 files changed

+100
-56
lines changed

simvue_cli/run.py renamed to simvue_cli/actions.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
"""
2-
Simvue CLI run
3-
==============
2+
Simvue CLI Actions
3+
==================
44
5-
Handles creation of and maintaining of runs between CLI calls
5+
Contains callbacks for CLI commands
66
"""
77
__author__ = "Kristian Zarebski"
88
__date__ = "2024-09-09"
@@ -206,7 +206,7 @@ def set_run_status(run_id: str, status: str, **kwargs) -> None:
206206
data={"status": status} | kwargs
207207
)
208208

209-
if status in ("completed", "lost", "failed", "terminated"):
209+
if status in {"completed", "lost", "failed", "terminated"}:
210210
run_shelf_file.unlink()
211211

212212

@@ -264,24 +264,25 @@ def user_info() -> dict:
264264
response = sv_api.get(
265265
f"{simvue_instance._config.server.url}/api/whoami", headers=simvue_instance._headers
266266
)
267-
if response.status_code != 200:
268-
return response.status_code
269-
270-
return response.json()
267+
return response.status_code if response.status_code != 200 else response.json()
271268

272269

273270
def get_runs_list(**kwargs) -> None:
274271
"""Retrieve list of Simvue runs"""
275272
client = Client()
276-
runs = client.get_runs(**kwargs)
277-
return runs
273+
return client.get_runs(**kwargs)
274+
275+
276+
def get_tag_list(**kwargs) -> None:
277+
"""Retrieve list of Simvue tags"""
278+
client = Client()
279+
return client.get_tags(**kwargs)
278280

279281

280282
def get_folders_list(**kwargs) -> None:
281283
"""Retrieve list of Simvue runs"""
282284
client = Client()
283-
runs = client.get_folders(**kwargs)
284-
return runs
285+
return client.get_folders(**kwargs)
285286

286287

287288
def get_run(run_id: str) -> None:

simvue_cli/cli/__init__.py

Lines changed: 83 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@
2828
import simvue as simvue_client
2929

3030
import simvue_cli.config
31-
import simvue_cli.run
31+
import simvue_cli.actions
3232
import simvue_cli.server
3333

34-
from simvue_cli.cli.display import create_runs_display, SIMVUE_LOGO
34+
from simvue_cli.cli.display import create_objects_display, SIMVUE_LOGO
3535
from simvue_cli.validation import SimvueName, SimvueFolder, JSONType
3636

3737
from click_params import PUBLIC_URL
@@ -70,7 +70,7 @@ def ping_server(timeout: int | None) -> None:
7070
return
7171
start_time = time.time()
7272
try:
73-
server_version: int | str = simvue_cli.run.get_server_version()
73+
server_version: int | str = simvue_cli.actions.get_server_version()
7474
if (status_code := 200 if isinstance(server_version, str) else server_version) != 200:
7575
raise RuntimeError
7676
successful_pings += 1
@@ -92,7 +92,7 @@ def whoami(user: bool, tenant: bool) -> None:
9292
if user and tenant:
9393
click.secho("cannot print 'only' with more than one choice")
9494
raise click.Abort
95-
user_info = simvue_cli.run.user_info()
95+
user_info = simvue_cli.actions.user_info()
9696
user_name = user_info.get("username")
9797
tenant_info = user_info.get("tenant")
9898
if user:
@@ -114,14 +114,16 @@ def about_simvue(ctx) -> None:
114114
)
115115
click.echo(f"\n{width * '='}\n")
116116
click.echo(f"\n{'\t' * int(0.04 * width)} Provided under the Apache-2.0 License")
117-
click.echo(f"{'\t' * int(0.04 * width)}© Copyright {datetime.datetime.today().strftime('%Y')} Simvue Development Team\n")
117+
click.echo(
118+
f"{'\t' * int(0.04 * width)}© Copyright {datetime.datetime.now().strftime('%Y')} Simvue Development Team\n"
119+
)
118120
out_table: list[list[str]] = []
119121
with contextlib.suppress(importlib.metadata.PackageNotFoundError):
120122
out_table.append(["CLI Version: ", importlib.metadata.version(simvue_cli.__name__)])
121123
with contextlib.suppress(importlib.metadata.PackageNotFoundError):
122124
out_table.append(["Python API Version: ", importlib.metadata.version(simvue_client.__name__)])
123125
with contextlib.suppress(Exception):
124-
server_version: int | str = simvue_cli.run.get_server_version()
126+
server_version: int | str = simvue_cli.actions.get_server_version()
125127
if isinstance(server_version, int):
126128
raise RuntimeError
127129
out_table.append(["Server Version: ", server_version])
@@ -210,9 +212,9 @@ def create_run(
210212
) -> None:
211213
"""Initialise a new Simvue run"""
212214
run_params |= {"running": not create_only, "tags": list(tag) if tag else None}
213-
run_id: str = simvue_cli.run.create_simvue_run(**run_params)
215+
run_id: str = simvue_cli.actions.create_simvue_run(**run_params)
214216

215-
click.echo(click.style(run_id) if not ctx.obj["plain"] else run_id)
217+
click.echo(run_id if ctx.obj["plain"] else click.style(run_id))
216218

217219

218220
@simvue_run.command("remove")
@@ -226,7 +228,7 @@ def delete_run(ctx, run_ids: list[str] | None, interactive: bool) -> None:
226228
run_ids = run_ids_str.split(" ")
227229

228230
for run_id in run_ids:
229-
if not (simvue_cli.run.get_run(run_id)):
231+
if not (simvue_cli.actions.get_run(run_id)):
230232
error_msg = f"Run '{run_id}' not found"
231233
if ctx.obj["plain"]:
232234
print(error_msg)
@@ -240,12 +242,10 @@ def delete_run(ctx, run_ids: list[str] | None, interactive: bool) -> None:
240242
continue
241243

242244
try:
243-
simvue_cli.run.delete_run(run_id)
245+
simvue_cli.actions.delete_run(run_id)
244246
except ValueError as e:
245247
click.echo(
246-
click.style(e.args[0], fg="red", bold=True)
247-
if not ctx.obj["plain"]
248-
else e.args[0]
248+
e.args[0] if ctx.obj["plain"] else click.style(e.args[0], fg="red", bold=True)
249249
)
250250
sys.exit(1)
251251

@@ -262,20 +262,18 @@ def delete_run(ctx, run_ids: list[str] | None, interactive: bool) -> None:
262262
@click.argument("run_id", type=str)
263263
def close_run(ctx, run_id: str) -> None:
264264
"""Mark an active run as completed"""
265-
if not (simvue_cli.run.get_run(run_id)):
265+
if not (simvue_cli.actions.get_run(run_id)):
266266
error_msg = f"Run '{run_id}' not found"
267267
if ctx.obj["plain"]:
268268
print(error_msg)
269269
else:
270270
click.secho(error_msg, fg="red", bold=True)
271271
sys.exit(1)
272272
try:
273-
simvue_cli.run.set_run_status(run_id, "completed")
273+
simvue_cli.actions.set_run_status(run_id, "completed")
274274
except ValueError as e:
275275
click.echo(
276-
click.style(e.args[0], fg="red", bold=True)
277-
if not ctx.obj["plain"]
278-
else e.args[0]
276+
e.args[0] if ctx.obj["plain"] else click.style(e.args[0], fg="red", bold=True)
279277
)
280278
sys.exit(1)
281279

@@ -292,38 +290,38 @@ def close_run(ctx, run_id: str) -> None:
292290
)
293291
def abort_run(ctx, run_id: str, reason: str) -> None:
294292
"""Abort an active run"""
295-
if not (simvue_cli.run.get_run(run_id)):
293+
if not (simvue_cli.actions.get_run(run_id)):
296294
error_msg = f"Run '{run_id}' not found"
297295
if ctx.obj["plain"]:
298296
print(error_msg)
299297
else:
300298
click.secho(error_msg, fg="red", bold=True)
301299
sys.exit(1)
302-
simvue_cli.run.set_run_status(run_id, "terminated", reason=reason)
300+
simvue_cli.actions.set_run_status(run_id, "terminated", reason=reason)
303301

304302

305303
@simvue_run.command("log.metrics")
306304
@click.argument("run_id", type=str)
307305
@click.argument("metrics", type=JSONType)
308306
def log_metrics(run_id: str, metrics: dict) -> None:
309307
"""Log metrics to Simvue server"""
310-
simvue_cli.run.log_metrics(run_id, metrics)
308+
simvue_cli.actions.log_metrics(run_id, metrics)
311309

312310

313311
@simvue_run.command("log.event")
314312
@click.argument("run_id", type=str)
315313
@click.argument("event_message", type=str)
316314
def log_event(run_id: str, event_message: str) -> None:
317315
"""Log event to Simvue server"""
318-
simvue_cli.run.log_event(run_id, event_message)
316+
simvue_cli.actions.log_event(run_id, event_message)
319317

320318

321319
@simvue_run.command("metadata")
322320
@click.argument("run_id", type=str)
323321
@click.argument("metadata", type=JSONType)
324322
def update_metadata(run_id: str, metadata: dict) -> None:
325323
"""Update metadata for a run on the Simvue server"""
326-
simvue_cli.run.update_metadata(run_id, metadata)
324+
simvue_cli.actions.update_metadata(run_id, metadata)
327325

328326

329327
@simvue_run.command("list")
@@ -372,7 +370,7 @@ def list_runs(
372370
) -> None:
373371
"""Retrieve runs list from Simvue server"""
374372
kwargs |= {"filters": kwargs.get("filters" or [])}
375-
runs = simvue_cli.run.get_runs_list(**kwargs)
373+
runs = simvue_cli.actions.get_runs_list(**kwargs)
376374
columns = ["id"]
377375

378376
if created:
@@ -390,7 +388,7 @@ def list_runs(
390388
if status:
391389
columns.append("status")
392390

393-
table = create_runs_display(columns, runs, plain_text=ctx.obj["plain"], enumerate_=enumerate_, format=format)
391+
table = create_objects_display(columns, runs, plain_text=ctx.obj["plain"], enumerate_=enumerate_, format=format)
394392
click.echo(table)
395393

396394

@@ -405,7 +403,7 @@ def get_run_json(run_id: str) -> None:
405403
run_id = input()
406404

407405
try:
408-
run_info = simvue_cli.run.get_run(run_id)
406+
run_info = simvue_cli.actions.get_run(run_id)
409407
except RuntimeError as e:
410408
error_msg = f"Failed to retrieve run '{run_id}': {e.args[0]}"
411409
click.echo(error_msg, fg="red", bold=True)
@@ -451,9 +449,9 @@ def simvue_alert(ctx) -> None:
451449
@click.option("--email", is_flag=True, help="Notify by email if triggered", show_default=True)
452450
def create_alert(ctx, name: str, abort: bool=False, email: bool=False) -> None:
453451
"""Create a User alert"""
454-
result = simvue_cli.run.create_user_alert(name, abort, email)
452+
result = simvue_cli.actions.create_user_alert(name, abort, email)
455453
alert_id = result["id"]
456-
click.echo(click.style(alert_id) if not ctx.obj["plain"] else alert_id)
454+
click.echo(alert_id if ctx.obj["plain"] else click.style(alert_id))
457455

458456

459457
@simvue.command("monitor")
@@ -490,7 +488,7 @@ def monitor(ctx, tag: tuple[str, ...] | None, delimiter: str, **run_params) -> N
490488
metric_labels: list[str] = []
491489
run_params |= {"tags": list(tag) if tag else None}
492490

493-
run_id: str | None = simvue_cli.run.create_simvue_run(timeout=None, running=True, **run_params)
491+
run_id: str | None = simvue_cli.actions.create_simvue_run(timeout=None, running=True, **run_params)
494492

495493
if not run_id:
496494
raise click.Abort("Failed to created run")
@@ -502,7 +500,7 @@ def monitor(ctx, tag: tuple[str, ...] | None, delimiter: str, **run_params) -> N
502500
metric_labels = line
503501
continue
504502
try:
505-
simvue_cli.run.log_metrics(run_id, dict(zip(metric_labels, [float(i) for i in line])))
503+
simvue_cli.actions.log_metrics(run_id, dict(zip(metric_labels, [float(i) for i in line])))
506504
except (RuntimeError, ValueError) as e:
507505
if ctx.obj["plain"]:
508506
click.echo(e)
@@ -511,9 +509,9 @@ def monitor(ctx, tag: tuple[str, ...] | None, delimiter: str, **run_params) -> N
511509
sys.exit(1)
512510
click.echo(run_id)
513511
except KeyboardInterrupt as e:
514-
simvue_cli.run.set_run_status(run_id, "terminated")
512+
simvue_cli.actions.set_run_status(run_id, "terminated")
515513
raise click.Abort from e
516-
simvue_cli.run.set_run_status(run_id, "completed")
514+
simvue_cli.actions.set_run_status(run_id, "completed")
517515

518516

519517
@simvue.group("folder")
@@ -563,7 +561,7 @@ def folder_list(
563561
) -> None:
564562
"""Retrieve folders list from Simvue server"""
565563
kwargs |= {"filters": kwargs.get("filters" or [])}
566-
runs = simvue_cli.run.get_folders_list(**kwargs)
564+
runs = simvue_cli.actions.get_folders_list(**kwargs)
567565
if not runs:
568566
return
569567
columns = ["id"]
@@ -578,9 +576,60 @@ def folder_list(
578576
if description:
579577
columns.append("description")
580578

581-
table = create_runs_display(columns, runs, plain_text=ctx.obj["plain"], enumerate_=enumerate_, format=table_format)
579+
table = create_objects_display(columns, runs, plain_text=ctx.obj["plain"], enumerate_=enumerate_, format=table_format)
580+
click.echo(table)
581+
582+
583+
@simvue.group("tag")
584+
@click.pass_context
585+
def simvue_tag(ctx) -> None:
586+
"""Create or retrieve Simvue runs"""
587+
pass
588+
589+
590+
@simvue_tag.command("list")
591+
@click.pass_context
592+
@click.option(
593+
"--format",
594+
"table_format",
595+
type=click.Choice(list(tabulate._table_formats.keys())),
596+
help="Display as table with output format",
597+
default=None,
598+
)
599+
@click.option(
600+
"--enumerate",
601+
"enumerate_",
602+
is_flag=True,
603+
help="Show counter next to runs",
604+
default=False,
605+
show_default=True,
606+
)
607+
@click.option(
608+
"--count",
609+
type=int,
610+
help="Maximum number of runs to retrieve",
611+
default=20,
612+
show_default=True,
613+
)
614+
@click.option("--name", is_flag=True, help="Show names")
615+
@click.option("--color", is_flag=True, help="Show hex colors")
616+
def tag_list(ctx, count: int, enumerate_: bool, table_format: str | None, name: bool, color: bool, **kwargs) -> None:
617+
tags = simvue_cli.actions.get_tag_list(**kwargs)
618+
if not tags:
619+
return
620+
columns = ["id"]
621+
622+
if name:
623+
columns.append("name")
624+
625+
if color:
626+
columns.append("colour")
627+
628+
629+
table = create_objects_display(columns, tags, plain_text=ctx.obj["plain"], enumerate_=enumerate_, format=table_format)
582630
click.echo(table)
583631

584632

585633
if __name__ in "__main__":
586634
simvue()
635+

simvue_cli/cli/display.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def format_tags(
130130
}
131131

132132

133-
def create_runs_display(
133+
def create_objects_display(
134134
columns: list[str],
135135
runs: list[dict[str, typing.Any]],
136136
plain_text: bool,

simvue_cli/server.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,14 @@
1111
import socket
1212
import urllib.parse as urllib_parser
1313

14-
from simvue.factory.proxy import Simvue
15-
1614
def get_ip_of_url(url: str) -> str:
1715
"""Retrieves the IP address for the given URL as a string"""
1816
try:
19-
# Extract the hostname from the URL if necessary
20-
hostname = urllib_parser.urlparse(url).hostname
21-
22-
if not hostname:
17+
if hostname := urllib_parser.urlparse(url).hostname:
18+
return socket.gethostbyname(hostname)
19+
else:
2320
raise RuntimeError
2421

25-
# Get the IP address of the hostname
26-
ip_address = socket.gethostbyname(hostname)
27-
return ip_address
2822
except (socket.gaierror, RuntimeError):
2923
return "Unknown IP"
3024

0 commit comments

Comments
 (0)