Skip to content

Commit 32a2699

Browse files
committed
Add more Pulp Exceptions.
Assisted-by: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent e1e023c commit 32a2699

File tree

3 files changed

+60
-18
lines changed

3 files changed

+60
-18
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add more Pulp Exceptions.

pulp_python/app/exceptions.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import http.client
2+
from gettext import gettext as _
3+
4+
from pulpcore.exceptions import PulpException
5+
6+
7+
class ProvenanceVerificationError(PulpException):
8+
"""
9+
Raised when provenance verification fails.
10+
"""
11+
12+
http_status_code = http.client.BAD_REQUEST
13+
error_code = "PLPY0001"
14+
15+
def __init__(self, message):
16+
"""
17+
:param message: Description of the provenance verification error
18+
:type message: str
19+
"""
20+
self.message = message
21+
22+
def __str__(self):
23+
return f"[{self.error_code}] " + _("Provenance verification failed: {message}").format(
24+
message=self.message
25+
)
26+
27+
28+
class AttestationVerificationError(PulpException):
29+
"""
30+
Raised when attestation verification fails.
31+
"""
32+
33+
http_status_code = http.client.BAD_REQUEST
34+
error_code = "PLPY0002"
35+
36+
def __init__(self, message):
37+
"""
38+
:param message: Description of the attestation verification error
39+
:type message: str
40+
"""
41+
self.message = message
42+
43+
def __str__(self):
44+
return f"[{self.error_code}] " + _("Attestation verification failed: {message}").format(
45+
message=self.message
46+
)

pulp_python/app/serializers.py

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@
88
from packaging.requirements import Requirement
99
from rest_framework import serializers
1010
from pypi_attestations import AttestationError
11-
from pydantic import TypeAdapter, ValidationError
11+
from pydantic import TypeAdapter, ValidationError as PydanticValidationError
1212
from urllib.parse import urljoin
1313

14+
from pulpcore.exceptions.validation import DigestValidationError, ValidationError
1415
from pulpcore.plugin import models as core_models
1516
from pulpcore.plugin import serializers as core_serializers
1617
from pulpcore.plugin.util import get_domain, get_prn, get_current_authenticated_user
1718

1819
from pulp_python.app import models as python_models
20+
from pulp_python.app.exceptions import AttestationVerificationError, ProvenanceVerificationError
1921
from pulp_python.app.provenance import (
2022
Attestation,
2123
Provenance,
@@ -374,7 +376,7 @@ def validate_attestations(self, value):
374376
attestations = TypeAdapter(list[Attestation]).validate_json(value)
375377
else:
376378
attestations = TypeAdapter(list[Attestation]).validate_python(value)
377-
except ValidationError as e:
379+
except PydanticValidationError as e:
378380
raise serializers.ValidationError(_("Invalid attestations: {}".format(e)))
379381
return attestations
380382

@@ -387,9 +389,7 @@ def handle_attestations(self, filename, sha256, attestations, offline=True):
387389
try:
388390
verify_provenance(filename, sha256, provenance, offline=offline)
389391
except AttestationError as e:
390-
raise serializers.ValidationError(
391-
{"attestations": _("Attestations failed verification: {}".format(e))}
392-
)
392+
raise AttestationVerificationError(str(e))
393393
return provenance.model_dump(mode="json")
394394

395395
def deferred_validate(self, data):
@@ -408,26 +408,23 @@ def deferred_validate(self, data):
408408
try:
409409
filename = data["relative_path"]
410410
except KeyError:
411-
raise serializers.ValidationError(detail={"relative_path": _("This field is required")})
411+
raise ValidationError(_("This field is required: relative_path"))
412412

413413
artifact = data["artifact"]
414414
try:
415415
_data = artifact_to_python_content_data(filename, artifact, domain=get_domain())
416416
except ValueError:
417-
raise serializers.ValidationError(
417+
raise ValidationError(
418418
_(
419419
"Extension on {} is not a valid python extension "
420420
"(.whl, .exe, .egg, .tar.gz, .tar.bz2, .zip)"
421421
).format(filename)
422422
)
423423

424424
if data.get("sha256") and data["sha256"] != artifact.sha256:
425-
raise serializers.ValidationError(
426-
detail={
427-
"sha256": _(
428-
"The uploaded artifact's sha256 checksum does not match the one provided"
429-
)
430-
}
425+
raise DigestValidationError(
426+
actual=artifact.sha256,
427+
expected=data["sha256"],
431428
)
432429

433430
data.update(_data)
@@ -641,15 +638,13 @@ def deferred_validate(self, data):
641638
try:
642639
provenance = Provenance.model_validate_json(data["file"].read())
643640
data["provenance"] = provenance.model_dump(mode="json")
644-
except ValidationError as e:
645-
raise serializers.ValidationError(
646-
_("The uploaded provenance is not valid: {}".format(e))
647-
)
641+
except PydanticValidationError as e:
642+
raise ValidationError(_("The uploaded provenance is not valid: {}".format(e)))
648643
if data.pop("verify"):
649644
try:
650645
verify_provenance(data["package"].filename, data["package"].sha256, provenance)
651646
except AttestationError as e:
652-
raise serializers.ValidationError(_("Provenance verification failed: {}".format(e)))
647+
raise ProvenanceVerificationError(str(e))
653648
return data
654649

655650
def retrieve(self, validated_data):

0 commit comments

Comments
 (0)