Skip to content

Commit 2fa994f

Browse files
committed
docs: Improve neo.py
1 parent e229f46 commit 2fa994f

File tree

2 files changed

+116
-25
lines changed

2 files changed

+116
-25
lines changed

src/libtmux/neo.py

Lines changed: 113 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,21 @@
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

320
from __future__ import annotations
421

@@ -12,14 +29,13 @@
1229
from libtmux.formats import FORMAT_SEPARATOR
1330

1431
if 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-
2037
logger = logging.getLogger(__name__)
2138

22-
2339
OutputRaw = dict[str, t.Any]
2440
OutputsRaw = list[OutputRaw]
2541

@@ -36,7 +52,26 @@
3652

3753
@dataclasses.dataclass()
3854
class 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

193245
def 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

src/libtmux/pane.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,9 @@ def send_keys(
347347

348348
@t.overload
349349
def display_message(
350-
self, cmd: str, get_text: t.Literal[True]
350+
self,
351+
cmd: str,
352+
get_text: t.Literal[True],
351353
) -> str | list[str]: ...
352354

353355
@t.overload

0 commit comments

Comments
 (0)