From bb1078d8f04a973b3e62e326fe6ee918da54b341 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 5 Aug 2022 20:34:39 -0500 Subject: [PATCH 01/10] refactor!(conftest): Move to tmuxp/conftest.py for doctest This allows pytest to detect the conftest module --- tests/conftest.py | 124 +--------------------------------------------- tmuxp/conftest.py | 123 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 123 deletions(-) create mode 100644 tmuxp/conftest.py diff --git a/tests/conftest.py b/tests/conftest.py index dcb37be2041..44a43177266 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,123 +1 @@ -import getpass -import logging -import os -import pathlib - -import pytest - -from libtmux import exc -from libtmux.server import Server -from libtmux.test import TEST_SESSION_PREFIX, get_test_session_name, namer - -logger = logging.getLogger(__name__) -USING_ZSH = "zsh" in os.getenv("SHELL", "") - - -@pytest.fixture(autouse=True, scope="session") -def home_path(tmp_path_factory: pytest.TempPathFactory): - return tmp_path_factory.mktemp("home") - - -@pytest.fixture(autouse=True, scope="session") -def user_path(home_path: pathlib.Path): - p = home_path / getpass.getuser() - p.mkdir() - return p - - -@pytest.mark.skipif(USING_ZSH, reason="Using ZSH") -@pytest.fixture(autouse=USING_ZSH, scope="session") -def zshrc(user_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(autouse=True) -def home_path_default(user_path: pathlib.Path): - os.environ["HOME"] = str(user_path) - - -@pytest.fixture(scope="function") -def monkeypatch_plugin_test_packages(monkeypatch): - paths = [ - "tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bwb/", - "tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bs/", - "tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_r/", - "tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_owc/", - "tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_awf/", - "tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_fail/", - ] - for path in paths: - monkeypatch.syspath_prepend(os.path.abspath(os.path.relpath(path))) - - -@pytest.fixture(scope="function") -def socket_name(request): - return "tmuxp_test%s" % next(namer) - - -@pytest.fixture(scope="function") -def server(request, socket_name): - t = Server() - t.socket_name = socket_name - - def fin(): - t.kill_server() - - request.addfinalizer(fin) - - return t - - -@pytest.fixture(scope="function") -def session(server): - session_name = "tmuxp" - - if not server.has_session(session_name): - server.cmd( - "-f", - "/dev/null", # use a blank config to reduce side effects - "new-session", - "-d", # detached - "-s", - session_name, - "/bin/sh", # use /bin/sh as a shell to reduce side effects - # normally, it'd be -c, but new-session is special - ) - - # find current sessions prefixed with tmuxp - old_test_sessions = [ - s.get("session_name") - for s in server._sessions - if s.get("session_name").startswith(TEST_SESSION_PREFIX) - ] - - 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. - """ - try: - server.switch_client(session.get("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 +from tmuxp.conftest import * # noqa F40 diff --git a/tmuxp/conftest.py b/tmuxp/conftest.py new file mode 100644 index 00000000000..dcb37be2041 --- /dev/null +++ b/tmuxp/conftest.py @@ -0,0 +1,123 @@ +import getpass +import logging +import os +import pathlib + +import pytest + +from libtmux import exc +from libtmux.server import Server +from libtmux.test import TEST_SESSION_PREFIX, get_test_session_name, namer + +logger = logging.getLogger(__name__) +USING_ZSH = "zsh" in os.getenv("SHELL", "") + + +@pytest.fixture(autouse=True, scope="session") +def home_path(tmp_path_factory: pytest.TempPathFactory): + return tmp_path_factory.mktemp("home") + + +@pytest.fixture(autouse=True, scope="session") +def user_path(home_path: pathlib.Path): + p = home_path / getpass.getuser() + p.mkdir() + return p + + +@pytest.mark.skipif(USING_ZSH, reason="Using ZSH") +@pytest.fixture(autouse=USING_ZSH, scope="session") +def zshrc(user_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(autouse=True) +def home_path_default(user_path: pathlib.Path): + os.environ["HOME"] = str(user_path) + + +@pytest.fixture(scope="function") +def monkeypatch_plugin_test_packages(monkeypatch): + paths = [ + "tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bwb/", + "tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bs/", + "tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_r/", + "tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_owc/", + "tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_awf/", + "tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_fail/", + ] + for path in paths: + monkeypatch.syspath_prepend(os.path.abspath(os.path.relpath(path))) + + +@pytest.fixture(scope="function") +def socket_name(request): + return "tmuxp_test%s" % next(namer) + + +@pytest.fixture(scope="function") +def server(request, socket_name): + t = Server() + t.socket_name = socket_name + + def fin(): + t.kill_server() + + request.addfinalizer(fin) + + return t + + +@pytest.fixture(scope="function") +def session(server): + session_name = "tmuxp" + + if not server.has_session(session_name): + server.cmd( + "-f", + "/dev/null", # use a blank config to reduce side effects + "new-session", + "-d", # detached + "-s", + session_name, + "/bin/sh", # use /bin/sh as a shell to reduce side effects + # normally, it'd be -c, but new-session is special + ) + + # find current sessions prefixed with tmuxp + old_test_sessions = [ + s.get("session_name") + for s in server._sessions + if s.get("session_name").startswith(TEST_SESSION_PREFIX) + ] + + 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. + """ + try: + server.switch_client(session.get("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 From 6e2ee09fd1282755f45ef4f11621ef447dcd5abe Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 5 Aug 2022 20:39:17 -0500 Subject: [PATCH 02/10] ci(pytest): Default args --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index cab5f595365..4d88811fbff 100644 --- a/setup.cfg +++ b/setup.cfg @@ -6,9 +6,9 @@ max-line-length = 88 extend-ignore = E203,W503 [tool:pytest] -addopts = --reruns=0 filterwarnings = ignore:distutils Version classes are deprecated. Use packaging.version instead. +addopts = --reruns=0 --tb=short --no-header --showlocals [isort] profile = black From bda8b572f0186f2002d6f27f983d51f6189aa208 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 5 Aug 2022 20:40:46 -0500 Subject: [PATCH 03/10] ci(pytest): Detect doctest modules --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 4d88811fbff..54b1fa598b6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -8,7 +8,7 @@ extend-ignore = E203,W503 [tool:pytest] filterwarnings = ignore:distutils Version classes are deprecated. Use packaging.version instead. -addopts = --reruns=0 --tb=short --no-header --showlocals +addopts = --reruns=0 --tb=short --no-header --showlocals --doctest-modules [isort] profile = black From f539cf19c3210f810f06e011fb1b89f566f205a7 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 5 Aug 2022 20:41:05 -0500 Subject: [PATCH 04/10] ci(pytest): Default doctest option flags --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index 54b1fa598b6..006953379fb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -9,6 +9,7 @@ extend-ignore = E203,W503 filterwarnings = ignore:distutils Version classes are deprecated. Use packaging.version instead. addopts = --reruns=0 --tb=short --no-header --showlocals --doctest-modules +doctest_optionflags = ELLIPSIS NORMALIZE_WHITESPACE [isort] profile = black From d04d8733bc7b6413f25f67a93ab76a0951084c88 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 5 Aug 2022 20:41:48 -0500 Subject: [PATCH 05/10] docs(conf): Update for doctest path --- docs/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index f397d80ff0e..7be0d094a87 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -8,7 +8,7 @@ import tmuxp # Get the project root dir, which is the parent dir of this -cwd = Path.cwd() +cwd = Path(__file__).parent project_root = cwd.parent sys.path.insert(0, str(project_root)) @@ -16,7 +16,7 @@ # package data about = {} -with open("../tmuxp/__about__.py") as fp: +with open(project_root / "tmuxp" / "__about__.py") as fp: exec(fp.read(), about) extensions = [ From 871c9224f4596ccc384ffac8a38721663d341bfa Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Aug 2022 07:14:47 -0500 Subject: [PATCH 06/10] tests: Defer test fixtures interpolation Interpolation needs to be deferred for libtmux to do its magic --- tests/fixtures/config/expand1.py | 94 ++++---- tests/fixtures/config/expand2.py | 13 +- tests/fixtures/config/shell_command_before.py | 221 +++++++++--------- tests/test_config.py | 10 +- 4 files changed, 176 insertions(+), 162 deletions(-) diff --git a/tests/fixtures/config/expand1.py b/tests/fixtures/config/expand1.py index 71e8e0704f3..4547dd43bbd 100644 --- a/tests/fixtures/config/expand1.py +++ b/tests/fixtures/config/expand1.py @@ -29,49 +29,51 @@ ], } -after_config = { - "session_name": "sampleconfig", - "start_directory": os.path.expanduser("~"), - "windows": [ - { - "window_name": "editor", - "panes": [ - {"shell_command": [{"cmd": "vim"}, {"cmd": "top"}]}, - {"shell_command": [{"cmd": "vim"}]}, - {"shell_command": [{"cmd": 'cowsay "hey"'}]}, - ], - "layout": "main-verticle", - }, - { - "window_name": "logging", - "panes": [{"shell_command": [{"cmd": "tail -F /var/log/syslog"}]}], - }, - { - "start_directory": "/var/log", - "options": {"automatic-rename": True}, - "panes": [ - {"shell_command": [{"cmd": "htop"}]}, - {"shell_command": [{"cmd": "vim"}]}, - ], - }, - { - "start_directory": os.path.normpath( - os.path.join(os.path.expanduser("~"), "./") - ), - "panes": [{"shell_command": [{"cmd": "pwd"}]}], - }, - { - "start_directory": os.path.normpath( - os.path.join(os.path.expanduser("~"), "./asdf") - ), - "panes": [{"shell_command": [{"cmd": "pwd"}]}], - }, - { - "start_directory": os.path.normpath( - os.path.join(os.path.expanduser("~"), "../") - ), - "panes": [{"shell_command": [{"cmd": "pwd"}]}], - }, - {"panes": [{"shell_command": [{"cmd": "top"}]}]}, - ], -} + +def after_config(): + return { + "session_name": "sampleconfig", + "start_directory": os.path.expanduser("~"), + "windows": [ + { + "window_name": "editor", + "panes": [ + {"shell_command": [{"cmd": "vim"}, {"cmd": "top"}]}, + {"shell_command": [{"cmd": "vim"}]}, + {"shell_command": [{"cmd": 'cowsay "hey"'}]}, + ], + "layout": "main-verticle", + }, + { + "window_name": "logging", + "panes": [{"shell_command": [{"cmd": "tail -F /var/log/syslog"}]}], + }, + { + "start_directory": "/var/log", + "options": {"automatic-rename": True}, + "panes": [ + {"shell_command": [{"cmd": "htop"}]}, + {"shell_command": [{"cmd": "vim"}]}, + ], + }, + { + "start_directory": os.path.normpath( + os.path.join(os.path.expanduser("~"), "./") + ), + "panes": [{"shell_command": [{"cmd": "pwd"}]}], + }, + { + "start_directory": os.path.normpath( + os.path.join(os.path.expanduser("~"), "./asdf") + ), + "panes": [{"shell_command": [{"cmd": "pwd"}]}], + }, + { + "start_directory": os.path.normpath( + os.path.join(os.path.expanduser("~"), "../") + ), + "panes": [{"shell_command": [{"cmd": "pwd"}]}], + }, + {"panes": [{"shell_command": [{"cmd": "top"}]}]}, + ], + } diff --git a/tests/fixtures/config/expand2.py b/tests/fixtures/config/expand2.py index 4cd49336ddb..7e73132e5fb 100644 --- a/tests/fixtures/config/expand2.py +++ b/tests/fixtures/config/expand2.py @@ -2,7 +2,12 @@ from .. import utils as test_utils -unexpanded_yaml = test_utils.read_config_file("config/expand2-unexpanded.yaml") -expanded_yaml = test_utils.read_config_file("config/expand2-expanded.yaml").format( - HOME=os.path.expanduser("~") -) + +def unexpanded_yaml(): + return test_utils.read_config_file("config/expand2-unexpanded.yaml") + + +def expanded_yaml(): + return test_utils.read_config_file("config/expand2-expanded.yaml").format( + HOME=os.path.expanduser("~") + ) diff --git a/tests/fixtures/config/shell_command_before.py b/tests/fixtures/config/shell_command_before.py index 0f5725e2eec..f458746ad0a 100644 --- a/tests/fixtures/config/shell_command_before.py +++ b/tests/fixtures/config/shell_command_before.py @@ -36,119 +36,126 @@ ], } -config_expanded = { # shell_command_before is string in some areas - "session_name": "sampleconfig", - "start_directory": "/", - "windows": [ - { - "window_name": "editor", - "start_directory": os.path.expanduser("~"), - "shell_command_before": { - "shell_command": [{"cmd": "source .venv/bin/activate"}] - }, - "panes": [ - {"shell_command": [{"cmd": "vim"}]}, - { - "shell_command_before": { - "shell_command": [{"cmd": "rbenv local 2.0.0-p0"}] + +def config_expanded(): + return { # shell_command_before is string in some areas + "session_name": "sampleconfig", + "start_directory": "/", + "windows": [ + { + "window_name": "editor", + "start_directory": os.path.expanduser("~"), + "shell_command_before": { + "shell_command": [{"cmd": "source .venv/bin/activate"}] + }, + "panes": [ + {"shell_command": [{"cmd": "vim"}]}, + { + "shell_command_before": { + "shell_command": [{"cmd": "rbenv local 2.0.0-p0"}] + }, + "shell_command": [{"cmd": 'cowsay "hey"'}], }, - "shell_command": [{"cmd": 'cowsay "hey"'}], + ], + "layout": "main-verticle", + }, + { + "shell_command_before": { + "shell_command": [{"cmd": "rbenv local 2.0.0-p0"}] }, - ], - "layout": "main-verticle", - }, - { - "shell_command_before": { - "shell_command": [{"cmd": "rbenv local 2.0.0-p0"}] + "window_name": "logging", + "panes": [ + {"shell_command": [{"cmd": "tail -F /var/log/syslog"}]}, + {"shell_command": []}, + ], }, - "window_name": "logging", - "panes": [ - {"shell_command": [{"cmd": "tail -F /var/log/syslog"}]}, - {"shell_command": []}, - ], - }, - { - "window_name": "shufu", - "panes": [ - { - "shell_command_before": { - "shell_command": [{"cmd": "rbenv local 2.0.0-p0"}] - }, - "shell_command": [{"cmd": "htop"}], - } - ], - }, - { - "options": {"automatic-rename": True}, - "panes": [{"shell_command": [{"cmd": "htop"}]}], - }, - {"panes": [{"shell_command": [{"cmd": "top"}]}]}, - ], -} - -config_after = { # shell_command_before is string in some areas - "session_name": "sampleconfig", - "start_directory": "/", - "windows": [ - { - "window_name": "editor", - "start_directory": os.path.expanduser("~"), - "shell_command_before": { - "shell_command": [{"cmd": "source .venv/bin/activate"}] + { + "window_name": "shufu", + "panes": [ + { + "shell_command_before": { + "shell_command": [{"cmd": "rbenv local 2.0.0-p0"}] + }, + "shell_command": [{"cmd": "htop"}], + } + ], }, - "panes": [ - { - "shell_command": [ - {"cmd": "source .venv/bin/activate"}, - {"cmd": "vim"}, - ] + { + "options": {"automatic-rename": True}, + "panes": [{"shell_command": [{"cmd": "htop"}]}], + }, + {"panes": [{"shell_command": [{"cmd": "top"}]}]}, + ], + } + + +def config_after(): + return { # shell_command_before is string in some areas + "session_name": "sampleconfig", + "start_directory": "/", + "windows": [ + { + "window_name": "editor", + "start_directory": os.path.expanduser("~"), + "shell_command_before": { + "shell_command": [{"cmd": "source .venv/bin/activate"}] }, - { - "shell_command_before": { - "shell_command": [{"cmd": "rbenv local 2.0.0-p0"}] + "panes": [ + { + "shell_command": [ + {"cmd": "source .venv/bin/activate"}, + {"cmd": "vim"}, + ] }, - "shell_command": [ - {"cmd": "source .venv/bin/activate"}, - {"cmd": "rbenv local 2.0.0-p0"}, - {"cmd": 'cowsay "hey"'}, - ], - }, - ], - "layout": "main-verticle", - }, - { - "shell_command_before": { - "shell_command": [{"cmd": "rbenv local 2.0.0-p0"}] + { + "shell_command_before": { + "shell_command": [{"cmd": "rbenv local 2.0.0-p0"}] + }, + "shell_command": [ + {"cmd": "source .venv/bin/activate"}, + {"cmd": "rbenv local 2.0.0-p0"}, + {"cmd": 'cowsay "hey"'}, + ], + }, + ], + "layout": "main-verticle", }, - "start_directory": "/", - "window_name": "logging", - "panes": [ - { - "shell_command": [ - {"cmd": "rbenv local 2.0.0-p0"}, - {"cmd": "tail -F /var/log/syslog"}, - ] + { + "shell_command_before": { + "shell_command": [{"cmd": "rbenv local 2.0.0-p0"}] }, - {"shell_command": [{"cmd": "rbenv local 2.0.0-p0"}]}, - ], - }, - { - "start_directory": "/", - "window_name": "shufu", - "panes": [ - { - "shell_command_before": { - "shell_command": [{"cmd": "rbenv local 2.0.0-p0"}] + "start_directory": "/", + "window_name": "logging", + "panes": [ + { + "shell_command": [ + {"cmd": "rbenv local 2.0.0-p0"}, + {"cmd": "tail -F /var/log/syslog"}, + ] }, - "shell_command": [{"cmd": "rbenv local 2.0.0-p0"}, {"cmd": "htop"}], - } - ], - }, - { - "start_directory": "/", - "options": {"automatic-rename": True}, - "panes": [{"shell_command": [{"cmd": "htop"}]}], - }, - {"start_directory": "/", "panes": [{"shell_command": [{"cmd": "top"}]}]}, - ], -} + {"shell_command": [{"cmd": "rbenv local 2.0.0-p0"}]}, + ], + }, + { + "start_directory": "/", + "window_name": "shufu", + "panes": [ + { + "shell_command_before": { + "shell_command": [{"cmd": "rbenv local 2.0.0-p0"}] + }, + "shell_command": [ + {"cmd": "rbenv local 2.0.0-p0"}, + {"cmd": "htop"}, + ], + } + ], + }, + { + "start_directory": "/", + "options": {"automatic-rename": True}, + "panes": [{"shell_command": [{"cmd": "htop"}]}], + }, + {"start_directory": "/", "panes": [{"shell_command": [{"cmd": "top"}]}]}, + ], + } diff --git a/tests/test_config.py b/tests/test_config.py index de776b35bf2..5695ae6248d 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -106,13 +106,13 @@ def test_scan_config(tmp_path: pathlib.Path): def test_config_expand1(config_fixture: "ConfigFixture"): """Expand shell commands from string to list.""" test_config = config.expand(config_fixture.expand1.before_config) - assert test_config == config_fixture.expand1.after_config + assert test_config == config_fixture.expand1.after_config() def test_config_expand2(config_fixture: "ConfigFixture"): """Expand shell commands from string to list.""" - unexpanded_dict = load_yaml(config_fixture.expand2.unexpanded_yaml) - expanded_dict = load_yaml(config_fixture.expand2.expanded_yaml) + unexpanded_dict = load_yaml(config_fixture.expand2.unexpanded_yaml()) + expanded_dict = load_yaml(config_fixture.expand2.expanded_yaml()) assert config.expand(unexpanded_dict) == expanded_dict @@ -233,10 +233,10 @@ def test_shell_command_before(config_fixture: "ConfigFixture"): test_config = config_fixture.shell_command_before.config_unexpanded test_config = config.expand(test_config) - assert test_config == config_fixture.shell_command_before.config_expanded + assert test_config == config_fixture.shell_command_before.config_expanded() test_config = config.trickle(test_config) - assert test_config == config_fixture.shell_command_before.config_after + assert test_config == config_fixture.shell_command_before.config_after() def test_in_session_scope(config_fixture: "ConfigFixture"): From 417e6f8399cdd7832efba40bfd1c89e6e296296c Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Aug 2022 08:15:21 -0500 Subject: [PATCH 07/10] test(conftest): Doctest default fixtures Only run on DoctestItem's --- tmuxp/conftest.py | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/tmuxp/conftest.py b/tmuxp/conftest.py index dcb37be2041..2a7b6aaf492 100644 --- a/tmuxp/conftest.py +++ b/tmuxp/conftest.py @@ -2,12 +2,21 @@ import logging import os import pathlib +import typing as t import pytest +from _pytest.doctest import DoctestItem +from _pytest.fixtures import SubRequest + from libtmux import exc +from libtmux.common import which from libtmux.server import Server from libtmux.test import TEST_SESSION_PREFIX, get_test_session_name, namer +from tests.fixtures import utils as test_utils + +if t.TYPE_CHECKING: + from libtmux.session import Session logger = logging.getLogger(__name__) USING_ZSH = "zsh" in os.getenv("SHELL", "") @@ -62,16 +71,16 @@ def socket_name(request): @pytest.fixture(scope="function") -def server(request, socket_name): - t = Server() - t.socket_name = socket_name +def server(request: SubRequest, monkeypatch: pytest.MonkeyPatch) -> Server: + tmux = Server() + tmux.socket_name = socket_name - def fin(): - t.kill_server() + def fin() -> None: + tmux.kill_server() request.addfinalizer(fin) - return t + return tmux @pytest.fixture(scope="function") @@ -108,8 +117,10 @@ def session(server): 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(session.get("session_id")) + server.switch_client(target_session=session_id) except exc.LibTmuxException: # server.attach_session(session.get('session_id')) pass @@ -121,3 +132,17 @@ def session(server): assert TEST_SESSION_NAME != "tmuxp" return session + + +@pytest.fixture(autouse=True) +def add_doctest_fixtures( + request: SubRequest, + doctest_namespace: t.Dict[str, t.Any], +) -> None: + if isinstance(request._pyfuncitem, DoctestItem) and which("tmux"): + doctest_namespace["server"]: "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 + doctest_namespace["test_utils"] = test_utils From 5c8b39ae31f66445b50e0e46a1d4f0f6ce24c927 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Aug 2022 08:24:40 -0500 Subject: [PATCH 08/10] test(doctest): Example config fixture --- tmuxp/config.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tmuxp/config.py b/tmuxp/config.py index 702c12de7d6..2cb0391a096 100644 --- a/tmuxp/config.py +++ b/tmuxp/config.py @@ -100,6 +100,11 @@ def in_cwd(): ------- list configs in current working directory + + Examples + -------- + >>> sorted(in_cwd()) + ['.tmuxp.json', '.tmuxp.yaml'] """ configs = [] From 8124d943057062162225cc6c4156c167b33c85cf Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Aug 2022 09:00:44 -0500 Subject: [PATCH 09/10] tests(doctest): Basic Workspace example --- tmuxp/workspacebuilder.py | 63 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/tmuxp/workspacebuilder.py b/tmuxp/workspacebuilder.py index ca346caa476..8723cc2d039 100644 --- a/tmuxp/workspacebuilder.py +++ b/tmuxp/workspacebuilder.py @@ -27,6 +27,69 @@ class WorkspaceBuilder: Build tmux workspace from a configuration. Creates and names windows, sets options, splits windows into panes. + Examples + -------- + + >>> import yaml + + >>> session_config = yaml.load(''' + ... session_name: sampleconfig + ... start_directory: '~' + ... windows: + ... - window_name: editor + ... layout: main-vertical + ... panes: + ... - shell_command: + ... - cmd: vim + ... - shell_command: + ... - cmd: echo "hey" + ... + ... - window_name: logging + ... panes: + ... - shell_command: + ... - cmd: tail | echo 'hi' + ... + ... - window_name: test + ... panes: + ... - shell_command: + ... - cmd: htop + ... ''', Loader=yaml.Loader) + + >>> builder = WorkspaceBuilder(sconf=session_config, server=server) + + ***New session:** + + >>> builder.build() + + >>> new_session = builder.session + + >>> new_session.name == 'sampleconfig' + True + + >>> len(new_session._windows) + 3 + + >>> sorted([window.name for window in new_session.windows]) + ['editor', 'logging', 'test'] + + **Existing session** + + >>> len(session._windows) + 1 + + >>> builder.build(session=session) + + _Caveat:_ Preserves old session name: + + >>> session.name == 'sampleconfig' + False + + >>> len(session._windows) + 3 + + >>> sorted([window.name for window in session.windows]) + ['editor', 'logging', 'test'] + The normal phase of loading is: 1. :term:`kaptan` imports json/yaml/ini. ``.get()`` returns python From 47910b5ef760fbd52a06913004b6375c0f6877c3 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Aug 2022 09:21:25 -0500 Subject: [PATCH 10/10] docs(CHANGES): Note doctest PR --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index d73b06ecd4a..c826574e06a 100644 --- a/CHANGES +++ b/CHANGES @@ -22,6 +22,8 @@ $ pipx install --suffix=@next 'tmuxp' --pip-args '\--pre' --force ### Internal - libtmux updated from v0.12 to v0.14 {issue}`790` +- Add [doctest](https://docs.python.org/3/library/doctest.html) w/ + [pytest + doctest](https://docs.pytest.org/en/7.1.x/how-to/doctest.html), ({issue}`791`). ## tmuxp 1.12.1 (2022-08-04)