Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Formatting summary & verbose output #608

Merged
merged 1 commit into from
Dec 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions docs/releasenotes/unreleased/other.1.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
More verbose output (#572)
---------------------------

Robotidy output is now more verbose. If the file is formatted (or would be formatted if not for
``--check`` or ``--no-overwrite options) the file path and run summary is displayed:

```
> robotidy --check .
Would reformat D:\test_repository\resources\db_keywords.resource file
Would reformat D:\test_repository\tests\ui\login.robot file

2 files would be reformatted, 112 files would be left unchanged.
```

```
> robotidy .
Formatting D:\test_repository\resources\db_keywords.resource file
Formatting D:\test_repository\tests\ui\login.robot file

2 files reformatted, 112 files left unchanged.
```

```
> robotidy --verbose .
Found D:\test_repository\resources\ui_keywords.resource file
Found (...)
Formatting D:\test_repository\resources\db_keywords.resource file
Found (...)
Formatting D:\test_repository\tests\ui\login.robot file
Found (...)

2 files reformatted, 112 files left unchanged.
```
29 changes: 28 additions & 1 deletion robotidy/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ def get_model(self, source):

def transform_files(self):
changed_files = 0
all_files = 0
stdin = False
for source, config in self.main_config.get_sources_with_configs():
self.config = config
all_files += 1
disabler_finder = RegisterDisablers(self.config.formatting.start_line, self.config.formatting.end_line)
try:
stdin = False
Expand All @@ -40,14 +43,15 @@ def transform_files(self):
click.echo("Loading file from stdin")
source = self.load_from_stdin()
elif self.config.verbose:
click.echo(f"Transforming {source} file")
click.echo(f"Found {source} file")
model = self.get_model(source)
model_path = model.source
disabler_finder.visit(model)
if disabler_finder.file_disabled:
continue
diff, old_model, new_model, model = self.transform_until_stable(model, disabler_finder)
if diff:
self.log_formatted_source(source, stdin)
changed_files += 1
self.output_diff(model_path, old_model, new_model)
if stdin:
Expand All @@ -59,10 +63,33 @@ def transform_files(self):
f"Failed to decode {source}. Default supported encoding by Robot Framework is UTF-8. Skipping file"
)
pass
return self.formatting_result(all_files, changed_files, stdin)

def formatting_result(self, all_files: int, changed_files: int, stdin: bool):
"""
Print formatting summary and return status code.
"""
if not stdin:
all_files = all_files - changed_files
all_files_plurar = "" if all_files == 1 else "s"
changed_files_plurar = "" if changed_files == 1 else "s"
future_tense = "" if self.config.overwrite else " would be"
click.echo(
f"\n{changed_files} file{changed_files_plurar}{future_tense} reformatted, "
f"{all_files} file{all_files_plurar}{future_tense} left unchanged."
)
if not self.config.check or not changed_files:
return 0
return 1

def log_formatted_source(self, source: str, stdin: bool):
if stdin:
return
if not self.config.overwrite:
click.echo(f"Would reformat {source}")
else:
click.echo(f"Reformatted {source}")

def transform_until_stable(self, model, disabler_finder):
diff, old_model, new_model = self.transform(model, disabler_finder.disablers)
reruns = self.config.reruns
Expand Down
68 changes: 44 additions & 24 deletions tests/utest/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,6 @@ def switch_cwd(new_cwd):
os.chdir(prev_cwd)


@contextmanager
def switch_cwd(new_cwd):
prev_cwd = Path.cwd()
os.chdir(new_cwd)
try:
yield
finally:
os.chdir(prev_cwd)


class TestCli:
@pytest.mark.parametrize(
"name, similar",
Expand Down Expand Up @@ -320,28 +310,46 @@ def test_help(self, flag):
result = run_tidy([flag])
assert f"Robotidy is a tool for formatting" in result.output

@pytest.mark.parametrize("source, return_status", [("golden.robot", 0), ("not_golden.robot", 1)])
def test_check(self, source, return_status):
@pytest.mark.parametrize(
"source, return_status, expected_output",
[
("golden.robot", 0, "\n0 files would be reformatted, 1 file would be left unchanged.\n"),
("not_golden.robot", 1, "\n1 file would be reformatted, 0 files would be left unchanged.\n"),
],
)
def test_check(self, source, return_status, expected_output):
source = TEST_DATA_DIR / "check" / source
if return_status:
expected_output = f"Would reformat {source}\n{expected_output}"
with patch("robotidy.utils.misc.ModelWriter") as mock_writer:
run_tidy(
result = run_tidy(
["--check", "--transform", "NormalizeSectionHeaderName", str(source)],
exit_code=return_status,
)
mock_writer.assert_not_called()
assert result.output == expected_output

@pytest.mark.parametrize("source, return_status", [("golden.robot", 0), ("not_golden.robot", 1)])
def test_check_overwrite(self, source, return_status):
@pytest.mark.parametrize(
"source, return_status, expected_output",
[
("golden.robot", 0, "\n0 files reformatted, 1 file left unchanged.\n"),
("not_golden.robot", 1, "\n1 file reformatted, 0 files left unchanged.\n"),
],
)
def test_check_overwrite(self, source, return_status, expected_output):
source = TEST_DATA_DIR / "check" / source
if return_status:
expected_output = f"Reformatted {source}\n{expected_output}"
with patch("robotidy.utils.misc.ModelWriter") as mock_writer:
run_tidy(
result = run_tidy(
["--check", "--overwrite", "--transform", "NormalizeSectionHeaderName", str(source)],
exit_code=return_status,
)
if return_status:
mock_writer.assert_called()
else:
mock_writer.assert_not_called()
assert result.output == expected_output

@pytest.mark.parametrize("color_flag", ["--color", "--no-color", None])
@pytest.mark.parametrize("color_env", [True, False])
Expand Down Expand Up @@ -409,26 +417,38 @@ def test_exclude_gitignore(self, exclude, extend_exclude, skip_gitignore, allowe
assert paths == allowed_paths

@pytest.mark.parametrize(
"source, should_parse",
"source, should_parse, summary",
[
(None, ["test.robot", "resources/test.robot"]), # calls: robotidy
("test3.robot", ["test3.robot"]), # calls: robotidy test3.robot
("test.robot", ["test.robot"]),
(".", ["test.robot", "test3.robot", "resources/test.robot"]),
(
None,
["test.robot", "resources/test.robot"],
"0 files reformatted, 2 files left unchanged.",
), # calls: robotidy
(
"test3.robot",
["test3.robot"],
"0 files reformatted, 1 file left unchanged.",
), # calls: robotidy test3.robot
("test.robot", ["test.robot"], "0 files reformatted, 1 file left unchanged."),
(
".",
["test.robot", "test3.robot", "resources/test.robot"],
"0 files reformatted, 3 files left unchanged.",
),
],
)
def test_src_and_space_in_param_in_configuration(self, source, should_parse):
def test_src_and_space_in_param_in_configuration(self, source, should_parse, summary):
source_dir = TEST_DATA_DIR / "pyproject_with_src"
os.chdir(source_dir)
if source is not None:
source = source_dir / source
result = run_tidy([str(source)])
else:
result = run_tidy()
expected = [f"Loaded configuration from {source_dir / 'pyproject.toml'}"]
expected = [f"Loaded configuration from {source_dir / 'pyproject.toml'}", summary]
for file in should_parse:
path = source_dir / file
expected.append(f"Transforming {path} file")
expected.append(f"Found {path} file")
actual = sorted(line for line in result.output.split("\n") if line.strip())
assert actual == sorted(expected)

Expand Down
Loading