From fba07b889ff848a6b06d9ab5c50fd79b06b9d0de Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 10:10:56 -0600 Subject: [PATCH 01/41] ruff: Enable pydocstyle w/ numpy convention --- pyproject.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 2c7d757a9..ecbd633c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -128,6 +128,7 @@ select = [ "TRY", # Trycertatops "PERF", # Perflint "RUF", # Ruff-specific rules + "D", # pydocstyle ] [tool.ruff.isort] @@ -136,6 +137,9 @@ known-first-party = [ ] combine-as-imports = true +[tool.ruff.pydocstyle] +convention = "numpy" + [tool.ruff.per-file-ignores] "*/__init__.py" = ["F401"] From f32527d459e3c617fc02f12a3e983563335e07e4 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 10:12:49 -0600 Subject: [PATCH 02/41] ruff(pydocstyle): Run automated fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `ruff --show-fixes --fix-only .` Fixed 72 errors: - src/libtmux/_internal/dataclasses.py: 2 × D412 (blank-lines-between-header-and-content) - src/libtmux/_vendor/version.py: 1 × D202 (no-blank-line-after-function) - src/libtmux/common.py: 3 × D412 (blank-lines-between-header-and-content) 2 × D211 (blank-line-before-class) - src/libtmux/exc.py: 16 × D211 (blank-line-before-class) - src/libtmux/pane.py: 2 × D412 (blank-lines-between-header-and-content) 1 × D202 (no-blank-line-after-function) - src/libtmux/server.py: 1 × D202 (no-blank-line-after-function) - src/libtmux/session.py: 5 × D202 (no-blank-line-after-function) - src/libtmux/test.py: 1 × D202 (no-blank-line-after-function) - src/libtmux/window.py: 3 × D202 (no-blank-line-after-function) 2 × D412 (blank-lines-between-header-and-content) - tests/legacy_api/test_pane.py: 1 × D202 (no-blank-line-after-function) - tests/legacy_api/test_server.py: 1 × D209 (new-line-after-last-paragraph) - tests/legacy_api/test_session.py: 5 × D202 (no-blank-line-after-function) - tests/legacy_api/test_tmuxobject.py: 4 × D202 (no-blank-line-after-function) - tests/legacy_api/test_window.py: 4 × D202 (no-blank-line-after-function) 1 × D403 (first-line-capitalized) - tests/test_pane.py: 1 × D202 (no-blank-line-after-function) - tests/test_server.py: 2 × D209 (new-line-after-last-paragraph) - tests/test_session.py: 5 × D202 (no-blank-line-after-function) - tests/test_tmuxobject.py: 4 × D202 (no-blank-line-after-function) - tests/test_window.py: 4 × D202 (no-blank-line-after-function) 1 × D403 (first-line-capitalized) Fixed 72 errors (77 additional fixes available with `--unsafe-fixes`). --- src/libtmux/_internal/dataclasses.py | 2 -- src/libtmux/_vendor/version.py | 1 - src/libtmux/common.py | 5 ----- src/libtmux/exc.py | 16 ---------------- src/libtmux/pane.py | 3 --- src/libtmux/server.py | 1 - src/libtmux/session.py | 5 ----- src/libtmux/test.py | 1 - src/libtmux/window.py | 5 ----- tests/legacy_api/test_pane.py | 1 - tests/legacy_api/test_server.py | 3 ++- tests/legacy_api/test_session.py | 5 ----- tests/legacy_api/test_tmuxobject.py | 4 ---- tests/legacy_api/test_window.py | 6 +----- tests/test_pane.py | 1 - tests/test_server.py | 6 ++++-- tests/test_session.py | 5 ----- tests/test_tmuxobject.py | 4 ---- tests/test_window.py | 6 +----- 19 files changed, 8 insertions(+), 72 deletions(-) diff --git a/src/libtmux/_internal/dataclasses.py b/src/libtmux/_internal/dataclasses.py index aeddfc0f2..31187b833 100644 --- a/src/libtmux/_internal/dataclasses.py +++ b/src/libtmux/_internal/dataclasses.py @@ -18,14 +18,12 @@ class SkipDefaultFieldsReprMixin: Notes ----- - Credit: Pietro Oldrati, 2022-05-08, Unilicense https://stackoverflow.com/a/72161437/1396928 Examples -------- - >>> @dataclasses.dataclass() ... class Item: ... name: str diff --git a/src/libtmux/_vendor/version.py b/src/libtmux/_vendor/version.py index 0aac18ff4..252b683f5 100644 --- a/src/libtmux/_vendor/version.py +++ b/src/libtmux/_vendor/version.py @@ -194,7 +194,6 @@ def __init__(self, version: str) -> None: If the ``version`` does not conform to PEP 440 in any way then this exception will be raised. """ - # Validate the version and parse it into pieces match = self._regex.search(version) if not match: diff --git a/src/libtmux/common.py b/src/libtmux/common.py index beae1fed8..dd6636851 100644 --- a/src/libtmux/common.py +++ b/src/libtmux/common.py @@ -36,7 +36,6 @@ class EnvironmentMixin: - """ Mixin class for managing session and server level environment variables in tmux. @@ -194,13 +193,11 @@ def getenv(self, name: str) -> Optional[t.Union[str, bool]]: class tmux_cmd: - """ :term:`tmux(1)` command via :py:mod:`subprocess`. Examples -------- - .. code-block:: python proc = tmux_cmd('new-session', '-s%' % 'my session') @@ -220,7 +217,6 @@ class tmux_cmd: Notes ----- - .. versionchanged:: 0.8 Renamed from ``tmux`` to ``tmux_cmd``. """ @@ -413,7 +409,6 @@ def has_minimum_version(raises: bool = True) -> bool: Notes ----- - .. versionchanged:: 0.7.0 No longer returns version, returns True or False diff --git a/src/libtmux/exc.py b/src/libtmux/exc.py index 0023cb3eb..962cbe600 100644 --- a/src/libtmux/exc.py +++ b/src/libtmux/exc.py @@ -13,17 +13,14 @@ class LibTmuxException(Exception): - """Base Exception for libtmux Errors.""" class TmuxSessionExists(LibTmuxException): - """Session does not exist in the server.""" class TmuxCommandNotFound(LibTmuxException): - """Application binary for tmux not found.""" @@ -47,12 +44,10 @@ def __init__( class VersionTooLow(LibTmuxException): - """Raised if tmux below the minimum version to use libtmux.""" class BadSessionName(LibTmuxException): - """Disallowed session name for tmux (empty, contains periods or colons).""" def __init__( @@ -65,17 +60,14 @@ def __init__( class OptionError(LibTmuxException): - """Root error for any error involving invalid, ambiguous or bad options.""" class UnknownOption(OptionError): - """Option unknown to tmux show-option(s) or show-window-option(s).""" class UnknownColorOption(UnknownOption): - """Unknown color option.""" def __init__(self, *args: object): @@ -83,22 +75,18 @@ def __init__(self, *args: object): class InvalidOption(OptionError): - """Option invalid to tmux, introduced in tmux v2.4.""" class AmbiguousOption(OptionError): - """Option that could potentially match more than one.""" class WaitTimeout(LibTmuxException): - """Function timed out without meeting condition""" class VariableUnpackingError(LibTmuxException): - """Error unpacking variable""" def __init__(self, variable: t.Optional[t.Any] = None, *args: object): @@ -119,12 +107,10 @@ def __init__(self, pane_id: t.Optional[str] = None, *args: object): class WindowError(LibTmuxException): - """Any type of window related error""" class MultipleActiveWindows(WindowError): - """Multiple active windows""" def __init__(self, count: int, *args: object): @@ -132,7 +118,6 @@ def __init__(self, count: int, *args: object): class NoActiveWindow(WindowError): - """No active window found""" def __init__(self, *args: object): @@ -140,7 +125,6 @@ def __init__(self, *args: object): class NoWindowsExist(WindowError): - """No windows exist for object""" def __init__(self, *args: object): diff --git a/src/libtmux/pane.py b/src/libtmux/pane.py index 23c3f434c..78a1fbde8 100644 --- a/src/libtmux/pane.py +++ b/src/libtmux/pane.py @@ -53,13 +53,11 @@ class Pane(Obj): Notes ----- - .. versionchanged:: 0.8 Renamed from ``.tmux`` to ``.cmd``. References ---------- - .. [pane_manual] tmux pane. openbsd manpage for TMUX(1). "Each window displayed by tmux may be split into one or more panes; each pane takes up a certain area of the display and is @@ -370,7 +368,6 @@ def clear(self) -> "Pane": def reset(self) -> "Pane": """Reset and clear pane history.""" - self.cmd("send-keys", r"-R \; clear-history") return self diff --git a/src/libtmux/server.py b/src/libtmux/server.py index da0f8db6e..ed0668c73 100644 --- a/src/libtmux/server.py +++ b/src/libtmux/server.py @@ -193,7 +193,6 @@ def cmd(self, *args: t.Any, **kwargs: t.Any) -> tmux_cmd: Renamed from ``.tmux`` to ``.cmd``. """ - cmd_args: t.List[t.Union[str, int]] = list(args) if self.socket_name: cmd_args.insert(0, f"-L{self.socket_name}") diff --git a/src/libtmux/session.py b/src/libtmux/session.py index fd0285bee..57cc67340 100644 --- a/src/libtmux/session.py +++ b/src/libtmux/session.py @@ -290,7 +290,6 @@ def show_option( Test and return True/False for on/off string. """ - tmux_args: t.Tuple[str, ...] = () if _global: @@ -337,7 +336,6 @@ def select_window(self, target_window: t.Union[str, int]) -> "Window": assure ``-l``, ``-n``, ``-p`` work. """ - # Note that we also provide the session ID here, since cmd() # will not automatically add it as there is already a '-t' # argument provided. @@ -383,7 +381,6 @@ def attach_session(self) -> "Session": def kill_session(self) -> None: """``$ tmux kill-session``.""" - proc = self.cmd("kill-session", "-t%s" % self.session_id) if proc.stderr: @@ -534,7 +531,6 @@ def kill_window(self, target_window: t.Optional[str] = None) -> None: target_window : str, optional window to kill """ - if target_window: if isinstance(target_window, int): target = "-t%s:%d" % (self.window_name, target_window) @@ -552,7 +548,6 @@ def kill_window(self, target_window: t.Optional[str] = None) -> None: @property def attached_pane(self) -> t.Optional["Pane"]: """Return active :class:`Pane` object.""" - return self.attached_window.attached_pane # diff --git a/src/libtmux/test.py b/src/libtmux/test.py index c8458f63c..98c41faab 100644 --- a/src/libtmux/test.py +++ b/src/libtmux/test.py @@ -209,7 +209,6 @@ def temp_session( ... session.new_window(window_name='my window') Window(@3 2:my window, Session($... ...)) """ - if "session_name" in kwargs: session_name = kwargs.pop("session_name") else: diff --git a/src/libtmux/window.py b/src/libtmux/window.py index d52b00f2a..5524ac690 100644 --- a/src/libtmux/window.py +++ b/src/libtmux/window.py @@ -159,7 +159,6 @@ def select_pane(self, target_pane: t.Union[str, int]) -> t.Optional["Pane"]: ------ :class:`Pane` """ - if target_pane in ["-l", "-U", "-D", "-L", "-R"]: proc = self.cmd("select-pane", "-t%s" % self.window_id, target_pane) else: @@ -210,7 +209,6 @@ def split_window( Notes ----- - :term:`tmux(1)` will move window to the new pane if the ``split-window`` target is off screen. tmux handles the ``-d`` the same way as ``new-window`` and ``attach`` in @@ -454,7 +452,6 @@ def rename_window(self, new_name: str) -> "Window": Examples -------- - >>> window = session.attached_window >>> window.rename_window('My project') @@ -463,7 +460,6 @@ def rename_window(self, new_name: str) -> "Window": >>> window.rename_window('New name') Window(@1 1:New name, Session($1 ...)) """ - import shlex lex = shlex.shlex(new_name) @@ -482,7 +478,6 @@ def rename_window(self, new_name: str) -> "Window": def kill_window(self) -> None: """Kill the current :class:`Window` object. ``$ tmux kill-window``.""" - proc = self.cmd( "kill-window", f"-t{self.session_id}:{self.window_index}", diff --git a/tests/legacy_api/test_pane.py b/tests/legacy_api/test_pane.py index c9c658f6e..669a5fd67 100644 --- a/tests/legacy_api/test_pane.py +++ b/tests/legacy_api/test_pane.py @@ -9,7 +9,6 @@ def test_resize_pane(session: Session) -> None: """Test Pane.resize_pane().""" - window = session.attached_window window.rename_window("test_resize_pane") diff --git a/tests/legacy_api/test_server.py b/tests/legacy_api/test_server.py index af815edb1..a972be229 100644 --- a/tests/legacy_api/test_server.py +++ b/tests/legacy_api/test_server.py @@ -111,7 +111,8 @@ def test_new_session_no_name(server: Server) -> None: def test_new_session_shell(server: Server) -> None: """Server.new_session creates and returns valid session running with - specified command""" + specified command + """ cmd = "sleep 1m" mysession = server.new_session("test_new_session", window_command=cmd) window = mysession.list_windows()[0] diff --git a/tests/legacy_api/test_session.py b/tests/legacy_api/test_session.py index cf7f3c63a..154a207e0 100644 --- a/tests/legacy_api/test_session.py +++ b/tests/legacy_api/test_session.py @@ -66,7 +66,6 @@ def test_select_window(session: Session) -> None: def test_select_window_returns_Window(session: Session) -> None: """Session.select_window returns Window object.""" - window_count = len(session._windows) assert len(session._windows) == window_count @@ -115,14 +114,12 @@ def test_new_session(server: Server) -> None: def test_show_options(session: Session) -> None: """Session.show_options() returns dict.""" - options = session.show_options() assert isinstance(options, dict) def test_set_show_options_single(session: Session) -> None: """Set option then Session.show_options(key).""" - session.set_option("history-limit", 20) assert session.show_option("history-limit") == 20 @@ -179,14 +176,12 @@ def test_set_option_invalid(session: Session) -> None: def test_show_environment(session: Session) -> None: """Session.show_environment() returns dict.""" - _vars = session.show_environment() assert isinstance(_vars, dict) def test_set_show_environment_single(session: Session) -> None: """Set environment then Session.show_environment(key).""" - session.set_environment("FOO", "BAR") assert session.getenv("FOO") == "BAR" diff --git a/tests/legacy_api/test_tmuxobject.py b/tests/legacy_api/test_tmuxobject.py index dc71a78d6..c73e327ac 100644 --- a/tests/legacy_api/test_tmuxobject.py +++ b/tests/legacy_api/test_tmuxobject.py @@ -42,7 +42,6 @@ def test_find_where(server: Server, session: Session) -> None: def test_find_where_None(server: Server, session: Session) -> None: """.find_where returns None if no results found.""" - while True: nonexistent_session = TEST_SESSION_PREFIX + next(namer) @@ -54,7 +53,6 @@ def test_find_where_None(server: Server, session: Session) -> None: def test_find_where_multiple_infos(server: Server, session: Session) -> None: """.find_where returns objects with multiple attributes.""" - for session in server.sessions: session_id = session.get("session_id") assert session_id is not None @@ -99,7 +97,6 @@ def test_find_where_multiple_infos(server: Server, session: Session) -> None: def test_where(server: Server, session: Session) -> None: """Test self.where() returns matching objects.""" - window = session.attached_window window.split_window() # create second pane @@ -153,7 +150,6 @@ def test_where(server: Server, session: Session) -> None: def test_get_by_id(server: Server, session: Session) -> None: """Test self.get_by_id() retrieves child object.""" - window = session.attached_window window.split_window() # create second pane diff --git a/tests/legacy_api/test_window.py b/tests/legacy_api/test_window.py index b58150f51..1255e5f28 100644 --- a/tests/legacy_api/test_window.py +++ b/tests/legacy_api/test_window.py @@ -109,7 +109,6 @@ def test_newest_pane_data(session: Session) -> None: def test_attached_pane(session: Session) -> None: """Window.attached_window returns active Pane.""" - window = session.attached_window # current window assert isinstance(window.attached_pane, Pane) @@ -268,7 +267,6 @@ def test_set_window_option_ambiguous(session: Session) -> None: def test_set_window_option_invalid(session: Session) -> None: """Window.set_window_option raises ValueError for invalid option key.""" - window = session.new_window(window_name="test_window") if has_gte_version("2.4"): @@ -281,7 +279,6 @@ def test_set_window_option_invalid(session: Session) -> None: def test_move_window(session: Session) -> None: """Window.move_window results in changed index""" - window = session.new_window(window_name="test_window") assert window.index is not None new_index = str(int(window.index) + 1) @@ -299,8 +296,7 @@ def test_move_window_to_other_session(server: Server, session: Session) -> None: def test_select_layout_accepts_no_arg(server: Server, session: Session) -> None: - """tmux allows select-layout with no arguments, so let's allow it here.""" - + """Tmux allows select-layout with no arguments, so let's allow it here.""" window = session.new_window(window_name="test_window") window.select_layout() diff --git a/tests/test_pane.py b/tests/test_pane.py index bd874840f..134b4d90d 100644 --- a/tests/test_pane.py +++ b/tests/test_pane.py @@ -9,7 +9,6 @@ def test_resize_pane(session: Session) -> None: """Test Pane.resize_pane().""" - window = session.attached_window window.rename_window("test_resize_pane") diff --git a/tests/test_server.py b/tests/test_server.py index 183ceede4..c60c103a3 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -111,7 +111,8 @@ def test_new_session_no_name(server: Server) -> None: def test_new_session_shell(server: Server) -> None: """Server.new_session creates and returns valid session running with - specified command""" + specified command + """ cmd = "sleep 1m" mysession = server.new_session("test_new_session", window_command=cmd) window = mysession.windows[0] @@ -131,7 +132,8 @@ def test_new_session_shell(server: Server) -> None: @pytest.mark.skipif(has_version("3.2"), reason="Wrong width returned with 3.2") def test_new_session_width_height(server: Server) -> None: """Server.new_session creates and returns valid session running with - specified width /height""" + specified width /height + """ cmd = "/usr/bin/env PS1='$ ' sh" mysession = server.new_session( "test_new_session_width_height", diff --git a/tests/test_session.py b/tests/test_session.py index 8c1c85eac..149a7f147 100644 --- a/tests/test_session.py +++ b/tests/test_session.py @@ -66,7 +66,6 @@ def test_select_window(session: Session) -> None: def test_select_window_returns_Window(session: Session) -> None: """Session.select_window returns Window object.""" - window_count = len(session.windows) assert len(session.windows) == window_count @@ -115,14 +114,12 @@ def test_new_session(server: Server) -> None: def test_show_options(session: Session) -> None: """Session.show_options() returns dict.""" - options = session.show_options() assert isinstance(options, dict) def test_set_show_options_single(session: Session) -> None: """Set option then Session.show_options(key).""" - session.set_option("history-limit", 20) assert session.show_option("history-limit") == 20 @@ -179,14 +176,12 @@ def test_set_option_invalid(session: Session) -> None: def test_show_environment(session: Session) -> None: """Session.show_environment() returns dict.""" - _vars = session.show_environment() assert isinstance(_vars, dict) def test_set_show_environment_single(session: Session) -> None: """Set environment then Session.show_environment(key).""" - session.set_environment("FOO", "BAR") assert session.getenv("FOO") == "BAR" diff --git a/tests/test_tmuxobject.py b/tests/test_tmuxobject.py index 59aab18f8..dd93929dd 100644 --- a/tests/test_tmuxobject.py +++ b/tests/test_tmuxobject.py @@ -42,7 +42,6 @@ def test_find_where(server: Server, session: Session) -> None: def test_find_where_None(server: Server, session: Session) -> None: """.find_where returns None if no results found.""" - while True: nonexistent_session = TEST_SESSION_PREFIX + next(namer) @@ -54,7 +53,6 @@ def test_find_where_None(server: Server, session: Session) -> None: def test_find_where_multiple_infos(server: Server, session: Session) -> None: """.find_where returns objects with multiple attributes.""" - for session in server.sessions: session_id = session.session_id assert session_id is not None @@ -97,7 +95,6 @@ def test_find_where_multiple_infos(server: Server, session: Session) -> None: def test_where(server: Server, session: Session) -> None: """Test self.where() returns matching objects.""" - window = session.attached_window window.split_window() # create second pane @@ -151,7 +148,6 @@ def test_where(server: Server, session: Session) -> None: def test_filter(server: Server) -> None: """Test self.filter() retrieves child object.""" - sess = server.new_session("test") window = sess.attached_window diff --git a/tests/test_window.py b/tests/test_window.py index 94e20b480..c61261cb1 100644 --- a/tests/test_window.py +++ b/tests/test_window.py @@ -110,7 +110,6 @@ def test_newest_pane_data(session: Session) -> None: def test_attached_pane(session: Session) -> None: """Window.attached_window returns active Pane.""" - window = session.attached_window # current window assert isinstance(window.attached_pane, Pane) @@ -280,7 +279,6 @@ def test_set_window_option_ambiguous(session: Session) -> None: def test_set_window_option_invalid(session: Session) -> None: """Window.set_window_option raises ValueError for invalid option key.""" - window = session.new_window(window_name="test_window") if has_gte_version("2.4"): @@ -293,7 +291,6 @@ def test_set_window_option_invalid(session: Session) -> None: def test_move_window(session: Session) -> None: """Window.move_window results in changed index""" - window = session.new_window(window_name="test_window") assert window.window_index is not None new_index = str(int(window.window_index) + 1) @@ -311,8 +308,7 @@ def test_move_window_to_other_session(server: Server, session: Session) -> None: def test_select_layout_accepts_no_arg(server: Server, session: Session) -> None: - """tmux allows select-layout with no arguments, so let's allow it here.""" - + """Tmux allows select-layout with no arguments, so let's allow it here.""" window = session.new_window(window_name="test_window") window.select_layout() From 8775e3e500d6289d7374685a36879b80fbeb6e0a Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 10:13:49 -0600 Subject: [PATCH 03/41] ruff(pydocstyle): Run automated fixes (unsafe ones) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `ruff --show-fixes --fix-only --unsafe-fixes .` Fixed 77 errors: - conftest.py: 1 × D400 (ends-in-period) - docs/conf.py: 1 × D400 (ends-in-period) - src/libtmux/_internal/query_list.py: 2 × D400 (ends-in-period) - src/libtmux/_vendor/version.py: 1 × D200 (fits-on-one-line) - src/libtmux/exc.py: 8 × D400 (ends-in-period) - src/libtmux/pane.py: 6 × D400 (ends-in-period) 2 × D200 (fits-on-one-line) - src/libtmux/pytest_plugin.py: 3 × D400 (ends-in-period) - src/libtmux/server.py: 5 × D400 (ends-in-period) 4 × D200 (fits-on-one-line) - src/libtmux/session.py: 10 × D400 (ends-in-period) 7 × D200 (fits-on-one-line) - src/libtmux/window.py: 12 × D400 (ends-in-period) 6 × D200 (fits-on-one-line) - tests/legacy_api/test_server.py: 3 × D400 (ends-in-period) - tests/legacy_api/test_window.py: 1 × D400 (ends-in-period) - tests/test_server.py: 4 × D400 (ends-in-period) - tests/test_window.py: 1 × D400 (ends-in-period) Fixed 77 errors. --- conftest.py | 2 +- docs/conf.py | 2 +- src/libtmux/_internal/query_list.py | 4 +-- src/libtmux/_vendor/version.py | 4 +-- src/libtmux/exc.py | 16 +++++------ src/libtmux/pane.py | 16 +++++------ src/libtmux/pytest_plugin.py | 6 ++--- src/libtmux/server.py | 18 ++++--------- src/libtmux/session.py | 36 ++++++++----------------- src/libtmux/window.py | 42 +++++++++-------------------- tests/legacy_api/test_server.py | 6 ++--- tests/legacy_api/test_window.py | 2 +- tests/test_server.py | 8 +++--- tests/test_window.py | 2 +- 14 files changed, 59 insertions(+), 105 deletions(-) diff --git a/conftest.py b/conftest.py index 299041497..c00eaa576 100644 --- a/conftest.py +++ b/conftest.py @@ -1,4 +1,4 @@ -"""Conftest.py (root-level) +"""Conftest.py (root-level). We keep this in root pytest fixtures in pytest's doctest plugin to be available, as well as avoiding conftest.py from being included in the wheel, in addition to pytest_plugin diff --git a/docs/conf.py b/docs/conf.py index dcb51b2ca..e6399b96d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -132,7 +132,7 @@ def linkcode_resolve(domain: str, info: t.Dict[str, str]) -> t.Union[None, str]: """ - Determine the URL corresponding to Python object + Determine the URL corresponding to Python object. Notes ----- diff --git a/src/libtmux/_internal/query_list.py b/src/libtmux/_internal/query_list.py index 07f10ef6a..b9dbbbafb 100644 --- a/src/libtmux/_internal/query_list.py +++ b/src/libtmux/_internal/query_list.py @@ -29,7 +29,7 @@ def __call__( class MultipleObjectsReturned(Exception): - """The requested object does not exist""" + """The requested object does not exist.""" class ObjectDoesNotExist(Exception): @@ -40,7 +40,7 @@ def keygetter( obj: "Mapping[str, t.Any]", path: str, ) -> t.Union[None, t.Any, str, t.List[str], "Mapping[str, str]"]: - """obj, "foods__breakfast", obj['foods']['breakfast'] + """obj, "foods__breakfast", obj['foods']['breakfast']. >>> keygetter({ "foods": { "breakfast": "cereal" } }, "foods__breakfast") 'cereal' diff --git a/src/libtmux/_vendor/version.py b/src/libtmux/_vendor/version.py index 252b683f5..ba50a37a8 100644 --- a/src/libtmux/_vendor/version.py +++ b/src/libtmux/_vendor/version.py @@ -491,9 +491,7 @@ def _parse_letter_version( def _parse_local_version(local: str) -> Optional[LocalType]: - """ - Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve"). - """ + """Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").""" if local is not None: return tuple( part.lower() if not part.isdigit() else int(part) diff --git a/src/libtmux/exc.py b/src/libtmux/exc.py index 962cbe600..bf35a73f4 100644 --- a/src/libtmux/exc.py +++ b/src/libtmux/exc.py @@ -83,22 +83,22 @@ class AmbiguousOption(OptionError): class WaitTimeout(LibTmuxException): - """Function timed out without meeting condition""" + """Function timed out without meeting condition.""" class VariableUnpackingError(LibTmuxException): - """Error unpacking variable""" + """Error unpacking variable.""" def __init__(self, variable: t.Optional[t.Any] = None, *args: object): return super().__init__(f"Unexpected variable: {variable!s}") class PaneError(LibTmuxException): - """Any type of pane related error""" + """Any type of pane related error.""" class PaneNotFound(PaneError): - """Pane not found""" + """Pane not found.""" def __init__(self, pane_id: t.Optional[str] = None, *args: object): if pane_id is not None: @@ -107,25 +107,25 @@ def __init__(self, pane_id: t.Optional[str] = None, *args: object): class WindowError(LibTmuxException): - """Any type of window related error""" + """Any type of window related error.""" class MultipleActiveWindows(WindowError): - """Multiple active windows""" + """Multiple active windows.""" def __init__(self, count: int, *args: object): return super().__init__(f"Multiple active windows: {count} found") class NoActiveWindow(WindowError): - """No active window found""" + """No active window found.""" def __init__(self, *args: object): return super().__init__("No active windows found") class NoWindowsExist(WindowError): - """No windows exist for object""" + """No windows exist for object.""" def __init__(self, *args: object): return super().__init__("No windows exist for object") diff --git a/src/libtmux/pane.py b/src/libtmux/pane.py index 78a1fbde8..59fe7a12a 100644 --- a/src/libtmux/pane.py +++ b/src/libtmux/pane.py @@ -387,7 +387,7 @@ def __repr__(self) -> str: # @property def id(self) -> t.Optional[str]: - """Alias of :attr:`Pane.pane_id` + """Alias of :attr:`Pane.pane_id`. >>> pane.id '%1' @@ -399,7 +399,7 @@ def id(self) -> t.Optional[str]: @property def index(self) -> t.Optional[str]: - """Alias of :attr:`Pane.pane_index` + """Alias of :attr:`Pane.pane_index`. >>> pane.index '0' @@ -411,7 +411,7 @@ def index(self) -> t.Optional[str]: @property def height(self) -> t.Optional[str]: - """Alias of :attr:`Pane.pane_height` + """Alias of :attr:`Pane.pane_height`. >>> pane.height.isdigit() True @@ -423,7 +423,7 @@ def height(self) -> t.Optional[str]: @property def width(self) -> t.Optional[str]: - """Alias of :attr:`Pane.pane_width` + """Alias of :attr:`Pane.pane_width`. >>> pane.width.isdigit() True @@ -437,15 +437,11 @@ def width(self) -> t.Optional[str]: # Legacy # def get(self, key: str, default: t.Optional[t.Any] = None) -> t.Any: - """ - .. deprecated:: 0.16 - """ + """.. deprecated:: 0.16.""" warnings.warn("Pane.get() is deprecated", stacklevel=2) return getattr(self, key, default) def __getitem__(self, key: str) -> t.Any: - """ - .. deprecated:: 0.16 - """ + """.. deprecated:: 0.16.""" warnings.warn(f"Item lookups, e.g. pane['{key}'] is deprecated", stacklevel=2) return getattr(self, key) diff --git a/src/libtmux/pytest_plugin.py b/src/libtmux/pytest_plugin.py index 0cfb1c594..b5ec77794 100644 --- a/src/libtmux/pytest_plugin.py +++ b/src/libtmux/pytest_plugin.py @@ -109,7 +109,7 @@ def server( monkeypatch: pytest.MonkeyPatch, config_file: pathlib.Path, ) -> Server: - """Returns a new, temporary :class:`libtmux.Server` + """Returns a new, temporary :class:`libtmux.Server`. >>> from libtmux.server import Server @@ -146,7 +146,7 @@ def fin() -> None: @pytest.fixture(scope="function") def session_params() -> t.Dict[str, t.Any]: - """Returns a new, temporary :class:`libtmux.Session` + """Returns a new, temporary :class:`libtmux.Session`. >>> import pytest >>> from libtmux.session import Session @@ -186,7 +186,7 @@ def session_params() -> t.Dict[str, t.Any]: def session( request: pytest.FixtureRequest, session_params: t.Dict[str, t.Any], server: Server ) -> "Session": - """Returns a new, temporary :class:`libtmux.Session` + """Returns a new, temporary :class:`libtmux.Session`. >>> from libtmux.session import Session diff --git a/src/libtmux/server.py b/src/libtmux/server.py index ed0668c73..7a51d8365 100644 --- a/src/libtmux/server.py +++ b/src/libtmux/server.py @@ -608,16 +608,12 @@ def _update_panes(self) -> "Server": return self def get_by_id(self, id: str) -> t.Optional[Session]: - """ - .. deprecated:: 0.16 - """ + """.. deprecated:: 0.16.""" warnings.warn("Server.get_by_id() is deprecated", stacklevel=2) return self.sessions.get(session_id=id, default=None) def where(self, kwargs: t.Dict[str, t.Any]) -> t.List[Session]: - """ - .. deprecated:: 0.16 - """ + """.. deprecated:: 0.16.""" warnings.warn("Server.find_where() is deprecated", stacklevel=2) try: return self.sessions.filter(**kwargs) @@ -625,9 +621,7 @@ def where(self, kwargs: t.Dict[str, t.Any]) -> t.List[Session]: return [] def find_where(self, kwargs: t.Dict[str, t.Any]) -> t.Optional[Session]: - """ - .. deprecated:: 0.16 - """ + """.. deprecated:: 0.16.""" warnings.warn("Server.find_where() is deprecated", stacklevel=2) return self.sessions.get(default=None, **kwargs) @@ -663,9 +657,7 @@ def _sessions(self) -> t.List[SessionDict]: return self._list_sessions() def _list_sessions(self) -> t.List["SessionDict"]: - """ - .. deprecated:: 0.16 - """ + """.. deprecated:: 0.16.""" warnings.warn("Server._list_sessions() is deprecated", stacklevel=2) return [s.__dict__ for s in self.sessions] @@ -683,7 +675,7 @@ def list_sessions(self) -> t.List[Session]: @property def children(self) -> QueryList["Session"]: # type:ignore - """Was used by TmuxRelationalObject (but that's longer used in this class) + """Was used by TmuxRelationalObject (but that's longer used in this class). .. deprecated:: 0.16 """ diff --git a/src/libtmux/session.py b/src/libtmux/session.py index 57cc67340..968f0375a 100644 --- a/src/libtmux/session.py +++ b/src/libtmux/session.py @@ -353,9 +353,7 @@ def select_window(self, target_window: t.Union[str, int]) -> "Window": # @property def attached_window(self) -> "Window": - """ - Return active :class:`Window` object. - """ + """Return active :class:`Window` object.""" active_windows = [ window for window in self.windows if window.window_active == "1" ] @@ -521,7 +519,7 @@ def new_window( ) def kill_window(self, target_window: t.Optional[str] = None) -> None: - """Close a tmux window, and all panes inside it, ``$ tmux kill-window`` + """Close a tmux window, and all panes inside it, ``$ tmux kill-window``. Kill the current window or the window at ``target-window``. removing it from any sessions to which it is linked. @@ -566,7 +564,7 @@ def __repr__(self) -> str: # @property def id(self) -> t.Optional[str]: - """Alias of :attr:`Session.session_id` + """Alias of :attr:`Session.session_id`. >>> session.id '$1' @@ -578,7 +576,7 @@ def id(self) -> t.Optional[str]: @property def name(self) -> t.Optional[str]: - """Alias of :attr:`Session.session_name` + """Alias of :attr:`Session.session_name`. >>> session.name 'libtmux_...' @@ -592,32 +590,24 @@ def name(self) -> t.Optional[str]: # Legacy: Redundant stuff we want to remove # def get(self, key: str, default: t.Optional[t.Any] = None) -> t.Any: - """ - .. deprecated:: 0.16 - """ + """.. deprecated:: 0.16.""" warnings.warn("Session.get() is deprecated", stacklevel=2) return getattr(self, key, default) def __getitem__(self, key: str) -> t.Any: - """ - .. deprecated:: 0.16 - """ + """.. deprecated:: 0.16.""" warnings.warn( f"Item lookups, e.g. session['{key}'] is deprecated", stacklevel=2 ) return getattr(self, key) def get_by_id(self, id: str) -> t.Optional[Window]: - """ - .. deprecated:: 0.16 - """ + """.. deprecated:: 0.16.""" warnings.warn("Session.get_by_id() is deprecated", stacklevel=2) return self.windows.get(window_id=id, default=None) def where(self, kwargs: t.Dict[str, t.Any]) -> t.List[Window]: - """ - .. deprecated:: 0.16 - """ + """.. deprecated:: 0.16.""" warnings.warn("Session.where() is deprecated", stacklevel=2) try: return self.windows.filter(**kwargs) @@ -625,16 +615,12 @@ def where(self, kwargs: t.Dict[str, t.Any]) -> t.List[Window]: return [] def find_where(self, kwargs: t.Dict[str, t.Any]) -> t.Optional[Window]: - """ - .. deprecated:: 0.16 - """ + """.. deprecated:: 0.16.""" warnings.warn("Session.find_where() is deprecated", stacklevel=2) return self.windows.get(default=None, **kwargs) def _list_windows(self) -> t.List["WindowDict"]: - """ - .. deprecated:: 0.16 - """ + """.. deprecated:: 0.16.""" warnings.warn("Session._list_windows() is deprecated", stacklevel=2) return [w.__dict__ for w in self.windows] @@ -657,7 +643,7 @@ def list_windows(self) -> t.List["Window"]: @property def children(self) -> QueryList["Window"]: # type:ignore - """Was used by TmuxRelationalObject (but that's longer used in this class) + """Was used by TmuxRelationalObject (but that's longer used in this class). .. deprecated:: 0.16 """ diff --git a/src/libtmux/window.py b/src/libtmux/window.py index 5524ac690..5a8aafcc8 100644 --- a/src/libtmux/window.py +++ b/src/libtmux/window.py @@ -565,7 +565,7 @@ def __repr__(self) -> str: # @property def id(self) -> t.Optional[str]: - """Alias of :attr:`Window.window_id` + """Alias of :attr:`Window.window_id`. >>> window.id '@1' @@ -577,7 +577,7 @@ def id(self) -> t.Optional[str]: @property def name(self) -> t.Optional[str]: - """Alias of :attr:`Window.window_name` + """Alias of :attr:`Window.window_name`. >>> window.name '...' @@ -589,7 +589,7 @@ def name(self) -> t.Optional[str]: @property def index(self) -> t.Optional[str]: - """Alias of :attr:`Window.window_index` + """Alias of :attr:`Window.window_index`. >>> window.index '1' @@ -601,7 +601,7 @@ def index(self) -> t.Optional[str]: @property def height(self) -> t.Optional[str]: - """Alias of :attr:`Window.window_height` + """Alias of :attr:`Window.window_height`. >>> window.height.isdigit() True @@ -613,7 +613,7 @@ def height(self) -> t.Optional[str]: @property def width(self) -> t.Optional[str]: - """Alias of :attr:`Window.window_width` + """Alias of :attr:`Window.window_width`. >>> window.width.isdigit() True @@ -627,34 +627,22 @@ def width(self) -> t.Optional[str]: # Legacy: Redundant stuff we want to remove # def get(self, key: str, default: t.Optional[t.Any] = None) -> t.Any: - """ - .. deprecated:: 0.16 - - """ + """.. deprecated:: 0.16.""" warnings.warn("Window.get() is deprecated", stacklevel=2) return getattr(self, key, default) def __getitem__(self, key: str) -> t.Any: - """ - .. deprecated:: 0.16 - - """ + """.. deprecated:: 0.16.""" warnings.warn(f"Item lookups, e.g. window['{key}'] is deprecated", stacklevel=2) return getattr(self, key) def get_by_id(self, id: str) -> t.Optional[Pane]: - """ - .. deprecated:: 0.16 - - """ + """.. deprecated:: 0.16.""" warnings.warn("Window.get_by_id() is deprecated", stacklevel=2) return self.panes.get(pane_id=id, default=None) def where(self, kwargs: t.Dict[str, t.Any]) -> t.List[Pane]: - """ - .. deprecated:: 0.16 - - """ + """.. deprecated:: 0.16.""" warnings.warn("Window.where() is deprecated", stacklevel=2) try: return self.panes.filter(**kwargs) @@ -662,18 +650,12 @@ def where(self, kwargs: t.Dict[str, t.Any]) -> t.List[Pane]: return [] def find_where(self, kwargs: t.Dict[str, t.Any]) -> t.Optional[Pane]: - """ - .. deprecated:: 0.16 - - """ + """.. deprecated:: 0.16.""" warnings.warn("Window.find_where() is deprecated", stacklevel=2) return self.panes.get(default=None, **kwargs) def _list_panes(self) -> t.List[PaneDict]: - """ - .. deprecated:: 0.16 - - """ + """.. deprecated:: 0.16.""" warnings.warn("Window._list_panes() is deprecated", stacklevel=2) return [pane.__dict__ for pane in self.panes] @@ -696,7 +678,7 @@ def list_panes(self) -> t.List["Pane"]: @property def children(self) -> QueryList["Pane"]: # type:ignore - """Was used by TmuxRelationalObject (but that's longer used in this class) + """Was used by TmuxRelationalObject (but that's longer used in this class). .. deprecated:: 0.16 """ diff --git a/tests/legacy_api/test_server.py b/tests/legacy_api/test_server.py index a972be229..c06909e0e 100644 --- a/tests/legacy_api/test_server.py +++ b/tests/legacy_api/test_server.py @@ -86,14 +86,14 @@ def test_show_environment_not_set(server: Server) -> None: def test_new_session(server: Server) -> None: - """Server.new_session creates and returns valid session""" + """Server.new_session creates and returns valid session.""" mysession = server.new_session("test_new_session") assert mysession.get("session_name") == "test_new_session" assert server.has_session("test_new_session") def test_new_session_no_name(server: Server) -> None: - """Server.new_session works with no name""" + """Server.new_session works with no name.""" first_session = server.new_session() first_session_name = first_session.get("session_name") assert first_session_name is not None @@ -111,7 +111,7 @@ def test_new_session_no_name(server: Server) -> None: def test_new_session_shell(server: Server) -> None: """Server.new_session creates and returns valid session running with - specified command + specified command. """ cmd = "sleep 1m" mysession = server.new_session("test_new_session", window_command=cmd) diff --git a/tests/legacy_api/test_window.py b/tests/legacy_api/test_window.py index 1255e5f28..3b208d0be 100644 --- a/tests/legacy_api/test_window.py +++ b/tests/legacy_api/test_window.py @@ -278,7 +278,7 @@ def test_set_window_option_invalid(session: Session) -> None: def test_move_window(session: Session) -> None: - """Window.move_window results in changed index""" + """Window.move_window results in changed index.""" window = session.new_window(window_name="test_window") assert window.index is not None new_index = str(int(window.index) + 1) diff --git a/tests/test_server.py b/tests/test_server.py index c60c103a3..5f7aa8fb5 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -86,14 +86,14 @@ def test_show_environment_not_set(server: Server) -> None: def test_new_session(server: Server) -> None: - """Server.new_session creates and returns valid session""" + """Server.new_session creates and returns valid session.""" mysession = server.new_session("test_new_session") assert mysession.session_name == "test_new_session" assert server.has_session("test_new_session") def test_new_session_no_name(server: Server) -> None: - """Server.new_session works with no name""" + """Server.new_session works with no name.""" first_session = server.new_session() first_session_name = first_session.session_name assert first_session_name is not None @@ -111,7 +111,7 @@ def test_new_session_no_name(server: Server) -> None: def test_new_session_shell(server: Server) -> None: """Server.new_session creates and returns valid session running with - specified command + specified command. """ cmd = "sleep 1m" mysession = server.new_session("test_new_session", window_command=cmd) @@ -132,7 +132,7 @@ def test_new_session_shell(server: Server) -> None: @pytest.mark.skipif(has_version("3.2"), reason="Wrong width returned with 3.2") def test_new_session_width_height(server: Server) -> None: """Server.new_session creates and returns valid session running with - specified width /height + specified width /height. """ cmd = "/usr/bin/env PS1='$ ' sh" mysession = server.new_session( diff --git a/tests/test_window.py b/tests/test_window.py index c61261cb1..ca1a15545 100644 --- a/tests/test_window.py +++ b/tests/test_window.py @@ -290,7 +290,7 @@ def test_set_window_option_invalid(session: Session) -> None: def test_move_window(session: Session) -> None: - """Window.move_window results in changed index""" + """Window.move_window results in changed index.""" window = session.new_window(window_name="test_window") assert window.window_index is not None new_index = str(int(window.window_index) + 1) From 8c038bd241eccdb41cda816acb8e16083f852ffa Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 11:31:45 -0600 Subject: [PATCH 04/41] chore(tests[window]): pydocstyle manual fixes --- tests/test_window.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/test_window.py b/tests/test_window.py index ca1a15545..b61653103 100644 --- a/tests/test_window.py +++ b/tests/test_window.py @@ -18,6 +18,7 @@ def test_select_window(session: Session) -> None: + """Test Window.select_window().""" window_count = len(session.windows) # to do, get option for base-index from tmux # for now however, let's get the index from the first window. @@ -43,7 +44,8 @@ def test_select_window(session: Session) -> None: assert len(session.windows) == 2 -def test_zfresh_window_data(session: Session) -> None: +def test_fresh_window_data(session: Session) -> None: + """Verify window data is fresh.""" attached_window = session.attached_window assert attached_window is not None pane_base_idx = attached_window.show_window_option("pane-base-index", g=True) @@ -96,6 +98,7 @@ def test_zfresh_window_data(session: Session) -> None: def test_newest_pane_data(session: Session) -> None: + """Test window.panes has fresh data.""" window = session.new_window(window_name="test", attach=True) assert isinstance(window, Window) assert len(window.panes) == 1 @@ -174,7 +177,7 @@ def test_split_window_horizontal(session: Session) -> None: def test_window_rename( session: Session, window_name_before: str, window_name_after: str ) -> None: - """Window.rename_window().""" + """Test Window.rename_window().""" window_name_before = "test" window_name_after = "ha ha ha fjewlkjflwef" @@ -196,6 +199,7 @@ def test_window_rename( def test_kill_window(session: Session) -> None: + """Test window.kill_window() kills window.""" session.new_window() # create a second window to not kick out the client. # there is another way to do this via options too. @@ -234,6 +238,7 @@ def test_set_show_window_options(session: Session) -> None: def test_empty_window_option_returns_None(session: Session) -> None: + """Verify unset window option returns None.""" window = session.new_window(window_name="test_window") assert window.show_window_option("alternate-screen") is None @@ -299,6 +304,7 @@ def test_move_window(session: Session) -> None: def test_move_window_to_other_session(server: Server, session: Session) -> None: + """Window.move_window to other session.""" window = session.new_window(window_name="test_window") new_session = server.new_session("test_move_window") window.move_window(session=new_session.session_id) @@ -317,6 +323,7 @@ def test_select_layout_accepts_no_arg(server: Server, session: Session) -> None: has_lt_version("3.2"), reason="needs filter introduced in tmux >= 3.2" ) def test_empty_window_name(session: Session) -> None: + """New windows can be created with empty string for window name.""" session.set_option("automatic-rename", "off") window = session.new_window(window_name="''", attach=True) @@ -349,6 +356,7 @@ def test_split_window_with_environment( session: Session, environment: t.Dict[str, str], ) -> None: + """Verify splitting window with environment variables.""" env = shutil.which("env") assert env is not None, "Cannot find usable `env` in Path." @@ -373,6 +381,7 @@ def test_split_window_with_environment_logs_warning_for_old_tmux( session: Session, caplog: pytest.LogCaptureFixture, ) -> None: + """Verify splitting window with environment variables warns if tmux too old.""" env = shutil.which("env") assert env is not None, "Cannot find usable `env` in Path." From 08d452226a4e5a1808ea1e70a4d880bd452e6bfe Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 12:28:21 -0600 Subject: [PATCH 05/41] chore(tests[version]): pydocstyle manual fixes --- tests/test_version.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/test_version.py b/tests/test_version.py index dc4af269d..99820f9f2 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -1,3 +1,4 @@ +"""Tests for version comparison.""" import operator import typing as t from contextlib import nullcontext as does_not_raise @@ -30,10 +31,13 @@ ], ) def test_version(version: str) -> None: + """Assert LooseVersion constructor against various version strings.""" assert LooseVersion(version) class VersionCompareFixture(t.NamedTuple): + """Test fixture for version comparison.""" + a: object op: "VersionCompareOp" b: object @@ -61,6 +65,7 @@ def test_version_compare( b: str, raises: t.Union[t.Type[Exception], bool], ) -> None: + """Assert version comparisons.""" raises_ctx: "RaisesContext[Exception]" = ( pytest.raises(t.cast(t.Type[Exception], raises)) if raises From 7b7a14373364862b41a78e931e76e1a112639849 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 12:31:30 -0600 Subject: [PATCH 06/41] chore(tests[test]): pydocstyle manual fixes --- tests/test_test.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/test_test.py b/tests/test_test.py index 741a340bd..d92e60e81 100644 --- a/tests/test_test.py +++ b/tests/test_test.py @@ -1,3 +1,4 @@ +"""Tests for libtmux's testing utilities.""" from time import time import pytest @@ -7,6 +8,7 @@ def test_retry_three_times() -> None: + """Test retry_until().""" ini = time() value = 0 @@ -28,6 +30,7 @@ def call_me_three_times() -> bool: def test_function_times_out() -> None: + """Test time outs with retry_until().""" ini = time() def never_true() -> bool: @@ -41,7 +44,8 @@ def never_true() -> bool: assert abs((end - ini) - 1.0) < 0.01 -def test_function_times_out_no_rise() -> None: +def test_function_times_out_no_raise() -> None: + """Tests retry_until() with exception raising disabled.""" ini = time() def never_true() -> bool: @@ -55,6 +59,7 @@ def never_true() -> bool: def test_function_times_out_no_raise_assert() -> None: + """Tests retry_until() with exception raising disabled, returning False.""" ini = time() def never_true() -> bool: @@ -68,6 +73,7 @@ def never_true() -> bool: def test_retry_three_times_no_raise_assert() -> None: + """Tests retry_until() with exception raising disabled, with closure variable.""" ini = time() value = 0 From 7fa1211eaea80ba967d47d829b81a27fedeaec0e Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 12:50:11 -0600 Subject: [PATCH 07/41] chore(tests[session]): pydocstyle manual fixes --- tests/test_session.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/test_session.py b/tests/test_session.py index 149a7f147..64fc81570 100644 --- a/tests/test_session.py +++ b/tests/test_session.py @@ -140,6 +140,7 @@ def test_set_show_option(session: Session) -> None: def test_empty_session_option_returns_None(session: Session) -> None: + """Verify Session.show_option returns None for unset option.""" assert session.show_option("default-shell") is None @@ -215,6 +216,8 @@ def test_unset_environment(session: Session) -> None: class PeriodRaisesBadSessionName(t.NamedTuple): + """Test fixture for bad session name names.""" + session_name: str raises: bool @@ -227,9 +230,10 @@ class PeriodRaisesBadSessionName(t.NamedTuple): PeriodRaisesBadSessionName("hey moo", False), ], ) -def test_periods_raise_badsessionname( +def test_periods_raise_bad_session_name( server: Server, session: Session, session_name: str, raises: bool ) -> None: + """Verify session names with periods raise BadSessionName.""" new_name = session_name + "moo" # used for rename / switch if raises: with pytest.raises(exc.BadSessionName): @@ -256,6 +260,7 @@ def test_periods_raise_badsessionname( def test_cmd_inserts_session_id(session: Session) -> None: + """Verify Session.cmd() inserts session_id.""" current_session_id = session.session_id last_arg = "last-arg" cmd = session.cmd("not-a-command", last_arg) @@ -279,6 +284,7 @@ def test_new_window_with_environment( session: Session, environment: t.Dict[str, str], ) -> None: + """Verify new window with environment vars.""" env = shutil.which("env") assert env is not None, "Cannot find usable `env` in PATH." @@ -303,6 +309,7 @@ def test_new_window_with_environment_logs_warning_for_old_tmux( session: Session, caplog: pytest.LogCaptureFixture, ) -> None: + """Verify new window with environment vars create a warning if tmux is too old.""" env = shutil.which("env") assert env is not None, "Cannot find usable `env` in PATH." From 591da9eda5de82dd46a5f94478c4b488af584283 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 13:00:51 -0600 Subject: [PATCH 08/41] chore(tests[server]): pydocstyle manual fixes --- tests/test_server.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/tests/test_server.py b/tests/test_server.py index 5f7aa8fb5..3a84bd590 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -12,6 +12,7 @@ def test_has_session(server: Server, session: Session) -> None: + """Server.has_session() returns True if session exists.""" session_name = session.session_name assert session_name is not None assert server.has_session(session_name) @@ -44,6 +45,7 @@ def test_config(server: Server) -> None: def test_256_colors(server: Server) -> None: + """Assert Server respects ``colors=256``.""" myserver = Server(colors=256) assert myserver.colors == 256 @@ -54,6 +56,7 @@ def test_256_colors(server: Server) -> None: def test_88_colors(server: Server) -> None: + """Assert Server respects ``colors=88``.""" myserver = Server(colors=88) assert myserver.colors == 88 @@ -110,9 +113,7 @@ def test_new_session_no_name(server: Server) -> None: def test_new_session_shell(server: Server) -> None: - """Server.new_session creates and returns valid session running with - specified command. - """ + """Verify ``Server.new_session`` creates valid session running w/ command.""" cmd = "sleep 1m" mysession = server.new_session("test_new_session", window_command=cmd) window = mysession.windows[0] @@ -131,9 +132,7 @@ def test_new_session_shell(server: Server) -> None: @pytest.mark.skipif(has_version("3.2"), reason="Wrong width returned with 3.2") def test_new_session_width_height(server: Server) -> None: - """Server.new_session creates and returns valid session running with - specified width /height. - """ + """Verify ``Server.new_session`` creates valid session running w/ dimensions.""" cmd = "/usr/bin/env PS1='$ ' sh" mysession = server.new_session( "test_new_session_width_height", @@ -148,31 +147,37 @@ def test_new_session_width_height(server: Server) -> None: def test_no_server_sessions() -> None: + """Verify ``Server.sessions`` returns empty list without tmux server.""" server = Server(socket_name="test_attached_session_no_server") assert server.sessions == [] def test_no_server_attached_sessions() -> None: + """Verify ``Server.attached_sessions`` returns empty list without tmux server.""" server = Server(socket_name="test_no_server_attached_sessions") assert server.attached_sessions == [] def test_no_server_is_alive() -> None: + """Verify is_alive() returns False without tmux server.""" dead_server = Server(socket_name="test_no_server_is_alive") assert not dead_server.is_alive() def test_with_server_is_alive(server: Server) -> None: + """Verify is_alive() returns True when tmux server is alive.""" server.new_session() assert server.is_alive() -def test_no_server_raise_if_dead() -> None: +def test_raise_if_dead_no_server_raises() -> None: + """Verify new_session() raises if tmux server is dead.""" dead_server = Server(socket_name="test_attached_session_no_server") with pytest.raises(subprocess.CalledProcessError): dead_server.raise_if_dead() -def test_with_server_raise_if_dead(server: Server) -> None: +def test_raise_if_dead_does_not_raise_if_alive(server: Server) -> None: + """Verify new_session() does not raise if tmux server is alive.""" server.new_session() server.raise_if_dead() From 5860efbdeddb5850c8c64c56f334fdfc3d68a7c2 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 13:18:07 -0600 Subject: [PATCH 09/41] chore(tests[pytest_plugin]): pydocstyle manual fixes --- tests/test_pytest_plugin.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_pytest_plugin.py b/tests/test_pytest_plugin.py index 9dbf994e5..21a5b7241 100644 --- a/tests/test_pytest_plugin.py +++ b/tests/test_pytest_plugin.py @@ -1,3 +1,4 @@ +"""Tests for libtmux pytest plugin.""" import textwrap import pytest @@ -7,6 +8,7 @@ def test_plugin( pytester: pytest.Pytester, monkeypatch: pytest.MonkeyPatch, ) -> None: + """Test libtmux pytest plugin.""" # Initialize variables pytester.plugins = ["pytest_plugin"] pytester.makefile( From c7857fe0ffcfe697824ea3fdf8d88584e1182847 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 13:20:30 -0600 Subject: [PATCH 10/41] chore(tests[pane]): pydocstyle manual fixes --- tests/test_pane.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_pane.py b/tests/test_pane.py index 134b4d90d..b44a1f617 100644 --- a/tests/test_pane.py +++ b/tests/test_pane.py @@ -28,6 +28,7 @@ def test_resize_pane(session: Session) -> None: def test_send_keys(session: Session) -> None: + """Verify Pane.send_keys().""" pane = session.attached_window.attached_pane assert pane is not None pane.send_keys("c-c", literal=True) @@ -40,6 +41,7 @@ def test_send_keys(session: Session) -> None: def test_set_height(session: Session) -> None: + """Verify Pane.set_height().""" window = session.new_window(window_name="test_set_height") window.split_window() pane1 = window.attached_pane @@ -53,6 +55,7 @@ def test_set_height(session: Session) -> None: def test_set_width(session: Session) -> None: + """Verify Pane.set_width().""" window = session.new_window(window_name="test_set_width") window.split_window() @@ -70,6 +73,7 @@ def test_set_width(session: Session) -> None: def test_capture_pane(session: Session) -> None: + """Verify Pane.capture_pane().""" env = shutil.which("env") assert env is not None, "Cannot find usable `env` in PATH." @@ -92,6 +96,7 @@ def test_capture_pane(session: Session) -> None: def test_capture_pane_start(session: Session) -> None: + """Assert Pane.capture_pane() with ``start`` param.""" env = shutil.which("env") assert env is not None, "Cannot find usable `env` in PATH." @@ -119,6 +124,7 @@ def test_capture_pane_start(session: Session) -> None: def test_capture_pane_end(session: Session) -> None: + """Assert Pane.capture_pane() with ``end`` param.""" env = shutil.which("env") assert env is not None, "Cannot find usable `env` in PATH." From 7796d6a5aed9e12f63420d58dfcea0b5ca59d6c1 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 13:22:17 -0600 Subject: [PATCH 11/41] chore(tests[dataclasses]): pydocstyle manual fixes --- tests/test_dataclasses.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test_dataclasses.py b/tests/test_dataclasses.py index 46c7a8708..16a2e01af 100644 --- a/tests/test_dataclasses.py +++ b/tests/test_dataclasses.py @@ -1,3 +1,4 @@ +"""Tests for libtmux object model, querying and traversal, etc.""" import pathlib import typing as t @@ -27,6 +28,7 @@ def test_pane( tmp_path: pathlib.Path, server: Server, ) -> None: + """Verify Pane dataclass object.""" monkeypatch.chdir(tmp_path) try: @@ -133,6 +135,7 @@ def test_pane( @pytest.fixture def session(session: Session) -> Session: + """Verify creating Session with Session.from_session_id().""" assert session.session_id is not None return Session.from_session_id(server=session.server, session_id=session.session_id) @@ -142,6 +145,7 @@ def test_querylist( tmp_path: pathlib.Path, session: Session, ) -> None: + """Verify QueryList behavior with libtmux object.""" monkeypatch.chdir(tmp_path) session.new_window(window_name="test_2") From 402fe8a6c689a40f83d8cfbaf3657c089689d25b Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 13:32:24 -0600 Subject: [PATCH 12/41] chore(tests[common]): pydocstyle manual fixes --- tests/test_common.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/tests/test_common.py b/tests/test_common.py index 5a1407c86..1cd62c6f3 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -1,5 +1,4 @@ """Tests for utility functions in libtmux.""" - import re import sys import typing as t @@ -29,6 +28,8 @@ def test_allows_master_version(monkeypatch: pytest.MonkeyPatch) -> None: + """Assert get_version() works with builds from git trunk.""" + class Hi: stdout: t.ClassVar = ["tmux master"] stderr = None @@ -47,6 +48,7 @@ def mock_tmux_cmd(*args: t.Any, **kwargs: t.Any) -> Hi: def test_allows_next_version(monkeypatch: pytest.MonkeyPatch) -> None: + """Assert get_version() supports next version.""" TMUX_NEXT_VERSION = str(float(TMUX_MAX_VERSION) + 0.1) class Hi: @@ -65,6 +67,8 @@ def mock_tmux_cmd(*args: t.Any, **kwargs: t.Any) -> Hi: def test_get_version_openbsd(monkeypatch: pytest.MonkeyPatch) -> None: + """Assert get_version() with OpenBSD versions.""" + class Hi: stderr: t.ClassVar = ["tmux: unknown option -- V"] @@ -82,6 +86,8 @@ def mock_tmux_cmd(*args: t.Any, **kwargs: t.Any) -> Hi: def test_get_version_too_low(monkeypatch: pytest.MonkeyPatch) -> None: + """Assert get_version() raises if tmux version too low.""" + class Hi: stderr: t.ClassVar = ["tmux: unknown option -- V"] @@ -95,7 +101,7 @@ def mock_tmux_cmd(*args: t.Any, **kwargs: t.Any) -> Hi: def test_ignores_letter_versions(monkeypatch: pytest.MonkeyPatch) -> None: - """Ignore letters such as 1.8b. + """Tests version utilities ignores letters such as 1.8b. See ticket https://github.com/tmux-python/tmuxp/issues/55. @@ -118,6 +124,8 @@ def test_ignores_letter_versions(monkeypatch: pytest.MonkeyPatch) -> None: def test_error_version_less_1_7(monkeypatch: pytest.MonkeyPatch) -> None: + """Test raises if tmux version less than 1.7.""" + def mock_get_version() -> LooseVersion: return LooseVersion("1.7") @@ -133,10 +141,12 @@ def mock_get_version() -> LooseVersion: def test_has_version() -> None: + """Test has_version().""" assert has_version(str(get_version())) def test_has_gt_version() -> None: + """Test has_gt_version().""" assert has_gt_version("1.6") assert has_gt_version("1.6b") @@ -145,6 +155,7 @@ def test_has_gt_version() -> None: def test_has_gte_version() -> None: + """Test has_gte_version().""" assert has_gte_version("1.6") assert has_gte_version("1.6b") assert has_gte_version(str(get_version())) @@ -154,6 +165,7 @@ def test_has_gte_version() -> None: def test_has_lt_version() -> None: + """Test has_lt_version().""" assert has_lt_version("4.0a") assert has_lt_version("4.0") @@ -162,6 +174,7 @@ def test_has_lt_version() -> None: def test_has_lte_version() -> None: + """Test has_lti_version().""" assert has_lte_version("4.0a") assert has_lte_version("4.0") assert has_lte_version(str(get_version())) @@ -171,16 +184,20 @@ def test_has_lte_version() -> None: def test_tmux_cmd_raises_on_not_found(monkeypatch: pytest.MonkeyPatch) -> None: + """Verify raises if tmux command not found.""" monkeypatch.setenv("PATH", "") with pytest.raises(TmuxCommandNotFound): tmux_cmd("-V") def test_tmux_cmd_unicode(session: Session) -> None: + """Verify tmux commands with unicode.""" session.cmd("new-window", "-t", 3, "-n", "юникод", "-F", "Ελληνικά") class SessionCheckName(t.NamedTuple): + """Test fixture for test_session_check_name().""" + session_name: t.Optional[str] raises: bool exc_msg_regex: t.Optional[str] @@ -200,6 +217,7 @@ class SessionCheckName(t.NamedTuple): def test_session_check_name( session_name: t.Optional[str], raises: bool, exc_msg_regex: t.Optional[str] ) -> None: + """Verify session_check_name().""" if raises: with pytest.raises(BadSessionName) as exc_info: session_check_name(session_name) @@ -210,6 +228,7 @@ def test_session_check_name( def test_get_libtmux_version() -> None: + """Verify get_libtmux_version().""" from libtmux.__about__ import __version__ version = get_libtmux_version() From 0c4b5e2a70230fb5ca55c4ac6e77922cb0c9cf48 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 13:36:48 -0600 Subject: [PATCH 13/41] chore(tests[legacy_window]): pydocstyle manual fixes --- tests/legacy_api/test_window.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/legacy_api/test_window.py b/tests/legacy_api/test_window.py index 3b208d0be..90c4f2463 100644 --- a/tests/legacy_api/test_window.py +++ b/tests/legacy_api/test_window.py @@ -17,6 +17,7 @@ def test_select_window(session: Session) -> None: + """Test Window.select_window().""" window_count = len(session._windows) # to do, get option for base-index from tmux # for now however, let's get the index from the first window. @@ -42,7 +43,8 @@ def test_select_window(session: Session) -> None: assert len(session._windows) == 2 -def test_zfresh_window_data(session: Session) -> None: +def test_fresh_window_data(session: Session) -> None: + """Verify window data is fresh.""" attached_window = session.attached_window assert attached_window is not None pane_base_idx = attached_window.show_window_option("pane-base-index", g=True) @@ -95,6 +97,7 @@ def test_zfresh_window_data(session: Session) -> None: def test_newest_pane_data(session: Session) -> None: + """Test window.panes has fresh data.""" window = session.new_window(window_name="test", attach=True) assert isinstance(window, Window) assert len(window.panes) == 1 @@ -161,7 +164,7 @@ def test_split_window_horizontal(session: Session) -> None: def test_window_rename( session: Session, window_name_before: str, window_name_after: str ) -> None: - """Window.rename_window().""" + """Test Window.rename_window().""" window_name_before = "test" window_name_after = "ha ha ha fjewlkjflwef" @@ -183,6 +186,7 @@ def test_window_rename( def test_kill_window(session: Session) -> None: + """Test window.kill_window() kills window.""" session.new_window() # create a second window to not kick out the client. # there is another way to do this via options too. @@ -222,6 +226,7 @@ def test_set_show_window_options(session: Session) -> None: def test_empty_window_option_returns_None(session: Session) -> None: + """Verify unset window option returns None.""" window = session.new_window(window_name="test_window") assert window.show_window_option("alternate-screen") is None @@ -287,6 +292,7 @@ def test_move_window(session: Session) -> None: def test_move_window_to_other_session(server: Server, session: Session) -> None: + """Window.move_window to other session.""" window = session.new_window(window_name="test_window") new_session = server.new_session("test_move_window") window.move_window(session=new_session.get("session_id")) @@ -305,6 +311,7 @@ def test_select_layout_accepts_no_arg(server: Server, session: Session) -> None: has_lt_version("3.2"), reason="needs filter introduced in tmux >= 3.2" ) def test_empty_window_name(session: Session) -> None: + """New windows can be created with empty string for window name.""" session.set_option("automatic-rename", "off") window = session.new_window(window_name="''", attach=True) @@ -337,6 +344,7 @@ def test_split_window_with_environment( session: Session, environment: t.Dict[str, str], ) -> None: + """Verify splitting window with environment variables.""" env = shutil.which("env") assert env is not None, "Cannot find usable `env` in Path." @@ -361,6 +369,7 @@ def test_split_window_with_environment_logs_warning_for_old_tmux( session: Session, caplog: pytest.LogCaptureFixture, ) -> None: + """Verify splitting window with environment variables warns if tmux too old.""" env = shutil.which("env") assert env is not None, "Cannot find usable `env` in Path." From 530df7d04bdc655c8146d3a731a3ae9dd7e665a1 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 13:37:49 -0600 Subject: [PATCH 14/41] chore(tests[legacy_version]): pydocstyle manual fixes --- tests/legacy_api/test_version.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/legacy_api/test_version.py b/tests/legacy_api/test_version.py index dc4af269d..99820f9f2 100644 --- a/tests/legacy_api/test_version.py +++ b/tests/legacy_api/test_version.py @@ -1,3 +1,4 @@ +"""Tests for version comparison.""" import operator import typing as t from contextlib import nullcontext as does_not_raise @@ -30,10 +31,13 @@ ], ) def test_version(version: str) -> None: + """Assert LooseVersion constructor against various version strings.""" assert LooseVersion(version) class VersionCompareFixture(t.NamedTuple): + """Test fixture for version comparison.""" + a: object op: "VersionCompareOp" b: object @@ -61,6 +65,7 @@ def test_version_compare( b: str, raises: t.Union[t.Type[Exception], bool], ) -> None: + """Assert version comparisons.""" raises_ctx: "RaisesContext[Exception]" = ( pytest.raises(t.cast(t.Type[Exception], raises)) if raises From a98fc87853dce6c2bebac17578de74e79d6a4490 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 13:38:27 -0600 Subject: [PATCH 15/41] chore(tests[legacy_test]): pydocstyle manual fixes --- tests/legacy_api/test_test.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/legacy_api/test_test.py b/tests/legacy_api/test_test.py index 741a340bd..d92e60e81 100644 --- a/tests/legacy_api/test_test.py +++ b/tests/legacy_api/test_test.py @@ -1,3 +1,4 @@ +"""Tests for libtmux's testing utilities.""" from time import time import pytest @@ -7,6 +8,7 @@ def test_retry_three_times() -> None: + """Test retry_until().""" ini = time() value = 0 @@ -28,6 +30,7 @@ def call_me_three_times() -> bool: def test_function_times_out() -> None: + """Test time outs with retry_until().""" ini = time() def never_true() -> bool: @@ -41,7 +44,8 @@ def never_true() -> bool: assert abs((end - ini) - 1.0) < 0.01 -def test_function_times_out_no_rise() -> None: +def test_function_times_out_no_raise() -> None: + """Tests retry_until() with exception raising disabled.""" ini = time() def never_true() -> bool: @@ -55,6 +59,7 @@ def never_true() -> bool: def test_function_times_out_no_raise_assert() -> None: + """Tests retry_until() with exception raising disabled, returning False.""" ini = time() def never_true() -> bool: @@ -68,6 +73,7 @@ def never_true() -> bool: def test_retry_three_times_no_raise_assert() -> None: + """Tests retry_until() with exception raising disabled, with closure variable.""" ini = time() value = 0 From fdef43c6d9b46e2f0149535a34d9239f9a0a2211 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 13:39:47 -0600 Subject: [PATCH 16/41] chore(tests[legacy_session]): pydocstyle manual fixes --- tests/legacy_api/test_session.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/legacy_api/test_session.py b/tests/legacy_api/test_session.py index 154a207e0..8d43c7abe 100644 --- a/tests/legacy_api/test_session.py +++ b/tests/legacy_api/test_session.py @@ -140,6 +140,7 @@ def test_set_show_option(session: Session) -> None: def test_empty_session_option_returns_None(session: Session) -> None: + """Verify Session.show_option returns None for unset option.""" assert session.show_option("default-shell") is None @@ -221,6 +222,7 @@ def test_unset_environment(session: Session) -> None: def test_periods_raise_badsessionname( server: Server, session: Session, session_name: str, raises: bool ) -> None: + """Verify session names with periods raise BadSessionName.""" new_name = session_name + "moo" # used for rename / switch if raises: with pytest.raises(exc.BadSessionName): @@ -247,6 +249,7 @@ def test_periods_raise_badsessionname( def test_cmd_inserts_session_id(session: Session) -> None: + """Verify Session.cmd() inserts session_id.""" current_session_id = session.id last_arg = "last-arg" cmd = session.cmd("not-a-command", last_arg) @@ -270,6 +273,7 @@ def test_new_window_with_environment( session: Session, environment: t.Dict[str, str], ) -> None: + """Verify new window with environment vars.""" env = shutil.which("env") assert env is not None, "Cannot find usable `env` in PATH." @@ -294,6 +298,7 @@ def test_new_window_with_environment_logs_warning_for_old_tmux( session: Session, caplog: pytest.LogCaptureFixture, ) -> None: + """Verify new window with environment vars create a warning if tmux is too old.""" env = shutil.which("env") assert env is not None, "Cannot find usable `env` in PATH." From 0c28aabdad0aa509a258ab13766b7aad4d4688a6 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 13:43:17 -0600 Subject: [PATCH 17/41] chore(tests[legacy_server]): pydocstyle manual fixes --- tests/legacy_api/test_server.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tests/legacy_api/test_server.py b/tests/legacy_api/test_server.py index c06909e0e..5b60afc2c 100644 --- a/tests/legacy_api/test_server.py +++ b/tests/legacy_api/test_server.py @@ -12,6 +12,7 @@ def test_has_session(server: Server, session: Session) -> None: + """Server.has_session() returns True if session exists.""" session_name = session.get("session_name") assert session_name is not None assert server.has_session(session_name) @@ -44,6 +45,7 @@ def test_config(server: Server) -> None: def test_256_colors(server: Server) -> None: + """Assert Server respects ``colors=256``.""" myserver = Server(colors=256) assert myserver.colors == 256 @@ -54,6 +56,7 @@ def test_256_colors(server: Server) -> None: def test_88_colors(server: Server) -> None: + """Assert Server respects ``colors=88``.""" myserver = Server(colors=88) assert myserver.colors == 88 @@ -110,9 +113,7 @@ def test_new_session_no_name(server: Server) -> None: def test_new_session_shell(server: Server) -> None: - """Server.new_session creates and returns valid session running with - specified command. - """ + """Verify ``Server.new_session`` creates valid session running w/ command.""" cmd = "sleep 1m" mysession = server.new_session("test_new_session", window_command=cmd) window = mysession.list_windows()[0] @@ -130,31 +131,37 @@ def test_new_session_shell(server: Server) -> None: def test_no_server_sessions() -> None: + """Verify ``Server.sessions`` returns empty list without tmux server.""" server = Server(socket_name="test_attached_session_no_server") assert server.sessions == [] def test_no_server_attached_sessions() -> None: + """Verify ``Server.attached_sessions`` returns empty list without tmux server.""" server = Server(socket_name="test_no_server_attached_sessions") assert server.attached_sessions == [] def test_no_server_is_alive() -> None: + """Verify is_alive() returns False without tmux server.""" dead_server = Server(socket_name="test_no_server_is_alive") assert not dead_server.is_alive() def test_with_server_is_alive(server: Server) -> None: + """Verify is_alive() returns True when tmux server is alive.""" server.new_session() assert server.is_alive() -def test_no_server_raise_if_dead() -> None: +def test_raise_if_dead_no_server_raises() -> None: + """Verify new_session() raises if tmux server is dead.""" dead_server = Server(socket_name="test_attached_session_no_server") with pytest.raises(subprocess.SubprocessError): dead_server.raise_if_dead() -def test_with_server_raise_if_dead(server: Server) -> None: +def test_raise_if_dead_does_not_raise_if_alive(server: Server) -> None: + """Verify new_session() does not raise if tmux server is alive.""" server.new_session() server.raise_if_dead() From 27500195736b45e24aeb3c9c9e9e52e7d4d8b099 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 13:44:10 -0600 Subject: [PATCH 18/41] chore(tests[legacy_pane]): pydocstyle manual fixes --- tests/legacy_api/test_pane.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/legacy_api/test_pane.py b/tests/legacy_api/test_pane.py index 669a5fd67..24b600b71 100644 --- a/tests/legacy_api/test_pane.py +++ b/tests/legacy_api/test_pane.py @@ -26,6 +26,7 @@ def test_resize_pane(session: Session) -> None: def test_send_keys(session: Session) -> None: + """Verify Pane.send_keys().""" pane = session.attached_window.attached_pane assert pane is not None pane.send_keys("c-c", literal=True) @@ -38,6 +39,7 @@ def test_send_keys(session: Session) -> None: def test_set_height(session: Session) -> None: + """Verify Pane.set_height().""" window = session.new_window(window_name="test_set_height") window.split_window() pane1 = window.attached_pane @@ -50,6 +52,7 @@ def test_set_height(session: Session) -> None: def test_set_width(session: Session) -> None: + """Verify Pane.set_width().""" window = session.new_window(window_name="test_set_width") window.split_window() @@ -66,6 +69,7 @@ def test_set_width(session: Session) -> None: def test_capture_pane(session: Session) -> None: + """Verify Pane.capture_pane().""" env = shutil.which("env") assert env is not None, "Cannot find usable `env` in PATH." From 66a5f6aab924b51880f7c8501861083b50b6f8ac Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 13:44:45 -0600 Subject: [PATCH 19/41] chore(tests[legacy_common]): pydocstyle manual fixes --- tests/legacy_api/test_common.py | 46 +++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/tests/legacy_api/test_common.py b/tests/legacy_api/test_common.py index 158049530..1cd62c6f3 100644 --- a/tests/legacy_api/test_common.py +++ b/tests/legacy_api/test_common.py @@ -1,9 +1,7 @@ """Tests for utility functions in libtmux.""" - import re import sys import typing as t -from typing import Optional import pytest @@ -30,6 +28,8 @@ def test_allows_master_version(monkeypatch: pytest.MonkeyPatch) -> None: + """Assert get_version() works with builds from git trunk.""" + class Hi: stdout: t.ClassVar = ["tmux master"] stderr = None @@ -48,6 +48,7 @@ def mock_tmux_cmd(*args: t.Any, **kwargs: t.Any) -> Hi: def test_allows_next_version(monkeypatch: pytest.MonkeyPatch) -> None: + """Assert get_version() supports next version.""" TMUX_NEXT_VERSION = str(float(TMUX_MAX_VERSION) + 0.1) class Hi: @@ -66,6 +67,8 @@ def mock_tmux_cmd(*args: t.Any, **kwargs: t.Any) -> Hi: def test_get_version_openbsd(monkeypatch: pytest.MonkeyPatch) -> None: + """Assert get_version() with OpenBSD versions.""" + class Hi: stderr: t.ClassVar = ["tmux: unknown option -- V"] @@ -83,6 +86,8 @@ def mock_tmux_cmd(*args: t.Any, **kwargs: t.Any) -> Hi: def test_get_version_too_low(monkeypatch: pytest.MonkeyPatch) -> None: + """Assert get_version() raises if tmux version too low.""" + class Hi: stderr: t.ClassVar = ["tmux: unknown option -- V"] @@ -96,7 +101,7 @@ def mock_tmux_cmd(*args: t.Any, **kwargs: t.Any) -> Hi: def test_ignores_letter_versions(monkeypatch: pytest.MonkeyPatch) -> None: - """Ignore letters such as 1.8b. + """Tests version utilities ignores letters such as 1.8b. See ticket https://github.com/tmux-python/tmuxp/issues/55. @@ -119,6 +124,8 @@ def test_ignores_letter_versions(monkeypatch: pytest.MonkeyPatch) -> None: def test_error_version_less_1_7(monkeypatch: pytest.MonkeyPatch) -> None: + """Test raises if tmux version less than 1.7.""" + def mock_get_version() -> LooseVersion: return LooseVersion("1.7") @@ -134,10 +141,12 @@ def mock_get_version() -> LooseVersion: def test_has_version() -> None: + """Test has_version().""" assert has_version(str(get_version())) def test_has_gt_version() -> None: + """Test has_gt_version().""" assert has_gt_version("1.6") assert has_gt_version("1.6b") @@ -146,6 +155,7 @@ def test_has_gt_version() -> None: def test_has_gte_version() -> None: + """Test has_gte_version().""" assert has_gte_version("1.6") assert has_gte_version("1.6b") assert has_gte_version(str(get_version())) @@ -155,6 +165,7 @@ def test_has_gte_version() -> None: def test_has_lt_version() -> None: + """Test has_lt_version().""" assert has_lt_version("4.0a") assert has_lt_version("4.0") @@ -163,6 +174,7 @@ def test_has_lt_version() -> None: def test_has_lte_version() -> None: + """Test has_lti_version().""" assert has_lte_version("4.0a") assert has_lte_version("4.0") assert has_lte_version(str(get_version())) @@ -172,29 +184,40 @@ def test_has_lte_version() -> None: def test_tmux_cmd_raises_on_not_found(monkeypatch: pytest.MonkeyPatch) -> None: + """Verify raises if tmux command not found.""" monkeypatch.setenv("PATH", "") with pytest.raises(TmuxCommandNotFound): tmux_cmd("-V") def test_tmux_cmd_unicode(session: Session) -> None: + """Verify tmux commands with unicode.""" session.cmd("new-window", "-t", 3, "-n", "юникод", "-F", "Ελληνικά") +class SessionCheckName(t.NamedTuple): + """Test fixture for test_session_check_name().""" + + session_name: t.Optional[str] + raises: bool + exc_msg_regex: t.Optional[str] + + @pytest.mark.parametrize( - "session_name,raises,exc_msg_regex", + SessionCheckName._fields, [ - ("", True, "empty"), - (None, True, "empty"), - ("my great session.", True, "contains periods"), - ("name: great session", True, "contains colons"), - ("new great session", False, None), - ("ajf8a3fa83fads,,,a", False, None), + SessionCheckName("", True, "empty"), + SessionCheckName(None, True, "empty"), + SessionCheckName("my great session.", True, "contains periods"), + SessionCheckName("name: great session", True, "contains colons"), + SessionCheckName("new great session", False, None), + SessionCheckName("ajf8a3fa83fads,,,a", False, None), ], ) def test_session_check_name( - session_name: Optional[str], raises: bool, exc_msg_regex: Optional[str] + session_name: t.Optional[str], raises: bool, exc_msg_regex: t.Optional[str] ) -> None: + """Verify session_check_name().""" if raises: with pytest.raises(BadSessionName) as exc_info: session_check_name(session_name) @@ -205,6 +228,7 @@ def test_session_check_name( def test_get_libtmux_version() -> None: + """Verify get_libtmux_version().""" from libtmux.__about__ import __version__ version = get_libtmux_version() From 611dba390afc3e1f56aab6bf5e6e4530ffc65d86 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 13:45:35 -0600 Subject: [PATCH 20/41] chore(tests[legacy]): pydocstyle manual fixes --- tests/legacy_api/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/legacy_api/__init__.py b/tests/legacy_api/__init__.py index e69de29bb..3e4a7d4c4 100644 --- a/tests/legacy_api/__init__.py +++ b/tests/legacy_api/__init__.py @@ -0,0 +1 @@ +"""Tests for Legacy libtmux API (to be deprecated).""" From 9a2859ad17a3b3ba8e7d99b67e459a43400455e4 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 13:45:58 -0600 Subject: [PATCH 21/41] chore(tests): pydocstyle manual fixes --- tests/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/__init__.py b/tests/__init__.py index e69de29bb..5d10f3bee 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -0,0 +1 @@ +"""Tests for libtmux package.""" From 147ecc54a0d72d7580b32312177ae0bccd83b676 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 25 Nov 2023 14:17:14 -0600 Subject: [PATCH 22/41] chore(window): pydocstyle manual fixes --- src/libtmux/window.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/libtmux/window.py b/src/libtmux/window.py index 5a8aafcc8..b07fde984 100644 --- a/src/libtmux/window.py +++ b/src/libtmux/window.py @@ -80,6 +80,7 @@ class Window(Obj): server: "Server" def refresh(self) -> None: + """Refresh window attributes from tmux.""" assert isinstance(self.window_id, str) return super()._refresh( obj_key="window_id", @@ -89,6 +90,7 @@ def refresh(self) -> None: @classmethod def from_window_id(cls, server: "Server", window_id: str) -> "Window": + """Create Window from existing window_id.""" window = fetch_obj( obj_key="window_id", obj_id=window_id, @@ -100,6 +102,7 @@ def from_window_id(cls, server: "Server", window_id: str) -> "Window": @property def session(self) -> "Session": + """Parent session of window.""" assert isinstance(self.session_id, str) from libtmux.session import Session @@ -282,7 +285,9 @@ def last_pane(self) -> t.Optional["Pane"]: return self.select_pane("-l") def select_layout(self, layout: t.Optional[str] = None) -> "Window": - """Wrapper for ``$ tmux select-layout ``. + """Select layout for window. + + Wrapper for ``$ tmux select-layout ``. Parameters ---------- @@ -323,8 +328,9 @@ def select_layout(self, layout: t.Optional[str] = None) -> "Window": return self def set_window_option(self, option: str, value: t.Union[int, str]) -> "Window": - """ - Wrapper for ``$ tmux set-window-option