diff --git a/CHANGES b/CHANGES index 9213addd0..a757793f5 100644 --- a/CHANGES +++ b/CHANGES @@ -44,6 +44,29 @@ _Upcoming changes will be written here._ - Fix incorrect return type annotations for `capture_pane()` and `display_message()` methods (changed from `str | list[str]` to `list[str]` - the methods always return a list). +#### APIs deprecated (#611) + +Legacy API methods (deprecated in 0.16-0.33) now raise {exc}`~libtmux.exc.DeprecatedError` (hard error) instead of emitting {class}`DeprecationWarning`. + +See {doc}`migration` for full context and examples. + +| Deprecated API | Replacement | Deprecated | Raises | Note | +|----------------|-------------|------------|--------|------| +| `kill_server()` | {meth}`~libtmux.Server.kill` | 0.30.0 | 0.51.0 | Server | +| `attach_session()`, `kill_session()` | {meth}`~libtmux.Session.attach`, {meth}`~libtmux.Session.kill` | 0.30.0 | 0.51.0 | Session | +| `select_window()`, `kill_window()`, `split_window()` | {meth}`~libtmux.Window.select`, {meth}`~libtmux.Window.kill`, {meth}`~libtmux.Window.split` | 0.30.0 / 0.33.0 | 0.51.0 | Window | +| `resize_pane()`, `select_pane()`, `split_window()` | {meth}`~libtmux.Pane.resize`, {meth}`~libtmux.Pane.select`, {meth}`~libtmux.Pane.split` | 0.28.0 / 0.30.0 / 0.33.0 | 0.51.0 | Pane | +| `attached_window`, `attached_pane` | {attr}`~libtmux.Session.active_window`, {attr}`~libtmux.Session.active_pane` / {attr}`~libtmux.Window.active_pane` | 0.31.0 | 0.51.0 | Session/Window | +| `list_*()`, `_list_*()`, `_update_*()`, `children`, `where()`, `find_where()`, `get_by_id()` | {attr}`~libtmux.Server.sessions` / {attr}`~libtmux.Session.windows` / {attr}`~libtmux.Window.panes` with {meth}`~libtmux.common.QueryList.filter` / {meth}`~libtmux.common.QueryList.get` | 0.16.0 / 0.17.0 | 0.51.0 | Query/filter helpers | +| Dict-style access (`obj["key"]`, `obj.get(...)`) | Attribute access (e.g., {attr}`~libtmux.window.Window.window_name`) | 0.17.0 | 0.51.0 | All tmux objects | + +The following deprecations from 0.50.0 continue to emit {class}`DeprecationWarning` (soft deprecation): + +| Deprecated API | Replacement | Deprecated | Note | +|----------------|-------------|------------|------| +| `set_window_option()`, `show_window_option()`, `show_window_options()` | {meth}`~libtmux.window.Window.set_option`, {meth}`~libtmux.window.Window.show_option`, {meth}`~libtmux.window.Window.show_options` | 0.50.0 | Window | +| `g` parameter on options/hooks methods | `global_` on {meth}`~libtmux.options.OptionsMixin.set_option`, {meth}`~libtmux.options.OptionsMixin.show_option`, {meth}`~libtmux.options.OptionsMixin.show_options` | 0.50.0 | Options & hooks | + ## libtmux 0.50.0 (2025-11-30) ### Overview diff --git a/MIGRATION b/MIGRATION index a983d061b..123b0cdcf 100644 --- a/MIGRATION +++ b/MIGRATION @@ -19,6 +19,94 @@ well. [tracker]: https://github.com/tmux-python/libtmux/discussions ``` +## Complete Deprecation Reference + +This table provides a quick reference for all deprecated APIs. See version-specific +sections below for detailed migration examples and code samples. + +### Method Renamings + +| Class | Deprecated | Replacement | Since | Raises | +|-------|------------|-------------|-------|--------| +| Server | `kill_server()` | `kill()` | 0.30.0 (2024-02-16) | 0.51.0 | +| Session | `attach_session()` | `attach()` | 0.30.0 (2024-02-16) | 0.51.0 | +| Session | `kill_session()` | `kill()` | 0.30.0 (2024-02-16) | 0.51.0 | +| Window | `select_window()` | `select()` | 0.30.0 (2024-02-16) | 0.51.0 | +| Window | `kill_window()` | `kill()` | 0.30.0 (2024-02-16) | 0.51.0 | +| Window | `split_window()` | `split()` | 0.33.0 (2024-03-17) | 0.51.0 | +| Window | `set_window_option()` | `set_option()` | 0.50.0 (2025-11-30) | _(warning)_ | +| Window | `show_window_option()` | `show_option()` | 0.50.0 (2025-11-30) | _(warning)_ | +| Window | `show_window_options()` | `show_options()` | 0.50.0 (2025-11-30) | _(warning)_ | +| Pane | `select_pane()` | `select()` | 0.30.0 (2024-02-16) | 0.51.0 | +| Pane | `resize_pane()` | `resize()` | 0.28.0 (2024-02-14) | 0.51.0 | +| Pane | `split_window()` | `split()` | 0.33.0 (2024-03-17) | 0.51.0 | + +### Property Renamings + +| Class | Deprecated | Replacement | Since | Raises | +|-------|------------|-------------|-------|--------| +| Session | `attached_window` | `active_window` | 0.31.0 (2024-02-17) | 0.51.0 | +| Session | `attached_pane` | `active_pane` | 0.31.0 (2024-02-17) | 0.51.0 | +| Window | `attached_pane` | `active_pane` | 0.31.0 (2024-02-17) | 0.51.0 | + +### Parameter Changes + +| Method(s) | Deprecated | Replacement | Since | Raises | +|-----------|------------|-------------|-------|--------| +| Options/hooks methods | `g` | `global_` | 0.50.0 (2025-11-30) | _(warning)_ | +| `split_window()` / `split()` | `percent` | `size` | 0.28.0 (2024-02-14) | 0.51.0 | +| `split_window()` / `split()` | `vertical`/`horizontal` | `direction` (PaneDirection) | 0.33.0 (2024-03-17) | 0.51.0 | +| `resize_pane()` | `-U`, `-D`, `-L`, `-R` | `adjustment_direction` | 0.28.0 (2024-02-14) | 0.51.0 | +| `Server.get_by_id()` | `id` | `session_id` | 0.16.0 (2022-12-10) | 0.51.0 | +| `Session.get_by_id()` | `id` | `window_id` | 0.16.0 (2022-12-10) | 0.51.0 | +| `Window.get_by_id()` | `id` | `pane_id` | 0.16.0 (2022-12-10) | 0.51.0 | + +### Query/Filter API Changes + +| Class | Deprecated | Replacement | Since | Raises | +|-------|------------|-------------|-------|--------| +| Server | `list_sessions()` / `_list_sessions()` | `sessions` property | 0.17.0 (2022-12-26) | 0.51.0 | +| Server | `where({...})` | `sessions.filter(**kwargs)` | 0.17.0 (2022-12-26) | 0.51.0 | +| Server | `find_where({...})` | `sessions.get(default=None, **kwargs)` | 0.17.0 (2022-12-26) | 0.51.0 | +| Server | `_list_panes()` / `_update_panes()` | `panes` property | 0.17.0 (2022-12-26) | 0.51.0 | +| Server | `_list_windows()` / `_update_windows()` | `windows` property | 0.17.0 (2022-12-26) | 0.51.0 | +| Server | `get_by_id(id)` | `sessions.get(session_id=..., default=None)` | 0.16.0 (2022-12-10) | 0.51.0 | +| Session | `list_windows()` / `_list_windows()` | `windows` property | 0.17.0 (2022-12-26) | 0.51.0 | +| Session | `where({...})` | `windows.filter(**kwargs)` | 0.17.0 (2022-12-26) | 0.51.0 | +| Session | `find_where({...})` | `windows.get(default=None, **kwargs)` | 0.17.0 (2022-12-26) | 0.51.0 | +| Session | `get_by_id(id)` | `windows.get(window_id=..., default=None)` | 0.16.0 (2022-12-10) | 0.51.0 | +| Window | `list_panes()` / `_list_panes()` | `panes` property | 0.17.0 (2022-12-26) | 0.51.0 | +| Window | `where({...})` | `panes.filter(**kwargs)` | 0.17.0 (2022-12-26) | 0.51.0 | +| Window | `find_where({...})` | `panes.get(default=None, **kwargs)` | 0.17.0 (2022-12-26) | 0.51.0 | +| Window | `get_by_id(id)` | `panes.get(pane_id=..., default=None)` | 0.16.0 (2022-12-10) | 0.51.0 | +| All | `children` property | `sessions`/`windows`/`panes` | 0.17.0 (2022-12-26) | 0.51.0 | + +### Attribute Access Changes + +| Pattern | Deprecated | Replacement | Since | Raises | +|---------|------------|-------------|-------|--------| +| Dict key access | `obj['key']` | `obj.key` | 0.17.0 (2022-12-26) | 0.51.0 | +| Dict get | `obj.get('key')` | `obj.key` | 0.17.0 (2022-12-26) | 0.51.0 | +| Dict get w/ default | `obj.get('key', None)` | `getattr(obj, 'key', None)` | 0.17.0 (2022-12-26) | 0.51.0 | + +### Removed Items + +| Item | Removed In | Migration | +|------|------------|-----------| +| tmux < 3.2a support | 0.49.0 (2025-11-29) | Upgrade tmux or use libtmux 0.48.x | +| `console_to_str()` | 0.42.0 (2025-02-02) | Use `text=True` in subprocess | +| `str_from_console()` | 0.42.0 (2025-02-02) | Use `text=True` in subprocess | +| `common.which()` | 0.12.0 (2022-07-13) | Use `shutil.which()` | + +### Default Behavior Changes + +| Method | Old Default | New Default | Since | +|--------|-------------|-------------|-------| +| `Session.new_window()` | `attach=True` | `attach=False` | 0.28.0 (2024-02-14) | +| `Window.split_window()` | `attach=True` | `attach=False` | 0.28.0 (2024-02-14) | + +--- + ## Upcoming Release _Detailed migration steps for the next version will be posted here._ diff --git a/src/libtmux/exc.py b/src/libtmux/exc.py index c5363b5ef..6a47b247c 100644 --- a/src/libtmux/exc.py +++ b/src/libtmux/exc.py @@ -19,6 +19,35 @@ class LibTmuxException(Exception): """Base Exception for libtmux Errors.""" +class DeprecatedError(LibTmuxException): + """Raised when a deprecated function, method, or parameter is used. + + This exception provides clear guidance on what to use instead. + + Parameters + ---------- + deprecated : str + The name of the deprecated API (e.g., "Pane.resize_pane()") + replacement : str + The recommended replacement API to use instead + version : str + The version when the API was deprecated (e.g., "0.28.0") + """ + + def __init__( + self, + *, + deprecated: str, + replacement: str, + version: str, + ) -> None: + msg = ( + f"{deprecated} was deprecated in {version} and has been removed. " + f"Use {replacement} instead." + ) + super().__init__(msg) + + class TmuxSessionExists(LibTmuxException): """Session does not exist in the server.""" diff --git a/src/libtmux/options.py b/src/libtmux/options.py index 0e6825d33..681b16575 100644 --- a/src/libtmux/options.py +++ b/src/libtmux/options.py @@ -797,8 +797,9 @@ def _show_options_raw( Parameters ---------- - g : str, optional - Pass ``-g`` flag for global variable, default False. + g : bool, optional + .. deprecated:: 0.50.0 + Use ``global_`` instead. Examples -------- @@ -834,8 +835,9 @@ def _show_options_raw( category=DeprecationWarning, stacklevel=2, ) - flags += ("-g",) - elif global_: + global_ = g + + if global_: flags += ("-g",) if scope is not None and not isinstance(scope, _DefaultOptionScope): @@ -864,8 +866,9 @@ def _show_options_dict( Parameters ---------- - g : str, optional - Pass ``-g`` flag for global variable, default False. + g : bool, optional + .. deprecated:: 0.50.0 + Use ``global_`` instead. Examples -------- @@ -913,8 +916,9 @@ def _show_options( Parameters ---------- - g : str, optional - Pass ``-g`` flag for global variable, default False. + g : bool, optional + .. deprecated:: 0.50.0 + Use ``global_`` instead. Examples -------- @@ -1013,7 +1017,8 @@ def _show_option_raw( ---------- option : str g : bool, optional - Pass ``-g`` flag, global. Default False. + .. deprecated:: 0.50.0 + Use ``global_`` instead. Raises ------ @@ -1063,8 +1068,9 @@ def _show_option_raw( category=DeprecationWarning, stacklevel=2, ) - flags += ("-g",) - elif global_: + global_ = g + + if global_: flags += ("-g",) if scope is not None and not isinstance(scope, _DefaultOptionScope): @@ -1104,7 +1110,8 @@ def _show_option( ---------- option : str g : bool, optional - Pass ``-g`` flag, global. Default False. + .. deprecated:: 0.50.0 + Use ``global_`` instead. Raises ------ @@ -1206,7 +1213,8 @@ def show_option( ---------- option : str g : bool, optional - Pass ``-g`` flag, global. Default False. + .. deprecated:: 0.50.0 + Use ``global_`` instead. Raises ------ diff --git a/src/libtmux/pane.py b/src/libtmux/pane.py index 40964f39f..b6cef7981 100644 --- a/src/libtmux/pane.py +++ b/src/libtmux/pane.py @@ -11,7 +11,6 @@ import logging import pathlib import typing as t -import warnings from libtmux import exc from libtmux.common import tmux_cmd @@ -554,16 +553,11 @@ def select_pane(self) -> Pane: Deprecated in favor of :meth:`.select()`. """ - warnings.warn( - "Pane.select_pane() is deprecated in favor of Pane.select()", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Pane.select_pane()", + replacement="Pane.select()", + version="0.30.0", ) - assert isinstance(self.pane_id, str) - pane = self.window.select_pane(self.pane_id) - if pane is None: - raise exc.PaneNotFound(pane_id=self.pane_id) - return pane def split( self, @@ -731,7 +725,7 @@ def set_width(self, width: int) -> Pane: :class:`Pane` Self, for method chaining. """ - self.resize_pane(width=width) + self.resize(width=width) return self def set_height(self, height: int) -> Pane: @@ -747,7 +741,7 @@ def set_height(self, height: int) -> Pane: :class:`Pane` Self, for method chaining. """ - self.resize_pane(height=height) + self.resize(height=height) return self def enter(self) -> Pane: @@ -915,54 +909,41 @@ def split_window( Deprecated in favor of :meth:`.split`. """ - warnings.warn( - "Pane.split_window() is deprecated in favor of Pane.split()", - category=DeprecationWarning, - stacklevel=2, - ) - if size is None and percent is not None: - size = f"{str(percent).rstrip('%')}%" - return self.split( - target=target, - attach=attach, - start_directory=start_directory, - direction=PaneDirection.Below if vertical else PaneDirection.Right, - shell=shell, - size=size, - environment=environment, + raise exc.DeprecatedError( + deprecated="Pane.split_window()", + replacement="Pane.split()", + version="0.33.0", ) def get(self, key: str, default: t.Any | None = None) -> t.Any: """Return key-based lookup. Deprecated by attributes. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Deprecated by attribute lookup, e.g. ``pane['window_name']`` is now accessed via ``pane.window_name``. """ - warnings.warn( - "Pane.get() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Pane.get()", + replacement="direct attribute access (e.g., pane.pane_id)", + version="0.17.0", ) - return getattr(self, key, default) def __getitem__(self, key: str) -> t.Any: """Return item lookup by key. Deprecated in favor of attributes. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Deprecated in favor of attributes. e.g. ``pane['window_name']`` is now accessed via ``pane.window_name``. """ - warnings.warn( - f"Item lookups, e.g. pane['{key}'] is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Pane[key] lookup", + replacement="direct attribute access (e.g., pane.pane_id)", + version="0.17.0", ) - return getattr(self, key) def resize_pane( self, @@ -985,17 +966,8 @@ def resize_pane( Deprecated by :meth:`Pane.resize`. """ - warnings.warn( - "Deprecated: Use Pane.resize() instead of Pane.resize_pane()", - category=DeprecationWarning, - stacklevel=2, - ) - return self.resize( - adjustment_direction=adjustment_direction, - adjustment=adjustment, - height=height, - width=width, - zoom=zoom, - mouse=mouse, - trim_below=trim_below, + raise exc.DeprecatedError( + deprecated="Pane.resize_pane()", + replacement="Pane.resize()", + version="0.28.0", ) diff --git a/src/libtmux/server.py b/src/libtmux/server.py index b09c58c50..71f9f84a7 100644 --- a/src/libtmux/server.py +++ b/src/libtmux/server.py @@ -13,7 +13,6 @@ import shutil import subprocess import typing as t -import warnings from libtmux import exc, formats from libtmux._internal.query_list import QueryList @@ -694,12 +693,11 @@ def kill_server(self) -> None: Deprecated in favor of :meth:`.kill()`. """ - warnings.warn( - "Server.kill_server() is deprecated in favor of Server.kill()", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Server.kill_server()", + replacement="Server.kill()", + version="0.30.0", ) - self.cmd("kill-server") def _list_panes(self) -> list[PaneDict]: """Return list of panes in :py:obj:`dict` form. @@ -709,22 +707,21 @@ def _list_panes(self) -> list[PaneDict]: The :py:obj:`list` is derived from ``stdout`` in :class:`util.tmux_cmd` which wraps :py:class:`subprocess.Popen`. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Deprecated in favor of :attr:`.panes`. """ - warnings.warn( - "Server._list_panes() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Server._list_panes()", + replacement="Server.panes property", + version="0.17.0", ) - return [p.__dict__ for p in self.panes] def _update_panes(self) -> Server: """Update internal pane data and return ``self`` for chainability. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Deprecated in favor of :attr:`.panes` and returning ``self``. @@ -732,13 +729,11 @@ def _update_panes(self) -> Server: ------- :class:`Server` """ - warnings.warn( - "Server._update_panes() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Server._update_panes()", + replacement="Server.panes property", + version="0.17.0", ) - self._list_panes() - return self def get_by_id(self, session_id: str) -> Session | None: """Return session by id. Deprecated in favor of :meth:`.sessions.get()`. @@ -748,45 +743,39 @@ def get_by_id(self, session_id: str) -> Session | None: Deprecated by :meth:`.sessions.get()`. """ - warnings.warn( - "Server.get_by_id() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Server.get_by_id()", + replacement="Server.sessions.get(session_id=..., default=None)", + version="0.16.0", ) - return self.sessions.get(session_id=session_id, default=None) def where(self, kwargs: dict[str, t.Any]) -> list[Session]: """Filter through sessions, return list of :class:`Session`. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Deprecated by :meth:`.session.filter()`. """ - warnings.warn( - "Server.find_where() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Server.where()", + replacement="Server.sessions.filter()", + version="0.17.0", ) - try: - return self.sessions.filter(**kwargs) - except IndexError: - return [] def find_where(self, kwargs: dict[str, t.Any]) -> Session | None: """Filter through sessions, return first :class:`Session`. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Slated to be removed in favor of :meth:`.sessions.get()`. """ - warnings.warn( - "Server.find_where() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Server.find_where()", + replacement="Server.sessions.get(default=None, **kwargs)", + version="0.17.0", ) - return self.sessions.get(default=None, **kwargs) def _list_windows(self) -> list[WindowDict]: """Return list of windows in :py:obj:`dict` form. @@ -796,68 +785,63 @@ def _list_windows(self) -> list[WindowDict]: The :py:obj:`list` is derived from ``stdout`` in :class:`common.tmux_cmd` which wraps :py:class:`subprocess.Popen`. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Slated to be removed in favor of :attr:`.windows`. """ - warnings.warn( - "Server._list_windows() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Server._list_windows()", + replacement="Server.windows property", + version="0.17.0", ) - return [w.__dict__ for w in self.windows] def _update_windows(self) -> Server: """Update internal window data and return ``self`` for chainability. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Deprecated in favor of :attr:`.windows` and returning ``self``. """ - warnings.warn( - "Server._update_windows() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Server._update_windows()", + replacement="Server.windows property", + version="0.17.0", ) - self._list_windows() - return self @property def _sessions(self) -> list[SessionDict]: """Property / alias to return :meth:`~._list_sessions`. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Slated to be removed in favor of :attr:`.sessions`. """ - warnings.warn( - "Server._sessions is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Server._sessions", + replacement="Server.sessions property", + version="0.17.0", ) - return self._list_sessions() def _list_sessions(self) -> list[SessionDict]: """Return list of session object dictionaries. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Slated to be removed in favor of :attr:`.sessions`. """ - warnings.warn( - "Server._list_sessions() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Server._list_sessions()", + replacement="Server.sessions property", + version="0.17.0", ) - return [s.__dict__ for s in self.sessions] def list_sessions(self) -> list[Session]: """Return list of :class:`Session` from the ``tmux(1)`` session. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Slated to be removed in favor of :attr:`.sessions`. @@ -865,25 +849,23 @@ def list_sessions(self) -> list[Session]: ------- list of :class:`Session` """ - warnings.warn( - "Server.list_sessions is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Server.list_sessions()", + replacement="Server.sessions property", + version="0.17.0", ) - return self.sessions @property def children(self) -> QueryList[Session]: """Was used by TmuxRelationalObject (but that's longer used in this class). - .. deprecated:: 0.16 + .. deprecated:: 0.17 Slated to be removed in favor of :attr:`.sessions`. """ - warnings.warn( - "Server.children is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Server.children", + replacement="Server.sessions property", + version="0.17.0", ) - return self.sessions diff --git a/src/libtmux/session.py b/src/libtmux/session.py index 003beeaca..7033f26b6 100644 --- a/src/libtmux/session.py +++ b/src/libtmux/session.py @@ -11,7 +11,6 @@ import logging import pathlib import typing as t -import warnings from libtmux._internal.query_list import QueryList from libtmux.common import tmux_cmd @@ -649,12 +648,11 @@ def attached_pane(self) -> Pane | None: Deprecated in favor of :meth:`.active_pane`. """ - warnings.warn( - "Session.attached_pane() is deprecated in favor of Session.active_pane()", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Session.attached_pane", + replacement="Session.active_pane", + version="0.31.0", ) - return self.active_window.active_pane @property def attached_window(self) -> Window: @@ -666,13 +664,11 @@ def attached_window(self) -> Window: Deprecated in favor of :meth:`.active_window`. """ - warnings.warn( - "Session.attached_window() is deprecated in favor of " - "Session.active_window()", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Session.attached_window", + replacement="Session.active_window", + version="0.31.0", ) - return self.active_window def attach_session(self) -> Session: """Return ``$ tmux attach-session`` aka alias: ``$ tmux attach``. @@ -683,17 +679,11 @@ def attach_session(self) -> Session: Deprecated in favor of :meth:`.attach()`. """ - warnings.warn( - "Session.attach_session() is deprecated in favor of Session.attach()", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Session.attach_session()", + replacement="Session.attach()", + version="0.30.0", ) - proc = self.cmd("attach-session") - - if proc.stderr: - raise exc.LibTmuxException(proc.stderr) - - return self def kill_session(self) -> None: """Destroy session. @@ -704,47 +694,41 @@ def kill_session(self) -> None: Deprecated in favor of :meth:`.kill()`. """ - warnings.warn( - "Session.kill_session() is deprecated in favor of Session.kill()", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Session.kill_session()", + replacement="Session.kill()", + version="0.30.0", ) - proc = self.cmd("kill-session") - - if proc.stderr: - raise exc.LibTmuxException(proc.stderr) def get(self, key: str, default: t.Any | None = None) -> t.Any: """Return key-based lookup. Deprecated by attributes. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Deprecated by attribute lookup.e.g. ``session['session_name']`` is now accessed via ``session.session_name``. """ - warnings.warn( - "Session.get() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Session.get()", + replacement="direct attribute access (e.g., session.session_name)", + version="0.17.0", ) - return getattr(self, key, default) def __getitem__(self, key: str) -> t.Any: """Return item lookup by key. Deprecated in favor of attributes. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Deprecated in favor of attributes. e.g. ``session['session_name']`` is now accessed via ``session.session_name``. """ - warnings.warn( - f"Item lookups, e.g. session['{key}'] is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Session[key] lookup", + replacement="direct attribute access (e.g., session.session_name)", + version="0.17.0", ) - return getattr(self, key) def get_by_id(self, session_id: str) -> Window | None: """Return window by id. Deprecated in favor of :meth:`.windows.get()`. @@ -754,104 +738,94 @@ def get_by_id(self, session_id: str) -> Window | None: Deprecated by :meth:`.windows.get()`. """ - warnings.warn( - "Session.get_by_id() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Session.get_by_id()", + replacement="Session.windows.get(window_id=..., default=None)", + version="0.16.0", ) - return self.windows.get(window_id=session_id, default=None) def where(self, kwargs: dict[str, t.Any]) -> list[Window]: """Filter through windows, return list of :class:`Window`. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Deprecated by :meth:`.windows.filter()`. """ - warnings.warn( - "Session.where() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Session.where()", + replacement="Session.windows.filter()", + version="0.17.0", ) - try: - return self.windows.filter(**kwargs) - except IndexError: - return [] def find_where(self, kwargs: dict[str, t.Any]) -> Window | None: """Filter through windows, return first :class:`Window`. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Slated to be removed in favor of :meth:`.windows.get()`. """ - warnings.warn( - "Session.find_where() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Session.find_where()", + replacement="Session.windows.get(default=None, **kwargs)", + version="0.17.0", ) - return self.windows.get(default=None, **kwargs) def _list_windows(self) -> list[WindowDict]: """Return list of windows (deprecated in favor of :attr:`.windows`). - .. deprecated:: 0.16 + .. deprecated:: 0.17 Slated to be removed in favor of :attr:`.windows`. """ - warnings.warn( - "Session._list_windows() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Session._list_windows()", + replacement="Session.windows property", + version="0.17.0", ) - return [w.__dict__ for w in self.windows] @property def _windows(self) -> list[WindowDict]: """Property / alias to return :meth:`Session._list_windows`. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Slated to be removed in favor of :attr:`.windows`. """ - warnings.warn( - "Session._windows is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Session._windows", + replacement="Session.windows property", + version="0.17.0", ) - return self._list_windows() def list_windows(self) -> list[Window]: """Return a list of :class:`Window` from the ``tmux(1)`` session. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Slated to be removed in favor of :attr:`.windows`. """ - warnings.warn( - "Session.list_windows() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Session.list_windows()", + replacement="Session.windows property", + version="0.17.0", ) - return self.windows @property def children(self) -> QueryList[Window]: """Was used by TmuxRelationalObject (but that's longer used in this class). - .. deprecated:: 0.16 + .. deprecated:: 0.17 Slated to be removed in favor of :attr:`.windows`. """ - warnings.warn( - "Session.children is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Session.children", + replacement="Session.windows property", + version="0.17.0", ) - return self.windows diff --git a/src/libtmux/window.py b/src/libtmux/window.py index d578d90d7..64c251d55 100644 --- a/src/libtmux/window.py +++ b/src/libtmux/window.py @@ -797,31 +797,10 @@ def split_window( ``percent=25`` deprecated in favor of ``size="25%"``. """ - warnings.warn( - "Window.split_window() is deprecated in favor of Window.split()", - category=DeprecationWarning, - stacklevel=2, - ) - - if percent is not None: - # Deprecated in 3.1 in favor of -l - warnings.warn( - f'Deprecated in favor of size="{str(percent).rstrip("%")}%" ' - '(using the "-l" flag).', - category=DeprecationWarning, - stacklevel=2, - ) - if size is None: - size = f"{str(percent).rstrip('%')}%" - - return self.split( - target=target, - start_directory=start_directory, - attach=attach, - direction=PaneDirection.Below if vertical else PaneDirection.Right, - shell=shell, - size=size, - environment=environment, + raise exc.DeprecatedError( + deprecated="Window.split_window()", + replacement="Window.split()", + version="0.33.0", ) @property @@ -834,15 +813,11 @@ def attached_pane(self) -> Pane | None: Deprecated in favor of :meth:`.active_pane`. """ - warnings.warn( - "Window.attached_pane() is deprecated in favor of Window.active_pane()", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Window.attached_pane", + replacement="Window.active_pane", + version="0.31.0", ) - panes = self.panes.filter(pane_active="1") - if len(panes) > 0: - return panes[0] - return None def select_window(self) -> Window: """Select window. @@ -853,13 +828,11 @@ def select_window(self) -> Window: Deprecated in favor of :meth:`.select()`. """ - warnings.warn( - "Window.select_window() is deprecated in favor of Window.select()", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Window.select_window()", + replacement="Window.select()", + version="0.30.0", ) - assert isinstance(self.window_index, str) - return self.session.select_window(self.window_index) def kill_window(self) -> None: """Kill the current :class:`Window` object. ``$ tmux kill-window``. @@ -870,15 +843,11 @@ def kill_window(self) -> None: Deprecated in favor of :meth:`.kill()`. """ - warnings.warn( - "Window.kill_server() is deprecated in favor of Window.kill()", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Window.kill_window()", + replacement="Window.kill()", + version="0.30.0", ) - proc = self.cmd("kill-window") - - if proc.stderr: - raise exc.LibTmuxException(proc.stderr) def set_window_option( self, @@ -887,13 +856,13 @@ def set_window_option( ) -> Window: """Set option for tmux window. Deprecated by :meth:`Window.set_option()`. - .. deprecated:: 0.26 + .. deprecated:: 0.50 Deprecated by :meth:`Window.set_option()`. """ warnings.warn( - "Window.set_window_option() is deprecated", + "Window.set_window_option() is deprecated in favor of Window.set_option()", category=DeprecationWarning, stacklevel=2, ) @@ -902,13 +871,14 @@ def set_window_option( def show_window_options(self, g: bool | None = False) -> WindowOptionDict: """Show options for tmux window. Deprecated by :meth:`Window.show_options()`. - .. deprecated:: 0.26 + .. deprecated:: 0.50 Deprecated by :meth:`Window.show_options()`. """ warnings.warn( - "Window.show_window_options() is deprecated", + "Window.show_window_options() is deprecated" + " in favor of Window.show_options()", category=DeprecationWarning, stacklevel=2, ) @@ -924,53 +894,51 @@ def show_window_option( ) -> str | int | None: """Return option for target window. Deprecated by :meth:`Window.show_option()`. - .. deprecated:: 0.26 + .. deprecated:: 0.50 Deprecated by :meth:`Window.show_option()`. """ warnings.warn( - "Window.show_window_option() is deprecated", + "Window.show_window_option() is deprecated" + " in favor of Window.show_option()", category=DeprecationWarning, stacklevel=2, ) return self.show_option( option=option, - g=g, - scope=OptionScope.Window, + global_=g, ) def get(self, key: str, default: t.Any | None = None) -> t.Any: """Return key-based lookup. Deprecated by attributes. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Deprecated by attribute lookup.e.g. ``window['window_name']`` is now accessed via ``window.window_name``. """ - warnings.warn( - "Window.get() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Window.get()", + replacement="direct attribute access (e.g., window.window_name)", + version="0.17.0", ) - return getattr(self, key, default) def __getitem__(self, key: str) -> t.Any: """Return item lookup by key. Deprecated in favor of attributes. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Deprecated in favor of attributes. e.g. ``window['window_name']`` is now accessed via ``window.window_name``. """ - warnings.warn( - f"Item lookups, e.g. window['{key}'] is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Window[key] lookup", + replacement="direct attribute access (e.g., window.window_name)", + version="0.17.0", ) - return getattr(self, key) def get_by_id(self, pane_id: str) -> Pane | None: """Return pane by id. Deprecated in favor of :meth:`.panes.get()`. @@ -980,100 +948,94 @@ def get_by_id(self, pane_id: str) -> Pane | None: Deprecated by :meth:`.panes.get()`. """ - warnings.warn( - "Window.get_by_id() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Window.get_by_id()", + replacement="Window.panes.get(pane_id=..., default=None)", + version="0.16.0", ) - return self.panes.get(pane_id=pane_id, default=None) def where(self, kwargs: dict[str, t.Any]) -> list[Pane]: """Filter through panes, return list of :class:`Pane`. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Deprecated by :meth:`.panes.filter()`. """ - warnings.warn( - "Window.where() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Window.where()", + replacement="Window.panes.filter()", + version="0.17.0", ) - try: - return self.panes.filter(**kwargs) - except IndexError: - return [] def find_where(self, kwargs: dict[str, t.Any]) -> Pane | None: """Filter through panes, return first :class:`Pane`. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Slated to be removed in favor of :meth:`.panes.get()`. """ - warnings.warn( - "Window.find_where() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Window.find_where()", + replacement="Window.panes.get(default=None, **kwargs)", + version="0.17.0", ) - return self.panes.get(default=None, **kwargs) def _list_panes(self) -> list[PaneDict]: """Return list of panes (deprecated in favor of :meth:`.panes`). - .. deprecated:: 0.16 + .. deprecated:: 0.17 Slated to be removed in favor of :attr:`.panes`. """ - warnings.warn( - "Window._list_panes() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Window._list_panes()", + replacement="Window.panes property", + version="0.17.0", ) - return [pane.__dict__ for pane in self.panes] @property def _panes(self) -> list[PaneDict]: """Property / alias to return :meth:`~._list_panes`. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Slated to be removed in favor of :attr:`.panes`. """ - warnings.warn("_panes is deprecated", category=DeprecationWarning, stacklevel=2) - return self._list_panes() + raise exc.DeprecatedError( + deprecated="Window._panes", + replacement="Window.panes property", + version="0.17.0", + ) def list_panes(self) -> list[Pane]: """Return list of :class:`Pane` for the window. - .. deprecated:: 0.16 + .. deprecated:: 0.17 Slated to be removed in favor of :attr:`.panes`. """ - warnings.warn( - "list_panes() is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Window.list_panes()", + replacement="Window.panes property", + version="0.17.0", ) - return self.panes @property def children(self) -> QueryList[Pane]: """Was used by TmuxRelationalObject (but that's longer used in this class). - .. deprecated:: 0.16 + .. deprecated:: 0.17 Slated to be removed in favor of :attr:`.panes`. """ - warnings.warn( - "Window.children is deprecated", - category=DeprecationWarning, - stacklevel=2, + raise exc.DeprecatedError( + deprecated="Window.children", + replacement="Window.panes property", + version="0.17.0", ) - return self.panes diff --git a/tests/legacy_api/test_common.py b/tests/legacy_api/test_common.py index c61f457bd..6c1b03cf4 100644 --- a/tests/legacy_api/test_common.py +++ b/tests/legacy_api/test_common.py @@ -1,4 +1,8 @@ -"""Tests for utility functions in libtmux.""" +"""Tests for utility functions in libtmux. + +Note: This file tests common utilities, not deprecated APIs. +The tests use the current API. +""" from __future__ import annotations @@ -9,6 +13,7 @@ import pytest import libtmux +from libtmux import exc from libtmux._compat import LooseVersion from libtmux.common import ( TMUX_MAX_VERSION, @@ -24,7 +29,6 @@ session_check_name, tmux_cmd, ) -from libtmux.exc import BadSessionName, LibTmuxException, TmuxCommandNotFound if t.TYPE_CHECKING: from libtmux.session import Session @@ -100,7 +104,7 @@ def mock_tmux_cmd(*args: t.Any, **kwargs: t.Any) -> Hi: return Hi() monkeypatch.setattr(libtmux.common, "tmux_cmd", mock_tmux_cmd) - with pytest.raises(LibTmuxException) as exc_info: + with pytest.raises(exc.LibTmuxException) as exc_info: get_version() exc_info.match("does not meet the minimum tmux version requirement") @@ -135,11 +139,11 @@ def mock_get_version() -> LooseVersion: return LooseVersion("1.7") monkeypatch.setattr(libtmux.common, "get_version", mock_get_version) - with pytest.raises(LibTmuxException) as excinfo: + with pytest.raises(exc.LibTmuxException) as excinfo: has_minimum_version() excinfo.match(r"libtmux only supports") - with pytest.raises(LibTmuxException) as excinfo: + with pytest.raises(exc.LibTmuxException) as excinfo: has_minimum_version() excinfo.match(r"libtmux only supports") @@ -191,7 +195,7 @@ def test_has_lte_version() -> None: def test_tmux_cmd_raises_on_not_found(monkeypatch: pytest.MonkeyPatch) -> None: """Verify raises if tmux command not found.""" monkeypatch.setenv("PATH", "") - with pytest.raises(TmuxCommandNotFound): + with pytest.raises(exc.TmuxCommandNotFound): tmux_cmd("-V") @@ -226,7 +230,7 @@ def test_session_check_name( ) -> None: """Verify session_check_name().""" if raises: - with pytest.raises(BadSessionName) as exc_info: + with pytest.raises(exc.BadSessionName) as exc_info: session_check_name(session_name) if exc_msg_regex is not None: assert exc_info.match(exc_msg_regex) diff --git a/tests/legacy_api/test_pane.py b/tests/legacy_api/test_pane.py index 31200a9b9..6b21d86eb 100644 --- a/tests/legacy_api/test_pane.py +++ b/tests/legacy_api/test_pane.py @@ -1,98 +1,71 @@ -"""Tests for libtmux Pane object.""" +"""Tests for deprecated libtmux Pane APIs. + +These tests verify that deprecated methods raise DeprecatedError. +""" from __future__ import annotations -import logging -import shutil import typing as t -if t.TYPE_CHECKING: - from libtmux.session import Session - -logger = logging.getLogger(__name__) - - -def test_resize_pane(session: Session) -> None: - """Test Pane.resize_pane().""" - window = session.attached_window - window.rename_window("test_resize_pane") - - pane1 = window.attached_pane - assert pane1 is not None - pane1_height = pane1["pane_height"] - window.split_window() +import pytest - pane1.resize_pane(height=4) - assert pane1["pane_height"] != pane1_height - assert int(pane1["pane_height"]) == 4 +from libtmux import exc - pane1.resize_pane(height=3) - assert int(pane1["pane_height"]) == 3 +if t.TYPE_CHECKING: + from libtmux.session import Session -def test_send_keys(session: Session) -> None: - """Verify Pane.send_keys().""" - pane = session.attached_window.attached_pane +def test_resize_pane_raises_deprecated_error(session: Session) -> None: + """Test Pane.resize_pane() raises DeprecatedError.""" + window = session.active_window + pane = window.active_pane assert pane is not None - pane.send_keys("c-c", literal=True) - pane_contents = "\n".join(pane.cmd("capture-pane", "-p").stdout) - assert "c-c" in pane_contents + with pytest.raises( + exc.DeprecatedError, match=r"Pane\.resize_pane\(\) was deprecated" + ): + pane.resize_pane(height=4) - pane.send_keys("c-a", literal=False) - assert "c-a" not in pane_contents, "should not print to pane" +def test_select_pane_raises_deprecated_error(session: Session) -> None: + """Test Pane.select_pane() raises DeprecatedError.""" + window = session.active_window + pane = window.active_pane + assert pane is not None -def test_set_height(session: Session) -> None: - """Verify Pane.set_height().""" - window = session.new_window(window_name="test_set_height") - window.split_window() - pane1 = window.attached_pane - assert pane1 is not None - pane1_height = pane1["pane_height"] - - pane1.set_height(4) - assert pane1["pane_height"] != pane1_height - assert int(pane1["pane_height"]) == 4 + with pytest.raises( + exc.DeprecatedError, match=r"Pane\.select_pane\(\) was deprecated" + ): + pane.select_pane() -def test_set_width(session: Session) -> None: - """Verify Pane.set_width().""" - window = session.new_window(window_name="test_set_width") - window.split_window() +def test_split_window_raises_deprecated_error(session: Session) -> None: + """Test Pane.split_window() raises DeprecatedError.""" + window = session.active_window + pane = window.active_pane + assert pane is not None - window.select_layout("main-vertical") - pane1 = window.attached_pane - assert pane1 is not None - pane1_width = pane1["pane_width"] + with pytest.raises( + exc.DeprecatedError, match=r"Pane\.split_window\(\) was deprecated" + ): + pane.split_window() - pane1.set_width(10) - assert pane1["pane_width"] != pane1_width - assert int(pane1["pane_width"]) == 10 - pane1.reset() +def test_pane_get_raises_deprecated_error(session: Session) -> None: + """Test Pane.get() raises DeprecatedError.""" + window = session.active_window + pane = window.active_pane + assert pane is not None + with pytest.raises(exc.DeprecatedError, match=r"Pane\.get\(\) was deprecated"): + pane.get("pane_id") -def test_capture_pane(session: Session) -> None: - """Verify Pane.capture_pane().""" - env = shutil.which("env") - assert env is not None, "Cannot find usable `env` in PATH." - session.new_window( - attach=True, - window_name="capture_pane", - window_shell=f"{env} PS1='$ ' sh", - ) - pane = session.attached_window.attached_pane +def test_pane_getitem_raises_deprecated_error(session: Session) -> None: + """Test Pane.__getitem__() raises DeprecatedError.""" + window = session.active_window + pane = window.active_pane assert pane is not None - pane_contents = "\n".join(pane.capture_pane()) - assert pane_contents == "$" - pane.send_keys( - r'printf "\n%s\n" "Hello World !"', - literal=True, - suppress_history=False, - ) - pane_contents = "\n".join(pane.capture_pane()) - assert pane_contents == r'$ printf "\n%s\n" "Hello World !"{}'.format( - "\n\nHello World !\n$", - ) + + with pytest.raises(exc.DeprecatedError, match=r"Pane\[key\] lookup was deprecated"): + _ = pane["pane_id"] diff --git a/tests/legacy_api/test_server.py b/tests/legacy_api/test_server.py index 3aa6ab473..d4ba5d848 100644 --- a/tests/legacy_api/test_server.py +++ b/tests/legacy_api/test_server.py @@ -1,169 +1,101 @@ -"""Test for libtmux Server object.""" +"""Tests for deprecated libtmux Server APIs. -from __future__ import annotations +These tests verify that deprecated methods raise exc.DeprecatedError. +""" -import logging -import subprocess -import typing as t +from __future__ import annotations import pytest +from libtmux import exc from libtmux.server import Server -if t.TYPE_CHECKING: - from libtmux.session import Session - -logger = logging.getLogger(__name__) - - -def test_has_session(server: Server, session: Session) -> None: - """Server.has_session() returns True if session exists.""" - session_name = session.get("session_name") - assert session_name is not None - assert server.has_session(session_name) - assert not server.has_session("asdf2314324321") - - -def test_socket_name(server: Server) -> None: - """``-L`` socket_name. - - ``-L`` socket_name file name of socket. which will be stored in - env TMUX_TMPDIR or /tmp if unset.) - - """ - myserver = Server(socket_name="test") - - assert myserver.socket_name == "test" - - -def test_socket_path(server: Server) -> None: - """``-S`` socket_path (alternative path for server socket).""" - myserver = Server(socket_path="test") - - assert myserver.socket_path == "test" - - -def test_config(server: Server) -> None: - """``-f`` file for tmux(1) configuration.""" - myserver = Server(config_file="test") - assert myserver.config_file == "test" - - -def test_256_colors(server: Server) -> None: - """Assert Server respects ``colors=256``.""" - myserver = Server(colors=256) - assert myserver.colors == 256 - - proc = myserver.cmd("list-sessions") - - assert "-2" in proc.cmd - assert "-8" not in proc.cmd - - -def test_88_colors(server: Server) -> None: - """Assert Server respects ``colors=88``.""" - myserver = Server(colors=88) - assert myserver.colors == 88 - - proc = myserver.cmd("list-sessions") - - assert "-8" in proc.cmd - assert "-2" not in proc.cmd - - -def test_show_environment(server: Server) -> None: - """Server.show_environment() returns dict.""" - vars_ = server.show_environment() - assert isinstance(vars_, dict) - - -def test_getenv(server: Server, session: Session) -> None: - """Set environment then Server.show_environment(key).""" - server.set_environment("FOO", "BAR") - assert server.getenv("FOO") == "BAR" - - server.set_environment("FOO", "DAR") - assert server.getenv("FOO") == "DAR" - - assert server.show_environment()["FOO"] == "DAR" - -def test_show_environment_not_set(server: Server) -> None: - """Unset environment variable returns None.""" - assert server.getenv("BAR") is None +def test_kill_server_raises_deprecated_error(server: Server) -> None: + """Test Server.kill_server() raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Server\.kill_server\(\) was deprecated" + ): + server.kill_server() -def test_new_session(server: Server) -> None: - """Server.new_session creates and returns valid session.""" - mysession = server.new_session("test_new_session") - assert mysession.get("session_name") == "test_new_session" - assert server.has_session("test_new_session") +def test_server_get_by_id_raises_deprecated_error(server: Server) -> None: + """Test Server.get_by_id() raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Server\.get_by_id\(\) was deprecated" + ): + server.get_by_id("$0") -def test_new_session_no_name(server: Server) -> None: - """Server.new_session works with no name.""" - first_session = server.new_session() - first_session_name = first_session.get("session_name") - assert first_session_name is not None - assert server.has_session(first_session_name) +def test_server_where_raises_deprecated_error(server: Server) -> None: + """Test Server.where() raises exc.DeprecatedError.""" + with pytest.raises(exc.DeprecatedError, match=r"Server\.where\(\) was deprecated"): + server.where({"session_name": "test"}) - expected_session_name = str(int(first_session_name) + 1) - # When a new session is created, it should enumerate - second_session = server.new_session() - second_session_name = second_session.get("session_name") - assert expected_session_name == second_session_name - assert second_session_name is not None - assert server.has_session(second_session_name) +def test_server_find_where_raises_deprecated_error(server: Server) -> None: + """Test Server.find_where() raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Server\.find_where\(\) was deprecated" + ): + server.find_where({"session_name": "test"}) -def test_new_session_shell(server: Server) -> None: - """Verify ``Server.new_session`` creates valid session running w/ command.""" - cmd = "sleep 1m" - mysession = server.new_session("test_new_session", window_command=cmd) - window = mysession.list_windows()[0] - pane = window.list_panes()[0] - assert mysession.get("session_name") == "test_new_session" - assert server.has_session("test_new_session") +def test_server_list_sessions_raises_deprecated_error(server: Server) -> None: + """Test Server.list_sessions() raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Server\.list_sessions\(\) was deprecated" + ): + server.list_sessions() - pane_start_command = pane.get("pane_start_command") - assert pane_start_command is not None - assert pane_start_command.replace('"', "") == cmd +def test_server_children_raises_deprecated_error(server: Server) -> None: + """Test Server.children raises exc.DeprecatedError.""" + with pytest.raises(exc.DeprecatedError, match=r"Server\.children was deprecated"): + _ = server.children -def test_no_server_sessions() -> None: - """Verify ``Server.sessions`` returns empty list without tmux server.""" - server = Server(socket_name="test_attached_session_no_server") - assert server.sessions == [] +def test_server__sessions_raises_deprecated_error(server: Server) -> None: + """Test Server._sessions raises exc.DeprecatedError.""" + with pytest.raises(exc.DeprecatedError, match=r"Server\._sessions was deprecated"): + _ = server._sessions -def test_no_server_attached_sessions() -> None: - """Verify ``Server.attached_sessions`` returns empty list without tmux server.""" - server = Server(socket_name="test_no_server_attached_sessions") - assert server.attached_sessions == [] +def test_server__list_sessions_raises_deprecated_error(server: Server) -> None: + """Test Server._list_sessions() raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Server\._list_sessions\(\) was deprecated" + ): + server._list_sessions() -def test_no_server_is_alive() -> None: - """Verify is_alive() returns False without tmux server.""" - dead_server = Server(socket_name="test_no_server_is_alive") - assert not dead_server.is_alive() +def test_server__list_windows_raises_deprecated_error(server: Server) -> None: + """Test Server._list_windows() raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Server\._list_windows\(\) was deprecated" + ): + server._list_windows() -def test_with_server_is_alive(server: Server) -> None: - """Verify is_alive() returns True when tmux server is alive.""" - server.new_session() - assert server.is_alive() +def test_server__update_windows_raises_deprecated_error(server: Server) -> None: + """Test Server._update_windows() raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Server\._update_windows\(\) was deprecated" + ): + server._update_windows() -def test_raise_if_dead_no_server_raises() -> None: - """Verify new_session() raises if tmux server is dead.""" - dead_server = Server(socket_name="test_attached_session_no_server") - with pytest.raises(subprocess.SubprocessError): - dead_server.raise_if_dead() +def test_server__list_panes_raises_deprecated_error(server: Server) -> None: + """Test Server._list_panes() raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Server\._list_panes\(\) was deprecated" + ): + server._list_panes() -def test_raise_if_dead_does_not_raise_if_alive(server: Server) -> None: - """Verify new_session() does not raise if tmux server is alive.""" - server.new_session() - server.raise_if_dead() +def test_server__update_panes_raises_deprecated_error(server: Server) -> None: + """Test Server._update_panes() raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Server\._update_panes\(\) was deprecated" + ): + server._update_panes() diff --git a/tests/legacy_api/test_session.py b/tests/legacy_api/test_session.py index a9560824e..7cc77ef5c 100644 --- a/tests/legacy_api/test_session.py +++ b/tests/legacy_api/test_session.py @@ -1,283 +1,118 @@ -"""Test for libtmux Session object.""" +"""Tests for deprecated libtmux Session APIs. + +These tests verify that deprecated methods raise exc.DeprecatedError. +""" from __future__ import annotations -import logging -import shutil import typing as t import pytest from libtmux import exc -from libtmux.pane import Pane -from libtmux.session import Session -from libtmux.test.constants import TEST_SESSION_PREFIX -from libtmux.test.random import namer -from libtmux.window import Window if t.TYPE_CHECKING: from libtmux.server import Server + from libtmux.session import Session -logger = logging.getLogger(__name__) - - -def test_has_session(server: Server, session: Session) -> None: - """Server.has_session returns True if has session_name exists.""" - TEST_SESSION_NAME = session.get("session_name") - assert TEST_SESSION_NAME is not None - assert server.has_session(TEST_SESSION_NAME) - assert not server.has_session(TEST_SESSION_NAME[:-2]) - assert server.has_session(TEST_SESSION_NAME[:-2], exact=False) - assert not server.has_session("asdf2314324321") - - -def test_select_window(session: Session) -> None: - """Session.select_window moves window.""" - # get the current window_base_index, since different user tmux config - # may start at 0 or 1, or whatever they want. - window_idx = session.attached_window.get("window_index") - assert window_idx is not None - window_base_index = int(window_idx) - - session.new_window(window_name="test_window") - window_count = len(session._windows) - - assert window_count >= 2 # 2 or more windows - - assert len(session._windows) == window_count - - # tmux selects a window, moves to it, shows it as attached_window - selected_window1 = session.select_window(window_base_index) - assert isinstance(selected_window1, Window) - attached_window1 = session.attached_window - - assert selected_window1.id == attached_window1.id - - # again: tmux selects a window, moves to it, shows it as - # attached_window - selected_window2 = session.select_window(window_base_index + 1) - assert isinstance(selected_window2, Window) - attached_window2 = session.attached_window - - assert selected_window2.id == attached_window2.id - - # assure these windows were really different - assert selected_window1.id != selected_window2.id - - -def test_select_window_returns_Window(session: Session) -> None: - """Session.select_window returns Window object.""" - window_count = len(session._windows) - assert len(session._windows) == window_count - - window_idx = session.attached_window.get("window_index") - assert window_idx is not None - window_base_index = int(window_idx) - window = session.select_window(window_base_index) - assert isinstance(window, Window) - - -def test_attached_window(session: Session) -> None: - """Session.attached_window returns Window.""" - assert isinstance(session.attached_window, Window) - - -def test_attached_pane(session: Session) -> None: - """Session.attached_pane returns Pane.""" - assert isinstance(session.attached_pane, Pane) - - -def test_session_rename(session: Session) -> None: - """Session.rename_session renames session.""" - session_name = session.get("session_name") - assert session_name is not None - TEST_SESSION_NAME = session_name - - test_name = "testingdis_sessname" - session.rename_session(test_name) - session_name = session.get("session_name") - assert session_name is not None - assert session_name == test_name - session.rename_session(TEST_SESSION_NAME) - session_name = session.get("session_name") - assert session_name is not None - assert session_name == TEST_SESSION_NAME - - -def test_new_session(server: Server) -> None: - """Server.new_session creates new session.""" - new_session_name = TEST_SESSION_PREFIX + next(namer) - new_session = server.new_session(session_name=new_session_name, detach=True) - - assert isinstance(new_session, Session) - assert new_session.get("session_name") == new_session_name - - -def test_show_options(session: Session) -> None: - """Session._show_options() returns dict.""" - options = session._show_options() - assert isinstance(options, dict) - - -def test_set_show_options_single(session: Session) -> None: - """Set option then Session._show_options(key).""" - session.set_option("history-limit", 20) - assert session._show_option("history-limit") == 20 - - session.set_option("history-limit", 40) - assert session._show_option("history-limit") == 40 - - assert session._show_options()["history-limit"] == 40 - - -def test_set_show_option(session: Session) -> None: - """Set option then Session._show_option(key).""" - session.set_option("history-limit", 20) - assert session._show_option("history-limit") == 20 - - session.set_option("history-limit", 40) - assert session._show_option("history-limit") == 40 +def test_attached_window_raises_deprecated_error(session: Session) -> None: + """Test Session.attached_window raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Session\.attached_window was deprecated" + ): + _ = session.attached_window -def test_empty_session_option_returns_None(session: Session) -> None: - """Verify Session._show_option returns None for unset option.""" - assert session._show_option("default-shell") is None +def test_attached_pane_raises_deprecated_error(session: Session) -> None: + """Test Session.attached_pane raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Session\.attached_pane was deprecated" + ): + _ = session.attached_pane -def test_show_option_unknown(session: Session) -> None: - """Session.show_option raises InvalidOption for invalid option.""" - with pytest.raises(exc.InvalidOption): - session.show_option("moooz") +def test_attach_session_raises_deprecated_error(session: Session) -> None: + """Test Session.attach_session() raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Session\.attach_session\(\) was deprecated" + ): + session.attach_session() -def test_show_option_ambiguous(session: Session) -> None: - """Session._show_option raises AmbiguousOption for ambiguous option.""" - with pytest.raises(exc.AmbiguousOption): - session._show_option("default-") +def test_kill_session_raises_deprecated_error(server: Server) -> None: + """Test Session.kill_session() raises exc.DeprecatedError.""" + # Create a new session to kill (so we don't kill our test session) + new_session = server.new_session(session_name="test_kill_session", detach=True) + with pytest.raises( + exc.DeprecatedError, match=r"Session\.kill_session\(\) was deprecated" + ): + new_session.kill_session() -def test_set_option_ambiguous(session: Session) -> None: - """Session.set_option raises AmbiguousOption for invalid option.""" - with pytest.raises(exc.AmbiguousOption): - session.set_option("default-", 43) + # Clean up using the new API + new_session.kill() -def test_set_option_invalid(session: Session) -> None: - """Session.set_option raises InvalidOption for invalid option.""" - with pytest.raises(exc.InvalidOption): - session.set_option("afewewfew", 43) +def test_session_get_raises_deprecated_error(session: Session) -> None: + """Test Session.get() raises exc.DeprecatedError.""" + with pytest.raises(exc.DeprecatedError, match=r"Session\.get\(\) was deprecated"): + session.get("session_name") -def test_show_environment(session: Session) -> None: - """Session.show_environment() returns dict.""" - vars_ = session.show_environment() - assert isinstance(vars_, dict) +def test_session_getitem_raises_deprecated_error(session: Session) -> None: + """Test Session.__getitem__() raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Session\[key\] lookup was deprecated" + ): + _ = session["session_name"] -def test_set_show_environment_single(session: Session) -> None: - """Set environment then Session.show_environment(key).""" - session.set_environment("FOO", "BAR") - assert session.getenv("FOO") == "BAR" +def test_session_get_by_id_raises_deprecated_error(session: Session) -> None: + """Test Session.get_by_id() raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Session\.get_by_id\(\) was deprecated" + ): + session.get_by_id("@0") - session.set_environment("FOO", "DAR") - assert session.getenv("FOO") == "DAR" - assert session.show_environment()["FOO"] == "DAR" +def test_session_where_raises_deprecated_error(session: Session) -> None: + """Test Session.where() raises exc.DeprecatedError.""" + with pytest.raises(exc.DeprecatedError, match=r"Session\.where\(\) was deprecated"): + session.where({"window_name": "test"}) -def test_show_environment_not_set(session: Session) -> None: - """Not set environment variable returns None.""" - assert session.getenv("BAR") is None +def test_session_find_where_raises_deprecated_error(session: Session) -> None: + """Test Session.find_where() raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Session\.find_where\(\) was deprecated" + ): + session.find_where({"window_name": "test"}) -def test_remove_environment(session: Session) -> None: - """Remove environment variable.""" - assert session.getenv("BAM") is None - session.set_environment("BAM", "OK") - assert session.getenv("BAM") == "OK" - session.remove_environment("BAM") - assert session.getenv("BAM") is None +def test_session_list_windows_raises_deprecated_error(session: Session) -> None: + """Test Session.list_windows() raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Session\.list_windows\(\) was deprecated" + ): + session.list_windows() -def test_unset_environment(session: Session) -> None: - """Unset environment variable.""" - assert session.getenv("BAM") is None - session.set_environment("BAM", "OK") - assert session.getenv("BAM") == "OK" - session.unset_environment("BAM") - assert session.getenv("BAM") is None +def test_session_children_raises_deprecated_error(session: Session) -> None: + """Test Session.children raises exc.DeprecatedError.""" + with pytest.raises(exc.DeprecatedError, match=r"Session\.children was deprecated"): + _ = session.children -@pytest.mark.parametrize( - ("session_name", "raises"), - [("hey.period", True), ("hey:its a colon", True), ("hey moo", False)], -) -def test_periods_raise_badsessionname( - server: Server, - session: Session, - session_name: str, - raises: bool, -) -> None: - """Verify session names with periods raise BadSessionName.""" - new_name = session_name + "moo" # used for rename / switch - if raises: - with pytest.raises(exc.BadSessionName): - session.rename_session(new_name) +def test_session__windows_raises_deprecated_error(session: Session) -> None: + """Test Session._windows raises exc.DeprecatedError.""" + with pytest.raises(exc.DeprecatedError, match=r"Session\._windows was deprecated"): + _ = session._windows - with pytest.raises(exc.BadSessionName): - server.new_session(session_name) - with pytest.raises(exc.BadSessionName): - server.has_session(session_name) - - with pytest.raises(exc.BadSessionName): - server.switch_client(new_name) - - with pytest.raises(exc.BadSessionName): - server.attach_session(new_name) - - else: - server.new_session(session_name) - server.has_session(session_name) - session.rename_session(new_name) - with pytest.raises(exc.LibTmuxException): - server.switch_client(new_name) - - -def test_cmd_inserts_session_id(session: Session) -> None: - """Verify Session.cmd() inserts session_id.""" - current_session_id = session.id - last_arg = "last-arg" - cmd = session.cmd("not-a-command", last_arg) - assert "-t" in cmd.cmd - assert current_session_id in cmd.cmd - assert cmd.cmd[-1] == last_arg - - -@pytest.mark.parametrize( - "environment", - [ - {"ENV_VAR": "window"}, - {"ENV_VAR_1": "window_1", "ENV_VAR_2": "window_2"}, - ], -) -def test_new_window_with_environment( - session: Session, - environment: dict[str, str], -) -> None: - """Verify new window with environment vars.""" - env = shutil.which("env") - assert env is not None, "Cannot find usable `env` in PATH." - - window = session.new_window( - attach=True, - window_name="window_with_environment", - window_shell=f"{env} PS1='$ ' sh", - environment=environment, - ) - pane = window.attached_pane - assert pane is not None - for k, v in environment.items(): - pane.send_keys(f"echo ${k}") - assert pane.capture_pane()[-2] == v +def test_session__list_windows_raises_deprecated_error(session: Session) -> None: + """Test Session._list_windows() raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Session\._list_windows\(\) was deprecated" + ): + session._list_windows() diff --git a/tests/legacy_api/test_tmuxobject.py b/tests/legacy_api/test_tmuxobject.py index dc023d24b..095e216d8 100644 --- a/tests/legacy_api/test_tmuxobject.py +++ b/tests/legacy_api/test_tmuxobject.py @@ -1,194 +1,85 @@ -"""Tests for libtmux TmuxRelationalObject and TmuxMappingObject.""" +"""Tests for deprecated libtmux TmuxRelationalObject APIs. + +These tests verify that deprecated methods raise exc.DeprecatedError. +""" from __future__ import annotations -import logging import typing as t -from libtmux.pane import Pane -from libtmux.session import Session -from libtmux.test.constants import TEST_SESSION_PREFIX -from libtmux.test.random import namer -from libtmux.window import Window +import pytest + +from libtmux import exc if t.TYPE_CHECKING: from libtmux.server import Server + from libtmux.session import Session -logger = logging.getLogger(__name__) - - -"""Test the :class:`TmuxRelationalObject` base class object.""" - - -def test_find_where(server: Server, session: Session) -> None: - """Test that find_where() retrieves single matching object.""" - # server.find_where - for session in server.sessions: - session_id = session.get("session_id") - assert session_id is not None - - assert server.find_where({"session_id": session_id}) == session - assert isinstance(server.find_where({"session_id": session_id}), Session) - - # session.find_where - for window in session.windows: - window_id = window.get("window_id") - assert window_id is not None - - assert session.find_where({"window_id": window_id}) == window - assert isinstance(session.find_where({"window_id": window_id}), Window) - - # window.find_where - for pane in window.panes: - pane_id = pane.get("pane_id") - assert pane_id is not None - - assert window.find_where({"pane_id": pane_id}) == pane - assert isinstance(window.find_where({"pane_id": pane_id}), Pane) - - -def test_find_where_None(server: Server, session: Session) -> None: - """.find_where returns None if no results found.""" - while True: - nonexistent_session = TEST_SESSION_PREFIX + next(namer) - - if not server.has_session(nonexistent_session): - break - - assert server.find_where({"session_name": nonexistent_session}) is None - - -def test_find_where_multiple_infos(server: Server, session: Session) -> None: - """.find_where returns objects with multiple attributes.""" - for session in server.sessions: - session_id = session.get("session_id") - assert session_id is not None - session_name = session.get("session_name") - assert session_name is not None - - find_where = server.find_where( - {"session_id": session_id, "session_name": session_name}, - ) - - assert find_where == session - assert isinstance(find_where, Session) - - # session.find_where - for window in session.windows: - window_id = window.get("window_id") - assert window_id is not None - window_index = window.get("window_index") - assert window_index is not None - - find_where_window = session.find_where( - {"window_id": window_id, "window_index": window_index}, - ) - - assert find_where_window == window - assert isinstance(find_where_window, Window) - - # window.find_where - for pane in window.panes: - pane_id = pane.get("pane_id") - assert pane_id is not None - pane_tty = pane.get("pane_tty") - assert pane_tty is not None - - find_where_pane = window.find_where( - {"pane_id": pane_id, "pane_tty": pane_tty}, - ) - - assert find_where_pane == pane - assert isinstance(find_where_pane, Pane) - - -def test_where(server: Server, session: Session) -> None: - """Test self.where() returns matching objects.""" - window = session.attached_window - window.split_window() # create second pane - - for session in server.sessions: - session_id = session.get("session_id") - assert session_id is not None - session_name = session.get("session_name") - assert session_name is not None - - server_sessions = server.where( - {"session_id": session_id, "session_name": session_name}, - ) - - assert len(server_sessions) == 1 - assert isinstance(server_sessions, list) - assert server_sessions[0] == session - assert isinstance(server_sessions[0], Session) - - # session.where - for window in session.windows: - window_id = window.get("window_id") - assert window_id is not None - - window_index = window.get("window_index") - assert window_index is not None - - session_windows = session.where( - {"window_id": window_id, "window_index": window_index}, - ) - assert len(session_windows) == 1 - assert isinstance(session_windows, list) - assert session_windows[0] == window - assert isinstance(session_windows[0], Window) +def test_server_find_where_raises_deprecated_error(server: Server) -> None: + """Test Server.find_where() raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Server\.find_where\(\) was deprecated" + ): + server.find_where({"session_name": "test"}) - # window.where - for pane in window.panes: - pane_id = pane.get("pane_id") - assert pane_id is not None - pane_tty = pane.get("pane_tty") - assert pane_tty is not None +def test_session_find_where_raises_deprecated_error(session: Session) -> None: + """Test Session.find_where() raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Session\.find_where\(\) was deprecated" + ): + session.find_where({"window_name": "test"}) - window_panes = window.where({"pane_id": pane_id, "pane_tty": pane_tty}) - assert len(window_panes) == 1 - assert isinstance(window_panes, list) - assert window_panes[0] == pane - assert isinstance(window_panes[0], Pane) +def test_window_find_where_raises_deprecated_error(session: Session) -> None: + """Test Window.find_where() raises exc.DeprecatedError.""" + window = session.active_window + with pytest.raises( + exc.DeprecatedError, match=r"Window\.find_where\(\) was deprecated" + ): + window.find_where({"pane_id": "%0"}) -def test_get_by_id(server: Server, session: Session) -> None: - """Test self.get_by_id() retrieves child object.""" - window = session.attached_window +def test_server_where_raises_deprecated_error(server: Server) -> None: + """Test Server.where() raises exc.DeprecatedError.""" + with pytest.raises(exc.DeprecatedError, match=r"Server\.where\(\) was deprecated"): + server.where({"session_name": "test"}) - window.split_window() # create second pane - for session in server.sessions: - session_id = session.get("session_id") - assert session_id is not None - get_session_by_id = server.get_by_id(session_id) +def test_session_where_raises_deprecated_error(session: Session) -> None: + """Test Session.where() raises exc.DeprecatedError.""" + with pytest.raises(exc.DeprecatedError, match=r"Session\.where\(\) was deprecated"): + session.where({"window_name": "test"}) - assert get_session_by_id == session - assert isinstance(get_session_by_id, Session) - assert server.get_by_id("$" + next(namer)) is None - # session.get_by_id - for window in session.windows: - window_id = window.get("window_id") - assert window_id is not None +def test_window_where_raises_deprecated_error(session: Session) -> None: + """Test Window.where() raises exc.DeprecatedError.""" + window = session.active_window + with pytest.raises(exc.DeprecatedError, match=r"Window\.where\(\) was deprecated"): + window.where({"pane_id": "%0"}) - get_window_by_id = session.get_by_id(window_id) - assert get_window_by_id == window - assert isinstance(get_window_by_id, Window) +def test_server_get_by_id_raises_deprecated_error(server: Server) -> None: + """Test Server.get_by_id() raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Server\.get_by_id\(\) was deprecated" + ): + server.get_by_id("$0") - assert session.get_by_id("@" + next(namer)) is None - # window.get_by_id - for pane in window.panes: - pane_id = pane.get("pane_id") - assert pane_id is not None +def test_session_get_by_id_raises_deprecated_error(session: Session) -> None: + """Test Session.get_by_id() raises exc.DeprecatedError.""" + with pytest.raises( + exc.DeprecatedError, match=r"Session\.get_by_id\(\) was deprecated" + ): + session.get_by_id("@0") - get_pane_by_id = window.get_by_id(pane_id) - assert get_pane_by_id == pane - assert isinstance(get_pane_by_id, Pane) - assert window.get_by_id("%" + next(namer)) is None +def test_window_get_by_id_raises_deprecated_error(session: Session) -> None: + """Test Window.get_by_id() raises exc.DeprecatedError.""" + window = session.active_window + with pytest.raises( + exc.DeprecatedError, match=r"Window\.get_by_id\(\) was deprecated" + ): + window.get_by_id("%0") diff --git a/tests/legacy_api/test_window.py b/tests/legacy_api/test_window.py index bd87f349c..2bf589f38 100644 --- a/tests/legacy_api/test_window.py +++ b/tests/legacy_api/test_window.py @@ -1,389 +1,169 @@ -"""Test for libtmux Window object.""" +"""Tests for deprecated libtmux Window APIs. + +These tests verify that deprecated methods raise exc.DeprecatedError. +""" from __future__ import annotations -import logging -import shutil -import time import typing as t import pytest from libtmux import exc -from libtmux.common import has_version -from libtmux.pane import Pane -from libtmux.server import Server -from libtmux.window import Window if t.TYPE_CHECKING: from libtmux.session import Session -logger = logging.getLogger(__name__) - - -def test_select_window(session: Session) -> None: - """Test Window.select_window().""" - window_count = len(session._windows) - # to do, get option for base-index from tmux - # for now however, let's get the index from the first window. - assert window_count == 1 - - assert session.attached_window is not None - assert session.attached_window.index is not None - window_base_index = int(session.attached_window.index) - - window = session.new_window(window_name="testing 3") - - # self.assertEqual(2, - # int(session.attached_window.index)) - assert window.index is not None - assert int(window_base_index) + 1 == int(window.index) - - session.select_window(str(window_base_index)) - assert window_base_index == int(session.attached_window.index) - - session.select_window("testing 3") - assert int(window_base_index) + 1 == int(session.attached_window.index) - - assert len(session._windows) == 2 - - -def test_fresh_window_data(session: Session) -> None: - """Verify window data is fresh.""" - attached_window = session.attached_window - assert attached_window is not None - pane_base_idx = attached_window._show_option("pane-base-index", global_=True) - assert pane_base_idx is not None - pane_base_index = int(pane_base_idx) - - assert len(session.windows) == 1 - - assert len(session.attached_window.panes) == 1 - current_windows = len(session._windows) - assert session.get("session_id") != "@0" - assert current_windows == 1 - - assert len(session.attached_window.panes) == 1 - assert isinstance(session.server, Server) - # len(session.attached_window.panes)) - - assert len(session.windows) == 1 - assert len(session.attached_window.panes) == 1 - for w in session.windows: - assert isinstance(w, Window) - window = session.attached_window - assert isinstance(window, Window) - assert len(session.attached_window.panes) == 1 - window.split_window() - - attached_window = session.attached_window - assert attached_window is not None - attached_window.select_pane(pane_base_index) - - attached_pane = session.attached_pane - assert attached_pane is not None - attached_pane.send_keys("cd /srv/www/flaskr") - - attached_window.select_pane(pane_base_index + 1) - attached_pane = session.attached_pane - assert attached_pane is not None - attached_pane.send_keys("source .venv/bin/activate") - session.new_window(window_name="second") - current_windows += 1 - assert current_windows == len(session._windows) - session.new_window(window_name="hey") - current_windows += 1 - assert current_windows == len(session._windows) - - session.select_window("1") - session.kill_window(target_window="hey") - current_windows -= 1 - assert current_windows == len(session._windows) - - -def test_newest_pane_data(session: Session) -> None: - """Test window.panes has fresh data.""" - window = session.new_window(window_name="test", attach=True) - assert isinstance(window, Window) - assert len(window.panes) == 1 - window.split_window(attach=True) - - assert len(window.panes) == 2 - # note: the below used to accept -h, removing because split_window now - # has attach as its only argument now - window.split_window(attach=True) - assert len(window.panes) == 3 - - -def test_attached_pane(session: Session) -> None: - """Window.attached_window returns active Pane.""" - window = session.attached_window # current window - assert isinstance(window.attached_pane, Pane) - - -def test_split_window(session: Session) -> None: - """Window.split_window() splits window, returns new Pane, vertical.""" - window_name = "test split window" - window = session.new_window(window_name=window_name, attach=True) - pane = window.split_window() - assert len(window.panes) == 2 - assert isinstance(pane, Pane) - assert window.width is not None - assert window.panes[0].height is not None - assert float(window.panes[0].height) <= ((float(window.width) + 1) / 2) - - -def test_split_window_shell(session: Session) -> None: - """Window.split_window() splits window, returns new Pane, vertical.""" - window_name = "test split window" - cmd = "sleep 1m" - window = session.new_window(window_name=window_name, attach=True) - pane = window.split_window(shell=cmd) - assert len(window.panes) == 2 - assert isinstance(pane, Pane) - assert window.width is not None - assert window.panes[0].height is not None - assert float(window.panes[0].height) <= ((float(window.width) + 1) / 2) - assert pane.get("pane_start_command", "").replace('"', "") == cmd - - -def test_split_window_horizontal(session: Session) -> None: - """Window.split_window() splits window, returns new Pane, horizontal.""" - window_name = "test split window" - window = session.new_window(window_name=window_name, attach=True) - pane = window.split_window(vertical=False) - assert len(window.panes) == 2 - assert isinstance(pane, Pane) - assert window.width is not None - assert window.panes[0].width is not None - assert float(window.panes[0].width) <= ((float(window.width) + 1) / 2) - - -@pytest.mark.filterwarnings("ignore:.*deprecated in favor of Window.split()") -@pytest.mark.filterwarnings("ignore:.*vertical is not required to pass with direction.") -def test_split_percentage( - session: Session, -) -> None: - """Test deprecated percent param.""" - window = session.new_window(window_name="split window size") - window.resize(height=100, width=100) - window_height_before = ( - int(window.window_height) if isinstance(window.window_height, str) else 0 - ) - if has_version("3.4"): - pytest.skip( - "tmux 3.4 has a split-window bug." - " See https://github.com/tmux/tmux/pull/3840.", - ) - with pytest.warns(match="Deprecated in favor of size.*"): - pane = window.split_window(percent=10) - assert pane.pane_height == str(int(window_height_before * 0.1)) - - -def test_split_window_size(session: Session) -> None: - """Window.split_window() respects size.""" - window = session.new_window(window_name="split_window window size") - window.resize(height=100, width=100) - - pane = window.split_window(size=10) - assert pane.pane_height == "10" - - pane = window.split_window(vertical=False, size=10) - assert pane.pane_width == "10" - - pane = window.split_window(size="10%") - assert pane.pane_height == "8" - - pane = window.split_window(vertical=False, size="10%") - assert pane.pane_width == "8" - - -@pytest.mark.parametrize( - ("window_name_before", "window_name_after"), - [("test", "ha ha ha fjewlkjflwef"), ("test", "hello \\ wazzup 0")], -) -def test_window_rename( - session: Session, - window_name_before: str, - window_name_after: str, -) -> None: - """Test Window.rename_window().""" - window_name_before = "test" - window_name_after = "ha ha ha fjewlkjflwef" - - session.set_option("automatic-rename", "off") - window = session.new_window(window_name=window_name_before, attach=True) - - assert window == session.attached_window - assert window.get("window_name") == window_name_before - - window.rename_window(window_name_after) - - window = session.attached_window - assert window.get("window_name") == window_name_after +def test_split_window_raises_deprecated_error(session: Session) -> None: + """Test Window.split_window() raises exc.DeprecatedError.""" + window = session.active_window - window = session.attached_window + with pytest.raises( + exc.DeprecatedError, match=r"Window\.split_window\(\) was deprecated" + ): + window.split_window() - assert window.get("window_name") == window_name_after +def test_attached_pane_raises_deprecated_error(session: Session) -> None: + """Test Window.attached_pane raises exc.DeprecatedError.""" + window = session.active_window -def test_kill_window(session: Session) -> None: - """Test window.kill_window() kills window.""" - session.new_window() - # create a second window to not kick out the client. - # there is another way to do this via options too. + with pytest.raises( + exc.DeprecatedError, match=r"Window\.attached_pane was deprecated" + ): + _ = window.attached_pane - w = session.attached_window - assert isinstance(w.get("window_id"), str) - assert len(session.windows.filter(window_id=w.get("window_id"))) == 1 +def test_select_window_raises_deprecated_error(session: Session) -> None: + """Test Window.select_window() raises exc.DeprecatedError.""" + window = session.active_window - w.kill_window() + with pytest.raises( + exc.DeprecatedError, match=r"Window\.select_window\(\) was deprecated" + ): + window.select_window() - assert len(session.windows.filter(window_id=w.get("window_id"))) == 0 +def test_kill_window_raises_deprecated_error(session: Session) -> None: + """Test Window.kill_window() raises exc.DeprecatedError.""" + # Create a new window to kill (so we don't kill our only window) + session.new_window(window_name="extra_window") + window = session.active_window -def test_show_window_options(session: Session) -> None: - """Window.show_window_options() returns dict.""" - window = session.new_window(window_name="test_window") + with pytest.raises( + exc.DeprecatedError, match=r"Window\.kill_window\(\) was deprecated" + ): + window.kill_window() - options = window.show_window_options() - assert isinstance(options, dict) +def test_set_window_option_emits_deprecation_warning(session: Session) -> None: + """Test Window.set_window_option() emits DeprecationWarning.""" + window = session.active_window -def test_set_window_and_show_window_options(session: Session) -> None: - """Window.set_window_option() then Window.show_window_options(key).""" - window = session.new_window(window_name="test_window") + with pytest.warns( + DeprecationWarning, match=r"Window\.set_window_option\(\) is deprecated" + ): + window.set_window_option("main-pane-height", 20) - window.set_window_option("main-pane-height", 20) - assert window.show_window_option("main-pane-height") == 20 - window.set_window_option("main-pane-height", 40) - assert window.show_window_option("main-pane-height") == 40 - assert window.show_window_options()["main-pane-height"] == 40 +def test_show_window_options_emits_deprecation_warning(session: Session) -> None: + """Test Window.show_window_options() emits DeprecationWarning.""" + window = session.active_window - window.set_window_option("pane-border-format", " #P ") - assert window.show_window_option("pane-border-format") == " #P " + with pytest.warns( + DeprecationWarning, match=r"Window\.show_window_options\(\) is deprecated" + ): + window.show_window_options() -def test_empty_window_option_returns_None(session: Session) -> None: - """Verify unset window option returns None.""" - window = session.new_window(window_name="test_window") - assert window.show_window_option("alternate-screen") is None +def test_show_window_option_emits_deprecation_warning(session: Session) -> None: + """Test Window.show_window_option() emits DeprecationWarning.""" + window = session.active_window + with pytest.warns( + DeprecationWarning, match=r"Window\.show_window_option\(\) is deprecated" + ): + window.show_window_option("main-pane-height") -def test_show_window_option(session: Session) -> None: - """Set option then Window.show_window_option(key).""" - window = session.new_window(window_name="test_window") - window.set_window_option("main-pane-height", 20) - assert window.show_window_option("main-pane-height") == 20 +def test_window_get_raises_deprecated_error(session: Session) -> None: + """Test Window.get() raises exc.DeprecatedError.""" + window = session.active_window - window.set_window_option("main-pane-height", 40) - assert window.show_window_option("main-pane-height") == 40 - assert window.show_window_option("main-pane-height") == 40 + with pytest.raises(exc.DeprecatedError, match=r"Window\.get\(\) was deprecated"): + window.get("window_id") -def test_show_window_option_unknown(session: Session) -> None: - """Window.show_window_option raises InvalidOption for bad option key.""" - window = session.new_window(window_name="test_window") +def test_window_getitem_raises_deprecated_error(session: Session) -> None: + """Test Window.__getitem__() raises exc.DeprecatedError.""" + window = session.active_window - with pytest.raises(exc.InvalidOption): - window.show_window_option("moooz") + with pytest.raises( + exc.DeprecatedError, match=r"Window\[key\] lookup was deprecated" + ): + _ = window["window_id"] -def test_show_window_option_ambiguous(session: Session) -> None: - """show_window_option raises AmbiguousOption for ambiguous option.""" - window = session.new_window(window_name="test_window") +def test_window_get_by_id_raises_deprecated_error(session: Session) -> None: + """Test Window.get_by_id() raises exc.DeprecatedError.""" + window = session.active_window - with pytest.raises(exc.AmbiguousOption): - window.show_window_option("clock-mode") + with pytest.raises( + exc.DeprecatedError, match=r"Window\.get_by_id\(\) was deprecated" + ): + window.get_by_id("%0") -def test_set_window_option_ambiguous(session: Session) -> None: - """set_window_option raises AmbiguousOption for ambiguous option.""" - window = session.new_window(window_name="test_window") +def test_window_where_raises_deprecated_error(session: Session) -> None: + """Test Window.where() raises exc.DeprecatedError.""" + window = session.active_window - with pytest.raises(exc.AmbiguousOption): - window.set_window_option("clock-mode", 12) + with pytest.raises(exc.DeprecatedError, match=r"Window\.where\(\) was deprecated"): + window.where({"pane_id": "%0"}) -def test_set_window_option_invalid(session: Session) -> None: - """Window.set_window_option raises InvalidOption for invalid option key.""" - window = session.new_window(window_name="test_window") +def test_window_find_where_raises_deprecated_error(session: Session) -> None: + """Test Window.find_where() raises exc.DeprecatedError.""" + window = session.active_window - with pytest.raises(exc.InvalidOption): - window.set_window_option("afewewfew", 43) + with pytest.raises( + exc.DeprecatedError, match=r"Window\.find_where\(\) was deprecated" + ): + window.find_where({"pane_id": "%0"}) -def test_move_window(session: Session) -> None: - """Window.move_window results in changed index.""" - window = session.new_window(window_name="test_window") - assert window.index is not None - new_index = str(int(window.index) + 1) - window.move_window(new_index) - assert window.index == new_index +def test_window_list_panes_raises_deprecated_error(session: Session) -> None: + """Test Window.list_panes() raises exc.DeprecatedError.""" + window = session.active_window + with pytest.raises( + exc.DeprecatedError, match=r"Window\.list_panes\(\) was deprecated" + ): + window.list_panes() -def test_move_window_to_other_session(server: Server, session: Session) -> None: - """Window.move_window to other session.""" - window = session.new_window(window_name="test_window") - new_session = server.new_session("test_move_window") - window.move_window(session=new_session.get("session_id")) - window_id = window.get("window_id") - assert window_id is not None - assert new_session.get_by_id(window_id) == window +def test_window_children_raises_deprecated_error(session: Session) -> None: + """Test Window.children raises exc.DeprecatedError.""" + window = session.active_window -def test_select_layout_accepts_no_arg(server: Server, session: Session) -> None: - """Tmux allows select-layout with no arguments, so let's allow it here.""" - window = session.new_window(window_name="test_window") - window.select_layout() + with pytest.raises(exc.DeprecatedError, match=r"Window\.children was deprecated"): + _ = window.children -def test_empty_window_name(session: Session) -> None: - """New windows can be created with empty string for window name.""" - session.set_option("automatic-rename", "off") - window = session.new_window(window_name="''", attach=True) +def test_window__panes_raises_deprecated_error(session: Session) -> None: + """Test Window._panes raises exc.DeprecatedError.""" + window = session.active_window - assert window == session.attached_window - assert window.get("window_name") == "''" - assert session.name is not None + with pytest.raises(exc.DeprecatedError, match=r"Window\._panes was deprecated"): + _ = window._panes - cmd = session.cmd( - "list-windows", - "-F", - "#{window_name}", - "-f", - "#{==:#{session_name}," + session.name + "}", - ) - assert "''" in cmd.stdout +def test_window__list_panes_raises_deprecated_error(session: Session) -> None: + """Test Window._list_panes() raises exc.DeprecatedError.""" + window = session.active_window -@pytest.mark.parametrize( - "environment", - [ - {"ENV_VAR": "pane"}, - {"ENV_VAR_1": "pane_1", "ENV_VAR_2": "pane_2"}, - ], -) -def test_split_window_with_environment( - session: Session, - environment: dict[str, str], -) -> None: - """Verify splitting window with environment variables.""" - env = shutil.which("env") - assert env is not None, "Cannot find usable `env` in Path." - - window = session.new_window(window_name="split_window_with_environment") - pane = window.split_window( - shell=f"{env} PS1='$ ' sh", - environment=environment, - ) - assert pane is not None - # wait a bit for the prompt to be ready as the test gets flaky otherwise - time.sleep(0.05) - for k, v in environment.items(): - pane.send_keys(f"echo ${k}") - assert pane.capture_pane()[-2] == v + with pytest.raises( + exc.DeprecatedError, match=r"Window\._list_panes\(\) was deprecated" + ): + window._list_panes() diff --git a/tests/test/test_retry.py b/tests/test/test_retry.py index ca09d8b4f..c2a0f9255 100644 --- a/tests/test/test_retry.py +++ b/tests/test/test_retry.py @@ -6,7 +6,7 @@ import pytest -from libtmux.exc import WaitTimeout +from libtmux import exc from libtmux.test.retry import retry_until @@ -42,7 +42,7 @@ def never_true() -> bool: ) # Sleep for 0.1 seconds to simulate work (called ~10 times in 1 second) return False - with pytest.raises(WaitTimeout): + with pytest.raises(exc.WaitTimeout): retry_until(never_true, 1) end = time() diff --git a/tests/test_common.py b/tests/test_common.py index 24b4ecf6d..a3345be8d 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -9,6 +9,7 @@ import pytest import libtmux +from libtmux import exc from libtmux._compat import LooseVersion from libtmux.common import ( TMUX_MAX_VERSION, @@ -24,7 +25,6 @@ session_check_name, tmux_cmd, ) -from libtmux.exc import BadSessionName, LibTmuxException, TmuxCommandNotFound if t.TYPE_CHECKING: from libtmux.session import Session @@ -40,7 +40,7 @@ def test_has_version() -> None: def test_tmux_cmd_raises_on_not_found(monkeypatch: pytest.MonkeyPatch) -> None: """Verify raises if tmux command not found.""" monkeypatch.setenv("PATH", "") - with pytest.raises(TmuxCommandNotFound): + with pytest.raises(exc.TmuxCommandNotFound): tmux_cmd("-V") @@ -111,7 +111,7 @@ def test_session_check_name( ) -> None: """Verify session_check_name().""" if raises: - with pytest.raises(BadSessionName) as exc_info: + with pytest.raises(exc.BadSessionName) as exc_info: session_check_name(session_name) if exc_msg_regex is not None: assert exc_info.match(exc_msg_regex) @@ -355,7 +355,7 @@ def mock_tmux_cmd(*args: t.Any, **kwargs: t.Any) -> MockTmuxOutput: monkeypatch.setattr(sys, "platform", mock_platform) if raises: - with pytest.raises(LibTmuxException) as exc_info: + with pytest.raises(exc.LibTmuxException) as exc_info: get_version() if exc_msg_regex is not None: exc_info.match(exc_msg_regex) @@ -499,7 +499,7 @@ def mock_get_version() -> LooseVersion: if check_type == "min_version": if raises: - with pytest.raises(LibTmuxException) as exc_info: + with pytest.raises(exc.LibTmuxException) as exc_info: has_minimum_version() if exc_msg_regex is not None: exc_info.match(exc_msg_regex) diff --git a/tests/test_dataclasses.py b/tests/test_dataclasses.py index 7a84f56b6..4fcc05207 100644 --- a/tests/test_dataclasses.py +++ b/tests/test_dataclasses.py @@ -65,8 +65,8 @@ def test_pane( old_pane_size = pane.pane_height - pane.resize_pane(adjustment_direction=ResizeAdjustmentDirection.Down, adjustment=25) - pane.resize_pane( + pane.resize(adjustment_direction=ResizeAdjustmentDirection.Down, adjustment=25) + pane.resize( adjustment_direction=ResizeAdjustmentDirection.Right, adjustment=25, ) diff --git a/tests/test_hooks.py b/tests/test_hooks.py index 1e0c1b1ac..4e03f0a26 100644 --- a/tests/test_hooks.py +++ b/tests/test_hooks.py @@ -19,8 +19,8 @@ def test_hooks_raw_cmd( ) -> None: """Raw hook set, show, unset via cmd.""" session = server.new_session(session_name="test hooks") - window = session.attached_window - pane = window.attached_pane + window = session.active_window + pane = window.active_pane assert pane is not None # @@ -198,8 +198,8 @@ def test_hooks_dataclass( ) -> None: """Tests for hooks dataclass.""" session = server.new_session(session_name="test hooks") - window = session.attached_window - pane = window.attached_pane + window = session.active_window + pane = window.active_pane assert pane is not None # @@ -277,8 +277,8 @@ def test_hooks_mixin( ) -> None: """Tests for hooks.""" session = server.new_session(session_name="test hooks") - window = session.attached_window - pane = window.attached_pane + window = session.active_window + pane = window.active_pane assert pane is not None pane.set_hook("session-renamed[0]", "set -g status-left-style bg=red") diff --git a/tests/test_options.py b/tests/test_options.py index cc3e94b3f..9cca8bd9b 100644 --- a/tests/test_options.py +++ b/tests/test_options.py @@ -8,6 +8,7 @@ import pytest +from libtmux import exc from libtmux._internal.constants import ( Options, PaneOptions, @@ -18,7 +19,6 @@ from libtmux._internal.sparse_array import SparseArray from libtmux.common import has_gte_version from libtmux.constants import OptionScope -from libtmux.exc import OptionError from libtmux.options import TerminalOverrides, convert_values, explode_arrays from libtmux.pane import Pane @@ -33,24 +33,24 @@ def test_options(server: Server) -> None: """Test basic options.""" session = server.new_session(session_name="test") window = session.new_window(window_name="test") - pane = window.split_window(attach=False) + pane = window.split(attach=False) for obj in [server, session, window, pane]: obj._show_options() obj._show_options(global_=True) obj._show_options(include_inherited=True) obj._show_options(include_hooks=True) - with pytest.raises(OptionError): + with pytest.raises(exc.OptionError): obj._show_option("test") if has_gte_version("3.0"): obj._show_option("test", ignore_errors=True) - with pytest.raises(OptionError): + with pytest.raises(exc.OptionError): obj.set_option("test", "invalid") if isinstance(obj, Pane): if has_gte_version("3.0"): obj.set_option("test", "invalid", ignore_errors=True) else: - with pytest.raises(OptionError): + with pytest.raises(exc.OptionError): obj.set_option("test", "invalid", ignore_errors=True) else: obj.set_option("test", "invalid", ignore_errors=True) @@ -60,7 +60,7 @@ def test_options_server(server: Server) -> None: """Test server options.""" session = server.new_session(session_name="test") window = session.new_window(window_name="test") - pane = window.split_window(attach=False) + pane = window.split(attach=False) server.set_option("buffer-limit", 100) assert server._show_option("buffer-limit") == 100 @@ -84,7 +84,7 @@ def test_options_server(server: Server) -> None: if has_gte_version("3.0"): pane.set_option("buffer-limit", 100) else: - with pytest.raises(OptionError): + with pytest.raises(exc.OptionError): pane.set_option("buffer-limit", 100) if has_gte_version("3.0"): @@ -122,7 +122,7 @@ def test_options_window(server: Server) -> None: """Test window options.""" session = server.new_session(session_name="test") window = session.new_window(window_name="test") - window.split_window(attach=False) + window.split(attach=False) window_options_ = window._show_options(scope=OptionScope.Window) @@ -134,7 +134,7 @@ def test_options_pane(server: Server) -> None: """Test pane options.""" session = server.new_session(session_name="test") window = session.new_window(window_name="test") - pane = window.split_window(attach=False) + pane = window.split(attach=False) pane_options_ = pane._show_options(scope=OptionScope.Pane) @@ -146,7 +146,7 @@ def test_options_grid(server: Server) -> None: """Test options against grid.""" session = server.new_session(session_name="test") window = session.new_window(window_name="test") - pane = window.split_window(attach=False) + pane = window.split(attach=False) for include_inherited in [True, False]: for global_ in [True, False]: @@ -501,7 +501,7 @@ def test_show_option_pane_fixture( """Test Pane.show_option(s)?.""" session = server.new_session(session_name="test") window = session.new_window(window_name="test") - pane = window.split_window(attach=False) + pane = window.split(attach=False) monkeypatch.setattr(pane, "cmd", fake_cmd(stdout=mocked_cmd_stdout)) @@ -566,7 +566,7 @@ def test_stable_baseline_options_and_hooks(server: Server) -> None: status_format = server.show_option("status-format") assert isinstance(status_format, (dict, type(None))) else: - with pytest.raises(OptionError): + with pytest.raises(exc.OptionError): server.show_option("status-format") # update-environment was added in tmux 3.0 @@ -574,7 +574,7 @@ def test_stable_baseline_options_and_hooks(server: Server) -> None: update_env = server.show_option("update-environment") assert isinstance(update_env, (list, type(None))) else: - with pytest.raises(OptionError): + with pytest.raises(exc.OptionError): server.show_option("update-environment") # List variables: Pane (pane-colours added in tmux 3.3) @@ -653,7 +653,7 @@ def test_style_option_validation(server: Server) -> None: assert "bg=default" not in str(style) # Invalid style should raise OptionError - with pytest.raises(OptionError): + with pytest.raises(exc.OptionError): session.set_option("status-style", "invalid-style") # Test complex style with multiple attributes (tmux >= 3.0) @@ -684,18 +684,18 @@ def test_option_error_handling(server: Server) -> None: session = server.new_session(session_name="test") # Test invalid/unknown option (tmux 3.0+ returns 'invalid option') - with pytest.raises(OptionError) as exc_info: + with pytest.raises(exc.OptionError) as exc_info: session.show_option("non-existent-option") error_msg = str(exc_info.value).lower() assert any(msg in error_msg for msg in ["unknown option", "invalid option"]) # Test invalid option value - with pytest.raises(OptionError): + with pytest.raises(exc.OptionError): session.set_option("aggressive-resize", "invalid") # Test ambiguous option (if supported by tmux version) if has_gte_version("2.4"): - with pytest.raises(OptionError) as exc_info: + with pytest.raises(exc.OptionError) as exc_info: # Use a partial name that could match multiple options session.show_option( "window-" diff --git a/tests/test_pane.py b/tests/test_pane.py index 015a7218c..b57365bef 100644 --- a/tests/test_pane.py +++ b/tests/test_pane.py @@ -183,10 +183,10 @@ def test_pane_split_window_zoom( assert pane_with_zoom.height == pane_with_zoom.window_height -def test_resize_pane( +def test_resize( session: Session, ) -> None: - """Verify resizing window.""" + """Verify resizing pane.""" session.cmd("detach-client", "-s") window = session.active_window @@ -208,14 +208,14 @@ def test_resize_pane( # Manual: Height pane_height_before = int(pane.pane_height) - pane.resize_pane( + pane.resize( height="50", ) assert int(pane.pane_height) == 50 # Manual: Width window.select_layout("main-horizontal") - pane.resize_pane( + pane.resize( width="75", ) assert int(pane.pane_width) == 75 @@ -223,14 +223,14 @@ def test_resize_pane( # Manual: Height percentage window.select_layout("main-vertical") pane_height_before = int(pane.pane_height) - pane.resize_pane( + pane.resize( height="15%", ) assert int(pane.pane_height) == 75 # Manual: Width percentage window.select_layout("main-horizontal") - pane.resize_pane( + pane.resize( width="15%", ) assert int(pane.pane_width) == 75 @@ -241,7 +241,7 @@ def test_resize_pane( # Adjustment: Down pane_height_before = int(pane.pane_height) - pane.resize_pane( + pane.resize( adjustment_direction=ResizeAdjustmentDirection.Down, adjustment=pane_height_adjustment * 2, ) @@ -249,7 +249,7 @@ def test_resize_pane( # Adjustment: Up pane_height_before = int(pane.pane_height) - pane.resize_pane( + pane.resize( adjustment_direction=ResizeAdjustmentDirection.Up, adjustment=pane_height_adjustment, ) @@ -258,12 +258,12 @@ def test_resize_pane( # # Zoom # - pane.resize_pane(height=50) + pane.resize(height=50) # Zoom - pane.resize_pane(height=2) + pane.resize(height=2) pane_height_before = int(pane.pane_height) - pane.resize_pane( + pane.resize( zoom=True, ) pane_height_expanded = int(pane.pane_height) diff --git a/tests/test_window.py b/tests/test_window.py index 084ba407e..5ea57f3c5 100644 --- a/tests/test_window.py +++ b/tests/test_window.py @@ -86,13 +86,17 @@ def test_fresh_window_data(session: Session) -> None: active_window = session.active_window assert active_window is not None - active_window.select_pane(pane_base_index) + pane_to_select = active_window.panes.get(pane_index=str(pane_base_index)) + assert pane_to_select is not None + pane_to_select.select() active_pane = session.active_pane assert active_pane is not None active_pane.send_keys("cd /srv/www/flaskr") - active_window.select_pane(pane_base_index + 1) + pane_to_select_2 = active_window.panes.get(pane_index=str(pane_base_index + 1)) + assert pane_to_select_2 is not None + pane_to_select_2.select() active_pane = session.active_pane assert active_pane is not None active_pane.send_keys("source .venv/bin/activate") @@ -104,7 +108,9 @@ def test_fresh_window_data(session: Session) -> None: assert current_windows == len(session.windows) session.select_window("1") - session.kill_window(target_window="hey") + window_to_kill = session.windows.get(window_name="hey") + assert window_to_kill is not None + window_to_kill.kill() current_windows -= 1 assert current_windows == len(session.windows) @@ -247,7 +253,7 @@ def test_window_rename( def test_kill_window(session: Session) -> None: - """Test window.kill_window() kills window.""" + """Test window.kill() kills window.""" session.new_window() # create a second window to not kick out the client. # there is another way to do this via options too. @@ -256,16 +262,16 @@ def test_kill_window(session: Session) -> None: assert w.window_id is not None - w.kill_window() + w.kill() with pytest.raises(ObjectDoesNotExist): w.refresh() def test_show_window_options(session: Session) -> None: - """Window.show_window_options() returns dict.""" + """Window.show_options() returns dict.""" window = session.new_window(window_name="test_window") - options = window.show_window_options() + options = window.show_options() assert isinstance(options, dict) options_2 = window._show_options() @@ -291,18 +297,18 @@ def test_show_window_options(session: Session) -> None: def test_set_window_and_show_window_options(session: Session) -> None: - """Window.set_window_option() then Window.show_window_options(key).""" + """Window.set_option() then Window.show_option(key).""" window = session.new_window(window_name="test_window") - window.set_window_option("main-pane-height", 20) - assert window.show_window_option("main-pane-height") == 20 + window.set_option("main-pane-height", 20) + assert window.show_option("main-pane-height") == 20 - window.set_window_option("main-pane-height", 40) - assert window.show_window_option("main-pane-height") == 40 - assert window.show_window_options()["main-pane-height"] == 40 + window.set_option("main-pane-height", 40) + assert window.show_option("main-pane-height") == 40 + assert window.show_options()["main-pane-height"] == 40 - window.set_window_option("pane-border-format", " #P ") - assert window.show_window_option("pane-border-format") == " #P " + window.set_option("pane-border-format", " #P ") + assert window.show_option("pane-border-format") == " #P " def test_set_and_show_window_options(session: Session) -> None: @@ -328,51 +334,51 @@ def test_set_and_show_window_options(session: Session) -> None: def test_empty_window_option_returns_None(session: Session) -> None: """Verify unset window option returns None.""" window = session.new_window(window_name="test_window") - assert window.show_window_option("alternate-screen") is None + assert window.show_option("alternate-screen") is None def test_show_window_option(session: Session) -> None: - """Set option then Window.show_window_option(key).""" + """Set option then Window.show_option(key).""" window = session.new_window(window_name="test_window") - window.set_window_option("main-pane-height", 20) - assert window.show_window_option("main-pane-height") == 20 + window.set_option("main-pane-height", 20) + assert window.show_option("main-pane-height") == 20 - window.set_window_option("main-pane-height", 40) - assert window.show_window_option("main-pane-height") == 40 - assert window.show_window_option("main-pane-height") == 40 + window.set_option("main-pane-height", 40) + assert window.show_option("main-pane-height") == 40 + assert window.show_option("main-pane-height") == 40 def test_show_window_option_unknown(session: Session) -> None: - """Window.show_window_option raises InvalidOption for bad option key.""" + """Window.show_option raises InvalidOption for bad option key.""" window = session.new_window(window_name="test_window") with pytest.raises(exc.InvalidOption): - window.show_window_option("moooz") + window.show_option("moooz") def test_show_window_option_ambiguous(session: Session) -> None: - """show_window_option raises AmbiguousOption for ambiguous option.""" + """show_option raises AmbiguousOption for ambiguous option.""" window = session.new_window(window_name="test_window") with pytest.raises(exc.AmbiguousOption): - window.show_window_option("clock-mode") + window.show_option("clock-mode") def test_set_window_option_ambiguous(session: Session) -> None: - """set_window_option raises AmbiguousOption for ambiguous option.""" + """set_option raises AmbiguousOption for ambiguous option.""" window = session.new_window(window_name="test_window") with pytest.raises(exc.AmbiguousOption): - window.set_window_option("clock-mode", 12) + window.set_option("clock-mode", 12) def test_set_window_option_invalid(session: Session) -> None: - """Window.set_window_option raises InvalidOption for invalid option key.""" + """Window.set_option raises InvalidOption for invalid option key.""" window = session.new_window(window_name="test_window") with pytest.raises(exc.InvalidOption): - window.set_window_option("afewewfew", 43) + window.set_option("afewewfew", 43) def test_move_window(session: Session) -> None: @@ -710,70 +716,57 @@ def test_split_start_directory_pathlib( class DeprecatedMethodTestCase(t.NamedTuple): - """Test case for deprecated method warnings.""" + """Test case for deprecated method errors.""" test_id: str method_name: str # Name of deprecated method to call args: tuple[t.Any, ...] # Positional args kwargs: dict[str, t.Any] # Keyword args - expected_warning_match: str # Regex pattern to match warning message + expected_error_match: str # Regex pattern to match error message -DEPRECATED_WINDOW_METHOD_TEST_CASES: list[DeprecatedMethodTestCase] = [ +# These methods were deprecated in 0.50.0 and still emit warnings (not errors) +DEPRECATED_WARNING_WINDOW_METHOD_TEST_CASES: list[DeprecatedMethodTestCase] = [ DeprecatedMethodTestCase( test_id="set_window_option", method_name="set_window_option", args=("main-pane-height", 20), kwargs={}, - expected_warning_match=r"Window\.set_window_option\(\) is deprecated", + expected_error_match=r"Window\.set_window_option\(\) is deprecated", ), DeprecatedMethodTestCase( test_id="show_window_options", method_name="show_window_options", args=(), kwargs={}, - expected_warning_match=r"Window\.show_window_options\(\) is deprecated", - ), - DeprecatedMethodTestCase( - test_id="show_window_options_global", - method_name="show_window_options", - args=(), - kwargs={"g": True}, - expected_warning_match=r"Window\.show_window_options\(\) is deprecated", + expected_error_match=r"Window\.show_window_options\(\) is deprecated", ), DeprecatedMethodTestCase( test_id="show_window_option", method_name="show_window_option", args=("main-pane-height",), kwargs={}, - expected_warning_match=r"Window\.show_window_option\(\) is deprecated", - ), - DeprecatedMethodTestCase( - test_id="show_window_option_global", - method_name="show_window_option", - args=("main-pane-height",), - kwargs={"g": True}, - expected_warning_match=r"Window\.show_window_option\(\) is deprecated", + expected_error_match=r"Window\.show_window_option\(\) is deprecated", ), ] -def _build_deprecated_method_params() -> list[t.Any]: - """Build pytest params for deprecated method tests.""" +def _build_deprecated_warning_method_params() -> list[t.Any]: + """Build pytest params for deprecated method warning tests.""" return [ - pytest.param(tc, id=tc.test_id) for tc in DEPRECATED_WINDOW_METHOD_TEST_CASES + pytest.param(tc, id=tc.test_id) + for tc in DEPRECATED_WARNING_WINDOW_METHOD_TEST_CASES ] -@pytest.mark.filterwarnings("ignore:g argument is deprecated:DeprecationWarning") -@pytest.mark.parametrize("test_case", _build_deprecated_method_params()) +@pytest.mark.parametrize("test_case", _build_deprecated_warning_method_params()) def test_deprecated_window_methods_emit_warning( session: Session, test_case: DeprecatedMethodTestCase, ) -> None: - """Verify deprecated Window methods emit DeprecationWarning.""" + """Verify deprecated Window methods emit DeprecationWarning (0.50.0).""" window = session.new_window(window_name="test_deprecation") method = getattr(window, test_case.method_name) - with pytest.warns(DeprecationWarning, match=test_case.expected_warning_match): + with pytest.warns(DeprecationWarning, match=test_case.expected_error_match): method(*test_case.args, **test_case.kwargs)