pulp-python 3.27.0__py3-none-any.whl → 3.27.2__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.
@@ -10,7 +10,7 @@ class PulpPythonPluginAppConfig(PulpPluginAppConfig):
10
10
 
11
11
  name = "pulp_python.app"
12
12
  label = "python"
13
- version = "3.27.0"
13
+ version = "3.27.2"
14
14
  python_package_name = "pulp-python"
15
15
  domain_compatible = True
16
16
 
@@ -1,6 +1,5 @@
1
1
  from django.conf import settings
2
2
 
3
-
4
3
  # Access Condition methods that can be used with PyPI access policies
5
4
 
6
5
 
@@ -31,7 +31,8 @@ class PythonReplicator(Replicator):
31
31
  def url(self, upstream_distribution):
32
32
  # Ignore distributions that are only pull-through
33
33
  repo, pub = upstream_distribution["repository"], upstream_distribution["publication"]
34
- if repo or pub:
34
+ repo_ver = upstream_distribution.get("repository_version")
35
+ if repo or pub or repo_ver:
35
36
  return super().url(upstream_distribution)
36
37
 
37
38
  return None
@@ -30,7 +30,6 @@ from pulp_python.app.utils import (
30
30
  parse_project_metadata,
31
31
  )
32
32
 
33
-
34
33
  log = logging.getLogger(__name__)
35
34
 
36
35
 
@@ -12,7 +12,6 @@ from pulp_python.app import models as python_models
12
12
  from pulp_python.app.serializers import PythonPublicationSerializer
13
13
  from pulp_python.app.utils import write_simple_index, write_simple_detail
14
14
 
15
-
16
15
  log = logging.getLogger(__name__)
17
16
 
18
17
 
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ import os
2
3
  from collections import defaultdict
3
4
  from gettext import gettext as _
4
5
  from itertools import groupby
@@ -8,18 +9,20 @@ from django.db.models import Prefetch
8
9
  from django.db.models.query import QuerySet
9
10
  from pulp_python.app.models import PythonPackageContent, PythonRepository
10
11
  from pulp_python.app.utils import (
11
- artifact_to_metadata_artifact,
12
12
  artifact_to_python_content_data,
13
+ copy_artifact_to_temp_file,
14
+ extract_wheel_metadata,
13
15
  fetch_json_release_metadata,
16
+ metadata_content_to_artifact,
14
17
  parse_metadata,
15
18
  )
16
- from pulpcore.plugin.models import Artifact, ContentArtifact, ProgressReport
19
+ from pulpcore.plugin.models import ContentArtifact, ProgressReport
17
20
  from pulpcore.plugin.util import get_domain
18
21
 
19
22
  log = logging.getLogger(__name__)
20
23
 
21
24
 
22
- BULK_SIZE = 1000
25
+ BULK_SIZE = 250
23
26
 
24
27
 
25
28
  def repair(repository_pk: UUID) -> None:
