pulp-python 3.19.0__tar.gz → 3.19.2__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.0 → pulp_python-3.19.2}/CHANGES.md +15 -0
  2. {pulp_python-3.19.0 → pulp_python-3.19.2}/MANIFEST.in +2 -0
  3. {pulp_python-3.19.0 → pulp_python-3.19.2}/PKG-INFO +2 -2
  4. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/__init__.py +5 -3
  5. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/global_access_conditions.py +0 -1
  6. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/management/commands/repair-python-metadata.py +3 -2
  7. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/modelresource.py +1 -0
  8. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/models.py +8 -7
  9. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/pypi/serializers.py +4 -2
  10. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/pypi/views.py +18 -19
  11. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/replica.py +3 -2
  12. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/serializers.py +5 -5
  13. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/tasks/publish.py +9 -10
  14. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/tasks/repair.py +4 -2
  15. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/tasks/sync.py +10 -12
  16. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/tasks/upload.py +4 -3
  17. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/urls.py +1 -1
  18. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/utils.py +6 -5
  19. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/pytest_plugin.py +7 -6
  20. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/functional/api/test_consume_content.py +1 -1
  21. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/functional/api/test_crud_content_unit.py +5 -4
  22. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/functional/api/test_crud_publications.py +32 -4
  23. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/functional/api/test_crud_remotes.py +3 -2
  24. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/functional/api/test_domains.py +7 -6
  25. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/functional/api/test_export_import.py +5 -4
  26. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/functional/api/test_pypi_apis.py +10 -32
  27. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/functional/api/test_rbac.py +5 -4
  28. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/functional/api/test_repair.py +2 -1
  29. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/functional/api/test_upload.py +1 -0
  30. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/functional/constants.py +8 -6
  31. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python.egg-info/PKG-INFO +2 -2
  32. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python.egg-info/requires.txt +1 -1
  33. {pulp_python-3.19.0 → pulp_python-3.19.2}/pyproject.toml +33 -3
  34. {pulp_python-3.19.0 → pulp_python-3.19.2}/COMMITMENT +0 -0
  35. {pulp_python-3.19.0 → pulp_python-3.19.2}/COPYRIGHT +0 -0
  36. {pulp_python-3.19.0 → pulp_python-3.19.2}/LICENSE +0 -0
  37. {pulp_python-3.19.0 → pulp_python-3.19.2}/README.md +0 -0
  38. {pulp_python-3.19.0 → pulp_python-3.19.2}/functest_requirements.txt +0 -0
  39. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/__init__.py +0 -0
  40. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/management/__init__.py +0 -0
  41. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/management/commands/__init__.py +0 -0
  42. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/migrations/0001_initial.py +0 -0
  43. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/migrations/0001_squashed_0010_update_json_field.py +0 -0
  44. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/migrations/0002_pythonpackagecontent_python_version.py +0 -0
  45. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/migrations/0003_new_sync_filters.py +0 -0
  46. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/migrations/0004_DATA_swap_distribution_model.py +0 -0
  47. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/migrations/0005_pythonpackagecontent_sha256.py +0 -0
  48. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/migrations/0006_pythonrepository_autopublish.py +0 -0
  49. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/migrations/0007_pythonpackagecontent_mv-2-1.py +0 -0
  50. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/migrations/0008_pythonpackagecontent_unique_sha256.py +0 -0
  51. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/migrations/0009_pythondistribution_allow_uploads.py +0 -0
  52. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/migrations/0010_update_json_field.py +0 -0
  53. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/migrations/0011_alter_pythondistribution_distribution_ptr_and_more.py +0 -0
  54. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/migrations/0012_add_domain.py +0 -0
  55. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/migrations/0013_add_rbac_permissions.py +0 -0
  56. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/migrations/0014_pythonpackagecontent_dynamic_and_more.py +0 -0
  57. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/migrations/0015_alter_pythonpackagecontent_options.py +0 -0
  58. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/migrations/__init__.py +0 -0
  59. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/pypi/__init__.py +0 -0
  60. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/settings.py +0 -0
  61. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/tasks/__init__.py +0 -0
  62. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/viewsets.py +0 -0
  63. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/webserver_snippets/__init__.py +0 -0
  64. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/webserver_snippets/apache.conf +0 -0
  65. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/app/webserver_snippets/nginx.conf +0 -0
  66. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/__init__.py +0 -0
  67. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/functional/__init__.py +0 -0
  68. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/functional/api/__init__.py +0 -0
  69. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/functional/api/test_auto_publish.py +0 -0
  70. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/functional/api/test_download_content.py +2 -2
  71. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/functional/api/test_full_mirror.py +8 -8
  72. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/functional/api/test_sync.py +11 -11
  73. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/functional/utils.py +2 -2
  74. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/unit/__init__.py +0 -0
  75. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python/tests/unit/test_models.py +0 -0
  76. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python.egg-info/SOURCES.txt +0 -0
  77. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python.egg-info/dependency_links.txt +0 -0
  78. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python.egg-info/entry_points.txt +0 -0
  79. {pulp_python-3.19.0 → pulp_python-3.19.2}/pulp_python.egg-info/top_level.txt +0 -0
  80. {pulp_python-3.19.0 → pulp_python-3.19.2}/setup.cfg +0 -0
  81. {pulp_python-3.19.0 → pulp_python-3.19.2}/test_requirements.txt +0 -0
  82. {pulp_python-3.19.0 → pulp_python-3.19.2}/unittest_requirements.txt +0 -0
