Skip to content

Commit b7e7726

Browse files
committed
feat: introduce Engine ABC and SubprocessEngine
1 parent 879bae2 commit b7e7726

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""Base engine for libtmux."""
2+
3+
from __future__ import annotations
4+
5+
import typing as t
6+
from abc import ABC, abstractmethod
7+
8+
if t.TYPE_CHECKING:
9+
from libtmux.common import tmux_cmd
10+
11+
12+
class Engine(ABC):
13+
"""Abstract base class for tmux execution engines."""
14+
15+
@abstractmethod
16+
def run(self, *args: t.Any) -> tmux_cmd:
17+
"""Run a tmux command and return the result."""
18+
...
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"""Subprocess engine for libtmux."""
2+
3+
from __future__ import annotations
4+
5+
import logging
6+
import shutil
7+
import subprocess
8+
import typing as t
9+
10+
from libtmux import exc
11+
from libtmux._internal.engines.base import Engine
12+
from libtmux.common import tmux_cmd
13+
14+
logger = logging.getLogger(__name__)
15+
16+
17+
class SubprocessEngine(Engine):
18+
"""Engine that runs tmux commands via subprocess."""
19+
20+
def run(self, *args: t.Any) -> tmux_cmd:
21+
"""Run a tmux command using subprocess.Popen."""
22+
tmux_bin = shutil.which("tmux")
23+
if not tmux_bin:
24+
raise exc.TmuxCommandNotFound
25+
26+
cmd = [tmux_bin]
27+
cmd += args # add the command arguments to cmd
28+
cmd = [str(c) for c in cmd]
29+
30+
try:
31+
process = subprocess.Popen(
32+
cmd,
33+
stdout=subprocess.PIPE,
34+
stderr=subprocess.PIPE,
35+
text=True,
36+
errors="backslashreplace",
37+
)
38+
stdout_str, stderr_str = process.communicate()
39+
returncode = process.returncode
40+
except Exception:
41+
logger.exception(f"Exception for {subprocess.list2cmdline(cmd)}")
42+
raise
43+
44+
stdout_split = stdout_str.split("\n")
45+
# remove trailing newlines from stdout
46+
while stdout_split and stdout_split[-1] == "":
47+
stdout_split.pop()
48+
49+
stderr_split = stderr_str.split("\n")
50+
stderr = list(filter(None, stderr_split)) # filter empty values
51+
52+
if "has-session" in cmd and len(stderr) and not stdout_split:
53+
stdout = [stderr[0]]
54+
else:
55+
stdout = stdout_split
56+
57+
logger.debug(
58+
"self.stdout for {cmd}: {stdout}".format(
59+
cmd=" ".join(cmd),
60+
stdout=stdout,
61+
),
62+
)
63+
64+
return tmux_cmd(
65+
cmd=cmd,
66+
stdout=stdout,
67+
stderr=stderr,
68+
returncode=returncode,
69+
)

0 commit comments

Comments
 (0)