From 0a99e55d5399fdf1b9efd81ddb6b30dfb2ed9f3f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 7 Mar 2026 17:39:36 -0600 Subject: [PATCH 1/3] common(fix[has_minimum_version]): cache get_version() to avoid double subprocess MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit why: has_minimum_version() called get_version() twice — once for the comparison and again inside the error message. On the error path this forked two tmux subprocesses when one is sufficient. what: - Assign get_version() result to current_version before the comparison - Reuse current_version in the VersionTooLow error message --- src/libtmux/common.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libtmux/common.py b/src/libtmux/common.py index a84068042..bc9140b24 100644 --- a/src/libtmux/common.py +++ b/src/libtmux/common.py @@ -456,11 +456,12 @@ def has_minimum_version(raises: bool = True) -> bool: Versions will now remove trailing letters per `Issue 55 `_. """ - if get_version() < LooseVersion(TMUX_MIN_VERSION): + current_version = get_version() + if current_version < LooseVersion(TMUX_MIN_VERSION): if raises: msg = ( f"libtmux only supports tmux {TMUX_MIN_VERSION} and greater. This " - f"system has {get_version()} installed. Upgrade your tmux to use " + f"system has {current_version} installed. Upgrade your tmux to use " "libtmux, or use libtmux v0.48.x for older tmux versions." ) raise exc.VersionTooLow(msg) From 2335b2baf13d96d8b77a84a270c66f300bdd5e2a Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 7 Mar 2026 18:00:46 -0600 Subject: [PATCH 2/3] server(docs[raise_if_dead]): add Raises section documenting both exception types why: raise_if_dead can raise TmuxCommandNotFound (missing binary) or CalledProcessError (server not running), but the docstring had no Raises section. Added after a fresh PR review surfaced the gap. what: - Add NumPy-style Raises section before the existing doctest - Document TmuxCommandNotFound and CalledProcessError with conditions --- src/libtmux/server.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libtmux/server.py b/src/libtmux/server.py index 68881b158..255954d6b 100644 --- a/src/libtmux/server.py +++ b/src/libtmux/server.py @@ -213,6 +213,14 @@ def is_alive(self) -> bool: def raise_if_dead(self) -> None: """Raise if server not connected. + Raises + ------ + :exc:`exc.TmuxCommandNotFound` + When the tmux binary cannot be found or executed. + :class:`subprocess.CalledProcessError` + When the tmux server is not running (non-zero exit from + ``list-sessions``). + >>> tmux = Server(socket_name="no_exist") >>> try: ... tmux.raise_if_dead() From cd81d15419207572105612703831be53e84ecdd8 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 7 Mar 2026 18:01:47 -0600 Subject: [PATCH 3/3] server(fix[raise_if_dead]): suppress check_call stdout/stderr why: subprocess.check_call without stdout/stderr redirection inherits the parent process's file descriptors, printing tmux output directly to the terminal. Library code should not produce terminal noise. what: - Pass stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL to check_call --- src/libtmux/server.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libtmux/server.py b/src/libtmux/server.py index 255954d6b..181e5223c 100644 --- a/src/libtmux/server.py +++ b/src/libtmux/server.py @@ -240,7 +240,11 @@ def raise_if_dead(self) -> None: if self.config_file: cmd_args.insert(0, f"-f{self.config_file}") - subprocess.check_call([tmux_bin, *cmd_args]) + subprocess.check_call( + [tmux_bin, *cmd_args], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ) # # Command