88from mailbits import ContentType
99from packaging .utils import canonicalize_name as normalize
1010import requests
11- from . import PYPI_SIMPLE_ENDPOINT , __url__ , __version__
11+ from . import ACCEPT_ANY , PYPI_SIMPLE_ENDPOINT , __url__ , __version__
1212from .classes import DistributionPackage , IndexPage , ProjectPage
1313from .errors import UnsupportedContentTypeError
1414from .html_stream import parse_links_stream_response
2525 platform .python_version (),
2626)
2727
28- ACCEPT = ", " .join (
29- [
30- "application/vnd.pypi.simple.v1+json" ,
31- "application/vnd.pypi.simple.v1+html" ,
32- "text/html;q=0.01" ,
33- ]
34- )
35-
3628
3729class PyPISimple :
3830 """
@@ -53,6 +45,10 @@ class PyPISimple:
5345 automatically close its session on exit, regardless of where the session
5446 object came from.
5547
48+ .. versionchanged:: 1.0.0
49+
50+ ``accept`` parameter added
51+
5652 :param str endpoint: The base URL of the simple API instance to query;
5753 defaults to the base URL for PyPI's simple API
5854
@@ -63,13 +59,19 @@ class PyPISimple:
6359
6460 :param session: Optional `requests.Session` object to use instead of
6561 creating a fresh one
62+
63+ :param str accept:
64+ The :mailheader:`Accept` header to send in requests in order to specify
65+ what serialization format the server should return; defaults to
66+ `ACCEPT_ANY`
6667 """
6768
6869 def __init__ (
6970 self ,
7071 endpoint : str = PYPI_SIMPLE_ENDPOINT ,
7172 auth : Any = None ,
7273 session : Optional [requests .Session ] = None ,
74+ accept : str = ACCEPT_ANY ,
7375 ) -> None :
7476 self .endpoint : str = endpoint .rstrip ("/" ) + "/"
7577 self .s : requests .Session
@@ -80,6 +82,7 @@ def __init__(
8082 self .s .headers ["User-Agent" ] = USER_AGENT
8183 if auth is not None :
8284 self .s .auth = auth
85+ self .accept = accept
8386
8487 def __enter__ (self ) -> PyPISimple :
8588 return self
@@ -95,6 +98,7 @@ def __exit__(
9598 def get_index_page (
9699 self ,
97100 timeout : float | tuple [float , float ] | None = None ,
101+ accept : Optional [str ] = None ,
98102 ) -> IndexPage :
99103 """
100104 Fetches the index/root page from the simple repository and returns an
@@ -105,8 +109,16 @@ def get_index_page(
105109 PyPI's project index file is very large and takes several seconds
106110 to parse. Use this method sparingly.
107111
112+ .. versionchanged:: 1.0.0
113+
114+ ``accept`` parameter added
115+
108116 :param timeout: optional timeout to pass to the ``requests`` call
109117 :type timeout: float | tuple[float,float] | None
118+ :param Optional[str] accept:
119+ The :mailheader:`Accept` header to send in order to
120+ specify what serialization format the server should return;
121+ defaults to the value supplied on client instantiation
110122 :rtype: IndexPage
111123 :raises requests.HTTPError: if the repository responds with an HTTP
112124 error code
@@ -115,14 +127,17 @@ def get_index_page(
115127 :raises UnsupportedRepoVersionError: if the repository version has a
116128 greater major component than the supported repository version
117129 """
118- r = self .s .get (self .endpoint , timeout = timeout , headers = {"Accept" : ACCEPT })
130+ r = self .s .get (
131+ self .endpoint , timeout = timeout , headers = {"Accept" : accept or self .accept }
132+ )
119133 r .raise_for_status ()
120134 return IndexPage .from_response (r )
121135
122136 def stream_project_names (
123137 self ,
124138 chunk_size : int = 65535 ,
125139 timeout : float | tuple [float , float ] | None = None ,
140+ accept : Optional [str ] = None ,
126141 ) -> Iterator [str ]:
127142 """
128143 Returns a generator of names of projects available in the repository.
@@ -145,10 +160,18 @@ def stream_project_names(
145160 rather than an HTML representation, the response body will be
146161 loaded & parsed in its entirety before yielding anything.
147162
163+ .. versionchanged:: 1.0.0
164+
165+ ``accept`` parameter added
166+
148167 :param int chunk_size: how many bytes to read from the response at a
149168 time
150169 :param timeout: optional timeout to pass to the ``requests`` call
151170 :type timeout: float | tuple[float,float] | None
171+ :param Optional[str] accept:
172+ The :mailheader:`Accept` header to send in order to
173+ specify what serialization format the server should return;
174+ defaults to the value supplied on client instantiation
152175 :rtype: Iterator[str]
153176 :raises requests.HTTPError: if the repository responds with an HTTP
154177 error code
@@ -157,7 +180,12 @@ def stream_project_names(
157180 :raises UnsupportedRepoVersionError: if the repository version has a
158181 greater major component than the supported repository version
159182 """
160- with self .s .get (self .endpoint , stream = True , timeout = timeout ) as r :
183+ with self .s .get (
184+ self .endpoint ,
185+ stream = True ,
186+ timeout = timeout ,
187+ headers = {"Accept" : accept or self .accept },
188+ ) as r :
161189 r .raise_for_status ()
162190 ct = ContentType .parse (r .headers .get ("content-type" , "text/html" ))
163191 if ct .content_type == "application/vnd.pypi.simple.v1+json" :
@@ -176,6 +204,7 @@ def get_project_page(
176204 self ,
177205 project : str ,
178206 timeout : float | tuple [float , float ] | None = None ,
207+ accept : Optional [str ] = None ,
179208 ) -> ProjectPage :
180209 """
181210 Fetches the page for the given project from the simple repository and
@@ -185,13 +214,19 @@ def get_project_page(
185214
186215 .. versionchanged:: 1.0.0
187216
188- A 404 now causes `NoSuchProjectError` to be raised instead of
189- returning `None`
217+ - A 404 now causes `NoSuchProjectError` to be raised instead of
218+ returning `None`
219+
220+ - ``accept`` parameter added
190221
191222 :param str project: The name of the project to fetch information on.
192223 The name does not need to be normalized.
193224 :param timeout: optional timeout to pass to the ``requests`` call
194225 :type timeout: float | tuple[float,float] | None
226+ :param Optional[str] accept:
227+ The :mailheader:`Accept` header to send in order to
228+ specify what serialization format the server should return;
229+ defaults to the value supplied on client instantiation
195230 :rtype: ProjectPage
196231 :raises NoSuchProjectError: if the repository responds with a 404 error
197232 code
@@ -203,7 +238,7 @@ def get_project_page(
203238 greater major component than the supported repository version
204239 """
205240 url = self .get_project_url (project )
206- r = self .s .get (url , timeout = timeout , headers = {"Accept" : ACCEPT })
241+ r = self .s .get (url , timeout = timeout , headers = {"Accept" : accept or None })
207242 if r .status_code == 404 :
208243 raise NoSuchProjectError (project , url )
209244 r .raise_for_status ()
0 commit comments