pulp-python 3.19.1__tar.gz → 3.19.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.
Files changed (82) hide show
  1. {pulp_python-3.19.1 → pulp_python-3.19.3}/CHANGES.md +17 -0
  2. {pulp_python-3.19.1 → pulp_python-3.19.3}/MANIFEST.in +2 -0
  3. {pulp_python-3.19.1 → pulp_python-3.19.3}/PKG-INFO +2 -2
  4. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/__init__.py +5 -3
  5. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/global_access_conditions.py +0 -1
  6. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/management/commands/repair-python-metadata.py +3 -2
  7. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/modelresource.py +1 -0
  8. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/models.py +8 -7
  9. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/pypi/serializers.py +4 -2
  10. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/pypi/views.py +45 -44
  11. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/replica.py +3 -2
  12. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/serializers.py +5 -5
  13. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/tasks/publish.py +2 -3
  14. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/tasks/repair.py +4 -2
  15. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/tasks/sync.py +10 -12
  16. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/tasks/upload.py +4 -3
  17. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/urls.py +1 -1
  18. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/utils.py +7 -6
  19. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/pytest_plugin.py +6 -5
  20. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/functional/api/test_consume_content.py +1 -1
  21. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/functional/api/test_crud_content_unit.py +5 -4
  22. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/functional/api/test_crud_publications.py +6 -5
  23. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/functional/api/test_crud_remotes.py +3 -2
  24. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/functional/api/test_domains.py +7 -6
  25. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/functional/api/test_export_import.py +5 -4
  26. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/functional/api/test_full_mirror.py +58 -12
  27. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/functional/api/test_pypi_apis.py +10 -12
  28. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/functional/api/test_rbac.py +5 -4
  29. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/functional/api/test_repair.py +2 -1
  30. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/functional/api/test_upload.py +1 -0
  31. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/functional/constants.py +8 -6
  32. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python.egg-info/PKG-INFO +2 -2
  33. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python.egg-info/requires.txt +1 -1
  34. {pulp_python-3.19.1 → pulp_python-3.19.3}/pyproject.toml +34 -3
  35. {pulp_python-3.19.1 → pulp_python-3.19.3}/COMMITMENT +0 -0
  36. {pulp_python-3.19.1 → pulp_python-3.19.3}/COPYRIGHT +0 -0
  37. {pulp_python-3.19.1 → pulp_python-3.19.3}/LICENSE +0 -0
  38. {pulp_python-3.19.1 → pulp_python-3.19.3}/README.md +0 -0
  39. {pulp_python-3.19.1 → pulp_python-3.19.3}/functest_requirements.txt +0 -0
  40. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/__init__.py +0 -0
  41. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/management/__init__.py +0 -0
  42. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/management/commands/__init__.py +0 -0
  43. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/migrations/0001_initial.py +0 -0
  44. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/migrations/0001_squashed_0010_update_json_field.py +0 -0
  45. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/migrations/0002_pythonpackagecontent_python_version.py +0 -0
  46. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/migrations/0003_new_sync_filters.py +0 -0
  47. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/migrations/0004_DATA_swap_distribution_model.py +0 -0
  48. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/migrations/0005_pythonpackagecontent_sha256.py +0 -0
  49. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/migrations/0006_pythonrepository_autopublish.py +0 -0
  50. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/migrations/0007_pythonpackagecontent_mv-2-1.py +0 -0
  51. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/migrations/0008_pythonpackagecontent_unique_sha256.py +0 -0
  52. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/migrations/0009_pythondistribution_allow_uploads.py +0 -0
  53. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/migrations/0010_update_json_field.py +0 -0
  54. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/migrations/0011_alter_pythondistribution_distribution_ptr_and_more.py +0 -0
  55. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/migrations/0012_add_domain.py +0 -0
  56. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/migrations/0013_add_rbac_permissions.py +0 -0
  57. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/migrations/0014_pythonpackagecontent_dynamic_and_more.py +0 -0
  58. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/migrations/0015_alter_pythonpackagecontent_options.py +0 -0
  59. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/migrations/__init__.py +0 -0
  60. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/pypi/__init__.py +0 -0
  61. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/settings.py +0 -0
  62. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/tasks/__init__.py +0 -0
  63. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/viewsets.py +0 -0
  64. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/webserver_snippets/__init__.py +0 -0
  65. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/webserver_snippets/apache.conf +0 -0
  66. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/app/webserver_snippets/nginx.conf +0 -0
  67. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/__init__.py +0 -0
  68. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/functional/__init__.py +0 -0
  69. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/functional/api/__init__.py +0 -0
  70. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/functional/api/test_auto_publish.py +0 -0
  71. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/functional/api/test_download_content.py +2 -2
  72. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/functional/api/test_sync.py +11 -11
  73. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/functional/utils.py +2 -2
  74. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/unit/__init__.py +0 -0
  75. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python/tests/unit/test_models.py +0 -0
  76. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python.egg-info/SOURCES.txt +0 -0
  77. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python.egg-info/dependency_links.txt +0 -0
  78. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python.egg-info/entry_points.txt +0 -0
  79. {pulp_python-3.19.1 → pulp_python-3.19.3}/pulp_python.egg-info/top_level.txt +0 -0
  80. {pulp_python-3.19.1 → pulp_python-3.19.3}/setup.cfg +0 -0
  81. {pulp_python-3.19.1 → pulp_python-3.19.3}/test_requirements.txt +0 -0
  82. {pulp_python-3.19.1 → pulp_python-3.19.3}/unittest_requirements.txt +0 -0
@@ -8,6 +8,23 @@
8
8
 
