pulp-python 3.30.2__tar.gz → 3.31.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. {pulp_python-3.30.2 → pulp_python-3.31.0}/CHANGES.md +50 -0
  2. {pulp_python-3.30.2 → pulp_python-3.31.0}/PKG-INFO +1 -1
  3. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/__init__.py +1 -1
  4. pulp_python-3.31.0/pulp_python/app/exceptions.py +54 -0
  5. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/models.py +5 -5
  6. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/pypi/views.py +12 -12
  7. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/serializers.py +4 -3
  8. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/tasks/sync.py +7 -6
  9. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/tasks/upload.py +11 -2
  10. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/utils.py +12 -8
  11. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/api/test_domains.py +8 -2
  12. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python.egg-info/PKG-INFO +1 -1
  13. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python.egg-info/SOURCES.txt +1 -0
  14. {pulp_python-3.30.2 → pulp_python-3.31.0}/pyproject.toml +2 -2
  15. {pulp_python-3.30.2 → pulp_python-3.31.0}/COMMITMENT +0 -0
  16. {pulp_python-3.30.2 → pulp_python-3.31.0}/COPYRIGHT +0 -0
  17. {pulp_python-3.30.2 → pulp_python-3.31.0}/LICENSE +0 -0
  18. {pulp_python-3.30.2 → pulp_python-3.31.0}/MANIFEST.in +0 -0
  19. {pulp_python-3.30.2 → pulp_python-3.31.0}/README.md +0 -0
  20. {pulp_python-3.30.2 → pulp_python-3.31.0}/functest_requirements.txt +0 -0
  21. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/__init__.py +0 -0
  22. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/global_access_conditions.py +0 -0
  23. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/management/__init__.py +0 -0
  24. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/management/commands/__init__.py +0 -0
  25. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/management/commands/repair-python-metadata.py +0 -0
  26. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0001_initial.py +0 -0
  27. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0001_squashed_0010_update_json_field.py +0 -0
  28. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0002_pythonpackagecontent_python_version.py +0 -0
  29. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0003_new_sync_filters.py +0 -0
  30. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0004_DATA_swap_distribution_model.py +0 -0
  31. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0005_pythonpackagecontent_sha256.py +0 -0
  32. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0006_pythonrepository_autopublish.py +0 -0
  33. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0007_pythonpackagecontent_mv-2-1.py +0 -0
  34. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0008_pythonpackagecontent_unique_sha256.py +0 -0
  35. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0009_pythondistribution_allow_uploads.py +0 -0
  36. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0010_update_json_field.py +0 -0
  37. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0011_alter_pythondistribution_distribution_ptr_and_more.py +0 -0
  38. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0012_add_domain.py +0 -0
  39. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0013_add_rbac_permissions.py +0 -0
  40. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0014_pythonpackagecontent_dynamic_and_more.py +0 -0
  41. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0015_alter_pythonpackagecontent_options.py +0 -0
  42. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0016_pythonpackagecontent_metadata_sha256.py +0 -0
  43. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0017_pythonpackagecontent_size.py +0 -0
  44. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0018_packageprovenance.py +0 -0
  45. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0019_create_missing_metadata_artifacts.py +0 -0
  46. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0020_pythonpackagecontent_name_normalized.py +0 -0
  47. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0021_pythonrepository_upload_duplicate_filenames.py +0 -0
  48. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/0022_pythonblocklistentry.py +0 -0
  49. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/migrations/__init__.py +0 -0
  50. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/modelresource.py +0 -0
  51. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/provenance.py +0 -0
  52. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/pypi/__init__.py +0 -0
  53. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/pypi/serializers.py +0 -0
  54. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/replica.py +0 -0
  55. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/settings.py +0 -0
  56. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/tasks/__init__.py +0 -0
  57. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/tasks/publish.py +0 -0
  58. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/tasks/repair.py +0 -0
  59. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/tasks/vulnerability_report.py +0 -0
  60. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/urls.py +0 -0
  61. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/viewsets.py +0 -0
  62. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/webserver_snippets/__init__.py +0 -0
  63. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/webserver_snippets/apache.conf +0 -0
  64. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/app/webserver_snippets/nginx.conf +0 -0
  65. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/pytest_plugin.py +0 -0
  66. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/__init__.py +0 -0
  67. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/__init__.py +0 -0
  68. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/api/__init__.py +0 -0
  69. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/api/test_attestations.py +0 -0
  70. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/api/test_auto_publish.py +0 -0
  71. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/api/test_blocklist.py +0 -0
  72. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/api/test_consume_content.py +0 -0
  73. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/api/test_crud_content_unit.py +0 -0
  74. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/api/test_crud_publications.py +0 -0
  75. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/api/test_crud_remotes.py +0 -0
  76. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/api/test_download_content.py +0 -0
  77. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/api/test_export_import.py +0 -0
  78. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/api/test_full_mirror.py +0 -0
  79. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/api/test_pypi_apis.py +0 -0
  80. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/api/test_pypi_simple_api.py +0 -0
  81. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/api/test_rbac.py +0 -0
  82. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/api/test_repair.py +0 -0
  83. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/api/test_sync.py +0 -0
  84. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/api/test_upload.py +0 -0
  85. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/api/test_vulnerability_report.py +0 -0
  86. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/assets/shelf-reader-0.1.tar.gz.publish.attestation +0 -0
  87. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/assets/shelf_reader-0.1-py2-none-any.whl.publish.attestation +0 -0
  88. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/constants.py +0 -0
  89. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/functional/utils.py +0 -0
  90. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/unit/__init__.py +0 -0
  91. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python/tests/unit/test_models.py +0 -0
  92. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python.egg-info/dependency_links.txt +0 -0
  93. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python.egg-info/entry_points.txt +0 -0
  94. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python.egg-info/requires.txt +0 -0
  95. {pulp_python-3.30.2 → pulp_python-3.31.0}/pulp_python.egg-info/top_level.txt +0 -0
  96. {pulp_python-3.30.2 → pulp_python-3.31.0}/setup.cfg +0 -0
  97. {pulp_python-3.30.2 → pulp_python-3.31.0}/test_requirements.txt +0 -0
  98. {pulp_python-3.30.2 → pulp_python-3.31.0}/unittest_requirements.txt +0 -0
