2323)
2424from pypi_attestations ._impl import Attestation , AttestationError , Distribution
2525
26- ONLINE_TESTS = "CI" in os .environ or "TEST_INTERACTIVE" in os .environ
27- online = pytest .mark .skipif (not ONLINE_TESTS , reason = "online tests not enabled" )
26+ ONLINE_TESTS = (
27+ "CI" in os .environ or "TEST_INTERACTIVE" in os .environ
28+ ) and "TEST_OFFLINE" not in os .environ
2829
30+ online = pytest .mark .skipif (not ONLINE_TESTS , reason = "online tests not enabled" )
2931
3032_HERE = Path (__file__ ).parent
3133_ASSETS = _HERE / "assets"
@@ -216,6 +218,7 @@ def test_verify_attestation_command(caplog: pytest.LogCaptureFixture) -> None:
216218 [
217219 "verify" ,
218220 "attestation" ,
221+ "--offline" ,
219222 "--identity" ,
220223 publish_attestation_identity ,
221224 artifact_path .as_posix (),
@@ -233,6 +236,7 @@ def test_verify_attestation_command(caplog: pytest.LogCaptureFixture) -> None:
233236 "verify" ,
234237 "attestation" ,
235238 "--staging" ,
239+ "--offline" ,
236240 "--identity" ,
237241 publish_attestation_identity ,
238242 artifact_path .as_posix (),
@@ -256,6 +260,7 @@ def test_verify_attestation_invalid_attestation(caplog: pytest.LogCaptureFixture
256260 [
257261 "verify" ,
258262 "attestation" ,
263+ "--offline" ,
259264 "--identity" ,
260265 publish_attestation_identity ,
261266 fake_package_name .as_posix (),
@@ -271,6 +276,7 @@ def test_verify_attestation_missing_artifact(caplog: pytest.LogCaptureFixture) -
271276 [
272277 "verify" ,
273278 "attestation" ,
279+ "--offline" ,
274280 "--identity" ,
275281 publish_attestation_identity ,
276282 "not_a_file.txt" ,
@@ -288,6 +294,7 @@ def test_verify_attestation_missing_attestation(caplog: pytest.LogCaptureFixture
288294 [
289295 "verify" ,
290296 "attestation" ,
297+ "--offline" ,
291298 "--identity" ,
292299 publish_attestation_identity ,
293300 f .name ,
@@ -310,6 +317,7 @@ def test_verify_attestation_invalid_artifact(
310317 [
311318 "verify" ,
312319 "attestation" ,
320+ "--offline" ,
313321 "--identity" ,
314322 publish_attestation_identity ,
315323 copied_artifact .as_posix (),
@@ -393,6 +401,7 @@ def test_verify_pypi_command_with_local_files(caplog: pytest.LogCaptureFixture)
393401 [
394402 "verify" ,
395403 "pypi" ,
404+ "--offline" ,
396405 "--repository" ,
397406 "https://github.com/trailofbits/pypi-attestations" ,
398407 "--provenance-file" ,
@@ -403,6 +412,40 @@ def test_verify_pypi_command_with_local_files(caplog: pytest.LogCaptureFixture)
403412 assert f"OK: { pypi_sdist_filename } " in caplog .text
404413
405414
415+ def test_verify_pypi_command_offline_without_local_dist (caplog : pytest .LogCaptureFixture ) -> None :
416+ with pytest .raises (SystemExit ):
417+ run_main_with_command (
418+ [
419+ "verify" ,
420+ "pypi" ,
421+ "--offline" ,
422+ "--repository" ,
423+ "https://github.com/trailofbits/pypi-attestations" ,
424+ "--provenance-file" ,
425+ pypi_sdist_provenance_path .as_posix (),
426+ pypi_sdist_url ,
427+ ]
428+ )
429+ assert "The '--offline' option can only be used with local files" in caplog .text
430+
431+
432+ def test_verify_pypi_command_offline_without_local_provenance (
433+ caplog : pytest .LogCaptureFixture ,
434+ ) -> None :
435+ with pytest .raises (SystemExit ):
436+ run_main_with_command (
437+ [
438+ "verify" ,
439+ "pypi" ,
440+ "--offline" ,
441+ "--repository" ,
442+ "https://github.com/trailofbits/pypi-attestations" ,
443+ pypi_sdist_path .as_posix (),
444+ ]
445+ )
446+ assert "The '--offline' option can only be used with local files" in caplog .text
447+
448+
406449@online
407450def test_verify_pypi_command_env_fail (caplog : pytest .LogCaptureFixture ) -> None :
408451 with pytest .raises (SystemExit ):
@@ -558,7 +601,7 @@ def test_verify_pypi_error_getting_provenance(
558601 monkeypatch .setattr (
559602 pypi_attestations ._cli ,
560603 "_get_distribution_from_arg" ,
561- lambda arg : Distribution (name = pypi_wheel_filename , digest = "a" ),
604+ lambda arg , offline : Distribution (name = pypi_wheel_filename , digest = "a" ),
562605 )
563606 response = requests .Response ()
564607 response .status_code = status_code
@@ -622,7 +665,7 @@ def test_verify_pypi_error_validating_provenance(
622665 monkeypatch .setattr (
623666 pypi_attestations ._cli ,
624667 "_get_distribution_from_arg" ,
625- lambda arg : Distribution (name = pypi_wheel_filename , digest = "a" ),
668+ lambda arg , offline : Distribution (name = pypi_wheel_filename , digest = "a" ),
626669 )
627670 response = stub (status_code = 200 , raise_for_status = lambda : None , text = "not json" )
628671 response .status_code = 200
@@ -714,6 +757,7 @@ def test_verify_pypi_command_local_nonexistent_artifact(caplog: pytest.LogCaptur
714757 [
715758 "verify" ,
716759 "pypi" ,
760+ "--offline" ,
717761 "--repository" ,
718762 "https://github.com/trailofbits/pypi-attestations" ,
719763 "--provenance-file" ,
@@ -730,6 +774,7 @@ def test_verify_pypi_command_local_nonexistent_provenance(caplog: pytest.LogCapt
730774 [
731775 "verify" ,
732776 "pypi" ,
777+ "--offline" ,
733778 "--repository" ,
734779 "https://github.com/trailofbits/pypi-attestations" ,
735780 "--provenance-file" ,
@@ -746,7 +791,7 @@ def test_verify_pypi_command_local_invalid_provenance(
746791 monkeypatch .setattr (
747792 pypi_attestations ._cli ,
748793 "_get_distribution_from_arg" ,
749- lambda arg : Distribution (name = pypi_sdist_filename , digest = "a" ),
794+ lambda arg , offline : Distribution (name = pypi_sdist_filename , digest = "a" ),
750795 )
751796
752797 with tempfile .NamedTemporaryFile (suffix = ".provenance" ) as f :
@@ -757,6 +802,7 @@ def test_verify_pypi_command_local_invalid_provenance(
757802 [
758803 "verify" ,
759804 "pypi" ,
805+ "--offline" ,
760806 "--repository" ,
761807 "https://github.com/trailofbits/pypi-attestations" ,
762808 "--provenance-file" ,
0 commit comments