Skip to content

Commit 16f7486

Browse files
committed
wip
1 parent 17e0e7c commit 16f7486

File tree

2 files changed

+44
-37
lines changed

2 files changed

+44
-37
lines changed

pulp_python/app/pypi/views.py

Lines changed: 21 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from aiohttp.client_exceptions import ClientError
55
from rest_framework.viewsets import ViewSet
6-
from rest_framework.renderers import JSONRenderer, TemplateHTMLRenderer
6+
from rest_framework.renderers import BrowsableAPIRenderer, JSONRenderer, TemplateHTMLRenderer
77
from rest_framework.response import Response
88
from django.core.exceptions import ObjectDoesNotExist
99
from django.shortcuts import redirect
@@ -18,7 +18,6 @@
1818
HttpResponseBadRequest,
1919
StreamingHttpResponse,
2020
HttpResponse,
21-
JsonResponse,
2221
)
2322
from drf_spectacular.utils import extend_schema
2423
from dynaconf import settings
@@ -74,18 +73,6 @@ class PyPISimpleJSONRenderer(JSONRenderer):
7473
media_type = PYPI_SIMPLE_V1_JSON
7574

7675

77-
def _select_content_type(request):
78-
"""Select content type based on Accept header."""
79-
accept_header = request.META.get("HTTP_ACCEPT", "")
80-
81-
for content_type in (PYPI_TEXT_HTML, PYPI_SIMPLE_V1_HTML, PYPI_SIMPLE_V1_JSON):
82-
if content_type in accept_header:
83-
return content_type
84-
if not accept_header:
85-
return PYPI_TEXT_HTML
86-
return None
87-
88-
8976
class PyPIMixin:
9077
"""Mixin to get index specific info."""
9178

@@ -263,32 +250,34 @@ class SimpleView(PackageUploadMixin, ViewSet):
263250
],
264251
}
265252

266-
renderer_classes = [
267-
TemplateHTMLRenderer,
268-
PyPISimpleHTMLRenderer,
269-
PyPISimpleJSONRenderer,
270-
]
253+
def get_renderers(self):
254+
"""Defines custom renderers."""
255+
if self.action in ["list", "retrieve"]:
256+
# Use PyPI renderers for simple API endpoints
257+
return [
258+
TemplateHTMLRenderer(),
259+
PyPISimpleHTMLRenderer(),
260+
PyPISimpleJSONRenderer(),
261+
]
262+
else:
263+
# Use standard DRF renderers
264+
return [JSONRenderer(), BrowsableAPIRenderer()]
271265

272266
@extend_schema(summary="Get index simple page")
273267
def list(self, request, path):
274268
"""Gets the simple api html page for the index."""
275-
content_type = _select_content_type(request)
276-
if content_type is None:
277-
return HttpResponse("Not Acceptable Content-Type", status=406)
278-
279269
repo_version, content = self.get_rvc()
280270
if self.should_redirect(repo_version=repo_version):
281271
return redirect(urljoin(self.base_content_url, f"{path}/simple/"))
282-
names = content.order_by("name").values_list("name", flat=True).distinct().iterator()
283272

284-
if content_type == PYPI_SIMPLE_V1_JSON:
285-
names_list = list(names)
286-
data_dict = write_simple_index_json(names_list)
273+
names = content.order_by("name").values_list("name", flat=True).distinct()
274+
275+
if request.accepted_renderer.media_type == PYPI_SIMPLE_V1_JSON:
276+
data_dict = write_simple_index_json(list(names))
287277
headers = {"X-PyPI-Last-Serial": str(PYPI_SERIAL_CONSTANT)}
288-
response = JsonResponse(data_dict, content_type=content_type, headers=headers)
289-
return response
278+
return Response(data_dict, headers=headers)
290279
else:
291-
return StreamingHttpResponse(write_simple_index(names, streamed=True))
280+
return StreamingHttpResponse(write_simple_index(names.iterator(), streamed=True))
292281

293282
def pull_through_package_simple(self, package, path, remote):
294283
"""Gets the package's simple page from remote."""
@@ -327,10 +316,6 @@ def parse_package(release_package):
327316
@extend_schema(operation_id="pypi_simple_package_read", summary="Get package simple page")
328317
def retrieve(self, request, path, package):
329318
"""Retrieves the simple api html page for a package."""
330-
content_type = _select_content_type(request)
331-
if content_type is None:
332-
return HttpResponse("Not Acceptable Content-Type", status=406)
333-
334319
repo_ver, content = self.get_rvc()
335320
# Should I redirect if the normalized name is different?
336321
normalized = canonicalize_name(package)
@@ -352,12 +337,11 @@ def retrieve(self, request, path, package):
352337
name = present[2]
353338
releases = ((f, urljoin(self.base_content_url, f"{path}/{f}"), d) for f, d, _ in packages)
354339

355-
if content_type == PYPI_SIMPLE_V1_JSON:
340+
if request.accepted_renderer.media_type == PYPI_SIMPLE_V1_JSON:
356341
releases_list = list(releases)
357342
data_dict = write_simple_detail_json(name, releases_list)
358343
headers = {"X-PyPI-Last-Serial": str(PYPI_SERIAL_CONSTANT)}
359-
response = JsonResponse(data_dict, content_type=content_type, headers=headers)
360-
return response
344+
return Response(data_dict, headers=headers)
361345
else:
362346
return StreamingHttpResponse(write_simple_detail(name, releases, streamed=True))
363347

pulp_python/tests/functional/api/test_pypi_apis.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,29 @@ def test_simple_json_api(python_remote_factory, python_repo_with_sync, python_di
313313
assert response_detail.headers["X-PyPI-Last-Serial"] == "1000000000"
314314

315315

316+
@pytest.mark.parametrize(
317+
"header, result",
318+
[
319+
("application/vnd.pypi.simple.v1+json", "application/vnd.pypi.simple.v1+json"),
320+
("application/vnd.pypi.simple.v1+html", "application/vnd.pypi.simple.v1+html"),
321+
("text/html", "text/html"),
322+
("sth/else", "text/html"),
323+
(f"application/vnd.pypi.simple.v1+html;q=0.2, application/vnd.pypi.simple.v1+json", "text/html"),
324+
],
325+
)
326+
def test_simple_json_api_headers(
327+
python_remote_factory, python_repo_with_sync, python_distribution_factory, header, result
328+
):
329+
remote = python_remote_factory(includes=PYTHON_SM_PROJECT_SPECIFIER)
330+
repo = python_repo_with_sync(remote)
331+
distro = python_distribution_factory(repository=repo)
332+
index_url = urljoin(distro.base_url, "simple/")
333+
334+
response = requests.get(index_url, headers={"Accept": header})
335+
# assert response.status_code == 200
336+
assert result in response.headers["Content-Type"]
337+
338+
316339
@pytest.mark.parallel
317340
def test_pypi_json(python_remote_factory, python_repo_with_sync, python_distribution_factory):
318341
"""Checks the data of `pypi/{package_name}/json` endpoint."""

0 commit comments

Comments
 (0)