@@ -8,6 +8,36 @@
8
8
 
9
9
  [//]: # (towncrier release notes start)
10
10
 
11
+ ## 3.31.0 (2026-06-09) {: #3.31.0 }
12
+
13
+ #### Features {: #3.31.0-feature }
14
+
15
+ - Add more Pulp Exceptions.
16
+
17
+ #### Bugfixes {: #3.31.0-bugfix }
18
+
19
+ - Fixed `upload_time` in Simple and JSON APIs to reflect repository addition time instead of content creation time.
20
+ [#1232](https://github.com/pulp/pulp_python/issues/1232)
21
+ - Fixed blocklist entries API to support `isnull` filter lookup on `version` to uniquely identify name-only entries.
22
+ [#1238](https://github.com/pulp/pulp_python/issues/1238)
23
+ - Optimized `upload_time` lookups in Simple and JSON APIs.
24
+ [#1242](https://github.com/pulp/pulp_python/issues/1242)
25
+ - Optimized `provenance` lookups in Simple API.
26
+ [#1243](https://github.com/pulp/pulp_python/issues/1243)
27
+
28
+ ---
29
+
30
+ ## 3.30.3 (2026-06-05) {: #3.30.3 }
31
+
32
+ #### Bugfixes {: #3.30.3-bugfix }
33
+
34
+ - Optimized `upload_time` lookups in Simple and JSON APIs.
35
+ [#1242](https://github.com/pulp/pulp_python/issues/1242)
36
+ - Optimized `provenance` lookups in Simple API.
37
+ [#1243](https://github.com/pulp/pulp_python/issues/1243)
38
+
39
+ ---
40
+
11
41
  ## 3.30.2 (2026-05-19) {: #3.30.2 }
12
42
 
13
43
  #### Bugfixes {: #3.30.2-bugfix }
@@ -89,6 +119,26 @@
89
119
 
90
120
  ---
91
121
 
122
+ ## 3.27.4 (2026-06-05) {: #3.27.4 }
123
+
124
+ #### Bugfixes {: #3.27.4-bugfix }
125
+
126
+ - Optimized `upload_time` lookups in Simple and JSON APIs.
127
+ [#1242](https://github.com/pulp/pulp_python/issues/1242)
128
+ - Optimized `provenance` lookups in Simple API.
129
+ [#1243](https://github.com/pulp/pulp_python/issues/1243)
130
+
131
+ ---
132
+
133
+ ## 3.27.3 (2026-05-19) {: #3.27.3 }
134
+
135
+ #### Bugfixes {: #3.27.3-bugfix }
136
+
137
+ - Fixed `upload_time` in Simple and JSON APIs to reflect repository addition time instead of content creation time.
138
+ [#1232](https://github.com/pulp/pulp_python/issues/1232)
139
+
140
+ ---
141
+
92
142
  ## 3.27.2 (2026-04-14) {: #3.27.2 }
93
143
 
94
144
  #### Bugfixes {: #3.27.2-bugfix }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pulp-python
3
- Version: 3.30.2
3
+ Version: 3.31.0
4
4
  Summary: pulp-python plugin for the Pulp Project
5
5
  Author-email: Pulp Team <pulp-list@redhat.com>
6
6
  Project-URL: Homepage, https://pulpproject.org
@@ -12,7 +12,7 @@ class PulpPythonPluginAppConfig(PulpPluginAppConfig):
12
12
 
13
13
  name = "pulp_python.app"
14
14
  label = "python"
15
- version = "3.30.2"
15
+ version = "3.31.0"
16
16
  python_package_name = "pulp-python"
17
17
  domain_compatible = True
18
18
 
@@ -0,0 +1,54 @@
1
+ from gettext import gettext as _
2
+
3
+ from pulpcore.plugin.exceptions import PulpException
4
+
5
+
6
+ class AttestationVerificationError(PulpException):
7
+ """
8
+ Raised when attestation verification fails.
9
+ """
10
+
11
+ error_code = "PYT0001"
12
+
13
+ def __init__(self, message):
14
+ super().__init__()
15
+ self.message = message
16
+
17
+ def __str__(self):
18
+ return f"[{self.error_code}] " + _("Attestation verification failed: {message}").format(
19
+ message=self.message
20
+ )
21
+
22
+
23
+ class UnsupportedProtocolError(PulpException):
24
+ """
25
+ Raised when an unsupported protocol is used for syncing.
26
+ """
27
+
28
+ error_code = "PYT0002"
29
+
30
+ def __init__(self, protocol):
31
+ super().__init__()
32
+ self.protocol = protocol
33
+
34
+ def __str__(self):
35
+ return f"[{self.error_code}] " + _(
36
+ "Only HTTP(S) is supported for python syncing, got: {protocol}"
37
+ ).format(protocol=self.protocol)
38
+
39
+
40
+ class InvalidAttestationsError(PulpException):
41
+ """
42
+ Raised when attestation data cannot be validated.
43
+ """
44
+
45
+ error_code = "PYT0003"
46
+
47
+ def __init__(self, message):
48
+ super().__init__()
49
+ self.message = message
50
+
51
+ def __str__(self):
52
+ return f"[{self.error_code}] " + _("Invalid attestations: {message}").format(
53
+ message=self.message
54
+ )
@@ -412,16 +412,16 @@ class PythonRepository(Repository, AutoAddObjPermsMixin):
412
412
 
413
413
  def _check_for_package_substitution(self, new_version):
414
414
  """
415
- Raise a ValidationError if newly added packages would replace existing packages that have
416
- the same filename but a different sha256 checksum.
415
+ Raise a ValidationError if newly added packages would replace existing packages
416
+ that have the same filename but a different sha256 checksum.
417
417
  """
418
418
  qs = PythonPackageContent.objects.filter(pk__in=new_version.content)
419
419
  duplicates = collect_duplicates(qs, ("filename",))
420
420
  if duplicates:
421
421
  raise ValidationError(
422
- "Found duplicate packages being added with the same filename but different checksums. " # noqa: E501
423
- "To allow this, set 'allow_package_substitution' to True on the repository. "
424
- f"Conflicting packages: {duplicates}"
422
+ "Found duplicate packages being added with the same filename but different "
423
+ "checksums. To allow this, set 'allow_package_substitution' to True on the "
424
+ f"repository. Conflicting packages: {duplicates}"
425
425
  )
426
426
 
427
427
  def _check_blocklist(self, new_version):
@@ -7,7 +7,7 @@ from urllib.parse import urljoin, urlparse, urlunsplit
7
7
  from django.contrib.sessions.models import Session
8
8
  from django.core.exceptions import ObjectDoesNotExist
9
9
  from django.db import transaction
10
- from django.db.models import OuterRef, Subquery
10
+ from django.db.models import Exists, F, FilteredRelation, OuterRef, Q
11
11
  from django.db.utils import DatabaseError
12
12
  from django.http.response import (
13
13
  Http404,
@@ -26,7 +26,6 @@ from rest_framework.renderers import BrowsableAPIRenderer, JSONRenderer, Templat
26
26
  from rest_framework.response import Response
27
27
  from rest_framework.viewsets import ViewSet
28
28
 
29
- from pulpcore.plugin.models import RepositoryContent
30
29
  from pulpcore.plugin.tasking import dispatch
31
30
  from pulpcore.plugin.util import get_domain, get_url
32
31
  from pulpcore.plugin.viewsets import OperationPostponedResponse
@@ -368,13 +367,16 @@ class SimpleView(PackageUploadMixin, ViewSet):
368
367
  return redirect(urljoin(self.base_content_url, f"{path}/simple/{normalized}/"))
369
368
  if content is not None:
370
369
  local_packages = content.filter(name_normalized=normalized)
371
- repo_added_subquery = RepositoryContent.objects.filter(
372
- content_id=OuterRef("pk"),
373
- repository=repo_ver.repository,
374
- version_removed=None,
375
- ).values("pulp_created")[:1]
376
370
  packages = local_packages.annotate(
377
- repo_added_time=Subquery(repo_added_subquery)
371
+ active_membership=FilteredRelation(
372
+ "version_memberships",
373
+ condition=Q(
374
+ version_memberships__repository=repo_ver.repository,
375
+ version_memberships__version_removed=None,
376
+ ),
377
+ ),
378
+ repo_added_time=F("active_membership__pulp_created"),
379
+ has_provenance=Exists(PackageProvenance.objects.filter(package_id=OuterRef("pk"))),
378
380
  ).values(
379
381
  "filename",
380
382
  "sha256",
@@ -383,9 +385,7 @@ class SimpleView(PackageUploadMixin, ViewSet):
383
385
  "size",
384
386
  "repo_added_time",
385
387
  "version",
386
- )
387
- provenances = PackageProvenance.objects.filter(package__in=local_packages).values_list(
388
- "package__filename", flat=True
388
+ "has_provenance",
389
389
  )
390
390
  local_releases = {
391
391
  p["filename"]: {
@@ -394,7 +394,7 @@ class SimpleView(PackageUploadMixin, ViewSet):
394
394
  "upload_time": p["repo_added_time"],
395
395
  "provenance": (
396
396
  self.get_provenance_url(normalized, p["version"], p["filename"])
397
- if p["filename"] in provenances
397
+ if p["has_provenance"]
398
398
  else None
399
399
  ),
400
400
  }
@@ -9,7 +9,8 @@ from django.db.utils import IntegrityError
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
 
@@ -387,7 +388,7 @@ class PythonPackageContentSerializer(core_serializers.SingleArtifactContentUploa
387
388
  attestations = TypeAdapter(list[Attestation]).validate_json(value)
388
389
  else:
389
390
  attestations = TypeAdapter(list[Attestation]).validate_python(value)
390
- except ValidationError as e:
391
+ except PydanticValidationError as e:
391
392
  raise serializers.ValidationError(_("Invalid attestations: {}").format(e))
392
393
  return attestations
393
394
 
@@ -654,7 +655,7 @@ class PackageProvenanceSerializer(core_serializers.NoArtifactContentUploadSerial
654
655
  try:
655
656
  provenance = Provenance.model_validate_json(data["file"].read())
656
657
  data["provenance"] = provenance.model_dump(mode="json")
657
- except ValidationError as e:
658
+ except PydanticValidationError as e:
658
659
  raise serializers.ValidationError(
659
660
  _("The uploaded provenance is not valid: {}").format(e)
660
661
  )
@@ -1,8 +1,7 @@
1
1
  import asyncio
2
2
  import logging
3
3
  from functools import partial
4
- from gettext import gettext as _
5
- from urllib.parse import urljoin
4
+ from urllib.parse import urljoin, urlparse
6
5
 
7
6
  from aiohttp import ClientError, ClientResponseError
8
7
  from bandersnatch.configuration import BandersnatchConfig
@@ -12,9 +11,9 @@ from lxml.etree import LxmlError
12
11
  from packaging.requirements import Requirement
13
12
  from pypi_attestations import Provenance
14
13
  from pypi_simple import IndexPage
15
- from rest_framework import serializers
16
14
 
17
15
  from pulpcore.plugin.download import HttpDownloader
16
+ from pulpcore.plugin.exceptions import SyncError
18
17
  from pulpcore.plugin.models import Artifact, ProgressReport, Remote, Repository
19
18
  from pulpcore.plugin.stages import (
20
19
  DeclarativeArtifact,
@@ -23,6 +22,7 @@ from pulpcore.plugin.stages import (
23
22
  Stage,
24
23
  )
25
24
 
25
+ from pulp_python.app.exceptions import UnsupportedProtocolError
26
26
  from pulp_python.app.models import (
27
27
  PackageProvenance,
28
28
  PythonPackageContent,
@@ -45,14 +45,14 @@ def sync(remote_pk, repository_pk, mirror):
45
45
  mirror (boolean): True for mirror mode, False for additive mode.
46
46
 
47
47
  Raises:
48
- serializers: ValidationError
48
+ SyncError
49
49
 
50
50
  """
51
51
  remote = PythonRemote.objects.get(pk=remote_pk)
52
52
  repository = Repository.objects.get(pk=repository_pk)
53
53
 
54
54
  if not remote.url:
55
- raise serializers.ValidationError(detail=_("A remote must have a url attribute to sync."))
55
+ raise SyncError("A remote must have a url attribute to sync.")
56
56
 
57
57
  first_stage = PythonBanderStage(remote)
58
58
  DeclarativeVersion(first_stage, repository, mirror).create()
@@ -115,7 +115,8 @@ class PythonBanderStage(Stage):
115
115
  url = self.remote.url.rstrip("/")
116
116
  downloader = self.remote.get_downloader(url=url)
117
117
  if not isinstance(downloader, HttpDownloader):
118
- raise ValueError("Only HTTP(S) is supported for python syncing")
118
+ scheme = urlparse(url).scheme
119
+ raise UnsupportedProtocolError(scheme)
119
120
 
120
121
  async with Master(url, allow_non_https=True) as master:
121
122
  # Replace the session with the remote's downloader session
@@ -4,10 +4,13 @@ from datetime import datetime, timezone
4
4
  from django.contrib.sessions.models import Session
5
5
  from django.db import transaction
6
6
  from pydantic import TypeAdapter
7
+ from pydantic import ValidationError as PydanticValidationError
8
+ from pypi_attestations import AttestationError
7
9
 
8
10
  from pulpcore.plugin.models import Artifact, Content, ContentArtifact, CreatedResource
9
11
  from pulpcore.plugin.util import get_current_authenticated_user, get_domain, get_prn
10
12
 
13
+ from pulp_python.app.exceptions import AttestationVerificationError, InvalidAttestationsError
11
14
  from pulp_python.app.models import PackageProvenance, PythonPackageContent, PythonRepository
12
15
  from pulp_python.app.provenance import (
13
16
  AnyPublisher,
@@ -123,13 +126,19 @@ def create_provenance(package, attestations, domain):
123
126
  Returns:
124
127
  the newly created PackageProvenance
125
128
  """
126
- attestations = TypeAdapter(list[Attestation]).validate_python(attestations)
129
+ try:
130
+ attestations = TypeAdapter(list[Attestation]).validate_python(attestations)
131
+ except PydanticValidationError as e:
132
+ raise InvalidAttestationsError(str(e))
127
133
 
128
134
  user = get_current_authenticated_user()
129
135
  publisher = AnyPublisher(kind="Pulp User", prn=get_prn(user))
130
136
  att_bundle = AttestationBundle(publisher=publisher, attestations=attestations)
131
137
  provenance = Provenance(attestation_bundles=[att_bundle])
132
- verify_provenance(package.filename, package.sha256, provenance)
138
+ try:
139
+ verify_provenance(package.filename, package.sha256, provenance)
140
+ except AttestationError as e:
141
+ raise AttestationVerificationError(str(e))
133
142
  provenance_json = provenance.model_dump(mode="json")
134
143
 
135
144
  prov_sha256 = PackageProvenance.calculate_sha256(provenance_json)
@@ -11,7 +11,7 @@ from datetime import timezone
11
11
  import pkginfo
12
12
  from aiohttp.client_exceptions import ClientError
13
13
  from django.conf import settings
14
- from django.db.models import OuterRef, Subquery
14
+ from django.db.models import F, FilteredRelation, Q
15
15
  from django.db.utils import IntegrityError
16
16
  from jinja2 import Template
17
17
  from packaging.requirements import Requirement
@@ -20,7 +20,7 @@ from packaging.version import InvalidVersion, parse
20
20
  from pypi_simple import ACCEPT_JSON_PREFERRED, ProjectPage
21
21
 
22
22
  from pulpcore.plugin.exceptions import TimeoutException
23
- from pulpcore.plugin.models import Artifact, Remote, RepositoryContent
23
+ from pulpcore.plugin.models import Artifact, Remote
24
24
  from pulpcore.plugin.util import get_domain
25
25
 
26
26
  log = logging.getLogger(__name__)
@@ -375,12 +375,16 @@ def python_content_to_json(
375
375
  Returns None if version is specified but not found within content_query
376
376
  """
377
377
  if repository_version:
378
- repo_added_subquery = RepositoryContent.objects.filter(
379
- content_id=OuterRef("pk"),
380
- repository=repository_version.repository,
381
- version_removed=None,
382
- ).values("pulp_created")[:1]
383
- content_query = content_query.annotate(repo_added_time=Subquery(repo_added_subquery))
378
+ content_query = content_query.annotate(
379
+ active_membership=FilteredRelation(
380
+ "version_memberships",
381
+ condition=Q(
382
+ version_memberships__repository=repository_version.repository,
383
+ version_memberships__version_removed=None,
384
+ ),
385
+ ),
386
+ repo_added_time=F("active_membership__pulp_created"),
387
+ )
384
388
  full_metadata = {"last_serial": 0} # For now the serial field isn't supported by Pulp
385
389
  latest_content = latest_content_version(content_query, version)
386
390
  if not latest_content:
@@ -174,7 +174,10 @@ def test_domain_content_replication(
174
174
  pulpcore_bindings.UpstreamPulpsApi, upstream_pulp_body, pulp_domain=replica_domain.name
175
175
  )
176
176
  # Run the replicate task and assert that all tasks successfully complete.
177
- response = pulpcore_bindings.UpstreamPulpsApi.replicate(upstream_pulp.pulp_href)
177
+ response = pulpcore_bindings.UpstreamPulpsApi.replicate(
178
+ upstream_pulp.pulp_href,
179
+ upstream_pulp_replicate=pulpcore_bindings.module.UpstreamPulpReplicate(),
180
+ )
178
181
  monitor_task_group(response.task_group)
179
182
 
180
183
  counts = {}
@@ -198,7 +201,10 @@ def test_domain_content_replication(
198
201
  body = {"remote": remote.pulp_href}
199
202
  monitor_task(python_bindings.RepositoriesPythonApi.sync(repo.pulp_href, body).task)
200
203
 
201
- response = pulpcore_bindings.UpstreamPulpsApi.replicate(upstream_pulp.pulp_href)
204
+ response = pulpcore_bindings.UpstreamPulpsApi.replicate(
205
+ upstream_pulp.pulp_href,
206
+ upstream_pulp_replicate=pulpcore_bindings.module.UpstreamPulpReplicate(),
207
+ )
202
208
  monitor_task_group(response.task_group)
203
209
 
204
210
  response = python_bindings.ContentPackagesApi.list(pulp_domain=replica_domain.name)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pulp-python
3
- Version: 3.30.2
3
+ Version: 3.31.0
4
4
  Summary: pulp-python plugin for the Pulp Project
5
5
  Author-email: Pulp Team <pulp-list@redhat.com>
6
6
  Project-URL: Homepage, https://pulpproject.org
@@ -17,6 +17,7 @@ pulp_python.egg-info/entry_points.txt
17
17
  pulp_python.egg-info/requires.txt
18
18
  pulp_python.egg-info/top_level.txt
19
19
  pulp_python/app/__init__.py
20
+ pulp_python/app/exceptions.py
20
21
  pulp_python/app/global_access_conditions.py
21
22
  pulp_python/app/modelresource.py
22
23
  pulp_python/app/models.py
@@ -7,7 +7,7 @@ build-backend = 'setuptools.build_meta'
7
7
 
8
8
  [project]
9
9
  name = "pulp-python"
10
- version = "3.30.2"
10
+ version = "3.31.0"
11
11
  description = "pulp-python plugin for the Pulp Project"
12
12
  readme = "README.md"
13
13
  authors = [
@@ -79,7 +79,7 @@ ignore = [
79
79
  [tool.bumpversion]
80
80
  # This section is managed by the plugin template. Do not edit manually.
81
81
 
82
- current_version = "3.30.2"
82
+ current_version = "3.31.0"
83
83
  commit = false
84
84
  tag = false
85
85
  parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<alpha>0a)?(?P<patch>\\d+)(\\.(?P<release>[a-z]+))?"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes