diff --git a/CHANGES b/CHANGES index 71ce18513ec..ca6b363a9f9 100644 --- a/CHANGES +++ b/CHANGES @@ -11,9 +11,9 @@ ```yaml session_name: Should not execute windows: - - panes: - - shell_command: echo "___$((1 + 3))___" - enter: false + - panes: + - shell_command: echo "___$((1 + 3))___" + enter: false ``` - #701: `tmuxp freeze` now accepts `--quiet` and `--yes` along with the diff --git a/Makefile b/Makefile index 9b02c94f1de..811a7aded17 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ PY_FILES= find . -type f -not -path '*/\.*' | grep -i '.*[.]py$$' 2> /dev/null +TEST_FILES= find . -type f -not -path '*/\.*' | grep -i '.*[.]\(yaml\|py\)$$' 2> /dev/null DOC_FILES= find . -type f -not -path '*/\.*' | grep -i '.*[.]rst\$\|.*[.]md\$\|.*[.]css\$\|.*[.]py\$\|mkdocs\.yml\|CHANGES\|TODO\|.*conf\.py' 2> /dev/null SHELL := /bin/bash @@ -23,7 +24,7 @@ start: $(MAKE) test; poetry run ptw . watch_test: - if command -v entr > /dev/null; then ${PY_FILES} | entr -c $(MAKE) test; else $(MAKE) test entr_warn; fi + if command -v entr > /dev/null; then ${TEST_FILES} | entr -c $(MAKE) test; else $(MAKE) test entr_warn; fi build_docs: $(MAKE) -C docs html diff --git a/docs/cli.md b/docs/cli.md index 332738e4479..01ae7255215 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -188,6 +188,7 @@ $ tmuxp load /path/to/folder/ ``` Name of the config, assume `$HOME/.tmuxp/myconfig.yaml`: + ```console $ tmuxp load myconfig ``` @@ -236,11 +237,13 @@ All of these options can be preselected to skip the prompt: ```console $ tmuxp load -y config ``` + - Detached / open in background: ```console $ tmuxp load -d config ``` + - Append windows to existing session ```console diff --git a/setup.cfg b/setup.cfg index 84854c63997..c271bb3b4f3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -3,42 +3,7 @@ exclude = .*/,.tox,*.egg,tmuxp/_compat.py,tmuxp/__*__.py, select = E,W,F,N max-line-length = 88 # Stuff we ignore thanks to black: https://github.com/ambv/black/issues/429 -ignore = E111, - E121, - E122, - E123, - E124, - E125, - E126, - E201, - E202, - E203, - E221, - E222, - E225, - E226, - E227, - E231, - E241, - E251, - E261, - E262, - E265, - E271, - E272, - E302, - E303, - E306, - E502, - E701, - E702, - E703, - E704, - W291, - W292, - W293, - W391, - W503 +extend-ignore = E203 [tool:pytest] addopts = --reruns=0 @@ -46,6 +11,7 @@ filterwarnings = ignore:distutils Version classes are deprecated. Use packaging.version instead. [isort] +profile = black combine_as_imports= true default_section = THIRDPARTY include_trailing_comma = true diff --git a/tests/__init__.py b/tests/__init__.py index 89d3f1684f0..6233b234811 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -4,8 +4,8 @@ ~~~~~~~~~~~ """ -import os +import pathlib -current_dir = os.path.abspath(os.path.dirname(__file__)) -example_dir = os.path.abspath(os.path.join(current_dir, "..", "examples")) -fixtures_dir = os.path.realpath(os.path.join(current_dir, "fixtures")) +TESTS_PATH = pathlib.Path(__file__).parent +EXAMPLE_PATH = TESTS_PATH.parent / "examples" +FIXTURES_PATH = TESTS_PATH / "fixtures" diff --git a/tests/conftest.py b/tests/conftest.py index 7ab1d4ae72a..da5d1713a00 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,7 @@ +import getpass import logging import os +import pathlib import pytest @@ -10,6 +12,23 @@ logger = logging.getLogger(__name__) +@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.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 = [ diff --git a/tests/test_config.py b/tests/test_config.py index 181751684bf..a89b3631548 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1,5 +1,8 @@ """Test for tmuxp configuration import, inlining, expanding and export.""" import os +import pathlib +import typing +from typing import Union import pytest @@ -7,89 +10,109 @@ from tmuxp import config, exc -from . import example_dir -from .fixtures import config as fixtures +from . import EXAMPLE_PATH -TMUXP_DIR = os.path.join(os.path.dirname(__file__), ".tmuxp") +if typing.TYPE_CHECKING: + from .fixtures import config as ConfigFixture -def load_yaml(yaml): - return kaptan.Kaptan(handler="yaml").import_config(yaml).get() +@pytest.fixture +def config_fixture(): + """Deferred import of tmuxp.tests.fixtures.* + + pytest setup (conftest.py) patches os.environ["HOME"], delay execution of + os.path.expanduser until here. + """ + from .fixtures import config as config_fixture + + return config_fixture -def load_config(_file): - return kaptan.Kaptan().import_config(_file).get() +def load_yaml(path: Union[str, pathlib.Path]) -> str: + return ( + kaptan.Kaptan(handler="yaml") + .import_config(str(path) if isinstance(path, pathlib.Path) else path) + .get() + ) + +def load_config(path: Union[str, pathlib.Path]) -> str: + return ( + kaptan.Kaptan() + .import_config(str(path) if isinstance(path, pathlib.Path) else path) + .get() + ) -def test_export_json(tmpdir): - json_config_file = tmpdir.join("config.json") + +def test_export_json(tmp_path: pathlib.Path, config_fixture: "ConfigFixture"): + json_config_file = tmp_path / "config.json" configparser = kaptan.Kaptan() - configparser.import_config(fixtures.sampleconfig.sampleconfigdict) + configparser.import_config(config_fixture.sampleconfig.sampleconfigdict) json_config_data = configparser.export("json", indent=2) - json_config_file.write(json_config_data) + json_config_file.write_text(json_config_data, encoding="utf-8") new_config = kaptan.Kaptan() new_config_data = new_config.import_config(str(json_config_file)).get() - assert fixtures.sampleconfig.sampleconfigdict == new_config_data + assert config_fixture.sampleconfig.sampleconfigdict == new_config_data -def test_export_yaml(tmpdir): - yaml_config_file = tmpdir.join("config.yaml") +def test_export_yaml(tmp_path: pathlib.Path, config_fixture: "ConfigFixture"): + yaml_config_file = tmp_path / "config.yaml" configparser = kaptan.Kaptan() - sampleconfig = config.inline(fixtures.sampleconfig.sampleconfigdict) + sampleconfig = config.inline(config_fixture.sampleconfig.sampleconfigdict) configparser.import_config(sampleconfig) yaml_config_data = configparser.export("yaml", indent=2, default_flow_style=False) - yaml_config_file.write(yaml_config_data) + yaml_config_file.write_text(yaml_config_data, encoding="utf-8") new_config_data = load_config(str(yaml_config_file)) - assert fixtures.sampleconfig.sampleconfigdict == new_config_data + assert config_fixture.sampleconfig.sampleconfigdict == new_config_data -def test_scan_config(tmpdir): +def test_scan_config(tmp_path: pathlib.Path): configs = [] - garbage_file = tmpdir.join("config.psd") - garbage_file.write("wat") + garbage_file = tmp_path / "config.psd" + garbage_file.write_text("wat", encoding="utf-8") - for r, d, f in os.walk(str(tmpdir)): + for r, d, f in os.walk(str(tmp_path)): for filela in (x for x in f if x.endswith((".json", ".ini", "yaml"))): - configs.append(str(tmpdir.join(filela))) + configs.append(str(tmp_path / filela)) files = 0 - if tmpdir.join("config.json").check(): + config_json = tmp_path / "config.json" + config_yaml = tmp_path / "config.yaml" + config_ini = tmp_path / "config.ini" + if config_json.exists(): files += 1 - assert str(tmpdir.join("config.json")) in configs + assert str(config_json) in configs - if tmpdir.join("config.yaml").check(): + if config_yaml.exists(): files += 1 - assert str(tmpdir.join("config.yaml")) in configs + assert str(config_yaml) in configs - if tmpdir.join("config.ini").check(): + if config_ini.exists(): files += 1 - assert str(tmpdir.join("config.ini")) in configs + assert str(config_ini) in configs assert len(configs) == files -def test_config_expand1(): +def test_config_expand1(config_fixture: "ConfigFixture"): """Expand shell commands from string to list.""" - test_config = config.expand(fixtures.expand1.before_config) - assert test_config == fixtures.expand1.after_config + test_config = config.expand(config_fixture.expand1.before_config) + assert test_config == config_fixture.expand1.after_config -def test_config_expand2(): +def test_config_expand2(config_fixture: "ConfigFixture"): """Expand shell commands from string to list.""" - - unexpanded_dict = load_yaml(fixtures.expand2.unexpanded_yaml) - - expanded_dict = load_yaml(fixtures.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 @@ -205,31 +228,31 @@ def test_inheritance_config(): assert config == inheritance_config_after -def test_shell_command_before(): +def test_shell_command_before(config_fixture: "ConfigFixture"): """Config inheritance for the nested 'start_command'.""" - test_config = fixtures.shell_command_before.config_unexpanded + test_config = config_fixture.shell_command_before.config_unexpanded test_config = config.expand(test_config) - assert test_config == fixtures.shell_command_before.config_expanded + assert test_config == config_fixture.shell_command_before.config_expanded test_config = config.trickle(test_config) - assert test_config == fixtures.shell_command_before.config_after + assert test_config == config_fixture.shell_command_before.config_after -def test_in_session_scope(): - sconfig = load_yaml(fixtures.shell_command_before_session.before) +def test_in_session_scope(config_fixture: "ConfigFixture"): + sconfig = load_yaml(config_fixture.shell_command_before_session.before) config.validate_schema(sconfig) assert config.expand(sconfig) == sconfig assert config.expand(config.trickle(sconfig)) == load_yaml( - fixtures.shell_command_before_session.expected + config_fixture.shell_command_before_session.expected ) -def test_trickle_relative_start_directory(): - test_config = config.trickle(fixtures.trickle.before) - assert test_config == fixtures.trickle.expected +def test_trickle_relative_start_directory(config_fixture: "ConfigFixture"): + test_config = config.trickle(config_fixture.trickle.before) + assert test_config == config_fixture.trickle.expected def test_trickle_window_with_no_pane_config(): @@ -250,7 +273,7 @@ def test_trickle_window_with_no_pane_config(): } -def test_expands_blank_panes(): +def test_expands_blank_panes(config_fixture: "ConfigFixture"): """Expand blank config into full form. Handle ``NoneType`` and 'blank':: @@ -277,10 +300,9 @@ def test_expands_blank_panes(): 'shell_command': [''] """ - - yaml_config_file = os.path.join(example_dir, "blank-panes.yaml") + yaml_config_file = EXAMPLE_PATH / "blank-panes.yaml" test_config = load_config(yaml_config_file) - assert config.expand(test_config) == fixtures.expand_blank.expected + assert config.expand(test_config) == config_fixture.expand_blank.expected def test_no_session_name(): diff --git a/tests/test_config_teamocil.py b/tests/test_config_teamocil.py index 721e3878abf..dc040261c38 100644 --- a/tests/test_config_teamocil.py +++ b/tests/test_config_teamocil.py @@ -1,6 +1,4 @@ """Test for tmuxp teamocil configuration.""" -import os - import pytest import kaptan @@ -9,8 +7,6 @@ from .fixtures import config_teamocil as fixtures -TMUXP_DIR = os.path.join(os.path.dirname(__file__), ".tmuxp") - @pytest.mark.parametrize( "teamocil_yaml,teamocil_dict,tmuxp_dict", diff --git a/tests/test_config_tmuxinator.py b/tests/test_config_tmuxinator.py index 88241c22a93..ddcf34e68ac 100644 --- a/tests/test_config_tmuxinator.py +++ b/tests/test_config_tmuxinator.py @@ -1,6 +1,4 @@ """Test for tmuxp tmuxinator configuration.""" -import os - import pytest import kaptan @@ -9,8 +7,6 @@ from .fixtures import config_tmuxinator as fixtures -TMUXP_DIR = os.path.join(os.path.dirname(__file__), ".tmuxp") - @pytest.mark.parametrize( "tmuxinator_yaml,tmuxinator_dict,tmuxp_dict", diff --git a/tests/test_util.py b/tests/test_util.py index e87c3bf0f96..c5f5b53824a 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -1,17 +1,15 @@ """Tests for utility functions in tmux.""" -import os - import pytest from tmuxp import exc from tmuxp.exc import BeforeLoadScriptError, BeforeLoadScriptNotExists from tmuxp.util import get_session, run_before_script -from . import fixtures_dir +from . import FIXTURES_PATH def test_raise_BeforeLoadScriptNotExists_if_not_exists(): - script_file = os.path.join(fixtures_dir, "script_noexists.sh") + script_file = FIXTURES_PATH / "script_noexists.sh" with pytest.raises(BeforeLoadScriptNotExists): run_before_script(script_file) @@ -21,14 +19,14 @@ def test_raise_BeforeLoadScriptNotExists_if_not_exists(): def test_raise_BeforeLoadScriptError_if_retcode(): - script_file = os.path.join(fixtures_dir, "script_failed.sh") + script_file = FIXTURES_PATH / "script_failed.sh" with pytest.raises(BeforeLoadScriptError): run_before_script(script_file) def test_return_stdout_if_ok(capsys): - script_file = os.path.join(fixtures_dir, "script_complete.sh") + script_file = FIXTURES_PATH / "script_complete.sh" run_before_script(script_file) out, err = capsys.readouterr() @@ -36,7 +34,7 @@ def test_return_stdout_if_ok(capsys): def test_beforeload_returncode(): - script_file = os.path.join(fixtures_dir, "script_failed.sh") + script_file = FIXTURES_PATH / "script_failed.sh" with pytest.raises(exc.BeforeLoadScriptError) as excinfo: run_before_script(script_file) @@ -44,7 +42,7 @@ def test_beforeload_returncode(): def test_beforeload_returns_stderr_messages(): - script_file = os.path.join(fixtures_dir, "script_failed.sh") + script_file = FIXTURES_PATH / "script_failed.sh" with pytest.raises(exc.BeforeLoadScriptError) as excinfo: run_before_script(script_file) diff --git a/tests/test_workspacebuilder.py b/tests/test_workspacebuilder.py index c5771a6024a..75000050a75 100644 --- a/tests/test_workspacebuilder.py +++ b/tests/test_workspacebuilder.py @@ -16,7 +16,7 @@ from tmuxp.cli import load_plugins from tmuxp.workspacebuilder import WorkspaceBuilder -from . import example_dir, fixtures_dir +from . import EXAMPLE_PATH, FIXTURES_PATH from .fixtures._util import load_fixture @@ -405,8 +405,8 @@ def test_automatic_rename_option(session): def test_blank_pane_count(session): """:todo: Verify blank panes of various types build into workspaces.""" - yaml_config_file = os.path.join(example_dir, "blank-panes.yaml") - test_config = kaptan.Kaptan().import_config(yaml_config_file).get() + yaml_config_file = EXAMPLE_PATH / "blank-panes.yaml" + test_config = kaptan.Kaptan().import_config(str(yaml_config_file)).get() test_config = config.expand(test_config) builder = WorkspaceBuilder(sconf=test_config) builder.build(session=session) @@ -589,8 +589,7 @@ def test_before_load_throw_error_if_retcode_error(server): config_script_fails = load_fixture("workspacebuilder/config_script_fails.yaml") sconfig = kaptan.Kaptan(handler="yaml") yaml = config_script_fails.format( - fixtures_dir=fixtures_dir, - script_failed=os.path.join(fixtures_dir, "script_failed.sh"), + script_failed=FIXTURES_PATH / "script_failed.sh", ) sconfig = sconfig.import_config(yaml).get() @@ -615,8 +614,7 @@ def test_before_load_throw_error_if_file_not_exists(server): ) sconfig = kaptan.Kaptan(handler="yaml") yaml = config_script_not_exists.format( - fixtures_dir=fixtures_dir, - script_not_exists=os.path.join(fixtures_dir, "script_not_exists.sh"), + script_not_exists=FIXTURES_PATH / "script_not_exists.sh", ) sconfig = sconfig.import_config(yaml).get() sconfig = config.expand(sconfig) @@ -639,11 +637,11 @@ def test_before_load_true_if_test_passes(server): config_script_completes = load_fixture( "workspacebuilder/config_script_completes.yaml" ) - assert os.path.exists(os.path.join(fixtures_dir, "script_complete.sh")) + script_complete_sh = FIXTURES_PATH / "script_complete.sh" + assert script_complete_sh.exists() sconfig = kaptan.Kaptan(handler="yaml") yaml = config_script_completes.format( - fixtures_dir=fixtures_dir, - script_complete=os.path.join(fixtures_dir, "script_complete.sh"), + script_complete=script_complete_sh, ) sconfig = sconfig.import_config(yaml).get() @@ -660,13 +658,10 @@ def test_before_load_true_if_test_passes_with_args(server): config_script_completes = load_fixture( "workspacebuilder/config_script_completes.yaml" ) - - assert os.path.exists(os.path.join(fixtures_dir, "script_complete.sh")) + script_complete_sh = FIXTURES_PATH / "script_complete.sh" + assert script_complete_sh.exists() sconfig = kaptan.Kaptan(handler="yaml") - yaml = config_script_completes.format( - fixtures_dir=fixtures_dir, - script_complete=os.path.join(fixtures_dir, "script_complete.sh") + " -v", - ) + yaml = config_script_completes.format(script_complete=script_complete_sh) sconfig = sconfig.import_config(yaml).get() sconfig = config.expand(sconfig)