From 03731a2a67bcd902ff7b50abf7318f78e0902609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Fri, 2 May 2025 12:25:52 +0200 Subject: [PATCH 1/3] run_local: allow stdin to be a file descriptor --- pkgs/clan-cli/clan_cli/cmd.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pkgs/clan-cli/clan_cli/cmd.py b/pkgs/clan-cli/clan_cli/cmd.py index 16c2d7e6c..5b0d6bfd1 100644 --- a/pkgs/clan-cli/clan_cli/cmd.py +++ b/pkgs/clan-cli/clan_cli/cmd.py @@ -259,7 +259,7 @@ if os.environ.get("CLAN_CLI_PERF"): @dataclass class RunOpts: - input: bytes | None = None + input: IO[bytes] | bytes | None = None stdout: IO[bytes] | None = None stderr: IO[bytes] | None = None env: dict[str, str] | None = None @@ -329,7 +329,7 @@ def run( if options.requires_root_perm: cmd = cmd_with_root(cmd, options.graphical_perm) - if options.input: + if options.input and isinstance(options.input, bytes): if any(not ch.isprintable() for ch in options.input.decode("ascii", "replace")): filtered_input = "<>" else: @@ -344,7 +344,7 @@ def run( start = timeit.default_timer() with ExitStack() as stack: - stdin = subprocess.PIPE if options.input is not None else None + stdin = subprocess.PIPE if isinstance(options.input, bytes) else options.input process = stack.enter_context( subprocess.Popen( cmd, @@ -364,13 +364,18 @@ def run( else: stack.enter_context(terminate_process_group(process)) + if isinstance(options.input, bytes): + input_bytes = options.input + else: + input_bytes = None + stdout_buf, stderr_buf = handle_io( process, options.log, prefix=options.prefix, msg_color=options.msg_color, timeout=options.timeout, - input_bytes=options.input, + input_bytes=input_bytes, stdout=options.stdout, stderr=options.stderr, ) From f5277c989ac931df2a8e61cb14f09c94421da36f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Fri, 2 May 2025 13:34:55 +0200 Subject: [PATCH 2/3] Host: always set needs_user_terminal for ssh commands, only override prefix if given by user --- pkgs/clan-cli/clan_cli/ssh/host.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pkgs/clan-cli/clan_cli/ssh/host.py b/pkgs/clan-cli/clan_cli/ssh/host.py index 1eca93a68..ecd357c38 100644 --- a/pkgs/clan-cli/clan_cli/ssh/host.py +++ b/pkgs/clan-cli/clan_cli/ssh/host.py @@ -122,6 +122,9 @@ class Host: if extra_env is None: extra_env = {} + if opts is None: + opts = RunOpts() + # If we are not root and we need to become root, prepend sudo sudo = "" if become_root and self.user != "root": @@ -132,11 +135,10 @@ class Host: for k, v in extra_env.items(): env_vars.append(f"{shlex.quote(k)}={shlex.quote(v)}") - if opts is None: - opts = RunOpts() - else: - opts.needs_user_terminal = True + if opts.prefix is None: opts.prefix = self.command_prefix + # always set needs_user_terminal to True because ssh asks for passwords + opts.needs_user_terminal = True if opts.cwd is not None: msg = "cwd is not supported for remote commands" From f6899166c733283fca2dc7af3bb2067b370e1407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Fri, 2 May 2025 15:09:51 +0200 Subject: [PATCH 3/3] cmd: don't shadow time module --- pkgs/clan-cli/clan_cli/cmd.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pkgs/clan-cli/clan_cli/cmd.py b/pkgs/clan-cli/clan_cli/cmd.py index 5b0d6bfd1..fb5db7b5e 100644 --- a/pkgs/clan-cli/clan_cli/cmd.py +++ b/pkgs/clan-cli/clan_cli/cmd.py @@ -244,12 +244,12 @@ class TimeTable: # Print in default color print(f"Took {v} for command: '{k}'") - def add(self, cmd: str, time: float) -> None: + def add(self, cmd: str, duration: float) -> None: with self.lock: if cmd in self.table: - self.table[cmd] += time + self.table[cmd] += duration else: - self.table[cmd] = time + self.table[cmd] = duration TIME_TABLE = None @@ -423,6 +423,3 @@ def run_no_stdout( cmd, opts, ) - - -# type: ignore