From 5b326f5331cc78f65293d1bc393053ab7027d4dd Mon Sep 17 00:00:00 2001 From: Johan Herland Date: Fri, 13 Sep 2024 11:54:15 +0200 Subject: [PATCH] extract_declared_dependencies: Handle exceptions due to invalid toml When parsing a pyproject.toml or pixi.toml with invalid TOML data, the tomllib parser will raise an exception that is not properly caught or handled by FawltyDeps. Fix this by logging an error message and returning from the parse function. This allows FawltyDeps to continue parsing other files and reporting undeclared/unused dependencies, whereas before it would abort with a traceback. --- fawltydeps/extract_declared_dependencies.py | 12 ++++++++++-- .../test_extract_declared_dependencies_pixi_toml.py | 12 ++++++++++++ ...t_extract_declared_dependencies_pyproject_toml.py | 12 ++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/fawltydeps/extract_declared_dependencies.py b/fawltydeps/extract_declared_dependencies.py index f245b767..b7a7a3f7 100644 --- a/fawltydeps/extract_declared_dependencies.py +++ b/fawltydeps/extract_declared_dependencies.py @@ -415,7 +415,11 @@ def parse_pyproject_toml(path: Path) -> Iterator[DeclaredDependency]: """ source = Location(path) with path.open("rb") as tomlfile: - parsed_contents = tomllib.load(tomlfile) + try: + parsed_contents = tomllib.load(tomlfile) + except tomllib.TOMLDecodeError as e: + logger.error(f"Failed to parse {source}: {e}") + return skip = set() @@ -457,7 +461,11 @@ def parse_pixi_toml(path: Path) -> Iterator[DeclaredDependency]: """ source = Location(path) with path.open("rb") as tomlfile: - parsed_contents = tomllib.load(tomlfile) + try: + parsed_contents = tomllib.load(tomlfile) + except tomllib.TOMLDecodeError as e: + logger.error(f"Failed to parse {source}: {e}") + return skip = set() diff --git a/tests/test_extract_declared_dependencies_pixi_toml.py b/tests/test_extract_declared_dependencies_pixi_toml.py index 5e3cf263..67ca1358 100644 --- a/tests/test_extract_declared_dependencies_pixi_toml.py +++ b/tests/test_extract_declared_dependencies_pixi_toml.py @@ -159,6 +159,18 @@ def test_parse_pixi_toml__wellformed_dependencies__yields_dependencies( assert result == expected +def test_parse_pixi_toml__invalid_toml__yields_no_deps_and_error_message( + write_tmp_files, caplog +): + tmp_path = write_tmp_files({"pixi.toml": "[this is not valid toml\n"}) + path = tmp_path / "pixi.toml" + + caplog.set_level(logging.ERROR) + result = list(parse_pixi_toml(path)) + assert result == [] + assert f"Failed to parse {path}:" in caplog.text + + @dataclass class PixiTestVector: """Test vectors for parsing of malformed pixi.toml.""" diff --git a/tests/test_extract_declared_dependencies_pyproject_toml.py b/tests/test_extract_declared_dependencies_pyproject_toml.py index cfe108b7..2dd083ac 100644 --- a/tests/test_extract_declared_dependencies_pyproject_toml.py +++ b/tests/test_extract_declared_dependencies_pyproject_toml.py @@ -353,6 +353,18 @@ def test_parse_pyproject_toml__wellformed_dependencies__yields_dependencies( assert result == expected +def test_parse_pyproject_toml__invalid_toml__yields_no_deps_and_error_message( + write_tmp_files, caplog +): + tmp_path = write_tmp_files({"pyproject.toml": "[this is not valid toml\n"}) + path = tmp_path / "pyproject.toml" + + caplog.set_level(logging.ERROR) + result = list(parse_pyproject_toml(path)) + assert result == [] + assert f"Failed to parse {path}:" in caplog.text + + @dataclass class PyprojectTestVector: """Test vectors for parsing of malformed pyproject.toml."""