diff --git a/src/packaging/utils.py b/src/packaging/utils.py index 23450953..608f9b95 100644 --- a/src/packaging/utils.py +++ b/src/packaging/utils.py @@ -110,7 +110,9 @@ def parse_wheel_filename( name_part = parts[0] # See PEP 427 for the rules on escaping the project name. if "__" in name_part or re.match(r"^[\w\d._]*$", name_part, re.UNICODE) is None: - raise InvalidWheelFilename(f"Invalid project name: {filename!r}") + raise InvalidWheelFilename( + f"Invalid wheel filename (invalid project name {name_part!r}): {filename!r}" + ) name = canonicalize_name(name_part) try: @@ -120,12 +122,18 @@ def parse_wheel_filename( f"Invalid wheel filename (invalid version): {filename!r}" ) from e + if str(version) != parts[1]: + raise InvalidWheelFilename( + f"Invalid wheel filename (non-normalized version): {filename!r}" + ) + if dashes == 5: build_part = parts[2] build_match = _build_tag_regex.match(build_part) if build_match is None: raise InvalidWheelFilename( - f"Invalid build number: {build_part} in {filename!r}" + f"Invalid wheel filename (invalid build number {build_part!r}): " + f"{filename!r}" ) build = cast(BuildTag, (int(build_match.group(1)), build_match.group(2))) else: diff --git a/tests/test_utils.py b/tests/test_utils.py index a8cc8d71..d6ae2cc2 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -144,22 +144,41 @@ def test_parse_wheel_filename(filename, name, version, build, tags): @pytest.mark.parametrize( - ("filename"), + ("filename", "expected"), [ - ("foo-1.0.whl"), # Missing tags - ("foo-1.0-py3-none-any.wheel"), # Incorrect file extension (`.wheel`) - ("foo__bar-1.0-py3-none-any.whl"), # Invalid name (`__`) - ("foo#bar-1.0-py3-none-any.whl"), # Invalid name (`#`) - ("foobar-1.x-py3-none-any.whl"), # Invalid version (`1.x`) - # Build number doesn't start with a digit (`abc`) - ("foo-1.0-abc-py3-none-any.whl"), - ("foo-1.0-200-py3-none-any-junk.whl"), # Too many dashes (`-junk`) + ("foo-1.0.whl", "wrong number of parts"), + ("foo-1.0-py3-none-any.wheel", "extension must be '.whl'"), + ("foo__bar-1.0-py3-none-any.whl", "invalid project name"), + ("foo#bar-1.0-py3-none-any.whl", "invalid project name"), + ("foobar-1.x-py3-none-any.whl", "invalid version"), + ("foo-1.0-abc-py3-none-any.whl", "invalid build number"), + ("foo-1.0-200-py3-none-any-junk.whl", "wrong number of parts"), + ("foo-01.0.0-py3-none-any.whl", "non-normalized version"), + ("foo-1.1RC1-py3-none-any.whl", "non-normalized version"), + ("foo-1.1.a1-py3-none-any.whl", "non-normalized version"), + ("foo-1.1_a1-py3-none-any.whl", "non-normalized version"), + ("foo-1.0a.1-py3-none-any.whl", "non-normalized version"), + ("foo-1.1alpha1-py3-none-any.whl", "non-normalized version"), + ("foo-1.1beta2-py3-none-any.whl", "non-normalized version"), + ("foo-1.1c2-py3-none-any.whl", "non-normalized version"), + ("foo-1.2a-py3-none-any.whl", "non-normalized version"), + ("foo-1.2_post2-py3-none-any.whl", "non-normalized version"), + ("foo-1.2post2-py3-none-any.whl", "non-normalized version"), + ("foo-1.2.post.2-py3-none-any.whl", "non-normalized version"), + ("foo-1.0.r4-py3-none-any.whl", "non-normalized version"), + ("foo-1.2.post-py3-none-any.whl", "non-normalized version"), + ("foo-1.2dev2-py3-none-any.whl", "non-normalized version"), + ("foo-1.2.dev-py3-none-any.whl", "non-normalized version"), + ("foo-1.0+ubuntu_1-py3-none-any.whl", "non-normalized version"), + ("foo-v1.0-py3-none-any.whl", "non-normalized version"), ], ) -def test_parse_wheel_invalid_filename(filename): - with pytest.raises(InvalidWheelFilename): +def test_parse_wheel_invalid_filename(filename, expected): + with pytest.raises(InvalidWheelFilename) as e: parse_wheel_filename(filename) + assert expected in str(e.value) + @pytest.mark.parametrize( ("filename", "name", "version"),