Skip to content

Dataclasses #371

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/libtmux/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
~~~~~~~~~~~~~~

"""
import dataclasses
import logging
import os
import re
Expand Down Expand Up @@ -320,6 +321,15 @@ def __len__(self) -> int:
return len(self._info.keys())

def __getattr__(self, key: str) -> str:
try:
# val = self._info[self.formatter_prefix + key]
val = object.__getattribute__(self, key)
assert val is not None
assert isinstance(val, str)
return val
except AttributeError:
pass

try:
val = self._info[self.formatter_prefix + key]
assert val is not None
Expand Down Expand Up @@ -405,9 +415,12 @@ def where(self, attrs: D, first: bool = False) -> t.Union[List[O], O]:

# from https://github.com/serkanyersen/underscore.py
def by(val: O) -> bool:
val2: t.Dict[str, str] = {}
if dataclasses.is_dataclass(val):
val2 = dataclasses.asdict(val)
for key in attrs.keys():
try:
if attrs[key] != val[key]:
if attrs[key] != val[key] and attrs[key] != val2[key]:
return False
except KeyError:
return False
Expand Down
121 changes: 93 additions & 28 deletions src/libtmux/pane.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@
~~~~~~~~~~~~

"""
from __future__ import annotations

import dataclasses
import logging
import typing as t
from typing import overload

import libtmux
from libtmux.common import tmux_cmd

from . import exc
from .common import PaneDict, TmuxMappingObject, TmuxRelationalObject
from .common import PaneDict, TmuxMappingObject

if t.TYPE_CHECKING:
from typing_extensions import Literal
Expand All @@ -24,8 +28,14 @@

logger = logging.getLogger(__name__)

__all__ = ["Pane"]


class Pane(TmuxMappingObject):
@dataclasses.dataclass
# <<<<<<< HEAD:src/libtmux/pane.py
# class Pane(TmuxMappingObject):
# =======
class Pane:
"""
A :term:`tmux(1)` :term:`Pane` [pane_manual]_.

Expand Down Expand Up @@ -68,35 +78,90 @@ class Pane(TmuxMappingObject):
Accessed April 1st, 2018.
"""

formatter_prefix = "pane_"
window: libtmux.window.Window
session_name: str = dataclasses.field(init=True)
session_id: str = dataclasses.field(init=True)
window_index: str = dataclasses.field(init=True)
window_id: str = dataclasses.field(init=True)
history_size: str
history_limit: str
history_bytes: str
pane_index: str
pane_width: str
pane_height: str
pane_title: str
_pane_id: str = dataclasses.field(init=False) # Legacy, relational
pane_id: str
pane_active: str
pane_dead: str
pane_in_mode: str
pane_synchronized: str
pane_tty: str
pane_pid: str
pane_current_path: str
pane_current_command: str
cursor_x: str
cursor_y: str
scroll_region_upper: str
scroll_region_lower: str
alternate_on: str
alternate_saved_x: str
alternate_saved_y: str
cursor_flag: str
insert_flag: str
keypad_cursor_flag: str
keypad_flag: str
wrap_flag: str
mouse_standard_flag: str
mouse_button_flag: str
mouse_any_flag: str
mouse_utf8_flag: str
session: libtmux.session.Session = dataclasses.field(init=False)
server: libtmux.server.Server = dataclasses.field(init=False)
window_name: str = dataclasses.field(init=True, default="")
pane_start_command: t.Optional[str] = dataclasses.field(init=True, default=None)

formatter_prefix: str = "pane_"
"""Namespace used for :class:`~libtmux.common.TmuxMappingObject`"""
window: "Window"
""":class:`libtmux.Window` pane is linked to"""
session: "Session"
""":class:`libtmux.Session` pane is linked to"""
server: "Server"
""":class:`libtmux.Server` pane is linked to"""

def __init__(
self,
window: "Window",
pane_id: t.Union[str, int],
**kwargs: t.Any,
) -> None:
self.window = window

