From 3bcd28a5730342d981014f693d32cd5944f9aa38 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 2 Dec 2023 16:50:14 -0600 Subject: [PATCH 01/94] pyproject(ruff): Add pydocstyle rule selector w/ numpy convention --- pyproject.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 9ebfde9c762..1c4536cd4b7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -146,6 +146,7 @@ select = [ "TRY", # Trycertatops "PERF", # Perflint "RUF", # Ruff-specific rules + "D", # pydocstyle ] [tool.ruff.isort] @@ -154,6 +155,9 @@ known-first-party = [ ] combine-as-imports = true +[tool.ruff.pydocstyle] +convention = "numpy" + [tool.ruff.per-file-ignores] "*/__init__.py" = ["F401"] "src/tmuxp/workspace/finders.py" = ["PTH"] From 82da0961fa5e8439ffaccb405616ea1ea981a718 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 9 Dec 2023 05:11:24 -0600 Subject: [PATCH 02/94] 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 45 errors: - docs/_ext/aafig.py: 7 × D208 (over-indentation) 1 × D202 (no-blank-line-after-function) - src/tmuxp/cli/__init__.py: 2 × D202 (no-blank-line-after-function) 1 × D209 (new-line-after-last-paragraph) - src/tmuxp/cli/freeze.py: 1 × D209 (new-line-after-last-paragraph) - src/tmuxp/cli/import_config.py: 2 × D209 (new-line-after-last-paragraph) - src/tmuxp/cli/load.py: 2 × D412 (blank-lines-between-header-and-content) 1 × D406 (new-line-after-section-name) 1 × D407 (dashed-underline-after-section) - src/tmuxp/cli/utils.py: 3 × D202 (no-blank-line-after-function) - src/tmuxp/exc.py: 5 × D211 (blank-line-before-class) - src/tmuxp/log.py: 1 × D202 (no-blank-line-after-function) - src/tmuxp/types.py: 1 × D412 (blank-lines-between-header-and-content) - src/tmuxp/workspace/builder.py: 2 × D202 (no-blank-line-after-function) 1 × D412 (blank-lines-between-header-and-content) - src/tmuxp/workspace/finders.py: 1 × D202 (no-blank-line-after-function) - src/tmuxp/workspace/freezer.py: 1 × D202 (no-blank-line-after-function) - src/tmuxp/workspace/importers.py: 2 × D202 (no-blank-line-after-function) 1 × D412 (blank-lines-between-header-and-content) - src/tmuxp/workspace/loader.py: 2 × D202 (no-blank-line-after-function) - tests/cli/test_cli.py: 1 × D202 (no-blank-line-after-function) - tests/tests/test_helpers.py: 1 × D202 (no-blank-line-after-function) - tests/workspace/test_finder.py: 3 × D202 (no-blank-line-after-function) - tests/workspace/test_freezer.py: 1 × D202 (no-blank-line-after-function) - tests/workspace/test_import_teamocil.py: 1 × D209 (new-line-after-last-paragraph) Fixed 45 errors (35 additional fixes available with `--unsafe-fixes`). --- docs/_ext/aafig.py | 15 +++++++-------- src/tmuxp/cli/__init__.py | 5 ++--- src/tmuxp/cli/freeze.py | 3 ++- src/tmuxp/cli/import_config.py | 6 ++++-- src/tmuxp/cli/load.py | 5 ++--- src/tmuxp/cli/utils.py | 3 --- src/tmuxp/exc.py | 5 ----- src/tmuxp/log.py | 1 - src/tmuxp/types.py | 1 - src/tmuxp/workspace/builder.py | 3 --- src/tmuxp/workspace/finders.py | 1 - src/tmuxp/workspace/freezer.py | 1 - src/tmuxp/workspace/importers.py | 3 --- src/tmuxp/workspace/loader.py | 2 -- tests/cli/test_cli.py | 1 - tests/tests/test_helpers.py | 1 - tests/workspace/test_finder.py | 3 --- tests/workspace/test_freezer.py | 1 - tests/workspace/test_import_teamocil.py | 3 ++- 19 files changed, 19 insertions(+), 44 deletions(-) diff --git a/docs/_ext/aafig.py b/docs/_ext/aafig.py index d3885405e2d..c9bb4f88794 100644 --- a/docs/_ext/aafig.py +++ b/docs/_ext/aafig.py @@ -1,14 +1,14 @@ """ - sphinxcontrib.aafig - ~~~~~~~~~~~~~~~~~~~ +sphinxcontrib.aafig +~~~~~~~~~~~~~~~~~~~ - Allow embedded ASCII art to be rendered as nice looking images - using the aafigure reStructuredText extension. +Allow embedded ASCII art to be rendered as nice looking images +using the aafigure reStructuredText extension. - See the README file for details. +See the README file for details. - :author: Leandro Lucarella - :license: BOLA, see LICENSE for details +:author: Leandro Lucarella +:license: BOLA, see LICENSE for details """ import logging import posixpath @@ -158,7 +158,6 @@ def render_aafigure( """ Render an ASCII art figure into the requested format output file. """ - if aafigure is None: raise AafigureNotInstalled() diff --git a/src/tmuxp/cli/__init__.py b/src/tmuxp/cli/__init__.py index d68246db1f2..d55cae760f8 100644 --- a/src/tmuxp/cli/__init__.py +++ b/src/tmuxp/cli/__init__.py @@ -111,8 +111,8 @@ def cli(_args: t.Optional[t.List[str]] = None) -> None: Pass the "--help" argument to any command to see detailed help. See detailed documentation and examples at: - http://tmuxp.git-pull.com/""" - + http://tmuxp.git-pull.com/ + """ try: has_minimum_version() except TmuxCommandNotFound: @@ -186,6 +186,5 @@ def startup(config_dir: pathlib.Path) -> None: ---------- str : get_workspace_dir(): Config directory to search """ - if not os.path.exists(config_dir): os.makedirs(config_dir) diff --git a/src/tmuxp/cli/freeze.py b/src/tmuxp/cli/freeze.py index 88a2f9751bf..fa76a652a77 100644 --- a/src/tmuxp/cli/freeze.py +++ b/src/tmuxp/cli/freeze.py @@ -90,7 +90,8 @@ def command_freeze( """Snapshot a tmux session into a tmuxp workspace. If SESSION_NAME is provided, snapshot that session. Otherwise, use the - current session.""" + current session. + """ server = Server(socket_name=args.socket_name, socket_path=args.socket_path) try: diff --git a/src/tmuxp/cli/import_config.py b/src/tmuxp/cli/import_config.py index 9048331fa9c..0b04d0eccb9 100644 --- a/src/tmuxp/cli/import_config.py +++ b/src/tmuxp/cli/import_config.py @@ -176,7 +176,8 @@ def command_import_tmuxinator( parser: t.Optional[argparse.ArgumentParser] = None, ) -> None: """Convert a tmuxinator config from workspace_file to tmuxp format and import - it into tmuxp.""" + it into tmuxp. + """ workspace_file = find_workspace_file( workspace_file, workspace_dir=get_tmuxinator_dir() ) @@ -188,7 +189,8 @@ def command_import_teamocil( parser: t.Optional[argparse.ArgumentParser] = None, ) -> None: """Convert a teamocil config from workspace_file to tmuxp format and import - it into tmuxp.""" + it into tmuxp. + """ workspace_file = find_workspace_file( workspace_file, workspace_dir=get_teamocil_dir() ) diff --git a/src/tmuxp/cli/load.py b/src/tmuxp/cli/load.py index e965299f90f..e8b60539ecc 100644 --- a/src/tmuxp/cli/load.py +++ b/src/tmuxp/cli/load.py @@ -50,8 +50,8 @@ class CLILoadNamespace(argparse.Namespace): def set_layout_hook(session: Session, hook_name: str) -> None: """Set layout hooks to normalize layout. - References: - + References + ---------- - tmuxp issue: https://github.com/tmux-python/tmuxp/issues/309 - tmux issue: https://github.com/tmux/tmux/issues/1106 @@ -305,7 +305,6 @@ def load_workspace( Notes ----- - tmuxp will check and load a workspace file. The file will use ConfigReader to load a JSON/YAML into a :py:obj:`dict`. Then :func:`loader.expand` and :func:`loader.trickle` will be used to expand any shorthands, template diff --git a/src/tmuxp/cli/utils.py b/src/tmuxp/cli/utils.py index 482f20d0421..0e8d28a60a1 100644 --- a/src/tmuxp/cli/utils.py +++ b/src/tmuxp/cli/utils.py @@ -47,7 +47,6 @@ def prompt( :param default: default value if no input provided. :rtype: string """ - _prompt = name + (default and " [%s]" % default or "") _prompt += name.endswith("?") and " " or ": " while True: @@ -78,7 +77,6 @@ def prompt_bool( :param no_choices: default 'n', 'no', '0', 'off', 'false', 'f' :rtype: bool """ - yes_choices = yes_choices or ("y", "yes", "1", "on", "true", "t") no_choices = no_choices or ("n", "no", "0", "off", "false", "f") @@ -121,7 +119,6 @@ def prompt_choices( :param no_choice: acceptable list of strings for "null choice" :rtype: str """ - _choices: t.List[str] = [] options: t.List[str] = [] diff --git a/src/tmuxp/exc.py b/src/tmuxp/exc.py index 3d04c63735d..4b2fb766228 100644 --- a/src/tmuxp/exc.py +++ b/src/tmuxp/exc.py @@ -12,12 +12,10 @@ class TmuxpException(Exception): - """Base Exception for Tmuxp Errors.""" class WorkspaceError(TmuxpException): - """Error parsing tmuxp workspace data.""" @@ -52,7 +50,6 @@ def __init__( class EmptyWorkspaceException(WorkspaceError): - """Workspace file is empty.""" def __init__(self, *args: object, **kwargs: object) -> None: @@ -75,7 +72,6 @@ def __init__(self, *args: object, **kwargs: object) -> None: class TmuxpPluginException(TmuxpException): - """Base Exception for Tmuxp Errors.""" @@ -88,7 +84,6 @@ def __init__(self, *args: object, **kwargs: object) -> None: @implements_to_string class BeforeLoadScriptError(Exception): - """Exception replacing :py:class:`subprocess.CalledProcessError` for :meth:`tmuxp.util.run_before_script`. """ diff --git a/src/tmuxp/log.py b/src/tmuxp/log.py index b05b5ac7ef9..70c385b549f 100644 --- a/src/tmuxp/log.py +++ b/src/tmuxp/log.py @@ -155,7 +155,6 @@ def debug_log_template( str Log template. """ - reset = Style.RESET_ALL levelname = ( LEVEL_COLORS.get(record.levelname, "") diff --git a/src/tmuxp/types.py b/src/tmuxp/types.py index f1f6c138f88..02f61db8702 100644 --- a/src/tmuxp/types.py +++ b/src/tmuxp/types.py @@ -2,7 +2,6 @@ Notes ----- - :class:`StrPath` and :class:`StrOrBytesPath` is based on `typeshed's`_. .. _typeshed's: https://github.com/python/typeshed/blob/9687d5/stdlib/_typeshed/__init__.pyi#L98 diff --git a/src/tmuxp/workspace/builder.py b/src/tmuxp/workspace/builder.py index f149d87d4d7..ed477caca49 100644 --- a/src/tmuxp/workspace/builder.py +++ b/src/tmuxp/workspace/builder.py @@ -33,7 +33,6 @@ class WorkspaceBuilder: Examples -------- - >>> import yaml >>> session_config = yaml.load(''' @@ -161,7 +160,6 @@ def __init__( TODO: Initialize :class:`libtmux.Session` from here, in ``self.session``. """ - if plugins is None: plugins = [] if not session_config: @@ -222,7 +220,6 @@ def build(self, session: t.Optional[Session] = None, append: bool = False) -> No append : bool append windows in current active session """ - if not session: if not self.server: raise exc.TmuxpException( diff --git a/src/tmuxp/workspace/finders.py b/src/tmuxp/workspace/finders.py index ecc7fea5a27..9ee7f1618e2 100644 --- a/src/tmuxp/workspace/finders.py +++ b/src/tmuxp/workspace/finders.py @@ -113,7 +113,6 @@ def get_workspace_dir() -> str: str : absolute path to tmuxp config directory """ - paths = [] if "TMUXP_CONFIGDIR" in os.environ: paths.append(os.environ["TMUXP_CONFIGDIR"]) diff --git a/src/tmuxp/workspace/freezer.py b/src/tmuxp/workspace/freezer.py index 0d1d14e98fb..8adb4295b63 100644 --- a/src/tmuxp/workspace/freezer.py +++ b/src/tmuxp/workspace/freezer.py @@ -19,7 +19,6 @@ def inline(workspace_dict: t.Dict[str, t.Any]) -> t.Any: dict workspace with shorthands inlined. """ - if ( "shell_command" in workspace_dict and isinstance(workspace_dict["shell_command"], list) diff --git a/src/tmuxp/workspace/importers.py b/src/tmuxp/workspace/importers.py index 9f60208f28c..e5fb789821d 100644 --- a/src/tmuxp/workspace/importers.py +++ b/src/tmuxp/workspace/importers.py @@ -15,7 +15,6 @@ def import_tmuxinator(workspace_dict: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]: ------- dict """ - tmuxp_workspace = {} if "project_name" in workspace_dict: @@ -111,7 +110,6 @@ def import_teamocil(workspace_dict: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]: Notes ----- - Todos: - change 'root' to a cd or start_directory @@ -120,7 +118,6 @@ def import_teamocil(workspace_dict: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]: - clear - cmd_separator """ - tmuxp_workspace = {} if "session" in workspace_dict: diff --git a/src/tmuxp/workspace/loader.py b/src/tmuxp/workspace/loader.py index 96c029069cf..e17d768ff5c 100644 --- a/src/tmuxp/workspace/loader.py +++ b/src/tmuxp/workspace/loader.py @@ -102,7 +102,6 @@ def expand( ------- dict """ - # Note: cli.py will expand workspaces relative to project's workspace directory # for the first cwd argument. cwd = pathlib.Path().cwd() if not cwd else pathlib.Path(cwd) @@ -208,7 +207,6 @@ def trickle(workspace_dict: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]: ------- dict """ - # prepends a pane's ``shell_command`` list with the window and sessions' # ``shell_command_before``. diff --git a/tests/cli/test_cli.py b/tests/cli/test_cli.py index 48f5be0bf1f..3cb3a20ee66 100644 --- a/tests/cli/test_cli.py +++ b/tests/cli/test_cli.py @@ -24,7 +24,6 @@ def test_creates_config_dir_not_exists(tmp_path: pathlib.Path) -> None: """cli.startup() creates config dir if not exists.""" - cli.startup(tmp_path) assert tmp_path.exists() diff --git a/tests/tests/test_helpers.py b/tests/tests/test_helpers.py index 5928f73937a..7f6360a4787 100644 --- a/tests/tests/test_helpers.py +++ b/tests/tests/test_helpers.py @@ -18,7 +18,6 @@ def test_kills_session(server: Server) -> None: @pytest.mark.flaky(reruns=5) def test_if_session_killed_before(server: Server) -> None: """Handles situation where session already closed within context""" - server = server session_name = get_test_session_name(server=server) diff --git a/tests/workspace/test_finder.py b/tests/workspace/test_finder.py index a1e79a7d17f..90f1e1dd374 100644 --- a/tests/workspace/test_finder.py +++ b/tests/workspace/test_finder.py @@ -20,7 +20,6 @@ def test_in_dir_from_config_dir(tmp_path: pathlib.Path) -> None: """config.in_dir() finds configs config dir.""" - cli.startup(tmp_path) yaml_config = tmp_path / "myconfig.yaml" yaml_config.touch() @@ -33,7 +32,6 @@ def test_in_dir_from_config_dir(tmp_path: pathlib.Path) -> None: def test_ignore_non_configs_from_current_dir(tmp_path: pathlib.Path) -> None: """cli.in_dir() ignore non-config from config dir.""" - cli.startup(tmp_path) junk_config = tmp_path / "myconfig.psd" @@ -48,7 +46,6 @@ def test_get_configs_cwd( tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch ) -> None: """config.in_cwd() find config in shell current working directory.""" - confdir = tmp_path / "tmuxpconf2" confdir.mkdir() diff --git a/tests/workspace/test_freezer.py b/tests/workspace/test_freezer.py index 718ab13c4d8..fcaa7662336 100644 --- a/tests/workspace/test_freezer.py +++ b/tests/workspace/test_freezer.py @@ -80,7 +80,6 @@ def test_freeze_config(session: Session) -> None: def test_inline_workspace() -> None: """:meth:`freezer.inline()` shell commands list to string.""" - test_workspace = freezer.inline(ibefore_workspace) assert test_workspace == iafter_workspace diff --git a/tests/workspace/test_import_teamocil.py b/tests/workspace/test_import_teamocil.py index 12ddc0513f3..cf376a6df23 100644 --- a/tests/workspace/test_import_teamocil.py +++ b/tests/workspace/test_import_teamocil.py @@ -59,7 +59,8 @@ def multisession_config() -> ( """Return loaded multisession teamocil config as a dictionary. Also prevents re-running assertion the loads the yaml, since ordering of - deep list items like panes will be inconsistent.""" + deep list items like panes will be inconsistent. + """ teamocil_yaml_file = fixtures.layouts.teamocil_yaml_file test_config = config_reader.ConfigReader._from_file(teamocil_yaml_file) teamocil_dict: t.Dict[str, t.Any] = fixtures.layouts.teamocil_dict From f9e2b5db9fa3fc456651632a9eeacc6f0c701430 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 9 Dec 2023 05:12:28 -0600 Subject: [PATCH 03/94] 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 35 errors: - conftest.py: 1 × D400 (ends-in-period) - docs/_ext/aafig.py: 2 × D200 (fits-on-one-line) 1 × D400 (ends-in-period) - docs/conf.py: 1 × D400 (ends-in-period) - src/tmuxp/_types.py: 1 × D400 (ends-in-period) - src/tmuxp/cli/debug_info.py: 4 × D200 (fits-on-one-line) - src/tmuxp/cli/load.py: 6 × D400 (ends-in-period) 1 × D200 (fits-on-one-line) - src/tmuxp/cli/utils.py: 5 × D400 (ends-in-period) 1 × D200 (fits-on-one-line) - src/tmuxp/config_reader.py: 1 × D400 (ends-in-period) - src/tmuxp/plugin.py: 2 × D200 (fits-on-one-line) - src/tmuxp/shell.py: 1 × D400 (ends-in-period) - src/tmuxp/types.py: 1 × D400 (ends-in-period) - src/tmuxp/util.py: 1 × D400 (ends-in-period) - tests/fixtures/pluginsystem/partials/_types.py: 2 × D400 (ends-in-period) - tests/fixtures/utils.py: 2 × D400 (ends-in-period) - tests/tests/test_helpers.py: 1 × D400 (ends-in-period) - tests/workspace/conftest.py: 1 × D400 (ends-in-period) Fixed 35 errors. --- conftest.py | 2 +- docs/_ext/aafig.py | 10 +++------- docs/conf.py | 2 +- src/tmuxp/_types.py | 2 +- src/tmuxp/cli/debug_info.py | 16 ++++------------ src/tmuxp/cli/load.py | 14 ++++++-------- src/tmuxp/cli/utils.py | 12 +++++------- src/tmuxp/config_reader.py | 2 +- src/tmuxp/plugin.py | 8 ++------ src/tmuxp/shell.py | 2 +- src/tmuxp/types.py | 2 +- src/tmuxp/util.py | 2 +- tests/fixtures/pluginsystem/partials/_types.py | 4 ++-- tests/fixtures/utils.py | 4 ++-- tests/tests/test_helpers.py | 2 +- tests/workspace/conftest.py | 2 +- 16 files changed, 33 insertions(+), 53 deletions(-) diff --git a/conftest.py b/conftest.py index 024ccbf9d96..9239dc22b85 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. diff --git a/docs/_ext/aafig.py b/docs/_ext/aafig.py index c9bb4f88794..0a5df9bacc1 100644 --- a/docs/_ext/aafig.py +++ b/docs/_ext/aafig.py @@ -1,5 +1,5 @@ """ -sphinxcontrib.aafig +sphinxcontrib.aafig. ~~~~~~~~~~~~~~~~~~~ Allow embedded ASCII art to be rendered as nice looking images @@ -61,9 +61,7 @@ class AafigError(SphinxError): class AafigDirective(images.Image): # type:ignore - """ - Directive to insert an ASCII art figure to be rendered by aafigure. - """ + """Directive to insert an ASCII art figure to be rendered by aafigure.""" has_content = True required_arguments = 0 @@ -155,9 +153,7 @@ def __init__(self, *args: object, **kwargs: object) -> None: def render_aafigure( app: "Sphinx", text: str, options: t.Dict[str, str] ) -> t.Tuple[str, str, t.Optional[str], t.Optional[str]]: - """ - Render an ASCII art figure into the requested format output file. - """ + """Render an ASCII art figure into the requested format output file.""" if aafigure is None: raise AafigureNotInstalled() diff --git a/docs/conf.py b/docs/conf.py index afe2de2a710..1ccd14f3f84 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -142,7 +142,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/tmuxp/_types.py b/src/tmuxp/_types.py index 79eac5c9c2a..6ea5e0c75cc 100644 --- a/src/tmuxp/_types.py +++ b/src/tmuxp/_types.py @@ -1,4 +1,4 @@ -"""Internal, :const:`typing.TYPE_CHECKING` guarded :term:`type annotations ` +"""Internal, :const:`typing.TYPE_CHECKING` guarded :term:`type annotations `. These are _not_ to be imported at runtime as `typing_extensions` is not bundled with tmuxp. Usage example: diff --git a/src/tmuxp/cli/debug_info.py b/src/tmuxp/cli/debug_info.py index df6a65e19dc..386584612f9 100644 --- a/src/tmuxp/cli/debug_info.py +++ b/src/tmuxp/cli/debug_info.py @@ -25,26 +25,18 @@ def create_debug_info_subparser( def command_debug_info( parser: t.Optional[argparse.ArgumentParser] = None, ) -> None: - """ - Print debug info to submit with Issues. - """ + """Print debug info to submit with Issues.""" def prepend_tab(strings: t.List[str]) -> t.List[str]: - """ - Prepend tab to strings in list. - """ + """Prepend tab to strings in list.""" return ["\t%s" % x for x in strings] def output_break() -> str: - """ - Generate output break. - """ + """Generate output break.""" return "-" * 25 def format_tmux_resp(std_resp: tmux_cmd) -> str: - """ - Format tmux command response for tmuxp stdout. - """ + """Format tmux command response for tmuxp stdout.""" return "\n".join( [ "\n".join(prepend_tab(std_resp.stdout)), diff --git a/src/tmuxp/cli/load.py b/src/tmuxp/cli/load.py index e8b60539ecc..876ba8adf50 100644 --- a/src/tmuxp/cli/load.py +++ b/src/tmuxp/cli/load.py @@ -105,9 +105,7 @@ def set_layout_hook(session: Session, hook_name: str) -> None: def load_plugins(session_config: t.Dict[str, t.Any]) -> t.List[t.Any]: - """ - Load and return plugins in workspace - """ + """Load and return plugins in workspace.""" plugins = [] if "plugins" in session_config: for plugin in session_config["plugins"]: @@ -155,7 +153,7 @@ def load_plugins(session_config: t.Dict[str, t.Any]) -> t.List[t.Any]: def _reattach(builder: WorkspaceBuilder) -> None: """ - Reattach session (depending on env being inside tmux already or not) + Reattach session (depending on env being inside tmux already or not). Parameters ---------- @@ -185,7 +183,7 @@ def _reattach(builder: WorkspaceBuilder) -> None: def _load_attached(builder: WorkspaceBuilder, detached: bool) -> None: """ - Load workspace in new session + Load workspace in new session. Parameters ---------- @@ -219,7 +217,7 @@ def _load_attached(builder: WorkspaceBuilder, detached: bool) -> None: def _load_detached(builder: WorkspaceBuilder) -> None: """ - Load workspace in new session but don't attach + Load workspace in new session but don't attach. Parameters ---------- @@ -238,7 +236,7 @@ def _load_detached(builder: WorkspaceBuilder) -> None: def _load_append_windows_to_current_session(builder: WorkspaceBuilder) -> None: """ - Load workspace as new windows in current session + Load workspace as new windows in current session. Parameters ---------- @@ -254,7 +252,7 @@ def _load_append_windows_to_current_session(builder: WorkspaceBuilder) -> None: def _setup_plugins(builder: WorkspaceBuilder) -> Session: """ - Runs after before_script + Runs after before_script. Parameters ---------- diff --git a/src/tmuxp/cli/utils.py b/src/tmuxp/cli/utils.py index 0e8d28a60a1..78f370527c9 100644 --- a/src/tmuxp/cli/utils.py +++ b/src/tmuxp/cli/utils.py @@ -18,9 +18,7 @@ def tmuxp_echo( log_level: str = "INFO", style_log: bool = False, ) -> None: - """ - Combines logging.log and click.echo - """ + """Combines logging.log and click.echo.""" if message is None: return @@ -45,7 +43,7 @@ def prompt( https://github.com/techniq/flask-script/blob/master/LICENSE :param name: prompt text :param default: default value if no input provided. - :rtype: string + :rtype: string. """ _prompt = name + (default and " [%s]" % default or "") _prompt += name.endswith("?") and " " or ": " @@ -75,7 +73,7 @@ def prompt_bool( :param default: default value if no input provided. :param yes_choices: default 'y', 'yes', '1', 'on', 'true', 't' :param no_choices: default 'n', 'no', '0', 'off', 'false', 'f' - :rtype: bool + :rtype: bool. """ yes_choices = yes_choices or ("y", "yes", "1", "on", "true", "t") no_choices = no_choices or ("n", "no", "0", "off", "false", "f") @@ -117,7 +115,7 @@ def prompt_choices( single strings or (key, value) tuples. :param default: default value if no input provided. :param no_choice: acceptable list of strings for "null choice" - :rtype: str + :rtype: str. """ _choices: t.List[str] = [] options: t.List[str] = [] @@ -202,7 +200,7 @@ def style( strikethrough: t.Optional[bool] = None, reset: bool = True, ) -> str: - """Credit: click""" + """Credit: click.""" if not isinstance(text, str): text = str(text) diff --git a/src/tmuxp/config_reader.py b/src/tmuxp/config_reader.py index 6c0913d2c36..df37670a422 100644 --- a/src/tmuxp/config_reader.py +++ b/src/tmuxp/config_reader.py @@ -118,7 +118,7 @@ def _from_file(cls, path: pathlib.Path) -> t.Dict[str, t.Any]: @classmethod def from_file(cls, path: pathlib.Path) -> "ConfigReader": - r"""Load data from file path + r"""Load data from file path. **YAML file** diff --git a/src/tmuxp/plugin.py b/src/tmuxp/plugin.py index f6b49432d22..48c5791651a 100644 --- a/src/tmuxp/plugin.py +++ b/src/tmuxp/plugin.py @@ -169,9 +169,7 @@ def __init__(self, **kwargs: "Unpack[PluginConfigSchema]") -> None: self._version_check() def _version_check(self) -> None: - """ - Check all dependency versions for compatibility. - """ + """Check all dependency versions for compatibility.""" for dep, constraints in self.version_constraints.items(): assert isinstance(constraints, dict) try: @@ -192,9 +190,7 @@ def _pass_version_check( vmax: t.Optional[str], incompatible: t.List[t.Union[t.Any, str]], ) -> bool: - """ - Provide affirmative if version compatibility is correct. - """ + """Provide affirmative if version compatibility is correct.""" if vmin and version < Version(vmin): return False if vmax and version > Version(vmax): diff --git a/src/tmuxp/shell.py b/src/tmuxp/shell.py index d5f6aaca950..f7e1ef0b332 100644 --- a/src/tmuxp/shell.py +++ b/src/tmuxp/shell.py @@ -170,7 +170,7 @@ def launch_ptpython() -> None: def get_ptipython(options: "LaunchOptionalImports", vi_mode: bool = False) -> t.Any: - """Based on django-extensions + """Based on django-extensions. Run renamed to launch, get_imported_objects renamed to get_launch_args """ diff --git a/src/tmuxp/types.py b/src/tmuxp/types.py index 02f61db8702..59d3a3aa681 100644 --- a/src/tmuxp/types.py +++ b/src/tmuxp/types.py @@ -1,4 +1,4 @@ -"""Internal :term:`type annotations ` +"""Internal :term:`type annotations `. Notes ----- diff --git a/src/tmuxp/util.py b/src/tmuxp/util.py index 8a306fbedf7..cea240329a4 100644 --- a/src/tmuxp/util.py +++ b/src/tmuxp/util.py @@ -91,7 +91,7 @@ def oh_my_zsh_auto_title() -> None: def get_current_pane(server: "Server") -> t.Optional["Pane"]: - """Return Pane if one found in env""" + """Return Pane if one found in env.""" if os.getenv("TMUX_PANE") is not None: try: return next(p for p in server.panes if p.pane_id == os.getenv("TMUX_PANE")) diff --git a/tests/fixtures/pluginsystem/partials/_types.py b/tests/fixtures/pluginsystem/partials/_types.py index ebe24eea04c..36c6c15c11e 100644 --- a/tests/fixtures/pluginsystem/partials/_types.py +++ b/tests/fixtures/pluginsystem/partials/_types.py @@ -1,4 +1,4 @@ -"""Internal, :const:`typing.TYPE_CHECKING` guarded :term:`type annotations ` +"""Internal, :const:`typing.TYPE_CHECKING` guarded :term:`type annotations `. These are _not_ to be imported at runtime as `typing_extensions` is not bundled with tmuxp. Usage example: @@ -15,7 +15,7 @@ class PluginTestConfigSchema(TypedDict): - """Same as PluginConfigSchema, but with tmux, libtmux, and tmuxp version""" + """Same as PluginConfigSchema, but with tmux, libtmux, and tmuxp version.""" tmux_version: NotRequired[str] libtmux_version: NotRequired[str] diff --git a/tests/fixtures/utils.py b/tests/fixtures/utils.py index 858227c5b3a..b9150ca5ac1 100644 --- a/tests/fixtures/utils.py +++ b/tests/fixtures/utils.py @@ -7,7 +7,7 @@ def get_workspace_file( _file: t.Union[str, pathlib.Path], ) -> pathlib.Path: - """Return fixture data, relative to __file__""" + """Return fixture data, relative to __file__.""" if isinstance(_file, str): _file = pathlib.Path(_file) @@ -15,7 +15,7 @@ def get_workspace_file( def read_workspace_file(_file: t.Union[pathlib.Path, str]) -> str: - """Return fixture data, relative to __file__""" + """Return fixture data, relative to __file__.""" if isinstance(_file, str): _file = pathlib.Path(_file) diff --git a/tests/tests/test_helpers.py b/tests/tests/test_helpers.py index 7f6360a4787..c744d436ccc 100644 --- a/tests/tests/test_helpers.py +++ b/tests/tests/test_helpers.py @@ -17,7 +17,7 @@ def test_kills_session(server: Server) -> None: @pytest.mark.flaky(reruns=5) def test_if_session_killed_before(server: Server) -> None: - """Handles situation where session already closed within context""" + """Handles situation where session already closed within context.""" server = server session_name = get_test_session_name(server=server) diff --git a/tests/workspace/conftest.py b/tests/workspace/conftest.py index 932055675af..9a47cfe69c2 100644 --- a/tests/workspace/conftest.py +++ b/tests/workspace/conftest.py @@ -7,7 +7,7 @@ @pytest.fixture def config_fixture() -> WorkspaceTestData: - """Deferred import of tmuxp.tests.fixtures.* + """Deferred import of tmuxp.tests.fixtures.*. pytest setup (conftest.py) patches os.environ["HOME"], delay execution of os.path.expanduser until here. From d76d4785661d310cd38fe9d2ae1e4ae3c80a1203 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 16 Dec 2023 17:12:29 -0600 Subject: [PATCH 04/94] tests(import_tmuxinator): pydocstyle manual fixes --- tests/workspace/test_import_tmuxinator.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/workspace/test_import_tmuxinator.py b/tests/workspace/test_import_tmuxinator.py index f68f9243b3a..f478312c5be 100644 --- a/tests/workspace/test_import_tmuxinator.py +++ b/tests/workspace/test_import_tmuxinator.py @@ -34,6 +34,7 @@ def test_config_to_dict( tmuxinator_dict: t.Dict[str, t.Any], tmuxp_dict: t.Dict[str, t.Any], ) -> None: + """Test exporting tmuxinator configuration to dictionary.""" yaml_to_dict = ConfigReader._load(format="yaml", content=tmuxinator_yaml) assert yaml_to_dict == tmuxinator_dict From eed77b337dcf54e95dfc769e395cf104927bf6bd Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 16 Dec 2023 18:11:50 -0600 Subject: [PATCH 05/94] tests(import_teamocil): pydocstyle manual fixes --- tests/workspace/test_import_teamocil.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/workspace/test_import_teamocil.py b/tests/workspace/test_import_teamocil.py index cf376a6df23..f7d1f2dfa49 100644 --- a/tests/workspace/test_import_teamocil.py +++ b/tests/workspace/test_import_teamocil.py @@ -39,6 +39,7 @@ def test_config_to_dict( teamocil_dict: t.Dict[str, t.Any], tmuxp_dict: t.Dict[str, t.Any], ) -> None: + """Test exporting teamocil configuration to dictionary.""" yaml_to_dict = config_reader.ConfigReader._load( format="yaml", content=teamocil_yaml ) @@ -89,6 +90,7 @@ def test_multisession_config( expected: t.Dict[str, t.Any], multisession_config: t.Dict[str, t.Any], ) -> None: + """Test importing teamocil multisession configuration.""" # teamocil can fit multiple sessions in a config assert importers.import_teamocil(multisession_config[session_name]) == expected From 121b67527bc12a375e7b1f5d87d90904b0fd097d Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 07:40:04 -0600 Subject: [PATCH 06/94] cli(freeze): Note pydocstyle updates --- tests/cli/test_freeze.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/cli/test_freeze.py b/tests/cli/test_freeze.py index 9d5fac36e2a..c3f593065d9 100644 --- a/tests/cli/test_freeze.py +++ b/tests/cli/test_freeze.py @@ -1,3 +1,4 @@ +"""Test workspace freezing functionality for tmuxp.""" import contextlib import io import pathlib @@ -83,6 +84,7 @@ def test_freeze_overwrite( tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch, ) -> None: + """Test overwrite prompt when freezing a tmuxp configuration file.""" monkeypatch.setenv("HOME", str(tmp_path)) exists_yaml = tmp_path / "exists.yaml" exists_yaml.touch() From 6bb9d45dc09725270a8b4911b2269c97d9e2b9a8 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 07:41:51 -0600 Subject: [PATCH 07/94] tests(cli[freezer]): Note pydocstyle updates --- tests/workspace/test_freezer.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/workspace/test_freezer.py b/tests/workspace/test_freezer.py index fcaa7662336..1447b7f4d14 100644 --- a/tests/workspace/test_freezer.py +++ b/tests/workspace/test_freezer.py @@ -1,4 +1,4 @@ -"""Tests for freezing tmux sessions with tmuxp.""" +"""Tests tmux session freezing functionality for tmuxp.""" import pathlib import time import typing @@ -16,6 +16,7 @@ def test_freeze_config(session: Session) -> None: + """Test freezing a tmux session.""" session_config = ConfigReader._from_file( test_utils.get_workspace_file("workspace/freezer/sample_workspace.yaml") ) @@ -87,6 +88,7 @@ def test_inline_workspace() -> None: def test_export_yaml( tmp_path: pathlib.Path, config_fixture: "WorkspaceTestData" ) -> None: + """Test exporting a frozen tmux session to YAML.""" yaml_workspace_file = tmp_path / "config.yaml" sample_workspace = freezer.inline( From 2ab7bedc2822d16b09bbd06c1279510cffec7f48 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 07:52:41 -0600 Subject: [PATCH 08/94] tests(workspace[finder]): Note pydocstyle updates --- tests/workspace/test_finder.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/workspace/test_finder.py b/tests/workspace/test_finder.py index 90f1e1dd374..fb8cb7da801 100644 --- a/tests/workspace/test_finder.py +++ b/tests/workspace/test_finder.py @@ -1,3 +1,4 @@ +"""Test config file searching for tmuxp.""" import argparse import pathlib import typing as t @@ -75,12 +76,14 @@ def test_get_configs_cwd( ], ) def test_is_pure_name(path: str, expect: bool) -> None: + """Test is_pure_name() is truthy when file, not directory or config alias.""" assert is_pure_name(path) == expect def test_tmuxp_configdir_env_var( tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch ) -> None: + """Tests get_workspace_dir() when TMUXP_CONFIGDIR is set.""" monkeypatch.setenv("TMUXP_CONFIGDIR", str(tmp_path)) assert get_workspace_dir() == str(tmp_path) @@ -89,6 +92,7 @@ def test_tmuxp_configdir_env_var( def test_tmuxp_configdir_xdg_config_dir( tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch ) -> None: + """Test get_workspace_dir() when XDG_CONFIG_HOME is set.""" monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path)) tmux_dir = tmp_path / "tmuxp" tmux_dir.mkdir() @@ -98,6 +102,7 @@ def test_tmuxp_configdir_xdg_config_dir( @pytest.fixture def homedir(tmp_path: pathlib.Path) -> pathlib.Path: + """Fixture to ensure and return a home directory.""" home = tmp_path / "home" home.mkdir() return home @@ -105,6 +110,7 @@ def homedir(tmp_path: pathlib.Path) -> pathlib.Path: @pytest.fixture def configdir(homedir: pathlib.Path) -> pathlib.Path: + """Fixture to ensure user directory for tmuxp and return it, via homedir fixture.""" conf = homedir / ".tmuxp" conf.mkdir() return conf @@ -112,6 +118,7 @@ def configdir(homedir: pathlib.Path) -> pathlib.Path: @pytest.fixture def projectdir(homedir: pathlib.Path) -> pathlib.Path: + """Fixture to ensure and return an example project dir.""" proj = homedir / "work" / "project" proj.mkdir(parents=True) return proj @@ -124,6 +131,7 @@ def test_resolve_dot( projectdir: pathlib.Path, monkeypatch: pytest.MonkeyPatch, ) -> None: + """Test find_workspace_file() resolves dots as relative / current directory.""" monkeypatch.setenv("HOME", str(homedir)) monkeypatch.setenv("XDG_CONFIG_HOME", str(homedir / ".config")) @@ -239,6 +247,7 @@ def test_find_workspace_file_arg( monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str], ) -> None: + """Test find_workspace_file() via file path.""" parser = argparse.ArgumentParser() parser.add_argument("workspace_file", type=str) From 9701cb33c25266a6bebbbabcd36c6fe06a373f2f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 07:55:12 -0600 Subject: [PATCH 09/94] chore(test[config]): Remove unused helper function --- tests/workspace/test_config.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/workspace/test_config.py b/tests/workspace/test_config.py index 5bef626f964..20fb8fb9db8 100644 --- a/tests/workspace/test_config.py +++ b/tests/workspace/test_config.py @@ -14,12 +14,6 @@ from ..fixtures.structures import WorkspaceTestData -def load_yaml(path: t.Union[str, pathlib.Path]) -> t.Dict[str, t.Any]: - return ConfigReader._from_file( - pathlib.Path(path) if isinstance(path, str) else path - ) - - def load_workspace(path: t.Union[str, pathlib.Path]) -> t.Dict[str, t.Any]: return ConfigReader._from_file( pathlib.Path(path) if isinstance(path, str) else path From 7f015bf2435e0d8aabc260d32839230ec64bd375 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 07:56:55 -0600 Subject: [PATCH 10/94] chore(test[config]): Remove unused test --- tests/workspace/test_config.py | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/tests/workspace/test_config.py b/tests/workspace/test_config.py index 20fb8fb9db8..ce69b505f5d 100644 --- a/tests/workspace/test_config.py +++ b/tests/workspace/test_config.py @@ -35,39 +35,6 @@ def test_export_json( assert config_fixture.sample_workspace.sample_workspace_dict == new_workspace_data -# -# There's no tests for this -# -def test_find_workspace_file(tmp_path: pathlib.Path) -> None: - configs = [str(tmp_path / x) for x in tmp_path.rglob("*.[json][ini][yaml]")] - - garbage_file = tmp_path / "config.psd" - garbage_file.write_text("wat", encoding="utf-8") - - # for _r, _d, f in os.walk(str(tmp_path)): - # configs.extend( - # [str(tmp_path / x) for x in f if x.endswith((".json", ".ini", "yaml"))] - # ) - - files = 0 - config_json = tmp_path / "config.json" - config_yaml = tmp_path / "config.yaml" - config_ini = tmp_path / "config.ini" - if config_json.exists(): - files += 1 - assert str(config_json) in configs - - if config_yaml.exists(): - files += 1 - assert str(config_yaml) in configs - - if config_ini.exists(): - files += 1 - assert str(config_ini) in configs - - assert len(configs) == files - - def test_workspace_expand1(config_fixture: "WorkspaceTestData") -> None: """Expand shell commands from string to list.""" test_workspace = loader.expand(config_fixture.expand1.before_workspace) From fdd66d600dedeec12d8c5a4edf25a415a100626a Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 08:01:58 -0600 Subject: [PATCH 11/94] tests(workspace[config]): Note pydocstyle updates --- tests/workspace/test_config.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/workspace/test_config.py b/tests/workspace/test_config.py index ce69b505f5d..db3023dcaff 100644 --- a/tests/workspace/test_config.py +++ b/tests/workspace/test_config.py @@ -15,6 +15,7 @@ def load_workspace(path: t.Union[str, pathlib.Path]) -> t.Dict[str, t.Any]: + """Load tmuxp workspace configuration from file.""" return ConfigReader._from_file( pathlib.Path(path) if isinstance(path, str) else path ) @@ -23,6 +24,7 @@ def load_workspace(path: t.Union[str, pathlib.Path]) -> t.Dict[str, t.Any]: def test_export_json( tmp_path: pathlib.Path, config_fixture: "WorkspaceTestData" ) -> None: + """Test exporting configuration dictionary to JSON.""" json_workspace_file = tmp_path / "config.json" configparser = ConfigReader(config_fixture.sample_workspace.sample_workspace_dict) @@ -94,6 +96,7 @@ def test_workspace_expand2(config_fixture: "WorkspaceTestData") -> None: def test_inheritance_workspace() -> None: + """TODO: Create a test to verify workspace config inheritance to object tree.""" workspace = inheritance_workspace_before # TODO: Look at verifying window_start_directory @@ -133,6 +136,7 @@ def test_shell_command_before(config_fixture: "WorkspaceTestData") -> None: def test_in_session_scope(config_fixture: "WorkspaceTestData") -> None: + """Verify shell_command before_session is in session scope.""" sconfig = ConfigReader._load( format="yaml", content=config_fixture.shell_command_before_session.before ) @@ -146,11 +150,13 @@ def test_in_session_scope(config_fixture: "WorkspaceTestData") -> None: def test_trickle_relative_start_directory(config_fixture: "WorkspaceTestData") -> None: + """Verify tmuxp config proliferates relative start directory to descendants.""" test_workspace = loader.trickle(config_fixture.trickle.before) assert test_workspace == config_fixture.trickle.expected def test_trickle_window_with_no_pane_workspace() -> None: + """Verify tmuxp window config automatically infers a single pane.""" test_yaml = """ session_name: test_session windows: @@ -201,6 +207,7 @@ def test_expands_blank_panes(config_fixture: "WorkspaceTestData") -> None: def test_no_session_name() -> None: + """Verify exception raised when tmuxp configuration has no session name.""" yaml_workspace = """ - window_name: editor panes: @@ -222,6 +229,7 @@ def test_no_session_name() -> None: def test_no_windows() -> None: + """Verify exception raised when tmuxp configuration has no windows.""" yaml_workspace = """ session_name: test session """ @@ -234,6 +242,7 @@ def test_no_windows() -> None: def test_no_window_name() -> None: + """Verify exception raised when tmuxp config missing window name.""" yaml_workspace = """ session_name: test session windows: @@ -256,6 +265,7 @@ def test_no_window_name() -> None: def test_replaces_env_variables(monkeypatch: pytest.MonkeyPatch) -> None: + """Test loading configuration resolves environmental variables.""" env_key = "TESTHEY92" env_val = "HEYO1" yaml_workspace = """ @@ -296,7 +306,8 @@ def test_replaces_env_variables(monkeypatch: pytest.MonkeyPatch) -> None: assert "logging @ %s" % env_val == sconfig["windows"][1]["window_name"] -def test_plugins() -> None: +def test_validate_plugins() -> None: + """Test validation of plugins loading via tmuxp configuration file.""" yaml_workspace = """ session_name: test session plugins: tmuxp-plugin-one.plugin.TestPluginOne From a1898e3d5f280c72d18dc8d77995e4aa1d373480 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 09:36:06 -0600 Subject: [PATCH 12/94] test_builder: rename before_script -> before_load --- tests/workspace/test_builder.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/workspace/test_builder.py b/tests/workspace/test_builder.py index 87d519cf218..93bb9afddc4 100644 --- a/tests/workspace/test_builder.py +++ b/tests/workspace/test_builder.py @@ -706,7 +706,7 @@ def test_window_index(session: Session) -> None: assert int(window.window_index) == expected_index -def test_before_load_throw_error_if_retcode_error(server: Server) -> None: +def test_before_script_throw_error_if_retcode_error(server: Server) -> None: config_script_fails = test_utils.read_workspace_file( "workspace/builder/config_script_fails.yaml" ) @@ -731,7 +731,7 @@ def test_before_load_throw_error_if_retcode_error(server: Server) -> None: assert not result, "Kills session if before_script exits with errcode" -def test_before_load_throw_error_if_file_not_exists(server: Server) -> None: +def test_before_script_throw_error_if_file_not_exists(server: Server) -> None: config_script_not_exists = test_utils.read_workspace_file( "workspace/builder/config_script_not_exists.yaml" ) @@ -757,7 +757,7 @@ def test_before_load_throw_error_if_file_not_exists(server: Server) -> None: assert not result, "Kills session if before_script doesn't exist" -def test_before_load_true_if_test_passes(server: Server) -> None: +def test_before_script_true_if_test_passes(server: Server) -> None: config_script_completes = test_utils.read_workspace_file( "workspace/builder/config_script_completes.yaml" ) @@ -775,7 +775,7 @@ def test_before_load_true_if_test_passes(server: Server) -> None: builder.build(session=session) -def test_before_load_true_if_test_passes_with_args(server: Server) -> None: +def test_before_script_true_if_test_passes_with_args(server: Server) -> None: config_script_completes = test_utils.read_workspace_file( "workspace/builder/config_script_completes.yaml" ) From a6fa5fe435f54a70034405179d382cad36f8e78e Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 10:51:00 -0600 Subject: [PATCH 13/94] tests(workspace[builder]): Note pydocstyle updates --- tests/workspace/test_builder.py | 133 +++++++++++++++++++++++++------- 1 file changed, 107 insertions(+), 26 deletions(-) diff --git a/tests/workspace/test_builder.py b/tests/workspace/test_builder.py index 93bb9afddc4..24a00b0603a 100644 --- a/tests/workspace/test_builder.py +++ b/tests/workspace/test_builder.py @@ -1,4 +1,4 @@ -"""Test for tmuxp workspacebuilder.""" +"""Test for tmuxp workspace builder.""" import functools import os import pathlib @@ -29,11 +29,15 @@ if t.TYPE_CHECKING: class AssertCallbackProtocol(t.Protocol): + """Assertion callback type protocol.""" + def __call__(self, cmd: str, hist: str) -> bool: + """Run function code for testing assertion.""" ... def test_split_windows(session: Session) -> None: + """Test workspace builder splits windows in a tmux session.""" workspace = ConfigReader._from_file( test_utils.get_workspace_file("workspace/builder/two_pane.yaml") ) @@ -54,6 +58,7 @@ def test_split_windows(session: Session) -> None: def test_split_windows_three_pane(session: Session) -> None: + """Test workspace builder splits windows in a tmux session.""" workspace = ConfigReader._from_file( test_utils.get_workspace_file("workspace/builder/three_pane.yaml") ) @@ -76,6 +81,7 @@ def test_split_windows_three_pane(session: Session) -> None: def test_focus_pane_index(session: Session) -> None: + """Test focus of pane by index works correctly, including with pane-base-index.""" workspace = ConfigReader._from_file( test_utils.get_workspace_file("workspace/builder/focus_and_pane.yaml") ) @@ -154,6 +160,7 @@ def f_check_again() -> bool: """.strip() ) def test_suppress_history(session: Session) -> None: + """Test suppression of command history.""" workspace = ConfigReader._from_file( test_utils.get_workspace_file("workspace/builder/suppress_history.yaml") ) @@ -213,6 +220,7 @@ def f(p: Pane, buffer_name: str, assertCase: AssertCallbackProtocol) -> bool: def test_session_options(session: Session) -> None: + """Test setting of options to session scope.""" workspace = ConfigReader._from_file( test_utils.get_workspace_file("workspace/builder/session_options.yaml") ) @@ -231,6 +239,7 @@ def test_session_options(session: Session) -> None: def test_global_options(session: Session) -> None: + """Test setting of global options.""" workspace = ConfigReader._from_file( test_utils.get_workspace_file("workspace/builder/global_options.yaml") ) @@ -246,8 +255,10 @@ def test_global_options(session: Session) -> None: def test_global_session_env_options( - session: Session, monkeypatch: pytest.MonkeyPatch + session: Session, + monkeypatch: pytest.MonkeyPatch, ) -> None: + """Test setting of global option variables.""" visual_silence = "on" monkeypatch.setenv("VISUAL_SILENCE", str(visual_silence)) repeat_time = 738 @@ -272,7 +283,10 @@ def test_global_session_env_options( ) -def test_window_options(session: Session) -> None: +def test_window_options( + session: Session, +) -> None: + """Test setting of window options.""" workspace = ConfigReader._from_file( test_utils.get_workspace_file("workspace/builder/window_options.yaml") ) @@ -301,7 +315,10 @@ def test_window_options(session: Session) -> None: @pytest.mark.flaky(reruns=5) -def test_window_options_after(session: Session) -> None: +def test_window_options_after( + session: Session, +) -> None: + """Test setting window options via options_after (WorkspaceBuilder.after_window).""" workspace = ConfigReader._from_file( test_utils.get_workspace_file("workspace/builder/window_options_after.yaml") ) @@ -339,7 +356,10 @@ def f() -> bool: ), "Synchronized command did not execute properly" -def test_window_shell(session: Session) -> None: +def test_window_shell( + session: Session, +) -> None: + """Test execution of commands via tmuxp configuration.""" workspace = ConfigReader._from_file( test_utils.get_workspace_file("workspace/builder/window_shell.yaml") ) @@ -365,7 +385,10 @@ def f(w: Window) -> bool: has_lt_version("3.0"), reason="needs -e flag for new-window and split-window introduced in tmux 3.0", ) -def test_environment_variables(session: Session) -> None: +def test_environment_variables( + session: Session, +) -> None: + """Test setting of environmental variables in tmux via workspace builder.""" workspace = ConfigReader._from_file( test_utils.get_workspace_file("workspace/builder/environment_vars.yaml") ) @@ -407,9 +430,11 @@ def test_environment_variables(session: Session) -> None: has_gte_version("3.0"), reason="warnings are not needed for tmux >= 3.0", ) -def test_environment_variables_logs( - session: Session, caplog: pytest.LogCaptureFixture +def test_environment_variables_warns_prior_to_tmux_3_0( + session: Session, + caplog: pytest.LogCaptureFixture, ) -> None: + """Warns when environmental variables cannot be set prior to tmux 3.0.""" workspace = ConfigReader._from_file( test_utils.get_workspace_file("workspace/builder/environment_vars.yaml") ) @@ -454,8 +479,10 @@ def test_environment_variables_logs( def test_automatic_rename_option( - server: "Server", monkeypatch: pytest.MonkeyPatch + server: "Server", + monkeypatch: pytest.MonkeyPatch, ) -> None: + """Test workspace builder with automatic renaming enabled.""" monkeypatch.setenv("DISABLE_AUTO_TITLE", "true") workspace = ConfigReader._from_file( test_utils.get_workspace_file("workspace/builder/window_automatic_rename.yaml") @@ -497,8 +524,13 @@ def check_window_name_match() -> bool: assert retry_until(check_window_name_mismatch, 2, interval=0.25) -def test_blank_pane_count(session: Session) -> None: - """:todo: Verify blank panes of various types build into workspaces.""" +def test_blank_pane_spawn( + session: Session, +) -> None: + """Test various ways of spawning blank panes from a tmuxp configuration. + + :todo: Verify blank panes of various types build into workspaces. + """ yaml_workspace_file = EXAMPLE_PATH / "blank-panes.yaml" test_config = ConfigReader._from_file(yaml_workspace_file) @@ -526,6 +558,7 @@ def test_blank_pane_count(session: Session) -> None: def test_start_directory(session: Session, tmp_path: pathlib.Path) -> None: + """Test workspace builder setting start_directory relative to current directory.""" test_dir = tmp_path / "foo bar" test_dir.mkdir() @@ -560,7 +593,9 @@ def f(path: str, p: Pane) -> bool: def test_start_directory_relative(session: Session, tmp_path: pathlib.Path) -> None: - """Same as above test, but with relative start directory, mimicking + """Test workspace builder setting start_directory relative to project file. + + Same as above test, but with relative start directory, mimicking loading it from a location of project file. Like:: $ tmuxp load ~/workspace/myproject/.tmuxp.yaml @@ -616,6 +651,7 @@ def f(path: str, p: Pane) -> bool: has_lt_version("3.2a"), reason="needs format introduced in tmux >= 3.2a" ) def test_start_directory_sets_session_path(server: Server) -> None: + """Test start_directory setting path in session_path.""" workspace = ConfigReader._from_file( test_utils.get_workspace_file( "workspace/builder/start_directory_session_path.yaml" @@ -688,7 +724,10 @@ def f(pane_path: str, p: Pane) -> bool: assert retry_until(_f) -def test_window_index(session: Session) -> None: +def test_window_index( + session: Session, +) -> None: + """Test window_index respected by workspace builder.""" proc = session.cmd("show-option", "-gv", "base-index") base_index = int(proc.stdout[0]) name_index_map = {"zero": 0 + base_index, "one": 1 + base_index, "five": 5} @@ -706,7 +745,10 @@ def test_window_index(session: Session) -> None: assert int(window.window_index) == expected_index -def test_before_script_throw_error_if_retcode_error(server: Server) -> None: +def test_before_script_throw_error_if_retcode_error( + server: Server, +) -> None: + """Test tmuxp configuration before_script when command fails.""" config_script_fails = test_utils.read_workspace_file( "workspace/builder/config_script_fails.yaml" ) @@ -731,7 +773,10 @@ def test_before_script_throw_error_if_retcode_error(server: Server) -> None: assert not result, "Kills session if before_script exits with errcode" -def test_before_script_throw_error_if_file_not_exists(server: Server) -> None: +def test_before_script_throw_error_if_file_not_exists( + server: Server, +) -> None: + """Test tmuxp configuration before_script when script does not exist.""" config_script_not_exists = test_utils.read_workspace_file( "workspace/builder/config_script_not_exists.yaml" ) @@ -757,7 +802,10 @@ def test_before_script_throw_error_if_file_not_exists(server: Server) -> None: assert not result, "Kills session if before_script doesn't exist" -def test_before_script_true_if_test_passes(server: Server) -> None: +def test_before_script_true_if_test_passes( + server: Server, +) -> None: + """Test tmuxp configuration before_script when command succeeds.""" config_script_completes = test_utils.read_workspace_file( "workspace/builder/config_script_completes.yaml" ) @@ -775,7 +823,10 @@ def test_before_script_true_if_test_passes(server: Server) -> None: builder.build(session=session) -def test_before_script_true_if_test_passes_with_args(server: Server) -> None: +def test_before_script_true_if_test_passes_with_args( + server: Server, +) -> None: + """Test tmuxp configuration before_script when command passes w/ args.""" config_script_completes = test_utils.read_workspace_file( "workspace/builder/config_script_completes.yaml" ) @@ -795,8 +846,10 @@ def test_before_script_true_if_test_passes_with_args(server: Server) -> None: def test_plugin_system_before_workspace_builder( - monkeypatch_plugin_test_packages: None, session: Session + monkeypatch_plugin_test_packages: None, + session: Session, ) -> None: + """Test tmuxp configuration plugin hook before workspace builder starts.""" workspace = ConfigReader._from_file( path=test_utils.get_workspace_file("workspace/builder/plugin_bwb.yaml") ) @@ -814,8 +867,10 @@ def test_plugin_system_before_workspace_builder( def test_plugin_system_on_window_create( - monkeypatch_plugin_test_packages: None, session: Session + monkeypatch_plugin_test_packages: None, + session: Session, ) -> None: + """Test tmuxp configuration plugin hooks work on window creation.""" workspace = ConfigReader._from_file( path=test_utils.get_workspace_file("workspace/builder/plugin_owc.yaml") ) @@ -833,8 +888,10 @@ def test_plugin_system_on_window_create( def test_plugin_system_after_window_finished( - monkeypatch_plugin_test_packages: None, session: Session + monkeypatch_plugin_test_packages: None, + session: Session, ) -> None: + """Test tmuxp configuration plugin hooks work after windows created.""" workspace = ConfigReader._from_file( path=test_utils.get_workspace_file("workspace/builder/plugin_awf.yaml") ) @@ -851,7 +908,10 @@ def test_plugin_system_after_window_finished( assert proc.stdout[0] == "'plugin_test_awf'" -def test_plugin_system_on_window_create_multiple_windows(session: Session) -> None: +def test_plugin_system_on_window_create_multiple_windows( + session: Session, +) -> None: + """Test tmuxp configuration plugin hooks work on windows creation.""" workspace = ConfigReader._from_file( path=test_utils.get_workspace_file( "workspace/builder/plugin_owc_multiple_windows.yaml" @@ -872,8 +932,10 @@ def test_plugin_system_on_window_create_multiple_windows(session: Session) -> No def test_plugin_system_after_window_finished_multiple_windows( - monkeypatch_plugin_test_packages: None, session: Session + monkeypatch_plugin_test_packages: None, + session: Session, ) -> None: + """Test tmuxp configuration plugin hooks work after windows created.""" workspace = ConfigReader._from_file( path=test_utils.get_workspace_file( "workspace/builder/plugin_awf_multiple_windows.yaml" @@ -894,8 +956,10 @@ def test_plugin_system_after_window_finished_multiple_windows( def test_plugin_system_multiple_plugins( - monkeypatch_plugin_test_packages: None, session: Session + monkeypatch_plugin_test_packages: None, + session: Session, ) -> None: + """Test tmuxp plugin system works with multiple plugins.""" workspace = ConfigReader._from_file( path=test_utils.get_workspace_file( "workspace/builder/plugin_multiple_plugins.yaml" @@ -921,7 +985,10 @@ def test_plugin_system_multiple_plugins( assert proc.stdout[0] == "'mp_test_awf'" -def test_load_configs_same_session(server: Server) -> None: +def test_load_configs_same_session( + server: Server, +) -> None: + """Test tmuxp configuration can be loaded into same session.""" workspace = ConfigReader._from_file( path=test_utils.get_workspace_file("workspace/builder/three_windows.yaml") ) @@ -952,7 +1019,10 @@ def test_load_configs_same_session(server: Server) -> None: assert len(server.sessions[1].windows) == 4 -def test_load_configs_separate_sessions(server: Server) -> None: +def test_load_configs_separate_sessions( + server: Server, +) -> None: + """Test workspace builder can load configuration in separate session.""" workspace = ConfigReader._from_file( path=test_utils.get_workspace_file("workspace/builder/three_windows.yaml") ) @@ -976,8 +1046,10 @@ def test_load_configs_separate_sessions(server: Server) -> None: def test_find_current_active_pane( - server: Server, monkeypatch: pytest.MonkeyPatch + server: Server, + monkeypatch: pytest.MonkeyPatch, ) -> None: + """Tests workspace builder can find the current active pane (and session).""" workspace = ConfigReader._from_file( path=test_utils.get_workspace_file("workspace/builder/three_windows.yaml") ) @@ -1135,6 +1207,7 @@ def test_load_workspace_enter( output: str, should_see: bool, ) -> None: + """Test workspace enters commands to panes in tmuxp configuration.""" yaml_workspace = tmp_path / "simple.yaml" yaml_workspace.write_text(yaml, encoding="utf-8") workspace = ConfigReader._from_file(yaml_workspace) @@ -1257,6 +1330,7 @@ def test_load_workspace_sleep( sleep: int, output: str, ) -> None: + """Test sleep commands in tmuxp configuration.""" yaml_workspace = tmp_path / "simple.yaml" yaml_workspace.write_text(yaml, encoding="utf-8") workspace = ConfigReader._from_file(yaml_workspace) @@ -1290,6 +1364,7 @@ def test_load_workspace_sleep( def test_first_pane_start_directory(session: Session, tmp_path: pathlib.Path) -> None: + """Test the first pane start_directory sticks.""" yaml_workspace = test_utils.get_workspace_file( "workspace/builder/first_pane_start_directory.yaml" ) @@ -1322,6 +1397,7 @@ def f(path: str, p: Pane) -> bool: has_lt_version("2.9"), reason="needs option introduced in tmux >= 2.9" ) def test_layout_main_horizontal(session: Session) -> None: + """Test that tmux's main-horizontal layout is used when specified.""" yaml_workspace = test_utils.get_workspace_file("workspace/builder/three_pane.yaml") workspace = ConfigReader._from_file(path=yaml_workspace) @@ -1359,7 +1435,12 @@ def is_almost_equal(x: int, y: int) -> bool: class DefaultSizeNamespaceFixture(t.NamedTuple): + """Pytest fixture default-size option in tmuxp workspace builder.""" + + # pytest parametrize needs a unique id for each fixture test_id: str + + # test params TMUXP_DEFAULT_SIZE: t.Optional[str] raises: bool confoverrides: t.Dict[str, t.Any] From 9fc854abd5638b00e596faeb11127b912e652c30 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 12:09:15 -0600 Subject: [PATCH 14/94] tests(workspace[conftest]): Note pydocstyle updates --- tests/workspace/conftest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/workspace/conftest.py b/tests/workspace/conftest.py index 9a47cfe69c2..286acc8c6cd 100644 --- a/tests/workspace/conftest.py +++ b/tests/workspace/conftest.py @@ -1,3 +1,4 @@ +"""Pytest configuration for tmuxp workspace tests.""" import types import pytest From adb5212714a7177cb0288752307d5a72dbef43de Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 12:09:32 -0600 Subject: [PATCH 15/94] tests(workspace[__init__]): Note pydocstyle updates --- tests/workspace/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/workspace/__init__.py b/tests/workspace/__init__.py index e69de29bb2d..ec8ccc92b49 100644 --- a/tests/workspace/__init__.py +++ b/tests/workspace/__init__.py @@ -0,0 +1 @@ +"""Workspace tests for tmuxp.""" From 4a9078d7edc3f8ccaa250e6c610d56de43aa496d Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 12:11:06 -0600 Subject: [PATCH 16/94] tests(tests[helpers]): Note pydocstyle updates --- tests/tests/test_helpers.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/tests/test_helpers.py b/tests/tests/test_helpers.py index c744d436ccc..22b04d87b1b 100644 --- a/tests/tests/test_helpers.py +++ b/tests/tests/test_helpers.py @@ -1,10 +1,11 @@ -"""Tests for .'s helper and utility functions.""" +"""Tests for tmuxp's helper and utility functions.""" import pytest from libtmux.server import Server from libtmux.test import get_test_session_name, temp_session -def test_kills_session(server: Server) -> None: +def test_temp_session_kills_session_on_exit(server: Server) -> None: + """Test temp_session() context manager kills session on exit.""" server = server session_name = get_test_session_name(server=server) @@ -16,7 +17,7 @@ def test_kills_session(server: Server) -> None: @pytest.mark.flaky(reruns=5) -def test_if_session_killed_before(server: Server) -> None: +def test_temp_session_if_session_killed_before_exit(server: Server) -> None: """Handles situation where session already closed within context.""" server = server session_name = get_test_session_name(server=server) From 602573870f81d24694893f69d0f7ebc22351a051 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 12:11:29 -0600 Subject: [PATCH 17/94] tests(tests): Note pydocstyle updates --- tests/tests/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/tests/__init__.py b/tests/tests/__init__.py index e69de29bb2d..f887a3d06e1 100644 --- a/tests/tests/__init__.py +++ b/tests/tests/__init__.py @@ -0,0 +1 @@ +"""Tests for tmuxp's pytest helpers.""" From 1bf16bafd948e890d4a64248aa9e48b6695b5739 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 12:13:45 -0600 Subject: [PATCH 18/94] tests(util): Note pydocstyle updates --- tests/test_util.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/test_util.py b/tests/test_util.py index dbb4f8b5e2c..d8a24527ad9 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -1,4 +1,4 @@ -"""Tests for utility functions in tmux.""" +"""Tests for tmuxp's utility functions.""" import pytest from libtmux.server import Server @@ -9,7 +9,8 @@ from .constants import FIXTURE_PATH -def test_raise_BeforeLoadScriptNotExists_if_not_exists() -> None: +def test_run_before_script_raise_BeforeLoadScriptNotExists_if_not_exists() -> None: + """run_before_script() raises BeforeLoadScriptNotExists if script not found.""" script_file = FIXTURE_PATH / "script_noexists.sh" with pytest.raises(BeforeLoadScriptNotExists): @@ -19,7 +20,8 @@ def test_raise_BeforeLoadScriptNotExists_if_not_exists() -> None: run_before_script(script_file) -def test_raise_BeforeLoadScriptError_if_retcode() -> None: +def test_run_before_script_raise_BeforeLoadScriptError_if_retcode() -> None: + """run_before_script() raises BeforeLoadScriptNotExists if script fails.""" script_file = FIXTURE_PATH / "script_failed.sh" with pytest.raises(BeforeLoadScriptError): @@ -27,6 +29,7 @@ def test_raise_BeforeLoadScriptError_if_retcode() -> None: def test_return_stdout_if_ok(capsys: pytest.CaptureFixture[str]) -> None: + """run_before_script() returns stdout if script succeeds.""" script_file = FIXTURE_PATH / "script_complete.sh" run_before_script(script_file) @@ -35,6 +38,7 @@ def test_return_stdout_if_ok(capsys: pytest.CaptureFixture[str]) -> None: def test_beforeload_returncode() -> None: + """run_before_script() returns returncode if script fails.""" script_file = FIXTURE_PATH / "script_failed.sh" with pytest.raises(exc.BeforeLoadScriptError) as excinfo: @@ -43,6 +47,7 @@ def test_beforeload_returncode() -> None: def test_beforeload_returns_stderr_messages() -> None: + """run_before_script() returns stderr messages if script fails.""" script_file = FIXTURE_PATH / "script_failed.sh" with pytest.raises(exc.BeforeLoadScriptError) as excinfo: @@ -51,8 +56,10 @@ def test_beforeload_returns_stderr_messages() -> None: def test_get_session_should_default_to_local_attached_session( - server: Server, monkeypatch: pytest.MonkeyPatch + server: Server, + monkeypatch: pytest.MonkeyPatch, ) -> None: + """get_session() should launch current terminal's tmux session, if inside one.""" server.new_session(session_name="myfirstsession") second_session = server.new_session(session_name="mysecondsession") @@ -67,6 +74,7 @@ def test_get_session_should_default_to_local_attached_session( def test_get_session_should_return_first_session_if_no_active_session( server: Server, ) -> None: + """get_session() should return first session if no active session.""" first_session = server.new_session(session_name="myfirstsession") server.new_session(session_name="mysecondsession") From 06f964b4b002256b2fa8cd4f5e451dbe27cace78 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 12:15:28 -0600 Subject: [PATCH 19/94] tests(shell): Note pydocstyle updates --- tests/test_shell.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_shell.py b/tests/test_shell.py index 2f87bddba9b..4fe574d4287 100644 --- a/tests/test_shell.py +++ b/tests/test_shell.py @@ -1,12 +1,15 @@ +"""Tests for tmuxp shell module.""" from tmuxp import shell def test_detect_best_shell() -> None: + """detect_best_shell() returns a a string of the best shell.""" result = shell.detect_best_shell() assert isinstance(result, str) def test_shell_detect() -> None: + """Tests shell detection functions.""" assert isinstance(shell.has_bpython(), bool) assert isinstance(shell.has_ipython(), bool) assert isinstance(shell.has_ptpython(), bool) From 64915fad1d8483349890784153e608092ba24cc0 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 13:27:05 -0600 Subject: [PATCH 20/94] tests(plugin): Note pydocstyle updates --- tests/test_plugin.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/test_plugin.py b/tests/test_plugin.py index 2151d7ce950..023ee332189 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -1,4 +1,4 @@ -"""Test for tmuxp plugin api.""" +"""Tests for tmuxp plugin API.""" import pytest from tmuxp.exc import TmuxpPluginException @@ -23,62 +23,73 @@ @pytest.fixture(autouse=True) def autopatch_sitedir(monkeypatch_plugin_test_packages: None) -> None: + """Fixture automatically used that patches sitedir.""" pass def test_all_pass() -> None: + """Plugin for tmuxp that loads successfully.""" AllVersionPassPlugin() def test_tmux_version_fail_min() -> None: + """Plugin raises if tmux version is below minimum constraint.""" with pytest.raises(TmuxpPluginException, match=r"Incompatible.*") as exc_info: TmuxVersionFailMinPlugin() assert "tmux-min-version-fail" in str(exc_info.value) def test_tmux_version_fail_max() -> None: + """Plugin raises if tmux version is above maximum constraint.""" with pytest.raises(TmuxpPluginException, match=r"Incompatible.*") as exc_info: TmuxVersionFailMaxPlugin() assert "tmux-max-version-fail" in str(exc_info.value) def test_tmux_version_fail_incompatible() -> None: + """Plugin raises if tmuxp version is incompatible.""" with pytest.raises(TmuxpPluginException, match=r"Incompatible.*") as exc_info: TmuxVersionFailIncompatiblePlugin() assert "tmux-incompatible-version-fail" in str(exc_info.value) def test_tmuxp_version_fail_min() -> None: + """Plugin raises if tmuxp version is below minimum constraint.""" with pytest.raises(TmuxpPluginException, match=r"Incompatible.*") as exc_info: TmuxpVersionFailMinPlugin() assert "tmuxp-min-version-fail" in str(exc_info.value) def test_tmuxp_version_fail_max() -> None: + """Plugin raises if tmuxp version is above max constraint.""" with pytest.raises(TmuxpPluginException, match=r"Incompatible.*") as exc_info: TmuxpVersionFailMaxPlugin() assert "tmuxp-max-version-fail" in str(exc_info.value) def test_tmuxp_version_fail_incompatible() -> None: + """Plugin raises if libtmux version is below minimum constraint.""" with pytest.raises(TmuxpPluginException, match=r"Incompatible.*") as exc_info: TmuxpVersionFailIncompatiblePlugin() assert "tmuxp-incompatible-version-fail" in str(exc_info.value) def test_libtmux_version_fail_min() -> None: + """Plugin raises if libtmux version is below minimum constraint.""" with pytest.raises(TmuxpPluginException, match=r"Incompatible.*") as exc_info: LibtmuxVersionFailMinPlugin() assert "libtmux-min-version-fail" in str(exc_info.value) def test_libtmux_version_fail_max() -> None: + """Plugin raises if libtmux version is above max constraint.""" with pytest.raises(TmuxpPluginException, match=r"Incompatible.*") as exc_info: LibtmuxVersionFailMaxPlugin() assert "libtmux-max-version-fail" in str(exc_info.value) def test_libtmux_version_fail_incompatible() -> None: + """Plugin raises if libtmux version is incompatible.""" with pytest.raises(TmuxpPluginException, match=r"Incompatible.*") as exc_info: LibtmuxVersionFailIncompatiblePlugin() assert "libtmux-incompatible-version-fail" in str(exc_info.value) From e8873a55be859aa910935c4047604c970f12a657 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 13:28:43 -0600 Subject: [PATCH 21/94] tests(fixtures[trickle]): Note pydocstyle updates --- tests/fixtures/workspace/trickle.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fixtures/workspace/trickle.py b/tests/fixtures/workspace/trickle.py index 662ebaf45b0..68fa31a9df6 100644 --- a/tests/fixtures/workspace/trickle.py +++ b/tests/fixtures/workspace/trickle.py @@ -1,3 +1,4 @@ +"""Test data for tmuxp workspace fixture to demo object tree inheritance.""" before = { # shell_command_before is string in some areas "session_name": "sample workspace", "start_directory": "/var", From 2e541928d4c44e67bffb13f014e7202c3d7467e6 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 13:29:11 -0600 Subject: [PATCH 22/94] tests(fixtures[shell_command_before]): Note pydocstyle updates --- tests/fixtures/workspace/shell_command_before.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/fixtures/workspace/shell_command_before.py b/tests/fixtures/workspace/shell_command_before.py index 69f5c2f2b4e..cbb44250473 100644 --- a/tests/fixtures/workspace/shell_command_before.py +++ b/tests/fixtures/workspace/shell_command_before.py @@ -1,3 +1,4 @@ +"""Test fixture for tmuxp to demonstrate shell_command_before.""" import pathlib import typing as t @@ -39,6 +40,7 @@ def config_expanded() -> t.Dict[str, t.Any]: + """Return expanded configuration for shell_command_before example.""" return { # shell_command_before is string in some areas "session_name": "sample workspace", "start_directory": "/", @@ -91,6 +93,7 @@ def config_expanded() -> t.Dict[str, t.Any]: def config_after() -> t.Dict[str, t.Any]: + """Return expected configuration for shell_command_before example.""" return { # shell_command_before is string in some areas "session_name": "sample workspace", "start_directory": "/", From 33690c5f70065fa51cf62c00032d0ac8cb14074f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 13:36:37 -0600 Subject: [PATCH 23/94] tests(fixtures[shell_command_before_session]): Note pydocstyle updates --- tests/fixtures/workspace/shell_command_before_session.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fixtures/workspace/shell_command_before_session.py b/tests/fixtures/workspace/shell_command_before_session.py index 79329382d4a..b103d666e54 100644 --- a/tests/fixtures/workspace/shell_command_before_session.py +++ b/tests/fixtures/workspace/shell_command_before_session.py @@ -1,3 +1,4 @@ +"""Tests shell_command_before configuration.""" from .. import utils as test_utils before = test_utils.read_workspace_file("workspace/shell_command_before_session.yaml") From 6f80928eff686c1d446cbc51a9df1189937e9ad7 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 13:37:13 -0600 Subject: [PATCH 24/94] tests(fixtures[sample_workspace]): Note pydocstyle updates --- tests/fixtures/workspace/sample_workspace.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fixtures/workspace/sample_workspace.py b/tests/fixtures/workspace/sample_workspace.py index baff8d4c924..62ceae252a2 100644 --- a/tests/fixtures/workspace/sample_workspace.py +++ b/tests/fixtures/workspace/sample_workspace.py @@ -1,3 +1,4 @@ +"""Example workspace fixture for tmuxp WorkspaceBuilder.""" sample_workspace_dict = { "session_name": "sample workspace", "start_directory": "~", From 78f9f2bfa87934f7793b7527a3b4f30d35b8a85c Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 14:20:05 -0600 Subject: [PATCH 25/94] tests(fixtures[expand_blank]): Note pydocstyle updates --- tests/fixtures/workspace/expand_blank.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fixtures/workspace/expand_blank.py b/tests/fixtures/workspace/expand_blank.py index 4d0dad3b490..d1fbd2e5504 100644 --- a/tests/fixtures/workspace/expand_blank.py +++ b/tests/fixtures/workspace/expand_blank.py @@ -1,3 +1,4 @@ +"""Expected expanded configuration for empty workspace panes.""" expected = { "session_name": "Blank pane test", "windows": [ From e54f1df890aa143007fccea6b0db31e18f985fac Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 14:20:50 -0600 Subject: [PATCH 26/94] tests(fixtures[expand1]): Note pydocstyle updates --- tests/fixtures/workspace/expand1.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/fixtures/workspace/expand1.py b/tests/fixtures/workspace/expand1.py index 540229b77a6..187111d86e0 100644 --- a/tests/fixtures/workspace/expand1.py +++ b/tests/fixtures/workspace/expand1.py @@ -1,3 +1,4 @@ +"""Examples of expansion of tmuxp configurations from shorthand style.""" import pathlib import typing as t @@ -32,6 +33,7 @@ def after_workspace() -> t.Dict[str, t.Any]: + """After expansion of shorthand style.""" return { "session_name": "sample workspace", "start_directory": str(pathlib.Path().home()), From 2d9f30d58c4323ed69bfc1302f8c09d503dcddd1 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 14:23:28 -0600 Subject: [PATCH 27/94] tests(fixtures[expand1]): Note pydocstyle updates --- tests/fixtures/workspace/expand2.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/fixtures/workspace/expand2.py b/tests/fixtures/workspace/expand2.py index aac7d52378a..335f13708b2 100644 --- a/tests/fixtures/workspace/expand2.py +++ b/tests/fixtures/workspace/expand2.py @@ -1,13 +1,16 @@ +"""YAML examples of expansion of tmuxp configurations from shorthand style.""" import pathlib from .. import utils as test_utils def unexpanded_yaml() -> str: + """Return unexpanded, shorthand YAML tmuxp configuration.""" return test_utils.read_workspace_file("workspace/expand2-unexpanded.yaml") def expanded_yaml() -> str: + """Return expanded, verbose YAML tmuxp configuration.""" return test_utils.read_workspace_file("workspace/expand2-expanded.yaml").format( HOME=str(pathlib.Path().home()) ) From c7a799c8f9ee7d0e7f61529a0f24704462e6502c Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 14:26:36 -0600 Subject: [PATCH 28/94] tests(fixtures[workspace]): Note pydocstyle updates --- tests/fixtures/workspace/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fixtures/workspace/__init__.py b/tests/fixtures/workspace/__init__.py index 097409c1569..632b47fbeb9 100644 --- a/tests/fixtures/workspace/__init__.py +++ b/tests/fixtures/workspace/__init__.py @@ -1,3 +1,4 @@ +"""Workspace data fixtures for tmuxp tests.""" from . import ( expand1, expand2, From a2c121aadb41fa5eb16b249423ab64a957688062 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 14:27:04 -0600 Subject: [PATCH 29/94] tests(fixtures[utils]): Note pydocstyle updates --- tests/fixtures/utils.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/fixtures/utils.py b/tests/fixtures/utils.py index b9150ca5ac1..955ebc6c569 100644 --- a/tests/fixtures/utils.py +++ b/tests/fixtures/utils.py @@ -1,3 +1,4 @@ +"""Utility functions for tmuxp fixtures.""" import pathlib import typing as t @@ -14,7 +15,9 @@ def get_workspace_file( return FIXTURE_PATH / _file -def read_workspace_file(_file: t.Union[pathlib.Path, str]) -> str: +def read_workspace_file( + _file: t.Union[pathlib.Path, str], +) -> str: """Return fixture data, relative to __file__.""" if isinstance(_file, str): _file = pathlib.Path(_file) @@ -23,8 +26,11 @@ def read_workspace_file(_file: t.Union[pathlib.Path, str]) -> str: def write_config( - config_path: pathlib.Path, filename: str, content: str + config_path: pathlib.Path, + filename: str, + content: str, ) -> pathlib.Path: + """Write configuration content to file.""" config = config_path / filename config.write_text(content, encoding="utf-8") return config From ea3168bd539555ebda55ee21cf179c4b6ad0031b Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 14:29:21 -0600 Subject: [PATCH 30/94] tests(fixtures[structures]): Note pydocstyle updates --- tests/fixtures/structures.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/fixtures/structures.py b/tests/fixtures/structures.py index 85f35d10f40..cd236ad2184 100644 --- a/tests/fixtures/structures.py +++ b/tests/fixtures/structures.py @@ -1,9 +1,12 @@ +"""Typings / structures for tmuxp fixtures.""" import dataclasses import typing as t @dataclasses.dataclass class WorkspaceTestData: + """Workspace data fixtures for tmuxp tests.""" + expand1: t.Any expand2: t.Any expand_blank: t.Any From 05f94a9c138790ff48d8e7411412c7c8fc1773a0 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 14:32:35 -0600 Subject: [PATCH 31/94] tests(plugins[tmuxp_test_plugin_r]): Note pydocstyle updates --- .../plugins/tmuxp_test_plugin_r/tmuxp_test_plugin_r/plugin.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_r/tmuxp_test_plugin_r/plugin.py b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_r/tmuxp_test_plugin_r/plugin.py index 25a43e93f96..b206c5da701 100644 --- a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_r/tmuxp_test_plugin_r/plugin.py +++ b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_r/tmuxp_test_plugin_r/plugin.py @@ -1,3 +1,4 @@ +"""Tmuxp example plugin for reattaching session.""" import typing as t from tmuxp.plugin import TmuxpPlugin @@ -7,8 +8,11 @@ class PluginReattach(TmuxpPlugin): + """Tmuxp plugin to test renaming session on reattach.""" + def __init__(self) -> None: self.message: str = "[+] This is the Tmuxp Test Plugin" def reattach(self, session: "Session") -> None: + """Apply hook that runs for tmux on session reattach.""" session.rename_session("plugin_test_r") From 568d3ca3a1631b26eb2bc225dbd42bfe6e3826da Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 14:32:56 -0600 Subject: [PATCH 32/94] tests(plugins[tmuxp_test_plugin_r]): Note pydocstyle updates --- .../plugins/tmuxp_test_plugin_r/tmuxp_test_plugin_r/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_r/tmuxp_test_plugin_r/__init__.py b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_r/tmuxp_test_plugin_r/__init__.py index e69de29bb2d..6e01504fd64 100644 --- a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_r/tmuxp_test_plugin_r/__init__.py +++ b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_r/tmuxp_test_plugin_r/__init__.py @@ -0,0 +1 @@ +"""Example tmuxp plugin module for reattaching sessions.""" From ec8abe2961309a9417b48b083c370ebb80c08a33 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 15:27:17 -0600 Subject: [PATCH 33/94] tests(plugins[tmuxp_test_plugin_owc]): Note pydocstyle updates --- .../tmuxp_test_plugin_owc/tmuxp_test_plugin_owc/plugin.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_owc/tmuxp_test_plugin_owc/plugin.py b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_owc/tmuxp_test_plugin_owc/plugin.py index 5f900a494f6..add308db6ff 100644 --- a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_owc/tmuxp_test_plugin_owc/plugin.py +++ b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_owc/tmuxp_test_plugin_owc/plugin.py @@ -1,3 +1,4 @@ +"""Tmuxp example plugin for on_window_create.""" import typing as t from tmuxp.plugin import TmuxpPlugin @@ -7,10 +8,13 @@ class PluginOnWindowCreate(TmuxpPlugin): + """Tmuxp plugin to test custom functionality on window creation.""" + def __init__(self) -> None: self.message: str = "[+] This is the Tmuxp Test Plugin" def on_window_create(self, window: "Window") -> None: + """Apply hook that runs for tmux on session reattach.""" if window.name == "editor": window.rename_window("plugin_test_owc") elif window.name == "owc_mw_test": From 8d521220317f6789093aa645254dcce2d618903f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 15:27:43 -0600 Subject: [PATCH 34/94] tests(plugins[tmuxp_test_plugin_owc]): Note pydocstyle updates --- .../tmuxp_test_plugin_owc/tmuxp_test_plugin_owc/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_owc/tmuxp_test_plugin_owc/__init__.py b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_owc/tmuxp_test_plugin_owc/__init__.py index e69de29bb2d..f649064840a 100644 --- a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_owc/tmuxp_test_plugin_owc/__init__.py +++ b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_owc/tmuxp_test_plugin_owc/__init__.py @@ -0,0 +1 @@ +"""Example tmuxp plugin module for hooks on window creation.""" From feb1c2ca7bcd4b647338acf8f3d9f76406cb88b1 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 15:37:16 -0600 Subject: [PATCH 35/94] tests(plugins[tmuxp_test_plugin_fail]): Note pydocstyle updates --- .../tmuxp_test_plugin_fail/tmuxp_test_plugin_fail/plugin.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_fail/tmuxp_test_plugin_fail/plugin.py b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_fail/tmuxp_test_plugin_fail/plugin.py index 5534c5afedf..a8cc86206ed 100644 --- a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_fail/tmuxp_test_plugin_fail/plugin.py +++ b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_fail/tmuxp_test_plugin_fail/plugin.py @@ -1,3 +1,4 @@ +"""Tmuxp example plugin that fails on initialization.""" import typing as t from tmuxp.plugin import TmuxpPlugin @@ -7,6 +8,8 @@ class PluginFailVersion(TmuxpPlugin): + """A tmuxp plugin that is doomed to fail. DOOMED.""" + def __init__(self) -> None: config: "PluginConfigSchema" = { "plugin_name": "tmuxp-plugin-fail-version", From efbdc465aa5fc18ec17cf18c80afd3ce45c4a299 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 15:38:03 -0600 Subject: [PATCH 36/94] tests(plugins[tmuxp_test_plugin_fail]): Note pydocstyle updates --- .../tmuxp_test_plugin_fail/tmuxp_test_plugin_fail/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_fail/tmuxp_test_plugin_fail/__init__.py b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_fail/tmuxp_test_plugin_fail/__init__.py index e69de29bb2d..2afcb8fce89 100644 --- a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_fail/tmuxp_test_plugin_fail/__init__.py +++ b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_fail/tmuxp_test_plugin_fail/__init__.py @@ -0,0 +1 @@ +"""Tmuxp plugin test, that is destined for failure.""" From cfafabd5b17fa8832e5e8e183f2a76886a79c2d3 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 15:38:55 -0600 Subject: [PATCH 37/94] tests(plugins[tmuxp_test_plugin_bwb]): Note pydocstyle updates --- .../tmuxp_test_plugin_bwb/tmuxp_test_plugin_bwb/plugin.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bwb/tmuxp_test_plugin_bwb/plugin.py b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bwb/tmuxp_test_plugin_bwb/plugin.py index d1be0b37723..cd2fb1e4f0e 100644 --- a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bwb/tmuxp_test_plugin_bwb/plugin.py +++ b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bwb/tmuxp_test_plugin_bwb/plugin.py @@ -1,3 +1,4 @@ +"""Tmuxp example plugin for before_worksplace_builder.""" import typing as t from tmuxp.plugin import TmuxpPlugin @@ -7,8 +8,11 @@ class PluginBeforeWorkspaceBuilder(TmuxpPlugin): + """Tmuxp plugin that runs before worksplace builder starts.""" + def __init__(self) -> None: self.message: str = "[+] This is the Tmuxp Test Plugin" def before_workspace_builder(self, session: "Session") -> None: + """Run hook before workspace builder begins.""" session.rename_session("plugin_test_bwb") From b2bb6225e6b830eb6da787671d06066e5c1263ca Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 15:43:47 -0600 Subject: [PATCH 38/94] tests(plugins[tmuxp_test_plugin_bwb]): Note pydocstyle updates --- .../tmuxp_test_plugin_bwb/tmuxp_test_plugin_bwb/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bwb/tmuxp_test_plugin_bwb/__init__.py b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bwb/tmuxp_test_plugin_bwb/__init__.py index e69de29bb2d..98ca0ca0fc7 100644 --- a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bwb/tmuxp_test_plugin_bwb/__init__.py +++ b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bwb/tmuxp_test_plugin_bwb/__init__.py @@ -0,0 +1 @@ +"""Example tmuxp plugin that runs before workspace builder inits.""" From 901bfb242be559944cafbcdd52492b5c7a4e50bb Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 15:45:36 -0600 Subject: [PATCH 39/94] tests(plugins[tmuxp_test_plugin_bs]): Note pydocstyle updates --- .../tmuxp_test_plugin_bs/tmuxp_test_plugin_bs/plugin.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bs/tmuxp_test_plugin_bs/plugin.py b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bs/tmuxp_test_plugin_bs/plugin.py index e2fbf98aca9..bfc7175a733 100644 --- a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bs/tmuxp_test_plugin_bs/plugin.py +++ b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bs/tmuxp_test_plugin_bs/plugin.py @@ -1,3 +1,4 @@ +"""Tmux plugin that runs before_script, if it is declared in configuration.""" import typing as t from tmuxp.plugin import TmuxpPlugin @@ -7,8 +8,11 @@ class PluginBeforeScript(TmuxpPlugin): + """Tmuxp plugin that runs before_script.""" + def __init__(self) -> None: self.message: str = "[+] This is the Tmuxp Test Plugin" def before_script(self, session: "Session") -> None: + """Run hook during before_script, if it is declared.""" session.rename_session("plugin_test_bs") From 3822f48c371d96d12f5770f98f9e97f982a10e54 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 16:50:58 -0600 Subject: [PATCH 40/94] tests(plugins[tmuxp_test_plugin_bs]): Note pydocstyle updates --- .../tmuxp_test_plugin_bs/tmuxp_test_plugin_bs/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bs/tmuxp_test_plugin_bs/__init__.py b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bs/tmuxp_test_plugin_bs/__init__.py index e69de29bb2d..4329e60aae7 100644 --- a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bs/tmuxp_test_plugin_bs/__init__.py +++ b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bs/tmuxp_test_plugin_bs/__init__.py @@ -0,0 +1 @@ +"""Example tmuxp plugin module that hooks in before_script, if declared.""" From 118eaebd421d44b966713d87d600e46e028451d5 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 16:51:56 -0600 Subject: [PATCH 41/94] tests(plugins[tmuxp_test_plugin_awf]): Note pydocstyle updates --- .../tmuxp_test_plugin_awf/tmuxp_test_plugin_awf/plugin.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_awf/tmuxp_test_plugin_awf/plugin.py b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_awf/tmuxp_test_plugin_awf/plugin.py index b4305ca7e7f..e2a77e8c662 100644 --- a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_awf/tmuxp_test_plugin_awf/plugin.py +++ b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_awf/tmuxp_test_plugin_awf/plugin.py @@ -1,3 +1,4 @@ +"""Tmuxp example plugin for after_window_finished.""" import typing as t from tmuxp.plugin import TmuxpPlugin @@ -7,10 +8,13 @@ class PluginAfterWindowFinished(TmuxpPlugin): + """Tmuxp plugin that runs after window creation completes.""" + def __init__(self) -> None: self.message: str = "[+] This is the Tmuxp Test Plugin" def after_window_finished(self, window: "Window") -> None: + """Run hook after window creation completed.""" if window.name == "editor": window.rename_window("plugin_test_awf") elif window.name == "awf_mw_test": From 87e9a66505b808f262e85144ed7a9ec60ace5782 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 16:52:13 -0600 Subject: [PATCH 42/94] tests(plugins[tmuxp_test_plugin_awf]): Note pydocstyle updates --- .../tmuxp_test_plugin_awf/tmuxp_test_plugin_awf/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_awf/tmuxp_test_plugin_awf/__init__.py b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_awf/tmuxp_test_plugin_awf/__init__.py index e69de29bb2d..9cbdb91f118 100644 --- a/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_awf/tmuxp_test_plugin_awf/__init__.py +++ b/tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_awf/tmuxp_test_plugin_awf/__init__.py @@ -0,0 +1 @@ +"""Example tmuxp plugin that runs after window creation completions.""" From ec159c4e4b39c57798c91a3f6aa5664af61aecf6 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 16:54:53 -0600 Subject: [PATCH 43/94] tests(fixtures[tmuxp_version_fail]): Note pydocstyle updates --- tests/fixtures/pluginsystem/partials/tmuxp_version_fail.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/fixtures/pluginsystem/partials/tmuxp_version_fail.py b/tests/fixtures/pluginsystem/partials/tmuxp_version_fail.py index 702d843e7a0..ed99d406b66 100644 --- a/tests/fixtures/pluginsystem/partials/tmuxp_version_fail.py +++ b/tests/fixtures/pluginsystem/partials/tmuxp_version_fail.py @@ -1,3 +1,4 @@ +"""Fixtures for tmuxp plugins for tmuxp version exceptions.""" import typing as t from .test_plugin_helpers import MyTestTmuxpPlugin @@ -7,6 +8,8 @@ class TmuxpVersionFailMinPlugin(MyTestTmuxpPlugin): + """Tmuxp plugin that fails when tmuxp below minimum version constraint.""" + def __init__(self) -> None: config: "PluginTestConfigSchema" = { "plugin_name": "tmuxp-min-version-fail", @@ -17,6 +20,8 @@ def __init__(self) -> None: class TmuxpVersionFailMaxPlugin(MyTestTmuxpPlugin): + """Tmuxp plugin that fails when tmuxp above maximum version constraint.""" + def __init__(self) -> None: config: "PluginTestConfigSchema" = { "plugin_name": "tmuxp-max-version-fail", @@ -27,6 +32,8 @@ def __init__(self) -> None: class TmuxpVersionFailIncompatiblePlugin(MyTestTmuxpPlugin): + """Tmuxp plugin that fails when tmuxp version constraint is invalid.""" + def __init__(self) -> None: config: "PluginTestConfigSchema" = { "plugin_name": "tmuxp-incompatible-version-fail", From 216500992a6b7f6513d2db9b1bb1306cc8e7bcb9 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 16:55:47 -0600 Subject: [PATCH 44/94] tests(fixtures[tmux_version_fail]): Note pydocstyle updates --- tests/fixtures/pluginsystem/partials/tmux_version_fail.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/fixtures/pluginsystem/partials/tmux_version_fail.py b/tests/fixtures/pluginsystem/partials/tmux_version_fail.py index acf886d588c..b30f3c40829 100644 --- a/tests/fixtures/pluginsystem/partials/tmux_version_fail.py +++ b/tests/fixtures/pluginsystem/partials/tmux_version_fail.py @@ -1,3 +1,4 @@ +"""Fixtures for tmuxp plugins for tmux version exceptions.""" import typing as t from .test_plugin_helpers import MyTestTmuxpPlugin @@ -7,6 +8,8 @@ class TmuxVersionFailMinPlugin(MyTestTmuxpPlugin): + """Tmuxp plugin that fails when tmux below minimum version constraint.""" + def __init__(self) -> None: config: "PluginTestConfigSchema" = { "plugin_name": "tmux-min-version-fail", @@ -17,6 +20,8 @@ def __init__(self) -> None: class TmuxVersionFailMaxPlugin(MyTestTmuxpPlugin): + """Tmuxp plugin that fails when tmux above maximum version constraint.""" + def __init__(self) -> None: config: "PluginTestConfigSchema" = { "plugin_name": "tmux-max-version-fail", @@ -27,6 +32,8 @@ def __init__(self) -> None: class TmuxVersionFailIncompatiblePlugin(MyTestTmuxpPlugin): + """Tmuxp plugin that fails when tmux version constraint is invalid.""" + def __init__(self) -> None: config: "PluginTestConfigSchema" = { "plugin_name": "tmux-incompatible-version-fail", From 383d5201126e08ac292bb7f16754b06ee3985c78 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 17:02:22 -0600 Subject: [PATCH 45/94] tests(fixtures[libtmux_version_fail]): Note pydocstyle updates --- .../fixtures/pluginsystem/partials/libtmux_version_fail.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/fixtures/pluginsystem/partials/libtmux_version_fail.py b/tests/fixtures/pluginsystem/partials/libtmux_version_fail.py index f801c21391a..b8a18466a5d 100644 --- a/tests/fixtures/pluginsystem/partials/libtmux_version_fail.py +++ b/tests/fixtures/pluginsystem/partials/libtmux_version_fail.py @@ -1,3 +1,4 @@ +"""Fixtures for tmuxp plugins for libtmux version exceptions.""" import typing as t from .test_plugin_helpers import MyTestTmuxpPlugin @@ -7,6 +8,8 @@ class LibtmuxVersionFailMinPlugin(MyTestTmuxpPlugin): + """Tmuxp plugin that fails when libtmux below minimum version constraint.""" + def __init__(self) -> None: config: "PluginTestConfigSchema" = { "plugin_name": "libtmux-min-version-fail", @@ -17,6 +20,8 @@ def __init__(self) -> None: class LibtmuxVersionFailMaxPlugin(MyTestTmuxpPlugin): + """Tmuxp plugin that fails when libtmux above maximum version constraint.""" + def __init__(self) -> None: config: "PluginTestConfigSchema" = { "plugin_name": "libtmux-max-version-fail", @@ -27,6 +32,8 @@ def __init__(self) -> None: class LibtmuxVersionFailIncompatiblePlugin(MyTestTmuxpPlugin): + """Tmuxp plugin that fails when libtmux version constraint is invalid.""" + def __init__(self) -> None: config: "PluginTestConfigSchema" = { "plugin_name": "libtmux-incompatible-version-fail", From 53f8b8f6682dc5c5172b1ad62d40a2f25759d2fc Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 17:04:09 -0600 Subject: [PATCH 46/94] tests(fixtures[test_plugin_helpers]): Note pydocstyle updates --- tests/fixtures/pluginsystem/partials/test_plugin_helpers.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/fixtures/pluginsystem/partials/test_plugin_helpers.py b/tests/fixtures/pluginsystem/partials/test_plugin_helpers.py index 8b6c054e29b..874a06c6422 100644 --- a/tests/fixtures/pluginsystem/partials/test_plugin_helpers.py +++ b/tests/fixtures/pluginsystem/partials/test_plugin_helpers.py @@ -1,3 +1,4 @@ +"""Tmuxp test plugin for asserting version constraints.""" import typing as t from tmuxp.plugin import TmuxpPlugin @@ -11,6 +12,8 @@ class MyTestTmuxpPlugin(TmuxpPlugin): + """Base class for testing tmuxp plugins with version constraints.""" + def __init__(self, **config: "Unpack[PluginTestConfigSchema]") -> None: assert isinstance(config, dict) tmux_version = config.pop("tmux_version", None) From 3160a7beebfa23e8da55e31cf611d30dec924c11 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 17:12:19 -0600 Subject: [PATCH 47/94] tests(fixtures[all_pass]): Note pydocstyle updates --- tests/fixtures/pluginsystem/partials/all_pass.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/fixtures/pluginsystem/partials/all_pass.py b/tests/fixtures/pluginsystem/partials/all_pass.py index 393fa00c429..19cbeb23f86 100644 --- a/tests/fixtures/pluginsystem/partials/all_pass.py +++ b/tests/fixtures/pluginsystem/partials/all_pass.py @@ -1,3 +1,4 @@ +"""Tmuxp test plugin with version constraints guaranteed to pass.""" import typing as t from .test_plugin_helpers import MyTestTmuxpPlugin @@ -7,6 +8,8 @@ class AllVersionPassPlugin(MyTestTmuxpPlugin): + """Tmuxp plugin with config constraints guaranteed to validate.""" + def __init__(self) -> None: config: "PluginTestConfigSchema" = { "plugin_name": "tmuxp-plugin-my-tmuxp-plugin", From cc255a03c174f9f3aea4372048eb0155494f4111 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 17:56:41 -0600 Subject: [PATCH 48/94] tests(fixtures[_types]): Note pydocstyle updates --- tests/fixtures/pluginsystem/partials/_types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fixtures/pluginsystem/partials/_types.py b/tests/fixtures/pluginsystem/partials/_types.py index 36c6c15c11e..460c71375de 100644 --- a/tests/fixtures/pluginsystem/partials/_types.py +++ b/tests/fixtures/pluginsystem/partials/_types.py @@ -1,4 +1,4 @@ -"""Internal, :const:`typing.TYPE_CHECKING` guarded :term:`type annotations `. +"""Internal, :const:`typing.TYPE_CHECKING` scoped :term:`type annotations `. These are _not_ to be imported at runtime as `typing_extensions` is not bundled with tmuxp. Usage example: From a3b69e174496032d70f0bde437302e40bdb7de63 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 18:12:39 -0600 Subject: [PATCH 49/94] tests(fixtures[partials]): Note pydocstyle updates --- tests/fixtures/pluginsystem/partials/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fixtures/pluginsystem/partials/__init__.py b/tests/fixtures/pluginsystem/partials/__init__.py index e69de29bb2d..793b5237355 100644 --- a/tests/fixtures/pluginsystem/partials/__init__.py +++ b/tests/fixtures/pluginsystem/partials/__init__.py @@ -0,0 +1 @@ +"""Tmuxp tests for plugins.""" From dc0f8bc3dd4a8fefb14a574883c20ab659807c0e Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 17 Dec 2023 18:13:10 -0600 Subject: [PATCH 50/94] tests(fixtures[pluginsystem]): Note pydocstyle updates --- tests/fixtures/pluginsystem/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fixtures/pluginsystem/__init__.py b/tests/fixtures/pluginsystem/__init__.py index e69de29bb2d..3e3bca44393 100644 --- a/tests/fixtures/pluginsystem/__init__.py +++ b/tests/fixtures/pluginsystem/__init__.py @@ -0,0 +1 @@ +""""Test data for tmuxp plugin system.""" From e876ab850d22c182bac0c529202e5b1679350183 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 08:37:02 -0600 Subject: [PATCH 51/94] tests(fixtures[import_tmuxinator]): pydocstyle manual fixes --- tests/fixtures/import_tmuxinator/__init__.py | 1 + tests/fixtures/import_tmuxinator/test1.py | 1 + tests/fixtures/import_tmuxinator/test2.py | 1 + tests/fixtures/import_tmuxinator/test3.py | 1 + 4 files changed, 4 insertions(+) diff --git a/tests/fixtures/import_tmuxinator/__init__.py b/tests/fixtures/import_tmuxinator/__init__.py index 91bc1d0f43e..dc711b29b7b 100644 --- a/tests/fixtures/import_tmuxinator/__init__.py +++ b/tests/fixtures/import_tmuxinator/__init__.py @@ -1 +1,2 @@ +"""Tmuxinator data fixtures for import_tmuxinator tests.""" from . import test1, test2, test3 diff --git a/tests/fixtures/import_tmuxinator/test1.py b/tests/fixtures/import_tmuxinator/test1.py index d7139f68a0d..684634dcded 100644 --- a/tests/fixtures/import_tmuxinator/test1.py +++ b/tests/fixtures/import_tmuxinator/test1.py @@ -1,3 +1,4 @@ +"""Tmuxinator data fixtures for import_tmuxinator tests, 1st dataset.""" from .. import utils as test_utils tmuxinator_yaml = test_utils.read_workspace_file("import_tmuxinator/test1.yaml") diff --git a/tests/fixtures/import_tmuxinator/test2.py b/tests/fixtures/import_tmuxinator/test2.py index 008b4e2f31d..d8dba900ceb 100644 --- a/tests/fixtures/import_tmuxinator/test2.py +++ b/tests/fixtures/import_tmuxinator/test2.py @@ -1,3 +1,4 @@ +"""Tmuxinator data fixtures for import_tmuxinator tests, 2nd dataset.""" from .. import utils as test_utils tmuxinator_yaml = test_utils.read_workspace_file("import_tmuxinator/test2.yaml") diff --git a/tests/fixtures/import_tmuxinator/test3.py b/tests/fixtures/import_tmuxinator/test3.py index dc0468d414d..86300a5156a 100644 --- a/tests/fixtures/import_tmuxinator/test3.py +++ b/tests/fixtures/import_tmuxinator/test3.py @@ -1,3 +1,4 @@ +"""Tmuxinator data fixtures for import_tmuxinator tests, 3rd dataset.""" from .. import utils as test_utils tmuxinator_yaml = test_utils.read_workspace_file("import_tmuxinator/test3.yaml") From 4c72aaee94d560f8d0242f31c8b97c8b8a2297aa Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 08:38:35 -0600 Subject: [PATCH 52/94] tests(fixtures[import_teamocil]): pydocstyle manual fixes --- tests/fixtures/import_teamocil/__init__.py | 1 + tests/fixtures/import_teamocil/layouts.py | 1 + tests/fixtures/import_teamocil/test1.py | 1 + tests/fixtures/import_teamocil/test2.py | 1 + tests/fixtures/import_teamocil/test3.py | 1 + tests/fixtures/import_teamocil/test4.py | 1 + 6 files changed, 6 insertions(+) diff --git a/tests/fixtures/import_teamocil/__init__.py b/tests/fixtures/import_teamocil/__init__.py index 6d5ce91af9e..5367bcbc497 100644 --- a/tests/fixtures/import_teamocil/__init__.py +++ b/tests/fixtures/import_teamocil/__init__.py @@ -1 +1,2 @@ +"""Teamocil data fixtures for import_teamocil tests.""" from . import layouts, test1, test2, test3, test4 diff --git a/tests/fixtures/import_teamocil/layouts.py b/tests/fixtures/import_teamocil/layouts.py index 14d509c9697..f6a949ac340 100644 --- a/tests/fixtures/import_teamocil/layouts.py +++ b/tests/fixtures/import_teamocil/layouts.py @@ -1,3 +1,4 @@ +"""Teamocil data fixtures for import_teamocil tests, for layout testing.""" from .. import utils as test_utils teamocil_yaml_file = test_utils.get_workspace_file("import_teamocil/layouts.yaml") diff --git a/tests/fixtures/import_teamocil/test1.py b/tests/fixtures/import_teamocil/test1.py index d55a92d4a34..2a7cd33b82f 100644 --- a/tests/fixtures/import_teamocil/test1.py +++ b/tests/fixtures/import_teamocil/test1.py @@ -1,3 +1,4 @@ +"""Teamocil data fixtures for import_teamocil tests, 1st test.""" from .. import utils as test_utils teamocil_yaml = test_utils.read_workspace_file("import_teamocil/test1.yaml") diff --git a/tests/fixtures/import_teamocil/test2.py b/tests/fixtures/import_teamocil/test2.py index 3478b22c77b..82c682eaff3 100644 --- a/tests/fixtures/import_teamocil/test2.py +++ b/tests/fixtures/import_teamocil/test2.py @@ -1,3 +1,4 @@ +"""Teamocil data fixtures for import_teamocil tests, 2nd test.""" from .. import utils as test_utils teamocil_yaml = test_utils.read_workspace_file("import_teamocil/test2.yaml") diff --git a/tests/fixtures/import_teamocil/test3.py b/tests/fixtures/import_teamocil/test3.py index 4f18f11d049..6249355d18c 100644 --- a/tests/fixtures/import_teamocil/test3.py +++ b/tests/fixtures/import_teamocil/test3.py @@ -1,3 +1,4 @@ +"""Teamocil data fixtures for import_teamocil tests, 3rd test.""" from .. import utils as test_utils teamocil_yaml = test_utils.read_workspace_file("import_teamocil/test3.yaml") diff --git a/tests/fixtures/import_teamocil/test4.py b/tests/fixtures/import_teamocil/test4.py index 62c0ead874f..f22b6595b22 100644 --- a/tests/fixtures/import_teamocil/test4.py +++ b/tests/fixtures/import_teamocil/test4.py @@ -1,3 +1,4 @@ +"""Teamocil data fixtures for import_teamocil tests, 4th test.""" from .. import utils as test_utils teamocil_yaml = test_utils.read_workspace_file("import_teamocil/test4.yaml") From 4616d1133c2fb6a78992083a8fd285a1bfcf1a7d Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 08:38:58 -0600 Subject: [PATCH 53/94] tests(fixtures): pydocstyle manual fixes --- tests/fixtures/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fixtures/__init__.py b/tests/fixtures/__init__.py index eb018c3ff09..32c2ed61025 100644 --- a/tests/fixtures/__init__.py +++ b/tests/fixtures/__init__.py @@ -1 +1,2 @@ +"""Fixture test data for tmuxp.""" from . import utils From 250f7736891a50482c5f9290488061889fa7985a Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 08:39:21 -0600 Subject: [PATCH 54/94] tests(constants): pydocstyle manual fixes --- tests/constants.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/constants.py b/tests/constants.py index 9fa14e00f07..eff81eced5a 100644 --- a/tests/constants.py +++ b/tests/constants.py @@ -1,3 +1,4 @@ +"""Constant variables for tmuxp tests.""" import pathlib TESTS_PATH = pathlib.Path(__file__).parent From 3b0c169f5e60414836a8b75d1c223aa9f87bb15b Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 08:40:56 -0600 Subject: [PATCH 55/94] tests(cli[shell]): pydocstyle manual fixes --- tests/cli/test_shell.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/cli/test_shell.py b/tests/cli/test_shell.py index 75658471df9..6d96bd0fa26 100644 --- a/tests/cli/test_shell.py +++ b/tests/cli/test_shell.py @@ -1,3 +1,4 @@ +"""CLI tests for tmuxp shell.""" import contextlib import io import pathlib @@ -116,6 +117,7 @@ def test_shell( monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str], ) -> None: + """CLI tests for tmuxp shell.""" monkeypatch.setenv("HOME", str(tmp_path)) window_name = "my_window" window = session.new_window(window_name=window_name) @@ -207,6 +209,7 @@ def test_shell_target_missing( monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str], ) -> None: + """CLI tests for tmuxp shell when target is not specified.""" monkeypatch.setenv("HOME", str(tmp_path)) window_name = "my_window" window = session.new_window(window_name=window_name) @@ -283,6 +286,7 @@ def test_shell_interactive( monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str], ) -> None: + """CLI tests for tmuxp shell when shell is specified.""" monkeypatch.setenv("HOME", str(tmp_path)) window_name = "my_window" window = session.new_window(window_name=window_name) From 79b805346c453e2204d051e16a40ec6f50a37b24 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 09:09:55 -0600 Subject: [PATCH 56/94] tests(cli[ls]): Note pydocstyle updates --- tests/cli/test_ls.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/cli/test_ls.py b/tests/cli/test_ls.py index f8a2113ec9c..7fdcf9ffde1 100644 --- a/tests/cli/test_ls.py +++ b/tests/cli/test_ls.py @@ -1,3 +1,4 @@ +"""CLI tests for tmuxp ls command.""" import contextlib import pathlib @@ -11,6 +12,7 @@ def test_ls_cli( tmp_path: pathlib.Path, capsys: pytest.CaptureFixture[str], ) -> None: + """CLI test for tmuxp ls.""" monkeypatch.setenv("HOME", str(tmp_path)) monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path / ".config")) From 130116389e8e85621d8969134a6c76e5a4a76947 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 09:20:13 -0600 Subject: [PATCH 57/94] tests(cli[load]): pydocstyle manual fixes --- tests/cli/test_load.py | 79 +++++++++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 17 deletions(-) diff --git a/tests/cli/test_load.py b/tests/cli/test_load.py index 399cea5fe24..13f7d100c6f 100644 --- a/tests/cli/test_load.py +++ b/tests/cli/test_load.py @@ -1,3 +1,4 @@ +"""CLI tests for tmuxp load.""" import contextlib import io import pathlib @@ -25,7 +26,11 @@ from ..fixtures import utils as test_utils -def test_load_workspace(server: "Server", monkeypatch: pytest.MonkeyPatch) -> None: +def test_load_workspace( + server: "Server", + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Generic test for loading a tmuxp workspace via tmuxp load.""" # this is an implementation test. Since this testsuite may be ran within # a tmux session by the developer himself, delete the TMUX variable # temporarily. @@ -42,8 +47,10 @@ def test_load_workspace(server: "Server", monkeypatch: pytest.MonkeyPatch) -> No def test_load_workspace_passes_tmux_config( - server: "Server", monkeypatch: pytest.MonkeyPatch + server: "Server", + monkeypatch: pytest.MonkeyPatch, ) -> None: + """Test tmuxp load with a tmux configuration file.""" # this is an implementation test. Since this testsuite may be ran within # a tmux session by the developer himself, delete the TMUX variable # temporarily. @@ -64,8 +71,10 @@ def test_load_workspace_passes_tmux_config( def test_load_workspace_named_session( - server: "Server", monkeypatch: pytest.MonkeyPatch + server: "Server", + monkeypatch: pytest.MonkeyPatch, ) -> None: + """Test tmuxp load with a custom tmux session name.""" # this is an implementation test. Since this testsuite may be ran within # a tmux session by the developer himself, delete the TMUX variable # temporarily. @@ -88,8 +97,11 @@ def test_load_workspace_named_session( has_lt_version("2.1"), reason="exact session name matches only tmux >= 2.1" ) def test_load_workspace_name_match_regression_252( - tmp_path: pathlib.Path, server: "Server", monkeypatch: pytest.MonkeyPatch + tmp_path: pathlib.Path, + server: "Server", + monkeypatch: pytest.MonkeyPatch, ) -> None: + """Test tmuxp load for a regression where tmux shell names would not match.""" monkeypatch.delenv("TMUX", raising=False) session_file = FIXTURE_PATH / "workspace/builder" / "two_pane.yaml" @@ -101,9 +113,9 @@ def test_load_workspace_name_match_regression_252( assert isinstance(session, Session) assert session.name == "sample workspace" - projfile = tmp_path / "simple.yaml" + workspace_file = tmp_path / "simple.yaml" - projfile.write_text( + workspace_file.write_text( """ session_name: sampleconfi start_directory: './' @@ -115,15 +127,18 @@ def test_load_workspace_name_match_regression_252( # open it detached session = load_workspace( - str(projfile), socket_name=server.socket_name, detached=True + str(workspace_file), socket_name=server.socket_name, detached=True ) assert session is not None assert session.name == "sampleconfi" def test_load_symlinked_workspace( - server: "Server", tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch + server: "Server", + tmp_path: pathlib.Path, + monkeypatch: pytest.MonkeyPatch, ) -> None: + """Test tmuxp load can follow a symlinked tmuxp config file.""" # this is an implementation test. Since this testsuite may be ran within # a tmux session by the developer himself, delete the TMUX variable # temporarily. @@ -133,9 +148,9 @@ def test_load_symlinked_workspace( realtemp.mkdir() linktemp = tmp_path / "symlinktemp" linktemp.symlink_to(realtemp) - projfile = linktemp / "simple.yaml" + workspace_file = linktemp / "simple.yaml" - projfile.write_text( + workspace_file.write_text( """ session_name: samplesimple start_directory: './' @@ -147,7 +162,7 @@ def test_load_symlinked_workspace( # open it detached session = load_workspace( - str(projfile), socket_name=server.socket_name, detached=True + str(workspace_file), socket_name=server.socket_name, detached=True ) assert session is not None assert session.attached_window is not None @@ -167,7 +182,12 @@ def test_load_symlinked_workspace( class CLILoadFixture(t.NamedTuple): + """Test fixture for tmuxp load tests.""" + + # pytest (internal): Test fixture name test_id: str + + # test params cli_args: t.List[t.Union[str, t.List[str]]] config_paths: t.List[str] session_names: t.List[str] @@ -274,6 +294,7 @@ def test_load( expected_in_err: "ExpectedOutput", expected_not_in_err: "ExpectedOutput", ) -> None: + """Parametrized test battery for tmuxp load CLI command.""" assert server.socket_name is not None monkeypatch.chdir(tmp_path) @@ -320,6 +341,7 @@ def test_regression_00132_session_name_with_dots( session: Session, capsys: pytest.CaptureFixture[str], ) -> None: + """Regression test for session names with dots.""" yaml_config = FIXTURE_PATH / "workspace/builder" / "regression_00132_dots.yaml" cli_args = [str(yaml_config)] with pytest.raises(libtmux.exc.BadSessionName): @@ -336,6 +358,7 @@ def test_load_zsh_autotitle_warning( capsys: pytest.CaptureFixture[str], server: "Server", ) -> None: + """Test loading ZSH without DISABLE_AUTO_TITLE raises warning.""" # create dummy tmuxp yaml so we don't get yelled at yaml_config = tmp_path / ".tmuxp.yaml" yaml_config.write_text( @@ -394,6 +417,7 @@ def test_load_log_file( monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str], ) -> None: + """Test loading via tmuxp load with --log-file.""" # create dummy tmuxp yaml that breaks to prevent actually loading tmux tmuxp_config_path = tmp_path / ".tmuxp.yaml" tmuxp_config_path.write_text( @@ -418,7 +442,10 @@ def test_load_log_file( assert result.out is not None -def test_load_plugins(monkeypatch_plugin_test_packages: None) -> None: +def test_load_plugins( + monkeypatch_plugin_test_packages: None, +) -> None: + """Test loading via tmuxp load with plugins.""" from tmuxp_test_plugin_bwb.plugin import ( # type: ignore PluginBeforeWorkspaceBuilder, ) @@ -455,6 +482,7 @@ def test_load_plugins_version_fail_skip( inputs: t.List[str], capsys: pytest.CaptureFixture[str], ) -> None: + """Test tmuxp load with plugins failing version constraints can continue.""" with contextlib.suppress(SystemExit): cli.cli(cli_args) @@ -479,6 +507,7 @@ def test_load_plugins_version_fail_no_skip( monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str], ) -> None: + """Test tmuxp load with plugins failing version constraints can exit.""" monkeypatch.setattr("sys.stdin", io.StringIO("".join(inputs))) with contextlib.suppress(SystemExit): @@ -498,6 +527,7 @@ def test_load_plugins_plugin_missing( cli_args: t.List[str], capsys: pytest.CaptureFixture[str], ) -> None: + """Test tmuxp load with plugins missing raise an error.""" with contextlib.suppress(SystemExit): cli.cli(cli_args) @@ -511,6 +541,7 @@ def test_plugin_system_before_script( server: "Server", monkeypatch: pytest.MonkeyPatch, ) -> None: + """Test tmuxp load with sessions using before_script.""" # this is an implementation test. Since this testsuite may be ran within # a tmux session by the developer himself, delete the TMUX variable # temporarily. @@ -527,8 +558,11 @@ def test_plugin_system_before_script( def test_load_attached( - server: "Server", monkeypatch: pytest.MonkeyPatch, mocker: MockerFixture + server: "Server", + monkeypatch: pytest.MonkeyPatch, + mocker: MockerFixture, ) -> None: + """Test tmuxp load's attachment behavior.""" # Load a session and attach from outside tmux monkeypatch.delenv("TMUX", raising=False) @@ -546,8 +580,11 @@ def test_load_attached( def test_load_attached_detached( - server: "Server", monkeypatch: pytest.MonkeyPatch, mocker: MockerFixture + server: "Server", + monkeypatch: pytest.MonkeyPatch, + mocker: MockerFixture, ) -> None: + """Test tmuxp load when sessions are build without attaching client.""" # Load a session but don't attach monkeypatch.delenv("TMUX", raising=False) @@ -565,8 +602,11 @@ def test_load_attached_detached( def test_load_attached_within_tmux( - server: "Server", monkeypatch: pytest.MonkeyPatch, mocker: MockerFixture + server: "Server", + monkeypatch: pytest.MonkeyPatch, + mocker: MockerFixture, ) -> None: + """Test loading via tmuxp load when already within a tmux session.""" # Load a session and attach from within tmux monkeypatch.setenv("TMUX", "/tmp/tmux-1234/default,123,0") @@ -584,8 +624,11 @@ def test_load_attached_within_tmux( def test_load_attached_within_tmux_detached( - server: "Server", monkeypatch: pytest.MonkeyPatch, mocker: MockerFixture + server: "Server", + monkeypatch: pytest.MonkeyPatch, + mocker: MockerFixture, ) -> None: + """Test loading via tmuxp load within a tmux session switches clients.""" # Load a session and attach from within tmux monkeypatch.setenv("TMUX", "/tmp/tmux-1234/default,123,0") @@ -603,8 +646,10 @@ def test_load_attached_within_tmux_detached( def test_load_append_windows_to_current_session( - server: "Server", monkeypatch: pytest.MonkeyPatch + server: "Server", + monkeypatch: pytest.MonkeyPatch, ) -> None: + """Test tmuxp load when windows are appended to the current session.""" yaml_config = test_utils.read_workspace_file("workspace/builder/two_pane.yaml") session_config = ConfigReader._load(format="yaml", content=yaml_config) From 7f738dabce94d284c363f809e812435170152c2e Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 09:29:16 -0600 Subject: [PATCH 58/94] tests(cli[import]): Note pydocstyle updates --- tests/cli/test_import.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/cli/test_import.py b/tests/cli/test_import.py index b08f78a438d..ce418889e30 100644 --- a/tests/cli/test_import.py +++ b/tests/cli/test_import.py @@ -1,3 +1,4 @@ +"""CLI tests for tmuxp import.""" import contextlib import io import pathlib @@ -17,6 +18,7 @@ def test_import( monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str], ) -> None: + """Basic CLI test for tmuxp import.""" cli.cli(cli_args) result = capsys.readouterr() assert "tmuxinator" in result.out @@ -46,6 +48,7 @@ def test_import_teamocil( tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch, ) -> None: + """CLI test for tmuxp import w/ teamocil.""" teamocil_config = test_utils.read_workspace_file("import_teamocil/test4.yaml") teamocil_path = tmp_path / ".teamocil" @@ -92,6 +95,7 @@ def test_import_tmuxinator( tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch, ) -> None: + """CLI test for tmuxp import w/ tmuxinator.""" tmuxinator_config = test_utils.read_workspace_file("import_tmuxinator/test3.yaml") tmuxinator_path = tmp_path / ".tmuxinator" From 9b136d5e8f09cb9648a246bb22fc96ea35de7fad Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 09:30:04 -0600 Subject: [PATCH 59/94] tests(cli[freeze]): Note pydocstyle updates --- tests/cli/test_freeze.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/cli/test_freeze.py b/tests/cli/test_freeze.py index c3f593065d9..96ca742d7d2 100644 --- a/tests/cli/test_freeze.py +++ b/tests/cli/test_freeze.py @@ -33,6 +33,7 @@ def test_freeze( tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch, ) -> None: + """Parametrized test for freezing a tmux session to a tmuxp config file.""" monkeypatch.setenv("HOME", str(tmp_path)) exists_yaml = tmp_path / "exists.yaml" exists_yaml.touch() From 26c1592325c420839547b902a0385bd87ca7d9a0 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 09:30:37 -0600 Subject: [PATCH 60/94] tests(cli[debug-info]): Note pydocstyle updates --- tests/cli/test_debug_info.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/cli/test_debug_info.py b/tests/cli/test_debug_info.py index df76fc830df..daba2c69fba 100644 --- a/tests/cli/test_debug_info.py +++ b/tests/cli/test_debug_info.py @@ -1,3 +1,4 @@ +"""CLI tests for tmuxp debuginfo.""" import pathlib import pytest @@ -10,6 +11,7 @@ def test_debug_info_cli( tmp_path: pathlib.Path, capsys: pytest.CaptureFixture[str], ) -> None: + """Basic CLI test for tmuxp debug-info.""" monkeypatch.setenv("SHELL", "/bin/bash") cli.cli(["debug-info"]) From 5df5ccd1bc10a7a39b25944c7dd5a91d3b8bf722 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 09:32:25 -0600 Subject: [PATCH 61/94] tests(cli[convert]): pydocstyle manual fixes --- tests/cli/test_convert.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/cli/test_convert.py b/tests/cli/test_convert.py index 6a36e3e46d6..3042d078333 100644 --- a/tests/cli/test_convert.py +++ b/tests/cli/test_convert.py @@ -1,3 +1,4 @@ +"""CLI tests for tmuxp convert.""" import contextlib import io import json @@ -24,6 +25,7 @@ def test_convert( tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch, ) -> None: + """Parametrized tests for tmuxp convert.""" # create dummy tmuxp yaml so we don't get yelled at filename = cli_args[1] if filename == ".": @@ -63,6 +65,7 @@ def test_convert_json( tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch, ) -> None: + """CLI test using tmuxp convert to convert configuration from json to yaml.""" # create dummy tmuxp yaml so we don't get yelled at json_config = tmp_path / ".tmuxp.json" json_config.write_text('{"session_name": "hello"}', encoding="utf-8") From 899145b3f30d6cdf0b8703d7b0a86c7e4fb4fc92 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 09:35:11 -0600 Subject: [PATCH 62/94] tests(cli[cli]): Note pydocstyle updates --- tests/cli/test_cli.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/tests/cli/test_cli.py b/tests/cli/test_cli.py index 3cb3a20ee66..50710327712 100644 --- a/tests/cli/test_cli.py +++ b/tests/cli/test_cli.py @@ -1,3 +1,4 @@ +"""CLI tests for tmuxp's core shell functionality.""" import argparse import contextlib import pathlib @@ -41,6 +42,7 @@ def test_help( monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str], ) -> None: + """Test tmuxp --help / -h.""" # In scrunched terminals, prevent width causing differentiation in result.out. monkeypatch.setenv("COLUMNS", "100") monkeypatch.setenv("LINES", "100") @@ -54,8 +56,10 @@ def test_help( def test_resolve_behavior( - tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch + tmp_path: pathlib.Path, + monkeypatch: pytest.MonkeyPatch, ) -> None: + """Test resolution of file paths.""" expect = tmp_path monkeypatch.chdir(tmp_path) assert pathlib.Path("../").resolve() == expect.parent @@ -64,7 +68,10 @@ def test_resolve_behavior( assert pathlib.Path(expect).resolve() == expect -def test_get_tmuxinator_dir(monkeypatch: pytest.MonkeyPatch) -> None: +def test_get_tmuxinator_dir( + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Test get_tmuxinator_dir() helper function.""" assert get_tmuxinator_dir() == pathlib.Path("~/.tmuxinator").expanduser() monkeypatch.setenv("HOME", "/moo") @@ -73,7 +80,10 @@ def test_get_tmuxinator_dir(monkeypatch: pytest.MonkeyPatch) -> None: assert get_tmuxinator_dir() == pathlib.Path("~/.tmuxinator/").expanduser() -def test_get_teamocil_dir(monkeypatch: pytest.MonkeyPatch) -> None: +def test_get_teamocil_dir( + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Test get_teamocil_dir() helper function.""" assert get_teamocil_dir() == pathlib.Path("~/.teamocil/").expanduser() monkeypatch.setenv("HOME", "/moo") @@ -82,11 +92,12 @@ def test_get_teamocil_dir(monkeypatch: pytest.MonkeyPatch) -> None: assert get_teamocil_dir() == pathlib.Path("~/.teamocil/").expanduser() -def test_pass_config_dir_ClickPath( +def test_pass_config_dir_argparse( tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str], ) -> None: + """Test workspace configurations can be detected via directory.""" configdir = tmp_path / "myconfigdir" configdir.mkdir() user_config_name = "myconfig" @@ -118,8 +129,10 @@ def check_cmd(config_arg: str) -> "_pytest.capture.CaptureResult[str]": def test_reattach_plugins( - monkeypatch_plugin_test_packages: None, server: "Server" + monkeypatch_plugin_test_packages: None, + server: "Server", ) -> None: + """Test reattach plugin hook.""" config_plugins = test_utils.read_workspace_file("workspace/builder/plugin_r.yaml") session_configig = ConfigReader._load(format="yaml", content=config_plugins) From 3fe63c4976bb5b6831a18af2aa4c81c45893de10 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 09:35:30 -0600 Subject: [PATCH 63/94] tests(cli): Note pydocstyle updates --- tests/cli/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/cli/__init__.py b/tests/cli/__init__.py index e69de29bb2d..95437011db7 100644 --- a/tests/cli/__init__.py +++ b/tests/cli/__init__.py @@ -0,0 +1 @@ +"""CLI tests for tmuxp.""" From 0f8a4ded9d215c81a2ddffa15325461b4470bf22 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 09:35:51 -0600 Subject: [PATCH 64/94] tests: pydocstyle manual fixes --- tests/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/__init__.py b/tests/__init__.py index e69de29bb2d..6940f228687 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -0,0 +1 @@ +"""Tests for tmuxp.""" From af23a4b45e016b218c753726901693629abcd2d7 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 09:41:36 -0600 Subject: [PATCH 65/94] workspace(validation): pydocstyle manual fixes --- src/tmuxp/workspace/validation.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/tmuxp/workspace/validation.py b/src/tmuxp/workspace/validation.py index 02578e1de80..a3b6a393b1d 100644 --- a/src/tmuxp/workspace/validation.py +++ b/src/tmuxp/workspace/validation.py @@ -1,13 +1,18 @@ +"""Validation errors for tmuxp configuration files.""" import typing as t from .. import exc class SchemaValidationError(exc.WorkspaceError): + """Tmuxp configuration validation base error.""" + pass class SessionNameMissingValidationError(SchemaValidationError): + """Tmuxp configuration error for session name missing.""" + def __init__(self, *args: object, **kwargs: object) -> None: return super().__init__( 'workspace requires "session_name"', @@ -17,6 +22,8 @@ def __init__(self, *args: object, **kwargs: object) -> None: class WindowListMissingValidationError(SchemaValidationError): + """Tmuxp configuration error for window list missing.""" + def __init__(self, *args: object, **kwargs: object) -> None: return super().__init__( 'workspace requires list of "windows"', @@ -26,6 +33,8 @@ def __init__(self, *args: object, **kwargs: object) -> None: class WindowNameMissingValidationError(SchemaValidationError): + """Tmuxp configuration error for missing window_name.""" + def __init__(self, *args: object, **kwargs: object) -> None: return super().__init__( 'workspace window is missing "window_name"', @@ -35,6 +44,8 @@ def __init__(self, *args: object, **kwargs: object) -> None: class InvalidPluginsValidationError(SchemaValidationError): + """Tmuxp configuration error for invalid plugins.""" + def __init__(self, plugins: t.Any, *args: object, **kwargs: object) -> None: return super().__init__( '"plugins" only supports list type. ' From 75b98a365d71f4011fe0f294ef2f9e33941b21ef Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 09:45:38 -0600 Subject: [PATCH 66/94] workspace(importers): Note pydocstyle updates --- src/tmuxp/workspace/importers.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tmuxp/workspace/importers.py b/src/tmuxp/workspace/importers.py index e5fb789821d..a33b44a035c 100644 --- a/src/tmuxp/workspace/importers.py +++ b/src/tmuxp/workspace/importers.py @@ -1,3 +1,4 @@ +"""Configuration import adapters to load teamocil, tmuxinator, etc. in tmuxp.""" import typing as t From e640bfef640c3668817c8c7fbbd4a3c4140c2f10 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 09:46:05 -0600 Subject: [PATCH 67/94] workspace(loader): Note pydocstyle updates --- src/tmuxp/workspace/loader.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tmuxp/workspace/loader.py b/src/tmuxp/workspace/loader.py index e17d768ff5c..a75aa61f428 100644 --- a/src/tmuxp/workspace/loader.py +++ b/src/tmuxp/workspace/loader.py @@ -13,7 +13,7 @@ def expandshell(value: str) -> str: - """Returned with variables expanded based on user's ``$HOME`` and ``env``. + """Resolve shell variables based on user's ``$HOME`` and ``env``. :py:func:`os.path.expanduser` and :py:fubasednc:`os.path.expandvars`. @@ -31,6 +31,7 @@ def expandshell(value: str) -> str: def expand_cmd(p: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]: + """Resolve shell variables and expand shorthands in a tmuxp config mapping.""" if isinstance(p, str): p = {"shell_command": [p]} elif isinstance(p, list): @@ -71,7 +72,7 @@ def expand( cwd: t.Optional[t.Union[pathlib.Path, str]] = None, parent: t.Optional[t.Any] = None, ) -> t.Dict[str, t.Any]: - """Return workspace with shorthand and inline properties expanded. + """Resolve workspace variables and expand shorthand style / inline properties. This is necessary to keep the code in the :class:`WorkspaceBuilder` clean and also allow for neat, short-hand "sugarified" syntax. From 18449d3b3ecbd3eea125aa7a735c097a369a5254 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 09:47:59 -0600 Subject: [PATCH 68/94] workspace(freezer): Note pydocstyle updates --- src/tmuxp/workspace/freezer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tmuxp/workspace/freezer.py b/src/tmuxp/workspace/freezer.py index 8adb4295b63..9c6d6306852 100644 --- a/src/tmuxp/workspace/freezer.py +++ b/src/tmuxp/workspace/freezer.py @@ -1,3 +1,4 @@ +"""Tmux session freezing functionality for tmuxp.""" import typing as t from libtmux.pane import Pane From c9d75c1e4849f10c39190c7f4a605303c79b3f89 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 09:48:34 -0600 Subject: [PATCH 69/94] workspace(finders): Note pydocstyle updates --- src/tmuxp/workspace/finders.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tmuxp/workspace/finders.py b/src/tmuxp/workspace/finders.py index 9ee7f1618e2..3eb8837cc52 100644 --- a/src/tmuxp/workspace/finders.py +++ b/src/tmuxp/workspace/finders.py @@ -1,3 +1,4 @@ +"""Workspace (configuration file) finders for tmuxp.""" import logging import os import pathlib From 77d41bbc3be660af16c8be40854586a25330e27f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 09:48:58 -0600 Subject: [PATCH 70/94] workspace(constants): Note pydocstyle updates --- src/tmuxp/workspace/constants.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tmuxp/workspace/constants.py b/src/tmuxp/workspace/constants.py index 50a463af895..da825868703 100644 --- a/src/tmuxp/workspace/constants.py +++ b/src/tmuxp/workspace/constants.py @@ -1 +1,2 @@ +"""Constant variables for tmuxp workspace functionality.""" VALID_WORKSPACE_DIR_FILE_EXTENSIONS = [".yaml", ".yml", ".json"] From 683f94949b4ee8ec188042dc12d469532f6e1d1f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 09:54:20 -0600 Subject: [PATCH 71/94] workspace(builder): Note pydocstyle updates --- src/tmuxp/workspace/builder.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tmuxp/workspace/builder.py b/src/tmuxp/workspace/builder.py index ed477caca49..4fb6f7c60d8 100644 --- a/src/tmuxp/workspace/builder.py +++ b/src/tmuxp/workspace/builder.py @@ -187,11 +187,13 @@ def __init__( @property def session(self) -> Session: + """Return tmux session using in workspace builder session.""" if self._session is None: raise exc.SessionMissingWorkspaceException() return self._session def session_exists(self, session_name: str) -> bool: + """Return true if tmux session already exists.""" assert session_name is not None assert isinstance(session_name, str) assert self.server is not None @@ -556,6 +558,7 @@ def config_after_window( window.set_window_option(key, val) def find_current_attached_session(self) -> Session: + """Return current attached session.""" assert self.server is not None current_active_pane = get_current_pane(self.server) @@ -572,4 +575,5 @@ def find_current_attached_session(self) -> Session: ) def first_window_pass(self, i: int, session: Session, append: bool) -> bool: + """Return True first window, used when iterating session windows.""" return len(session.windows) == 1 and i == 1 and not append From 0915ec17382dd8e8c2833bd3628c5147bb64d8c3 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 09:54:52 -0600 Subject: [PATCH 72/94] workspace: Note pydocstyle updates --- src/tmuxp/workspace/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tmuxp/workspace/__init__.py b/src/tmuxp/workspace/__init__.py index e69de29bb2d..ac87e57f625 100644 --- a/src/tmuxp/workspace/__init__.py +++ b/src/tmuxp/workspace/__init__.py @@ -0,0 +1 @@ +"""tmuxp workspace functionality.""" From a641f20ea62f9a82725f1fb1db542a4673759a17 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 09:57:28 -0600 Subject: [PATCH 73/94] util: Note pydocstyle updates --- src/tmuxp/util.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tmuxp/util.py b/src/tmuxp/util.py index cea240329a4..888f8f551d1 100644 --- a/src/tmuxp/util.py +++ b/src/tmuxp/util.py @@ -30,7 +30,7 @@ def run_before_script( script_file: t.Union[str, pathlib.Path], cwd: t.Optional[pathlib.Path] = None ) -> int: - """Function to wrap try/except for subprocess.check_call().""" + """Execute a shell script, wraps :meth:`subprocess.check_call()` in a try/catch.""" try: proc = subprocess.Popen( shlex.split(str(script_file)), @@ -105,6 +105,7 @@ def get_session( session_name: t.Optional[str] = None, current_pane: t.Optional["Pane"] = None, ) -> "Session": + """Get tmux session for server by session name, respects current pane, if passed.""" try: if session_name: session = server.sessions.get(session_name=session_name) @@ -131,6 +132,7 @@ def get_window( window_name: t.Optional[str] = None, current_pane: t.Optional["Pane"] = None, ) -> "Window": + """Get tmux window for server by window name, respects current pane, if passed.""" try: if window_name: window = session.windows.get(window_name=window_name) @@ -150,6 +152,7 @@ def get_window( def get_pane(window: "Window", current_pane: t.Optional["Pane"] = None) -> "Pane": + """Get tmux pane for server by pane name, respects current pane, if passed.""" pane = None try: if current_pane is not None: From 75719df441f212061f13457c01e3186ecce6a12c Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 10:08:02 -0600 Subject: [PATCH 74/94] shell: Note pydocstyle updates --- src/tmuxp/shell.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/tmuxp/shell.py b/src/tmuxp/shell.py index f7e1ef0b332..946eca37cf7 100644 --- a/src/tmuxp/shell.py +++ b/src/tmuxp/shell.py @@ -25,12 +25,16 @@ ] class LaunchOptionalImports(TypedDict): + """tmuxp shell optional imports.""" + server: NotRequired["Server"] session: NotRequired["Session"] window: NotRequired["Window"] pane: NotRequired["Pane"] class LaunchImports(t.TypedDict): + """tmuxp shell launch import mapping.""" + libtmux: ModuleType Server: t.Type[Server] Session: t.Type[Session] @@ -43,6 +47,7 @@ class LaunchImports(t.TypedDict): def has_ipython() -> bool: + """Return True if ipython is installed.""" try: from IPython import start_ipython # NOQA F841 except ImportError: @@ -55,6 +60,7 @@ def has_ipython() -> bool: def has_ptpython() -> bool: + """Return True if ptpython is installed.""" try: from ptpython.repl import embed, run_config # F841 except ImportError: @@ -67,6 +73,7 @@ def has_ptpython() -> bool: def has_ptipython() -> bool: + """Return True if ptpython + ipython are both installed.""" try: from ptpython.ipython import embed # F841 from ptpython.repl import run_config # F841 @@ -81,6 +88,7 @@ def has_ptipython() -> bool: def has_bpython() -> bool: + """Return True if bpython is installed.""" try: from bpython import embed # NOQA F841 except ImportError: @@ -89,6 +97,7 @@ def has_bpython() -> bool: def detect_best_shell() -> "CLIShellLiteral": + """Return the best, most feature-rich shell available.""" if has_ptipython(): return "ptipython" elif has_ptpython(): @@ -103,6 +112,7 @@ def detect_best_shell() -> "CLIShellLiteral": def get_bpython( options: "LaunchOptionalImports", extra_args: t.Optional[t.Dict[str, t.Any]] = None ) -> t.Callable[[], None]: + """Return bpython shell.""" if extra_args is None: extra_args = {} @@ -119,6 +129,7 @@ def launch_bpython() -> None: def get_ipython_arguments() -> t.List[str]: + """Return ipython shell args via ``IPYTHON_ARGUMENTS`` environment variables.""" ipython_args = "IPYTHON_ARGUMENTS" return os.environ.get(ipython_args, "").split() @@ -126,6 +137,7 @@ def get_ipython_arguments() -> t.List[str]: def get_ipython( options: "LaunchOptionalImports", **extra_args: t.Dict[str, t.Any] ) -> t.Any: + """Return ipython shell.""" try: from IPython import start_ipython @@ -151,6 +163,7 @@ def launch_ipython() -> None: def get_ptpython(options: "LaunchOptionalImports", vi_mode: bool = False) -> t.Any: + """Return ptpython shell.""" try: from ptpython.repl import embed, run_config except ImportError: @@ -196,6 +209,7 @@ def launch_ptipython() -> None: def get_launch_args(**kwargs: "Unpack[LaunchOptionalImports]") -> "LaunchImports": + """Return tmuxp shell launch arguments, counting for overrides.""" import libtmux from libtmux.pane import Pane from libtmux.server import Server @@ -216,6 +230,7 @@ def get_launch_args(**kwargs: "Unpack[LaunchOptionalImports]") -> "LaunchImports def get_code(use_pythonrc: bool, imported_objects: "LaunchImports") -> t.Any: + """Launch basic python shell via :mod:`code`.""" import code try: @@ -274,6 +289,7 @@ def launch( use_vi_mode: bool = False, **kwargs: "Unpack[LaunchOptionalImports]", ) -> None: + """Launch interactive libtmux shell for tmuxp shell.""" # Also allowing passing shell='code' to force using code.interact imported_objects = get_launch_args(**kwargs) From 7f4a4ee90f963e7b8adfb76a48fecc08bdb7127c Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 10:14:21 -0600 Subject: [PATCH 75/94] plugin: pydocstyle manual fixes --- src/tmuxp/plugin.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/tmuxp/plugin.py b/src/tmuxp/plugin.py index 48c5791651a..24a1de7d3f8 100644 --- a/src/tmuxp/plugin.py +++ b/src/tmuxp/plugin.py @@ -1,3 +1,4 @@ +"""Plugin system for tmuxp.""" import typing as t import libtmux @@ -34,18 +35,24 @@ from ._types import PluginConfigSchema class VersionConstraints(TypedDict): + """Version constraints mapping for a tmuxp plugin.""" + version: t.Union[Version, str] vmin: str vmax: t.Optional[str] incompatible: t.List[t.Union[t.Any, str]] class TmuxpPluginVersionConstraints(TypedDict): + """Version constraints for a tmuxp plugin.""" + tmux: VersionConstraints tmuxp: VersionConstraints libtmux: VersionConstraints class Config(t.TypedDict): + """tmuxp plugin configuration mapping.""" + plugin_name: str tmux_min_version: str tmux_max_version: t.Optional[str] @@ -73,12 +80,14 @@ class Config(t.TypedDict): def validate_plugin_config(config: "PluginConfigSchema") -> "TypeGuard[Config]": + """Return True if tmuxp plugin configuration valid, also upcasts.""" return isinstance(config, dict) def setup_plugin_config( config: "PluginConfigSchema", default_config: "Config" = DEFAULT_CONFIG ) -> "Config": + """Initialize tmuxp plugin configuration.""" new_config = config.copy() for default_key, default_value in default_config.items(): if default_key not in new_config: @@ -90,6 +99,8 @@ def setup_plugin_config( class TmuxpPlugin: + """Base class for a tmuxp plugin.""" + def __init__(self, **kwargs: "Unpack[PluginConfigSchema]") -> None: """ Initialize plugin. From 5f30d2b362e45506574ed0f203cdc64d921bae8b Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 10:16:00 -0600 Subject: [PATCH 76/94] log: Note pydocstyle updates --- src/tmuxp/log.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/tmuxp/log.py b/src/tmuxp/log.py index 70c385b549f..62baacf0d29 100644 --- a/src/tmuxp/log.py +++ b/src/tmuxp/log.py @@ -32,11 +32,9 @@ def setup_logger( logger: t.Optional[logging.Logger] = None, level: str = "INFO" ) -> None: - """ - Setup logging for CLI use. + """Configure tmuxp's logging for CLI use. - Tries to do some conditionals to prevent handlers from being added twice. - Just to be safe. + Can checks for any existing loggers to prevent loading handlers twice. Parameters ---------- @@ -58,6 +56,7 @@ def set_style( prefix: str = "", suffix: str = "", ) -> str: + """Stylize terminal logging output.""" if stylized: return prefix + style_before + message + style_after + suffix @@ -65,6 +64,8 @@ def set_style( class LogFormatter(logging.Formatter): + """Format logs for tmuxp.""" + def template( self: logging.Formatter, record: logging.LogRecord, @@ -119,6 +120,7 @@ def __init__(self, color: bool = True, **kwargs: t.Any) -> None: logging.Formatter.__init__(self, **kwargs) def format(self, record: logging.LogRecord) -> str: + """Format a log record.""" try: record.message = record.getMessage() except Exception as e: From 2abbaa9aecc2f42ea0b52ae778a2de77dd324055 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 10:19:39 -0600 Subject: [PATCH 77/94] exc: pydocstyle manual fixes --- src/tmuxp/exc.py | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/src/tmuxp/exc.py b/src/tmuxp/exc.py index 4b2fb766228..eff64bc4197 100644 --- a/src/tmuxp/exc.py +++ b/src/tmuxp/exc.py @@ -20,8 +20,13 @@ class WorkspaceError(TmuxpException): class SessionNotFound(TmuxpException): + """tmux session not found.""" + def __init__( - self, session_target: t.Optional[str] = None, *args: object, **kwargs: object + self, + session_target: t.Optional[str] = None, + *args: object, + **kwargs: object, ) -> None: msg = "Session not found" if session_target is not None: @@ -30,8 +35,13 @@ def __init__( class WindowNotFound(TmuxpException): + """tmux window not found.""" + def __init__( - self, window_target: t.Optional[str] = None, *args: object, **kwargs: object + self, + window_target: t.Optional[str] = None, + *args: object, + **kwargs: object, ) -> None: msg = "Window not found" if window_target is not None: @@ -40,8 +50,13 @@ def __init__( class PaneNotFound(TmuxpException): + """tmux pane not found.""" + def __init__( - self, pane_target: t.Optional[str] = None, *args: object, **kwargs: object + self, + pane_target: t.Optional[str] = None, + *args: object, + **kwargs: object, ) -> None: msg = "Pane not found" if pane_target is not None: @@ -52,11 +67,17 @@ def __init__( class EmptyWorkspaceException(WorkspaceError): """Workspace file is empty.""" - def __init__(self, *args: object, **kwargs: object) -> None: + def __init__( + self, + *args: object, + **kwargs: object, + ) -> None: return super().__init__("Session configuration is empty.", *args, **kwargs) class SessionMissingWorkspaceException(WorkspaceError, ObjectDoesNotExist): + """Session missing while loading tmuxp workspace.""" + def __init__(self, *args: object, **kwargs: object) -> None: return super().__init__( "No session object exists for WorkspaceBuilder. " @@ -67,6 +88,8 @@ def __init__(self, *args: object, **kwargs: object) -> None: class ActiveSessionMissingWorkspaceException(WorkspaceError): + """Active session cannot be found while loading tmuxp workspace.""" + def __init__(self, *args: object, **kwargs: object) -> None: return super().__init__("No session active.", *args, **kwargs) @@ -76,6 +99,8 @@ class TmuxpPluginException(TmuxpException): class BeforeLoadScriptNotExists(OSError): + """Raises if shell script could not be found.""" + def __init__(self, *args: object, **kwargs: object) -> None: super().__init__(*args, **kwargs) @@ -84,7 +109,9 @@ def __init__(self, *args: object, **kwargs: object) -> None: @implements_to_string class BeforeLoadScriptError(Exception): - """Exception replacing :py:class:`subprocess.CalledProcessError` for + """Shell script execution error. + + Replaces :py:class:`subprocess.CalledProcessError` for :meth:`tmuxp.util.run_before_script`. """ @@ -102,4 +129,5 @@ def __init__( ) def __str__(self) -> str: + """Return shell error message.""" return self.message From da51f0ce0b91f4545c8d1477464f9269fdbff698 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 10:20:17 -0600 Subject: [PATCH 78/94] config_reader: Note pydocstyle updates --- src/tmuxp/config_reader.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tmuxp/config_reader.py b/src/tmuxp/config_reader.py index df37670a422..6943aff30dc 100644 --- a/src/tmuxp/config_reader.py +++ b/src/tmuxp/config_reader.py @@ -1,3 +1,4 @@ +"""Configuration parser for YAML and JSON files.""" import json import pathlib import typing as t From ac33398b9241c6df257772a32d70b2091e7c6032 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 10:44:36 -0600 Subject: [PATCH 79/94] cli(utils): Note pydocstyle updates --- src/tmuxp/cli/utils.py | 47 +++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/src/tmuxp/cli/utils.py b/src/tmuxp/cli/utils.py index 78f370527c9..4dc861cf6be 100644 --- a/src/tmuxp/cli/utils.py +++ b/src/tmuxp/cli/utils.py @@ -1,3 +1,4 @@ +"""CLI utility helpers for tmuxp.""" import logging import re import typing as t @@ -18,7 +19,7 @@ def tmuxp_echo( log_level: str = "INFO", style_log: bool = False, ) -> None: - """Combines logging.log and click.echo.""" + """Combine logging.log and click.echo.""" if message is None: return @@ -36,14 +37,24 @@ def prompt( value_proc: t.Optional[t.Callable[[str], str]] = None, ) -> str: """Return user input from command line. + + Parameters + ---------- + :param name: prompt text + :param default: default value if no input provided. + + Returns + ------- + str + + See Also + -------- :meth:`~prompt`, :meth:`~prompt_bool` and :meth:`prompt_choices` are from `flask-script`_. See the `flask-script license`_. + .. _flask-script: https://github.com/techniq/flask-script .. _flask-script license: https://github.com/techniq/flask-script/blob/master/LICENSE - :param name: prompt text - :param default: default value if no input provided. - :rtype: string. """ _prompt = name + (default and " [%s]" % default or "") _prompt += name.endswith("?") and " " or ": " @@ -68,12 +79,18 @@ def prompt_bool( yes_choices: t.Optional[t.Sequence[t.Any]] = None, no_choices: t.Optional[t.Sequence[t.Any]] = None, ) -> bool: - """Return user input from command line and converts to boolean value. + """Return True / False by prompting user input from command line. + + Parameters + ---------- :param name: prompt text :param default: default value if no input provided. :param yes_choices: default 'y', 'yes', '1', 'on', 'true', 't' :param no_choices: default 'n', 'no', '0', 'off', 'false', 'f' - :rtype: bool. + + Returns + ------- + bool """ yes_choices = yes_choices or ("y", "yes", "1", "on", "true", "t") no_choices = no_choices or ("n", "no", "0", "off", "false", "f") @@ -110,12 +127,18 @@ def prompt_choices( no_choice: t.Sequence[str] = ("none",), ) -> t.Optional[str]: """Return user input from command line from set of provided choices. + + Parameters + ---------- :param name: prompt text :param choices: list or tuple of available choices. Choices may be single strings or (key, value) tuples. :param default: default value if no input provided. :param no_choice: acceptable list of strings for "null choice" - :rtype: str. + + Returns + ------- + str """ _choices: t.List[str] = [] options: t.List[str] = [] @@ -143,6 +166,7 @@ def prompt_choices( def strip_ansi(value: str) -> str: + """Clear ANSI from a string value.""" return _ansi_re.sub("", value) @@ -182,6 +206,8 @@ def _interpret_color( class UnknownStyleColor(Exception): + """Raised when encountering an unknown terminal style color.""" + def __init__(self, color: "CLIColour", *args: object, **kwargs: object) -> None: return super().__init__(f"Unknown color {color!r}", *args, **kwargs) @@ -241,11 +267,12 @@ def style( def unstyle(text: str) -> str: - """Removes ANSI styling information from a string. Usually it's not - necessary to use this function as tmuxp_echo function will + """Remove ANSI styling information from a string. + + Usually it's not necessary to use this function as tmuxp_echo function will automatically remove styling if necessary. - credit: click. + Credit: click. :param text: the text to remove style information from. """ From db4729ac6cbac38a07046abb741f1f638b085565 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 10:46:16 -0600 Subject: [PATCH 80/94] cli(shell): Note pydocstyle updates --- src/tmuxp/cli/shell.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/tmuxp/cli/shell.py b/src/tmuxp/cli/shell.py index a0087ba3593..f6831d178e4 100644 --- a/src/tmuxp/cli/shell.py +++ b/src/tmuxp/cli/shell.py @@ -1,3 +1,4 @@ +"""CLI for ``tmuxp shell`` subcommand.""" import argparse import os import pathlib @@ -18,6 +19,8 @@ class CLIShellNamespace(argparse.Namespace): + """Typed :class:`argparse.Namespace` for tmuxp shell command.""" + session_name: str socket_name: t.Optional[str] socket_path: t.Optional[str] @@ -31,6 +34,7 @@ class CLIShellNamespace(argparse.Namespace): def create_shell_subparser(parser: argparse.ArgumentParser) -> argparse.ArgumentParser: + """Augment :class:`argparse.ArgumentParser` with ``shell`` subcommand.""" parser.add_argument("session_name", metavar="session-name", nargs="?") parser.add_argument("window_name", metavar="window-name", nargs="?") parser.add_argument( @@ -132,7 +136,7 @@ def command_shell( args: CLIShellNamespace, parser: t.Optional[argparse.ArgumentParser] = None, ) -> None: - """Launch python shell for tmux server, session, window and pane. + """Entrypoint for ``tmuxp shell`` for tmux server, session, window and pane. Priority given to loaded session/window/pane objects: From 1d0937e01aa88b42d710024230befa5e06ecea5f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 10:49:00 -0600 Subject: [PATCH 81/94] cli(ls): Note pydocstyle updates --- src/tmuxp/cli/ls.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tmuxp/cli/ls.py b/src/tmuxp/cli/ls.py index e0447edf32e..d76577741f4 100644 --- a/src/tmuxp/cli/ls.py +++ b/src/tmuxp/cli/ls.py @@ -1,3 +1,4 @@ +"""CLI for ``tmuxp ls`` subcommand.""" import argparse import os import typing as t @@ -9,12 +10,14 @@ def create_ls_subparser( parser: argparse.ArgumentParser, ) -> argparse.ArgumentParser: + """Augment :class:`argparse.ArgumentParser` with ``ls`` subcommand.""" return parser def command_ls( parser: t.Optional[argparse.ArgumentParser] = None, ) -> None: + """Entrypoint for ``tmuxp ls`` subcommand.""" tmuxp_dir = get_workspace_dir() if os.path.exists(tmuxp_dir) and os.path.isdir(tmuxp_dir): for f in sorted(os.listdir(tmuxp_dir)): From acb1c6a70871a173b83371397317f9db803060bd Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 10:52:12 -0600 Subject: [PATCH 82/94] cli(load): pydocstyle manual fixes --- src/tmuxp/cli/load.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/tmuxp/cli/load.py b/src/tmuxp/cli/load.py index 876ba8adf50..4311e87efc4 100644 --- a/src/tmuxp/cli/load.py +++ b/src/tmuxp/cli/load.py @@ -1,9 +1,4 @@ -"""Command line tool for managing tmuxp workspaces. - -tmuxp.cli.load -~~~~~~~~~~~~~~ - -""" +"""CLI for ``tmuxp load`` subcommand.""" import argparse import importlib import logging @@ -31,11 +26,15 @@ CLIColorsLiteral: TypeAlias = t.Literal[56, 88] class OptionOverrides(TypedDict): + """Optional argument overrides for tmuxp load.""" + detached: NotRequired[bool] new_session_name: NotRequired[t.Optional[str]] class CLILoadNamespace(argparse.Namespace): + """Typed :class:`argparse.Namespace` for tmuxp load command.""" + workspace_files: t.List[str] socket_name: t.Optional[str] socket_path: t.Optional[str] @@ -251,8 +250,7 @@ def _load_append_windows_to_current_session(builder: WorkspaceBuilder) -> None: def _setup_plugins(builder: WorkspaceBuilder) -> Session: - """ - Runs after before_script. + """Execute hooks for plugins running after ``before_script``. Parameters ---------- @@ -276,8 +274,7 @@ def load_workspace( answer_yes: bool = False, append: bool = False, ) -> t.Optional[Session]: - """ - Load a tmux "workspace" session via tmuxp file. + """Entrypoint for ``tmuxp load``, load a tmuxp "workspace" session via config file. Parameters ---------- @@ -486,6 +483,7 @@ def load_workspace( def create_load_subparser(parser: argparse.ArgumentParser) -> argparse.ArgumentParser: + """Augment :class:`argparse.ArgumentParser` with ``load`` subcommand.""" workspace_files = parser.add_argument( "workspace_files", nargs="+", From f109a549ef46cd1d3b5c3ee3a253332136524805 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 10:57:05 -0600 Subject: [PATCH 83/94] cli(import_config): Note pydocstyle updates --- src/tmuxp/cli/import_config.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/tmuxp/cli/import_config.py b/src/tmuxp/cli/import_config.py index 0b04d0eccb9..70f4bf71f5e 100644 --- a/src/tmuxp/cli/import_config.py +++ b/src/tmuxp/cli/import_config.py @@ -1,3 +1,4 @@ +"""CLI for ``tmuxp shell`` subcommand.""" import argparse import os import pathlib @@ -12,8 +13,7 @@ def get_tmuxinator_dir() -> pathlib.Path: - """ - Return tmuxinator configuration directory. + """Return tmuxinator configuration directory. Checks for ``TMUXINATOR_CONFIG`` environmental variable. @@ -33,8 +33,7 @@ def get_tmuxinator_dir() -> pathlib.Path: def get_teamocil_dir() -> pathlib.Path: - """ - Return teamocil configuration directory. + """Return teamocil configuration directory. Returns ------- @@ -66,6 +65,7 @@ def command_import( def create_import_subparser( parser: argparse.ArgumentParser, ) -> argparse.ArgumentParser: + """Augment :class:`argparse.ArgumentParser` with ``import`` subparser.""" importsubparser = parser.add_subparsers( title="commands", description="valid commands", help="additional help" ) @@ -117,7 +117,10 @@ def create_import_subparser( class ImportConfigFn(t.Protocol): + """Typing for import configuration callback function.""" + def __call__(self, workspace_dict: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]: + """Execute tmuxp import function.""" ... @@ -126,6 +129,7 @@ def import_config( importfunc: ImportConfigFn, parser: t.Optional[argparse.ArgumentParser] = None, ) -> None: + """Import a configuration from a workspace_file.""" existing_workspace_file = ConfigReader._from_file(pathlib.Path(workspace_file)) cfg_reader = ConfigReader(importfunc(existing_workspace_file)) @@ -175,7 +179,9 @@ def command_import_tmuxinator( workspace_file: str, parser: t.Optional[argparse.ArgumentParser] = None, ) -> None: - """Convert a tmuxinator config from workspace_file to tmuxp format and import + """Entrypoint for ``tmuxp import tmuxinator`` subcommand. + + Converts a tmuxinator config from workspace_file to tmuxp format and import it into tmuxp. """ workspace_file = find_workspace_file( @@ -188,7 +194,9 @@ def command_import_teamocil( workspace_file: str, parser: t.Optional[argparse.ArgumentParser] = None, ) -> None: - """Convert a teamocil config from workspace_file to tmuxp format and import + """Entrypoint for ``tmuxp import teamocil`` subcommand. + + Convert a teamocil config from workspace_file to tmuxp format and import it into tmuxp. """ workspace_file = find_workspace_file( From d4eb1f24cf027fbee62da9e73b59eeba9dae8c79 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 10:59:20 -0600 Subject: [PATCH 84/94] cli(freeze): Note pydocstyle updates --- src/tmuxp/cli/freeze.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/tmuxp/cli/freeze.py b/src/tmuxp/cli/freeze.py index fa76a652a77..f82dbb10329 100644 --- a/src/tmuxp/cli/freeze.py +++ b/src/tmuxp/cli/freeze.py @@ -1,3 +1,4 @@ +"""CLI for ``tmuxp freeze`` subcommand.""" import argparse import os import pathlib @@ -21,6 +22,8 @@ class CLIFreezeNamespace(argparse.Namespace): + """Typed :class:`argparse.Namespace` for tmuxp freeze command.""" + session_name: str socket_name: t.Optional[str] socket_path: t.Optional[str] @@ -34,6 +37,7 @@ class CLIFreezeNamespace(argparse.Namespace): def create_freeze_subparser( parser: argparse.ArgumentParser, ) -> argparse.ArgumentParser: + """Augment :class:`argparse.ArgumentParser` with ``freeze`` subcommand.""" parser.add_argument( dest="session_name", metavar="session-name", @@ -87,10 +91,10 @@ def command_freeze( args: CLIFreezeNamespace, parser: t.Optional[argparse.ArgumentParser] = None, ) -> None: - """Snapshot a tmux session into a tmuxp workspace. + """Entrypoint for ``tmuxp freeze``, snapshot a tmux session into a tmuxp workspace. - If SESSION_NAME is provided, snapshot that session. Otherwise, use the - current session. + If SESSION_NAME is provided, snapshot that session. Otherwise, use the current + session. """ server = Server(socket_name=args.socket_name, socket_path=args.socket_path) From 1811a9f99abffe7659d8bca25a3a88fd144057aa Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 11:00:26 -0600 Subject: [PATCH 85/94] cli(edit): Note pydocstyle updates --- src/tmuxp/cli/edit.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tmuxp/cli/edit.py b/src/tmuxp/cli/edit.py index 31b263dd362..f18a63bef3f 100644 --- a/src/tmuxp/cli/edit.py +++ b/src/tmuxp/cli/edit.py @@ -1,3 +1,4 @@ +"""CLI for ``tmuxp edit`` subcommand.""" import argparse import os import pathlib @@ -10,6 +11,7 @@ def create_edit_subparser( parser: argparse.ArgumentParser, ) -> argparse.ArgumentParser: + """Augment :class:`argparse.ArgumentParser` with ``edit`` subcommand.""" parser.add_argument( dest="workspace_file", metavar="workspace-file", @@ -23,6 +25,7 @@ def command_edit( workspace_file: t.Union[str, pathlib.Path], parser: t.Optional[argparse.ArgumentParser] = None, ) -> None: + """Entrypoint for ``tmuxp edit``, open tmuxp workspace file in system editor.""" workspace_file = find_workspace_file(workspace_file) sys_editor = os.environ.get("EDITOR", "vim") From 788617fc684db50bdf711593d1a33e73a0f9be14 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 11:01:26 -0600 Subject: [PATCH 86/94] cli(debug-info): Note pydocstyle updates --- src/tmuxp/cli/debug_info.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tmuxp/cli/debug_info.py b/src/tmuxp/cli/debug_info.py index 386584612f9..d6b06618bb8 100644 --- a/src/tmuxp/cli/debug_info.py +++ b/src/tmuxp/cli/debug_info.py @@ -1,3 +1,4 @@ +"""CLI for ``tmuxp debug-info`` subcommand.""" import argparse import os import pathlib @@ -19,13 +20,14 @@ def create_debug_info_subparser( parser: argparse.ArgumentParser, ) -> argparse.ArgumentParser: + """Augment :class:`argparse.ArgumentParser` with ``debug-info`` subcommand.""" return parser def command_debug_info( parser: t.Optional[argparse.ArgumentParser] = None, ) -> None: - """Print debug info to submit with Issues.""" + """Entrypoint for ``tmuxp debug-info`` to print debug info to submit with issues.""" def prepend_tab(strings: t.List[str]) -> t.List[str]: """Prepend tab to strings in list.""" From 184ef8ddbc805c22d38b3a75dfdd6705e01c2052 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 11:02:45 -0600 Subject: [PATCH 87/94] cli(convert): Note pydocstyle updates --- src/tmuxp/cli/convert.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/tmuxp/cli/convert.py b/src/tmuxp/cli/convert.py index e0e2a2c03a1..88d995d67d6 100644 --- a/src/tmuxp/cli/convert.py +++ b/src/tmuxp/cli/convert.py @@ -1,3 +1,4 @@ +"""CLI for ``tmuxp convert`` subcommand.""" import argparse import os import pathlib @@ -16,6 +17,7 @@ def create_convert_subparser( parser: argparse.ArgumentParser, ) -> argparse.ArgumentParser: + """Augment :class:`argparse.ArgumentParser` with ``convert`` subcommand.""" workspace_file = parser.add_argument( dest="workspace_file", type=str, @@ -40,6 +42,8 @@ def create_convert_subparser( class ConvertUnknownFileType(exc.TmuxpException): + """Raise if tmuxp convert encounters an unknown filetype.""" + def __init__(self, ext: str, *args: object, **kwargs: object) -> None: return super().__init__( f"Unknown filetype: {ext} (valid: [.json, .yaml, .yml])" @@ -51,7 +55,7 @@ def command_convert( answer_yes: bool, parser: t.Optional[argparse.ArgumentParser] = None, ) -> None: - """Convert a tmuxp config between JSON and YAML.""" + """Entrypoint for ``tmuxp convert`` convert a tmuxp config between JSON and YAML.""" workspace_file = find_workspace_file( workspace_file, workspace_dir=get_workspace_dir() ) From 2bf573806281633438f175bfa595ba9c39624c25 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 11:03:56 -0600 Subject: [PATCH 88/94] cli: pydocstyle manual fixes --- src/tmuxp/cli/__init__.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/tmuxp/cli/__init__.py b/src/tmuxp/cli/__init__.py index d55cae760f8..0d1e6d2d388 100644 --- a/src/tmuxp/cli/__init__.py +++ b/src/tmuxp/cli/__init__.py @@ -1,9 +1,4 @@ -"""CLI utilities for tmuxp. - -tmuxp.cli -~~~~~~~~~ - -""" +"""CLI utilities for tmuxp.""" import argparse import logging import os @@ -45,6 +40,7 @@ def create_parser() -> argparse.ArgumentParser: + """Create CLI :class:`argparse.ArgumentParser` for tmuxp.""" parser = argparse.ArgumentParser(prog="tmuxp") parser.add_argument( "--version", @@ -97,6 +93,8 @@ def create_parser() -> argparse.ArgumentParser: class CLINamespace(argparse.Namespace): + """Typed :class:`argparse.Namespace` for tmuxp root-level CLI.""" + log_level: "CLIVerbosity" subparser_name: "CLISubparserName" import_subparser_name: t.Optional["CLIImportSubparserName"] From f14f0702d2e36a9892d56a822d58aeaac631501c Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 11:04:27 -0600 Subject: [PATCH 89/94] _types: Note pydocstyle updates --- src/tmuxp/_types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tmuxp/_types.py b/src/tmuxp/_types.py index 6ea5e0c75cc..7e3eb7d7229 100644 --- a/src/tmuxp/_types.py +++ b/src/tmuxp/_types.py @@ -1,4 +1,4 @@ -"""Internal, :const:`typing.TYPE_CHECKING` guarded :term:`type annotations `. +"""Internal, :const:`typing.TYPE_CHECKING` guarded :term:`typings `. These are _not_ to be imported at runtime as `typing_extensions` is not bundled with tmuxp. Usage example: From 8aff08cee3b5efdc279e7da9053ca04c8b5dbdd5 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 11:05:32 -0600 Subject: [PATCH 90/94] __about__: Note pydocstyle updates --- src/tmuxp/__about__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tmuxp/__about__.py b/src/tmuxp/__about__.py index 2b798fbdf6d..2b7f6a77e59 100644 --- a/src/tmuxp/__about__.py +++ b/src/tmuxp/__about__.py @@ -1,3 +1,4 @@ +"""Metadata for tmuxp package.""" __title__ = "tmuxp" __package_name__ = "tmuxp" __version__ = "1.32.1" From 791caede4fef1f3aeb4adc43e33637cfed9dea73 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 11:06:20 -0600 Subject: [PATCH 91/94] docs(conf): Note pydocstyle updates --- docs/conf.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 1ccd14f3f84..bddd5b1f8ec 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,5 @@ # flake8: NOQA: E501 +"""Sphinx documentation configuration for tmuxp.""" import contextlib import inspect import pathlib @@ -212,7 +213,7 @@ def linkcode_resolve(domain: str, info: t.Dict[str, str]) -> t.Union[None, str]: def remove_tabs_js(app: "Sphinx", exc: Exception) -> None: - # Fix for sphinx-inline-tabs#18 + """Fix for sphinx-inline-tabs#18.""" if app.builder.format == "html" and not exc: tabs_js = pathlib.Path(app.builder.outdir) / "_static" / "tabs.js" with contextlib.suppress(FileNotFoundError): @@ -220,4 +221,5 @@ def remove_tabs_js(app: "Sphinx", exc: Exception) -> None: def setup(app: "Sphinx") -> None: + """Sphinx setup hook.""" app.connect("build-finished", remove_tabs_js) From 893c15e377cdd034eed18b702e83f741022726c6 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 11:06:57 -0600 Subject: [PATCH 92/94] docs(aafig): Note pydocstyle updates --- docs/_ext/aafig.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/_ext/aafig.py b/docs/_ext/aafig.py index 0a5df9bacc1..b0f0b284cc1 100644 --- a/docs/_ext/aafig.py +++ b/docs/_ext/aafig.py @@ -1,4 +1,5 @@ -""" +"""aafig plugin for sphinx. + sphinxcontrib.aafig. ~~~~~~~~~~~~~~~~~~~ From b97f98a79becc452bf2a78917720cd4d9db9b0bb Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 11:11:09 -0600 Subject: [PATCH 93/94] conftest: pydocstyle manual fixes --- conftest.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/conftest.py b/conftest.py index 9239dc22b85..c8fa6dfb700 100644 --- a/conftest.py +++ b/conftest.py @@ -1,8 +1,13 @@ """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. +as avoiding conftest.py from being included in the wheel, in addition to pytest_plugin +for pytester only being available via the root directory. + +See "pytest_plugins in non-top-level conftest files" in +https://docs.pytest.org/en/stable/deprecations.html """ + import logging import os import pathlib @@ -26,7 +31,7 @@ @pytest.mark.skipif(not USING_ZSH, reason="Using ZSH") @pytest.fixture(autouse=USING_ZSH, scope="session") def zshrc(user_path: pathlib.Path) -> pathlib.Path: - """This quiets ZSH default message. + """Quiets ZSH default message. Needs a startup file .zshenv, .zprofile, .zshrc, .zlogin. """ @@ -37,11 +42,13 @@ def zshrc(user_path: pathlib.Path) -> pathlib.Path: @pytest.fixture(autouse=True) def home_path_default(monkeypatch: pytest.MonkeyPatch, user_path: pathlib.Path) -> None: + """Set HOME to user_path (random, temporary directory).""" monkeypatch.setenv("HOME", str(user_path)) @pytest.fixture def tmuxp_configdir(user_path: pathlib.Path) -> pathlib.Path: + """Ensure and return tmuxp config directory.""" xdg_config_dir = user_path / ".config" xdg_config_dir.mkdir(exist_ok=True) @@ -54,12 +61,14 @@ def tmuxp_configdir(user_path: pathlib.Path) -> pathlib.Path: def tmuxp_configdir_default( monkeypatch: pytest.MonkeyPatch, tmuxp_configdir: pathlib.Path ) -> None: + """Set tmuxp configuration directory for ``TMUXP_CONFIGDIR``.""" monkeypatch.setenv("TMUXP_CONFIGDIR", str(tmuxp_configdir)) assert get_workspace_dir() == str(tmuxp_configdir) @pytest.fixture(scope="function") def monkeypatch_plugin_test_packages(monkeypatch: pytest.MonkeyPatch) -> None: + """Monkeypatch tmuxp plugin fixtures to python path.""" paths = [ "tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bwb/", "tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bs/", @@ -74,12 +83,14 @@ def monkeypatch_plugin_test_packages(monkeypatch: pytest.MonkeyPatch) -> None: @pytest.fixture(scope="function") def session_params(session_params: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]: + """Terminal-friendly tmuxp session_params for dimensions.""" session_params.update({"x": 800, "y": 600}) return session_params @pytest.fixture(scope="function") def socket_name(request: pytest.FixtureRequest) -> str: + """Random socket name for tmuxp.""" return "tmuxp_test%s" % next(namer) @@ -89,6 +100,7 @@ def add_doctest_fixtures( doctest_namespace: t.Dict[str, t.Any], tmp_path: pathlib.Path, ) -> None: + """Harness pytest fixtures to doctests namespace.""" if isinstance(request._pyfuncitem, DoctestItem) and shutil.which("tmux"): doctest_namespace["server"] = request.getfixturevalue("server") session: "Session" = request.getfixturevalue("session") From f8055cbbefa1eab368851734687d10f0cfa5b796 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 21 Dec 2023 11:12:12 -0600 Subject: [PATCH 94/94] docs(CHANGES): Note pydocstyle updates --- CHANGES | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES b/CHANGES index 17416adea74..738d8c0b2ee 100644 --- a/CHANGES +++ b/CHANGES @@ -22,6 +22,11 @@ $ pipx install --suffix=@next 'tmuxp' --pip-args '\--pre' --force ### CI - Move CodeQL from advanced configuration file to GitHub's default +- Add pydocstyle rule to ruff (#891) + +### Documentation + +- Add docstrings to functions, methods, classes, and packages (#891) ## tmuxp 1.32.1 (2023-11-23)