From 5a388a7c88897bdae3528b41a89a07523b3c029e Mon Sep 17 00:00:00 2001 From: Tim Paine <3105306+timkpaine@users.noreply.github.com> Date: Wed, 25 Oct 2023 12:30:00 -0400 Subject: [PATCH] Add more helpful error message when metadata is malformed, xref #558 #626 --- src/build/_util.py | 6 ++++++ tests/test_projectbuilder.py | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/build/_util.py b/src/build/_util.py index 691e15a7..93c4ef01 100644 --- a/src/build/_util.py +++ b/src/build/_util.py @@ -53,6 +53,12 @@ def check_dependency( # dependency is not installed in the environment. yield (*ancestral_req_strings, normalised_req_string) else: + if dist.version is None: + # Malformed dist-info or some other form of metadata corruption + # req.specifier.contains will raise TypeError, so let's do the same + # with a more helpful error message + msg = f'Package {req.name} has malformed metadata and no version information could be found' + raise TypeError(msg) if req.specifier and not req.specifier.contains(dist.version, prereleases=True): # the installed version is incompatible. yield (*ancestral_req_strings, normalised_req_string) diff --git a/tests/test_projectbuilder.py b/tests/test_projectbuilder.py index 602ca06e..c8f4d7b5 100644 --- a/tests/test_projectbuilder.py +++ b/tests/test_projectbuilder.py @@ -43,6 +43,8 @@ def from_name(cls, name): return CircularMockDistribution() elif name == 'nested_circular_dep': return NestedCircularMockDistribution() + elif name == 'malformed_dep': + return MalformedMockDistribution() raise _importlib.metadata.PackageNotFoundError @@ -127,6 +129,11 @@ def read_text(self, filename): """ ).strip() +class MalformedMockDistribution(MockDistribution): + def read_text(self, filename): + if filename == 'METADATA': + return "" + @pytest.mark.parametrize( ('requirement_string', 'expected'), @@ -165,6 +172,13 @@ def test_check_dependency(monkeypatch, requirement_string, expected): monkeypatch.setattr(_importlib.metadata, 'Distribution', MockDistribution) assert next(build.check_dependency(requirement_string), None) == expected +def test_check_dependency_bad_metadata(monkeypatch): + monkeypatch.setattr(_importlib.metadata, 'Distribution', MockDistribution) + with pytest.raises(TypeError) as excinfo: + with pytest.warns(DeprecationWarning): + next(build.check_dependency("malformed_dep==1.0.0"), None) + assert "Package malformed_dep has malformed metadata and no version information could be found" in str(excinfo) + def test_bad_project(package_test_no_project): # Passing a nonexistent project directory