pulp-python 3.7.3__tar.gz → 3.9.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pulp-python-3.7.3 → pulp-python-3.9.0}/CHANGES.rst +68 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/PKG-INFO +1 -1
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/__init__.py +1 -1
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/models.py +46 -59
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/pypi/views.py +10 -2
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/serializers.py +13 -11
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/tasks/sync.py +14 -18
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/viewsets.py +1 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/api/test_crud_content_unit.py +3 -7
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/api/test_download_content.py +3 -3
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/api/test_sync.py +47 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python.egg-info/PKG-INFO +1 -1
- pulp-python-3.9.0/pulp_python.egg-info/requires.txt +4 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pyproject.toml +2 -1
- pulp-python-3.9.0/requirements.txt +4 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/setup.py +1 -1
- pulp-python-3.7.3/pulp_python.egg-info/requires.txt +0 -5
- pulp-python-3.7.3/requirements.txt +0 -5
- {pulp-python-3.7.3 → pulp-python-3.9.0}/COMMITMENT +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/COPYRIGHT +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/LICENSE +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/MANIFEST.in +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/README.md +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/functest_requirements.txt +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/__init__.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/migrations/0001_initial.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/migrations/0002_pythonpackagecontent_python_version.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/migrations/0003_new_sync_filters.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/migrations/0004_DATA_swap_distribution_model.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/migrations/0005_pythonpackagecontent_sha256.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/migrations/0006_pythonrepository_autopublish.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/migrations/0007_pythonpackagecontent_mv-2-1.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/migrations/0008_pythonpackagecontent_unique_sha256.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/migrations/0009_pythondistribution_allow_uploads.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/migrations/0010_update_json_field.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/migrations/__init__.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/pypi/__init__.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/pypi/serializers.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/settings.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/tasks/__init__.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/tasks/publish.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/tasks/upload.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/urls.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/utils.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/webserver_snippets/__init__.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/webserver_snippets/apache.conf +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/webserver_snippets/nginx.conf +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/__init__.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/__init__.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/api/__init__.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/api/test_auto_publish.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/api/test_consume_content.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/api/test_crud_publications.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/api/test_crud_remotes.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/api/test_full_mirror.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/api/test_pypi_apis.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/conftest.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/constants.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/utils.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/unit/__init__.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/unit/test_models.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/upgrade/__init__.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/upgrade/post/__init__.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/upgrade/post/test_publish.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/upgrade/pre/__init__.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/upgrade/pre/test_publish.py +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python.egg-info/SOURCES.txt +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python.egg-info/dependency_links.txt +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python.egg-info/entry_points.txt +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python.egg-info/top_level.txt +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/setup.cfg +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/test_requirements.txt +0 -0
- {pulp-python-3.7.3 → pulp-python-3.9.0}/unittest_requirements.txt +0 -0
|
@@ -13,6 +13,60 @@ Changelog
|
|
|
13
13
|
|
|
14
14
|
.. towncrier release notes start
|
|
15
15
|
|
|
16
|
+
3.9.0 (2023-03-17)
|
|
17
|
+
==================
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
Features
|
|
21
|
+
--------
|
|
22
|
+
|
|
23
|
+
- Added version filter to package list endpoint.
|
|
24
|
+
`#577 <https://github.com/pulp/pulp_python/issues/577>`__
|
|
25
|
+
- Allow duplicate uploads to return existing packages instead of erring.
|
|
26
|
+
`#590 <https://github.com/pulp/pulp_python/issues/590>`__
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
Bugfixes
|
|
30
|
+
--------
|
|
31
|
+
|
|
32
|
+
- Fixed pull-through caching ignoring remote proxy settings.
|
|
33
|
+
`#553 <https://github.com/pulp/pulp_python/issues/553>`__
|
|
34
|
+
- Changed includes and excludes openapi schema to report as array of strings instead of object.
|
|
35
|
+
`#576 <https://github.com/pulp/pulp_python/issues/576>`__
|
|
36
|
+
- Fixed syncing ignoring remote proxy.
|
|
37
|
+
`#581 <https://github.com/pulp/pulp_python/issues/581>`__
|
|
38
|
+
- Fixed duplicate operationID for generated PyPI simple endpoints schema.
|
|
39
|
+
`#594 <https://github.com/pulp/pulp_python/issues/594>`__
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
----
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
3.8.0 (2022-12-19)
|
|
46
|
+
==================
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
Bugfixes
|
|
50
|
+
--------
|
|
51
|
+
|
|
52
|
+
- Fixed syncing failing when using bandersnatch 5.3.0
|
|
53
|
+
`#554 <https://github.com/pulp/pulp_python/issues/554>`__
|
|
54
|
+
- Prevent .netrc file from being read on syncs.
|
|
55
|
+
`#566 <https://github.com/pulp/pulp_python/issues/566>`__
|
|
56
|
+
- Fix 500 error when pip installing using object storage.
|
|
57
|
+
`#572 <https://github.com/pulp/pulp_python/issues/572>`__
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
Improved Documentation
|
|
61
|
+
----------------------
|
|
62
|
+
|
|
63
|
+
- Documented ``pulp_python`` specific settings.
|
|
64
|
+
`#571 <https://github.com/pulp/pulp_python/issues/571>`__
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
----
|
|
68
|
+
|
|
69
|
+
|
|
16
70
|
3.7.3 (2022-10-06)
|
|
17
71
|
==================
|
|
18
72
|
|
|
@@ -78,6 +132,20 @@ Misc
|
|
|
78
132
|
----
|
|
79
133
|
|
|
80
134
|
|
|
135
|
+
3.6.1 (2022-08-19)
|
|
136
|
+
==================
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
Bugfixes
|
|
140
|
+
--------
|
|
141
|
+
|
|
142
|
+
- Fixed syncing failing when using bandersnatch 5.3.0
|
|
143
|
+
`#554 <https://github.com/pulp/pulp_python/issues/554>`__
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
----
|
|
147
|
+
|
|
148
|
+
|
|
81
149
|
3.6.0 (2021-12-15)
|
|
82
150
|
==================
|
|
83
151
|
|
|
@@ -5,15 +5,14 @@ from django.contrib.postgres.fields import ArrayField
|
|
|
5
5
|
from django.core.exceptions import ObjectDoesNotExist
|
|
6
6
|
from django.db import models
|
|
7
7
|
from django.conf import settings
|
|
8
|
-
from yarl import URL
|
|
9
|
-
|
|
10
8
|
from pulpcore.plugin.models import (
|
|
11
9
|
Content,
|
|
12
10
|
Publication,
|
|
13
11
|
Distribution,
|
|
14
12
|
Remote,
|
|
15
|
-
Repository
|
|
13
|
+
Repository,
|
|
16
14
|
)
|
|
15
|
+
from pulpcore.plugin.responses import ArtifactResponse
|
|
17
16
|
|
|
18
17
|
from pathlib import PurePath
|
|
19
18
|
from .utils import (
|
|
@@ -21,7 +20,7 @@ from .utils import (
|
|
|
21
20
|
parse_project_metadata,
|
|
22
21
|
python_content_to_json,
|
|
23
22
|
PYPI_LAST_SERIAL,
|
|
24
|
-
PYPI_SERIAL_CONSTANT
|
|
23
|
+
PYPI_SERIAL_CONSTANT,
|
|
25
24
|
)
|
|
26
25
|
from pulpcore.plugin.repo_version_utils import remove_duplicates, validate_repo_version
|
|
27
26
|
|
|
@@ -39,10 +38,12 @@ PACKAGE_TYPES = (
|
|
|
39
38
|
("sdist", "sdist"),
|
|
40
39
|
)
|
|
41
40
|
|
|
42
|
-
PLATFORMS = (
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
PLATFORMS = (
|
|
42
|
+
("windows", "windows"),
|
|
43
|
+
("macos", "macos"),
|
|
44
|
+
("freebsd", "freebsd"),
|
|
45
|
+
("linux", "linux"),
|
|
46
|
+
)
|
|
46
47
|
|
|
47
48
|
|
|
48
49
|
class PythonDistribution(Distribution):
|
|
@@ -50,7 +51,7 @@ class PythonDistribution(Distribution):
|
|
|
50
51
|
Distribution for 'Python' Content.
|
|
51
52
|
"""
|
|
52
53
|
|
|
53
|
-
TYPE =
|
|
54
|
+
TYPE = "python"
|
|
54
55
|
|
|
55
56
|
allow_uploads = models.BooleanField(default=True)
|
|
56
57
|
|
|
@@ -76,47 +77,31 @@ class PythonDistribution(Distribution):
|
|
|
76
77
|
# Temporary fix for PublishedMetadata not being properly served from remote storage
|
|
77
78
|
# https://github.com/pulp/pulp_python/issues/413
|
|
78
79
|
if settings.DEFAULT_FILE_STORAGE != "pulpcore.app.models.storage.FileSystem":
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
parameters = {
|
|
101
|
-
"ResponseContentDisposition": content_disposition,
|
|
102
|
-
"ResponseContentType": "text/html"
|
|
103
|
-
}
|
|
104
|
-
else:
|
|
105
|
-
raise NotImplementedError()
|
|
106
|
-
|
|
107
|
-
url = URL(file.storage.url(file.name, parameters=parameters), encoded=True)
|
|
108
|
-
# Trick the content app to stream the metadata from the remote storage
|
|
109
|
-
remote = PythonRemote(name="Redirect", url=str(url), policy="streamed")
|
|
110
|
-
remote.get_remote_artifact_url = lambda *args, **kwargs: str(url)
|
|
111
|
-
setattr(self, "publication", None)
|
|
112
|
-
setattr(self, "repository", None)
|
|
113
|
-
setattr(self, "remote", remote)
|
|
114
|
-
return None
|
|
80
|
+
if self.publication or self.repository:
|
|
81
|
+
try:
|
|
82
|
+
publication = self.publication or Publication.objects.filter(
|
|
83
|
+
repository_version=self.repository.latest_version()
|
|
84
|
+
).latest("pulp_created")
|
|
85
|
+
except ObjectDoesNotExist:
|
|
86
|
+
return None
|
|
87
|
+
rel_path = f"{path}/index.html"
|
|
88
|
+
try:
|
|
89
|
+
ca = (
|
|
90
|
+
publication.published_artifact.select_related(
|
|
91
|
+
"content_artifact",
|
|
92
|
+
"content_artifact__artifact",
|
|
93
|
+
)
|
|
94
|
+
.get(relative_path=rel_path)
|
|
95
|
+
.content_artifact
|
|
96
|
+
)
|
|
97
|
+
except ObjectDoesNotExist:
|
|
98
|
+
return None
|
|
99
|
+
headers = {"Content-Type": "text/html"}
|
|
100
|
+
return ArtifactResponse(ca.artifact, headers=headers)
|
|
115
101
|
|
|
116
102
|
if name:
|
|
117
103
|
package_content = PythonPackageContent.objects.filter(
|
|
118
|
-
pk__in=self.publication.repository_version.content,
|
|
119
|
-
name__iexact=name
|
|
104
|
+
pk__in=self.publication.repository_version.content, name__iexact=name
|
|
120
105
|
)
|
|
121
106
|
# TODO Change this value to the Repo's serial value when implemented
|
|
122
107
|
headers = {PYPI_LAST_SERIAL: str(PYPI_SERIAL_CONSTANT)}
|
|
@@ -150,7 +135,7 @@ class PythonPackageContent(Content):
|
|
|
150
135
|
|
|
151
136
|
PROTECTED_FROM_RECLAIM = False
|
|
152
137
|
|
|
153
|
-
TYPE =
|
|
138
|
+
TYPE = "python"
|
|
154
139
|
repo_key_fields = ("filename",)
|
|
155
140
|
# Required metadata
|
|
156
141
|
filename = models.TextField(db_index=True)
|
|
@@ -190,9 +175,9 @@ class PythonPackageContent(Content):
|
|
|
190
175
|
path = PurePath(relative_path)
|
|
191
176
|
metadata = get_project_metadata_from_artifact(path.name, artifact)
|
|
192
177
|
data = parse_project_metadata(vars(metadata))
|
|
193
|
-
data[
|
|
194
|
-
data[
|
|
195
|
-
data[
|
|
178
|
+
data["packagetype"] = metadata.packagetype
|
|
179
|
+
data["version"] = metadata.version
|
|
180
|
+
data["filename"] = path.name
|
|
196
181
|
data["sha256"] = artifact.sha256
|
|
197
182
|
return PythonPackageContent(**data)
|
|
198
183
|
|
|
@@ -206,11 +191,11 @@ class PythonPackageContent(Content):
|
|
|
206
191
|
e.g. <PythonPackageContent: shelf-reader [version] (whl)>
|
|
207
192
|
|
|
208
193
|
"""
|
|
209
|
-
return
|
|
194
|
+
return "<{obj_name}: {name} [{version}] ({type})>".format(
|
|
210
195
|
obj_name=self._meta.object_name,
|
|
211
196
|
name=self.name,
|
|
212
197
|
version=self.version,
|
|
213
|
-
type=self.packagetype
|
|
198
|
+
type=self.packagetype,
|
|
214
199
|
)
|
|
215
200
|
|
|
216
201
|
class Meta:
|
|
@@ -223,7 +208,7 @@ class PythonPublication(Publication):
|
|
|
223
208
|
A Publication for PythonContent.
|
|
224
209
|
"""
|
|
225
210
|
|
|
226
|
-
TYPE =
|
|
211
|
+
TYPE = "python"
|
|
227
212
|
|
|
228
213
|
class Meta:
|
|
229
214
|
default_related_name = "%(app_label)s_%(model_name)s"
|
|
@@ -238,16 +223,18 @@ class PythonRemote(Remote):
|
|
|
238
223
|
prereleases (models.BooleanField): Whether to sync pre-release versions of packages.
|
|
239
224
|
"""
|
|
240
225
|
|
|
241
|
-
TYPE =
|
|
226
|
+
TYPE = "python"
|
|
242
227
|
DEFAULT_DOWNLOAD_CONCURRENCY = 10
|
|
243
228
|
prereleases = models.BooleanField(default=False)
|
|
244
229
|
includes = models.JSONField(default=list)
|
|
245
230
|
excludes = models.JSONField(default=list)
|
|
246
|
-
package_types = ArrayField(
|
|
247
|
-
|
|
231
|
+
package_types = ArrayField(
|
|
232
|
+
models.CharField(max_length=15, blank=True), choices=PACKAGE_TYPES, default=list
|
|
233
|
+
)
|
|
248
234
|
keep_latest_packages = models.IntegerField(default=0)
|
|
249
|
-
exclude_platforms = ArrayField(
|
|
250
|
-
|
|
235
|
+
exclude_platforms = ArrayField(
|
|
236
|
+
models.CharField(max_length=10, blank=True), choices=PLATFORMS, default=list
|
|
237
|
+
)
|
|
251
238
|
|
|
252
239
|
def get_remote_artifact_url(self, relative_path=None, request=None):
|
|
253
240
|
"""Get url for remote_artifact"""
|
|
@@ -201,12 +201,20 @@ class SimpleView(ViewSet, PackageUploadMixin):
|
|
|
201
201
|
return link.text, d_url, value if digest == 'sha256' else ''
|
|
202
202
|
|
|
203
203
|
url = remote.get_remote_artifact_url(f'simple/{package}/')
|
|
204
|
-
|
|
204
|
+
kwargs = {}
|
|
205
|
+
if proxy_url := remote.proxy_url:
|
|
206
|
+
if remote.proxy_username or remote.proxy_password:
|
|
207
|
+
parsed_proxy = urlparse(proxy_url)
|
|
208
|
+
netloc = f"{remote.proxy_username}:{remote.proxy_password}@{parsed_proxy.netloc}"
|
|
209
|
+
proxy_url = urlunsplit((parsed_proxy.scheme, netloc, "", "", ""))
|
|
210
|
+
kwargs["proxies"] = {"http": proxy_url, "https": proxy_url}
|
|
211
|
+
|
|
212
|
+
response = requests.get(url, stream=True, **kwargs)
|
|
205
213
|
links = parse_links_stream_response(response)
|
|
206
214
|
packages = (parse_url(link) for link in links)
|
|
207
215
|
return StreamingHttpResponse(write_simple_detail(package, packages, streamed=True))
|
|
208
216
|
|
|
209
|
-
@extend_schema(summary="Get package simple page")
|
|
217
|
+
@extend_schema(operation_id="pypi_simple_package_read", summary="Get package simple page")
|
|
210
218
|
def retrieve(self, request, path, package):
|
|
211
219
|
"""Retrieves the simple api html page for a package."""
|
|
212
220
|
distro, repo_ver, content = self.get_drvc(path)
|
|
@@ -226,20 +226,21 @@ class PythonPackageContentSerializer(core_serializers.SingleArtifactContentUploa
|
|
|
226
226
|
"The uploaded artifact's sha256 checksum does not match the one provided"
|
|
227
227
|
)}
|
|
228
228
|
)
|
|
229
|
-
sha256 = artifact.sha256
|
|
230
|
-
if sha256 and python_models.PythonPackageContent.objects.filter(sha256=sha256).exists():
|
|
231
|
-
raise serializers.ValidationError(detail={"sha256": _('This field must be unique')})
|
|
232
229
|
|
|
233
230
|
_data = parse_project_metadata(vars(metadata))
|
|
234
231
|
_data['packagetype'] = metadata.packagetype
|
|
235
232
|
_data['version'] = metadata.version
|
|
236
233
|
_data['filename'] = filename
|
|
237
|
-
_data['sha256'] = sha256
|
|
234
|
+
_data['sha256'] = artifact.sha256
|
|
238
235
|
|
|
239
236
|
data.update(_data)
|
|
240
237
|
|
|
241
238
|
return data
|
|
242
239
|
|
|
240
|
+
def retrieve(self, validated_data):
|
|
241
|
+
content = python_models.PythonPackageContent.objects.filter(sha256=validated_data["sha256"])
|
|
242
|
+
return content.first()
|
|
243
|
+
|
|
243
244
|
class Meta:
|
|
244
245
|
fields = core_serializers.SingleArtifactContentUploadSerializer.Meta.fields + (
|
|
245
246
|
'filename', 'packagetype', 'name', 'version', 'sha256', 'metadata_version', 'summary',
|
|
@@ -278,20 +279,21 @@ class PythonRemoteSerializer(core_serializers.RemoteSerializer):
|
|
|
278
279
|
A Serializer for PythonRemote.
|
|
279
280
|
"""
|
|
280
281
|
|
|
281
|
-
includes = serializers.
|
|
282
|
+
includes = serializers.ListField(
|
|
283
|
+
child=serializers.CharField(allow_blank=False),
|
|
282
284
|
required=False,
|
|
283
|
-
|
|
285
|
+
allow_empty=True,
|
|
284
286
|
help_text=_(
|
|
285
|
-
"A
|
|
287
|
+
"A list containing project specifiers for Python packages to include."
|
|
286
288
|
),
|
|
287
289
|
)
|
|
288
|
-
excludes = serializers.
|
|
290
|
+
excludes = serializers.ListField(
|
|
291
|
+
child=serializers.CharField(allow_blank=False),
|
|
289
292
|
required=False,
|
|
290
|
-
|
|
293
|
+
allow_empty=True,
|
|
291
294
|
help_text=_(
|
|
292
|
-
"A
|
|
295
|
+
"A list containing project specifiers for Python packages to exclude."
|
|
293
296
|
),
|
|
294
|
-
|
|
295
297
|
)
|
|
296
298
|
prereleases = serializers.BooleanField(
|
|
297
299
|
required=False,
|
|
@@ -3,7 +3,7 @@ import logging
|
|
|
3
3
|
from aiohttp import ClientResponseError, ClientError
|
|
4
4
|
from lxml.etree import LxmlError
|
|
5
5
|
from gettext import gettext as _
|
|
6
|
-
from os import environ
|
|
6
|
+
from os import environ, path
|
|
7
7
|
|
|
8
8
|
from rest_framework import serializers
|
|
9
9
|
|
|
@@ -26,7 +26,7 @@ from bandersnatch.mirror import Mirror
|
|
|
26
26
|
from bandersnatch.master import Master
|
|
27
27
|
from bandersnatch.configuration import BandersnatchConfig
|
|
28
28
|
from packaging.requirements import Requirement
|
|
29
|
-
from urllib.parse import urljoin
|
|
29
|
+
from urllib.parse import urljoin, urlsplit, urlunsplit
|
|
30
30
|
|
|
31
31
|
logger = logging.getLogger(__name__)
|
|
32
32
|
|
|
@@ -111,14 +111,22 @@ class PythonBanderStage(Stage):
|
|
|
111
111
|
"""
|
|
112
112
|
If includes is specified, then only sync those,else try to sync all other packages
|
|
113
113
|
"""
|
|
114
|
+
# Prevent bandersnatch from reading actual .netrc file, set to nonexistent file
|
|
115
|
+
# See discussion on https://github.com/pulp/pulp_python/issues/581
|
|
116
|
+
environ["NETRC"] = f"{path.curdir}/.fake-netrc"
|
|
114
117
|
# TODO Change Bandersnatch internal API to take proxy settings in from config parameters
|
|
115
|
-
if self.remote.proxy_url:
|
|
116
|
-
|
|
117
|
-
|
|
118
|
+
if proxy_url := self.remote.proxy_url:
|
|
119
|
+
if self.remote.proxy_username or self.remote.proxy_password:
|
|
120
|
+
parsed_proxy = urlsplit(proxy_url)
|
|
121
|
+
creds = f"{self.remote.proxy_username}:{self.remote.proxy_password}"
|
|
122
|
+
netloc = f"{creds}@{parsed_proxy.netloc}"
|
|
123
|
+
proxy_url = urlunsplit((parsed_proxy.scheme, netloc, "", "", ""))
|
|
124
|
+
environ['http_proxy'] = proxy_url
|
|
125
|
+
environ['https_proxy'] = proxy_url
|
|
118
126
|
# Bandersnatch includes leading slash when forming API urls
|
|
119
127
|
url = self.remote.url.rstrip("/")
|
|
120
128
|
# local & global timeouts defaults to 10secs and 5 hours
|
|
121
|
-
async with
|
|
129
|
+
async with Master(url) as master:
|
|
122
130
|
deferred_download = self.remote.policy != Remote.IMMEDIATE
|
|
123
131
|
workers = self.remote.download_concurrency or self.remote.DEFAULT_DOWNLOAD_CONCURRENCY
|
|
124
132
|
async with ProgressReport(
|
|
@@ -140,18 +148,6 @@ class PythonBanderStage(Stage):
|
|
|
140
148
|
await pmirror.synchronize(packages_to_sync)
|
|
141
149
|
|
|
142
150
|
|
|
143
|
-
class PulpMaster(Master):
|
|
144
|
-
"""
|
|
145
|
-
Temporary subclass of bandersnatch.Master until features are in bandersnatch.
|
|
146
|
-
"""
|
|
147
|
-
|
|
148
|
-
async def __aenter__(self) -> "Master":
|
|
149
|
-
"""Ensure Pulp does not try to read the .netrc file."""
|
|
150
|
-
await super().__aenter__()
|
|
151
|
-
self.session._trust_env = False
|
|
152
|
-
return self
|
|
153
|
-
|
|
154
|
-
|
|
155
151
|
class PulpMirror(Mirror):
|
|
156
152
|
"""
|
|
157
153
|
Pulp Mirror Class to perform syncing using Bandersnatch
|
{pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/api/test_crud_content_unit.py
RENAMED
|
@@ -146,7 +146,7 @@ class ContentUnitTestCase(TestCaseUsingBindings, TestHelpersMixin):
|
|
|
146
146
|
"""
|
|
147
147
|
1) upload file
|
|
148
148
|
2) upload the same file again
|
|
149
|
-
3) this should
|
|
149
|
+
3) this should return first unit
|
|
150
150
|
"""
|
|
151
151
|
delete_orphans()
|
|
152
152
|
response = self.do_upload()
|
|
@@ -154,12 +154,8 @@ class ContentUnitTestCase(TestCaseUsingBindings, TestHelpersMixin):
|
|
|
154
154
|
content_unit = self.content_api.read(created_resources[0])
|
|
155
155
|
self.check_package_data(content_unit.to_dict())
|
|
156
156
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
task_report = cm.exception.task.to_dict()
|
|
160
|
-
msg = "This field must be unique"
|
|
161
|
-
self.assertTrue("sha256" in task_report["error"]["description"])
|
|
162
|
-
self.assertTrue(msg in task_report["error"]["description"])
|
|
157
|
+
created_resources = monitor_task(self.do_upload().task).created_resources
|
|
158
|
+
self.assertEqual(content_unit.pulp_href, created_resources[0])
|
|
163
159
|
|
|
164
160
|
def test_08_upload_same_filename_different_artifact(self):
|
|
165
161
|
"""
|
{pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/api/test_download_content.py
RENAMED
|
@@ -124,7 +124,7 @@ class PublishPyPIJSON(TestCaseUsingBindings, TestHelpersMixin):
|
|
|
124
124
|
This test checks that Pulp can fully sync another Python Package repository that is not
|
|
125
125
|
PyPI. This reads the repository's simple page if XMLRPC isn't supported.
|
|
126
126
|
"""
|
|
127
|
-
remote = self._create_remote(includes=
|
|
127
|
+
remote = self._create_remote(includes=[], prereleases=True)
|
|
128
128
|
repo = self._create_repo_and_sync_with_remote(remote)
|
|
129
129
|
self.assertEqual(get_content_summary(repo.to_dict()), PYTHON_LG_FIXTURE_SUMMARY)
|
|
130
130
|
|
|
@@ -138,14 +138,14 @@ class PublishPyPIJSON(TestCaseUsingBindings, TestHelpersMixin):
|
|
|
138
138
|
# Test using live generated simple pages
|
|
139
139
|
distro = self._create_distribution_from_repo(repo)
|
|
140
140
|
|
|
141
|
-
remote = self._create_remote(includes=
|
|
141
|
+
remote = self._create_remote(includes=[], url=distro.base_url)
|
|
142
142
|
repo2 = self._create_repo_and_sync_with_remote(remote)
|
|
143
143
|
self.assertEqual(get_content_summary(repo2.to_dict()), PYTHON_MD_FIXTURE_SUMMARY)
|
|
144
144
|
|
|
145
145
|
# Now test using publication simple pages
|
|
146
146
|
pub = self._create_publication(repo)
|
|
147
147
|
distro2 = self._create_distribution_from_publication(pub)
|
|
148
|
-
remote = self._create_remote(includes=
|
|
148
|
+
remote = self._create_remote(includes=[], url=distro2.base_url, prereleases=True)
|
|
149
149
|
|
|
150
150
|
repo3 = self._create_repo_and_sync_with_remote(remote)
|
|
151
151
|
self.assertEqual(get_content_summary(repo3.to_dict()), PYTHON_MD_FIXTURE_SUMMARY)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# coding=utf-8
|
|
2
2
|
"""Tests that sync python plugin repositories."""
|
|
3
|
+
import pytest
|
|
3
4
|
import unittest
|
|
4
5
|
|
|
5
6
|
from pulp_smash import config
|
|
@@ -640,6 +641,52 @@ class PlatformExcludeTestCase(unittest.TestCase):
|
|
|
640
641
|
)
|
|
641
642
|
|
|
642
643
|
|
|
644
|
+
@pytest.mark.parallel
|
|
645
|
+
def test_proxy_sync(
|
|
646
|
+
python_repo,
|
|
647
|
+
python_repo_api_client,
|
|
648
|
+
python_remote_factory,
|
|
649
|
+
python_content_api_client,
|
|
650
|
+
http_proxy,
|
|
651
|
+
):
|
|
652
|
+
"""Test syncing with a proxy."""
|
|
653
|
+
body = gen_python_remote(proxy_url=http_proxy.proxy_url)
|
|
654
|
+
remote = python_remote_factory(**body)
|
|
655
|
+
sync_resp = python_repo_api_client.sync(python_repo.pulp_href, {"remote": remote.pulp_href})
|
|
656
|
+
monitor_task(sync_resp.task)
|
|
657
|
+
|
|
658
|
+
repo = python_repo_api_client.read(python_repo.pulp_href)
|
|
659
|
+
assert repo.latest_version_href[-2] == "1"
|
|
660
|
+
|
|
661
|
+
content_resp = python_content_api_client.list(repository_version=repo.latest_version_href)
|
|
662
|
+
assert content_resp.count == 2
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
@pytest.mark.parallel
|
|
666
|
+
def test_proxy_auth_sync(
|
|
667
|
+
python_repo,
|
|
668
|
+
python_repo_api_client,
|
|
669
|
+
python_remote_factory,
|
|
670
|
+
python_content_api_client,
|
|
671
|
+
http_proxy_with_auth,
|
|
672
|
+
):
|
|
673
|
+
"""Test syncing with a proxy with auth."""
|
|
674
|
+
body = gen_python_remote(
|
|
675
|
+
proxy_url=http_proxy_with_auth.proxy_url,
|
|
676
|
+
proxy_username=http_proxy_with_auth.username,
|
|
677
|
+
proxy_password=http_proxy_with_auth.password,
|
|
678
|
+
)
|
|
679
|
+
remote = python_remote_factory(**body)
|
|
680
|
+
sync_resp = python_repo_api_client.sync(python_repo.pulp_href, {"remote": remote.pulp_href})
|
|
681
|
+
monitor_task(sync_resp.task)
|
|
682
|
+
|
|
683
|
+
repo = python_repo_api_client.read(python_repo.pulp_href)
|
|
684
|
+
assert repo.latest_version_href[-2] == "1"
|
|
685
|
+
|
|
686
|
+
content_resp = python_content_api_client.list(repository_version=repo.latest_version_href)
|
|
687
|
+
assert content_resp.count == 2
|
|
688
|
+
|
|
689
|
+
|
|
643
690
|
def sync_to_remote(self, body, create=False, mirror=False):
|
|
644
691
|
"""Takes a body and creates/updates a remote object, then it performs a sync"""
|
|
645
692
|
if create:
|
|
@@ -16,11 +16,12 @@ ignore = [
|
|
|
16
16
|
"dev_requirements.txt",
|
|
17
17
|
"doc_requirements.txt",
|
|
18
18
|
"docs/**",
|
|
19
|
-
"flake8.cfg",
|
|
20
19
|
"template_config.yml",
|
|
21
20
|
".travis/**",
|
|
22
21
|
".travis.yml",
|
|
23
22
|
"shelf_reader-0.1-py2-none-any.whl",
|
|
24
23
|
".github/**",
|
|
25
24
|
".ci/**",
|
|
25
|
+
"lint_requirements.txt",
|
|
26
|
+
".flake8",
|
|
26
27
|
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/app/migrations/0010_update_json_field.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/api/test_auto_publish.py
RENAMED
|
File without changes
|
{pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/api/test_consume_content.py
RENAMED
|
File without changes
|
{pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/api/test_crud_publications.py
RENAMED
|
File without changes
|
{pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/api/test_crud_remotes.py
RENAMED
|
File without changes
|
{pulp-python-3.7.3 → pulp-python-3.9.0}/pulp_python/tests/functional/api/test_full_mirror.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|