Files
wehub-resource-sync 26446540fa
Lint / lint (push) Waiting to run
CI / MacOS (push) Waiting to run
CI / Windows (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:36:25 +08:00

176 lines
5.7 KiB
Python

# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# pylint: disable=missing-timeout
"""Helper utility for downloading"""
import logging
import os
import shutil
import tempfile
import time
from pathlib import Path
LOG = logging.getLogger("download")
def download(url, path, overwrite=False, size_compare=False, retries=3):
"""Downloads the file from the internet.
Set the input options correctly to overwrite or do the size comparison
Parameters
----------
url : str
Download url.
path : str
Local file path to save downloaded file.
overwrite : bool, optional
Whether to overwrite existing file, defaults to False.
size_compare : bool, optional
Whether to do size compare to check downloaded file, defaults
to False
retries: int, optional
Number of time to retry download, defaults to 3.
"""
# pylint: disable=import-outside-toplevel
import urllib.request as urllib2
path = Path(path).resolve()
if path.exists() and path.is_file() and not overwrite:
if size_compare:
import requests
file_size = path.stat().st_size
res_head = requests.head(url)
res_get = requests.get(url, stream=True)
if "Content-Length" not in res_head.headers:
res_get = urllib2.urlopen(url)
url_file_size = int(res_get.headers["Content-Length"])
if url_file_size != file_size:
LOG.warning("Existing file %s has incorrect size, downloading fresh copy", path)
download(url, path, overwrite=True, size_compare=False, retries=retries)
return
LOG.info("File %s exists, skipping.", path)
return
LOG.info("Downloading from url %s to %s", url, path)
# Stateful start time
start_time = time.time()
dirpath = path.parent
dirpath.mkdir(parents=True, exist_ok=True)
def _download_progress(count, block_size, total_size):
# pylint: disable=unused-argument
"""Show the download progress."""
if count == 0:
return
duration = time.time() - start_time
progress_bytes = int(count * block_size)
progress_megabytes = progress_bytes / (1024.0 * 1024)
speed_kbps = int(progress_bytes / (1024 * duration))
percent = min(int(count * block_size * 100 / total_size), 100)
# Temporarily suppress newlines on the output stream.
prev_terminator = logging.StreamHandler.terminator
logging.StreamHandler.terminator = ""
LOG.debug(
"\r...%d%%, %.2f MB, %d KB/s, %d seconds passed",
percent,
progress_megabytes,
speed_kbps,
duration,
)
logging.StreamHandler.terminator = prev_terminator
with tempfile.TemporaryDirectory() as tempdir:
tempdir = Path(tempdir)
download_loc = tempdir.joinpath(path.name)
for i_retry in range(retries):
# pylint: disable=broad-except
try:
urllib2.urlretrieve(url, download_loc, reporthook=_download_progress)
LOG.debug("")
try:
download_loc.rename(path)
except OSError:
# Prefer a move, but if the tempdir and final
# location are in different drives, fall back to a
# copy.
shutil.copy2(download_loc, path)
return
except Exception as err:
if i_retry == retries - 1:
raise err
LOG.warning(
"%s\nDownload attempt %d/%d failed, retrying.", repr(err), i_retry, retries
)
if "TEST_DATA_ROOT_PATH" in os.environ:
TEST_DATA_ROOT_PATH = Path(os.environ.get("TEST_DATA_ROOT_PATH"))
else:
TEST_DATA_ROOT_PATH = Path(Path("~").expanduser(), ".tvm_test_data")
TEST_DATA_ROOT_PATH.mkdir(parents=True, exist_ok=True)
def download_testdata(url, relpath, module=None, overwrite=False):
"""Downloads the test data from the internet.
Parameters
----------
url : str
Download url.
relpath : str
Relative file path.
module : Union[str, list, tuple], optional
Subdirectory paths under test data folder.
overwrite : bool, defaults to False
If True, will download a fresh copy of the file regardless of
the cache. If False, will only download the file if a cached
version is missing.
Returns
-------
abspath : str
Absolute file path of downloaded file
"""
global TEST_DATA_ROOT_PATH
if module is None:
module_path = ""
elif isinstance(module, str):
module_path = module
elif isinstance(module, list | tuple):
module_path = Path(*module)
else:
raise ValueError("Unsupported module: " + module)
abspath = Path(TEST_DATA_ROOT_PATH, module_path, relpath)
download(url, abspath, overwrite=overwrite, size_compare=False)
return str(abspath)