99from packaging .version import Version , InvalidVersion
1010from rest_framework import serializers
1111from pypi_attestations import AttestationError
12- from pydantic import TypeAdapter , ValidationError
12+ from pydantic import TypeAdapter , ValidationError as PydanticValidationError
1313from urllib .parse import urljoin
1414
15+ from pulpcore .plugin .exceptions import DigestValidationError
1516from pulpcore .plugin import models as core_models
1617from pulpcore .plugin import serializers as core_serializers
1718from pulpcore .plugin .util import get_domain , get_prn , get_current_authenticated_user , reverse
1819
1920from pulp_python .app import models as python_models
21+ from pulp_python .app .exceptions import (
22+ AttestationVerificationError ,
23+ InvalidProvenanceError ,
24+ InvalidPythonExtensionError ,
25+ MissingRelativePathError ,
26+ ProvenanceVerificationError ,
27+ )
2028from pulp_python .app .utils import canonicalize_name
2129from pulp_python .app .provenance import (
2230 Attestation ,
@@ -386,7 +394,7 @@ def validate_attestations(self, value):
386394 attestations = TypeAdapter (list [Attestation ]).validate_json (value )
387395 else :
388396 attestations = TypeAdapter (list [Attestation ]).validate_python (value )
389- except ValidationError as e :
397+ except PydanticValidationError as e :
390398 raise serializers .ValidationError (_ ("Invalid attestations: {}" .format (e )))
391399 return attestations
392400
@@ -399,9 +407,7 @@ def handle_attestations(self, filename, sha256, attestations, offline=True):
399407 try :
400408 verify_provenance (filename , sha256 , provenance , offline = offline )
401409 except AttestationError as e :
402- raise serializers .ValidationError (
403- {"attestations" : _ ("Attestations failed verification: {}" .format (e ))}
404- )
410+ raise AttestationVerificationError (str (e ))
405411 return provenance .model_dump (mode = "json" )
406412
407413 def deferred_validate (self , data ):
@@ -420,26 +426,18 @@ def deferred_validate(self, data):
420426 try :
421427 filename = data ["relative_path" ]
422428 except KeyError :
423- raise serializers . ValidationError ( detail = { "relative_path" : _ ( "This field is required" )} )
429+ raise MissingRelativePathError ( )
424430
425431 artifact = data ["artifact" ]
426432 try :
427433 _data = artifact_to_python_content_data (filename , artifact , domain = get_domain ())
428434 except ValueError :
429- raise serializers .ValidationError (
430- _ (
431- "Extension on {} is not a valid python extension "
432- "(.whl, .exe, .egg, .tar.gz, .tar.bz2, .zip)"
433- ).format (filename )
434- )
435+ raise InvalidPythonExtensionError (filename )
435436
436437 if data .get ("sha256" ) and data ["sha256" ] != artifact .sha256 :
437- raise serializers .ValidationError (
438- detail = {
439- "sha256" : _ (
440- "The uploaded artifact's sha256 checksum does not match the one provided"
441- )
442- }
438+ raise DigestValidationError (
439+ actual = artifact .sha256 ,
440+ expected = data ["sha256" ],
443441 )
444442
445443 data .update (_data )
@@ -653,15 +651,13 @@ def deferred_validate(self, data):
653651 try :
654652 provenance = Provenance .model_validate_json (data ["file" ].read ())
655653 data ["provenance" ] = provenance .model_dump (mode = "json" )
656- except ValidationError as e :
657- raise serializers .ValidationError (
658- _ ("The uploaded provenance is not valid: {}" .format (e ))
659- )
654+ except PydanticValidationError as e :
655+ raise InvalidProvenanceError (str (e ))
660656 if data .pop ("verify" ):
661657 try :
662658 verify_provenance (data ["package" ].filename , data ["package" ].sha256 , provenance )
663659 except AttestationError as e :
664- raise serializers . ValidationError ( _ ( "Provenance verification failed: {}" . format ( e ) ))
660+ raise ProvenanceVerificationError ( str ( e ))
665661 return data
666662
667663 def retrieve (self , validated_data ):
0 commit comments