From f651d521a750cf32e383cebe24a4b8db4341b034 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 06:48:34 -0600 Subject: [PATCH 01/14] pytest_plugin(fix): Move pathlib import outside TYPE_CHECKING block why: Make pathlib available at documentation build time for type hints what: - Move pathlib import from TYPE_CHECKING block to regular imports - Fixes forward reference resolution in sphinx-autodoc-typehints --- src/libtmux/pytest_plugin.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libtmux/pytest_plugin.py b/src/libtmux/pytest_plugin.py index 8b2d6589f..cc45ce7a9 100644 --- a/src/libtmux/pytest_plugin.py +++ b/src/libtmux/pytest_plugin.py @@ -7,6 +7,7 @@ import getpass import logging import os +import pathlib import typing as t import pytest @@ -17,8 +18,6 @@ from libtmux.test.random import get_test_session_name, namer if t.TYPE_CHECKING: - import pathlib - from libtmux.session import Session logger = logging.getLogger(__name__) From 7074d6a2a6023db9e9b5050444e11de5f4d76088 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 06:48:41 -0600 Subject: [PATCH 02/14] docs(conf): Add always_document_param_types config why: Ensure consistent parameter documentation in autodoc output what: - Add always_document_param_types = True for sphinx-autodoc-typehints --- docs/conf.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/conf.py b/docs/conf.py index db39b88fc..e625b2456 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -118,6 +118,9 @@ autodoc_class_signature = "separated" toc_object_entries_show_parents = "hide" +# sphinx-autodoc-typehints +always_document_param_types = True + # sphinx-copybutton copybutton_prompt_text = ( r">>> |\.\.\. |> |\$ |\# | In \[\d*\]: | {2,5}\.\.\.: | {5,8}: " From aee4bac286c3ccc34209977686e756bc878b7cc9 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 05:15:13 -0600 Subject: [PATCH 03/14] docs(CHANGES,MIGRATION): Fix non-consecutive header levels why: Sphinx/myst was warning about jumping from H2 to H4 what: - Change #### (H4) subsection headers to ### (H3) in both files for proper header level hierarchy (H1 -> H2 -> H3) --- CHANGES | 54 +++++++++++++++++++++++++++--------------------------- MIGRATION | 6 +++--- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/CHANGES b/CHANGES index 502d46c81..00f8daef4 100644 --- a/CHANGES +++ b/CHANGES @@ -55,7 +55,7 @@ unified, typed API for managing tmux options and hooks across all object types. ### What's New -#### Unified Options API (#516) +### Unified Options API (#516) All tmux objects now share a consistent options interface through {class}`~options.OptionsMixin`: @@ -104,7 +104,7 @@ window.unset_option('automatic-rename') | `suppress_warnings` | `-q` | Suppress warnings | | `append` | `-a` | Append to existing value | -#### Hook Management (#516) +### Hook Management (#516) New {class}`~hooks.HooksMixin` provides programmatic control over tmux hooks: @@ -151,7 +151,7 @@ session.set_hooks('session-renamed', { | `run_hook(hook)` | Run a hook immediately | | `set_hooks(hook, values)` | Set multiple indexed hooks at once | -#### SparseArray for Indexed Options (#516) +### SparseArray for Indexed Options (#516) tmux uses sparse indexed arrays for options like `command-alias[0]`, `command-alias[99]`, `terminal-features[0]`. Python lists can't represent @@ -173,7 +173,7 @@ gaps in indices, so libtmux introduces {class}`~_internal.sparse_array.SparseArr ['first', 'ninety-ninth'] ``` -#### New Constants (#516) +### New Constants (#516) - {class}`~constants.OptionScope` enum: `Server`, `Session`, `Window`, `Pane` - `OPTION_SCOPE_FLAG_MAP`: Maps scope to tmux flags (`-s`, `-w`, `-p`) @@ -181,7 +181,7 @@ gaps in indices, so libtmux introduces {class}`~_internal.sparse_array.SparseArr ### Breaking changes -#### Deprecated Window methods (#516) +### Deprecated Window methods (#516) The following methods are deprecated and will be removed in a future release: @@ -214,7 +214,7 @@ window.set_option('automatic-rename', True) ### Breaking Changes -#### tmux 1.8 to 3.1c support removed (#608) +### tmux 1.8 to 3.1c support removed (#608) Support for tmux versions below 3.2a has been removed. This completes the deprecation announced in v0.48.0. @@ -228,7 +228,7 @@ deprecation announced in v0.48.0. ### Breaking Changes -#### Minimum tmux version bumped to 3.2+ (606) +### Minimum tmux version bumped to 3.2+ (606) tmux versions below 3.2a are now deprecated. libtmux 0.48.0 will be the last version to support tmux below 3.2. This is to ensure support for hooks, options, @@ -243,7 +243,7 @@ release. Set `LIBTMUX_SUPPRESS_VERSION_WARNING=1` to suppress the warning. ### What's new -#### tmux 3.6 support (#607) +### tmux 3.6 support (#607) Added tmux 3.6 to test grid and `TMUX_MAX_VERSION` 3.4 -> 3.6. @@ -288,7 +288,7 @@ be a few months in waiting (watchers / snapshots are in development in #587). ### Breaking -#### Imports removed from libtmux.test (#580) +### Imports removed from libtmux.test (#580) Root-level of imports from `libtmux.test` are no longer possible. @@ -324,7 +324,7 @@ from libtmux.test.constants import ( ### Development -#### Test helpers: Increased coverage (#580) +### Test helpers: Increased coverage (#580) Several improvements to the test helper modules: @@ -338,7 +338,7 @@ Several improvements to the test helper modules: ### Breaking Changes -#### Test helpers: Refactor +### Test helpers: Refactor Test helper functionality has been split into focused modules (#578): @@ -403,7 +403,7 @@ from libtmux.test.temporary import temp_session, temp_window ### New Features -#### Context Managers support (#566) +### Context Managers support (#566) Added context manager support for all major object types: @@ -430,7 +430,7 @@ This makes it easier to write clean, safe code that properly cleans up tmux reso ### New Features -#### Server Initialization Callbacks +### Server Initialization Callbacks Server now accepts 2 new optional params, `socket_name_factory` and `on_init` callbacks (#565): @@ -439,7 +439,7 @@ Server now accepts 2 new optional params, `socket_name_factory` and `on_init` ca - Useful for creating multiple servers with unique names and tracking server instances - Socket name factory is tried after socket_name, maintaining backward compatibility -#### New test fixture: `TestServer` +### New test fixture: `TestServer` Add `TestServer` pytest fixture for creating temporary tmux servers (#565): @@ -493,7 +493,7 @@ Add `TestServer` pytest fixture for creating temporary tmux servers (#565): ### Development -#### chore: Implement PEP 563 deferred annotation resolution (#555) +### chore: Implement PEP 563 deferred annotation resolution (#555) - Add `from __future__ import annotations` to defer annotation resolution and reduce unnecessary runtime computations during type checking. - Enable Ruff checks for PEP-compliant annotations: @@ -549,13 +549,13 @@ _Maintenance only, no bug fixes or new features_ ### Breaking changes -#### Project and package management: poetry to uv (#547) +### Project and package management: poetry to uv (#547) [uv] is the new package and project manager for the project, replacing Poetry. [uv]: https://github.com/astral-sh/uv -#### Build system: poetry to hatchling (#547) +### Build system: poetry to hatchling (#547) [Build system] moved from [poetry] to [hatchling]. @@ -659,7 +659,7 @@ _Maintenance only, no bug fixes or new features_ ### Breaking changes -#### Command target change (#535) +### Command target change (#535) Commands: All `cmd()` methods using custom or overridden targets must use the keyword argument `target`. This avoids entanglement with inner shell values that include `-t` for @@ -674,7 +674,7 @@ other purposes. These methods include: ### Breaking changes -#### Improved new sessions (#532) +### Improved new sessions (#532) - `Session.new_window()`: @@ -686,7 +686,7 @@ other purposes. These methods include: [PEP 3102]: https://www.python.org/dev/peps/pep-3102/ -#### Improved window splitting (#532) +### Improved window splitting (#532) - `Window.split_window()` to {meth}`Window.split()` @@ -701,7 +701,7 @@ other purposes. These methods include: - Learned `zoom` -#### Tweak: Pane position (#532) +### Tweak: Pane position (#532) It's now possible to retrieve the position of a pane in a window via a `bool` helper:: @@ -811,11 +811,11 @@ _Maintenance only, no bug fixes or new features_ ## libtmux 0.29.0 (2024-02-16) -#### Fixes +### Fixes - Use {exc}`DeprecationWarning` for APIs set to be deprecated (#526) -#### Testing +### Testing - pytest: Ignore {exc}`DeprecationWarning` by default (#526) @@ -823,11 +823,11 @@ _Maintenance only, no bug fixes or new features_ _Maintenance only, no bug fixes or new features_ -#### Testing +### Testing - CI: Bump actions to node 20+ versions -#### Documentation +### Documentation - Refine docs and add migration for v0.28.0 @@ -835,7 +835,7 @@ _Maintenance only, no bug fixes or new features_ ### Breaking changes -#### Detached / unselected by default (#523) +### Detached / unselected by default (#523) To ensure consistency and principle of least surprise, keep these set to not use `-a` unless explicitly specified. @@ -1240,7 +1240,7 @@ _Maintenance only, no bug fixes or new features_ ### New features -#### Detect if server active (#448) +### Detect if server active (#448) - `Server.is_alive()` - `Server.raise_if_dead()` diff --git a/MIGRATION b/MIGRATION index 77fd07dc8..a983d061b 100644 --- a/MIGRATION +++ b/MIGRATION @@ -114,7 +114,7 @@ Using the old `g` parameter will emit a {class}`DeprecationWarning`. ## libtmux 0.46.0 (2025-02-25) -#### Imports removed from libtmux.test (#580) +### Imports removed from libtmux.test (#580) Root-level of imports from `libtmux.test` are no longer possible. @@ -230,7 +230,7 @@ from libtmux.test.temporary import temp_session, temp_window ## 0.28.0: Resizing and detached by default (2024-02-15) -#### Detach by default +### Detach by default - {meth}`Session.new_window()` + {meth}`Window.split_window()` no longer attaches by default (#523) @@ -239,7 +239,7 @@ from libtmux.test.temporary import temp_session, temp_window For the old behavior in 0.28.0 and beyond, pass `attach=True` explicitly. -#### Resizing panes +### Resizing panes - `Pane.resize_pane()` renamed to {meth}`Pane.resize()` (via #523) From 874239b6e15b12566d7f34e74162a69daf8a12cb Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 05:17:31 -0600 Subject: [PATCH 04/14] docs: Remove duplicate reference definitions why: Myst was warning about duplicate markdown reference definitions what: - Remove duplicate [uv] reference in developing.md - Remove duplicate [uv] reference in CHANGES - Remove duplicate [ptpython] reference in quickstart.md --- CHANGES | 2 -- docs/quickstart.md | 1 - 2 files changed, 3 deletions(-) diff --git a/CHANGES b/CHANGES index 00f8daef4..6d3f10a09 100644 --- a/CHANGES +++ b/CHANGES @@ -569,8 +569,6 @@ _Maintenance only, no bug fixes or new features_ via [ruff 0.4.2](https://github.com/astral-sh/ruff/blob/v0.4.2/CHANGELOG.md). -[uv]: https://github.com/astral-sh/uv - ### Documentation - Fix docstrings in `query_list` for `MultipleObjectsReturned` and diff --git a/docs/quickstart.md b/docs/quickstart.md index 2350bdf97..431acedb4 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -491,4 +491,3 @@ and our [test suite] (see {ref}`development`.) [workspacebuilder.py]: https://github.com/tmux-python/libtmux/blob/master/libtmux/workspacebuilder.py [test suite]: https://github.com/tmux-python/libtmux/tree/master/tests -[ptpython]: https://github.com/prompt-toolkit/ptpython From 33bac19cd9ae575c3e19625718273a97ede9ffd5 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 05:35:38 -0600 Subject: [PATCH 05/14] docs(conf): Suppress sphinx-autodoc-typehints forward reference warnings why: Forward references in TYPE_CHECKING blocks cannot be resolved at doc build time, causing ~69 warnings that obscure other issues what: - Add suppress_warnings config to hide forward_reference warnings - These warnings are cosmetic - types like Self, Server, Session are used as string forward references to avoid circular imports --- docs/conf.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/conf.py b/docs/conf.py index e625b2456..8bc5f215c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -121,6 +121,12 @@ # sphinx-autodoc-typehints always_document_param_types = True +# Suppress warnings for forward references that can't be resolved +# (types in TYPE_CHECKING blocks used for circular import avoidance) +suppress_warnings = [ + "sphinx_autodoc_typehints.forward_reference", +] + # sphinx-copybutton copybutton_prompt_text = ( r">>> |\.\.\. |> |\$ |\# | In \[\d*\]: | {2,5}\.\.\.: | {5,8}: " From 45eb1dc91a514a50598fd34b3a989370d98444bf Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 06:02:58 -0600 Subject: [PATCH 06/14] docs(docstrings): Add Returns/Raises sections for RST field list compliance why: Sphinx/Napoleon requires proper field list structure to avoid "Field list ends without a blank line" warnings when processing NumPy-style docstrings. what: - Add Raises sections to EnvironmentMixin methods (common.py) - Add Returns sections to capture_pane, display_message, set_width, set_height (pane.py) - Fix attached_sessions Returns format (server.py) - Add Raises section to kill_window (session.py) - Add Returns/Raises sections to split, select_layout, move_window (window.py) - Standardize parameter descriptions (capitalize, add periods) --- src/libtmux/common.py | 23 ++++++++++++++--- src/libtmux/pane.py | 24 ++++++++++++++++-- src/libtmux/server.py | 5 ++-- src/libtmux/session.py | 7 +++++- src/libtmux/window.py | 57 ++++++++++++++++++++++++++++++------------ 5 files changed, 91 insertions(+), 25 deletions(-) diff --git a/src/libtmux/common.py b/src/libtmux/common.py index d15ddc02e..60a3b49c7 100644 --- a/src/libtmux/common.py +++ b/src/libtmux/common.py @@ -65,9 +65,14 @@ def set_environment(self, name: str, value: str) -> None: Parameters ---------- name : str - the environment variable name. such as 'PATH'. + The environment variable name, e.g. 'PATH'. value : str - environment value. + Environment value. + + Raises + ------ + ValueError + If tmux returns an error. """ args = ["set-environment"] if self._add_option: @@ -92,7 +97,12 @@ def unset_environment(self, name: str) -> None: Parameters ---------- name : str - the environment variable name. such as 'PATH'. + The environment variable name, e.g. 'PATH'. + + Raises + ------ + ValueError + If tmux returns an error. """ args = ["set-environment"] if self._add_option: @@ -116,7 +126,12 @@ def remove_environment(self, name: str) -> None: Parameters ---------- name : str - the environment variable name. such as 'PATH'. + The environment variable name, e.g. 'PATH'. + + Raises + ------ + ValueError + If tmux returns an error. """ args = ["set-environment"] if self._add_option: diff --git a/src/libtmux/pane.py b/src/libtmux/pane.py index e1ab4cbdb..15f5953b6 100644 --- a/src/libtmux/pane.py +++ b/src/libtmux/pane.py @@ -345,6 +345,11 @@ def capture_pane( Negative numbers are lines in the history. ``-`` is the end of the visible pane. Default: None + + Returns + ------- + str | list[str] + Captured pane content. """ cmd = ["capture-pane", "-p"] if start is not None: @@ -432,6 +437,11 @@ def display_message( get_text : bool, optional Returns only text without displaying a message in target-client status line. + + Returns + ------- + str | list[str] | None + Message output if get_text is True, otherwise None. """ if get_text: return self.cmd("display-message", "-p", cmd).stdout @@ -714,7 +724,12 @@ def set_width(self, width: int) -> Pane: Parameters ---------- width : int - pane width, in cells + Pane width, in cells. + + Returns + ------- + :class:`Pane` + Self, for method chaining. """ self.resize_pane(width=width) return self @@ -725,7 +740,12 @@ def set_height(self, height: int) -> Pane: Parameters ---------- height : int - height of pain, in cells + Pane height, in cells. + + Returns + ------- + :class:`Pane` + Self, for method chaining. """ self.resize_pane(height=height) return self diff --git a/src/libtmux/server.py b/src/libtmux/server.py index e400ef12b..b09c58c50 100644 --- a/src/libtmux/server.py +++ b/src/libtmux/server.py @@ -313,7 +313,7 @@ def cmd( @property def attached_sessions(self) -> list[Session]: - """Return active :class:`Session`s. + """Return active :class:`Session` instances. Examples -------- @@ -322,7 +322,8 @@ def attached_sessions(self) -> list[Session]: Returns ------- - list of :class:`Session` + list[:class:`Session`] + Sessions that are attached. """ return self.sessions.filter(session_attached__noeq="1") diff --git a/src/libtmux/session.py b/src/libtmux/session.py index 83c7ed6bf..003beeaca 100644 --- a/src/libtmux/session.py +++ b/src/libtmux/session.py @@ -578,7 +578,12 @@ def kill_window(self, target_window: str | None = None) -> None: Parameters ---------- target_window : str, optional - window to kill + Window to kill. + + Raises + ------ + :exc:`libtmux.exc.LibTmuxException` + If tmux returns an error. """ if target_window: if isinstance(target_window, int): diff --git a/src/libtmux/window.py b/src/libtmux/window.py index 5aab420c9..d578d90d7 100644 --- a/src/libtmux/window.py +++ b/src/libtmux/window.py @@ -284,27 +284,32 @@ def split( Parameters ---------- attach : bool, optional - make new window the current window after creating it, default + Make new window the current window after creating it, default True. start_directory : str or PathLike, optional - specifies the working directory in which the new window is created. + Specifies the working directory in which the new window is created. direction : PaneDirection, optional - split in direction. If none is specified, assume down. - full_window_split: bool, optional - split across full window width or height, rather than active pane. - zoom: bool, optional - expand pane + Split in direction. If none is specified, assume down. + full_window_split : bool, optional + Split across full window width or height, rather than active pane. + zoom : bool, optional + Expand pane. shell : str, optional - execute a command on splitting the window. The pane will close + Execute a command on splitting the window. The pane will close when the command exits. - NOTE: When this command exits the pane will close. This feature + NOTE: When this command exits the pane will close. This feature is useful for long-running processes where the closing of the window upon completion is desired. - size: int, optional + size : int, optional Cell/row or percentage to occupy with respect to current window. - environment: dict, optional + environment : dict, optional Environmental variables for new pane. Passthrough to ``-e``. + + Returns + ------- + :class:`Pane` + The newly created pane. """ active_pane = self.active_pane or self.panes[0] return active_pane.split( @@ -409,7 +414,7 @@ def select_layout(self, layout: str | None = None) -> Window: Parameters ---------- layout : str, optional - string of the layout, 'even-horizontal', 'tiled', etc. Entering + String of the layout, 'even-horizontal', 'tiled', etc. Entering None (leaving this blank) is same as ``select-layout`` with no layout. In recent tmux versions, it picks the most recently set layout. @@ -430,7 +435,17 @@ def select_layout(self, layout: str | None = None) -> Window: Panes are spread out as evenly as possible over the window in both rows and columns. 'custom' - custom dimensions (see :term:`tmux(1)` manpages). + Custom dimensions (see :term:`tmux(1)` manpages). + + Returns + ------- + :class:`Window` + Self, for method chaining. + + Raises + ------ + :exc:`libtmux.exc.LibTmuxException` + If tmux returns an error. """ cmd = ["select-layout"] @@ -539,11 +554,21 @@ def move_window( Parameters ---------- destination : str, optional - the ``target window`` or index to move the window to, default: - empty string + The ``target window`` or index to move the window to, default: + empty string. session : str, optional - the ``target session`` or index to move the window to, default: + The ``target session`` or index to move the window to, default: current session. + + Returns + ------- + :class:`Window` + Self, for method chaining. + + Raises + ------ + :exc:`libtmux.exc.LibTmuxException` + If tmux returns an error. """ session = session or self.session_id proc = self.cmd( From 796746a03c47827662541d6dc1cd5511d10eebfc Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 06:03:12 -0600 Subject: [PATCH 07/14] docs(docstrings): Add docstrings to dataclasses, fix citation syntax why: Dataclasses without docstrings cause "Inline strong start-string without end-string" warnings. Citation syntax [1]_ not resolving properly. what: - Add docstrings to ServerOptions, SessionOptions, WindowOptions, PaneOptions, Options dataclasses (constants.py) - Simplify EnvironmentVarGuard docstring, convert citation to inline URL (environment.py) --- src/libtmux/_internal/constants.py | 10 ++++++++++ src/libtmux/test/environment.py | 10 ++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/libtmux/_internal/constants.py b/src/libtmux/_internal/constants.py index 99693c958..d344c9cd9 100644 --- a/src/libtmux/_internal/constants.py +++ b/src/libtmux/_internal/constants.py @@ -26,6 +26,8 @@ class ServerOptions( SkipDefaultFieldsReprMixin, ): + """Container for tmux server options.""" + backspace: str | None = field(default=None) buffer_limit: int | None = field(default=None) command_alias: SparseArray[str] = field(default_factory=SparseArray) @@ -59,6 +61,8 @@ def __init__(self, **kwargs: object) -> None: class SessionOptions( SkipDefaultFieldsReprMixin, ): + """Container for tmux session options.""" + activity_action: t.Literal["any", "none", "current", "other"] | None = field( default=None, ) @@ -134,6 +138,8 @@ def __init__(self, **kwargs: object) -> None: class WindowOptions( SkipDefaultFieldsReprMixin, ): + """Container for tmux window options.""" + aggressive_resize: t.Literal["on", "off"] | None = field(default=None) automatic_rename: t.Literal["on", "off"] | None = field(default=None) automatic_rename_format: str | None = field(default=None) @@ -197,6 +203,8 @@ def __init__(self, **kwargs: object) -> None: class PaneOptions( SkipDefaultFieldsReprMixin, ): + """Container for tmux pane options.""" + allow_passthrough: t.Literal["on", "off", "all"] | None = field(default=None) allow_rename: t.Literal["on", "off"] | None = field(default=None) alternate_screen: t.Literal["on", "off"] | None = field(default=None) @@ -239,6 +247,8 @@ class Options( PaneOptions, SkipDefaultFieldsReprMixin, ): + """Container for all tmux options (server, session, window, and pane).""" + def __init__(self, **kwargs: object) -> None: # Convert hyphenated keys to underscored attribute names and assign values # Remove asaterisk from inherited options diff --git a/src/libtmux/test/environment.py b/src/libtmux/test/environment.py index c08ba377f..20a399a71 100644 --- a/src/libtmux/test/environment.py +++ b/src/libtmux/test/environment.py @@ -21,19 +21,13 @@ class EnvironmentVarGuard: """Mock environmental variables safely. - Helps rotect the environment variable properly. Can be used as context + Helps protect the environment variable properly. Can be used as context manager. Notes ----- Vendorized to fix issue with Anaconda Python 2 not including test module, - see #121 [1]_ - - References - ---------- - .. [1] Just installed, "ImportError: cannot import name test_support". - GitHub issue for tmuxp. https://github.com/tmux-python/tmuxp/issues/121. - Created October 12th, 2015. Accessed April 7th, 2018. + see `tmuxp#121 `_. """ def __init__(self) -> None: From 5b12d5e8e16f08350a3f1bc7b4e448998bda0027 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 06:03:24 -0600 Subject: [PATCH 08/14] docs: Fix duplicate label, undefined ref, and strikethrough warnings why: Sphinx warns about duplicate labels, undefined references, and strikethrough syntax not supported in non-HTML output. what: - Remove duplicate (internals)= label from about.md - Add (setting_a_tmux_configuration)= label and fix reference in pytest-plugin/index.md - Replace ~~strikethrough~~ with italicized note in CHANGES --- CHANGES | 6 ++---- docs/about.md | 2 -- docs/pytest-plugin/index.md | 6 +++--- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/CHANGES b/CHANGES index 6d3f10a09..ecd0a3cf1 100644 --- a/CHANGES +++ b/CHANGES @@ -1581,10 +1581,8 @@ _Maintenance only, no bug fixes or new features_ - Python 3.7 and 3.8 returns in 0.12.0 - ~~Final python 3.7 and 3.8 release~~ - - ~~Fixes and security updates will go to - [`v0.11.x`](https://github.com/tmux-python/libtmux/tree/v0.11.x)~~ + *Note: This was not the final Python 3.7 and 3.8 release as originally stated. + Python 3.7 and 3.8 support was extended in 0.12.0.* - Internal: Use new separator to split `tmux(1)` formatting information (#289, #343) diff --git a/docs/about.md b/docs/about.md index 3a5c91bba..898d2fa4c 100644 --- a/docs/about.md +++ b/docs/about.md @@ -1,5 +1,3 @@ -(internals)= - (about)= # About diff --git a/docs/pytest-plugin/index.md b/docs/pytest-plugin/index.md index 8f8dca41d..8a310a0b1 100644 --- a/docs/pytest-plugin/index.md +++ b/docs/pytest-plugin/index.md @@ -12,8 +12,6 @@ your case, we won't stabilize APIs until we're sure everything is by the book. [connect with us]: https://github.com/tmux-python/libtmux/discussions -``` - ```{module} libtmux.pytest_plugin ``` @@ -59,6 +57,8 @@ These fixtures are automatically used when the plugin is enabled and `pytest` is These are set to ensure panes and windows can be reliably referenced and asserted. +(setting_a_tmux_configuration)= + ## Setting a tmux configuration If you would like {func}`session fixture ` to automatically use a configuration, you have a few @@ -108,7 +108,7 @@ def test_something(TestServer): assert server.is_alive() ``` -You can also use it with custom configurations, similar to the {ref}`server fixture `: +You can also use it with custom configurations, similar to the {ref}`server fixture `: ```python def test_with_config(TestServer, tmp_path): From f82f97bb8ebd54a79e620c2d281e8a56f6951f94 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 06:03:38 -0600 Subject: [PATCH 09/14] docs(conf): Use signature-only typehints to eliminate RST conflicts why: sphinx-autodoc-typehints was injecting :type: and :rtype: directives into docstrings at runtime, causing "Unexpected indentation" errors due to RST field list parsing conflicts with Napoleon-processed docstrings. what: - Change autodoc_typehints from "description" to "signature" - Set always_document_param_types = False to disable param type injection - Set typehints_document_rtype = False to disable return type injection - Type hints are now visible in function signatures only This eliminates all 64 anonymous "Unexpected indentation" errors while maintaining type documentation in the API reference. --- docs/conf.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 8bc5f215c..291135e18 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -111,15 +111,18 @@ # sphinx.ext.autodoc autoclass_content = "both" autodoc_member_order = "bysource" -# Automatically extract typehints when specified and place them in -# descriptions of the relevant function/method. -autodoc_typehints = "description" +# Show type hints in signature only (not in description) to avoid RST +# indentation conflicts from sphinx-autodoc-typehints type injection +autodoc_typehints = "signature" # Don't show class signature with the class' name. autodoc_class_signature = "separated" toc_object_entries_show_parents = "hide" # sphinx-autodoc-typehints -always_document_param_types = True +# When autodoc_typehints = "signature", disable all docstring modifications +# to prevent RST parsing conflicts +always_document_param_types = False +typehints_document_rtype = False # Suppress warnings for forward references that can't be resolved # (types in TYPE_CHECKING blocks used for circular import avoidance) From 5142a84f15e54087008b5f50a5749cbac46b327b Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 08:54:50 -0600 Subject: [PATCH 10/14] pane(fix[typing]): Correct return types for capture_pane and display_message why: The return type annotations incorrectly included `str` as a possible return type, but the implementation only ever returns `list[str]`. what: - Change capture_pane() return type from `str | list[str]` to `list[str]` - Change display_message() return type from `str | list[str] | None` to `list[str] | None` - Update corresponding docstring Returns sections --- src/libtmux/pane.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libtmux/pane.py b/src/libtmux/pane.py index 15f5953b6..40964f39f 100644 --- a/src/libtmux/pane.py +++ b/src/libtmux/pane.py @@ -321,7 +321,7 @@ def capture_pane( self, start: t.Literal["-"] | int | None = None, end: t.Literal["-"] | int | None = None, - ) -> str | list[str]: + ) -> list[str]: """Capture text from pane. ``$ tmux capture-pane`` to pane. @@ -348,7 +348,7 @@ def capture_pane( Returns ------- - str | list[str] + list[str] Captured pane content. """ cmd = ["capture-pane", "-p"] @@ -416,7 +416,7 @@ def display_message( self, cmd: str, get_text: t.Literal[True], - ) -> str | list[str]: ... + ) -> list[str]: ... @t.overload def display_message(self, cmd: str, get_text: t.Literal[False]) -> None: ... @@ -425,7 +425,7 @@ def display_message( self, cmd: str, get_text: bool = False, - ) -> str | list[str] | None: + ) -> list[str] | None: """Display message to pane. Displays a message in target-client status line. @@ -440,7 +440,7 @@ def display_message( Returns ------- - str | list[str] | None + list[str] | None Message output if get_text is True, otherwise None. """ if get_text: From 0828fbd1813ad9bb720b28cab1bd4bbf5d1518a8 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 10:20:06 -0600 Subject: [PATCH 11/14] docs(conf): Suppress forward reference warnings from sphinx-autodoc-typehints why: Types in TYPE_CHECKING blocks (used for circular import avoidance) cause sphinx-autodoc-typehints to emit warnings about unresolvable forward references. These warnings are expected and safe to suppress. what: - Add suppress_warnings config for sphinx_autodoc_typehints.forward_reference --- docs/conf.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 291135e18..f3a8107b6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -111,19 +111,14 @@ # sphinx.ext.autodoc autoclass_content = "both" autodoc_member_order = "bysource" -# Show type hints in signature only (not in description) to avoid RST -# indentation conflicts from sphinx-autodoc-typehints type injection -autodoc_typehints = "signature" +# Automatically extract typehints when specified and place them in +# descriptions of the relevant function/method. +autodoc_typehints = "description" # Don't show class signature with the class' name. autodoc_class_signature = "separated" toc_object_entries_show_parents = "hide" # sphinx-autodoc-typehints -# When autodoc_typehints = "signature", disable all docstring modifications -# to prevent RST parsing conflicts -always_document_param_types = False -typehints_document_rtype = False - # Suppress warnings for forward references that can't be resolved # (types in TYPE_CHECKING blocks used for circular import avoidance) suppress_warnings = [ From 49d9e9bc5326babbf4517023929c70a096dcb983 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 10:53:20 -0600 Subject: [PATCH 12/14] docs: Add :no-index: to module directives to fix duplicate warnings why: Sphinx warns about duplicate object descriptions when the same module is referenced in multiple documentation files. what: - Add :no-index: directive to module blocks in windows.md, pytest-plugin/index.md, and quickstart.md to prevent duplicate indexing --- docs/api/windows.md | 2 +- docs/pytest-plugin/index.md | 2 +- docs/quickstart.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api/windows.md b/docs/api/windows.md index 728554b0d..384879ae6 100644 --- a/docs/api/windows.md +++ b/docs/api/windows.md @@ -7,7 +7,7 @@ - Identified by `@`, e.g. `@313` ```{module} libtmux - +:no-index: ``` ```{eval-rst} diff --git a/docs/pytest-plugin/index.md b/docs/pytest-plugin/index.md index 8a310a0b1..82d55dd2f 100644 --- a/docs/pytest-plugin/index.md +++ b/docs/pytest-plugin/index.md @@ -13,7 +13,7 @@ your case, we won't stabilize APIs until we're sure everything is by the book. [connect with us]: https://github.com/tmux-python/libtmux/discussions ```{module} libtmux.pytest_plugin - +:no-index: ``` ## Usage diff --git a/docs/quickstart.md b/docs/quickstart.md index 431acedb4..39b11aa70 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -129,7 +129,7 @@ $ ptpython ``` ```{module} libtmux - +:no-index: ``` First, we can grab a {class}`Server`. From 9a693456c7d59f69519a5fa4de047058b20ad078 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 07:59:17 -0600 Subject: [PATCH 13/14] docs(CHANGES) Add documentation summary --- CHANGES | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index ecd0a3cf1..545095bc5 100644 --- a/CHANGES +++ b/CHANGES @@ -32,7 +32,13 @@ $ uvx --from 'libtmux' --prerelease allow python -_Future release notes will be placed here_ +_Upcoming changes will be written here._ + +### Documentation (#612) + +- Normalize docs headings and Sphinx module directives to fix anchor and index generation issues. +- Tweak Sphinx type-hints configuration to avoid RST indentation conflicts and suppress forward-reference warnings. +- Refresh docstrings and cross-references (pane/window APIs, environment helpers, pytest plugin) for clearer return types and stable anchors. ## libtmux 0.50.0 (2025-11-30) From 47470504adc1b4e8cc2840621ffb4904e01276b0 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 08:54:56 -0600 Subject: [PATCH 14/14] docs(CHANGES) Document return type annotation fixes why: Users relying on type hints should know about the corrected return types. what: - Add changelog entry for capture_pane() and display_message() type fixes --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index 545095bc5..0bb3419d3 100644 --- a/CHANGES +++ b/CHANGES @@ -39,6 +39,8 @@ _Upcoming changes will be written here._ - Normalize docs headings and Sphinx module directives to fix anchor and index generation issues. - Tweak Sphinx type-hints configuration to avoid RST indentation conflicts and suppress forward-reference warnings. - Refresh docstrings and cross-references (pane/window APIs, environment helpers, pytest plugin) for clearer return types and stable anchors. +- Fix incorrect return type annotations for `capture_pane()` and `display_message()` methods + (changed from `str | list[str]` to `list[str]` - the methods always return a list). ## libtmux 0.50.0 (2025-11-30)