@@ -8,6 +8,21 @@
8
8
 
9
9
  [//]: # (towncrier release notes start)
10
10
 
11
+ ## 3.19.2 (2026-04-28) {: #3.19.2 }
12
+
13
+ No significant changes.
14
+
15
+ ---
16
+
17
+ ## 3.19.1 (2025-09-14) {: #3.19.1 }
18
+
19
+ #### Bugfixes {: #3.19.1-bugfix }
20
+
21
+ - Fixed publication error when package's dists contain differing versions of its name.
22
+ [#907](https://github.com/pulp/pulp_python/issues/907)
23
+
24
+ ---
25
+
11
26
  ## 3.19.0 (2025-08-26) {: #3.19.0 }
12
27
 
13
28
  #### Features {: #3.19.0-feature }
@@ -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.0
3
+ Version: 3.19.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
@@ -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.0"
15
+ version = "3.19.2"
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,56 @@
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
18
  StreamingHttpResponse,
19
- HttpResponse,
20
19
  )
20
+ from django.shortcuts import redirect
21
21
  from drf_spectacular.utils import extend_schema
22
22
  from dynaconf import settings
23
- from itertools import chain
24
23
  from packaging.utils import canonicalize_name
25
- from urllib.parse import urljoin, urlparse, urlunsplit
26
- from pathlib import PurePath
27
24
  from pypi_simple import ACCEPT_JSON_PREFERRED, ProjectPage
25
+ from rest_framework.response import Response
26
+ from rest_framework.viewsets import ViewSet
28
27
 
29
- from pulpcore.plugin.viewsets import OperationPostponedResponse
28
+ from pulpcore.plugin.exceptions import TimeoutException
30
29
  from pulpcore.plugin.tasking import dispatch
31
30
  from pulpcore.plugin.util import get_domain, get_url
32
- from pulpcore.plugin.exceptions import TimeoutException
31
+ from pulpcore.plugin.viewsets import OperationPostponedResponse
32
+
33
+ from pulp_python.app import tasks
33
34
  from pulp_python.app.models import (
34
35
  PythonDistribution,
35
36
  PythonPackageContent,
36
37
  PythonPublication,
37
38
  )
38
39
  from pulp_python.app.pypi.serializers import (
39
- SummarySerializer,
40
40
  PackageMetadataSerializer,
41
41
  PackageUploadSerializer,
42
42
  PackageUploadTaskSerializer,
43
+ SummarySerializer,
43
44
  )
44
45
  from pulp_python.app.utils import (
45
- write_simple_index,
46
- write_simple_detail,
47
- python_content_to_json,
48
46
  PYPI_LAST_SERIAL,
49
47
  PYPI_SERIAL_CONSTANT,
50
48
  get_remote_package_filter,
49
+ python_content_to_json,
50
+ write_simple_detail,
51
+ write_simple_index,
51
52
  )
52
53
 
53
- from pulp_python.app import tasks
54
-
55
54
  log = logging.getLogger(__name__)
56
55
 
57
56
  ORIGIN_HOST = settings.CONTENT_ORIGIN if settings.CONTENT_ORIGIN else settings.PYPI_API_HOSTNAME
@@ -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
 
@@ -59,9 +58,9 @@ def write_simple_api(publication):
59
58
  python_models.PythonPackageContent.objects.filter(
60
59
  pk__in=publication.repository_version.content, _pulp_domain=domain
61
60
  )
62
- .order_by("name")
61
+ .order_by("name__normalize")
63
62
  .values_list("name", flat=True)
64
- .distinct()
63
+ .distinct("name__normalize")
65
64
  )
66
65
 
67
66
  # write the root index, which lists all of the projects for which there is a package available
@@ -80,22 +79,22 @@ def write_simple_api(publication):
80
79
  packages = python_models.PythonPackageContent.objects.filter(
81
80
  pk__in=publication.repository_version.content, _pulp_domain=domain
82
81
  )
83
- releases = packages.order_by("name").values("name", "filename", "sha256")
82
+ releases = packages.order_by("name__normalize").values("name", "filename", "sha256")
84
83
 
85
84
  ind = 0
86
- current_name = project_names[ind]
85
+ current_name = canonicalize_name(project_names[ind])
87
86
  package_releases = []
88
87
  for release in releases.iterator():
