33
44from aiohttp .client_exceptions import ClientError
55from rest_framework .viewsets import ViewSet
6- from rest_framework .renderers import JSONRenderer , TemplateHTMLRenderer
6+ from rest_framework .renderers import BrowsableAPIRenderer , JSONRenderer , TemplateHTMLRenderer
77from rest_framework .response import Response
88from django .core .exceptions import ObjectDoesNotExist
99from django .shortcuts import redirect
1818 HttpResponseBadRequest ,
1919 StreamingHttpResponse ,
2020 HttpResponse ,
21- JsonResponse ,
2221)
2322from drf_spectacular .utils import extend_schema
2423from 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-
8976class 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
0 commit comments