pulp-python 3.27.2__tar.gz → 3.27.3__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.
- {pulp_python-3.27.2 → pulp_python-3.27.3}/CHANGES.md +9 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/PKG-INFO +1 -1
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/__init__.py +5 -3
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/management/commands/repair-python-metadata.py +3 -2
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/modelresource.py +1 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/models.py +9 -8
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/pypi/serializers.py +7 -5
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/pypi/views.py +40 -28
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/replica.py +3 -2
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/serializers.py +14 -13
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/tasks/publish.py +2 -2
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/tasks/repair.py +4 -2
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/tasks/sync.py +13 -15
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/tasks/upload.py +7 -6
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/utils.py +23 -9
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/viewsets.py +2 -1
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/pytest_plugin.py +8 -6
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/test_consume_content.py +0 -1
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/test_crud_content_unit.py +5 -4
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/test_crud_publications.py +6 -5
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/test_crud_remotes.py +3 -2
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/test_domains.py +6 -5
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/test_export_import.py +5 -3
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/test_pypi_apis.py +48 -5
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/test_pypi_simple_api.py +5 -6
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/test_rbac.py +5 -4
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/test_repair.py +2 -1
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/test_upload.py +5 -3
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/constants.py +4 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python.egg-info/PKG-INFO +1 -1
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pyproject.toml +31 -2
- {pulp_python-3.27.2 → pulp_python-3.27.3}/COMMITMENT +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/COPYRIGHT +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/LICENSE +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/MANIFEST.in +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/README.md +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/functest_requirements.txt +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/__init__.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/global_access_conditions.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/management/__init__.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/management/commands/__init__.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0001_initial.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0001_squashed_0010_update_json_field.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0002_pythonpackagecontent_python_version.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0003_new_sync_filters.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0004_DATA_swap_distribution_model.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0005_pythonpackagecontent_sha256.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0006_pythonrepository_autopublish.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0007_pythonpackagecontent_mv-2-1.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0008_pythonpackagecontent_unique_sha256.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0009_pythondistribution_allow_uploads.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0010_update_json_field.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0011_alter_pythondistribution_distribution_ptr_and_more.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0012_add_domain.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0013_add_rbac_permissions.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0014_pythonpackagecontent_dynamic_and_more.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0015_alter_pythonpackagecontent_options.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0016_pythonpackagecontent_metadata_sha256.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0017_pythonpackagecontent_size.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0018_packageprovenance.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/0019_create_missing_metadata_artifacts.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/migrations/__init__.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/provenance.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/pypi/__init__.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/settings.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/tasks/__init__.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/tasks/vulnerability_report.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/urls.py +2 -2
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/webserver_snippets/__init__.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/webserver_snippets/apache.conf +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/app/webserver_snippets/nginx.conf +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/__init__.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/__init__.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/__init__.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/test_attestations.py +2 -2
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/test_auto_publish.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/test_download_content.py +2 -2
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/test_full_mirror.py +9 -9
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/test_sync.py +11 -11
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/test_vulnerability_report.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/assets/shelf-reader-0.1.tar.gz.publish.attestation +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/assets/shelf_reader-0.1-py2-none-any.whl.publish.attestation +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/utils.py +2 -2
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/unit/__init__.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/unit/test_models.py +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python.egg-info/SOURCES.txt +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python.egg-info/dependency_links.txt +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python.egg-info/entry_points.txt +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python.egg-info/requires.txt +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python.egg-info/top_level.txt +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/setup.cfg +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/test_requirements.txt +0 -0
- {pulp_python-3.27.2 → pulp_python-3.27.3}/unittest_requirements.txt +0 -0
|
@@ -8,6 +8,15 @@
|
|
|
8
8
|
|
|
9
9
|
[//]: # (towncrier release notes start)
|
|
10
10
|
|
|
11
|
+
## 3.27.3 (2026-05-19) {: #3.27.3 }
|
|
12
|
+
|
|
13
|
+
#### Bugfixes {: #3.27.3-bugfix }
|
|
14
|
+
|
|
15
|
+
- Fixed `upload_time` in Simple and JSON APIs to reflect repository addition time instead of content creation time.
|
|
16
|
+
[#1232](https://github.com/pulp/pulp_python/issues/1232)
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
11
20
|
## 3.27.2 (2026-04-14) {: #3.27.2 }
|
|
12
21
|
|
|
13
22
|
#### Bugfixes {: #3.27.2-bugfix }
|
|
@@ -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.
|
|
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
|
|
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
|
-
|
|
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,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
|
-
|
|
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
|
|
4
|
+
from django.db.utils import IntegrityError
|
|
5
5
|
from pydantic import TypeAdapter, ValidationError
|
|
6
|
-
from
|
|
7
|
-
|
|
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
|
-
|
|
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
|
|
4
|
-
from
|
|
5
|
-
from
|
|
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
|
-
|
|
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
|
|
27
|
-
from
|
|
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.
|
|
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
|
-
|
|
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
|
-
"
|
|
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["
|
|
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,
|
|
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
|
|
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;
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
)
|
|
@@ -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.
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
{pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/test_crud_content_unit.py
RENAMED
|
@@ -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,
|
{pulp_python-3.27.2 → pulp_python-3.27.3}/pulp_python/tests/functional/api/test_crud_publications.py
RENAMED
|
@@ -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
|