diff --git a/.coveragerc b/.coveragerc index 9ed88302e..7c74c56a0 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,15 +1,20 @@ [run] +parallel = 1 +branch = 1 + omit = - test/* - */_vendor/* - */_* - pkg/* - */log.py + docs/conf.py + */_compat.py [report] +skip_covered = True +show_missing = True exclude_lines = - pragma: no cover - def __repr__ - raise NotImplementedError - if __name__ == .__main__.: - def parse_args + \#\s*pragma: no cover + ^\s*raise NotImplementedError\b + ^\s*return NotImplemented\b + ^\s*assert False(,|$) + ^\s*assert_never\( + + ^\s*if TYPE_CHECKING: + ^\s*@overload( |$) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e5443194d..64b3ba367 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -68,7 +68,11 @@ jobs: export PATH=$HOME/tmux-builds/tmux-${{ matrix.tmux-version }}/bin:$PATH ls $HOME/tmux-builds/tmux-${{ matrix.tmux-version }}/bin tmux -V - poetry run py.test --cov=./ --cov-report=xml + poetry run py.test --cov=./ --cov-append --cov-report=xml + env: + COV_CORE_SOURCE: . + COV_CORE_CONFIG: .coveragerc + COV_CORE_DATAFILE: .coverage.eager - uses: codecov/codecov-action@v2 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.prettierrc b/.prettierrc index de753c537..2d553cc6c 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,3 +1,4 @@ { - "printWidth": 100 + "printWidth": 100, + "proseWrap": 'always' } diff --git a/README.md b/README.md index 9c751f3dd..b3ec76ad6 100644 --- a/README.md +++ b/README.md @@ -70,23 +70,23 @@ List sessions: ```python >>> server.list_sessions() -[Session($... libtmux_...), Session($... ...)] +[Session($1 ...), Session($0 ...)] ``` Find session: ```python ->>> server.get_by_id('$0') -Session($... ...) +>>> server.get_by_id('$1') +Session($1 ...) ``` Find session by dict lookup: ```python >>> server.sessions[0].rename_session('foo') -Session($... foo) +Session($1 foo) >>> server.find_where({ "session_name": "foo" }) -Session($... foo) +Session($1 foo) ``` Control your session: @@ -103,7 +103,7 @@ Create new window in the background (don't switch to it): ```python >>> session.new_window(attach=False, window_name="ha in the bg") -Window(@... ...:ha in the bg, Session($... libtmux_...)) +Window(@2 2:ha in the bg, Session($1 ...)) ``` Close window: @@ -118,14 +118,14 @@ Grab remaining tmux window: ```python >>> window = session.attached_window >>> window.split_window(attach=False) -Pane(%... Window(@... ...:..., Session($... libtmux_...))) +Pane(%2 Window(@1 1:... Session($1 ...))) ``` Rename window: ```python >>> window.rename_window('libtmuxower') -Window(@... ...:libtmuxower, Session($... ...)) +Window(@1 1:libtmuxower, Session($1 ...)) ``` Split window (create a new pane): @@ -134,13 +134,13 @@ Split window (create a new pane): >>> pane = window.split_window() >>> pane = window.split_window(attach=False) >>> pane.select_pane() -Pane(%... Window(@... ...:..., Session($... libtmux_...))) +Pane(%3 Window(@1 1:..., Session($1 ...))) >>> window = session.new_window(attach=False, window_name="test") >>> window -Window(@... ...:test, Session($...)) +Window(@2 2:test, Session($1 ...)) >>> pane = window.split_window(attach=False) >>> pane -Pane(%... Window(@... ...:..., Session($... libtmux_...))) +Pane(%5 Window(@2 2:test, Session($1 ...))) ``` Type inside the pane (send key strokes): @@ -175,9 +175,9 @@ Traverse and navigate: ```python >>> pane.window -Window(@... ...:..., Session($... ...)) +Window(@1 1:..., Session($1 ...)) >>> pane.window.session -Session($... ...) +Session($1 ...) ``` # Python support diff --git a/docs/conf.py b/docs/conf.py index 1bbb683df..94c7f7fd6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -160,7 +160,10 @@ ) ] -intersphinx_mapping = {"http://docs.python.org/": None} +intersphinx_mapping = { + "": ("https://docs.python.org/", None), + "pytest": ("https://docs.pytest.org/en/stable/", None), +} def linkcode_resolve( diff --git a/docs/conftest.py b/docs/conftest.py new file mode 100644 index 000000000..62571f546 --- /dev/null +++ b/docs/conftest.py @@ -0,0 +1 @@ +from libtmux.conftest import * # NOQA: F4 diff --git a/docs/developing.md b/docs/developing.md index 244b55b44..2ace7f008 100644 --- a/docs/developing.md +++ b/docs/developing.md @@ -23,6 +23,14 @@ Makefile commands prefixed with `watch_` will watch files and rerun. Helpers: `make test` Rerun tests on file change: `make watch_test` (requires [entr(1)]) +### Pytest plugin + +:::{seealso} + +See {ref}`pytest_plugin`. + +::: + ## Documentation Default preview server: http://localhost:8023 diff --git a/docs/index.md b/docs/index.md index bf7af19ca..ed92e5ade 100644 --- a/docs/index.md +++ b/docs/index.md @@ -28,6 +28,7 @@ api :hidden: developing +pytest-plugin internals/index history glossary diff --git a/docs/pytest-plugin.md b/docs/pytest-plugin.md new file mode 100644 index 000000000..8f546f2e3 --- /dev/null +++ b/docs/pytest-plugin.md @@ -0,0 +1,98 @@ +(pytest_plugin)= + +# `pytest` plugin + +Testing tmux with libtmux + +```{seealso} Using libtmux? + +Do you want more flexbility? Correctness? Power? Defaults changed? [Connect with us] on the tracker, we want to know +your case, we won't stabilize APIs until we're sure everything is by the book. + +[connect with us]: https://github.com/tmux-python/libtmux/discussions + +``` + +```{module} libtmux.pytest_plugin + +``` + +## Usage + +Install `libtmux` via the python package manager of your choosing, e.g. + +```console +$ pip install libtmux +``` + +The pytest plugin will automatically be detected via pytest, and the fixtures will be added. + +## Fixtures + +`pytest-tmux` works through providing {ref}`pytest fixtures ` - so read up on +those! + +The plugin's fixtures guarantee a fresh, headless `tmux(1)` server, session, window, or pane is +passed into your test. + +(recommended-fixtures)= + +## Recommended fixtures + +These are fixtures are automatically used when the plugin is enabled and `pytest` is ran. + +- Creating temporary, test directories for: + - `/home/` ({func}`home_path`) + - `/home/${user}` ({func}`user_path`) +- Default `.tmux.conf` configuration with these settings ({func}`config_file`): + + - `base-index -g 1` + + These are set to ensure panes and windows can be reliably referenced and asserted. + +## Setting a tmux configuration + +If you would like :func:`session` fixture to automatically use a configuration, you have a few +options: + +- Pass a `config_file` into :class:`libtmux.server.Server` +- Set the `HOME` directory to a local or temporary pytest path with a configurat configuration file + +You could also read the code and override :func:`server`'s fixture in your own doctest. doctest. + +(set_home)= + +### Setting a temporary home directory + +```python +import pathlib +import pytest + +@pytest.fixture(autouse=True, scope="function") +def set_home( + monkeypatch: pytest.MonkeyPatch, + user_path: pathlib.Path, +): + monkeypatch.setenv("HOME", str(user_path)) +``` + +## See examples + +View libtmux's own [tests/](https://github.com/tmux-python/libtmux/tree/master/tests) as well as +tmuxp's [tests/](https://github.com/tmux-python/tmuxp/tree/master/tests). + +libtmux's tests `autouse` the {ref}`recommended-fixtures` above to ensure stable, assertions and +object lookups in the test grid. + +## API reference + +```{eval-rst} +.. autoapimodule:: libtmux.pytest_plugin + :members: + :inherited-members: + :private-members: + :show-inheritance: + :member-order: bysource + :exclude-members: Server, TEST_SESSION_PREFIX, get_test_session_name, + namer, logger +``` diff --git a/docs/quickstart.md b/docs/quickstart.md index f2cef0b99..8d8b19350 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -139,7 +139,7 @@ We can list sessions with {meth}`Server.list_sessions`: ```python >>> server.list_sessions() -[Session($... ...), Session($... ...)] +[Session($1 ...), Session($0 ...)] ``` This returns a list of {class}`Session` objects you can grab. We can @@ -147,7 +147,7 @@ find our current session with: ```python >>> server.list_sessions()[0] -Session($... ...) +Session($1 ...) ``` However, this isn't guaranteed, libtmux works against current tmux information, the @@ -162,7 +162,7 @@ tmux sessions use the `$[0-9]` convention as a way to identify sessions. ```python >>> server.get_by_id('$1') -Session($... ...) +Session($1 ...) ``` You may `session = server.get_by_id('$')` to use the session object. @@ -172,10 +172,10 @@ You may `session = server.get_by_id('$')` to use the session object. ```python # Just for setting up the example: >>> server.sessions[0].rename_session('foo') -Session($... foo) +Session($1 foo) >>> server.find_where({ "session_name": "foo" }) -Session($... foo) +Session($1 foo) ``` With `find_where`, pass in a dict and return the first object found. In @@ -188,11 +188,11 @@ So you may now use: ```python # Prepping the example: >>> server.sessions[0].rename_session('foo') -Session($... foo) +Session($1 foo) >>> session = server.find_where({ "session_name": "foo" }) >>> session -Session($... foo) +Session($1 foo) ``` to give us a `session` object to play with. @@ -206,7 +206,7 @@ Let's make a {meth}`Session.new_window`, in the background: ```python >>> session.new_window(attach=False, window_name="ha in the bg") -Window(@... ...:ha in the bg, Session($... ...)) +Window(@2 ...:ha in the bg, Session($1 ...)) ``` So a few things: @@ -245,7 +245,7 @@ should have history, so navigate up with the arrow key. ```python >>> session.new_window(attach=False, window_name="ha in the bg") -Window(@... ...:ha in the bg, Session($... ...)) +Window(@2 ...:ha in the bg, Session($1 ...)) ``` Try to kill the window by the matching id `@[0-9999]`. @@ -253,7 +253,7 @@ Try to kill the window by the matching id `@[0-9999]`. ```python # Setup >>> session.new_window(attach=False, window_name="ha in the bg") -Window(@... ...:ha in the bg, Session($... ...)) +Window(@1 ...:ha in the bg, Session($1 ...)) >>> session.kill_window('ha in the bg') ``` @@ -264,7 +264,7 @@ object: ```python >>> window = session.new_window(attach=False, window_name="check this out") >>> window -Window(@... ...:check this out, Session($... ...)) +Window(@2 2:check this out, Session($1 ...)) ``` And kill: @@ -291,7 +291,7 @@ Let's create a pane, {meth}`Window.split_window`: ```python >>> window.split_window(attach=False) -Pane(%... Window(@... ...:..., Session($... ...))) +Pane(%2 Window(@1 ...:..., Session($1 ...))) ``` Powered up. Let's have a break down: @@ -304,7 +304,7 @@ Also, since you are aware of this power, let's commemorate the experience: ```python >>> window.rename_window('libtmuxower') -Window(@... ...:..., Session($... ...)) +Window(@1 ...:..., Session($1 ...)) ``` You should have noticed {meth}`Window.rename_window` renamed the window. @@ -329,7 +329,7 @@ can also use the `.select_*` available on the object, in this case the pane has ```python >>> pane.select_pane() -Pane(%... Window(@... ...:..., Session($... ...))) +Pane(%1 Window(@1 ...:..., Session($1 ...))) ``` ```{eval-rst} diff --git a/docs/reference/properties.md b/docs/reference/properties.md index a2061fa12..085361f3f 100644 --- a/docs/reference/properties.md +++ b/docs/reference/properties.md @@ -43,7 +43,7 @@ Get the {class}`~libtmux.Session` object: ```python >>> session = server.sessions[0] >>> session -Session($... libtmux_...) +Session($1 libtmux_...) ``` Quick access to basic attributes: @@ -53,7 +53,7 @@ Quick access to basic attributes: 'libtmux_...' >>> session.id -'$...' +'$1' ``` To see all attributes for a session: @@ -79,7 +79,7 @@ The same concepts apply for {class}`~libtmux.Window`: >>> window = session.attached_window >>> window -Window(@... ...:..., Session($... ...)) +Window(@1 ...:..., Session($1 ...)) ``` Basics: @@ -89,7 +89,7 @@ Basics: '...' >>> window.id -'@...' +'@1' >>> window.height '...' @@ -120,7 +120,7 @@ Get the {class}`~libtmux.Pane`: >>> pane = window.attached_pane >>> pane -Pane(%... Window(@... ...:..., Session($... libtmux_...))) +Pane(%1 Window(@1 ...:..., Session($1 libtmux_...))) ``` Basics: diff --git a/docs/topics/traversal.md b/docs/topics/traversal.md index a03b515c0..02b537306 100644 --- a/docs/topics/traversal.md +++ b/docs/topics/traversal.md @@ -42,14 +42,14 @@ Get first session {class}`~libtmux.Session` to `session`: ```python >>> session = server.sessions[0] >>> session -Session($... ...) +Session($1 ...) ``` Get a list of sessions: ```python >>> server.sessions -[Session($... ...), Session($... ...)] +[Session($1 ...), Session($0 ...)] ``` Iterate through sessions in a server: @@ -57,29 +57,29 @@ Iterate through sessions in a server: ```python >>> for sess in server.sessions: ... print(sess) -Session($... ...) -Session($... ...) +Session($1 ...) +Session($0 ...) ``` Grab a {class}`~libtmux.Window` from a session: ```python >>> session.windows[0] -Window(@... ...:..., Session($... ...)) +Window(@1 ...:..., Session($1 ...)) ``` Grab the currently focused window from session: ```python >>> session.attached_window -Window(@... ...:..., Session($... ...)) +Window(@1 ...:..., Session($1 ...)) ``` Grab the currently focused {class}`Pane` from session: ```python >>> session.attached_pane -Pane(%... Window(@... ...:..., Session($... ...))) +Pane(%1 Window(@1 ...:..., Session($1 ...))) ``` Assign the attached {class}`~libtmux.Pane` to `p`: @@ -93,7 +93,7 @@ Access the window/server of a pane: ```python >>> p = session.attached_pane >>> p.window -Window(@... ...:..., Session($... ...)) +Window(@1 ...:..., Session($1 ...)) >>> p.server diff --git a/libtmux/conftest.py b/libtmux/conftest.py index 280d58253..c99992127 100644 --- a/libtmux/conftest.py +++ b/libtmux/conftest.py @@ -1,117 +1,44 @@ -import logging -import os +import pathlib import shutil import typing as t import pytest from _pytest.doctest import DoctestItem -from _pytest.fixtures import SubRequest -from _pytest.monkeypatch import MonkeyPatch -from libtmux import exc -from libtmux.server import Server -from libtmux.test import TEST_SESSION_PREFIX, get_test_session_name, namer +from libtmux.pytest_plugin import USING_ZSH if t.TYPE_CHECKING: from libtmux.session import Session -logger = logging.getLogger(__name__) - - -@pytest.fixture(autouse=True) -def clear_env(monkeypatch: MonkeyPatch) -> None: - """Clear out any unnecessary environment variables that could interrupt tests. - - tmux show-environment tests were being interrupted due to a lot of crazy env vars. - """ - for k, v in os.environ.items(): - if not any( - needle in k.lower() - for needle in [ - "window", - "tmux", - "pane", - "session", - "pytest", - "path", - "pwd", - "shell", - "home", - "xdg", - "disable_auto_title", - "lang", - "term", - ] - ): - monkeypatch.delenv(k) - - -@pytest.fixture(scope="function") -def server(request: SubRequest, monkeypatch: MonkeyPatch) -> Server: - - t = Server() - t.socket_name = "tmuxp_test%s" % next(namer) - - def fin() -> None: - t.kill_server() - - request.addfinalizer(fin) - - return t - - -@pytest.fixture(scope="function") -def session(request: SubRequest, server: Server) -> "Session": - session_name = "tmuxp" - - if not server.has_session(session_name): - server.cmd("new-session", "-d", "-s", session_name) - - # find current sessions prefixed with tmuxp - old_test_sessions = [] - for s in server._sessions: - old_name = s.get("session_name") - if old_name is not None and old_name.startswith(TEST_SESSION_PREFIX): - old_test_sessions.append(old_name) - - TEST_SESSION_NAME = get_test_session_name(server=server) - - try: - session = server.new_session(session_name=TEST_SESSION_NAME) - except exc.LibTmuxException as e: - raise e - - """ - Make sure that tmuxp can :ref:`test_builder_visually` and switches to - the newly created session for that testcase. - """ - session_id = session.get("session_id") - assert session_id is not None - - try: - server.switch_client(target_session=session_id) - except exc.LibTmuxException: - # server.attach_session(session.get('session_id')) - pass - - for old_test_session in old_test_sessions: - logger.debug("Old test test session %s found. Killing it." % old_test_session) - server.kill_session(old_test_session) - assert TEST_SESSION_NAME == session.get("session_name") - assert TEST_SESSION_NAME != "tmuxp" - - return session - @pytest.fixture(autouse=True) def add_doctest_fixtures( - request: SubRequest, + request: pytest.FixtureRequest, doctest_namespace: t.Dict[str, t.Any], ) -> None: if isinstance(request._pyfuncitem, DoctestItem) and shutil.which("tmux"): + request.getfixturevalue("set_home") doctest_namespace["server"] = request.getfixturevalue("server") session: "Session" = request.getfixturevalue("session") doctest_namespace["session"] = session doctest_namespace["window"] = session.attached_window doctest_namespace["pane"] = session.attached_pane + + +@pytest.fixture(autouse=True, scope="function") +def set_home( + monkeypatch: pytest.MonkeyPatch, + user_path: pathlib.Path, +) -> None: + monkeypatch.setenv("HOME", str(user_path)) + + +@pytest.fixture(autouse=True, scope="session") +@pytest.mark.usefixtures("clear_env") +def setup( + request: pytest.FixtureRequest, + config_file: pathlib.Path, +) -> None: + if USING_ZSH: + request.getfixturevalue("zshrc") diff --git a/libtmux/pane.py b/libtmux/pane.py index 0ac259f99..469a0d9b3 100644 --- a/libtmux/pane.py +++ b/libtmux/pane.py @@ -39,13 +39,13 @@ class Pane(TmuxMappingObject): Examples -------- >>> pane - Pane(%1 Window(@1 ...:..., Session($1 ...))) + Pane(%1 Window(@1 1:..., Session($1 ...))) >>> pane in window.panes True >>> pane.window - Window(@1 ...:..., Session($1 ...)) + Window(@1 1:..., Session($1 ...)) >>> pane.session Session($1 ...) diff --git a/libtmux/pytest_plugin.py b/libtmux/pytest_plugin.py new file mode 100644 index 000000000..863e9e44f --- /dev/null +++ b/libtmux/pytest_plugin.py @@ -0,0 +1,164 @@ +import getpass +import logging +import os +import pathlib +import typing as t + +import pytest + +from libtmux import exc +from libtmux.server import Server +from libtmux.test import TEST_SESSION_PREFIX, get_test_session_name, namer + +if t.TYPE_CHECKING: + from libtmux.session import Session + +logger = logging.getLogger(__name__) +USING_ZSH = "zsh" in os.getenv("SHELL", "") + + +@pytest.fixture(scope="session") +def home_path(tmp_path_factory: pytest.TempPathFactory) -> pathlib.Path: + """Temporary `/home/` path.""" + return tmp_path_factory.mktemp("home") + + +@pytest.fixture(scope="session") +def home_user_name() -> str: + """Default username to set for :func:`user_path` fixture.""" + return getpass.getuser() + + +@pytest.fixture(scope="session") +def user_path(home_path: pathlib.Path, home_user_name: str) -> pathlib.Path: + """Default temporary user directory. + + Used by: :func:`config_file`, :func:`zshrc` + + Note: You will need to set the home directory, see :ref:`set_home`. + """ + p = home_path / home_user_name + p.mkdir() + return p + + +@pytest.mark.skipif(USING_ZSH, reason="Using ZSH") +@pytest.fixture(scope="session") +def zshrc(user_path: pathlib.Path) -> pathlib.Path: + """This quiets ZSH default message. + + Needs a startup file .zshenv, .zprofile, .zshrc, .zlogin. + """ + p = user_path / ".zshrc" + p.touch() + return p + + +@pytest.fixture(scope="session") +def config_file(user_path: pathlib.Path) -> pathlib.Path: + """Default `.tmux.conf` configuration. + + - ``base-index -g 1`` + + These guarantee pane and windows targets can be reliably referenced and asserted. + + Note: You will need to set the home directory, see :ref:`set_home`. + """ + c = user_path / ".tmux.conf" + c.write_text( + """ +set -g base-index 1 + """, + encoding="utf-8", + ) + return c + + +@pytest.fixture +def clear_env(monkeypatch: pytest.MonkeyPatch) -> None: + """Clear out any unnecessary environment variables that could interrupt tests. + + tmux show-environment tests were being interrupted due to a lot of crazy env vars. + """ + for k, v in os.environ.items(): + if not any( + needle in k.lower() + for needle in [ + "window", + "tmux", + "pane", + "session", + "pytest", + "path", + "pwd", + "shell", + "home", + "xdg", + "disable_auto_title", + "lang", + "term", + ] + ): + monkeypatch.delenv(k) + + +@pytest.fixture(scope="function") +def server( + request: pytest.FixtureRequest, + monkeypatch: pytest.MonkeyPatch, + config_file: pathlib.Path, +) -> Server: + """Returns a new, temporary :class:`libtmux.Server`""" + t = Server() + t.socket_name = "libtmux_test%s" % next(namer) + + def fin() -> None: + t.kill_server() + + request.addfinalizer(fin) + + return t + + +@pytest.fixture(scope="function") +def session(request: pytest.FixtureRequest, server: Server) -> "Session": + """Returns a new, temporary :class:`libtmux.Session`""" + session_name = "tmuxp" + + if not server.has_session(session_name): + server.cmd("new-session", "-d", "-s", session_name) + + # find current sessions prefixed with tmuxp + old_test_sessions = [] + for s in server._sessions: + old_name = s.get("session_name") + if old_name is not None and old_name.startswith(TEST_SESSION_PREFIX): + old_test_sessions.append(old_name) + + TEST_SESSION_NAME = get_test_session_name(server=server) + + try: + session = server.new_session(session_name=TEST_SESSION_NAME) + except exc.LibTmuxException as e: + raise e + + """ + Make sure that tmuxp can :ref:`test_builder_visually` and switches to + the newly created session for that testcase. + """ + session_id = session.get("session_id") + assert session_id is not None + + try: + server.switch_client(target_session=session_id) + except exc.LibTmuxException: + # server.attach_session(session.get('session_id')) + pass + + for old_test_session in old_test_sessions: + logger.debug("Old test test session %s found. Killing it." % old_test_session) + server.kill_session(old_test_session) + assert TEST_SESSION_NAME == session.get("session_name") + assert TEST_SESSION_NAME != "tmuxp" + + return session diff --git a/libtmux/server.py b/libtmux/server.py index e0e7c35c7..a049f3b9e 100644 --- a/libtmux/server.py +++ b/libtmux/server.py @@ -56,13 +56,13 @@ class Server(TmuxRelationalObject["Session", "SessionDict"], EnvironmentMixin): [Session($1 ...)] >>> server.sessions[0].windows - [Window(@1 ...:..., Session($1 ...)] + [Window(@1 1:..., Session($1 ...)] >>> server.sessions[0].attached_window - Window(@1 ...:..., Session($1 ...) + Window(@1 1:..., Session($1 ...) >>> server.sessions[0].attached_pane - Pane(%1 Window(@1 ...:..., Session($1 ...))) + Pane(%1 Window(@1 1:..., Session($1 ...))) References ---------- diff --git a/libtmux/window.py b/libtmux/window.py index d38b8298c..434dca17c 100644 --- a/libtmux/window.py +++ b/libtmux/window.py @@ -44,7 +44,7 @@ class Window(TmuxMappingObject, TmuxRelationalObject["Pane", "PaneDict"]): >>> window = session.new_window('My project') >>> window - Window(@... ...:My project, Session($... ...)) + Window(@2 2:My project, Session($... ...)) Windows have panes: @@ -329,10 +329,10 @@ def rename_window(self, new_name: str) -> "Window": >>> window = session.attached_window >>> window.rename_window('My project') - Window(@1 ...:My project, Session($1 ...)) + Window(@1 1:My project, Session($1 ...)) >>> window.rename_window('New name') - Window(@1 ...:New name, Session($1 ...)) + Window(@1 1:New name, Session($1 ...)) """ import shlex diff --git a/pyproject.toml b/pyproject.toml index a4d41744f..069a9bab9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -102,6 +102,9 @@ coverage = ["codecov", "coverage", "pytest-cov"] format = ["black", "isort"] lint = ["flake8", "flake8-bugbear", "flake8-comprehensions", "mypy"] +[tool.poetry.plugins.pytest11] +libtmux = "libtmux.pytest_plugin" + [tool.mypy] strict = true diff --git a/tests/conftest.py b/tests/conftest.py index 535e57934..62571f546 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1 +1 @@ -from libtmux.conftest import * # noqa F40 +from libtmux.conftest import * # NOQA: F4