def __post_init__(self, **kwargs: t.Any) -> None:
# if not window:
# raise ValueError("Pane must have ``Window`` object")
#
# self.window = window
self.session = self.window.session
self.server = self.session.server

self._pane_id = pane_id
self._pane_id = kwargs.get("pane_id", self.pane_id)

try:
info = self._info
except IndexError:
info = {}
for k, v in info.items():
if not hasattr(k, v):
setattr(self, k, v)

self.server._update_panes()

def refresh(self) -> None:
try:
info = self._info
except IndexError:
info = {}
for k, v in info.items():
if not hasattr(k, v):
setattr(self, k, v)

@property
def _info(self) -> PaneDict: # type: ignore # mypy#1362
attrs = {"pane_id": self._pane_id}
# attrs = {"pane_id": self._pane_id}
attrs = {"pane_id": object.__getattribute__(self, "_pane_id")}

# from https://github.com/serkanyersen/underscore.py
def by(val: PaneDict) -> bool:
if dataclasses.is_dataclass(val):
val = dataclasses.asdict(val)
for key in attrs.keys():
try:
if attrs[key] != val[key]:
Expand All @@ -122,7 +187,7 @@ def cmd(self, cmd: str, *args: t.Any, **kwargs: t.Any) -> tmux_cmd:
:class:`Server.cmd`
"""
if not any(arg.startswith("-t") for arg in args):
args = ("-t", self.get("pane_id")) + args
args = ("-t", self.pane_id) + args

return self.server.cmd(cmd, *args, **kwargs)

Expand Down Expand Up @@ -251,7 +316,7 @@ def split_window(
:class:`Pane`
"""
return self.window.split_window(
target=self.get("pane_id"),
target=self.pane_id,
start_directory=start_directory,
attach=attach,
vertical=vertical,
Expand Down Expand Up @@ -315,6 +380,7 @@ def resize_pane(self, *args: t.Any, **kwargs: t.Any) -> "Pane":
raise exc.LibTmuxException(proc.stderr)

self.server._update_panes()
self.refresh()
return self

def enter(self) -> None:
Expand Down Expand Up @@ -349,12 +415,11 @@ def select_pane(self) -> "Pane":
-------
:class:`pane`
"""
pane = self.window.select_pane(self._pane_id)
if pane is None:
raise exc.LibTmuxException(f"Pane not found: {self}")
return pane
# pane = self.window.select_pane(self._pane_id)
# if pane is None:
# raise exc.LibTmuxException(f"Pane not found: {self}")
# return pane
return self.window.select_pane(self.pane_id)

def __repr__(self) -> str:
return "{}({} {})".format(
self.__class__.__name__, self.get("pane_id"), self.window
)
return "{}({} {})".format(self.__class__.__name__, self.pane_id, self.window)
3 changes: 2 additions & 1 deletion src/libtmux/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ def __init__(self, server: "Server", session_id: str, **kwargs: t.Any) -> None:

@property
def _info(self) -> t.Optional[SessionDict]: # type: ignore # mypy#1362
attrs = {"session_id": str(self._session_id)}
# attrs = {"session_id": str(self._session_id)}
attrs = {"session_id": object.__getattribute__(self, "_session_id")}

def by(val: SessionDict) -> bool:
for key in attrs.keys():
Expand Down
5 changes: 3 additions & 2 deletions src/libtmux/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ def __repr__(self) -> str:

@property
def _info(self) -> WindowDict: # type: ignore # mypy#1362
attrs = {"window_id": self._window_id}
# attrs = {"window_id": self._window_id}
attrs = {"window_id": object.__getattribute__(self, "_window_id")}

# from https://github.com/serkanyersen/underscore.py
def by(val: WindowDict) -> bool:
Expand Down Expand Up @@ -500,7 +501,7 @@ def split_window(
if target:
tmux_args += ("-t%s" % target,)
else:
tmux_args += ("-t%s" % self.panes[0].get("pane_id"),)
tmux_args += ("-t%s" % self.panes[0].pane_id,)

if vertical:
tmux_args += ("-v",)
Expand Down
20 changes: 10 additions & 10 deletions tests/test_pane.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ def test_resize_pane(session: Session) -> None:

pane1 = window.attached_pane
assert pane1 is not None
pane1_height = pane1["pane_height"]
pane1_height = pane1.pane_height
window.split_window()

pane1.resize_pane(height=4)
assert pane1["pane_height"] != pane1_height
assert int(pane1["pane_height"]) == 4
assert pane1.pane_height != pane1_height
assert int(pane1.pane_height) == 4

pane1.resize_pane(height=3)
assert int(pane1["pane_height"]) == 3
assert int(pane1.pane_height) == 3


def test_send_keys(session: Session) -> None:
Expand All @@ -42,11 +42,11 @@ def test_set_height(session: Session) -> None:
window.split_window()
pane1 = window.attached_pane
assert pane1 is not None
pane1_height = pane1["pane_height"]
pane1_height = pane1.pane_height

pane1.set_height(4)
assert pane1["pane_height"] != pane1_height
assert int(pane1["pane_height"]) == 4
assert pane1.pane_height != pane1_height
assert int(pane1.pane_height) == 4


def test_set_width(session: Session) -> None:
Expand All @@ -56,11 +56,11 @@ def test_set_width(session: Session) -> None:
window.select_layout("main-vertical")
pane1 = window.attached_pane
assert pane1 is not None
pane1_width = pane1["pane_width"]
pane1_width = pane1.pane_width

pane1.set_width(10)
assert pane1["pane_width"] != pane1_width
assert int(pane1["pane_width"]) == 10
assert pane1.pane_width != pane1_width
assert int(pane1.pane_width) == 10

pane1.reset()

Expand Down
2 changes: 1 addition & 1 deletion tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def test_new_session_shell(server: Server) -> None:
assert mysession.get("session_name") == "test_new_session"
assert server.has_session("test_new_session")

pane_start_command = pane.get("pane_start_command")
pane_start_command = pane.pane_start_command
assert pane_start_command is not None

if has_gte_version("3.2"):
Expand Down
12 changes: 6 additions & 6 deletions tests/test_tmuxobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def test_find_where(server: Server, session: Session) -> None:
# window.find_where
for pane in window.panes:
pane_id = pane.get("pane_id")
assert pane_id is not None
pane_id = pane.pane_id

assert window.find_where({"pane_id": pane_id}) == pane
assert isinstance(window.find_where({"pane_id": pane_id}), Pane)
Expand Down Expand Up @@ -84,9 +84,9 @@ def test_find_where_multiple_infos(server: Server, session: Session) -> None:

# window.find_where
for pane in window.panes:
pane_id = pane.get("pane_id")
pane_id = pane.pane_id
assert pane_id is not None
pane_tty = pane.get("pane_tty")
pane_tty = pane.pane_tty
assert pane_tty is not None

find_where = window.find_where(
Expand Down Expand Up @@ -137,10 +137,10 @@ def test_where(server: Server, session: Session) -> None:

# window.where
for pane in window.panes:
pane_id = pane.get("pane_id")
pane_id = pane.pane_id
assert pane_id is not None

pane_tty = pane.get("pane_tty")
pane_tty = pane.pane_tty
assert pane_tty is not None

window_panes = window.where({"pane_id": pane_id, "pane_tty": pane_tty})
Expand Down Expand Up @@ -181,7 +181,7 @@ def test_get_by_id(server: Server, session: Session) -> None:

# window.get_by_id
for pane in window.panes:
pane_id = pane.get("pane_id")
pane_id = pane.pane_id
assert pane_id is not None

get_pane_by_id = window.get_by_id(pane_id)
Expand Down