|  | 
| 39 | 39 | pypi_sdist_url = "https://files.pythonhosted.org/packages/db/89/b982115aabe1068fd581d83d2a0b26b78e1e7ce6184e75003d173e15c0b3/sigstore-3.6.1.tar.gz" | 
| 40 | 40 | pypi_wheel_filename = pypi_wheel_url.split("/")[-1] | 
| 41 | 41 | pypi_sdist_filename = pypi_sdist_url.split("/")[-1] | 
|  | 42 | +pypi_wheel_abbrev = f"sigstore/{pypi_wheel_filename}" | 
|  | 43 | +pypi_sdist_abbrev = f"sigstore/{pypi_sdist_filename}" | 
| 42 | 44 | 
 | 
| 43 | 45 | 
 | 
| 44 | 46 | def run_main_with_command(cmd: list[str]) -> None: | 
| @@ -366,35 +368,33 @@ def test_validate_files(tmp_path: Path, caplog: pytest.LogCaptureFixture) -> Non | 
| 366 | 368 | 
 | 
| 367 | 369 | 
 | 
| 368 | 370 | @online | 
| 369 |  | -def test_verify_pypi_command(caplog: pytest.LogCaptureFixture) -> None: | 
| 370 |  | -    # Happy path wheel | 
| 371 |  | -    run_main_with_command( | 
| 372 |  | -        [ | 
| 373 |  | -            "verify", | 
| 374 |  | -            "pypi", | 
| 375 |  | -            "--repository", | 
| 376 |  | -            "https://github.com/sigstore/sigstore-python", | 
| 377 |  | -            pypi_wheel_url, | 
| 378 |  | -        ] | 
| 379 |  | -    ) | 
| 380 |  | -    assert f"OK: {pypi_wheel_filename}" in caplog.text | 
| 381 |  | - | 
| 382 |  | -    caplog.clear() | 
| 383 |  | - | 
| 384 |  | -    # Happy path sdist | 
|  | 371 | +@pytest.mark.parametrize( | 
|  | 372 | +    "url_argument, filename", | 
|  | 373 | +    [ | 
|  | 374 | +        (pypi_wheel_url, pypi_wheel_filename), | 
|  | 375 | +        (pypi_sdist_url, pypi_sdist_filename), | 
|  | 376 | +        (f"pypi:{pypi_wheel_filename}", pypi_wheel_filename), | 
|  | 377 | +        (f"pypi:{pypi_sdist_filename}", pypi_sdist_filename), | 
|  | 378 | +    ], | 
|  | 379 | +) | 
|  | 380 | +def test_verify_pypi_command( | 
|  | 381 | +    caplog: pytest.LogCaptureFixture, url_argument: str, filename: str | 
|  | 382 | +) -> None: | 
|  | 383 | +    # Happy path | 
| 385 | 384 |     run_main_with_command( | 
| 386 | 385 |         [ | 
| 387 | 386 |             "verify", | 
| 388 | 387 |             "pypi", | 
| 389 | 388 |             "--repository", | 
| 390 | 389 |             "https://github.com/sigstore/sigstore-python", | 
| 391 |  | -            pypi_sdist_url, | 
|  | 390 | +            url_argument, | 
| 392 | 391 |         ] | 
| 393 | 392 |     ) | 
| 394 |  | -    assert f"OK: {pypi_sdist_filename}" in caplog.text | 
|  | 393 | +    assert f"OK: {filename}" in caplog.text | 
| 395 | 394 | 
 | 
| 396 |  | -    caplog.clear() | 
| 397 | 395 | 
 | 