9
9
  [//]: # (towncrier release notes start)
10
10
 
11
+ ## 3.19.3 (2026-05-04) {: #3.19.3 }
12
+
13
+ #### Bugfixes {: #3.19.3-bugfix }
14
+
15
+ - Fixed pull-through caching not checking the repository if package was not present on remote.
16
+ [#1004](https://github.com/pulp/pulp_python/issues/1004)
17
+ - Fixed pull-through caching failing for packages with bad names.
18
+ [#1040](https://github.com/pulp/pulp_python/issues/1040)
19
+
20
+ ---
21
+
22
+ ## 3.19.2 (2026-04-28) {: #3.19.2 }
23
+
24
+ No significant changes.
25
+
26
+ ---
27
+
11
28
  ## 3.19.1 (2025-09-14) {: #3.19.1 }
12
29
 
13
30
  #### Bugfixes {: #3.19.1-bugfix }
@@ -10,3 +10,5 @@ include test_requirements.txt
10
10
  include unittest_requirements.txt
11
11
  include pulp_python/app/webserver_snippets/*
12
12
  exclude releasing.md
13
+
14
+ exclude .gitleaks.toml
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pulp-python
3
- Version: 3.19.1
3
+ Version: 3.19.3
4
4
  Summary: pulp-python plugin for the Pulp Project
5
5
  Author-email: Pulp Team <pulp-list@redhat.com>
6
6
  Project-URL: Homepage, https://pulpproject.org
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python :: 3.13
20
20
  Requires-Python: >=3.11
21
21
  Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
- Requires-Dist: pulpcore<3.100,>=3.81.0
23
+ Requires-Dist: pulpcore<3.100,>=3.85.0
24
24
  Requires-Dist: pkginfo<1.13.0,>=1.12.0
25
25
  Requires-Dist: bandersnatch<6.6,>=6.3.0
26
26
  Requires-Dist: pypi-simple<2.0,>=1.5.0
@@ -1,6 +1,8 @@
1
+ from gettext import gettext as _
2
+
1
3
  from django.db.models.signals import post_migrate
4
+
2
5
  from pulpcore.plugin import PulpPluginAppConfig
3
- from gettext import gettext as _
4
6
 
5
7
 
6
8
  class PulpPythonPluginAppConfig(PulpPluginAppConfig):
@@ -10,7 +12,7 @@ class PulpPythonPluginAppConfig(PulpPluginAppConfig):
10
12
 
11
13
  name = "pulp_python.app"
12
14
  label = "python"
13
- version = "3.19.1"
15
+ version = "3.19.3"
14
16
  python_package_name = "pulp-python"
15
17
  domain_compatible = True
16
18
 
@@ -26,7 +28,7 @@ class PulpPythonPluginAppConfig(PulpPluginAppConfig):
26
28
 
27
29
  # TODO: Remove this when https://github.com/pulp/pulpcore/issues/5500 is resolved
28
30
  def _populate_pypi_access_policies(sender, apps, verbosity, **kwargs):
29
- from pulp_python.app.pypi.views import PyPIView, SimpleView, UploadView, MetadataView
31
+ from pulp_python.app.pypi.views import MetadataView, PyPIView, SimpleView, UploadView
30
32
 
31
33
  try:
32
34
  AccessPolicy = apps.get_model("core", "AccessPolicy")
@@ -1,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
 
@@ -1,11 +1,12 @@
1
- import re
2
1
  import os
3
- from django.core.management import BaseCommand, CommandError
2
+ import re
4
3
  from gettext import gettext as _
5
4
 
6
5
  from django.conf import settings
6
+ from django.core.management import BaseCommand, CommandError
7
7
 
8
8
  from pulpcore.plugin.util import extract_pk
9
+
9
10
  from pulp_python.app.models import PythonPackageContent, PythonRepository
10
11
  from pulp_python.app.utils import artifact_to_python_content_data
11
12
 
@@ -1,6 +1,7 @@
1
1
  from pulpcore.plugin.importexport import BaseContentResource
2
2
  from pulpcore.plugin.modelresources import RepositoryResource
3
3
  from pulpcore.plugin.util import get_domain
4
+
4
5
  from pulp_python.app.models import (
5
6
  PythonPackageContent,
6
7
  PythonRepository,
@@ -1,30 +1,31 @@
1
1
  from logging import getLogger
2
+ from pathlib import PurePath
2
3
 
3
4
  from aiohttp.web import json_response
5
+ from django.conf import settings
4
6
  from django.contrib.postgres.fields import ArrayField
5
7
  from django.core.exceptions import ObjectDoesNotExist
6
8
  from django.db import models
7
- from django.conf import settings
9
+
8
10
  from pulpcore.plugin.models import (
9
11
  AutoAddObjPermsMixin,
10
12
  Content,
11
- Publication,
12
13
  Distribution,
14
+ Publication,
13
15
  Remote,
14
16
  Repository,
15
17
  )
18
+ from pulpcore.plugin.repo_version_utils import remove_duplicates, validate_repo_version
16
19
  from pulpcore.plugin.responses import ArtifactResponse
20
+ from pulpcore.plugin.util import get_domain, get_domain_pk
17
21
 
18
- from pathlib import PurePath
19
22
  from .utils import (
23
+ PYPI_LAST_SERIAL,
24
+ PYPI_SERIAL_CONSTANT,
20
25
  artifact_to_python_content_data,
21
26
  canonicalize_name,
22
27
  python_content_to_json,
23
- PYPI_LAST_SERIAL,
24
- PYPI_SERIAL_CONSTANT,
25
28
  )
26
- from pulpcore.plugin.repo_version_utils import remove_duplicates, validate_repo_version
27
- from pulpcore.plugin.util import get_domain_pk, get_domain
28
29
 
29
30
  log = getLogger(__name__)
30
31
 
@@ -1,11 +1,13 @@
1
1
  import logging
2
2
  from gettext import gettext as _
3
3
 
4
+ from django.db.utils import IntegrityError
4
5
  from rest_framework import serializers
5
- from pulp_python.app.utils import DIST_EXTENSIONS
6
+
6
7
  from pulpcore.plugin.models import Artifact
7
8
  from pulpcore.plugin.util import get_domain
8
- from django.db.utils import IntegrityError
9
+
10
+ from pulp_python.app.utils import DIST_EXTENSIONS
9
11
 
10
12
  log = logging.getLogger(__name__)
11
13
 
@@ -1,57 +1,57 @@
1
1
  import json
2
2
  import logging
3
+ from datetime import datetime, timedelta, timezone
4
+ from itertools import chain
5
+ from pathlib import PurePath
6
+ from urllib.parse import urljoin, urlparse, urlunsplit
3
7
 
4
8
  from aiohttp.client_exceptions import ClientError
5
- from rest_framework.viewsets import ViewSet
6
- from rest_framework.response import Response
7
- from django.core.exceptions import ObjectDoesNotExist
8
- from django.shortcuts import redirect
9
- from datetime import datetime, timezone, timedelta
10
-
11
9
  from django.contrib.sessions.models import Session
10
+ from django.core.exceptions import ObjectDoesNotExist
12
11
  from django.db import transaction
13
12
  from django.db.utils import DatabaseError
14
13
  from django.http.response import (
15
14
  Http404,
16
- HttpResponseForbidden,
15
+ HttpResponse,
17
16
  HttpResponseBadRequest,
17
+ HttpResponseForbidden,
18
+ HttpResponseNotFound,
18
19
  StreamingHttpResponse,
19
- HttpResponse,
20
20
  )
21
+ from django.shortcuts import redirect
21
22
  from drf_spectacular.utils import extend_schema
22
23
  from dynaconf import settings
23
- from itertools import chain
24
24
  from packaging.utils import canonicalize_name
25
- from urllib.parse import urljoin, urlparse, urlunsplit
26
- from pathlib import PurePath
27
25
  from pypi_simple import ACCEPT_JSON_PREFERRED, ProjectPage
26
+ from rest_framework.response import Response
27
+ from rest_framework.viewsets import ViewSet
28
28
 
29
- from pulpcore.plugin.viewsets import OperationPostponedResponse
29
+ from pulpcore.plugin.exceptions import TimeoutException
30
30
  from pulpcore.plugin.tasking import dispatch
31
31
  from pulpcore.plugin.util import get_domain, get_url
32
- from pulpcore.plugin.exceptions import TimeoutException
32
+ from pulpcore.plugin.viewsets import OperationPostponedResponse
33
+
34
+ from pulp_python.app import tasks
33
35
  from pulp_python.app.models import (
34
36
  PythonDistribution,
35
37
  PythonPackageContent,
36
38
  PythonPublication,
37
39
  )
38
40
  from pulp_python.app.pypi.serializers import (
39
- SummarySerializer,
40
41
  PackageMetadataSerializer,
41
42
  PackageUploadSerializer,
42
43
  PackageUploadTaskSerializer,
44
+ SummarySerializer,
43
45
  )
44
46
  from pulp_python.app.utils import (
45
- write_simple_index,
46
- write_simple_detail,
47
- python_content_to_json,
48
47
  PYPI_LAST_SERIAL,
49
48
  PYPI_SERIAL_CONSTANT,
50
49
  get_remote_package_filter,
50
+ python_content_to_json,
51
+ write_simple_detail,
52
+ write_simple_index,
51
53
  )
52
54
 
53
- from pulp_python.app import tasks
54
-
55
55
  log = logging.getLogger(__name__)
56
56
 
57
57
  ORIGIN_HOST = settings.CONTENT_ORIGIN if settings.CONTENT_ORIGIN else settings.PYPI_API_HOSTNAME
@@ -256,7 +256,7 @@ class SimpleView(PackageUploadMixin, ViewSet):
256
256
 
257
257
  rfilter = get_remote_package_filter(remote)
258
258
  if not rfilter.filter_project(package):
259
- raise Http404(f"{package} does not exist.")
259
+ return {}
260
260
 
261
261
  url = remote.get_remote_artifact_url(f"simple/{package}/")
262
262
  remote.headers = remote.headers or []
@@ -264,19 +264,19 @@ class SimpleView(PackageUploadMixin, ViewSet):
264
264
  downloader = remote.get_downloader(url=url, max_retries=1)
265
265
  try:
266
266
  d = downloader.fetch()
267
- except ClientError:
268
- return HttpResponse(f"Failed to fetch {package} from {remote.url}.", status=502)
269
- except TimeoutException:
270
- return HttpResponse(f"{remote.url} timed out while fetching {package}.", status=504)
267
+ except (ClientError, TimeoutException):
268
+ log.info(f"Failed to fetch {package} simple page from {remote.url}")
269
+ return {}
271
270
 
272
271
  if d.headers["content-type"] == "application/vnd.pypi.simple.v1+json":
273
272
  page = ProjectPage.from_json_data(json.load(open(d.path, "rb")), base_url=url)
274
273
  else:
275
274
  page = ProjectPage.from_html(package, open(d.path, "rb").read(), base_url=url)
276
- packages = [
277
- parse_package(p) for p in page.packages if rfilter.filter_release(package, p.version)
278
- ]
279
- return HttpResponse(write_simple_detail(package, packages))
275
+ return {
276
+ p.filename: parse_package(p)
277
+ for p in page.packages
278
+ if rfilter.filter_release(package, p.version)
279
+ }
280
280
 
281
281
  @extend_schema(operation_id="pypi_simple_package_read", summary="Get package simple page")
282
282
  def retrieve(self, request, path, package):
@@ -284,24 +284,25 @@ class SimpleView(PackageUploadMixin, ViewSet):
284
284
  repo_ver, content = self.get_rvc()
285
285
  # Should I redirect if the normalized name is different?
286
286
  normalized = canonicalize_name(package)
287
+ releases = {}
287
288
  if self.distribution.remote:
288
- return self.pull_through_package_simple(normalized, path, self.distribution.remote)
289
- if self.should_redirect(repo_version=repo_ver):
289
+ releases = self.pull_through_package_simple(normalized, path, self.distribution.remote)
290
+ elif self.should_redirect(repo_version=repo_ver):
290
291
  return redirect(urljoin(self.base_content_url, f"{path}/simple/{normalized}/"))
291
- packages = (
292
- content.filter(name__normalize=normalized)
293
- .values_list("filename", "sha256", "name")
294
- .iterator()
295
- )
296
- try:
297
- present = next(packages)
298
- except StopIteration:
299
- raise Http404(f"{normalized} does not exist.")
300
- else:
301
- packages = chain([present], packages)
302
- name = present[2]
303
- releases = ((f, urljoin(self.base_content_url, f"{path}/{f}"), d) for f, d, _ in packages)
304
- return StreamingHttpResponse(write_simple_detail(name, releases, streamed=True))
292
+ if content:
293
+ packages = content.filter(name__normalize=normalized).values("filename", "sha256")
294
+ local_releases = {
295
+ p["filename"]: (
296
+ p["filename"],
297
+ urljoin(self.base_content_url, f"{path}/{p['filename']}"),
298
+ p["sha256"],
299
+ )
300
+ for p in packages
301
+ }
302
+ releases.update(local_releases)
303
+ if not releases:
304
+ return HttpResponseNotFound(f"{normalized} does not exist.")
305
+ return HttpResponse(write_simple_detail(normalized, releases.values()))
305
306
 
306
307
  @extend_schema(
307
308
  request=PackageUploadSerializer,
@@ -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
 
@@ -1,6 +1,7 @@
1
1
  import logging
2
2
  import os
3
3
  from gettext import gettext as _
4
+
4
5
  from django.conf import settings
5
6
  from django.db.utils import IntegrityError
6
7
  from packaging.requirements import Requirement
@@ -18,7 +19,6 @@ from pulp_python.app.utils import (
18
19
  parse_project_metadata,
19
20
  )
20
21
 
21
-
22
22
  log = logging.getLogger(__name__)
23
23
 
24
24
 
@@ -165,7 +165,7 @@ class PythonPackageContentSerializer(core_serializers.SingleArtifactContentUploa
165
165
  required=False,
166
166
  allow_blank=True,
167
167
  help_text=_(
168
- "The maintainer's name at a minimum; " "additional contact information may be provided."
168
+ "The maintainer's name at a minimum; additional contact information may be provided."
169
169
  ),
170
170
  )
171
171
  maintainer_email = serializers.CharField(
@@ -489,7 +489,7 @@ class PythonRemoteSerializer(core_serializers.RemoteSerializer):
489
489
  package_types = MultipleChoiceArrayField(
490
490
  required=False,
491
491
  help_text=_(
492
- "The package types to sync for Python content. Leave blank to get every" "package type."
492
+ "The package types to sync for Python content. Leave blank to get everypackage type."
493
493
  ),
494
494
  choices=python_models.PACKAGE_TYPES,
495
495
  default=list,
@@ -519,7 +519,7 @@ class PythonRemoteSerializer(core_serializers.RemoteSerializer):
519
519
  Requirement(pkg)
520
520
  except ValueError as ve:
521
521
  raise serializers.ValidationError(
522
- _("includes specifier {} is invalid. {}".format(pkg, ve))
522
+ _("includes specifier {} is invalid. {}").format(pkg, ve)
523
523
  )
524
524
  return value
525
525
 
@@ -530,7 +530,7 @@ class PythonRemoteSerializer(core_serializers.RemoteSerializer):
530
530
  Requirement(pkg)
531
531
  except ValueError as ve:
532
532
  raise serializers.ValidationError(
533
- _("excludes specifier {} is invalid. {}".format(pkg, ve))
533
+ _("excludes specifier {} is invalid. {}").format(pkg, ve)
534
534
  )
535
535
  return value
536
536
 
@@ -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
@@ -9,8 +9,7 @@ from pulpcore.plugin import models
9
9
  from pulpcore.plugin.util import get_domain
10
10
 
11
11
  from pulp_python.app import models as python_models
12
- from pulp_python.app.utils import write_simple_index, write_simple_detail
13
-
12
+ from pulp_python.app.utils import write_simple_detail, write_simple_index
14
13
 
15
14
  log = logging.getLogger(__name__)
16
15
 
@@ -6,14 +6,16 @@ from uuid import UUID
6
6
 
7
7
  from django.db.models import Prefetch
8
8
  from django.db.models.query import QuerySet
9
+
10
+ from pulpcore.plugin.models import ContentArtifact, ProgressReport
11
+ from pulpcore.plugin.util import get_domain
12
+
9
13
  from pulp_python.app.models import PythonPackageContent, PythonRepository
10
14
  from pulp_python.app.utils import (
11
15
  artifact_to_python_content_data,
12
16
  fetch_json_release_metadata,
13
17
  parse_metadata,
14
18
  )
15
- from pulpcore.plugin.models import ContentArtifact, ProgressReport
16
- from pulpcore.plugin.util import get_domain
17
19
 
18
20
  log = logging.getLogger(__name__)
19
21
 
@@ -1,10 +1,15 @@
1
1
  import logging
2
-
3
- from aiohttp import ClientResponseError, ClientError
4
- from lxml.etree import LxmlError
5
- from gettext import gettext as _
6
2
  from functools import partial
3
+ from gettext import gettext as _
4
+ from urllib.parse import urljoin
7
5
 
6
+ from aiohttp import ClientError, ClientResponseError
7
+ from bandersnatch.configuration import BandersnatchConfig
8
+ from bandersnatch.master import Master
9
+ from bandersnatch.mirror import Mirror
10
+ from lxml.etree import LxmlError
11
+ from packaging.requirements import Requirement
12
+ from pypi_simple import IndexPage
8
13
  from rest_framework import serializers
9
14
 
10
15
  from pulpcore.plugin.download import HttpDownloader
@@ -20,14 +25,7 @@ from pulp_python.app.models import (
20
25
  PythonPackageContent,
21
26
  PythonRemote,
22
27
  )
23
- from pulp_python.app.utils import parse_metadata, PYPI_LAST_SERIAL
24
- from pypi_simple import IndexPage
25
-
26
- from bandersnatch.mirror import Mirror
27
- from bandersnatch.master import Master
28
- from bandersnatch.configuration import BandersnatchConfig
29
- from packaging.requirements import Requirement
30
- from urllib.parse import urljoin
28
+ from pulp_python.app.utils import PYPI_LAST_SERIAL, parse_metadata
31
29
 
32
30
  logger = logging.getLogger(__name__)
33
31
 
@@ -1,9 +1,10 @@
1
1
  import time
2
-
3
2
  from datetime import datetime, timezone
4
- from django.db import transaction
3
+
5
4
  from django.contrib.sessions.models import Session
6
- from pulpcore.plugin.models import Artifact, CreatedResource, ContentArtifact
5
+ from django.db import transaction
6
+
7
+ from pulpcore.plugin.models import Artifact, ContentArtifact, CreatedResource
7
8
  from pulpcore.plugin.util import get_domain
8
9
 
9
10
  from pulp_python.app.models import PythonPackageContent, PythonRepository
@@ -1,7 +1,7 @@
1
1
  from django.conf import settings
2
2
  from django.urls import path
3
3
 
4
- from pulp_python.app.pypi.views import SimpleView, MetadataView, PyPIView, UploadView
4
+ from pulp_python.app.pypi.views import MetadataView, PyPIView, SimpleView, UploadView
5
5
 
6
6
  if settings.DOMAIN_ENABLED:
7
7
  PYPI_API_URL = "pypi/<slug:pulp_domain>/<path:path>/"
@@ -1,16 +1,17 @@
1
- import pkginfo
1
+ import json
2
2
  import re
3
3
  import shutil
4
4
  import tempfile
5
- import json
6
5
  from collections import defaultdict
6
+
7
+ import pkginfo
7
8
  from django.conf import settings
8
9
  from jinja2 import Template
9
- from packaging.utils import canonicalize_name
10
10
  from packaging.requirements import Requirement
11
- from packaging.version import parse, InvalidVersion
12
- from pulpcore.plugin.models import Remote
11
+ from packaging.utils import canonicalize_name
12
+ from packaging.version import InvalidVersion, parse
13
13
 
14
+ from pulpcore.plugin.models import Remote
14
15
 
15
16
  PYPI_LAST_SERIAL = "X-PYPI-LAST-SERIAL"
16
17
  """TODO This serial constant is temporary until Python repositories implements serials"""
@@ -457,7 +458,7 @@ class PackageIncludeFilter:
457
458
 
458
459
  try:
459
460
  version = parse(version)
460
- except InvalidVersion:
461
+ except (InvalidVersion, TypeError):
461
462
  return False
462
463
 
463
464
  include_range = self._filter_includes.get("range", {})
@@ -1,16 +1,17 @@
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_FIXTURE_URL,
10
11
  PYTHON_URL,
12
+ PYTHON_XS_PROJECT_SPECIFIER,
11
13
  )
12
14
 
13
-
14
15
  # Bindings API Fixtures
15
16
 
16
17
 
@@ -1,5 +1,4 @@
1
1
  import subprocess
2
-
3
2
  from urllib.parse import urlsplit
4
3
 
5
4
 
@@ -21,6 +20,7 @@ def test_pip_consume_content(
21
20
  "install",
22
21
  "--no-deps",
23
22
  "--no-cache-dir",
23
+ "--no-build-isolation",
24
24
  "--force-reinstall",
25
25
  "--trusted-host",
26
26
  urlsplit(distro.base_url).hostname,
@@ -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
  )
14
15
 
@@ -1,13 +1,14 @@
1
- import pytest
2
1
  import random
3
- from pypi_simple import PyPISimple
4
2
  from urllib.parse import urljoin
5
3
 
4
+ import pytest
5
+ from pypi_simple import PyPISimple
6
+
6
7
  from pulp_python.tests.functional.constants import (
7
- PYTHON_SM_PROJECT_SPECIFIER,
8
- PYTHON_SM_FIXTURE_RELEASES,
9
- PYTHON_SM_FIXTURE_CHECKSUMS,
10
8
  PYTHON_EGG_FILENAME,
9
+ PYTHON_SM_FIXTURE_CHECKSUMS,
10
+ PYTHON_SM_FIXTURE_RELEASES,
11
+ PYTHON_SM_PROJECT_SPECIFIER,
11
12
  PYTHON_WHEEL_FILENAME,
12
13
  )
13
14
  from pulp_python.tests.functional.utils import ensure_simple
@@ -1,11 +1,12 @@
1
- import pytest
2
1
  import uuid
3
2
 
3
+ import pytest
4
+
4
5
  from pulp_python.tests.functional.constants import (
5
6
  BANDERSNATCH_CONF,
6
7
  DEFAULT_BANDER_REMOTE_BODY,
7
- PYTHON_INVALID_SPECIFIER_NO_NAME,
8
8
  PYTHON_INVALID_SPECIFIER_BAD_VERSION,
9
+ PYTHON_INVALID_SPECIFIER_NO_NAME,
9
10
  PYTHON_VALID_SPECIFIER_NO_VERSION,
10
11
  )
11
12
 
@@ -1,17 +1,17 @@
1
- import pytest
2
- import uuid
3
1
  import json
4
2
  import subprocess
3
+ import uuid
4
+ from urllib.parse import urlsplit
5
+
6
+ import pytest
5
7
 
6
- from pulpcore.app import settings
8
+ from pulpcore.app import settings # noqa: TID251
7
9
 
8
10
  from pulp_python.tests.functional.constants import (
9
11
  PYTHON_EGG_FILENAME,
10
- PYTHON_SM_PROJECT_SPECIFIER,
11
12
  PYTHON_SM_PACKAGE_COUNT,
13
+ PYTHON_SM_PROJECT_SPECIFIER,
12
14
  )
13
- from urllib.parse import urlsplit
14
-
15
15
 
16
16
  pytestmark = pytest.mark.skipif(not settings.DOMAIN_ENABLED, reason="Domain not enabled")
17
17
 
@@ -270,6 +270,7 @@ def test_domain_pypi_apis(
270
270
  "pip",
271
271
  "install",
272
272
  "--no-deps",
273
+ "--no-build-isolation",
273
274
  "--trusted-host",
274
275
  urlsplit(distro.base_url).hostname,
275
276
  "-i",
@@ -5,16 +5,17 @@ NOTE: assumes ALLOWED_EXPORT_PATHS setting contains "/tmp" - all tests will fail
5
5
  the case.
6
6
  """
7
7
 
8
- import pytest
9
8
  import uuid
10
9
 
11
- from pulpcore.app import settings
10
+ import pytest
11
+
12
+ from pulpcore.app import settings # noqa: TID251
13
+
12
14
  from pulp_python.tests.functional.constants import (
13
- PYTHON_XS_PROJECT_SPECIFIER,
14
15
  PYTHON_SM_PROJECT_SPECIFIER,
16
+ PYTHON_XS_PROJECT_SPECIFIER,
15
17
  )
16
18
 
17
-
18
19
  pytestmark = [
19
20
  pytest.mark.skipif(settings.DOMAIN_ENABLED, reason="Domains do not support export."),
20
21
  pytest.mark.skipif(
@@ -1,19 +1,19 @@
1
+ import subprocess
2
+ from random import sample
3
+ from urllib.parse import urljoin, urlsplit
4
+
1
5
  import pytest
2
6
  import requests
3
- import subprocess
7
+ from packaging.version import parse
8
+ from pypi_simple import ProjectPage
4
9
 
5
10
  from pulp_python.tests.functional.constants import (
6
11
  PYPI_URL,
7
- PYTHON_XS_FIXTURE_CHECKSUMS,
8
- PYTHON_SM_PROJECT_SPECIFIER,
9
12
  PYTHON_SM_FIXTURE_RELEASES,
13
+ PYTHON_SM_PROJECT_SPECIFIER,
14
+ PYTHON_XS_FIXTURE_CHECKSUMS,
10
15
  )
11
16
 
12
- from pypi_simple import ProjectPage
13
- from packaging.version import parse
14
- from urllib.parse import urljoin, urlsplit
15
- from random import sample
16
-
17
17
 
18
18
  def test_pull_through_install(
19
19
  python_bindings, python_remote_factory, python_distribution_factory, delete_orphans_pre
@@ -66,7 +66,7 @@ def test_pull_through_filter(python_remote_factory, python_distribution_factory)
66
66
 
67
67
  r = requests.get(f"{distro.base_url}simple/pulpcore/")
68
68
  assert r.status_code == 404
69
- assert r.json() == {"detail": "pulpcore does not exist."}
69
+ assert r.text == "pulpcore does not exist."
70
70
 
71
71
  r = requests.get(f"{distro.base_url}simple/shelf-reader/")
72
72
  assert r.status_code == 200
@@ -86,11 +86,11 @@ def test_pull_through_filter(python_remote_factory, python_distribution_factory)
86
86
 
87
87
  r = requests.get(f"{distro.base_url}simple/django/")
88
88
  assert r.status_code == 404
89
- assert r.json() == {"detail": "django does not exist."}
89
+ assert r.text == "django does not exist."
90
90
 
91
91
  r = requests.get(f"{distro.base_url}simple/pulpcore/")
92
- assert r.status_code == 502
93
- assert r.text == f"Failed to fetch pulpcore from {remote.url}."
92
+ assert r.status_code == 404
93
+ assert r.text == "pulpcore does not exist."
94
94
 
95
95
  r = requests.get(f"{distro.base_url}simple/shelf-reader/")
96
96
  assert r.status_code == 200
@@ -138,3 +138,49 @@ def test_pull_through_with_repo(
138
138
  assert r.status_code == 200
139
139
  tasks = pulpcore_bindings.TasksApi.list(reserved_resources=repo.prn)
140
140
  assert tasks.count == 3
141
+
142
+
143
+ @pytest.mark.parallel
144
+ def test_pull_through_local_only(
145
+ python_remote_factory, python_distribution_factory, python_repo_with_sync
146
+ ):
147
+ """Tests that pull-through checks the repository if the package is not present on the remote."""
148
+ remote = python_remote_factory(url=PYPI_URL, includes=["pulpcore"])
149
+ repo = python_repo_with_sync(remote=remote)
150
+ remote2 = python_remote_factory(includes=[]) # Fixtures does not have pulpcore
151
+ distro = python_distribution_factory(repository=repo.pulp_href, remote=remote2.pulp_href)
152
+
153
+ url = f"{distro.base_url}simple/pulpcore/"
154
+ r = requests.get(url)
155
+ assert r.status_code == 200
156
+ assert "?redirect=" not in r.text
157
+
158
+ url = f"{distro.base_url}simple/shelf-reader/"
159
+ r = requests.get(url)
160
+ assert r.status_code == 200
161
+ assert "?redirect=" in r.text
162
+
163
+ url = f"{distro.base_url}simple/pulp_python/"
164
+ r = requests.get(url)
165
+ assert r.status_code == 404
166
+ assert r.text == "pulp-python does not exist."
167
+
168
+
169
+ @pytest.mark.parallel
170
+ def test_pull_through_filtering_bad_names(python_remote_factory, python_distribution_factory):
171
+ """Tests that pull-through handles packages with invalid names gracefully."""
172
+ # ipython version 0.13.X has improper named bdist_wininst, e.g ipython-0.13.py2-win-amd64.exe
173
+ # pypi-simple expects the platform to go before the pyversion (for .exe), so when parsed the
174
+ # version and package type will be None.
175
+ remote = python_remote_factory(url=PYPI_URL, includes=["ipython"])
176
+ distro = python_distribution_factory(remote=remote.pulp_href)
177
+
178
+ url = f"{distro.base_url}simple/ipython/"
179
+ response = requests.get(url)
180
+
181
+ assert response.status_code == 200
182
+
183
+ project_page = ProjectPage.from_response(response, "ipython")
184
+ # Should have no packages with None version (they get filtered out)
185
+ assert len(project_page.packages) > 0
186
+ assert all(package.version is not None for package in project_page.packages)
@@ -1,27 +1,25 @@
1
- import pytest
2
- import requests
3
1
  import subprocess
4
-
5
2
  from urllib.parse import urljoin
6
3
 
4
+ import pytest
5
+ import requests
6
+
7
7
  from pulp_python.tests.functional.constants import (
8
- PYTHON_SM_PROJECT_SPECIFIER,
9
- PYTHON_SM_FIXTURE_RELEASES,
10
- PYTHON_SM_FIXTURE_CHECKSUMS,
11
- PYTHON_MD_PROJECT_SPECIFIER,
12
- PYTHON_MD_PYPI_SUMMARY,
13
8
  PYTHON_EGG_FILENAME,
14
- PYTHON_EGG_URL,
15
9
  PYTHON_EGG_SHA256,
10
+ PYTHON_EGG_URL,
11
+ PYTHON_MD_PROJECT_SPECIFIER,
12
+ PYTHON_MD_PYPI_SUMMARY,
13
+ PYTHON_SM_FIXTURE_CHECKSUMS,
14
+ PYTHON_SM_FIXTURE_RELEASES,
15
+ PYTHON_SM_PROJECT_SPECIFIER,
16
16
  PYTHON_WHEEL_FILENAME,
17
- PYTHON_WHEEL_URL,
18
17
  PYTHON_WHEEL_SHA256,
18
+ PYTHON_WHEEL_URL,
19
19
  SHELF_PYTHON_JSON,
20
20
  )
21
-
22
21
  from pulp_python.tests.functional.utils import ensure_simple
23
22
 
24
-
25
23
  PYPI_LAST_SERIAL = "X-PYPI-LAST-SERIAL"
26
24
  PYPI_SERIAL_CONSTANT = 1000000000
27
25
 
@@ -1,6 +1,7 @@
1
- import pytest
2
1
  import uuid
3
2
 
3
+ import pytest
4
+
4
5
  from pulp_python.tests.functional.constants import (
5
6
  PYTHON_EGG_FILENAME,
6
7
  PYTHON_EGG_SHA256,
@@ -44,9 +45,9 @@ def try_action(python_bindings, monitor_task):
44
45
  except python_bindings.module.ApiException as e:
45
46
  assert e.status == outcome, f"{e}"
46
47
  else:
47
- assert (
48
- status_code == outcome
49
- ), f"User performed {action} when they shouldn't been able to"
48
+ assert status_code == outcome, (
49
+ f"User performed {action} when they shouldn't been able to"
50
+ )
50
51
  return data
51
52
 
52
53
  return _try_action
@@ -1,7 +1,8 @@
1
- import pytest
2
1
  import subprocess
3
2
  from urllib.parse import urljoin
4
3
 
4
+ import pytest
5
+
5
6
  from pulp_python.tests.functional.constants import (
6
7
  PYTHON_EGG_FILENAME,
7
8
  PYTHON_FIXTURES_URL,
@@ -1,4 +1,5 @@
1
1
  import pytest
2
+
2
3
  from pulp_python.tests.functional.constants import (
3
4
  PYTHON_EGG_FILENAME,
4
5
  PYTHON_EGG_URL,
@@ -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
  )
@@ -112,19 +111,22 @@ PYTHON_LG_PROJECT_SPECIFIER = [
112
111
  "aiohttp", # matches 7
113
112
  "bcrypt", # matches 8
114
113
  "celery", # matches 13
114
+ "crane", # matches 0
115
115
  "Django", # matches 31
116
+ "pulp-2to3-migration", # matches 2
116
117
  "pytz", # matches 6
117
118
  "scipy", # matches 23
118
119
  "setuptools", # matches 2
119
120
  "shelf-reader", # matches 2
121
+ "twine", # matches 14
120
122
  ]
121
- PYTHON_LG_PACKAGE_COUNT = 92
123
+ PYTHON_LG_PACKAGE_COUNT = 108
122
124
  PYTHON_LG_FIXTURE_SUMMARY = {PYTHON_CONTENT_NAME: PYTHON_LG_PACKAGE_COUNT}
123
125
  PYTHON_LG_FIXTURE_COUNTS = {
124
- "latest_3": 51,
125
- "sdist": 28,
126
- "bdist_wheel": 64,
127
- "multi": 34, # keep_latest=1, package_types="bdist_wheel", prereleases=False
126
+ "latest_3": 59,
127
+ "sdist": 36,
128
+ "bdist_wheel": 72,
129
+ "multi": 36, # keep_latest=1, package_types="bdist_wheel", prereleases=False
128
130
  }
129
131
 
130
132
  DJANGO_LATEST_3 = 4 # latest version has 2 dists, each other has 1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pulp-python
3
- Version: 3.19.1
3
+ Version: 3.19.3
4
4
  Summary: pulp-python plugin for the Pulp Project
5
5
  Author-email: Pulp Team <pulp-list@redhat.com>
6
6
  Project-URL: Homepage, https://pulpproject.org
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python :: 3.13
20
20
  Requires-Python: >=3.11
21
21
  Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
- Requires-Dist: pulpcore<3.100,>=3.81.0
23
+ Requires-Dist: pulpcore<3.100,>=3.85.0
24
24
  Requires-Dist: pkginfo<1.13.0,>=1.12.0
25
25
  Requires-Dist: bandersnatch<6.6,>=6.3.0
26
26
  Requires-Dist: pypi-simple<2.0,>=1.5.0
@@ -1,4 +1,4 @@
1
- pulpcore<3.100,>=3.81.0
1
+ pulpcore<3.100,>=3.85.0
2
2
  pkginfo<1.13.0,>=1.12.0
3
3
  bandersnatch<6.6,>=6.3.0
4
4
  pypi-simple<2.0,>=1.5.0
@@ -7,7 +7,7 @@ build-backend = 'setuptools.build_meta'
7
7
 
8
8
  [project]
9
9
  name = "pulp-python"
10
- version = "3.19.1"
10
+ version = "3.19.3"
11
11
  description = "pulp-python plugin for the Pulp Project"
12
12
  readme = "README.md"
13
13
  authors = [
@@ -26,7 +26,7 @@ classifiers=[
26
26
  ]
27
27
  requires-python = ">=3.11"
28
28
  dependencies = [
29
- "pulpcore>=3.81.0,<3.100",
29
+ "pulpcore>=3.85.0,<3.100",
30
30
  "pkginfo>=1.12.0,<1.13.0",
31
31
  "bandersnatch>=6.3.0,<6.6", # 6.6 has breaking changes
32
32
  "pypi-simple>=1.5.0,<2.0",
@@ -71,12 +71,14 @@ ignore = [
71
71
  ".github/**",
72
72
  "lint_requirements.txt",
73
73
  ".flake8",
74
+ "AGENTS.md",
75
+ "CLAUDE.md",
74
76
  ]
75
77
 
76
78
  [tool.bumpversion]
77
79
  # This section is managed by the plugin template. Do not edit manually.
78
80
 
79
- current_version = "3.19.1"
81
+ current_version = "3.19.3"
80
82
  commit = false
81
83
  tag = false
82
84
  parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<alpha>0a)?(?P<patch>\\d+)(\\.(?P<release>[a-z]+))?"
@@ -121,5 +123,34 @@ replace = "version = \"{new_version}\""
121
123
  filename = "./pyproject.toml"
122
124
  search = "version = \"{current_version}\""
123
125
  replace = "version = \"{new_version}\""
126
+
127
+
124
128
  [tool.black]
125
129
  line-length = 100
130
+
131
+ [tool.ruff]
132
+ # This section is managed by the plugin template. Do not edit manually.
133
+ line-length = 100
134
+ extend-exclude = [
135
+ "docs/**",
136
+ "**/migrations/*.py",
137
+ ]
138
+
139
+ [tool.ruff.lint]
140
+ # This section is managed by the plugin template. Do not edit manually.
141
+ extend-select = [
142
+ "I",
143
+ "INT",
144
+ "TID",
145
+ "T10",
146
+ ]
147
+
148
+ [tool.ruff.lint.flake8-tidy-imports.banned-api]
149
+ # This section is managed by the plugin template. Do not edit manually.
150
+ "distutils".msg = "The 'distutils' module has been deprecated since Python 3.9."
151
+ "pulpcore.app".msg = "The 'pulpcore' apis must only be consumed via 'pulpcore.plugin'."
152
+
153
+ [tool.ruff.lint.isort]
154
+ # This section is managed by the plugin template. Do not edit manually.
155
+ sections = { second-party = ["pulpcore"] }
156
+ section-order = ["future", "standard-library", "third-party", "second-party", "first-party", "local-folder"]
File without changes
File without changes
File without changes
File without changes
@@ -1,10 +1,10 @@
1
1
  import pytest
2
2
 
3
3
  from pulp_python.tests.functional.constants import (
4
- PYTHON_MD_PROJECT_SPECIFIER,
4
+ PYTHON_LG_PACKAGE_COUNT,
5
5
  PYTHON_LG_PROJECT_SPECIFIER,
6
6
  PYTHON_MD_PACKAGE_COUNT,
7
- PYTHON_LG_PACKAGE_COUNT,
7
+ PYTHON_MD_PROJECT_SPECIFIER,
8
8
  )
9
9
 
10
10
 
@@ -1,21 +1,21 @@
1
1
  import pytest
2
2
 
3
3
  from pulp_python.tests.functional.constants import (
4
- PYTHON_XS_PACKAGE_COUNT,
5
- PYTHON_PRERELEASE_TEST_SPECIFIER,
6
- PYTHON_WITH_PRERELEASE_COUNT,
7
- PYTHON_WITHOUT_PRERELEASE_COUNT,
8
- PYTHON_XS_PROJECT_SPECIFIER,
9
- PYTHON_MD_PROJECT_SPECIFIER,
4
+ DJANGO_LATEST_3,
5
+ PYTHON_LG_FIXTURE_COUNTS,
6
+ PYTHON_LG_PACKAGE_COUNT,
7
+ PYTHON_LG_PROJECT_SPECIFIER,
10
8
  PYTHON_MD_PACKAGE_COUNT,
11
- PYTHON_SM_PROJECT_SPECIFIER,
9
+ PYTHON_MD_PROJECT_SPECIFIER,
10
+ PYTHON_PRERELEASE_TEST_SPECIFIER,
12
11
  PYTHON_SM_PACKAGE_COUNT,
12
+ PYTHON_SM_PROJECT_SPECIFIER,
13
13
  PYTHON_UNAVAILABLE_PACKAGE_COUNT,
14
14
  PYTHON_UNAVAILABLE_PROJECT_SPECIFIER,
15
- PYTHON_LG_PROJECT_SPECIFIER,
16
- PYTHON_LG_PACKAGE_COUNT,
17
- PYTHON_LG_FIXTURE_COUNTS,
18
- DJANGO_LATEST_3,
15
+ PYTHON_WITH_PRERELEASE_COUNT,
16
+ PYTHON_WITHOUT_PRERELEASE_COUNT,
17
+ PYTHON_XS_PACKAGE_COUNT,
18
+ PYTHON_XS_PROJECT_SPECIFIER,
19
19
  SCIPY_COUNTS,
20
20
  )
21
21
 
@@ -1,6 +1,6 @@
1
- import requests
2
-
3
1
  from urllib.parse import urljoin
2
+
3
+ import requests
4
4
  from lxml import html
5
5
 
6
6
 
File without changes