Skip to content

Commit e416f8c

Browse files
author
Andrew Cheng
committed
Expose opt-in content_ids on repository version detail
Add a content_ids SerializerMethodField to RepositoryVersionSerializer that returns the version's content unit UUIDs only when the request includes the content_ids=true query parameter (null otherwise). This lets clients diff content sets between versions directly instead of issuing expensive content filter queries. Closes #7831 Assisted by: Claude Opus 4.8
1 parent 94f63c3 commit e416f8c

3 files changed

Lines changed: 53 additions & 0 deletions

File tree

CHANGES/7831.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added an opt-in ``content_ids`` field to the repository version detail, returning the list of content unit UUIDs in the version when the request includes the ``content_ids=true`` query parameter. This lets clients diff content sets between versions directly instead of issuing expensive content filter queries.

pulpcore/app/serializers/repository.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,10 +291,26 @@ class RepositoryVersionSerializer(ModelSerializer, NestedHyperlinkedModelSeriali
291291
vuln_report = serializers.SerializerMethodField(
292292
read_only=True,
293293
)
294+
content_ids = serializers.SerializerMethodField(
295+
help_text=_(
296+
"The list of content unit UUIDs in this version. Only returned when the request "
297+
"includes the 'content_ids=true' query parameter; otherwise null."
298+
),
299+
read_only=True,
300+
)
294301

295302
def get_vuln_report(self, object):
296303
return f"{reverse('vuln_report-list')}?repo_versions={get_prn(object)}"
297304

305+
def get_content_ids(self, object):
306+
request = self.context.get("request")
307+
if request is None:
308+
return None
309+
value = request.query_params.get("content_ids")
310+
if value is None or value.lower() not in ("true", "1", "yes"):
311+
return None
312+
return object.content_ids
313+
298314
class Meta:
299315
model = models.RepositoryVersion
300316
fields = ModelSerializer.Meta.fields + (
@@ -304,6 +320,7 @@ class Meta:
304320
"base_version",
305321
"content_summary",
306322
"vuln_report",
323+
"content_ids",
307324
)
308325

309326

pulpcore/tests/unit/serializers/test_repository.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from types import SimpleNamespace
22
from unittest.mock import Mock
3+
from uuid import uuid4
34

45
import pytest
56
from rest_framework import serializers
@@ -10,6 +11,7 @@
1011
PublicationSerializer,
1112
RemoteSerializer,
1213
RepositorySyncURLSerializer,
14+
RepositoryVersionSerializer,
1315
ValidateFieldsMixin,
1416
)
1517

@@ -265,3 +267,36 @@ def test_create_remote_with_invalid_parameter():
265267
serializer = RemoteSerializer(data=data)
266268
with pytest.raises(serializers.ValidationError, match="Unexpected field"):
267269
serializer.validate(data)
270+
271+
272+
def _content_ids_serializer(query_params=None):
273+
"""Build a RepositoryVersionSerializer with an optional fake request in its context."""
274+
context = {}
275+
if query_params is not None:
276+
context["request"] = SimpleNamespace(query_params=query_params)
277+
return RepositoryVersionSerializer(context=context)
278+
279+
280+
def test_get_content_ids_omitted_without_request():
281+
"""content_ids is null when there is no request in the serializer context."""
282+
obj = SimpleNamespace(content_ids=[uuid4()])
283+
serializer = _content_ids_serializer()
284+
assert serializer.get_content_ids(obj) is None
285+
286+
287+
@pytest.mark.parametrize("value", [None, "", "false", "0", "no", "False"])
288+
def test_get_content_ids_omitted_when_not_requested(value):
289+
"""content_ids is null unless the request explicitly opts in via the query parameter."""
290+
query_params = {} if value is None else {"content_ids": value}
291+
obj = SimpleNamespace(content_ids=[uuid4()])
292+
serializer = _content_ids_serializer(query_params=query_params)
293+
assert serializer.get_content_ids(obj) is None
294+
295+
296+
@pytest.mark.parametrize("value", ["true", "True", "TRUE", "1", "yes"])
297+
def test_get_content_ids_returned_when_requested(value):
298+
"""content_ids returns the version's UUIDs when the request opts in."""
299+
content_ids = [uuid4(), uuid4()]
300+
obj = SimpleNamespace(content_ids=content_ids)
301+
serializer = _content_ids_serializer(query_params={"content_ids": value})
302+
assert serializer.get_content_ids(obj) == content_ids

0 commit comments

Comments
 (0)