89
- if release["name"] != current_name:
88
+ if canonicalize_name(release["name"]) != current_name:
90
89
  write_project_page(
91
- name=canonicalize_name(current_name),
90
+ name=current_name,
92
91
  simple_dir=simple_dir,
93
92
  package_releases=package_releases,
94
93
  publication=publication,
95
94
  )
96
95
  package_releases = []
97
96
  ind += 1
98
- current_name = project_names[ind]
97
+ current_name = canonicalize_name(project_names[ind])
99
98
  relative_path = release["filename"]
100
99
  path = f"../../{relative_path}"
101
100
  checksum = release["sha256"]
@@ -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"""
@@ -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
 
@@ -178,7 +179,7 @@ def python_content_factory(python_bindings, download_python_file, monitor_task):
178
179
 
179
180
  task = python_bindings.ContentPackagesApi.create(**body).task
180
181
  response = monitor_task(task)
181
- return python_bindings.ContentPackagesApi.read(response.created_resources[0])
182
+ return python_bindings.ContentPackagesApi.read(response.created_resources[-1])
182
183
 
183
184
  yield _gen_python_content
184
185
 
@@ -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,12 +1,14 @@
1
- import pytest
2
1
  import random
3
2
  from urllib.parse import urljoin
4
3
 
4
+ import pytest
5
+ from pypi_simple import PyPISimple
6
+
5
7
  from pulp_python.tests.functional.constants import (
6
- PYTHON_SM_PROJECT_SPECIFIER,
7
- PYTHON_SM_FIXTURE_RELEASES,
8
- PYTHON_SM_FIXTURE_CHECKSUMS,
9
8
  PYTHON_EGG_FILENAME,
9
+ PYTHON_SM_FIXTURE_CHECKSUMS,
10
+ PYTHON_SM_FIXTURE_RELEASES,
11
+ PYTHON_SM_PROJECT_SPECIFIER,
10
12
  PYTHON_WHEEL_FILENAME,
11
13
  )
12
14
  from pulp_python.tests.functional.utils import ensure_simple
@@ -109,3 +111,29 @@ def test_new_content_is_published(python_publication_workflow, python_distributi
109
111
  url = urljoin(distro.base_url, "simple/")
110
112
  proper, msgs = ensure_simple(url, {"shelf-reader": releases})
111
113
  assert proper is True, msgs
114
+
115
+
116
+ @pytest.mark.parallel
117
+ def test_non_matching_canonicalized_name(
118
+ python_repo, python_content_factory, python_publication_factory, python_distribution_factory
119
+ ):
120
+ """Ensures a package with dists that have non-matching canonicalized names is published."""
121
+ packages = []
122
+ filenames = ["msg_parser-1.0.0-py2.py3-none-any.whl", "msg_parser-1.0.0.tar.gz"]
123
+ with PyPISimple() as client:
124
+ page = client.get_project_page("msg-parser")
125
+ for pkg in page.packages:
126
+ if pkg.filename in filenames:
127
+ c = python_content_factory(pkg.filename, url=pkg.url, repository=python_repo)
128
+ if c.filename.endswith(".tar.gz"):
129
+ # The metadata name in the SDist is not the same as the Wheel's name
130
+ assert c.name == "msg_parser"
131
+ else:
132
+ assert c.name == "msg-parser"
133
+ packages.append(c)
134
+ pub = python_publication_factory(repository=python_repo)
135
+ distro = python_distribution_factory(publication=pub)
136
+
137
+ url = urljoin(distro.base_url, "simple/")
138
+ proper, msgs = ensure_simple(url, {"msg-parser": filenames})
139
+ assert proper is True, msgs
@@ -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,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
 
@@ -225,26 +223,6 @@ def test_twine_upload(
225
223
  check=True,
226
224
  )
227
225
 
228
- # Test re-uploading same packages with --skip-existing works
229
- output = subprocess.run(
230
- (
231
- "twine",
232
- "upload",
233
- "--repository-url",
234
- url,
235
- dist_dir / "*",
236
- "-u",
237
- username,
238
- "-p",
239
- password,
240
- "--skip-existing",
241
- ),
242
- capture_output=True,
243
- check=True,
244
- text=True,
245
- )
246
- assert output.stdout.count("Skipping") == 2
247
-
248
226
 
249
227
  @pytest.mark.parallel
250
228
  def test_simple_redirect_with_publications(
@@ -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.0
3
+ Version: 3.19.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
@@ -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.0"
10
+ version = "3.19.2"
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.0"
81
+ current_version = "3.19.2"
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,33 @@ 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
+ "pulpcore.app".msg = "The 'pulpcore' apis must only be consumed via 'pulpcore.plugin'."
151
+
152
+ [tool.ruff.lint.isort]
153
+ # This section is managed by the plugin template. Do not edit manually.
154
+ sections = { second-party = ["pulpcore"] }
155
+ 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,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
@@ -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