Merge pull request 'clan-cli: made run_no_stdout runOpts compatible and make time table thread safe' (#2566) from Qubasa/clan-core:Qubasa-main into main

This commit is contained in:
clan-bot
2024-12-06 11:25:49 +00:00
3 changed files with 30 additions and 42 deletions

View File

@@ -4,6 +4,7 @@ from dataclasses import dataclass, field
from pathlib import Path from pathlib import Path
from typing import Any, Literal from typing import Any, Literal
from clan_cli.cmd import RunOpts
from clan_cli.errors import ClanError from clan_cli.errors import ClanError
from clan_cli.nix import nix_shell, run_no_stdout from clan_cli.nix import nix_shell, run_no_stdout
@@ -154,7 +155,7 @@ def show_block_devices(options: BlockDeviceOptions) -> Blockdevices:
"PATH,NAME,RM,SIZE,RO,MOUNTPOINTS,TYPE,ID-LINK", "PATH,NAME,RM,SIZE,RO,MOUNTPOINTS,TYPE,ID-LINK",
], ],
) )
proc = run_no_stdout(cmd, needs_user_terminal=True) proc = run_no_stdout(cmd, RunOpts(needs_user_terminal=True))
res = proc.stdout.strip() res = proc.stdout.strip()
blk_info: dict[str, Any] = json.loads(res) blk_info: dict[str, Any] = json.loads(res)

View File

@@ -6,6 +6,7 @@ import select
import shlex import shlex
import signal import signal
import subprocess import subprocess
import threading
import time import time
import timeit import timeit
import weakref import weakref
@@ -212,30 +213,33 @@ class TimeTable:
def __init__(self) -> None: def __init__(self) -> None:
self.table: dict[str, float] = {} self.table: dict[str, float] = {}
self.lock = threading.Lock()
weakref.finalize(self, self.table_print) weakref.finalize(self, self.table_print)
def table_print(self) -> None: def table_print(self) -> None:
print("======== CMD TIMETABLE ========") with self.lock:
print("======== CMD TIMETABLE ========")
# Sort the table by time in descending order # Sort the table by time in descending order
sorted_table = sorted( sorted_table = sorted(
self.table.items(), key=lambda item: item[1], reverse=True self.table.items(), key=lambda item: item[1], reverse=True
) )
for k, v in sorted_table: for k, v in sorted_table:
# Check if timedelta is greater than 1 second # Check if timedelta is greater than 1 second
if v > 1: if v > 1:
# Print in red # Print in red
print(f"\033[91mTook {v}s\033[0m for command: '{k}'") print(f"\033[91mTook {v}s\033[0m for command: '{k}'")
else: else:
# Print in default color # Print in default color
print(f"Took {v} for command: '{k}'") print(f"Took {v} for command: '{k}'")
def add(self, cmd: str, time: float) -> None: def add(self, cmd: str, time: float) -> None:
if cmd in self.table: with self.lock:
self.table[cmd] += time if cmd in self.table:
else: self.table[cmd] += time
self.table[cmd] = time else:
self.table[cmd] = time
TIME_TABLE = None TIME_TABLE = None
@@ -339,34 +343,17 @@ def run(
def run_no_stdout( def run_no_stdout(
cmd: list[str], cmd: list[str],
*, opts: RunOpts | None = None,
env: dict[str, str] | None = None,
cwd: Path | None = None,
log: Log = Log.STDERR,
prefix: str | None = None,
check: bool = True,
error_msg: str | None = None,
needs_user_terminal: bool = False,
shell: bool = False,
) -> CmdOut: ) -> CmdOut:
""" """
Like run, but automatically suppresses all output, if not in DEBUG log level. Like run, but automatically suppresses all output, if not in DEBUG log level.
If in DEBUG log level the stdout of commands will be shown. If in DEBUG log level the stdout of commands will be shown.
""" """
opts = RunOpts( if opts is None:
env=env, opts = RunOpts()
cwd=cwd,
log=log,
check=check,
error_msg=error_msg,
needs_user_terminal=needs_user_terminal,
shell=shell,
prefix=prefix,
)
if cmdlog.isEnabledFor(logging.DEBUG): if cmdlog.isEnabledFor(logging.DEBUG):
opts.log = log if log.value > Log.STDERR.value else Log.STDERR opts.log = opts.log if opts.log.value > Log.STDERR.value else Log.STDERR
else:
opts.log = log
return run( return run(
cmd, cmd,

View File

@@ -8,7 +8,7 @@ from typing import Literal
from clan_cli.api import API from clan_cli.api import API
from clan_cli.api.modules import parse_frontmatter from clan_cli.api.modules import parse_frontmatter
from clan_cli.api.serde import dataclass_to_dict from clan_cli.api.serde import dataclass_to_dict
from clan_cli.cmd import run_no_stdout from clan_cli.cmd import RunOpts, run_no_stdout
from clan_cli.completions import add_dynamic_completer, complete_tags from clan_cli.completions import add_dynamic_completer, complete_tags
from clan_cli.dirs import specific_machine_dir from clan_cli.dirs import specific_machine_dir
from clan_cli.errors import ClanCmdError, ClanError from clan_cli.errors import ClanCmdError, ClanError
@@ -145,7 +145,7 @@ def check_machine_online(
], ],
) )
try: try:
proc = run_no_stdout(cmd, needs_user_terminal=True) proc = run_no_stdout(cmd, RunOpts(needs_user_terminal=True))
if proc.returncode != 0: if proc.returncode != 0:
return "Offline" return "Offline"
except ClanCmdError: except ClanCmdError: