From 1835725c25c31366bd6ae54bdf955157309e78c4 Mon Sep 17 00:00:00 2001 From: Gerrod Ubben Date: Tue, 4 Feb 2025 10:05:56 -0500 Subject: [PATCH] Declare compatibility with pulpcore 3.70 --- .github/workflows/scripts/install.sh | 2 +- CHANGES/+pulpcore-3.70.feature | 1 + pulp_python/app/fields.py | 12 ----------- pulp_python/app/pypi/serializers.py | 7 +++---- pulp_python/app/serializers.py | 13 ++++++------ pulp_python/pytest_plugin.py | 4 ++-- .../tests/functional/api/test_crud_remotes.py | 15 +++++++------ pulp_python/tests/functional/api/test_rbac.py | 21 +++++++++++++------ pyproject.toml | 2 +- template_config.yml | 2 +- 10 files changed, 39 insertions(+), 40 deletions(-) create mode 100644 CHANGES/+pulpcore-3.70.feature delete mode 100644 pulp_python/app/fields.py diff --git a/.github/workflows/scripts/install.sh b/.github/workflows/scripts/install.sh index d4082b98..a512cbea 100755 --- a/.github/workflows/scripts/install.sh +++ b/.github/workflows/scripts/install.sh @@ -97,7 +97,7 @@ minio_access_key: "'$MINIO_ACCESS_KEY'"\ minio_secret_key: "'$MINIO_SECRET_KEY'"\ pulp_scenario_settings: {"domain_enabled": true}\ pulp_scenario_env: {}\ -test_storages_compat_layer: false\ +test_storages_compat_layer: true\ ' vars/main.yaml export PULP_API_ROOT="/rerouted/djnd/" fi diff --git a/CHANGES/+pulpcore-3.70.feature b/CHANGES/+pulpcore-3.70.feature new file mode 100644 index 00000000..b70054c1 --- /dev/null +++ b/CHANGES/+pulpcore-3.70.feature @@ -0,0 +1 @@ +Added pulpcore 3.70 compatibility diff --git a/pulp_python/app/fields.py b/pulp_python/app/fields.py deleted file mode 100644 index 110d2c55..00000000 --- a/pulp_python/app/fields.py +++ /dev/null @@ -1,12 +0,0 @@ -from drf_spectacular.utils import extend_schema_field -from drf_spectacular.types import OpenApiTypes -from rest_framework import serializers - - -@extend_schema_field(OpenApiTypes.OBJECT) -class JSONObjectField(serializers.JSONField): - """A drf JSONField override to force openapi schema to use 'object' type. - - Not strictly correct, but we relied on that for a long time. - See: https://github.com/tfranzel/drf-spectacular/issues/1095 - """ diff --git a/pulp_python/app/pypi/serializers.py b/pulp_python/app/pypi/serializers.py index 301d7a8b..dc99fc80 100644 --- a/pulp_python/app/pypi/serializers.py +++ b/pulp_python/app/pypi/serializers.py @@ -3,7 +3,6 @@ from rest_framework import serializers from pulp_python.app.utils import DIST_EXTENSIONS -from pulp_python.app import fields from pulpcore.plugin.models import Artifact from pulpcore.plugin.util import get_domain from django.db.utils import IntegrityError @@ -29,9 +28,9 @@ class PackageMetadataSerializer(serializers.Serializer): """ last_serial = serializers.IntegerField(help_text=_("Cache value from last PyPI sync")) - info = fields.JSONObjectField(help_text=_("Core metadata of the package")) - releases = fields.JSONObjectField(help_text=_("List of all the releases of the package")) - urls = fields.JSONObjectField() + info = serializers.JSONField(help_text=_("Core metadata of the package")) + releases = serializers.JSONField(help_text=_("List of all the releases of the package")) + urls = serializers.JSONField() class PackageUploadSerializer(serializers.Serializer): diff --git a/pulp_python/app/serializers.py b/pulp_python/app/serializers.py index 0c8c9070..dca90d27 100644 --- a/pulp_python/app/serializers.py +++ b/pulp_python/app/serializers.py @@ -8,7 +8,6 @@ from pulpcore.plugin.util import get_domain from pulp_python.app import models as python_models -from pulp_python.app import fields from pulp_python.app.utils import artifact_to_python_content_data @@ -158,7 +157,7 @@ class PythonPackageContentSerializer(core_serializers.SingleArtifactContentUploa required=False, allow_blank=True, help_text=_('A browsable URL for the project and a label for it, separated by a comma.') ) - project_urls = fields.JSONObjectField( + project_urls = serializers.JSONField( required=False, default=dict, help_text=_('A dictionary of labels and URLs for the project.') ) @@ -171,28 +170,28 @@ class PythonPackageContentSerializer(core_serializers.SingleArtifactContentUploa required=False, allow_blank=True, help_text=_('Field to specify the OS and CPU for which the binary package was compiled. ') ) - requires_dist = fields.JSONObjectField( + requires_dist = serializers.JSONField( required=False, default=list, help_text=_('A JSON list containing names of some other distutils project ' 'required by this distribution.') ) - provides_dist = fields.JSONObjectField( + provides_dist = serializers.JSONField( required=False, default=list, help_text=_('A JSON list containing names of a Distutils project which is contained' ' within this distribution.') ) - obsoletes_dist = fields.JSONObjectField( + obsoletes_dist = serializers.JSONField( required=False, default=list, help_text=_('A JSON list containing names of a distutils project\'s distribution which ' 'this distribution renders obsolete, meaning that the two projects should not ' 'be installed at the same time.') ) - requires_external = fields.JSONObjectField( + requires_external = serializers.JSONField( required=False, default=list, help_text=_('A JSON list containing some dependency in the system that the distribution ' 'is to be used.') ) - classifiers = fields.JSONObjectField( + classifiers = serializers.JSONField( required=False, default=list, help_text=_('A JSON list containing classification values for a Python package.') ) diff --git a/pulp_python/pytest_plugin.py b/pulp_python/pytest_plugin.py index f04a7d4b..fde4d0f8 100644 --- a/pulp_python/pytest_plugin.py +++ b/pulp_python/pytest_plugin.py @@ -162,9 +162,9 @@ def python_content_factory(python_bindings, download_python_file, monitor_task): def _gen_python_content(relative_path=PYTHON_EGG_FILENAME, url=None, **body): body["relative_path"] = relative_path if url: - body["file"] = download_python_file(relative_path, url) + body["file"] = str(download_python_file(relative_path, url)) elif not any(x in body for x in ("artifact", "file", "upload")): - body["file"] = download_python_file(PYTHON_EGG_FILENAME, PYTHON_URL) + body["file"] = str(download_python_file(PYTHON_EGG_FILENAME, PYTHON_URL)) if repo := body.get("repository"): repo_href = repo if isinstance(repo, str) else repo.pulp_href body["repository"] = repo_href diff --git a/pulp_python/tests/functional/api/test_crud_remotes.py b/pulp_python/tests/functional/api/test_crud_remotes.py index 2c8e681a..96735425 100644 --- a/pulp_python/tests/functional/api/test_crud_remotes.py +++ b/pulp_python/tests/functional/api/test_crud_remotes.py @@ -14,7 +14,7 @@ @pytest.mark.parametrize("kwargs", [{}, {"policy": "on_demand"}]) def test_remote_from_bandersnatch_config(kwargs, python_bindings, add_to_cleanup, tmp_path): """Verify whether it's possible to create a remote from a Bandersnatch config.""" - filename = tmp_path / "bandersnatch.conf" + filename = str(tmp_path / "bandersnatch.conf") with open(filename, mode="wb") as config: config.write(BANDERSNATCH_CONF) config.flush() @@ -40,7 +40,7 @@ def test_remote_default_policy(python_bindings, gen_object_with_cleanup, monitor @pytest.mark.parallel -def test_remote_invalid_project_specifier(python_bindings): +def test_remote_invalid_project_specifier(python_bindings, has_pulp_plugin): """Test that creating a remote with an invalid project specifier fails.""" # Test an include specifier without a "name" field. body = { @@ -48,8 +48,10 @@ def test_remote_invalid_project_specifier(python_bindings): "url": "https://test", "includes": PYTHON_INVALID_SPECIFIER_NO_NAME, } - with pytest.raises(python_bindings.ApiException): - python_bindings.RemotesPythonApi.create(body) + # Pydantic addition to bindings in 3.70 prevent this test from working + if has_pulp_plugin("core", max="3.70"): + with pytest.raises(python_bindings.ApiException): + python_bindings.RemotesPythonApi.create(body) # Test an include specifier with an invalid "version_specifier" field value. body["includes"] = PYTHON_INVALID_SPECIFIER_BAD_VERSION @@ -59,8 +61,9 @@ def test_remote_invalid_project_specifier(python_bindings): # Test an exclude specifier without a "name" field. body.pop("includes") body["excludes"] = PYTHON_INVALID_SPECIFIER_NO_NAME - with pytest.raises(python_bindings.ApiException): - python_bindings.RemotesPythonApi.create(body) + if has_pulp_plugin("core", max="3.70"): + with pytest.raises(python_bindings.ApiException): + python_bindings.RemotesPythonApi.create(body) # Test an exclude specifier with an invalid "version_specifier" field value. body["excludes"] = PYTHON_INVALID_SPECIFIER_BAD_VERSION diff --git a/pulp_python/tests/functional/api/test_rbac.py b/pulp_python/tests/functional/api/test_rbac.py index c95ec543..ce9489a9 100644 --- a/pulp_python/tests/functional/api/test_rbac.py +++ b/pulp_python/tests/functional/api/test_rbac.py @@ -27,18 +27,27 @@ def _gen_users(role_names=list()): @pytest.fixture -def try_action(monitor_task): +def try_action(pulpcore_bindings, monitor_task): def _try_action(user, client, action, outcome, *args, **kwargs): action_api = getattr(client, f"{action}_with_http_info") try: with user: - response, status, _ = action_api(*args, **kwargs, _return_http_data_only=False) - if isinstance(response, AsyncOperationResponse): - response = monitor_task(response.task) - except ApiException as e: + response = action_api(*args, **kwargs) + if isinstance(response, tuple): + # old bindings + data, status_code, _ = response + else: + # new bindings + data = response.data + status_code = response.status_code + if isinstance(data, pulpcore_bindings.module.AsyncOperationResponse): + response = monitor_task(data.task) + except pulpcore_bindings.module.ApiException as e: assert e.status == outcome, f"{e}" else: - assert status == outcome, f"User performed {action} when they shouldn't been able to" + assert ( + status_code == outcome + ), f"User performed {action} when they shouldn't been able to" return response return _try_action diff --git a/pyproject.toml b/pyproject.toml index af1a1e4f..9cc858dc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ classifiers=[ ] requires-python = ">=3.9" dependencies = [ - "pulpcore>=3.49.0,<3.70", + "pulpcore>=3.49.0,<3.85", "pkginfo>=1.10.0,<1.12.0", # Twine has <1.11 in their requirements "bandersnatch>=6.3,<7.0", # Anything >6.3 requires Python 3.10+ "pypi-simple>=1.5.0,<2.0", diff --git a/template_config.yml b/template_config.yml index ddc66452..d84bdba0 100644 --- a/template_config.yml +++ b/template_config.yml @@ -68,6 +68,6 @@ test_lowerbounds: true test_performance: false test_reroute: true test_s3: true -test_storages_compat_layer: false +test_storages_compat_layer: true use_issue_template: true