pulp-python 3.30.3__py3-none-any.whl → 3.31.0__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.
- pulp_python/app/__init__.py +1 -1
- pulp_python/app/exceptions.py +54 -0
- pulp_python/app/models.py +5 -5
- pulp_python/app/serializers.py +4 -3
- pulp_python/app/tasks/sync.py +7 -6
- pulp_python/app/tasks/upload.py +11 -2
- {pulp_python-3.30.3.dist-info → pulp_python-3.31.0.dist-info}/METADATA +1 -1
- {pulp_python-3.30.3.dist-info → pulp_python-3.31.0.dist-info}/RECORD +12 -11
- {pulp_python-3.30.3.dist-info → pulp_python-3.31.0.dist-info}/WHEEL +0 -0
- {pulp_python-3.30.3.dist-info → pulp_python-3.31.0.dist-info}/entry_points.txt +0 -0
- {pulp_python-3.30.3.dist-info → pulp_python-3.31.0.dist-info}/licenses/LICENSE +0 -0
- {pulp_python-3.30.3.dist-info → pulp_python-3.31.0.dist-info}/top_level.txt +0 -0
pulp_python/app/__init__.py
CHANGED
|
@@ -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
|
+
)
|
pulp_python/app/models.py
CHANGED
|
@@ -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
|
|
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
|
|
423
|
-
"To allow this, set 'allow_package_substitution' to True on the
|
|
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):
|
pulp_python/app/serializers.py
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
658
|
+
except PydanticValidationError as e:
|
|
658
659
|
raise serializers.ValidationError(
|
|
659
660
|
_("The uploaded provenance is not valid: {}").format(e)
|
|
660
661
|
)
|
pulp_python/app/tasks/sync.py
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import logging
|
|
3
3
|
from functools import partial
|
|
4
|
-
from
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
pulp_python/app/tasks/upload.py
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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)
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
pulp_python/__init__.py,sha256=GIuTLoBTc-07dSLJUh8xrZPRz8x-jJ61pfR0J1IjnzI,65
|
|
2
2
|
pulp_python/pytest_plugin.py,sha256=LNnLjOkeEu2X4gJi614bHVmbsHyEwooHYIeecr96Qy4,8606
|
|
3
|
-
pulp_python/app/__init__.py,sha256=
|
|
3
|
+
pulp_python/app/__init__.py,sha256=Dh2hJwj55-Hhj1AS-ylzEngH75RptOtCuDTpvanHjhM,2490
|
|
4
|
+
pulp_python/app/exceptions.py,sha256=mPNcWyuzF0XeOPybm-G6oDKtRqvfj4jyp41iaYqcqkA,1314
|
|
4
5
|
pulp_python/app/global_access_conditions.py,sha256=MZJtyoVsr-4hRaty6mKDqh3caOHd5UKJjEWLV2crOLs,1080
|
|
5
6
|
pulp_python/app/modelresource.py,sha256=4SFAdqk6lozi_cZz4uqDIqhqPAZF-7l5jJwPn-xGZFs,1249
|
|
6
|
-
pulp_python/app/models.py,sha256=
|
|
7
|
+
pulp_python/app/models.py,sha256=oEZ05nKkYzqkMOq2dUJ4QzZlA0-rvwWyxrEHwax91YI,17691
|
|
7
8
|
pulp_python/app/provenance.py,sha256=iyhkuNahHiTDK0Djrd4-PlgErA5SJVI0uQOIPj46tEI,2352
|
|
8
9
|
pulp_python/app/replica.py,sha256=qiWRP7tM_v4yP_XLIQfumfGolru-Jt6ZA0KVb-9g2cA,1882
|
|
9
|
-
pulp_python/app/serializers.py,sha256=
|
|
10
|
+
pulp_python/app/serializers.py,sha256=y4WJTMPVKcGlbj98cKTeqWQLCB2kfjkX2hON90_iGDo,33882
|
|
10
11
|
pulp_python/app/settings.py,sha256=Cyc_p6U0HQjKpyrRL6JFrK3R7RMQJ9MAgNMJCfzPEiA,255
|
|
11
12
|
pulp_python/app/urls.py,sha256=M2xjQ0j47BwQVpi75QCa5eUnQDcroKv3Cee7UrQ3QcA,1387
|
|
12
13
|
pulp_python/app/utils.py,sha256=aFBd0llndGiBb6VlvoOvGkD3G3ciWyQierykpqxue_8,27386
|
|
@@ -44,8 +45,8 @@ pulp_python/app/pypi/views.py,sha256=F55Zp4GPAQDVk936Szu2ECge8p1-5A160iqzrMDTZGc
|
|
|
44
45
|
pulp_python/app/tasks/__init__.py,sha256=lTFpVvpDKbqv9RC0b2RYU8Bo6svDjrA-djt16pADFr8,284
|
|
45
46
|
pulp_python/app/tasks/publish.py,sha256=bjsJzqJbLu7TF5rLb-UsZMmlNnc_LKw-sdHX9Gcatbw,4334
|
|
46
47
|
pulp_python/app/tasks/repair.py,sha256=5InzdbjW8y3AC4Vj2PsNLm3wGGTr8D3LcfPw_WA2Fks,12257
|
|
47
|
-
pulp_python/app/tasks/sync.py,sha256=
|
|
48
|
-
pulp_python/app/tasks/upload.py,sha256=
|
|
48
|
+
pulp_python/app/tasks/sync.py,sha256=_alhmNMVxEGo6touaXuNMkBZH7gv-zdo_gxUmUyPGHY,12886
|
|
49
|
+
pulp_python/app/tasks/upload.py,sha256=HBOknlsAb0mlE-2dJsalH_8JUZwrKk4AsVibmVJf2aQ,6102
|
|
49
50
|
pulp_python/app/tasks/vulnerability_report.py,sha256=0cyxNb4048HFUdUlGBA6wYsg-hEMjSfE8mtw05Ct9BQ,1126
|
|
50
51
|
pulp_python/app/webserver_snippets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
51
52
|
pulp_python/app/webserver_snippets/apache.conf,sha256=3frHSl2YV_8pJPscaFxMVo7HmxGJdb8XVmfdLtCxzoA,97
|
|
@@ -77,9 +78,9 @@ pulp_python/tests/functional/assets/shelf-reader-0.1.tar.gz.publish.attestation,
|
|
|
77
78
|
pulp_python/tests/functional/assets/shelf_reader-0.1-py2-none-any.whl.publish.attestation,sha256=muTQ8dqYSSdx76DlaPjB1REcNIS-aak-Na0TkASxu8M,10426
|
|
78
79
|
pulp_python/tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
79
80
|
pulp_python/tests/unit/test_models.py,sha256=TBI0yKsrdbnJSPeBFfxSqhXK7zaNvR6qg5JehGH3Pds,229
|
|
80
|
-
pulp_python-3.
|
|
81
|
-
pulp_python-3.
|
|
82
|
-
pulp_python-3.
|
|
83
|
-
pulp_python-3.
|
|
84
|
-
pulp_python-3.
|
|
85
|
-
pulp_python-3.
|
|
81
|
+
pulp_python-3.31.0.dist-info/licenses/LICENSE,sha256=2ylvL381vKOhdO-w6zkrOxe9lLNBhRQpo9_0EbHC_HM,18046
|
|
82
|
+
pulp_python-3.31.0.dist-info/METADATA,sha256=8-vDJU8B_2GbuEf6SZLVlpYanFBoBpRrzPZZ8-F-v3E,1744
|
|
83
|
+
pulp_python-3.31.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
84
|
+
pulp_python-3.31.0.dist-info/entry_points.txt,sha256=HvqLEXjw_dS5jqAwnE5JiRZFE6f-y5SRtitKLPml2To,115
|
|
85
|
+
pulp_python-3.31.0.dist-info/top_level.txt,sha256=X0hXgXc_bpbiKqVrkt8jD5_QEiQviKbHDwveQcOcJjo,12
|
|
86
|
+
pulp_python-3.31.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|