|
9 | 9 | from drf_spectacular.utils import extend_schema_serializer |
10 | 10 | from packaging.requirements import Requirement |
11 | 11 | from packaging.version import InvalidVersion, Version |
12 | | -from pydantic import TypeAdapter, ValidationError |
| 12 | +from pydantic import TypeAdapter |
| 13 | +from pydantic import ValidationError as PydanticValidationError |
13 | 14 | from pypi_attestations import AttestationError |
14 | 15 | from rest_framework import serializers |
15 | 16 |
|
16 | 17 | from pulpcore.plugin import models as core_models |
17 | 18 | from pulpcore.plugin import serializers as core_serializers |
| 19 | +from pulpcore.plugin.exceptions import DigestValidationError |
18 | 20 | from pulpcore.plugin.util import get_current_authenticated_user, get_domain, get_prn, reverse |
19 | 21 |
|
20 | 22 | from pulp_python.app import models as python_models |
| 23 | +from pulp_python.app.exceptions import ( |
| 24 | + InvalidProvenanceError, |
| 25 | + InvalidPythonExtensionError, |
| 26 | + MissingRelativePathError, |
| 27 | + ProvenanceVerificationError, |
| 28 | +) |
21 | 29 | from pulp_python.app.provenance import ( |
22 | 30 | AnyPublisher, |
23 | 31 | Attestation, |
@@ -387,7 +395,7 @@ def validate_attestations(self, value): |
387 | 395 | attestations = TypeAdapter(list[Attestation]).validate_json(value) |
388 | 396 | else: |
389 | 397 | attestations = TypeAdapter(list[Attestation]).validate_python(value) |
390 | | - except ValidationError as e: |
| 398 | + except PydanticValidationError as e: |
391 | 399 | raise serializers.ValidationError(_("Invalid attestations: {}").format(e)) |
392 | 400 | return attestations |
393 | 401 |
|
@@ -421,26 +429,18 @@ def deferred_validate(self, data): |
421 | 429 | try: |
422 | 430 | filename = data["relative_path"] |
423 | 431 | except KeyError: |
424 | | - raise serializers.ValidationError(detail={"relative_path": _("This field is required")}) |
| 432 | + raise MissingRelativePathError() |
425 | 433 |
|
426 | 434 | artifact = data["artifact"] |
427 | 435 | try: |
428 | 436 | _data = artifact_to_python_content_data(filename, artifact, domain=get_domain()) |
429 | 437 | except ValueError: |
430 | | - raise serializers.ValidationError( |
431 | | - _( |
432 | | - "Extension on {} is not a valid python extension " |
433 | | - "(.whl, .exe, .egg, .tar.gz, .tar.bz2, .zip)" |
434 | | - ).format(filename) |
435 | | - ) |
| 438 | + raise InvalidPythonExtensionError(filename) |
436 | 439 |
|
437 | 440 | if data.get("sha256") and data["sha256"] != artifact.sha256: |
438 | | - raise serializers.ValidationError( |
439 | | - detail={ |
440 | | - "sha256": _( |
441 | | - "The uploaded artifact's sha256 checksum does not match the one provided" |
442 | | - ) |
443 | | - } |
| 441 | + raise DigestValidationError( |
| 442 | + actual=artifact.sha256, |
| 443 | + expected=data["sha256"], |
444 | 444 | ) |
445 | 445 |
|
446 | 446 | data.update(_data) |
@@ -654,15 +654,13 @@ def deferred_validate(self, data): |
654 | 654 | try: |
655 | 655 | provenance = Provenance.model_validate_json(data["file"].read()) |
656 | 656 | data["provenance"] = provenance.model_dump(mode="json") |
657 | | - except ValidationError as e: |
658 | | - raise serializers.ValidationError( |
659 | | - _("The uploaded provenance is not valid: {}").format(e) |
660 | | - ) |
| 657 | + except PydanticValidationError as e: |
| 658 | + raise InvalidProvenanceError(str(e)) |
661 | 659 | if data.pop("verify"): |
662 | 660 | try: |
663 | 661 | verify_provenance(data["package"].filename, data["package"].sha256, provenance) |
664 | 662 | except AttestationError as e: |
665 | | - raise serializers.ValidationError(_("Provenance verification failed: {}").format(e)) |
| 663 | + raise ProvenanceVerificationError(str(e)) |
666 | 664 | return data |
667 | 665 |
|
668 | 666 | def retrieve(self, validated_data): |
|
0 commit comments