1- """Tools for hydrating tmux data into python dataclass objects."""
1+ """Provide tools for hydrating tmux data into Python dataclass objects.
2+
3+ This module defines mechanisms for fetching and converting tmux command outputs
4+ into Python dataclasses (via the :class:`Obj` base class). This facilitates
5+ more structured and Pythonic interaction with tmux objects such as sessions,
6+ windows, and panes.
7+
8+ Implementation Notes
9+ --------------------
10+ - :func:`fetch_objs` retrieves lists of raw field data from tmux.
11+ - :func:`fetch_obj` retrieves a single tmux object by its key and ID.
12+ - :class:`Obj` is a base dataclass that holds common tmux fields.
13+
14+ See Also
15+ --------
16+ :func:`fetch_objs`
17+ :func:`fetch_obj`
18+ """
219
320from __future__ import annotations
421
1229from libtmux .formats import FORMAT_SEPARATOR
1330
1431if t .TYPE_CHECKING :
32+ from libtmux .server import Server
33+
1534 ListCmd = t .Literal ["list-sessions" , "list-windows" , "list-panes" ]
1635 ListExtraArgs = t .Optional [Iterable [str ]]
1736
18- from libtmux .server import Server
19-
2037logger = logging .getLogger (__name__ )
2138
22-
2339OutputRaw = dict [str , t .Any ]
2440OutputsRaw = list [OutputRaw ]
2541
3652
3753@dataclasses .dataclass ()
3854class Obj :
39- """Dataclass of generic tmux object."""
55+ """Represent a generic tmux dataclass object with standard fields.
56+
57+ Objects extending this base class derive many fields from tmux commands
58+ via the :func:`fetch_objs` and :func:`fetch_obj` functions.
59+
60+ Parameters
61+ ----------
62+ server
63+ The :class:`Server` instance owning this tmux object.
64+
65+ Attributes
66+ ----------
67+ pane_id, window_id, session_id, etc.
68+ Various tmux-specific fields automatically populated when refreshed.
69+
70+ Examples
71+ --------
72+ Subclasses of :class:`Obj` typically represent concrete tmux entities
73+ (e.g., sessions, windows, and panes).
74+ """
4075
4176 server : Server
4277
@@ -91,7 +126,7 @@ class Obj:
91126 mouse_standard_flag : str | None = None
92127 next_session_id : str | None = None
93128 origin_flag : str | None = None
94- pane_active : str | None = None # Not detected by script
129+ pane_active : str | None = None
95130 pane_at_bottom : str | None = None
96131 pane_at_left : str | None = None
97132 pane_at_right : str | None = None
@@ -146,7 +181,7 @@ class Obj:
146181 uid : str | None = None
147182 user : str | None = None
148183 version : str | None = None
149- window_active : str | None = None # Not detected by script
184+ window_active : str | None = None
150185 window_active_clients : str | None = None
151186 window_active_sessions : str | None = None
152187 window_activity : str | None = None
@@ -176,6 +211,24 @@ def _refresh(
176211 list_cmd : ListCmd = "list-panes" ,
177212 list_extra_args : ListExtraArgs | None = None ,
178213 ) -> None :
214+ """Refresh fields for this object by re-fetching from tmux.
215+
216+ Parameters
217+ ----------
218+ obj_key
219+ The field name to match (e.g. 'pane_id').
220+ obj_id
221+ The object identifier (e.g. '%1').
222+ list_cmd
223+ The tmux command to use (e.g. 'list-panes').
224+ list_extra_args
225+ Additional arguments to pass to the tmux command.
226+
227+ Raises
228+ ------
229+ exc.TmuxObjectDoesNotExist
230+ If the requested object does not exist in tmux's output.
231+ """
179232 assert isinstance (obj_id , str )
180233 obj = fetch_obj (
181234 obj_key = obj_key ,
@@ -185,50 +238,63 @@ def _refresh(
185238 server = self .server ,
186239 )
187240 assert obj is not None
188- if obj is not None :
189- for k , v in obj .items ():
190- setattr (self , k , v )
241+ for k , v in obj .items ():
242+ setattr (self , k , v )
191243
192244
193245def fetch_objs (
194246 server : Server ,
195247 list_cmd : ListCmd ,
196248 list_extra_args : ListExtraArgs | None = None ,
197249) -> OutputsRaw :
198- """Fetch a listing of raw data from a tmux command."""
250+ """Fetch a list of raw data from a tmux command.
251+
252+ Parameters
253+ ----------
254+ server
255+ The :class:`Server` against which to run the command.
256+ list_cmd
257+ The tmux command to run (e.g. 'list-sessions', 'list-windows', 'list-panes').
258+ list_extra_args
259+ Any extra arguments (e.g. ['-a']).
260+
261+ Returns
262+ -------
263+ list of dict
264+ A list of dictionaries of field-name to field-value mappings.
265+
266+ Raises
267+ ------
268+ exc.LibTmuxException
269+ If tmux reports an error in stderr.
270+ """
199271 formats = list (Obj .__dataclass_fields__ .keys ())
200272
201273 cmd_args : list [str | int ] = []
202-
203274 if server .socket_name :
204275 cmd_args .insert (0 , f"-L{ server .socket_name } " )
205276 if server .socket_path :
206277 cmd_args .insert (0 , f"-S{ server .socket_path } " )
207- tmux_formats = [f"#{{{ f } }}{ FORMAT_SEPARATOR } " for f in formats ]
208278
209- tmux_cmds = [
210- * cmd_args ,
211- list_cmd ,
212- ]
279+ tmux_formats = [f"#{{{ f } }}{ FORMAT_SEPARATOR } " for f in formats ]
280+ tmux_cmds = [* cmd_args , list_cmd ]
213281
214282 if list_extra_args is not None and isinstance (list_extra_args , Iterable ):
215283 tmux_cmds .extend (list (list_extra_args ))
216284
217285 tmux_cmds .append ("-F{}" .format ("" .join (tmux_formats )))
218-
219- proc = tmux_cmd (* tmux_cmds ) # output
286+ proc = tmux_cmd (* tmux_cmds )
220287
221288 if proc .stderr :
222289 raise exc .LibTmuxException (proc .stderr )
223290
224291 obj_output = proc .stdout
225-
226292 obj_formatters = [
227293 dict (zip (formats , formatter .split (FORMAT_SEPARATOR )))
228294 for formatter in obj_output
229295 ]
230296
231- # Filter empty values
297+ # Filter out empty values
232298 return [{k : v for k , v in formatter .items () if v } for formatter in obj_formatters ]
233299
234300
@@ -239,7 +305,31 @@ def fetch_obj(
239305 list_cmd : ListCmd = "list-panes" ,
240306 list_extra_args : ListExtraArgs | None = None ,
241307) -> OutputRaw :
242- """Fetch raw data from tmux command."""
308+ """Fetch a single tmux object by key and ID.
309+
310+ Parameters
311+ ----------
312+ server
313+ The :class:`Server` instance to query.
314+ obj_key
315+ The field name to look for (e.g., 'pane_id').
316+ obj_id
317+ The specific ID to match (e.g., '%0').
318+ list_cmd
319+ The tmux command to run ('list-panes', 'list-windows', etc.).
320+ list_extra_args
321+ Extra arguments to pass (e.g., ['-a']).
322+
323+ Returns
324+ -------
325+ dict
326+ A dictionary of field-name to field-value mappings for the object.
327+
328+ Raises
329+ ------
330+ exc.TmuxObjectDoesNotExist
331+ If no matching object is found in tmux's output.
332+ """
243333 obj_formatters_filtered = fetch_objs (
244334 server = server ,
245335 list_cmd = list_cmd ,
@@ -250,6 +340,7 @@ def fetch_obj(
250340 for _obj in obj_formatters_filtered :
251341 if _obj .get (obj_key ) == obj_id :
252342 obj = _obj
343+ break
253344
254345 if obj is None :
255346 raise exc .TmuxObjectDoesNotExist (
@@ -259,6 +350,4 @@ def fetch_obj(
259350 list_extra_args = list_extra_args ,
260351 )
261352
262- assert obj is not None
263-
264353 return obj
0 commit comments