Skip to content

Commit eed205a

Browse files
committed
More refactoring
1 parent 1f65cc4 commit eed205a

File tree

2 files changed

+17
-24
lines changed

2 files changed

+17
-24
lines changed

src/pip/_internal/network/download.py

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,10 @@ def _prepare_download(
4141
resp: Response,
4242
link: Link,
4343
progress_bar: str,
44-
total_length: Optional[int],
4544
range_start: Optional[int] = 0,
4645
) -> Iterable[bytes]:
46+
total_length = _get_http_response_size(resp)
47+
4748
if link.netloc == PyPI.file_storage_domain:
4849
url = link.show_url
4950
else:
@@ -170,21 +171,14 @@ def __init__(
170171
def __call__(self, link: Link, location: str) -> Tuple[str, str]:
171172
"""Download the file given by link into location."""
172173
resp = _http_get_download(self._session, link)
173-
total_length = _get_http_response_size(resp)
174174
content_type = resp.headers.get("Content-Type", "")
175175

176176
filename = _get_http_response_filename(resp, link)
177177
filepath = os.path.join(location, filename)
178178

179179
with open(filepath, "wb") as content_file:
180-
bytes_received = self._process_response(
181-
resp, link, content_file, 0, total_length
182-
)
183-
# If possible, check for an incomplete download and attempt resuming.
184-
if total_length and bytes_received < total_length:
185-
self._attempt_resume(
186-
resp, link, content_file, total_length, bytes_received
187-
)
180+
bytes_received = self._process_response(resp, link, content_file, 0)
181+
self._attempt_resume_if_needed(resp, link, content_file, bytes_received)
188182

189183
return filepath, content_type
190184

@@ -194,11 +188,11 @@ def _process_response(
194188
link: Link,
195189
content_file: BinaryIO,
196190
bytes_received: int,
197-
total_length: Optional[int],
198191
) -> int:
199192
"""Process the response and write the chunks to the file."""
193+
total_length = _get_http_response_size(resp)
200194
chunks = _prepare_download(
201-
resp, link, self._progress_bar, total_length, range_start=bytes_received
195+
resp, link, self._progress_bar, range_start=bytes_received
202196
)
203197
return self._write_chunks_to_file(
204198
chunks, content_file, allow_partial=bool(total_length)
@@ -223,15 +217,15 @@ def _write_chunks_to_file(
223217

224218
return bytes_received
225219

226-
def _attempt_resume(
220+
def _attempt_resume_if_needed(
227221
self,
228222
resp: Response,
229223
link: Link,
230224
content_file: BinaryIO,
231-
total_length: Optional[int],
232225
bytes_received: int,
233226
) -> None:
234-
"""Attempt to resume the download if connection was dropped."""
227+
"""Attempt to resume/retry the download if connection was dropped."""
228+
total_length = _get_http_response_size(resp)
235229
etag_or_last_modified = _get_http_response_etag_or_last_modified(resp)
236230

237231
attempts_left = self._resume_retries
@@ -246,28 +240,30 @@ def _attempt_resume(
246240
)
247241

248242
try:
243+
# Try to resume the download using a HTTP range request.
249244
resume_resp = _http_get_download(
250245
self._session,
251246
link,
252247
range_start=bytes_received,
253248
if_range=etag_or_last_modified,
254249
)
255250

256-
# If the server responded with 200 (e.g. when the file has been
257-
# modified on the server or range requests are not supported by
258-
# the server), reset the download to start from the beginning.
259-
restart = resume_resp.status_code != HTTPStatus.PARTIAL_CONTENT
260-
if restart:
251+
# Fallback: if the server responded with 200 (i.e., the file has
252+
# since been modified or range requests are unsupported) or any
253+
# other unexpected status, restart the download from the beginning.
254+
must_restart = resume_resp.status_code != HTTPStatus.PARTIAL_CONTENT
255+
if must_restart:
261256
bytes_received, total_length, etag_or_last_modified = (
262257
self._reset_download_state(resume_resp, content_file)
263258
)
264259

265260
bytes_received += self._process_response(
266-
resume_resp, link, content_file, bytes_received, total_length
261+
resume_resp, link, content_file, bytes_received
267262
)
268263
except (ConnectionError, ReadTimeoutError, OSError):
269264
continue
270265

266+
# No more resume attempts. Raise an error if the download is still incomplete.
271267
if total_length and bytes_received < total_length:
272268
os.remove(content_file.name)
273269
raise IncompleteDownloadError(

tests/unit/test_network_download.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from pip._internal.models.link import Link
1111
from pip._internal.network.download import (
1212
Downloader,
13-
_get_http_response_size,
1413
_http_get_download,
1514
_prepare_download,
1615
parse_content_disposition,
@@ -91,12 +90,10 @@ def test_prepare_download__log(
9190
if from_cache:
9291
resp.from_cache = from_cache
9392
link = Link(url)
94-
total_length = _get_http_response_size(resp)
9593
_prepare_download(
9694
resp,
9795
link,
9896
progress_bar="on",
99-
total_length=total_length,
10097
range_start=range_start,
10198
)
10299

0 commit comments

Comments
 (0)