|  | 396 | +@online | 
|  | 397 | +def test_verify_pypi_command_env_fail(caplog: pytest.LogCaptureFixture) -> None: | 
| 398 | 398 |     with pytest.raises(SystemExit): | 
| 399 | 399 |         # Failure from the Sigstore environment | 
| 400 | 400 |         run_main_with_command( | 
| @@ -468,7 +468,7 @@ def test_verify_pypi_invalid_url( | 
| 468 | 468 |     assert "Unsupported/invalid URL" in caplog.text | 
| 469 | 469 | 
 | 
| 470 | 470 | 
 | 
| 471 |  | -def test_verify_pypi_invalid_file_name( | 
|  | 471 | +def test_verify_pypi_invalid_file_name_url( | 
| 472 | 472 |     caplog: pytest.LogCaptureFixture, monkeypatch: pytest.MonkeyPatch | 
| 473 | 473 | ) -> None: | 
| 474 | 474 |     # Failure because file is neither a wheer nor a sdist | 
| @@ -503,6 +503,41 @@ def test_verify_pypi_invalid_file_name( | 
| 503 | 503 |     assert "Invalid wheel filename" in caplog.text | 
| 504 | 504 | 
 | 
| 505 | 505 | 
 | 
|  | 506 | +def test_verify_pypi_invalid_sdist_filename_pypi( | 
|  | 507 | +    caplog: pytest.LogCaptureFixture, monkeypatch: pytest.MonkeyPatch | 
|  | 508 | +) -> None: | 
|  | 509 | +    # Failure because file is neither a wheer nor a sdist | 
|  | 510 | +    monkeypatch.setattr(pypi_attestations._cli, "_download_file", lambda url, dest: None) | 
|  | 511 | +    with pytest.raises(SystemExit): | 
|  | 512 | +        run_main_with_command( | 
|  | 513 | +            [ | 
|  | 514 | +                "verify", | 
|  | 515 | +                "pypi", | 
|  | 516 | +                "--repository", | 
|  | 517 | +                "https://github.com/sigstore/sigstore-python", | 
|  | 518 | +                f"pypi:{pypi_wheel_filename}.invalid_ext", | 
|  | 519 | +            ] | 
|  | 520 | +        ) | 
|  | 521 | +    assert ( | 
|  | 522 | +        "File should be a wheel (*.whl) or a source distribution (*.zip or *.tar.gz)" in caplog.text | 
|  | 523 | +    ) | 
|  | 524 | + | 
|  | 525 | +    caplog.clear() | 
|  | 526 | + | 
|  | 527 | +    """Test that invalid sdist filenames are properly handled.""" | 
|  | 528 | +    with pytest.raises(SystemExit): | 
|  | 529 | +        run_main_with_command( | 
|  | 530 | +            [ | 
|  | 531 | +                "verify", | 
|  | 532 | +                "pypi", | 
|  | 533 | +                "--repository", | 
|  | 534 | +                "https://github.com/sigstore/sigstore-python", | 
|  | 535 | +                "pypi:invalid-sdist-name.tar.gz",  # Invalid sdist filename format | 
|  | 536 | +            ] | 
|  | 537 | +        ) | 
|  | 538 | +    assert "Invalid distribution filename:" in caplog.text | 
|  | 539 | + | 
|  | 540 | + | 
| 506 | 541 | @online | 
| 507 | 542 | def test_verify_pypi_validation_fails( | 
| 508 | 543 |     caplog: pytest.LogCaptureFixture, monkeypatch: pytest.MonkeyPatch | 
| @@ -562,6 +597,44 @@ def test_verify_pypi_error_getting_provenance( | 
| 562 | 597 |     assert expected_error in caplog.text | 
| 563 | 598 | 
 | 
| 564 | 599 | 
 | 
|  | 600 | +def test_verify_pypi_error_finding_package_info( | 
|  | 601 | +    caplog: pytest.LogCaptureFixture, | 
|  | 602 | +    monkeypatch: pytest.MonkeyPatch, | 
|  | 603 | +) -> None: | 
|  | 604 | +    response = stub(raise_for_status=raiser(requests.HTTPError("myerror"))) | 
|  | 605 | +    monkeypatch.setattr(requests, "get", lambda url, headers: response) | 
|  | 606 | +    with pytest.raises(SystemExit): | 
|  | 607 | +        run_main_with_command( | 
|  | 608 | +            [ | 
|  | 609 | +                "verify", | 
|  | 610 | +                "pypi", | 
|  | 611 | +                "--repository", | 
|  | 612 | +                "https://github.com/sigstore/sigstore-python", | 
|  | 613 | +                "pypi:somefile-1.0.0.tar.gz", | 
|  | 614 | +            ] | 
|  | 615 | +        ) | 
|  | 616 | +    assert "Error trying to get information for 'somefile' from PyPI: myerror" in caplog.text | 
|  | 617 | + | 
|  | 618 | + | 
|  | 619 | +def test_verify_pypi_error_finding_artifact_url( | 
|  | 620 | +    caplog: pytest.LogCaptureFixture, | 
|  | 621 | +    monkeypatch: pytest.MonkeyPatch, | 
|  | 622 | +) -> None: | 
|  | 623 | +    response = stub(raise_for_status=lambda: None, json=lambda: {"files": []}) | 
|  | 624 | +    monkeypatch.setattr(requests, "get", lambda url, headers: response) | 
|  | 625 | +    with pytest.raises(SystemExit): | 
|  | 626 | +        run_main_with_command( | 
|  | 627 | +            [ | 
|  | 628 | +                "verify", | 
|  | 629 | +                "pypi", | 
|  | 630 | +                "--repository", | 
|  | 631 | +                "https://github.com/sigstore/sigstore-python", | 
|  | 632 | +                "pypi:somefile-1.0.0.tar.gz", | 
|  | 633 | +            ] | 
|  | 634 | +        ) | 
|  | 635 | +    assert "Could not find the artifact 'somefile-1.0.0.tar.gz' on PyPI" in caplog.text | 
|  | 636 | + | 
|  | 637 | + | 
| 565 | 638 | def test_verify_pypi_error_validating_provenance( | 
| 566 | 639 |     caplog: pytest.LogCaptureFixture, | 
| 567 | 640 |     monkeypatch: pytest.MonkeyPatch, | 
|  | 
0 commit comments