From 70c71e8f935b3c5152036a993295df13c5fe69ca Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Mon, 28 Aug 2023 22:16:44 -0500 Subject: Add style tool to fix fish file formatting (#39155) --- lib/spack/spack/bootstrap/environment.py | 7 +++++++ lib/spack/spack/cmd/style.py | 35 +++++++++++++++++++++++--------- lib/spack/spack/test/cmd/style.py | 8 +++++--- 3 files changed, 37 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/bootstrap/environment.py b/lib/spack/spack/bootstrap/environment.py index a2086160f6..96ec527a8a 100644 --- a/lib/spack/spack/bootstrap/environment.py +++ b/lib/spack/spack/bootstrap/environment.py @@ -37,6 +37,7 @@ class BootstrapEnvironment(spack.environment.Environment): mypy_root_spec(), black_root_spec(), flake8_root_spec(), + fish_root_spec(), pytest_root_spec(), ] @@ -179,6 +180,12 @@ def flake8_root_spec() -> str: return _root_spec("py-flake8@3.8.2:") +def fish_root_spec() -> str: + """Return the root spec used to bootstrap fish""" + # fish 3.2.0 introduces the `--check` flag to `fish_indent` + return _root_spec("fish@3.2:") + + def pytest_root_spec() -> str: """Return the root spec used to bootstrap flake8""" return _root_spec("py-pytest@6.2.4:") diff --git a/lib/spack/spack/cmd/style.py b/lib/spack/spack/cmd/style.py index adc880f1bd..9cd1458af7 100644 --- a/lib/spack/spack/cmd/style.py +++ b/lib/spack/spack/cmd/style.py @@ -36,7 +36,7 @@ exclude_directories = [os.path.relpath(spack.paths.external_path, spack.paths.pr #: double-check the results of other tools (if, e.g., --fix was provided) #: The list maps an executable name to a method to ensure the tool is #: bootstrapped or present in the environment. -tool_names = ["isort", "black", "flake8", "mypy"] +tool_names = ["isort", "black", "flake8", "mypy", "fish_indent"] #: tools we run in spack style tools = {} @@ -61,12 +61,13 @@ def is_package(f): #: decorator for adding tools to the list class tool: - def __init__(self, name, required=False): + def __init__(self, name, required=False, suffix=".py"): self.name = name self.required = required + self.suffix = suffix def __call__(self, fun): - tools[self.name] = (fun, self.required) + tools[self.name] = (fun, self.required, self.suffix) return fun @@ -121,12 +122,8 @@ def changed_files(base="develop", untracked=True, all_files=False, root=None): files = git(*arg_list, output=str).split("\n") for f in files: - # Ignore non-Python files - if not (f.endswith(".py") or f == "bin/spack"): - continue - # Ignore files in the exclude locations - if any(os.path.realpath(f).startswith(e) for e in excludes): + if not f or any(os.path.realpath(f).startswith(e) for e in excludes): continue changed.add(f) @@ -352,6 +349,22 @@ def run_black(black_cmd, file_list, args): return returncode +@tool("fish_indent", suffix=".fish") +def run_fish_indent(fish_indent_cmd, file_list, args): + if args.fix: + fish_indent_args = ["--write"] + else: + fish_indent_args = ["--check"] + + output = fish_indent_cmd(*fish_indent_args, *file_list, fail_on_error=False, output=str) + returncode = fish_indent_cmd.returncode + + rewrite_and_print_output(output, args) + print_tool_result("fish_indent", returncode) + + return returncode + + def validate_toolset(arg_value): """Validate --tool and --skip arguments (sets of optionally comma-separated tools).""" tools = set(",".join(arg_value).split(",")) # allow args like 'isort,flake8' @@ -417,9 +430,11 @@ def style(parser, args): print_style_header(file_list, args, tools_to_run) for tool_name in tools_to_run: - run_function, required = tools[tool_name] + run_function, required, suffix = tools[tool_name] print_tool_header(tool_name) - return_code |= run_function(which(tool_name), file_list, args) + file_subset = [f for f in file_list if f.endswith(suffix)] + if file_subset: + return_code |= run_function(which(tool_name), file_subset, args) if return_code == 0: tty.msg(color.colorize("@*{spack style checks were clean}")) diff --git a/lib/spack/spack/test/cmd/style.py b/lib/spack/spack/test/cmd/style.py index 5591116968..5b86fc8aac 100644 --- a/lib/spack/spack/test/cmd/style.py +++ b/lib/spack/spack/test/cmd/style.py @@ -56,7 +56,7 @@ def flake8_package_with_errors(scope="function"): """A flake8 package with errors.""" repo = spack.repo.Repo(spack.paths.mock_packages_path) filename = repo.filename_for_package_name("flake8") - tmp = filename + ".tmp" + tmp = filename.replace("package.py", "package2.py") shutil.copy(filename, tmp) package = FileFilter(tmp) @@ -64,11 +64,12 @@ def flake8_package_with_errors(scope="function"): # this is a black error (quote style and spacing before/after operator) package.filter('state = "unmodified"', "state = 'modified'", string=True) - # this is an isort error (orderign) and a flake8 error (unused import) + # this is an isort error (ordering) and a flake8 error (unused import) package.filter( "from spack.package import *", "from spack.package import *\nimport os", string=True ) yield tmp + os.remove(tmp) def test_changed_files_from_git_rev_base(git, tmpdir, capfd): @@ -213,6 +214,7 @@ def test_fix_style(external_style_root): @pytest.mark.skipif(not which("isort"), reason="isort is not installed.") @pytest.mark.skipif(not which("mypy"), reason="mypy is not installed.") @pytest.mark.skipif(not which("black"), reason="black is not installed.") +@pytest.mark.skipif(not which("fish_indent"), reason="fish is not installed.") def test_external_root(external_style_root, capfd): """Ensure we can run in a separate root directory w/o configuration files.""" tmpdir, py_file = external_style_root @@ -285,5 +287,5 @@ def test_style_with_black(flake8_package_with_errors): def test_skip_tools(): - output = style("--skip", "isort,mypy,black,flake8") + output = style("--skip", "isort,mypy,black,flake8,fish_indent") assert "Nothing to run" in output -- cgit v1.2.3-60-g2f50