diff --git a/dotbot/dispatcher.py b/dotbot/dispatcher.py index 630c895..ad82bd9 100644 --- a/dotbot/dispatcher.py +++ b/dotbot/dispatcher.py @@ -7,7 +7,13 @@ from .context import Context class Dispatcher(object): def __init__( - self, base_directory, only=None, skip=None, exit_on_failure=False, options=Namespace(), plugins=None, + self, + base_directory, + only=None, + skip=None, + exit_on_failure=False, + options=Namespace(), + plugins=None, ): self._log = Messenger() self._setup_context(base_directory, options) diff --git a/dotbot/plugins/clean.py b/dotbot/plugins/clean.py index 1d17b72..70d3522 100644 --- a/dotbot/plugins/clean.py +++ b/dotbot/plugins/clean.py @@ -44,7 +44,9 @@ class Clean(Plugin): self._log.debug("Ignoring nonexistent directory %s" % target) return True for item in os.listdir(os.path.expandvars(os.path.expanduser(target))): - path = os.path.abspath(os.path.join(os.path.expandvars(os.path.expanduser(target)), item)) + path = os.path.abspath( + os.path.join(os.path.expandvars(os.path.expanduser(target)), item) + ) if recursive and os.path.isdir(path): # isdir implies not islink -- we don't want to descend into # symlinked directories. okay to do a recursive call here diff --git a/tests/conftest.py b/tests/conftest.py index 74a01a8..3d9da2e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -45,7 +45,7 @@ def wrap_function(function, function_path, arg_index, kwarg_key, root): msg = "The '{0}' argument to {1}() must be rooted in {2}" msg = msg.format(kwarg_key, function_path, root) - assert value[:len(str(root))] == str(root), msg + assert value[: len(str(root))] == str(root), msg return function(*args, **kwargs) @@ -78,7 +78,7 @@ def wrap_open(root): msg = "The 'file' argument to open() must be rooted in {0}" msg = msg.format(root) if value != os.devnull and "w" in mode: - assert value[:len(str(root))] == str(root), msg + assert value[: len(str(root))] == str(root), msg return wrapped(*args, **kwargs) @@ -161,9 +161,7 @@ def root(): # to ensure the variable closures work correctly. function_path = "{0}.{1}".format(module.__name__, function_name) function = getattr(module, function_name) - wrapped = wrap_function( - function, function_path, arg_index, kwarg_key, current_root - ) + wrapped = wrap_function(function, function_path, arg_index, kwarg_key, current_root) patches.append(mock.patch(function_path, wrapped)) # open() must be separately wrapped. @@ -251,7 +249,7 @@ class Dotfiles(object): msg = "The config file path must be rooted in {0}" msg = msg.format(root) - assert path[:len(str(root))] == str(root), msg + assert path[: len(str(root))] == str(root), msg self.config_filename = path else: diff --git a/tests/dotbot_plugin_directory.py b/tests/dotbot_plugin_directory.py index 5ab828a..517b5c8 100644 --- a/tests/dotbot_plugin_directory.py +++ b/tests/dotbot_plugin_directory.py @@ -16,7 +16,9 @@ class Directory(dotbot.Plugin): self._log.debug("Attempting to get options from Context") options = self._context.options() if len(options.plugin_dirs) != 1: - self._log.debug("Context.options.plugins length is %i, expected 1" % len(options.plugins)) + self._log.debug( + "Context.options.plugins length is %i, expected 1" % len(options.plugins) + ) return False with open(os.path.abspath(os.path.expanduser("~/flag")), "w") as file: diff --git a/tests/dotbot_plugin_file.py b/tests/dotbot_plugin_file.py index 23b6a36..832d585 100644 --- a/tests/dotbot_plugin_file.py +++ b/tests/dotbot_plugin_file.py @@ -16,10 +16,14 @@ class File(dotbot.Plugin): self._log.debug("Attempting to get options from Context") options = self._context.options() if len(options.plugins) != 1: - self._log.debug("Context.options.plugins length is %i, expected 1" % len(options.plugins)) + self._log.debug( + "Context.options.plugins length is %i, expected 1" % len(options.plugins) + ) return False if not options.plugins[0].endswith("file.py"): - self._log.debug("Context.options.plugins[0] is %s, expected end with file.py" % options.plugins[0]) + self._log.debug( + "Context.options.plugins[0] is %s, expected end with file.py" % options.plugins[0] + ) return False with open(os.path.abspath(os.path.expanduser("~/flag")), "w") as file: diff --git a/tests/test_clean.py b/tests/test_clean.py index e67d4de..63bcd75 100644 --- a/tests/test_clean.py +++ b/tests/test_clean.py @@ -15,10 +15,7 @@ import pytest # For these reasons, if the tests are running on Windows with Python < 3.8 # or with PyPy, the entire link test suite must be skipped. # -if ( - sys.platform[:5] == "win32" - and (sys.version_info < (3, 8) or "pypy" in sys.version.lower()) -): +if sys.platform[:5] == "win32" and (sys.version_info < (3, 8) or "pypy" in sys.version.lower()): reason = "It is impossible to perform link tests on this platform" pytestmark = pytest.mark.skip(reason=reason) @@ -27,12 +24,16 @@ def test_clean_default(root, home, dotfiles, run_dotbot): """Verify clean uses default unless overridden.""" os.symlink(os.path.join(root, "nowhere"), os.path.join(home, ".g")) - dotfiles.write_config([{ - "clean": { - "~/nonexistent": {"force": True}, - "~/": None, - }, - }]) + dotfiles.write_config( + [ + { + "clean": { + "~/nonexistent": {"force": True}, + "~/": None, + }, + } + ] + ) run_dotbot() assert not os.path.isdir(os.path.join(home, "nonexistent")) @@ -140,10 +141,12 @@ def test_clean_defaults_2(root, home, dotfiles, run_dotbot): """Verify that explicit clean defaults override the implicit default.""" os.symlink(os.path.join(root, "nowhere"), os.path.join(home, ".g")) - dotfiles.write_config([ - {"defaults": {"clean": {"force": True}}}, - {"clean": ["~"]}, - ]) + dotfiles.write_config( + [ + {"defaults": {"clean": {"force": True}}}, + {"clean": ["~"]}, + ] + ) run_dotbot() assert not os.path.islink(os.path.join(home, ".g")) diff --git a/tests/test_cli.py b/tests/test_cli.py index 8ce690a..5868e6f 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -7,12 +7,16 @@ import pytest def test_except_create(capfd, home, dotfiles, run_dotbot): """Verify that `--except` works as intended.""" - dotfiles.write_config([ - {"create": ["~/a"]}, - {"shell": [ - {"command": "echo success", "stdout": True}, - ]}, - ]) + dotfiles.write_config( + [ + {"create": ["~/a"]}, + { + "shell": [ + {"command": "echo success", "stdout": True}, + ] + }, + ] + ) run_dotbot("--except", "create") assert not os.path.exists(os.path.join(home, "a")) @@ -23,12 +27,16 @@ def test_except_create(capfd, home, dotfiles, run_dotbot): def test_except_shell(capfd, home, dotfiles, run_dotbot): """Verify that `--except` works as intended.""" - dotfiles.write_config([ - {"create": ["~/a"]}, - {"shell": [ - {"command": "echo failure", "stdout": True}, - ]}, - ]) + dotfiles.write_config( + [ + {"create": ["~/a"]}, + { + "shell": [ + {"command": "echo failure", "stdout": True}, + ] + }, + ] + ) run_dotbot("--except", "shell") assert os.path.exists(os.path.join(home, "a")) @@ -39,12 +47,16 @@ def test_except_shell(capfd, home, dotfiles, run_dotbot): def test_except_multiples(capfd, home, dotfiles, run_dotbot): """Verify that `--except` works with multiple exceptions.""" - dotfiles.write_config([ - {"create": ["~/a"]}, - {"shell": [ - {"command": "echo failure", "stdout": True}, - ]}, - ]) + dotfiles.write_config( + [ + {"create": ["~/a"]}, + { + "shell": [ + {"command": "echo failure", "stdout": True}, + ] + }, + ] + ) run_dotbot("--except", "create", "shell") assert not os.path.exists(os.path.join(home, "a")) @@ -55,11 +67,13 @@ def test_except_multiples(capfd, home, dotfiles, run_dotbot): def test_exit_on_failure(capfd, home, dotfiles, run_dotbot): """Verify that processing can halt immediately on failures.""" - dotfiles.write_config([ - {"create": ["~/a"]}, - {"shell": ["this_is_not_a_command"]}, - {"create": ["~/b"]}, - ]) + dotfiles.write_config( + [ + {"create": ["~/a"]}, + {"shell": ["this_is_not_a_command"]}, + {"create": ["~/b"]}, + ] + ) with pytest.raises(SystemExit): run_dotbot("-x") @@ -70,10 +84,12 @@ def test_exit_on_failure(capfd, home, dotfiles, run_dotbot): def test_only(capfd, home, dotfiles, run_dotbot): """Verify that `--only` works as intended.""" - dotfiles.write_config([ - {"create": ["~/a"]}, - {"shell": [{"command": "echo success", "stdout": True}]}, - ]) + dotfiles.write_config( + [ + {"create": ["~/a"]}, + {"shell": [{"command": "echo success", "stdout": True}]}, + ] + ) run_dotbot("--only", "shell") assert not os.path.exists(os.path.join(home, "a")) @@ -84,11 +100,13 @@ def test_only(capfd, home, dotfiles, run_dotbot): def test_only_with_defaults(capfd, home, dotfiles, run_dotbot): """Verify that `--only` does not suppress defaults.""" - dotfiles.write_config([ - {"defaults": {"shell": {"stdout": True}}}, - {"create": ["~/a"]}, - {"shell": [{"command": "echo success"}]}, - ]) + dotfiles.write_config( + [ + {"defaults": {"shell": {"stdout": True}}}, + {"create": ["~/a"]}, + {"shell": [{"command": "echo success"}]}, + ] + ) run_dotbot("--only", "shell") assert not os.path.exists(os.path.join(home, "a")) @@ -99,11 +117,13 @@ def test_only_with_defaults(capfd, home, dotfiles, run_dotbot): def test_only_with_multiples(capfd, home, dotfiles, run_dotbot): """Verify that `--only` works as intended.""" - dotfiles.write_config([ - {"create": ["~/a"]}, - {"shell": [{"command": "echo success", "stdout": True}]}, - {"link": ["~/.f"]} - ]) + dotfiles.write_config( + [ + {"create": ["~/a"]}, + {"shell": [{"command": "echo success", "stdout": True}]}, + {"link": ["~/.f"]}, + ] + ) run_dotbot("--only", "create", "shell") assert os.path.isdir(os.path.join(home, "a")) @@ -128,7 +148,9 @@ def test_plugin_loading_directory(home, dotfiles, run_dotbot): """Verify that plugins can be loaded from a directory.""" dotfiles.makedirs("plugins") - plugin_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), "dotbot_plugin_directory.py") + plugin_file = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "dotbot_plugin_directory.py" + ) shutil.copy(plugin_file, os.path.join(dotfiles.directory, "plugins", "directory.py")) dotfiles.write_config([{"plugin_directory": "~"}]) run_dotbot("--plugin-dir", os.path.join(dotfiles.directory, "plugins")) diff --git a/tests/test_create.py b/tests/test_create.py index 7ea1ab6..7b2c6d5 100644 --- a/tests/test_create.py +++ b/tests/test_create.py @@ -24,10 +24,7 @@ def test_default_mode(home, dotfiles, run_dotbot): """ read_only = 0o777 - stat.S_IWUSR - stat.S_IWGRP - stat.S_IWOTH - config = [ - {"defaults": {"create": {"mode": read_only}}}, - {"create": ["~/a"]} - ] + config = [{"defaults": {"create": {"mode": read_only}}}, {"create": ["~/a"]}] dotfiles.write_config(config) run_dotbot() diff --git a/tests/test_link.py b/tests/test_link.py index e620b6a..37ddded 100644 --- a/tests/test_link.py +++ b/tests/test_link.py @@ -15,10 +15,7 @@ import pytest # For these reasons, if the tests are running on Windows with Python < 3.8 # or with PyPy, the entire link test suite must be skipped. # -if ( - sys.platform[:5] == "win32" - and (sys.version_info < (3, 8) or "pypy" in sys.version.lower()) -): +if sys.platform[:5] == "win32" and (sys.version_info < (3, 8) or "pypy" in sys.version.lower()): reason = "It is impossible to perform link tests on this platform" pytestmark = pytest.mark.skip(reason=reason) @@ -98,7 +95,9 @@ def test_link_environment_variable_expansion_source(monkeypatch, root, home, dot assert file.read() == "grape" -def test_link_environment_variable_expansion_source_extended(monkeypatch, root, home, dotfiles, run_dotbot): +def test_link_environment_variable_expansion_source_extended( + monkeypatch, root, home, dotfiles, run_dotbot +): """Verify link expands environment variables in extended config syntax.""" monkeypatch.setenv("APPLE", "h") @@ -198,10 +197,12 @@ def test_link_glob_1(home, dotfiles, run_dotbot): dotfiles.write("bin/a", "apple") dotfiles.write("bin/b", "banana") dotfiles.write("bin/c", "cherry") - dotfiles.write_config([ - {"defaults": {"link": {"glob": True, "create": True}}}, - {"link": {"~/bin": "bin/*"}}, - ]) + dotfiles.write_config( + [ + {"defaults": {"link": {"glob": True, "create": True}}}, + {"link": {"~/bin": "bin/*"}}, + ] + ) run_dotbot() with open(os.path.join(home, "bin", "a")) as file: @@ -218,10 +219,12 @@ def test_link_glob_2(home, dotfiles, run_dotbot): dotfiles.write("bin/a", "apple") dotfiles.write("bin/b", "banana") dotfiles.write("bin/c", "cherry") - dotfiles.write_config([ - {"defaults": {"link": {"glob": True, "create": True}}}, - {"link": {"~/bin/": "bin/*"}}, - ]) + dotfiles.write_config( + [ + {"defaults": {"link": {"glob": True, "create": True}}}, + {"link": {"~/bin/": "bin/*"}}, + ] + ) run_dotbot() with open(os.path.join(home, "bin", "a")) as file: @@ -238,10 +241,12 @@ def test_link_glob_3(home, dotfiles, run_dotbot): dotfiles.write("bin/.a", "dot-apple") dotfiles.write("bin/.b", "dot-banana") dotfiles.write("bin/.c", "dot-cherry") - dotfiles.write_config([ - {"defaults": {"link": {"glob": True, "create": True}}}, - {"link": {"~/bin/": "bin/.*"}}, - ]) + dotfiles.write_config( + [ + {"defaults": {"link": {"glob": True, "create": True}}}, + {"link": {"~/bin/": "bin/.*"}}, + ] + ) run_dotbot() with open(os.path.join(home, "bin", ".a")) as file: @@ -258,14 +263,18 @@ def test_link_glob_4(home, dotfiles, run_dotbot): dotfiles.write(".a", "dot-apple") dotfiles.write(".b", "dot-banana") dotfiles.write(".c", "dot-cherry") - dotfiles.write_config([{ - "link": { - "~": { - "path": ".*", - "glob": True, - }, - }, - }]) + dotfiles.write_config( + [ + { + "link": { + "~": { + "path": ".*", + "glob": True, + }, + }, + } + ] + ) run_dotbot() with open(os.path.join(home, ".a")) as file: @@ -281,14 +290,18 @@ def test_link_glob_ambiguous_failure(path, home, dotfiles, run_dotbot): """Verify ambiguous link globbing fails.""" dotfiles.makedirs("foo") - dotfiles.write_config([{ - "link": { - "~/foo/": { - "path": path, - "glob": True, + dotfiles.write_config( + [ + { + "link": { + "~/foo/": { + "path": path, + "glob": True, + } + } } - } - }]) + ] + ) with pytest.raises(SystemExit): run_dotbot() assert not os.path.exists(os.path.join(home, "foo")) @@ -298,14 +311,18 @@ def test_link_glob_ambiguous_success(home, dotfiles, run_dotbot): """Verify the case where ambiguous link globbing succeeds.""" dotfiles.makedirs("foo") - dotfiles.write_config([{ - "link": { - "~/foo": { - "path": "foo", - "glob": True, + dotfiles.write_config( + [ + { + "link": { + "~/foo": { + "path": "foo", + "glob": True, + } + } } - } - }]) + ] + ) run_dotbot() assert os.path.exists(os.path.join(home, "foo")) @@ -317,24 +334,26 @@ def test_link_glob_exclude_1(home, dotfiles, run_dotbot): dotfiles.write("config/bar/b", "banana") dotfiles.write("config/bar/c", "cherry") dotfiles.write("config/baz/d", "donut") - dotfiles.write_config([ - { - "defaults": { + dotfiles.write_config( + [ + { + "defaults": { + "link": { + "glob": True, + "create": True, + }, + }, + }, + { "link": { - "glob": True, - "create": True, + "~/.config/": { + "path": "config/*", + "exclude": ["config/baz"], + }, }, }, - }, - { - "link": { - "~/.config/": { - "path": "config/*", - "exclude": ["config/baz"], - }, - }, - }, - ]) + ] + ) run_dotbot() assert not os.path.exists(os.path.join(home, ".config", "baz")) @@ -358,24 +377,26 @@ def test_link_glob_exclude_2(home, dotfiles, run_dotbot): dotfiles.write("config/bar/c", "cherry") dotfiles.write("config/baz/d", "donut") dotfiles.write("config/baz/buzz/e", "egg") - dotfiles.write_config([ - { - "defaults": { + dotfiles.write_config( + [ + { + "defaults": { + "link": { + "glob": True, + "create": True, + }, + }, + }, + { "link": { - "glob": True, - "create": True, + "~/.config/": { + "path": "config/*/*", + "exclude": ["config/baz/*"], + }, }, }, - }, - { - "link": { - "~/.config/": { - "path": "config/*/*", - "exclude": ["config/baz/*"], - }, - }, - }, - ]) + ] + ) run_dotbot() assert not os.path.exists(os.path.join(home, ".config", "baz")) @@ -401,24 +422,26 @@ def test_link_glob_exclude_3(home, dotfiles, run_dotbot): dotfiles.write("config/baz/d", "donut") dotfiles.write("config/baz/buzz/e", "egg") dotfiles.write("config/baz/bizz/g", "grape") - dotfiles.write_config([ - { - "defaults": { + dotfiles.write_config( + [ + { + "defaults": { + "link": { + "glob": True, + "create": True, + }, + }, + }, + { "link": { - "glob": True, - "create": True, + "~/.config/": { + "path": "config/*/*", + "exclude": ["config/baz/buzz"], + }, }, }, - }, - { - "link": { - "~/.config/": { - "path": "config/*/*", - "exclude": ["config/baz/buzz"], - }, - }, - }, - ]) + ] + ) run_dotbot() assert not os.path.exists(os.path.join(home, ".config", "baz", "buzz")) @@ -451,24 +474,26 @@ def test_link_glob_exclude_4(home, dotfiles, run_dotbot): dotfiles.write("config/baz/buzz/e", "egg") dotfiles.write("config/baz/bizz/g", "grape") dotfiles.write("config/fiz/f", "fig") - dotfiles.write_config([ - { - "defaults": { + dotfiles.write_config( + [ + { + "defaults": { + "link": { + "glob": True, + "create": True, + }, + }, + }, + { "link": { - "glob": True, - "create": True, + "~/.config/": { + "path": "config/*/*", + "exclude": ["config/baz/*", "config/fiz/*"], + }, }, }, - }, - { - "link": { - "~/.config/": { - "path": "config/*/*", - "exclude": ["config/baz/*", "config/fiz/*"], - }, - }, - }, - ]) + ] + ) run_dotbot() assert not os.path.exists(os.path.join(home, ".config", "baz")) @@ -492,10 +517,12 @@ def test_link_glob_multi_star(home, dotfiles, run_dotbot): dotfiles.write("config/foo/a", "apple") dotfiles.write("config/bar/b", "banana") dotfiles.write("config/bar/c", "cherry") - dotfiles.write_config([ - {"defaults": {"link": {"glob": True, "create": True}}}, - {"link": {"~/.config/": "config/*/*"}}, - ]) + dotfiles.write_config( + [ + {"defaults": {"link": {"glob": True, "create": True}}}, + {"link": {"~/.config/": "config/*/*"}}, + ] + ) run_dotbot() assert not os.path.islink(os.path.join(home, ".config")) @@ -518,7 +545,7 @@ def test_link_glob_multi_star(home, dotfiles, run_dotbot): ("conf/[bc]*", lambda fruit: fruit if fruit[0] in "bc" else None), ("conf/*e", lambda fruit: fruit if fruit[-1] == "e" else None), ("conf/??r*", lambda fruit: fruit if fruit[2] == "r" else None), - ) + ), ) def test_link_glob_patterns(pattern, expect_file, home, dotfiles, run_dotbot): """Verify link glob pattern matching.""" @@ -526,10 +553,12 @@ def test_link_glob_patterns(pattern, expect_file, home, dotfiles, run_dotbot): fruits = ["apple", "apricot", "banana", "cherry", "currant", "cantalope"] [dotfiles.write("conf/" + fruit, fruit) for fruit in fruits] [dotfiles.write("conf/." + fruit, "dot-" + fruit) for fruit in fruits] - dotfiles.write_config([ - {"defaults": {"link": {"glob": True, "create": True}}}, - {"link": {"~/globtest": pattern}}, - ]) + dotfiles.write_config( + [ + {"defaults": {"link": {"glob": True, "create": True}}}, + {"link": {"~/globtest": pattern}}, + ] + ) run_dotbot() for fruit in fruits: @@ -554,10 +583,12 @@ def test_link_glob_recursive(home, dotfiles, run_dotbot): dotfiles.write("config/foo/bar/a", "apple") dotfiles.write("config/foo/bar/b", "banana") dotfiles.write("config/foo/bar/c", "cherry") - dotfiles.write_config([ - {"defaults": {"link": {"glob": True, "create": True}}}, - {"link": {"~/.config/": {"path": "config/**", "exclude": ["config/**/b"]}}}, - ]) + dotfiles.write_config( + [ + {"defaults": {"link": {"glob": True, "create": True}}}, + {"link": {"~/.config/": {"path": "config/**", "exclude": ["config/**/b"]}}}, + ] + ) run_dotbot() assert not os.path.islink(os.path.join(home, ".config")) @@ -581,14 +612,18 @@ def test_link_if(home, dotfiles, run_dotbot): os.mkdir(os.path.join(home, "d")) dotfiles.write("f", "apple") - dotfiles.write_config([{ - "link": { - "~/.f": {"path": "f", "if": "true"}, - "~/.g": {"path": "f", "if": "false"}, - "~/.h": {"path": "f", "if": "[ -d ~/d ]"}, - "~/.i": {"path": "f", "if": "badcommand"}, - }, - }]) + dotfiles.write_config( + [ + { + "link": { + "~/.f": {"path": "f", "if": "true"}, + "~/.g": {"path": "f", "if": "false"}, + "~/.h": {"path": "f", "if": "[ -d ~/d ]"}, + "~/.i": {"path": "f", "if": "badcommand"}, + }, + } + ] + ) run_dotbot() assert not os.path.exists(os.path.join(home, ".g")) @@ -608,21 +643,23 @@ def test_link_if_defaults(home, dotfiles, run_dotbot): os.mkdir(os.path.join(home, "d")) dotfiles.write("f", "apple") - dotfiles.write_config([ - { - "defaults": { - "link": { - "if": "false", + dotfiles.write_config( + [ + { + "defaults": { + "link": { + "if": "false", + }, }, }, - }, - { - "link": { - "~/.j": {"path": "f", "if": "true"}, - "~/.k": {"path": "f"}, # default is false + { + "link": { + "~/.j": {"path": "f", "if": "true"}, + "~/.k": {"path": "f"}, # default is false + }, }, - }, - ]) + ] + ) run_dotbot() assert not os.path.exists(os.path.join(home, ".k")) @@ -639,14 +676,18 @@ def test_link_if_windows(home, dotfiles, run_dotbot): os.mkdir(os.path.join(home, "d")) dotfiles.write("f", "apple") - dotfiles.write_config([{ - "link": { - "~/.f": {"path": "f", "if": 'cmd /c "exit 0"'}, - "~/.g": {"path": "f", "if": 'cmd /c "exit 1"'}, - "~/.h": {"path": "f", "if": 'cmd /c "dir %USERPROFILE%\\d'}, - "~/.i": {"path": "f", "if": 'cmd /c "badcommand"'}, - }, - }]) + dotfiles.write_config( + [ + { + "link": { + "~/.f": {"path": "f", "if": 'cmd /c "exit 0"'}, + "~/.g": {"path": "f", "if": 'cmd /c "exit 1"'}, + "~/.h": {"path": "f", "if": 'cmd /c "dir %USERPROFILE%\\d'}, + "~/.i": {"path": "f", "if": 'cmd /c "badcommand"'}, + }, + } + ] + ) run_dotbot() assert not os.path.exists(os.path.join(home, ".g")) @@ -666,21 +707,23 @@ def test_link_if_defaults_windows(home, dotfiles, run_dotbot): os.mkdir(os.path.join(home, "d")) dotfiles.write("f", "apple") - dotfiles.write_config([ - { - "defaults": { - "link": { - "if": 'cmd /c "exit 1"', + dotfiles.write_config( + [ + { + "defaults": { + "link": { + "if": 'cmd /c "exit 1"', + }, }, }, - }, - { - "link": { - "~/.j": {"path": "f", "if": 'cmd /c "exit 0"'}, - "~/.k": {"path": "f"}, # default is false + { + "link": { + "~/.j": {"path": "f", "if": 'cmd /c "exit 0"'}, + "~/.k": {"path": "f"}, # default is false + }, }, - }, - ]) + ] + ) run_dotbot() assert not os.path.exists(os.path.join(home, ".k")) @@ -692,14 +735,18 @@ def test_link_if_defaults_windows(home, dotfiles, run_dotbot): def test_link_ignore_missing(ignore_missing, home, dotfiles, run_dotbot): """Verify link 'ignore_missing' is respected when the target is missing.""" - dotfiles.write_config([{ - "link": { - "~/missing_link": { - "path": "missing", - "ignore-missing": ignore_missing, - }, - }, - }]) + dotfiles.write_config( + [ + { + "link": { + "~/missing_link": { + "path": "missing", + "ignore-missing": ignore_missing, + }, + }, + } + ] + ) if ignore_missing: run_dotbot() @@ -728,10 +775,7 @@ def test_link_no_canonicalize(key, home, dotfiles, run_dotbot): """Verify link canonicalization can be disabled.""" dotfiles.write("f", "apple") - dotfiles.write_config([ - {"defaults": {"link": {key: False}}}, - {"link": {"~/.f": {"path": "f"}}} - ]) + dotfiles.write_config([{"defaults": {"link": {key: False}}}, {"link": {"~/.f": {"path": "f"}}}]) try: os.symlink( dotfiles.directory, @@ -759,15 +803,19 @@ def test_link_prefix(home, dotfiles, run_dotbot): dotfiles.write("conf/a", "apple") dotfiles.write("conf/b", "banana") dotfiles.write("conf/c", "cherry") - dotfiles.write_config([{ - "link": { - "~/": { - "glob": True, - "path": "conf/*", - "prefix": ".", - }, - }, - }]) + dotfiles.write_config( + [ + { + "link": { + "~/": { + "glob": True, + "path": "conf/*", + "prefix": ".", + }, + }, + } + ] + ) run_dotbot() with open(os.path.join(home, ".a")) as file: assert file.read() == "apple" @@ -782,26 +830,30 @@ def test_link_relative(home, dotfiles, run_dotbot): dotfiles.write("f", "apple") dotfiles.write("d/e", "grape") - dotfiles.write_config([{ - "link": { - "~/.f": { - "path": "f", - }, - "~/.frel": { - "path": "f", - "relative": True, - }, - "~/nested/.frel": { - "path": "f", - "relative": True, - "create": True, - }, - "~/.d": { - "path": "d", - "relative": True, - }, - }, - }]) + dotfiles.write_config( + [ + { + "link": { + "~/.f": { + "path": "f", + }, + "~/.frel": { + "path": "f", + "relative": True, + }, + "~/nested/.frel": { + "path": "f", + "relative": True, + "create": True, + }, + "~/.d": { + "path": "d", + "relative": True, + }, + }, + } + ] + ) run_dotbot() f = os.readlink(os.path.join(home, ".f")) @@ -866,15 +918,17 @@ def test_link_relink_relative_leaves_file(home, dotfiles, run_dotbot): dotfiles.write("f", "apple") with open(os.path.join(home, ".f"), "w") as file: file.write("grape") - config = [{ - "link": { - "~/.folder/f": { - "path": "f", - "create": True, - "relative": True, + config = [ + { + "link": { + "~/.folder/f": { + "path": "f", + "create": True, + "relative": True, + }, }, - }, - }] + } + ] dotfiles.write_config(config) run_dotbot() @@ -895,9 +949,13 @@ def test_link_defaults_1(home, dotfiles, run_dotbot): file.write("grape") os.symlink(os.path.join(home, "f"), os.path.join(home, ".f")) dotfiles.write("f", "apple") - dotfiles.write_config([{ - "link": {"~/.f": "f"}, - }]) + dotfiles.write_config( + [ + { + "link": {"~/.f": "f"}, + } + ] + ) with pytest.raises(SystemExit): run_dotbot() @@ -912,10 +970,12 @@ def test_link_defaults_2(home, dotfiles, run_dotbot): file.write("grape") os.symlink(os.path.join(home, "f"), os.path.join(home, ".f")) dotfiles.write("f", "apple") - dotfiles.write_config([ - {"defaults": {"link": {"relink": True}}}, - {"link": {"~/.f": "f"}}, - ]) + dotfiles.write_config( + [ + {"defaults": {"link": {"relink": True}}}, + {"link": {"~/.f": "f"}}, + ] + ) run_dotbot() with open(os.path.join(home, ".f"), "r") as file: diff --git a/tests/test_shell.py b/tests/test_shell.py index 8296ab3..9ae7a64 100644 --- a/tests/test_shell.py +++ b/tests/test_shell.py @@ -1,12 +1,18 @@ def test_shell_allow_stdout(capfd, dotfiles, run_dotbot): """Verify shell command STDOUT works.""" - dotfiles.write_config([{ - "shell": [{ - "command": "echo apple", - "stdout": True, - }], - }]) + dotfiles.write_config( + [ + { + "shell": [ + { + "command": "echo apple", + "stdout": True, + } + ], + } + ] + ) run_dotbot() output = capfd.readouterr() @@ -36,10 +42,12 @@ def test_shell_cli_verbosity_overrides_2(capfd, dotfiles, run_dotbot): def test_shell_cli_verbosity_overrides_3(capfd, dotfiles, run_dotbot): """Verify that '-vv' overrides an explicit defaults:shell:stdout=False.""" - dotfiles.write_config([ - {"defaults": {"shell": {"stdout": False}}}, - {"shell": [{"command": "echo apple"}]}, - ]) + dotfiles.write_config( + [ + {"defaults": {"shell": {"stdout": False}}}, + {"shell": [{"command": "echo apple"}]}, + ] + ) run_dotbot("-vv") stdout = capfd.readouterr().out.splitlines() @@ -59,12 +67,18 @@ def test_shell_cli_verbosity_stderr(capfd, dotfiles, run_dotbot): def test_shell_cli_verbosity_stderr_with_explicit_stdout_off(capfd, dotfiles, run_dotbot): """Verify that commands can output to STDERR with STDOUT explicitly off.""" - dotfiles.write_config([{ - "shell": [{ - "command": "echo apple >&2", - "stdout": False, - }], - }]) + dotfiles.write_config( + [ + { + "shell": [ + { + "command": "echo apple >&2", + "stdout": False, + } + ], + } + ] + ) run_dotbot("-vv") stderr = capfd.readouterr().err.splitlines() @@ -74,20 +88,22 @@ def test_shell_cli_verbosity_stderr_with_explicit_stdout_off(capfd, dotfiles, ru def test_shell_cli_verbosity_stderr_with_defaults_stdout_off(capfd, dotfiles, run_dotbot): """Verify that commands can output to STDERR with defaults:shell:stdout=False.""" - dotfiles.write_config([ - { - "defaults": { - "shell": { - "stdout": False, + dotfiles.write_config( + [ + { + "defaults": { + "shell": { + "stdout": False, + }, }, }, - }, - { - "shell": [ - {"command": "echo apple >&2"}, - ], - }, - ]) + { + "shell": [ + {"command": "echo apple >&2"}, + ], + }, + ] + ) run_dotbot("-vv") stderr = capfd.readouterr().err.splitlines() @@ -117,10 +133,12 @@ def test_shell_single_v_verbosity_stderr(capfd, dotfiles, run_dotbot): def test_shell_compact_stdout_1(capfd, dotfiles, run_dotbot): """Verify that shell command stdout works in compact form.""" - dotfiles.write_config([ - {"defaults": {"shell": {"stdout": True}}}, - {"shell": ["echo apple"]}, - ]) + dotfiles.write_config( + [ + {"defaults": {"shell": {"stdout": True}}}, + {"shell": ["echo apple"]}, + ] + ) run_dotbot() stdout = capfd.readouterr().out.splitlines() @@ -130,10 +148,12 @@ def test_shell_compact_stdout_1(capfd, dotfiles, run_dotbot): def test_shell_compact_stdout_2(capfd, dotfiles, run_dotbot): """Verify that shell command stdout works in compact form.""" - dotfiles.write_config([ - {"defaults": {"shell": {"stdout": True}}}, - {"shell": [["echo apple", "echoing message"]]}, - ]) + dotfiles.write_config( + [ + {"defaults": {"shell": {"stdout": True}}}, + {"shell": [["echo apple", "echoing message"]]}, + ] + ) run_dotbot() stdout = capfd.readouterr().out.splitlines() @@ -144,9 +164,13 @@ def test_shell_compact_stdout_2(capfd, dotfiles, run_dotbot): def test_shell_stdout_disabled_by_default(capfd, dotfiles, run_dotbot): """Verify that the shell command disables stdout by default.""" - dotfiles.write_config([{ - "shell": ["echo banana"], - }]) + dotfiles.write_config( + [ + { + "shell": ["echo banana"], + } + ] + ) run_dotbot() stdout = capfd.readouterr().out.splitlines() @@ -156,10 +180,12 @@ def test_shell_stdout_disabled_by_default(capfd, dotfiles, run_dotbot): def test_shell_can_override_defaults(capfd, dotfiles, run_dotbot): """Verify that the shell command can override defaults.""" - dotfiles.write_config([ - {"defaults": {"shell": {"stdout": True}}}, - {"shell": [{"command": "echo apple", "stdout": False}]}, - ]) + dotfiles.write_config( + [ + {"defaults": {"shell": {"stdout": True}}}, + {"shell": [{"command": "echo apple", "stdout": False}]}, + ] + ) run_dotbot() stdout = capfd.readouterr().out.splitlines() @@ -169,12 +195,18 @@ def test_shell_can_override_defaults(capfd, dotfiles, run_dotbot): def test_shell_quiet_default(capfd, dotfiles, run_dotbot): """Verify that quiet is off by default.""" - dotfiles.write_config([{ - "shell": [{ - "command": "echo banana", - "description": "echoing a thing...", - }], - }]) + dotfiles.write_config( + [ + { + "shell": [ + { + "command": "echo banana", + "description": "echoing a thing...", + } + ], + } + ] + ) run_dotbot() stdout = capfd.readouterr().out.splitlines() @@ -186,13 +218,19 @@ def test_shell_quiet_default(capfd, dotfiles, run_dotbot): def test_shell_quiet_enabled_with_description(capfd, dotfiles, run_dotbot): """Verify that only the description is shown when quiet is enabled.""" - dotfiles.write_config([{ - "shell": [{ - "command": "echo banana", - "description": "echoing a thing...", - "quiet": True, - }], - }]) + dotfiles.write_config( + [ + { + "shell": [ + { + "command": "echo banana", + "description": "echoing a thing...", + "quiet": True, + } + ], + } + ] + ) run_dotbot() stdout = capfd.readouterr().out.splitlines() @@ -204,12 +242,18 @@ def test_shell_quiet_enabled_with_description(capfd, dotfiles, run_dotbot): def test_shell_quiet_enabled_without_description(capfd, dotfiles, run_dotbot): """Verify the command is shown when quiet is enabled with no description.""" - dotfiles.write_config([{ - "shell": [{ - "command": "echo banana", - "quiet": True, - }], - }]) + dotfiles.write_config( + [ + { + "shell": [ + { + "command": "echo banana", + "quiet": True, + } + ], + } + ] + ) run_dotbot() stdout = capfd.readouterr().out.splitlines() diff --git a/tox.ini b/tox.ini index acabf72..3ccd81a 100644 --- a/tox.ini +++ b/tox.ini @@ -2,6 +2,7 @@ envlist = py{27, 35, 36, 37, 38, 39, 310} pypy{2, 3} + py310-black skip_missing_interpreters = true @@ -14,3 +15,13 @@ deps = commands = pytest tests/ + + +[testenv:py310-black] +skip_install = true +skip_build = true +deps = + black + +commands = + black --check dotbot/ tests/