diff --git a/changelog/861.feature.rst b/changelog/861.feature.rst new file mode 100644 index 00000000..b04d252e --- /dev/null +++ b/changelog/861.feature.rst @@ -0,0 +1 @@ +Show more helpful error message for invalid metadata. diff --git a/tests/test_package.py b/tests/test_package.py index 62108b5d..3d2e2799 100644 --- a/tests/test_package.py +++ b/tests/test_package.py @@ -337,23 +337,46 @@ def test_fips_metadata_excludes_md5_and_blake2(monkeypatch): assert "blake2_256_digest" not in mddict -def test_pkginfo_returns_no_metadata(monkeypatch): +@pytest.mark.parametrize( + "read_data, missing_fields", + [ + pytest.param( + b"Metadata-Version: 2.3\nName: test-package\nVersion: 1.0.0\n", + "Name, Version", + id="unsupported Metadata-Version", + ), + pytest.param( + b"Metadata-Version: 2.2\nName: UNKNOWN\nVersion: UNKNOWN\n", + "Name, Version", + id="missing Name and Version", + ), + pytest.param( + b"Metadata-Version: 2.2\nName: UNKNOWN\nVersion: 1.0.0\n", + "Name", + id="missing Name", + ), + pytest.param( + b"Metadata-Version: 2.2\nName: test-package\nVersion: UNKNOWN\n", + "Version", + id="missing Version", + ), + ], +) +def test_pkginfo_returns_no_metadata(read_data, missing_fields, monkeypatch): """Raise an exception when pkginfo can't interpret the metadata. This could be caused by a version number or format it doesn't support yet. """ - - def EmptyDist(filename): - return pretend.stub(name=None, version=None) - - monkeypatch.setattr(package_file, "DIST_TYPES", {"bdist_wheel": EmptyDist}) + monkeypatch.setattr(package_file.wheel.Wheel, "read", lambda _: read_data) filename = "tests/fixtures/twine-1.5.0-py2.py3-none-any.whl" with pytest.raises(exceptions.InvalidDistribution) as err: package_file.PackageFile.from_filename(filename, comment=None) - assert "Invalid distribution metadata" in err.value.args[0] - assert "1.0, 1.1, 1.2, 2.0, 2.1, and 2.2" in err.value.args[0] + assert ( + f"Metadata is missing required fields: {missing_fields}." in err.value.args[0] + ) + assert "1.0, 1.1, 1.2, 2.0, 2.1, 2.2" in err.value.args[0] def test_malformed_from_file(monkeypatch): diff --git a/twine/package.py b/twine/package.py index da468a89..0619ba6e 100644 --- a/twine/package.py +++ b/twine/package.py @@ -101,15 +101,21 @@ def from_filename(cls, filename: str, comment: Optional[str]) -> "PackageFile": "Unknown distribution format: '%s'" % os.path.basename(filename) ) - # If pkginfo encounters a metadata version it doesn't support, it may - # give us back empty metadata. At the very least, we should have a name - # and version - if not (meta.name and meta.version): + # If pkginfo encounters a metadata version it doesn't support, it may give us + # back empty metadata. At the very least, we should have a name and version, + # which could also be empty if, for example, a MANIFEST.in doesn't include + # setup.cfg. + missing_fields = [ + f.capitalize() for f in ["name", "version"] if not getattr(meta, f) + ] + if missing_fields: supported_metadata = list(pkginfo.distribution.HEADER_ATTRS) raise exceptions.InvalidDistribution( - "Invalid distribution metadata. " - "This version of twine supports Metadata-Version " - f"{', '.join(supported_metadata[:-1])}, and {supported_metadata[-1]}" + "Metadata is missing required fields: " + f"{', '.join(missing_fields)}.\n" + "Make sure the distribution includes the files where those fields " + "are specified, and is using a supported Metadata-Version: " + f"{', '.join(supported_metadata)}." ) py_version: Optional[str]