Skip to content

Commit f3f4426

Browse files
authored
Merge pull request #3232 from eas342/allHeadSafe
un-indenting head-safe check to apply for cached files too
2 parents ebcbe4c + 9dca39b commit f3f4426

File tree

3 files changed

+408
-18
lines changed

3 files changed

+408
-18
lines changed

CHANGES.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ heasarc
2323
Infrastructure, Utility and Other Changes and Additions
2424
-------------------------------------------------------
2525

26+
query.py
27+
^^^^^^^^
28+
29+
- ``BaseQuery._download_file`` now returns the local file path in all cases.
30+
Some corner cases where downloads were not properly continued have been
31+
fixed. [#3232]
32+
33+
2634

2735
0.4.10 (2025-03-18)
2836
===================
@@ -133,6 +141,7 @@ Infrastructure, Utility and Other Changes and Additions
133141
``astroquery.test()`` functionality. [#3215]
134142

135143

144+
136145
0.4.9 (2025-01-24)
137146
==================
138147

astroquery/query.py

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,6 @@ def _download_file(self, url, local_filepath, timeout=None, auth=None,
412412
verbose : bool
413413
Whether to show download progress. Defaults to True.
414414
"""
415-
416415
if head_safe:
417416
response = self._session.request("HEAD", url,
418417
timeout=timeout, stream=True,
@@ -426,23 +425,29 @@ def _download_file(self, url, local_filepath, timeout=None, auth=None,
426425
if 'content-length' in response.headers:
427426
length = int(response.headers['content-length'])
428427
if length == 0:
429-
log.warn('URL {0} has length=0'.format(url))
428+
log.warning('URL {0} has length=0'.format(url))
430429
else:
431430
length = None
432431

433432
if ((os.path.exists(local_filepath)
434433
and ('Accept-Ranges' in response.headers)
434+
and length is not None
435435
and continuation)):
436436
open_mode = 'ab'
437437

438438
existing_file_length = os.stat(local_filepath).st_size
439-
if length is not None and existing_file_length >= length:
440-
# all done!
441-
log.info("Found cached file {0} with expected size {1}."
442-
.format(local_filepath, existing_file_length))
443-
return
444-
elif existing_file_length == 0:
439+
if existing_file_length == 0:
440+
log.info(f"Found existing {local_filepath} file with length 0. Overwriting.")
445441
open_mode = 'wb'
442+
if head_safe:
443+
response = self._session.request(method, url,
444+
timeout=timeout, stream=True,
445+
auth=auth, **kwargs)
446+
response.raise_for_status()
447+
elif existing_file_length >= length:
448+
# all done!
449+
log.info(f"Found cached file {local_filepath} with size {existing_file_length} = {length}.")
450+
return local_filepath
446451
else:
447452
log.info("Continuing download of file {0}, with {1} bytes to "
448453
"go ({2}%)".format(local_filepath,
@@ -454,6 +459,7 @@ def _download_file(self, url, local_filepath, timeout=None, auth=None,
454459
end = "{0}".format(length-1) if length is not None else ""
455460
self._session.headers['Range'] = "bytes={0}-{1}".format(existing_file_length,
456461
end)
462+
log.debug(f"Continuing with range={self._session.headers['Range']}")
457463

458464
response = self._session.request(method, url,
459465
timeout=timeout, stream=True,
@@ -466,17 +472,24 @@ def _download_file(self, url, local_filepath, timeout=None, auth=None,
466472
statinfo = os.stat(local_filepath)
467473
if statinfo.st_size != length:
468474
log.warning(f"Found cached file {local_filepath} with size {statinfo.st_size} "
469-
f"that is different from expected size {length}")
475+
f"that is different from expected size {length}. ")
476+
if continuation:
477+
log.warning(
478+
"Continuation was requested but is not possible because "
479+
"'Accepts-Ranges' is not in the response headers.")
470480
open_mode = 'wb'
481+
response = self._session.request(method, url,
482+
timeout=timeout, stream=True,
483+
auth=auth, **kwargs)
484+
response.raise_for_status()
471485
else:
472-
log.info("Found cached file {0} with expected size {1}."
473-
.format(local_filepath, statinfo.st_size))
486+
log.info(f"Found cached file {local_filepath} with expected size {statinfo.st_size}.")
474487
response.close()
475-
return
488+
return local_filepath
476489
else:
477-
log.info("Found cached file {0}.".format(local_filepath))
478-
response.close()
479-
return
490+
# This case doesn't appear reachable under normal circumstances
491+
# It is not covered by tests, and probably indicates a badly-behaved server
492+
raise ValueError(f"Found cached file {local_filepath}. Could not verify length.")
480493
else:
481494
open_mode = 'wb'
482495
if head_safe:
@@ -488,7 +501,7 @@ def _download_file(self, url, local_filepath, timeout=None, auth=None,
488501
blocksize = astropy.utils.data.conf.download_block_size
489502

490503
log.debug(f"Downloading URL {url} to {local_filepath} with size {length} "
491-
f"by blocks of {blocksize}")
504+
f"by blocks of {blocksize} with open_mode={open_mode}")
492505

493506
bytes_read = 0
494507

@@ -514,7 +527,7 @@ def _download_file(self, url, local_filepath, timeout=None, auth=None,
514527
f.write(response.content)
515528

516529
response.close()
517-
return response
530+
return local_filepath
518531

519532

520533
@deprecated(since="v0.4.7", message=("The suspend_cache function is deprecated,"

0 commit comments

Comments
 (0)