diff --git a/dir_content_diff/base_comparators.py b/dir_content_diff/base_comparators.py index 3606423..0296eb4 100644 --- a/dir_content_diff/base_comparators.py +++ b/dir_content_diff/base_comparators.py @@ -631,8 +631,7 @@ def diff(self, ref, comp, *args, **kwargs): res = pdfdiff_pages(ref, comp, *args, **kwargs) if not res: return False - else: - return res + return res def __call__(self, ref_file, comp_file, *args, **kwargs): """Process arguments before calling the diff method.""" diff --git a/dir_content_diff/cli/__init__.py b/dir_content_diff/cli/__init__.py index 6ee2297..00621a0 100644 --- a/dir_content_diff/cli/__init__.py +++ b/dir_content_diff/cli/__init__.py @@ -17,6 +17,7 @@ import click from yaml import safe_load +from dir_content_diff import _DEFAULT_EXPORT_SUFFIX from dir_content_diff import compare_files from dir_content_diff import compare_trees from dir_content_diff import export_formatted_file @@ -42,22 +43,27 @@ def setup_logger(level: str = "info"): ) -def load_config(ctx, param, value): +def load_config(ctx, param, value): # pylint: disable=unused-argument """Load configuration from the given path.""" + # pylint: disable=raise-missing-from ctx.config = {} if value is not None: try: ctx.config = json.loads(value) - except Exception as json_exc: + except Exception: # pylint: disable=broad-exception-caught + path = Path(value) + if not path.exists(): + msg = f"The file '{path}' does not exist." + raise FileNotFoundError(msg) try: - path = Path(value) - if not path.exists(): - msg = f"The file '{path}' does not exist." - raise FileNotFoundError(msg) - with path.open() as f: + with path.open(encoding="utf-8") as f: ctx.config = safe_load(f.read()) - except Exception as path_exc: - raise path_exc from json_exc + except Exception: # pylint: disable=broad-exception-caught + msg = ( + "Could not load the configuration because it could not be parsed as a JSON " + "string nor as a YAML file." + ) + raise SyntaxError(msg) @click.command( @@ -149,8 +155,22 @@ def input_diff(ref, comp, config, export_formatted_files=False, sort_diffs=False diff = compare_files(ref, comp, comparator, **config) res = {str(ref): diff} if diff is not False else {} if export_formatted_files: - export_formatted_file(ref, **config) - export_formatted_file(comp, **config) + export_formatted_file( + ref, + ref.with_name(ref.stem + _DEFAULT_EXPORT_SUFFIX).with_suffix( + ref.suffix + ), + comparator, + **config, + ) + export_formatted_file( + comp, + comp.with_name(comp.stem + _DEFAULT_EXPORT_SUFFIX).with_suffix( + comp.suffix + ), + comparator, + **config, + ) if res: if sort_diffs: diff --git a/tests/test_cli.py b/tests/test_cli.py index e25dfd2..674989a 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -11,6 +11,7 @@ import json import logging +import re import pytest import yaml @@ -20,6 +21,8 @@ class TestCli: + """Tests of the CLI.""" + @pytest.fixture def config(self, tmp_path): """The config as a dict.""" @@ -179,50 +182,86 @@ def test_diff_tree( ) assert (tmp_path / "diff-pdf" / "file.pdf" / "diff-1.png").exists() + # Test with files and formatted files + caplog.set_level(logging.DEBUG, logger="dir-content-diff") + caplog.clear() + ref_file = ref_tree / "file.json" + res_file = res_tree_diff / "file.json" + result = cli_runner.invoke( + dir_content_diff.cli.main, + [str(ref_file), str(res_file), "--config", config_file_str, "-f"], + catch_exceptions=False, + ) + assert result.stdout == "" + nb_format_msg = 0 + for i in caplog.messages: + if not i.startswith("Format:"): + continue + match = re.match(r"Format: \S+ into \S+", i) + assert match is not None + nb_format_msg += 1 + assert nb_format_msg == 2 + assert (tmp_path / "ref" / "file_FORMATTED.json").exists() + assert (tmp_path / "res" / "file_FORMATTED.json").exists() + class TestFailures: - def test_dir_file(self, cli_runner, caplog, ref_tree, res_tree_diff): + """Test that the proper exceptions are raised.""" + + def test_dir_file(self, cli_runner, ref_tree, res_tree_diff): """Test exception when comparing a directory with a file.""" ref_file = ref_tree / "file.pdf" res_file = res_tree_diff / "file.pdf" with pytest.raises( ValueError, - match=r"The reference and compared inputs must both be either two directories or two files\.", + match=( + r"The reference and compared inputs must both be either two directories or two" + r" files\." + ), ): - result = cli_runner.invoke( + cli_runner.invoke( dir_content_diff.cli.main, [str(ref_tree), str(res_file)], catch_exceptions=False, ) with pytest.raises( ValueError, - match=r"The reference and compared inputs must both be either two directories or two files\.", + match=( + r"The reference and compared inputs must both be either two directories or two" + r" files\." + ), ): - result = cli_runner.invoke( + cli_runner.invoke( dir_content_diff.cli.main, [str(ref_file), str(res_tree_diff)], catch_exceptions=False, ) - def test_not_existing_config(self, cli_runner, caplog): + def test_not_existing_config(self, cli_runner): """Test exception when the config file does not exist.""" with pytest.raises( FileNotFoundError, match=r"The file '/NOT/EXISTING/FILE' does not exist\.", ): - result = cli_runner.invoke( + cli_runner.invoke( dir_content_diff.cli.main, ["/A/FILE", "/ANOTHER/FILE", "--config", "/NOT/EXISTING/FILE"], catch_exceptions=False, ) - def test_bad_yaml_config(self, tmp_path, cli_runner, caplog): + def test_bad_yaml_config(self, tmp_path, cli_runner): """Test exception when the config file does not exist.""" filepath = tmp_path / "config_file.yaml" with filepath.open("w", encoding="utf-8") as f: f.write("entry: &A !!!") - with pytest.raises(yaml.constructor.ConstructorError): - result = cli_runner.invoke( + with pytest.raises( + SyntaxError, + match=( + r"Could not load the configuration because it could not be parsed as a JSON " + r"string nor as a YAML file\." + ), + ): + cli_runner.invoke( dir_content_diff.cli.main, ["/A/FILE", "/ANOTHER/FILE", "--config", str(filepath)], catch_exceptions=False,