pulp-python 3.27.2__py3-none-any.whl → 3.27.3__py3-none-any.whl

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 (39) hide show
  1. pulp_python/app/__init__.py +5 -3
  2. pulp_python/app/management/commands/repair-python-metadata.py +3 -2
  3. pulp_python/app/modelresource.py +1 -0
  4. pulp_python/app/models.py +9 -8
  5. pulp_python/app/pypi/serializers.py +7 -5
  6. pulp_python/app/pypi/views.py +40 -28
  7. pulp_python/app/replica.py +3 -2
  8. pulp_python/app/serializers.py +14 -13
  9. pulp_python/app/tasks/publish.py +2 -2
  10. pulp_python/app/tasks/repair.py +4 -2
  11. pulp_python/app/tasks/sync.py +13 -15
  12. pulp_python/app/tasks/upload.py +7 -6
  13. pulp_python/app/urls.py +2 -2
  14. pulp_python/app/utils.py +23 -9
  15. pulp_python/app/viewsets.py +2 -1
  16. pulp_python/pytest_plugin.py +8 -6
  17. pulp_python/tests/functional/api/test_attestations.py +2 -2
  18. pulp_python/tests/functional/api/test_consume_content.py +0 -1
  19. pulp_python/tests/functional/api/test_crud_content_unit.py +5 -4
  20. pulp_python/tests/functional/api/test_crud_publications.py +6 -5
  21. pulp_python/tests/functional/api/test_crud_remotes.py +3 -2
  22. pulp_python/tests/functional/api/test_domains.py +6 -5
  23. pulp_python/tests/functional/api/test_download_content.py +2 -2
  24. pulp_python/tests/functional/api/test_export_import.py +5 -3
  25. pulp_python/tests/functional/api/test_full_mirror.py +9 -9
  26. pulp_python/tests/functional/api/test_pypi_apis.py +48 -5
  27. pulp_python/tests/functional/api/test_pypi_simple_api.py +5 -6
  28. pulp_python/tests/functional/api/test_rbac.py +5 -4
  29. pulp_python/tests/functional/api/test_repair.py +2 -1
  30. pulp_python/tests/functional/api/test_sync.py +11 -11
  31. pulp_python/tests/functional/api/test_upload.py +5 -3
  32. pulp_python/tests/functional/constants.py +4 -0
  33. pulp_python/tests/functional/utils.py +2 -2
  34. {pulp_python-3.27.2.dist-info → pulp_python-3.27.3.dist-info}/METADATA +1 -1
  35. {pulp_python-3.27.2.dist-info → pulp_python-3.27.3.dist-info}/RECORD +39 -39
  36. {pulp_python-3.27.2.dist-info → pulp_python-3.27.3.dist-info}/WHEEL +0 -0
  37. {pulp_python-3.27.2.dist-info → pulp_python-3.27.3.dist-info}/entry_points.txt +0 -0
  38. {pulp_python-3.27.2.dist-info → pulp_python-3.27.3.dist-info}/licenses/LICENSE +0 -0
  39. {pulp_python-3.27.2.dist-info → pulp_python-3.27.3.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,8 @@
1
+ from gettext import gettext as _
2
+
1
3
  from django.db.models.signals import post_migrate
4
+
2
5
  from pulpcore.plugin import PulpPluginAppConfig
3
- from gettext import gettext as _
4
6
 
5
7
 
6
8
  class PulpPythonPluginAppConfig(PulpPluginAppConfig):
@@ -10,7 +12,7 @@ class PulpPythonPluginAppConfig(PulpPluginAppConfig):
10
12
 
11
13
  name = "pulp_python.app"
12
14
  label = "python"
13
- version = "3.27.2"
15
+ version = "3.27.3"
14
16
  python_package_name = "pulp-python"
15
17
  domain_compatible = True
16
18
 
@@ -26,7 +28,7 @@ class PulpPythonPluginAppConfig(PulpPluginAppConfig):
26
28
 
27
29
  # TODO: Remove this when https://github.com/pulp/pulpcore/issues/5500 is resolved
28
30
  def _populate_pypi_access_policies(sender, apps, verbosity, **kwargs):
29
- from pulp_python.app.pypi.views import PyPIView, SimpleView, UploadView, MetadataView
31
+ from pulp_python.app.pypi.views import MetadataView, PyPIView, SimpleView, UploadView
30
32
 
31
33
  try:
32
34
  AccessPolicy = apps.get_model("core", "AccessPolicy")
@@ -1,11 +1,12 @@
1
- import re
2
1
  import os
3
- from django.core.management import BaseCommand, CommandError
2
+ import re
4
3
  from gettext import gettext as _
5
4
 
6
5
  from django.conf import settings
6
+ from django.core.management import BaseCommand, CommandError
7
7
 
8
8
  from pulpcore.plugin.util import extract_pk
9
+
9
10
  from pulp_python.app.models import PythonPackageContent, PythonRepository
10
11
  from pulp_python.app.utils import artifact_to_python_content_data
11
12
 
@@ -1,6 +1,7 @@
1
1
  from pulpcore.plugin.importexport import BaseContentResource
2
2
  from pulpcore.plugin.modelresources import RepositoryResource
3
3
  from pulpcore.plugin.util import get_domain
4
+
4
5
  from pulp_python.app.models import (
5
6
  PythonPackageContent,
6
7
  PythonRepository,
pulp_python/app/models.py CHANGED
@@ -1,38 +1,39 @@
1
1
  import hashlib
2
2
  import json
3
3
  from logging import getLogger
4
+ from pathlib import PurePath
4
5
 
5
6
  from aiohttp.web import json_response
7
+ from django.conf import settings
6
8
  from django.contrib.postgres.fields import ArrayField
7
9
  from django.core.exceptions import ObjectDoesNotExist
8
10
  from django.db import models
9
- from django.conf import settings
10
11
  from django_lifecycle import (
11
12
  BEFORE_SAVE,
12
13
  hook,
13
14
  )
15
+
14
16
  from pulpcore.plugin.models import (
15
17
  AutoAddObjPermsMixin,
16
18
  Content,
17
- Publication,
18
19
  Distribution,
20
+ Publication,
19
21
  Remote,
20
22
  Repository,
21
23
  )
24
+ from pulpcore.plugin.repo_version_utils import remove_duplicates, validate_repo_version
22
25
  from pulpcore.plugin.responses import ArtifactResponse
26
+ from pulpcore.plugin.util import get_domain, get_domain_pk
23
27
 
24
- from pathlib import PurePath
25
28
  from .provenance import Provenance
26
29
  from .utils import (
27
- artifact_to_python_content_data,
30
+ PYPI_LAST_SERIAL,
31
+ PYPI_SERIAL_CONSTANT,
28
32
  artifact_to_metadata_artifact,
33
+ artifact_to_python_content_data,
29
34
  canonicalize_name,
30
35
  python_content_to_json,
31
- PYPI_LAST_SERIAL,
32
- PYPI_SERIAL_CONSTANT,
33
36
  )
34
- from pulpcore.plugin.repo_version_utils import remove_duplicates, validate_repo_version
35
- from pulpcore.plugin.util import get_domain_pk, get_domain
36
37
 
37
38
  log = getLogger(__name__)
38
39
 
@@ -1,13 +1,15 @@
1
1
  import logging
2
2
  from gettext import gettext as _
3
3
 
4
- from rest_framework import serializers
4
+ from django.db.utils import IntegrityError
5
5
  from pydantic import TypeAdapter, ValidationError
6
- from pulp_python.app.provenance import Attestation
7
- from pulp_python.app.utils import DIST_EXTENSIONS, SUPPORTED_METADATA_VERSIONS
6
+ from rest_framework import serializers
7
+
8
8
  from pulpcore.plugin.models import Artifact
9
9
  from pulpcore.plugin.util import get_domain
10
- from django.db.utils import IntegrityError
10
+
11
+ from pulp_python.app.provenance import Attestation
12
+ from pulp_python.app.utils import DIST_EXTENSIONS, SUPPORTED_METADATA_VERSIONS
11
13
 
12
14
  log = logging.getLogger(__name__)
13
15
 
@@ -110,7 +112,7 @@ class PackageUploadSerializer(serializers.Serializer):
110
112
  attestations = TypeAdapter(list[Attestation]).validate_python(attestations)
111
113
  except ValidationError as e:
112
114
  raise serializers.ValidationError(
113
- {"attestations": _("The uploaded attestations are not valid: {}".format(e))}
115
+ {"attestations": _("The uploaded attestations are not valid: {}").format(e)}
114
116
  )
115
117
 
116
118
  sha256 = data.get("sha256_digest")
@@ -1,60 +1,61 @@
1
1
  import logging
2
-
3
- from rest_framework.viewsets import ViewSet
4
- from rest_framework.renderers import BrowsableAPIRenderer, JSONRenderer, TemplateHTMLRenderer
5
- from rest_framework.response import Response
6
- from rest_framework.exceptions import NotAcceptable
7
- from django.core.exceptions import ObjectDoesNotExist
8
- from django.shortcuts import redirect
9
- from datetime import datetime, timezone, timedelta
2
+ from datetime import datetime, timedelta, timezone
3
+ from itertools import chain
4
+ from pathlib import PurePath
5
+ from urllib.parse import urljoin, urlparse, urlunsplit
10
6
 
11
7
  from django.contrib.sessions.models import Session
8
+ from django.core.exceptions import ObjectDoesNotExist
12
9
  from django.db import transaction
10
+ from django.db.models import OuterRef, Subquery
13
11
  from django.db.utils import DatabaseError
14
12
  from django.http.response import (
15
13
  Http404,
16
- HttpResponseNotFound,
17
- HttpResponseForbidden,
14
+ HttpResponse,
18
15
  HttpResponseBadRequest,
16
+ HttpResponseForbidden,
17
+ HttpResponseNotFound,
19
18
  StreamingHttpResponse,
20
- HttpResponse,
21
19
  )
20
+ from django.shortcuts import redirect
22
21
  from drf_spectacular.utils import extend_schema
23
22
  from dynaconf import settings
24
- from itertools import chain
25
23
  from packaging.utils import canonicalize_name
26
- from urllib.parse import urljoin, urlparse, urlunsplit
27
- from pathlib import PurePath
24
+ from rest_framework.exceptions import NotAcceptable
25
+ from rest_framework.renderers import BrowsableAPIRenderer, JSONRenderer, TemplateHTMLRenderer
26
+ from rest_framework.response import Response
27
+ from rest_framework.viewsets import ViewSet
28
28
 
29
- from pulpcore.plugin.viewsets import OperationPostponedResponse
29
+ from pulpcore.plugin.models import RepositoryContent
30
30
  from pulpcore.plugin.tasking import dispatch
31
31
  from pulpcore.plugin.util import get_domain, get_url
32
+ from pulpcore.plugin.viewsets import OperationPostponedResponse
33
+
34
+ from pulp_python.app import tasks
32
35
  from pulp_python.app.models import (
36
+ PackageProvenance,
33
37
  PythonDistribution,
34
38
  PythonPackageContent,
35
39
  PythonPublication,
36
- PackageProvenance,
37
40
  )
38
41
  from pulp_python.app.pypi.serializers import (
39
- SummarySerializer,
40
42
  PackageMetadataSerializer,
41
43
  PackageUploadSerializer,
42
44
  PackageUploadTaskSerializer,
45
+ SummarySerializer,
43
46
  )
44
47
  from pulp_python.app.utils import (
45
- write_simple_index,
46
- write_simple_index_json,
47
- write_simple_detail,
48
- write_simple_detail_json,
49
- python_content_to_json,
50
48
  PYPI_LAST_SERIAL,
51
49
  PYPI_SERIAL_CONSTANT,
52
50
  get_remote_package_filter,
53
51
  get_remote_simple_page,
52
+ python_content_to_json,
53
+ write_simple_detail,
54
+ write_simple_detail_json,
55
+ write_simple_index,
56
+ write_simple_index_json,
54
57
  )
55
58
 
56
- from pulp_python.app import tasks
57
-
58
59
  log = logging.getLogger(__name__)
59
60
 
60
61
  ORIGIN_HOST = settings.CONTENT_ORIGIN if settings.CONTENT_ORIGIN else settings.PYPI_API_HOSTNAME
@@ -362,13 +363,20 @@ class SimpleView(PackageUploadMixin, ViewSet):
362
363
  return redirect(urljoin(self.base_content_url, f"{path}/simple/{normalized}/"))
363
364
  if content:
364
365
  local_packages = content.filter(name__normalize=normalized)
365
- packages = local_packages.values(
366
+ repo_added_subquery = RepositoryContent.objects.filter(
367
+ content_id=OuterRef("pk"),
368
+ repository=repo_ver.repository,
369
+ version_removed=None,
370
+ ).values("pulp_created")[:1]
371
+ packages = local_packages.annotate(
372
+ repo_added_time=Subquery(repo_added_subquery)
373
+ ).values(
366
374
  "filename",
367
375
  "sha256",
368
376
  "metadata_sha256",
369
377
  "requires_python",
370
378
  "size",
371
- "pulp_created",
379
+ "repo_added_time",
372
380
  "version",
373
381
  )
374
382
  provenances = PackageProvenance.objects.filter(package__in=local_packages).values_list(
@@ -378,7 +386,7 @@ class SimpleView(PackageUploadMixin, ViewSet):
378
386
  p["filename"]: {
379
387
  **p,
380
388
  "url": urljoin(self.base_content_url, f"{path}/{p['filename']}"),
381
- "upload_time": p["pulp_created"],
389
+ "upload_time": p["repo_added_time"],
382
390
  "provenance": (
383
391
  self.get_provenance_url(normalized, p["version"], p["filename"])
384
392
  if p["filename"] in provenances
@@ -460,7 +468,11 @@ class MetadataView(PyPIMixin, ViewSet):
460
468
  if settings.DOMAIN_ENABLED:
461
469
  domain = get_domain()
462
470
  json_body = python_content_to_json(
463
- path, package_content, version=version, domain=domain
471
+ path,
472
+ package_content,
473
+ version=version,
474
+ domain=domain,
475
+ repository_version=repo_ver,
464
476
  )
465
477
  if json_body:
466
478
  return Response(data=json_body, headers=headers)
@@ -1,10 +1,11 @@
1
- from pulpcore.plugin.replica import Replicator
2
-
3
1
  from pulp_glue.python.context import (
4
2
  PulpPythonDistributionContext,
5
3
  PulpPythonPublicationContext,
6
4
  PulpPythonRepositoryContext,
7
5
  )
6
+
7
+ from pulpcore.plugin.replica import Replicator
8
+
8
9
  from pulp_python.app.models import PythonDistribution, PythonRemote, PythonRepository
9
10
  from pulp_python.app.tasks import sync as python_sync
10
11
 
@@ -2,25 +2,26 @@ import logging
2
2
  import os
3
3
  import tempfile
4
4
  from gettext import gettext as _
5
+
5
6
  from django.conf import settings
6
7
  from django.db.utils import IntegrityError
7
8
  from drf_spectacular.utils import extend_schema_serializer
8
9
  from packaging.requirements import Requirement
9
- from rest_framework import serializers
10
- from pypi_attestations import AttestationError
11
10
  from pydantic import TypeAdapter, ValidationError
11
+ from pypi_attestations import AttestationError
12
+ from rest_framework import serializers
12
13
 
13
14
  from pulpcore.plugin import models as core_models
14
15
  from pulpcore.plugin import serializers as core_serializers
15
- from pulpcore.plugin.util import get_domain, get_prn, get_current_authenticated_user
16
+ from pulpcore.plugin.util import get_current_authenticated_user, get_domain, get_prn
16
17
 
17
18
  from pulp_python.app import models as python_models
18
19
  from pulp_python.app.provenance import (
20
+ AnyPublisher,
19
21
  Attestation,
22
+ AttestationBundle,
20
23
  Provenance,
21
24
  verify_provenance,
22
- AttestationBundle,
23
- AnyPublisher,
24
25
  )
25
26
  from pulp_python.app.utils import (
26
27
  DIST_EXTENSIONS,
@@ -210,7 +211,7 @@ class PythonPackageContentSerializer(core_serializers.SingleArtifactContentUploa
210
211
  required=False,
211
212
  allow_blank=True,
212
213
  help_text=_(
213
- "The maintainer's name at a minimum; " "additional contact information may be provided."
214
+ "The maintainer's name at a minimum; additional contact information may be provided."
214
215
  ),
215
216
  )
216
217
  maintainer_email = serializers.CharField(
@@ -359,7 +360,7 @@ class PythonPackageContentSerializer(core_serializers.SingleArtifactContentUploa
359
360
  else:
360
361
  attestations = TypeAdapter(list[Attestation]).validate_python(value)
361
362
  except ValidationError as e:
362
- raise serializers.ValidationError(_("Invalid attestations: {}".format(e)))
363
+ raise serializers.ValidationError(_("Invalid attestations: {}").format(e))
363
364
  return attestations
364
365
 
365
366
  def handle_attestations(self, filename, sha256, attestations, offline=True):
@@ -372,7 +373,7 @@ class PythonPackageContentSerializer(core_serializers.SingleArtifactContentUploa
372
373
  verify_provenance(filename, sha256, provenance, offline=offline)
373
374
  except AttestationError as e:
374
375
  raise serializers.ValidationError(
375
- {"attestations": _("Attestations failed verification: {}".format(e))}
376
+ {"attestations": _("Attestations failed verification: {}").format(e)}
376
377
  )
377
378
  return provenance.model_dump(mode="json")
378
379
 
@@ -627,13 +628,13 @@ class PackageProvenanceSerializer(core_serializers.NoArtifactContentUploadSerial
627
628
  data["provenance"] = provenance.model_dump(mode="json")
628
629
  except ValidationError as e:
629
630
  raise serializers.ValidationError(
630
- _("The uploaded provenance is not valid: {}".format(e))
631
+ _("The uploaded provenance is not valid: {}").format(e)
631
632
  )
632
633
  if data.pop("verify"):
633
634
  try:
634
635
  verify_provenance(data["package"].filename, data["package"].sha256, provenance)
635
636
  except AttestationError as e:
636
- raise serializers.ValidationError(_("Provenance verification failed: {}".format(e)))
637
+ raise serializers.ValidationError(_("Provenance verification failed: {}").format(e))
637
638
  return data
638
639
 
639
640
  def retrieve(self, validated_data):
@@ -701,7 +702,7 @@ class PythonRemoteSerializer(core_serializers.RemoteSerializer):
701
702
  package_types = MultipleChoiceArrayField(
702
703
  required=False,
703
704
  help_text=_(
704
- "The package types to sync for Python content. Leave blank to get every" "package type."
705
+ "The package types to sync for Python content. Leave blank to get everypackage type."
705
706
  ),
706
707
  choices=python_models.PACKAGE_TYPES,
707
708
  default=list,
@@ -736,7 +737,7 @@ class PythonRemoteSerializer(core_serializers.RemoteSerializer):
736
737
  Requirement(pkg)
737
738
  except ValueError as ve:
738
739
  raise serializers.ValidationError(
739
- _("includes specifier {} is invalid. {}".format(pkg, ve))
740
+ _("includes specifier {} is invalid. {}").format(pkg, ve)
740
741
  )
741
742
  return value
742
743
 
@@ -747,7 +748,7 @@ class PythonRemoteSerializer(core_serializers.RemoteSerializer):
747
748
  Requirement(pkg)
748
749
  except ValueError as ve:
749
750
  raise serializers.ValidationError(
750
- _("excludes specifier {} is invalid. {}".format(pkg, ve))
751
+ _("excludes specifier {} is invalid. {}").format(pkg, ve)
751
752
  )
752
753
  return value
753
754
 
@@ -1,6 +1,6 @@
1
- from gettext import gettext as _
2
1
  import logging
3
2
  import os
3
+ from gettext import gettext as _
4
4
 
5
5
  from django.core.files import File
6
6
  from packaging.utils import canonicalize_name
@@ -10,7 +10,7 @@ from pulpcore.plugin.util import get_domain
10
10
 
11
11
  from pulp_python.app import models as python_models
12
12
  from pulp_python.app.serializers import PythonPublicationSerializer
13
- from pulp_python.app.utils import write_simple_index, write_simple_detail
13
+ from pulp_python.app.utils import write_simple_detail, write_simple_index
14
14
 
15
15
  log = logging.getLogger(__name__)
16
16
 
@@ -7,6 +7,10 @@ from uuid import UUID
7
7
 
8
8
  from django.db.models import Prefetch
9
9
  from django.db.models.query import QuerySet
10
+
11
+ from pulpcore.plugin.models import ContentArtifact, ProgressReport
12
+ from pulpcore.plugin.util import get_domain
13
+
10
14
  from pulp_python.app.models import PythonPackageContent, PythonRepository
11
15
  from pulp_python.app.utils import (
12
16
  artifact_to_python_content_data,
@@ -16,8 +20,6 @@ from pulp_python.app.utils import (
16
20
  metadata_content_to_artifact,
17
21
  parse_metadata,
18
22
  )
19
- from pulpcore.plugin.models import ContentArtifact, ProgressReport
20
- from pulpcore.plugin.util import get_domain
21
23
 
22
24
  log = logging.getLogger(__name__)
23
25
 
@@ -1,11 +1,17 @@
1
- import logging
2
1
  import asyncio
3
-
4
- from aiohttp import ClientResponseError, ClientError
5
- from lxml.etree import LxmlError
6
- from gettext import gettext as _
2
+ import logging
7
3
  from functools import partial
4
+ from gettext import gettext as _
5
+ from urllib.parse import urljoin
8
6
 
7
+ from aiohttp import ClientError, ClientResponseError
8
+ from bandersnatch.configuration import BandersnatchConfig
9
+ from bandersnatch.master import Master
10
+ from bandersnatch.mirror import Mirror
11
+ from lxml.etree import LxmlError
12
+ from packaging.requirements import Requirement
13
+ from pypi_attestations import Provenance
14
+ from pypi_simple import IndexPage
9
15
  from rest_framework import serializers
10
16
 
11
17
  from pulpcore.plugin.download import HttpDownloader
@@ -18,19 +24,11 @@ from pulpcore.plugin.stages import (
18
24
  )
19
25
 
20
26
  from pulp_python.app.models import (
27
+ PackageProvenance,
21
28
  PythonPackageContent,
22
29
  PythonRemote,
23
- PackageProvenance,
24
30
  )
25
- from pulp_python.app.utils import parse_metadata, PYPI_LAST_SERIAL, aget_remote_simple_page
26
- from pypi_simple import IndexPage
27
- from pypi_attestations import Provenance
28
-
29
- from bandersnatch.mirror import Mirror
30
- from bandersnatch.master import Master
31
- from bandersnatch.configuration import BandersnatchConfig
32
- from packaging.requirements import Requirement
33
- from urllib.parse import urljoin
31
+ from pulp_python.app.utils import PYPI_LAST_SERIAL, aget_remote_simple_page, parse_metadata
34
32
 
35
33
  logger = logging.getLogger(__name__)
36
34
 
@@ -1,17 +1,18 @@
1
1
  import time
2
-
3
2
  from datetime import datetime, timezone
4
- from django.db import transaction
3
+
5
4
  from django.contrib.sessions.models import Session
5
+ from django.db import transaction
6
6
  from pydantic import TypeAdapter
7
- from pulpcore.plugin.models import Artifact, CreatedResource, Content, ContentArtifact
8
- from pulpcore.plugin.util import get_domain, get_current_authenticated_user, get_prn
9
7
 
10
- from pulp_python.app.models import PythonPackageContent, PythonRepository, PackageProvenance
8
+ from pulpcore.plugin.models import Artifact, Content, ContentArtifact, CreatedResource
9
+ from pulpcore.plugin.util import get_current_authenticated_user, get_domain, get_prn
10
+
11
+ from pulp_python.app.models import PackageProvenance, PythonPackageContent, PythonRepository
11
12
  from pulp_python.app.provenance import (
13
+ AnyPublisher,
12
14
  Attestation,
13
15
  AttestationBundle,
14
- AnyPublisher,
15
16
  Provenance,
16
17
  verify_provenance,
17
18
  )
pulp_python/app/urls.py CHANGED
@@ -2,11 +2,11 @@ from django.conf import settings
2
2
  from django.urls import path
3
3
 
4
4
  from pulp_python.app.pypi.views import (
5
- SimpleView,
6
5
  MetadataView,
6
+ ProvenanceView,
7
7
  PyPIView,
8
+ SimpleView,
8
9
  UploadView,
9
- ProvenanceView,
10
10
  )
11
11
 
12
12
  if settings.DOMAIN_ENABLED:
pulp_python/app/utils.py CHANGED
@@ -1,23 +1,26 @@
1
1
  import hashlib
2
+ import json
2
3
  import logging
3
- import pkginfo
4
4
  import re
5
5
  import shutil
6
6
  import tempfile
7
7
  import zipfile
8
- import json
9
- from aiohttp.client_exceptions import ClientError
10
8
  from collections import defaultdict
11
9
  from datetime import timezone
10
+
11
+ import pkginfo
12
+ from aiohttp.client_exceptions import ClientError
12
13
  from django.conf import settings
14
+ from django.db.models import OuterRef, Subquery
13
15
  from django.db.utils import IntegrityError
14
16
  from jinja2 import Template
15
- from packaging.utils import canonicalize_name
16
17
  from packaging.requirements import Requirement
17
- from packaging.version import parse, InvalidVersion
18
+ from packaging.utils import canonicalize_name
19
+ from packaging.version import InvalidVersion, parse
18
20
  from pypi_simple import ACCEPT_JSON_PREFERRED, ProjectPage
19
- from pulpcore.plugin.models import Artifact, Remote
21
+
20
22
  from pulpcore.plugin.exceptions import TimeoutException
23
+ from pulpcore.plugin.models import Artifact, Remote, RepositoryContent
21
24
  from pulpcore.plugin.util import get_domain
22
25
 
23
26
  log = logging.getLogger(__name__)
@@ -357,7 +360,9 @@ def fetch_json_release_metadata(name: str, version: str, remotes: set[Remote]) -
357
360
  raise Exception(f"Failed to fetch {url} from any remote.")
358
361
 
359
362
 
360
- def python_content_to_json(base_path, content_query, version=None, domain=None):
363
+ def python_content_to_json(
364
+ base_path, content_query, version=None, domain=None, repository_version=None
365
+ ):
361
366
  """
362
367
  Converts a QuerySet of PythonPackageContent into the PyPi JSON format
363
368
  https://www.python.org/dev/peps/pep-0566/
@@ -369,6 +374,13 @@ def python_content_to_json(base_path, content_query, version=None, domain=None):
369
374
 
370
375
  Returns None if version is specified but not found within content_query
371
376
  """
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))
372
384
  full_metadata = {"last_serial": 0} # For now the serial field isn't supported by Pulp
373
385
  latest_content = latest_content_version(content_query, version)
374
386
  if not latest_content:
@@ -513,8 +525,10 @@ def python_content_to_download_info(content, base_path, domain=None):
513
525
  "python_version": content.python_version,
514
526
  "requires_python": content.requires_python or None,
515
527
  "size": content.size,
516
- "upload_time": str(content.pulp_created),
517
- "upload_time_iso_8601": str(content.pulp_created.isoformat()),
528
+ "upload_time": str(getattr(content, "repo_added_time", None) or content.pulp_created),
529
+ "upload_time_iso_8601": str(
530
+ (getattr(content, "repo_added_time", None) or content.pulp_created).isoformat()
531
+ ),
518
532
  "url": url,
519
533
  "yanked": False,
520
534
  "yanked_reason": None,
@@ -1,7 +1,8 @@
1
+ from pathlib import Path
2
+
1
3
  from bandersnatch.configuration import BandersnatchConfig
2
4
  from django.db import transaction
3
5
  from drf_spectacular.utils import extend_schema, extend_schema_view
4
- from pathlib import Path
5
6
  from rest_framework import status
6
7
  from rest_framework.decorators import action
7
8
  from rest_framework.response import Response
@@ -1,16 +1,18 @@
1
- import pytest
2
- import uuid
3
1
  import subprocess
2
+ import uuid
3
+
4
+ import pytest
4
5
 
5
6
  from pulpcore.tests.functional.utils import BindingsNamespace
7
+
6
8
  from pulp_python.tests.functional.constants import (
7
- PYTHON_FIXTURE_URL,
8
- PYTHON_XS_PROJECT_SPECIFIER,
9
9
  PYTHON_EGG_FILENAME,
10
- PYTHON_URL,
11
10
  PYTHON_EGG_URL,
12
- PYTHON_WHEEL_URL,
11
+ PYTHON_FIXTURE_URL,
12
+ PYTHON_URL,
13
13
  PYTHON_WHEEL_FILENAME,
14
+ PYTHON_WHEEL_URL,
15
+ PYTHON_XS_PROJECT_SPECIFIER,
14
16
  )
15
17
 
16
18
  # Bindings API Fixtures
@@ -1,11 +1,11 @@
1
- import pytest
2
1
  import json
3
- import requests
4
2
  import shutil
5
3
  import subprocess
6
4
  from pathlib import Path
7
5
  from urllib.parse import urljoin
8
6
 
7
+ import pytest
8
+ import requests
9
9
  from pypi_simple import PyPISimple
10
10
 
11
11
  from pulpcore.tests.functional.utils import PulpTaskError
@@ -1,5 +1,4 @@
1
1
  import subprocess
2
-
3
2
  from urllib.parse import urlsplit
4
3
 
5
4
 
@@ -1,14 +1,15 @@
1
- import pytest
2
-
3
1
  from urllib.parse import urljoin
2
+
3
+ import pytest
4
4
  from pypi_simple import PyPISimple
5
5
 
6
6
  from pulpcore.tests.functional.utils import PulpTaskError
7
+
7
8
  from pulp_python.tests.functional.constants import (
8
- PYTHON_FIXTURES_URL,
9
- PYTHON_PACKAGE_DATA,
10
9
  PYTHON_EGG_FILENAME,
11
10
  PYTHON_EGG_URL,
11
+ PYTHON_FIXTURES_URL,
12
+ PYTHON_PACKAGE_DATA,
12
13
  PYTHON_SM_FIXTURE_CHECKSUMS,
13
14
  PYTHON_WHEEL_FILENAME,
14
15
  PYTHON_WHEEL_URL,
@@ -1,13 +1,14 @@
1
- import pytest
2
1
  import random
3
- from pypi_simple import PyPISimple
4
2
  from urllib.parse import urljoin
5
3
 
4
+ import pytest
5
+ from pypi_simple import PyPISimple
6
+
6
7
  from pulp_python.tests.functional.constants import (
7
- PYTHON_SM_PROJECT_SPECIFIER,
8
- PYTHON_SM_FIXTURE_RELEASES,
9
- PYTHON_SM_FIXTURE_CHECKSUMS,
10
8
  PYTHON_EGG_FILENAME,
9
+ PYTHON_SM_FIXTURE_CHECKSUMS,
10
+ PYTHON_SM_FIXTURE_RELEASES,
11
+ PYTHON_SM_PROJECT_SPECIFIER,
11
12
  PYTHON_WHEEL_FILENAME,
12
13
  )
13
14
  from pulp_python.tests.functional.utils import ensure_simple
@@ -1,11 +1,12 @@
1
- import pytest
2
1
  import uuid
3
2
 
3
+ import pytest
4
+
4
5
  from pulp_python.tests.functional.constants import (
5
6
  BANDERSNATCH_CONF,
6
7
  DEFAULT_BANDER_REMOTE_BODY,
7
- PYTHON_INVALID_SPECIFIER_NO_NAME,
8
8
  PYTHON_INVALID_SPECIFIER_BAD_VERSION,
9
+ PYTHON_INVALID_SPECIFIER_NO_NAME,
9
10
  PYTHON_VALID_SPECIFIER_NO_VERSION,
10
11
  )
11
12
 
@@ -1,16 +1,17 @@
1
- import pytest
2
- import uuid
3
1
  import json
4
2
  import subprocess
3
+ import uuid
4
+ from urllib.parse import urlsplit
5
5
 
6
- from pulpcore.app import settings
6
+ import pytest
7
+
8
+ from pulpcore.app import settings # noqa: TID251
7
9
 
8
10
  from pulp_python.tests.functional.constants import (
9
11
  PYTHON_EGG_FILENAME,
10
- PYTHON_SM_PROJECT_SPECIFIER,
11
12
  PYTHON_SM_PACKAGE_COUNT,
13
+ PYTHON_SM_PROJECT_SPECIFIER,
12
14
  )
13
- from urllib.parse import urlsplit
14
15
 
15
16
  pytestmark = pytest.mark.skipif(not settings.DOMAIN_ENABLED, reason="Domain not enabled")
16
17
 
@@ -1,10 +1,10 @@
1
1
  import pytest
2
2
 
3
3
  from pulp_python.tests.functional.constants import (
4
- PYTHON_MD_PROJECT_SPECIFIER,
4
+ PYTHON_LG_PACKAGE_COUNT,
5
5
  PYTHON_LG_PROJECT_SPECIFIER,
6
6
  PYTHON_MD_PACKAGE_COUNT,
7
- PYTHON_LG_PACKAGE_COUNT,
7
+ PYTHON_MD_PROJECT_SPECIFIER,
8
8
  )
9
9
 
10
10
 
@@ -5,13 +5,15 @@ NOTE: assumes ALLOWED_EXPORT_PATHS setting contains "/tmp" - all tests will fail
5
5
  the case.
6
6
  """
7
7
 
8
- import pytest
9
8
  import uuid
10
9
 
11
- from pulpcore.app import settings
10
+ import pytest
11
+
12
+ from pulpcore.app import settings # noqa: TID251
13
+
12
14
  from pulp_python.tests.functional.constants import (
13
- PYTHON_XS_PROJECT_SPECIFIER,
14
15
  PYTHON_SM_PROJECT_SPECIFIER,
16
+ PYTHON_XS_PROJECT_SPECIFIER,
15
17
  )
16
18
 
17
19
  pytestmark = [
@@ -1,20 +1,20 @@
1
+ import subprocess
2
+ from hashlib import sha256
3
+ from random import sample
4
+ from urllib.parse import urljoin, urlsplit, urlunsplit
5
+
1
6
  import pytest
2
7
  import requests
3
- import subprocess
8
+ from packaging.version import parse
9
+ from pypi_simple import ProjectPage
4
10
 
5
11
  from pulp_python.tests.functional.constants import (
6
12
  PYPI_URL,
7
- PYTHON_XS_FIXTURE_CHECKSUMS,
8
- PYTHON_SM_PROJECT_SPECIFIER,
9
13
  PYTHON_SM_FIXTURE_RELEASES,
14
+ PYTHON_SM_PROJECT_SPECIFIER,
15
+ PYTHON_XS_FIXTURE_CHECKSUMS,
10
16
  )
11
17
 
12
- from pypi_simple import ProjectPage
13
- from packaging.version import parse
14
- from urllib.parse import urljoin, urlsplit, urlunsplit
15
- from random import sample
16
- from hashlib import sha256
17
-
18
18
 
19
19
  def test_pull_through_install(
20
20
  python_bindings, python_remote_factory, python_distribution_factory, delete_orphans_pre
@@ -1,18 +1,23 @@
1
- import pytest
2
- import requests
3
1
  import subprocess
4
-
2
+ import time
3
+ from datetime import datetime
5
4
  from urllib.parse import urljoin
6
5
 
6
+ import pytest
7
+ import requests
8
+
7
9
  from pulp_python.tests.functional.constants import (
8
10
  PYPI_SERIAL_CONSTANT,
9
- PYTHON_MD_PROJECT_SPECIFIER,
10
- PYTHON_MD_PYPI_SUMMARY,
11
+ PYPI_SIMPLE_V1_JSON,
11
12
  PYTHON_EGG_FILENAME,
12
13
  PYTHON_EGG_SHA256,
14
+ PYTHON_MD_PROJECT_SPECIFIER,
15
+ PYTHON_MD_PYPI_SUMMARY,
13
16
  PYTHON_WHEEL_FILENAME,
14
17
  PYTHON_WHEEL_SHA256,
15
18
  SHELF_PYTHON_JSON,
19
+ TWINE_WHEEL_FILENAME,
20
+ TWINE_WHEEL_URL,
16
21
  )
17
22
  from pulp_python.tests.functional.utils import ensure_metadata
18
23
 
@@ -328,3 +333,41 @@ def assert_download_info(expected, received, message="Failed to match"):
328
333
  matched = True
329
334
  break
330
335
  assert matched is True, message
336
+
337
+
338
+ @pytest.mark.parallel
339
+ def test_upload_time_reflects_repo_addition(
340
+ monitor_task,
341
+ python_bindings,
342
+ python_content_factory,
343
+ python_distribution_factory,
344
+ python_repo_factory,
345
+ ):
346
+ """
347
+ Test that upload_time reflects repository addition time instead of content creation time.
348
+ Checks both Simple and JSON APIs.
349
+ """
350
+ content = python_content_factory(TWINE_WHEEL_FILENAME, url=TWINE_WHEEL_URL)
351
+ content_created = datetime.fromisoformat(
352
+ str(python_bindings.ContentPackagesApi.read(content.pulp_href).pulp_created)
353
+ )
354
+ time.sleep(2)
355
+
356
+ repo = python_repo_factory()
357
+ body = {"add_content_units": [content.pulp_href]}
358
+ monitor_task(python_bindings.RepositoriesPythonApi.modify(repo.pulp_href, body).task)
359
+ distro = python_distribution_factory(repository=repo)
360
+
361
+ # Simple API
362
+ headers = {"Accept": PYPI_SIMPLE_V1_JSON}
363
+ resp = requests.get(f"{urljoin(distro.base_url, 'simple/')}twine", headers=headers)
364
+ assert resp.status_code == 200
365
+ simple_time = datetime.fromisoformat(resp.json()["files"][0]["upload-time"])
366
+ assert simple_time > content_created
367
+
368
+ # JSON API
369
+ json_resp = requests.get(urljoin(distro.base_url, "pypi/twine/json"))
370
+ assert json_resp.status_code == 200
371
+ json_time = datetime.fromisoformat(json_resp.json()["urls"][0]["upload_time"])
372
+ assert json_time > content_created
373
+ assert json_time == simple_time
@@ -5,6 +5,9 @@ import requests
5
5
 
6
6
  from pulp_python.tests.functional.constants import (
7
7
  PYPI_SERIAL_CONSTANT,
8
+ PYPI_SIMPLE_V1_HTML,
9
+ PYPI_SIMPLE_V1_JSON,
10
+ PYPI_TEXT_HTML,
8
11
  PYTHON_SM_FIXTURE_CHECKSUMS,
9
12
  PYTHON_SM_FIXTURE_RELEASES,
10
13
  PYTHON_SM_PROJECT_SPECIFIER,
@@ -27,10 +30,6 @@ from pulp_python.tests.functional.utils import ensure_simple
27
30
 
28
31
  API_VERSION = "1.1"
29
32
 
30
- PYPI_TEXT_HTML = "text/html"
31
- PYPI_SIMPLE_V1_HTML = "application/vnd.pypi.simple.v1+html"
32
- PYPI_SIMPLE_V1_JSON = "application/vnd.pypi.simple.v1+json"
33
-
34
33
 
35
34
  @pytest.mark.parallel
36
35
  def test_simple_html_index_api(
@@ -69,7 +68,7 @@ def test_simple_html_detail_api(
69
68
  monitor_task(python_bindings.RepositoriesPythonApi.modify(repo.pulp_href, body).task)
70
69
  distro = python_distribution_factory(repository=repo)
71
70
 
72
- url = f'{urljoin(distro.base_url, "simple/")}twine'
71
+ url = f"{urljoin(distro.base_url, 'simple/')}twine"
73
72
  headers = {"Accept": PYPI_SIMPLE_V1_HTML}
74
73
 
75
74
  response = requests.get(url, headers=headers)
@@ -125,7 +124,7 @@ def test_simple_json_detail_api(
125
124
  monitor_task(python_bindings.RepositoriesPythonApi.modify(repo.pulp_href, body).task)
126
125
  distro = python_distribution_factory(repository=repo)
127
126
 
128
- url = f'{urljoin(distro.base_url, "simple/")}twine'
127
+ url = f"{urljoin(distro.base_url, 'simple/')}twine"
129
128
  headers = {"Accept": PYPI_SIMPLE_V1_JSON}
130
129
 
131
130
  response = requests.get(url, headers=headers)
@@ -1,6 +1,7 @@
1
- import pytest
2
1
  import uuid
3
2
 
3
+ import pytest
4
+
4
5
  from pulp_python.tests.functional.constants import (
5
6
  PYTHON_EGG_FILENAME,
6
7
  PYTHON_EGG_SHA256,
@@ -44,9 +45,9 @@ def try_action(python_bindings, monitor_task):
44
45
  except python_bindings.module.ApiException as e:
45
46
  assert e.status == outcome, f"{e}"
46
47
  else:
47
- assert (
48
- status_code == outcome
49
- ), f"User performed {action} when they shouldn't been able to"
48
+ assert status_code == outcome, (
49
+ f"User performed {action} when they shouldn't been able to"
50
+ )
50
51
  return data
51
52
 
52
53
  return _try_action
@@ -1,7 +1,8 @@
1
- import pytest
2
1
  import subprocess
3
2
  from urllib.parse import urljoin
4
3
 
4
+ import pytest
5
+
5
6
  from pulp_python.tests.functional.constants import (
6
7
  PYTHON_EGG_FILENAME,
7
8
  PYTHON_FIXTURES_URL,
@@ -1,21 +1,21 @@
1
1
  import pytest
2
2
 
3
3
  from pulp_python.tests.functional.constants import (
4
- PYTHON_XS_PACKAGE_COUNT,
5
- PYTHON_PRERELEASE_TEST_SPECIFIER,
6
- PYTHON_WITH_PRERELEASE_COUNT,
7
- PYTHON_WITHOUT_PRERELEASE_COUNT,
8
- PYTHON_XS_PROJECT_SPECIFIER,
9
- PYTHON_MD_PROJECT_SPECIFIER,
4
+ DJANGO_LATEST_3,
5
+ PYTHON_LG_FIXTURE_COUNTS,
6
+ PYTHON_LG_PACKAGE_COUNT,
7
+ PYTHON_LG_PROJECT_SPECIFIER,
10
8
  PYTHON_MD_PACKAGE_COUNT,
11
- PYTHON_SM_PROJECT_SPECIFIER,
9
+ PYTHON_MD_PROJECT_SPECIFIER,
10
+ PYTHON_PRERELEASE_TEST_SPECIFIER,
12
11
  PYTHON_SM_PACKAGE_COUNT,
12
+ PYTHON_SM_PROJECT_SPECIFIER,
13
13
  PYTHON_UNAVAILABLE_PACKAGE_COUNT,
14
14
  PYTHON_UNAVAILABLE_PROJECT_SPECIFIER,
15
- PYTHON_LG_PROJECT_SPECIFIER,
16
- PYTHON_LG_PACKAGE_COUNT,
17
- PYTHON_LG_FIXTURE_COUNTS,
18
- DJANGO_LATEST_3,
15
+ PYTHON_WITH_PRERELEASE_COUNT,
16
+ PYTHON_WITHOUT_PRERELEASE_COUNT,
17
+ PYTHON_XS_PACKAGE_COUNT,
18
+ PYTHON_XS_PROJECT_SPECIFIER,
19
19
  SCIPY_COUNTS,
20
20
  )
21
21
  from pulp_python.tests.functional.utils import ensure_metadata
@@ -1,16 +1,18 @@
1
+ from urllib.parse import urljoin
2
+
1
3
  import pytest
2
4
  import requests
5
+
3
6
  from pulp_python.tests.functional.constants import (
4
7
  PYTHON_EGG_FILENAME,
8
+ PYTHON_EGG_SHA256,
5
9
  PYTHON_EGG_URL,
6
10
  PYTHON_FIXTURES_URL,
7
11
  PYTHON_WHEEL_FILENAME,
8
- PYTHON_WHEEL_URL,
9
- PYTHON_EGG_SHA256,
10
12
  PYTHON_WHEEL_SHA256,
13
+ PYTHON_WHEEL_URL,
11
14
  )
12
15
  from pulp_python.tests.functional.utils import ensure_metadata
13
- from urllib.parse import urljoin
14
16
 
15
17
 
16
18
  @pytest.mark.parametrize(
@@ -382,3 +382,7 @@ VULNERABILITY_REPORT_TEST_PACKAGES = [
382
382
  ]
383
383
 
384
384
  PYPI_SERIAL_CONSTANT = 1000000000
385
+
386
+ PYPI_TEXT_HTML = "text/html"
387
+ PYPI_SIMPLE_V1_HTML = "application/vnd.pypi.simple.v1+html"
388
+ PYPI_SIMPLE_V1_JSON = "application/vnd.pypi.simple.v1+json"
@@ -1,6 +1,6 @@
1
- import requests
2
-
3
1
  from urllib.parse import urljoin
2
+
3
+ import requests
4
4
  from lxml import html
5
5
 
6
6
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pulp-python
3
- Version: 3.27.2
3
+ Version: 3.27.3
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
@@ -1,19 +1,19 @@
1
1
  pulp_python/__init__.py,sha256=GIuTLoBTc-07dSLJUh8xrZPRz8x-jJ61pfR0J1IjnzI,65
2
- pulp_python/pytest_plugin.py,sha256=EBivPJa39ZE1QaDWea9candeeJL_W_cBk6Q7Onhw4bE,8604
3
- pulp_python/app/__init__.py,sha256=6t82RCPUBUunBDp9wK3Rg12nnTglsi0JTYE_9jdyUik,2488
2
+ pulp_python/pytest_plugin.py,sha256=LNnLjOkeEu2X4gJi614bHVmbsHyEwooHYIeecr96Qy4,8606
3
+ pulp_python/app/__init__.py,sha256=FR3rXdqMB5fAFWr2iBu0QMdEckieNzR_YRsIaRNb3EU,2490
4
4
  pulp_python/app/global_access_conditions.py,sha256=MZJtyoVsr-4hRaty6mKDqh3caOHd5UKJjEWLV2crOLs,1080
5
- pulp_python/app/modelresource.py,sha256=dogoBWibBmQyFpcV-Hp1lu7D2WwSECa5PEShWSIg7mg,1248
6
- pulp_python/app/models.py,sha256=j2U__78AMhyYIiRKyA_o5_55EvqkZSJVh4QWmpGtX-A,14055
5
+ pulp_python/app/modelresource.py,sha256=4SFAdqk6lozi_cZz4uqDIqhqPAZF-7l5jJwPn-xGZFs,1249
6
+ pulp_python/app/models.py,sha256=VVyr8LjAtHeHvY6klFeokwHNnY90qUuMchalm-2Gtjk,14056
7
7
  pulp_python/app/provenance.py,sha256=iyhkuNahHiTDK0Djrd4-PlgErA5SJVI0uQOIPj46tEI,2352
8
- pulp_python/app/replica.py,sha256=W60Kt9CwZSfztRi3-f82Rfp0F_zhzpOTiz35bvRFBBE,1881
9
- pulp_python/app/serializers.py,sha256=ItjeHJ1qRN7dYvpxSJAdRUMJ6JsjvHoI_so4zhkTvkI,28674
8
+ pulp_python/app/replica.py,sha256=qiWRP7tM_v4yP_XLIQfumfGolru-Jt6ZA0KVb-9g2cA,1882
9
+ pulp_python/app/serializers.py,sha256=8RpEeRSCLLD5rMd-Pz8fTXCglYmwDUWZNySGh6P3JuA,28669
10
10
  pulp_python/app/settings.py,sha256=HXJK3rr0LVTOv1xBS5cZvVtz6j4SvFZl0PH3sLTcu2w,227
11
- pulp_python/app/urls.py,sha256=dw6SQ7N6SIxHALAjTdGg3dPL3-54MVoDzUKfqXA2epI,1328
12
- pulp_python/app/utils.py,sha256=2MEHK_fuLpZA9w4ohbhcs1D2ii478gwW_iAuSTsu-kw,26740
13
- pulp_python/app/viewsets.py,sha256=-UgY6uySh5TVLMv_p0dAeJQIRs9SIOrfFORFMGj9N8o,28439
11
+ pulp_python/app/urls.py,sha256=NuNnyGc0lqa2HPtMpCpqJlMA0Hi4htOtZO_i8YPCc3k,1328
12
+ pulp_python/app/utils.py,sha256=f9sCzZ58Sf7EBNqzBG0NBGtWE6gE2eIcnoSTAhdVIIg,27303
13
+ pulp_python/app/viewsets.py,sha256=R0vJSI-G9WBvaVPXdtBgTTlvddN_MFwoRUtWFwqBsaQ,28440
14
14
  pulp_python/app/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  pulp_python/app/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- pulp_python/app/management/commands/repair-python-metadata.py,sha256=i-mC3UYxIiHJoknRV4xZZ7cQ44lyqWshpbaeYi7as8E,4457
16
+ pulp_python/app/management/commands/repair-python-metadata.py,sha256=oYPPRy5GeT6DhADvJCs8r3YgCy-s_sCveuktZt_oHVY,4458
17
17
  pulp_python/app/migrations/0001_initial.py,sha256=xbEeZoLAUhdVrySf22Uz-e9Jm32rbY_HjxuNcEar6EE,6843
18
18
  pulp_python/app/migrations/0001_squashed_0010_update_json_field.py,sha256=hFo1OD0JS_vn8bl49nF3Qz9QZBkVc5uDdNRnporvuyY,10455
19
19
  pulp_python/app/migrations/0002_pythonpackagecontent_python_version.py,sha256=2WMNRVfjbkVfI_cTu8VNQRlPXK4n-JuFRsBZFcm04AE,427
@@ -36,46 +36,46 @@ pulp_python/app/migrations/0018_packageprovenance.py,sha256=FU67aw6u77TjlPuzxRrR
36
36
  pulp_python/app/migrations/0019_create_missing_metadata_artifacts.py,sha256=glHecwu0X17RdRHo1MvjDRvrqpJ7EgxvYXy1FOXJvn4,817
37
37
  pulp_python/app/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
38
  pulp_python/app/pypi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
- pulp_python/app/pypi/serializers.py,sha256=w6_doLpaO8Dnzur57MYrTIqEP4I3LI8biu9ipLC66fk,5028
40
- pulp_python/app/pypi/views.py,sha256=ksQflLQSwcsmoJtQG6B440rQ8CPF_bSTdWXpYJFEAg4,21006
39
+ pulp_python/app/pypi/serializers.py,sha256=rE0Cci2IMg4NbNWlVdo-8zPaJCAUq2Re57q_T3jMt0Y,5030
40
+ pulp_python/app/pypi/views.py,sha256=4WdfY7HSLd4nfs3DQGcUiXfOxT20LfdEIrZvc9uIwm4,21530
41
41
  pulp_python/app/tasks/__init__.py,sha256=lTFpVvpDKbqv9RC0b2RYU8Bo6svDjrA-djt16pADFr8,284
42
- pulp_python/app/tasks/publish.py,sha256=Z3kWz22bKNXk2j-k1OgwOTEYcgzDzckYQjRo2hItnTA,4334
43
- pulp_python/app/tasks/repair.py,sha256=KQzVhdtjcfFTCco9zk_iETfVETsUqQJSvMV4OBOd7es,12255
44
- pulp_python/app/tasks/sync.py,sha256=hBA4iyY9HFbLZMFWqVJ4W3Q3NAN122QVaOSEGSSnMtc,12868
45
- pulp_python/app/tasks/upload.py,sha256=12E9ihDqbe9Ihij9o6p_yuV6WF1Yyt6zPeOI2dzCEms,5697
42
+ pulp_python/app/tasks/publish.py,sha256=EMAfOZH8EFB9A-rzuxjrQG5FnvSXBVGT7dHQGCAUtrM,4334
43
+ pulp_python/app/tasks/repair.py,sha256=5InzdbjW8y3AC4Vj2PsNLm3wGGTr8D3LcfPw_WA2Fks,12257
44
+ pulp_python/app/tasks/sync.py,sha256=LqGQsiSbOQl05H9e7PC830aaLDuQXS1Ql1GiwfrO1Qc,12866
45
+ pulp_python/app/tasks/upload.py,sha256=Pclsh6co5hBO6wdxZbGKBUSBV643nd9c2RXQO2Nkdik,5698
46
46
  pulp_python/app/tasks/vulnerability_report.py,sha256=0cyxNb4048HFUdUlGBA6wYsg-hEMjSfE8mtw05Ct9BQ,1126
47
47
  pulp_python/app/webserver_snippets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
48
  pulp_python/app/webserver_snippets/apache.conf,sha256=3frHSl2YV_8pJPscaFxMVo7HmxGJdb8XVmfdLtCxzoA,97
49
49
  pulp_python/app/webserver_snippets/nginx.conf,sha256=gMqZGFefsTJVVx9YRxpHVS7NMEll9CzOseYdtLr3Avc,344
50
50
  pulp_python/tests/__init__.py,sha256=4Yz43a8s-KyhdHFb5eEhIIvH72807Y84uAHnG5bO5y0,31
51
51
  pulp_python/tests/functional/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
- pulp_python/tests/functional/constants.py,sha256=SvzlxGQz1I-p3JEBSqNz9qoAYfq5yhGsqtYoJpCOioU,13819
53
- pulp_python/tests/functional/utils.py,sha256=ZmOVSa94o0KvH7l42YwuUAcNJo8Eb733QBH2G6nGkeQ,5901
52
+ pulp_python/tests/functional/constants.py,sha256=4e_zssE9G1bSNNJxYo7VgwvojUL_NocG5mUH996KBJs,13969
53
+ pulp_python/tests/functional/utils.py,sha256=GWnXrsQGZd0Ngewa_9yce58Qc3z7FbrlRvqao_8ZML0,5901
54
54
  pulp_python/tests/functional/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
- pulp_python/tests/functional/api/test_attestations.py,sha256=_opUZT65c5H2j_8ous-nKGHmDOw8EMjxdooTIQhiXQ8,8640
55
+ pulp_python/tests/functional/api/test_attestations.py,sha256=cyZl4jCL-Q5Qu7XpxLc5_YmCzyc1Ctfl1IvSJ6YPQQU,8640
56
56
  pulp_python/tests/functional/api/test_auto_publish.py,sha256=uCIt4LsO61oMk3bDs3LMQDJI8zkKqvY0b1uX16bTxzM,1747
57
- pulp_python/tests/functional/api/test_consume_content.py,sha256=QUOZ_bQ_Ortzitc7sjlMEJzRhPm00wayxjZvEeK18jI,1000
58
- pulp_python/tests/functional/api/test_crud_content_unit.py,sha256=GbCDRY5iaLSRvPAvhz1a3mrYu_WN2lOEnFLltT6yL54,8756
59
- pulp_python/tests/functional/api/test_crud_publications.py,sha256=uoTGHbhKq_mYOYtNV8Tt9cyhzY0zsoG1DhYrfIdYcMc,5646
60
- pulp_python/tests/functional/api/test_crud_remotes.py,sha256=uRo51X3MDWIls4Fdxw5unvU47_JyyLEg2w41ByvDcmY,5811
61
- pulp_python/tests/functional/api/test_domains.py,sha256=owbvFxOKDuAVX2PUpsO0olAmQmIKFThBqnQtjfKbS8Y,10210
62
- pulp_python/tests/functional/api/test_download_content.py,sha256=msnsKpU6TGT8eNu6e0uFa4fte6hj85OTexwOHdf66-c,4950
63
- pulp_python/tests/functional/api/test_export_import.py,sha256=QciJ7Pdv6HSv3mKGqKSNW5g9M8e9tkWcapRQ1PUxabU,4512
64
- pulp_python/tests/functional/api/test_full_mirror.py,sha256=npBj0IR10JUmjZyBY99NAGc8t5Xjbzl-y__69X9Eh1E,12045
65
- pulp_python/tests/functional/api/test_pypi_apis.py,sha256=sdovsmCb88aDaEqTe_RKXiBJDaAx5BRRaT1oNPbIAfo,11691
66
- pulp_python/tests/functional/api/test_pypi_simple_api.py,sha256=UzO3K3GMqiDUsAMWlxy9xM3kYtnD6e2WYNtwlJWYm-U,7251
67
- pulp_python/tests/functional/api/test_rbac.py,sha256=cy1RQHvWKbE4f4aPu33ZdIUBiJBnW8aOXKlDHHcCuxo,10512
68
- pulp_python/tests/functional/api/test_repair.py,sha256=8tW4jgR4pAsAswsblZM2NKdGAKnh1zuH7572k2GO4ag,12908
69
- pulp_python/tests/functional/api/test_sync.py,sha256=a9bSHFesOnh0Pvc9KCNSUw0ghIlEWdIvXhVw7gSRG2Y,13801
70
- pulp_python/tests/functional/api/test_upload.py,sha256=zd-qRwjGDuEazLZeVgeZqLbz6Lhd8jdOyS1K5QB0PDE,5877
57
+ pulp_python/tests/functional/api/test_consume_content.py,sha256=-7b6KOrIT3NLSUafeu1tzXEXRPddDbS5VeMHxMIy2n8,999
58
+ pulp_python/tests/functional/api/test_crud_content_unit.py,sha256=Pwjv3ytSfqBuoemuhJNIOEWdwzurPVN1XO3kDRlLFqY,8757
59
+ pulp_python/tests/functional/api/test_crud_publications.py,sha256=3cuSDC9C9M1opt0lh5ObGj8t7gq5jUW-RWj6MrA4Teo,5647
60
+ pulp_python/tests/functional/api/test_crud_remotes.py,sha256=clFFhgG5udyKzWOLwxpmwjhiVz8r5JEPAQHkztcAf9w,5812
61
+ pulp_python/tests/functional/api/test_domains.py,sha256=BnWBwid_RA0xenBBHwvkT5_23RPe19DjQCICdMWad3w,10227
62
+ pulp_python/tests/functional/api/test_download_content.py,sha256=5IuaHXyLakPkjm5sLTxtTl7Dq0yl7N36HpObnIa0Sks,4950
63
+ pulp_python/tests/functional/api/test_export_import.py,sha256=rHns9wdaeP-vtfW_qoGHU9EVuJ4YuWE0-rjl_8otAgU,4530
64
+ pulp_python/tests/functional/api/test_full_mirror.py,sha256=eU5HzgBBFOnX1q4m8ELx-t-I3U4TWXL-LNrlc2BcWVc,12045
65
+ pulp_python/tests/functional/api/test_pypi_apis.py,sha256=mhST0GV-uDrVPsBWYRGaJx1pp9htzbYiUGuIGOI0s_s,13218
66
+ pulp_python/tests/functional/api/test_pypi_simple_api.py,sha256=tOUl8WXgJkMoxGyLbA-WorCxIRKfGWM-27_dK_Jc0Q4,7171
67
+ pulp_python/tests/functional/api/test_rbac.py,sha256=-xNWqvKKU-v1uC6tCRGBK0aWaff25K9C-AfzQkdHhhI,10513
68
+ pulp_python/tests/functional/api/test_repair.py,sha256=4FR7jx_LA2K-pnRJXKkhq-1uUoWXST1leZ9XdyhGM2U,12909
69
+ pulp_python/tests/functional/api/test_sync.py,sha256=TTHR1CpZeRoD97RKxj2pZPsP0OS9ibYKGPOh1WfKISg,13801
70
+ pulp_python/tests/functional/api/test_upload.py,sha256=PZ0HK7UU9gvxNaRlB_EAY1-pcghDtx22DMGk5C1oM2I,5879
71
71
  pulp_python/tests/functional/api/test_vulnerability_report.py,sha256=Rv492Wrvu1FY7O_moo9DTB6OkI-OZURj_fuTKbENLh8,1730
72
72
  pulp_python/tests/functional/assets/shelf-reader-0.1.tar.gz.publish.attestation,sha256=_Ygrz7523z55s4uPmQWYxF29jr0NqJxVm_d-Z8KvrZ0,10363
73
73
  pulp_python/tests/functional/assets/shelf_reader-0.1-py2-none-any.whl.publish.attestation,sha256=muTQ8dqYSSdx76DlaPjB1REcNIS-aak-Na0TkASxu8M,10426
74
74
  pulp_python/tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
75
  pulp_python/tests/unit/test_models.py,sha256=TBI0yKsrdbnJSPeBFfxSqhXK7zaNvR6qg5JehGH3Pds,229
76
- pulp_python-3.27.2.dist-info/licenses/LICENSE,sha256=2ylvL381vKOhdO-w6zkrOxe9lLNBhRQpo9_0EbHC_HM,18046
77
- pulp_python-3.27.2.dist-info/METADATA,sha256=x1jBFDn5orYv_arddsXzAQcV9OJ3Ol1hIGt1cgmXrto,1743
78
- pulp_python-3.27.2.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
79
- pulp_python-3.27.2.dist-info/entry_points.txt,sha256=HvqLEXjw_dS5jqAwnE5JiRZFE6f-y5SRtitKLPml2To,115
80
- pulp_python-3.27.2.dist-info/top_level.txt,sha256=X0hXgXc_bpbiKqVrkt8jD5_QEiQviKbHDwveQcOcJjo,12
81
- pulp_python-3.27.2.dist-info/RECORD,,
76
+ pulp_python-3.27.3.dist-info/licenses/LICENSE,sha256=2ylvL381vKOhdO-w6zkrOxe9lLNBhRQpo9_0EbHC_HM,18046
77
+ pulp_python-3.27.3.dist-info/METADATA,sha256=_nH8PqkU8tHJnd3IHYRVFHo_DfX34sFOjgipyPLbF7o,1743
78
+ pulp_python-3.27.3.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
79
+ pulp_python-3.27.3.dist-info/entry_points.txt,sha256=HvqLEXjw_dS5jqAwnE5JiRZFE6f-y5SRtitKLPml2To,115
80
+ pulp_python-3.27.3.dist-info/top_level.txt,sha256=X0hXgXc_bpbiKqVrkt8jD5_QEiQviKbHDwveQcOcJjo,12
81
+ pulp_python-3.27.3.dist-info/RECORD,,