@@ -118,11 +121,21 @@ def repair_metadata(content: QuerySet[PythonPackageContent]) -> tuple[int, set[s
118
121
  .first()
119
122
  .artifact
120
123
  )
121
- new_data = artifact_to_python_content_data(package.filename, main_artifact, domain)
124
+ # Copy artifact to temp file once, extract both content data and metadata
125
+ temp_path = copy_artifact_to_temp_file(main_artifact, package.filename)
126
+ try:
127
+ new_data = artifact_to_python_content_data(
128
+ package.filename, main_artifact, domain, temp_path=temp_path
129
+ )
130
+ metadata_content = (
131
+ extract_wheel_metadata(temp_path) if package.filename.endswith(".whl") else None
132
+ )
133
+ finally:
134
+ os.unlink(temp_path)
122
135
  total_metadata_repaired += update_metadata_artifact_if_needed(
123
136
  package,
124
137
  new_data.get("metadata_sha256"),
125
- main_artifact,
138
+ metadata_content,
126
139
  metadata_batch,
127
140
  pkgs_metadata_not_repaired,
128
141
  )
@@ -236,7 +249,7 @@ def update_package_if_needed(
236
249
  def update_metadata_artifact_if_needed(
237
250
  package: PythonPackageContent,
238
251
  new_metadata_sha256: str | None,
239
- main_artifact: Artifact,
252
+ metadata_content: bytes | None,
240
253
  metadata_batch: list[tuple],
241
254
  pkgs_metadata_not_repaired: set[str],
242
255
  ) -> int:
@@ -248,7 +261,7 @@ def update_metadata_artifact_if_needed(
248
261
  Args:
249
262
  package: Package to check for metadata changes.
250
263
  new_metadata_sha256: The correct metadata_sha256 extracted from the main artifact, or None.
251
- main_artifact: The main package artifact used to generate metadata.
264
+ metadata_content: Raw metadata bytes extracted from the wheel, or None.
252
265
  metadata_batch: List of tuples for batch processing (updated in-place).
253
266
  pkgs_metadata_not_repaired: Set of package PKs that failed repair (updated in-place).
254
267
 
@@ -265,13 +278,13 @@ def update_metadata_artifact_if_needed(
265
278
 
266
279
  # Create missing
267
280
  if not cas:
268
- metadata_batch.append((package, main_artifact))
281
+ metadata_batch.append((package, metadata_content))
269
282
  # Fix existing
270
283
  elif new_metadata_sha256 != original_metadata_sha256:
271
284
  ca = cas.first()
272
285
  metadata_artifact = ca.artifact
273
286
  if metadata_artifact is None or (metadata_artifact.sha256 != new_metadata_sha256):
274
- metadata_batch.append((package, main_artifact))
287
+ metadata_batch.append((package, metadata_content))
275
288
 
276
289
  if len(metadata_batch) == BULK_SIZE:
277
290
  not_repaired = _process_metadata_batch(metadata_batch)
@@ -288,7 +301,7 @@ def _process_metadata_batch(metadata_batch: list[tuple]) -> set[str]:
288
301
  and their corresponding ContentArtifacts.
289
302
 
290
303
  Args:
291
- metadata_batch: List of (package, main_artifact) tuples.
304
+ metadata_batch: List of (package, metadata_content) tuples.
292
305
 
293
306
  Returns:
294
307
  Set of package PKs for which metadata artifacts could not be created.
@@ -296,8 +309,8 @@ def _process_metadata_batch(metadata_batch: list[tuple]) -> set[str]:
296
309
  not_repaired = set()
297
310
  content_artifacts = []
298
311
 
299
- for package, main_artifact in metadata_batch:
300
- metadata_artifact = artifact_to_metadata_artifact(package.filename, main_artifact)
312
+ for package, metadata_content in metadata_batch:
313
+ metadata_artifact = metadata_content_to_artifact(metadata_content)
301
314
  if metadata_artifact:
302
315
  ca = ContentArtifact(
303
316
  artifact=metadata_artifact,
pulp_python/app/utils.py CHANGED
@@ -20,7 +20,6 @@ from pulpcore.plugin.models import Artifact, Remote
20
20
  from pulpcore.plugin.exceptions import TimeoutException
21
21
  from pulpcore.plugin.util import get_domain
22
22
 
23
-
24
23
  log = logging.getLogger(__name__)
25
24
 
26
25
 
@@ -241,18 +240,37 @@ def compute_metadata_sha256(filename: str) -> str | None:
241
240
  return hashlib.sha256(metadata_content).hexdigest() if metadata_content else None
242
241
 
243
242
 
244
- def artifact_to_python_content_data(filename, artifact, domain=None):
243
+ def copy_artifact_to_temp_file(artifact, filename, tmp_dir="."):
244
+ """
245
+ Copy an artifact's file to a temporary file on disk.
246
+
247
+ Returns the path to the temp file. The caller is responsible for cleanup.
248
+ """
249
+ temp_file = tempfile.NamedTemporaryFile("wb", dir=tmp_dir, suffix=filename, delete=False)
250
+ artifact.file.seek(0)
251
+ shutil.copyfileobj(artifact.file, temp_file)
252
+ temp_file.flush()
253
+ temp_file.close()
254
+ return temp_file.name
255
+
256
+
257
+ def artifact_to_python_content_data(filename, artifact, domain=None, temp_path=None):
245
258
  """
246
259
  Takes the artifact/filename and returns the metadata needed to create a PythonPackageContent.
260
+
261
+ If temp_path is provided, uses it instead of copying the artifact to a new temp file.
247
262
  """
248
263
  # Copy file to a temp directory under the user provided filename, we do this
249
264
  # because pkginfo validates that the filename has a valid extension before
250
265
  # reading it
251
- with tempfile.NamedTemporaryFile("wb", dir=".", suffix=filename) as temp_file:
252
- artifact.file.seek(0)
253
- shutil.copyfileobj(artifact.file, temp_file)
254
- temp_file.flush()
255
- metadata = get_project_metadata_from_file(temp_file.name)
266
+ if temp_path:
267
+ metadata = get_project_metadata_from_file(temp_path)
268
+ else:
269
+ with tempfile.NamedTemporaryFile("wb", dir=".", suffix=filename) as temp_file:
270
+ artifact.file.seek(0)
271
+ shutil.copyfileobj(artifact.file, temp_file)
272
+ temp_file.flush()
273
+ metadata = get_project_metadata_from_file(temp_file.name)
256
274
  data = parse_project_metadata(vars(metadata))
257
275
  data["sha256"] = artifact.sha256
258
276
  data["size"] = artifact.size
@@ -281,6 +299,16 @@ def artifact_to_metadata_artifact(
281
299
  if not metadata_content:
282
300
  return None
283
301
 
302
+ return metadata_content_to_artifact(metadata_content, tmp_dir)
303
+
304
+
305
+ def metadata_content_to_artifact(metadata_content: bytes, tmp_dir: str = ".") -> Artifact | None:
306
+ """
307
+ Creates an Artifact from raw metadata content bytes.
308
+ """
309
+ if not metadata_content:
310
+ return None
311
+
284
312
  with tempfile.NamedTemporaryFile(
285
313
  "wb", dir=tmp_dir, suffix=".metadata", delete=False
286
314
  ) as temp_md:
@@ -13,7 +13,6 @@ from pulp_python.tests.functional.constants import (
13
13
  PYTHON_WHEEL_FILENAME,
14
14
  )
15
15
 
16
-
17
16
  # Bindings API Fixtures
18
17
 
19
18
 
@@ -12,7 +12,6 @@ from pulp_python.tests.functional.constants import (
12
12
  )
13
13
  from urllib.parse import urlsplit
14
14
 
15
-
16
15
  pytestmark = pytest.mark.skipif(not settings.DOMAIN_ENABLED, reason="Domain not enabled")
17
16
 
18
17
 
@@ -14,7 +14,6 @@ from pulp_python.tests.functional.constants import (
14
14
  PYTHON_SM_PROJECT_SPECIFIER,
15
15
  )
16
16
 
17
-
18
17
  pytestmark = [
19
18
  pytest.mark.skipif(
20
19
  "/tmp" not in settings.ALLOWED_EXPORT_PATHS,
@@ -16,7 +16,6 @@ from pulp_python.tests.functional.constants import (
16
16
  )
17
17
  from pulp_python.tests.functional.utils import ensure_metadata
18
18
 
19
-
20
19
  PYPI_LAST_SERIAL = "X-PYPI-LAST-SERIAL"
21
20
 
22
21
 
@@ -1,7 +1,6 @@
1
1
  import os
2
2
  from urllib.parse import urljoin
3
3
 
4
-
5
4
  PULP_FIXTURES_BASE_URL = os.environ.get(
6
5
  "REMOTE_FIXTURES_ORIGIN", "https://fixtures.pulpproject.org/"
7
6
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pulp-python
3
- Version: 3.27.0
3
+ Version: 3.27.2
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,15 +1,15 @@
1
1
  pulp_python/__init__.py,sha256=GIuTLoBTc-07dSLJUh8xrZPRz8x-jJ61pfR0J1IjnzI,65
2
- pulp_python/pytest_plugin.py,sha256=r6-flyyEed8lmIQii_zBWPqKN7tKcdr_sGvjixW3N98,8605
3
- pulp_python/app/__init__.py,sha256=tB8iSoqCh0PCNIUXjg8r79WWPKoGmnLDRrqeKsZ5NAE,2488
4
- pulp_python/app/global_access_conditions.py,sha256=y8NwdgAoaB5iY7EzSBoCQOgVopSHpVMc55FKJmCGGlI,1081
2
+ pulp_python/pytest_plugin.py,sha256=EBivPJa39ZE1QaDWea9candeeJL_W_cBk6Q7Onhw4bE,8604
3
+ pulp_python/app/__init__.py,sha256=6t82RCPUBUunBDp9wK3Rg12nnTglsi0JTYE_9jdyUik,2488
4
+ pulp_python/app/global_access_conditions.py,sha256=MZJtyoVsr-4hRaty6mKDqh3caOHd5UKJjEWLV2crOLs,1080
5
5
  pulp_python/app/modelresource.py,sha256=dogoBWibBmQyFpcV-Hp1lu7D2WwSECa5PEShWSIg7mg,1248
6
6
  pulp_python/app/models.py,sha256=j2U__78AMhyYIiRKyA_o5_55EvqkZSJVh4QWmpGtX-A,14055
7
7
  pulp_python/app/provenance.py,sha256=iyhkuNahHiTDK0Djrd4-PlgErA5SJVI0uQOIPj46tEI,2352
8
- pulp_python/app/replica.py,sha256=GHSLLKUVg4SRMEsMnesxI2xgB0Z83AzrWY1-UbACF0g,1802
9
- pulp_python/app/serializers.py,sha256=UD_wn8uAHrI986o4B1ueiJn1XNzIygKMY7Say_osGrE,28675
8
+ pulp_python/app/replica.py,sha256=W60Kt9CwZSfztRi3-f82Rfp0F_zhzpOTiz35bvRFBBE,1881
9
+ pulp_python/app/serializers.py,sha256=ItjeHJ1qRN7dYvpxSJAdRUMJ6JsjvHoI_so4zhkTvkI,28674
10
10
  pulp_python/app/settings.py,sha256=HXJK3rr0LVTOv1xBS5cZvVtz6j4SvFZl0PH3sLTcu2w,227
11
11
  pulp_python/app/urls.py,sha256=dw6SQ7N6SIxHALAjTdGg3dPL3-54MVoDzUKfqXA2epI,1328
12
- pulp_python/app/utils.py,sha256=Y0lYDMCsGaIh8MKU6Wu3n57LuNzN3zKn0rVP_XZKPVE,25777
12
+ pulp_python/app/utils.py,sha256=2MEHK_fuLpZA9w4ohbhcs1D2ii478gwW_iAuSTsu-kw,26740
13
13
  pulp_python/app/viewsets.py,sha256=-UgY6uySh5TVLMv_p0dAeJQIRs9SIOrfFORFMGj9N8o,28439
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
@@ -39,8 +39,8 @@ pulp_python/app/pypi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
39
39
  pulp_python/app/pypi/serializers.py,sha256=w6_doLpaO8Dnzur57MYrTIqEP4I3LI8biu9ipLC66fk,5028
40
40
  pulp_python/app/pypi/views.py,sha256=ksQflLQSwcsmoJtQG6B440rQ8CPF_bSTdWXpYJFEAg4,21006
41
41
  pulp_python/app/tasks/__init__.py,sha256=lTFpVvpDKbqv9RC0b2RYU8Bo6svDjrA-djt16pADFr8,284
42
- pulp_python/app/tasks/publish.py,sha256=b0JwHZvnIsJ8gEc_GJm6lUKQC3Po1lxW1TcP2q59WXA,4335
43
- pulp_python/app/tasks/repair.py,sha256=_SACezEsnal8VnSGR91yTI-kJ6axZaEIBrhS1hkO8JA,11723
42
+ pulp_python/app/tasks/publish.py,sha256=Z3kWz22bKNXk2j-k1OgwOTEYcgzDzckYQjRo2hItnTA,4334
43
+ pulp_python/app/tasks/repair.py,sha256=KQzVhdtjcfFTCco9zk_iETfVETsUqQJSvMV4OBOd7es,12255
44
44
  pulp_python/app/tasks/sync.py,sha256=hBA4iyY9HFbLZMFWqVJ4W3Q3NAN122QVaOSEGSSnMtc,12868
45
45
  pulp_python/app/tasks/upload.py,sha256=12E9ihDqbe9Ihij9o6p_yuV6WF1Yyt6zPeOI2dzCEms,5697
46
46
  pulp_python/app/tasks/vulnerability_report.py,sha256=0cyxNb4048HFUdUlGBA6wYsg-hEMjSfE8mtw05Ct9BQ,1126
@@ -49,7 +49,7 @@ pulp_python/app/webserver_snippets/apache.conf,sha256=3frHSl2YV_8pJPscaFxMVo7Hmx
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=lUkMLsPUOeF7duMB_epr65gDMybLu-JZDWNFKT2Ybio,13820
52
+ pulp_python/tests/functional/constants.py,sha256=SvzlxGQz1I-p3JEBSqNz9qoAYfq5yhGsqtYoJpCOioU,13819
53
53
  pulp_python/tests/functional/utils.py,sha256=ZmOVSa94o0KvH7l42YwuUAcNJo8Eb733QBH2G6nGkeQ,5901
54
54
  pulp_python/tests/functional/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
55
  pulp_python/tests/functional/api/test_attestations.py,sha256=_opUZT65c5H2j_8ous-nKGHmDOw8EMjxdooTIQhiXQ8,8640
@@ -58,11 +58,11 @@ pulp_python/tests/functional/api/test_consume_content.py,sha256=QUOZ_bQ_Ortzitc7
58
58
  pulp_python/tests/functional/api/test_crud_content_unit.py,sha256=GbCDRY5iaLSRvPAvhz1a3mrYu_WN2lOEnFLltT6yL54,8756
59
59
  pulp_python/tests/functional/api/test_crud_publications.py,sha256=uoTGHbhKq_mYOYtNV8Tt9cyhzY0zsoG1DhYrfIdYcMc,5646
60
60
  pulp_python/tests/functional/api/test_crud_remotes.py,sha256=uRo51X3MDWIls4Fdxw5unvU47_JyyLEg2w41ByvDcmY,5811
61
- pulp_python/tests/functional/api/test_domains.py,sha256=-WSW9dnsY7XXHsSCocTk5WUBycmKOvJ96nZLwEMts6M,10211
61
+ pulp_python/tests/functional/api/test_domains.py,sha256=owbvFxOKDuAVX2PUpsO0olAmQmIKFThBqnQtjfKbS8Y,10210
62
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=A_LkhvnoXzm1-F7Qy8dZZcpDo2BPngnhjf55T0bH20E,4513
63
+ pulp_python/tests/functional/api/test_export_import.py,sha256=QciJ7Pdv6HSv3mKGqKSNW5g9M8e9tkWcapRQ1PUxabU,4512
64
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=aQuZy_OO767fT0arc0syE6qtYkFjh0nEmp8Gqo9RDj4,11692
65
+ pulp_python/tests/functional/api/test_pypi_apis.py,sha256=sdovsmCb88aDaEqTe_RKXiBJDaAx5BRRaT1oNPbIAfo,11691
66
66
  pulp_python/tests/functional/api/test_pypi_simple_api.py,sha256=UzO3K3GMqiDUsAMWlxy9xM3kYtnD6e2WYNtwlJWYm-U,7251
67
67
  pulp_python/tests/functional/api/test_rbac.py,sha256=cy1RQHvWKbE4f4aPu33ZdIUBiJBnW8aOXKlDHHcCuxo,10512
68
68
  pulp_python/tests/functional/api/test_repair.py,sha256=8tW4jgR4pAsAswsblZM2NKdGAKnh1zuH7572k2GO4ag,12908
@@ -73,9 +73,9 @@ pulp_python/tests/functional/assets/shelf-reader-0.1.tar.gz.publish.attestation,
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.0.dist-info/licenses/LICENSE,sha256=2ylvL381vKOhdO-w6zkrOxe9lLNBhRQpo9_0EbHC_HM,18046
77
- pulp_python-3.27.0.dist-info/METADATA,sha256=ZO4wvq-YLDUFQSfZk2qEf3iN1A98IhW5g5I_mFAu9Zk,1743
78
- pulp_python-3.27.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
79
- pulp_python-3.27.0.dist-info/entry_points.txt,sha256=HvqLEXjw_dS5jqAwnE5JiRZFE6f-y5SRtitKLPml2To,115
80
- pulp_python-3.27.0.dist-info/top_level.txt,sha256=X0hXgXc_bpbiKqVrkt8jD5_QEiQviKbHDwveQcOcJjo,12
81
- pulp_python-3.27.0.dist-info/RECORD,,
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,,