Skip to content

Instantly share code, notes, and snippets.

@scivision
Created September 10, 2021 00:10
Show Gist options
  • Save scivision/c6ecc06831cf1003bc0d3def0ebd687a to your computer and use it in GitHub Desktop.
Save scivision/c6ecc06831cf1003bc0d3def0ebd687a to your computer and use it in GitHub Desktop.
Meson build download and extract file
run_command('python', 'meson_file_download.py', url, zipfn, '-hash', 'md5', md5hash, check: true)
run_command('python', 'meson_file_extract.py', zipfn, outpath, check: true)
#!/usr/bin/env python3
"""
We use SystemExit as this will not blast the whole traceback to Meson.
Usually just a terse stderr will suffice and not overwhelm the Meson user.
"""
from __future__ import annotations
from pathlib import Path
import urllib.request
import urllib.error
import hashlib
import argparse
import socket
def url_retrieve(
url: str,
outfile: Path,
filehash: tuple[str, str] = None,
overwrite: bool = False,
):
"""
Parameters
----------
url: str
URL to download from
outfile: pathlib.Path
output filepath (including name)
filehash: tuple of str, str
hash type (md5, sha1, etc.) and hash
overwrite: bool
overwrite if file exists
"""
outfile = Path(outfile).expanduser().resolve()
if outfile.is_dir():
raise ValueError("Please specify full filepath, including filename")
# need .resolve() in case intermediate relative dir doesn't exist
if overwrite or not outfile.is_file():
outfile.parent.mkdir(parents=True, exist_ok=True)
try:
urllib.request.urlretrieve(url, str(outfile))
except (socket.gaierror, urllib.error.URLError) as err:
raise SystemExit(
"ConnectionError: could not download {} due to {}".format(url, err)
)
if filehash:
if not file_checksum(outfile, filehash[0], filehash[1]):
raise SystemExit("HashError: {}".format(outfile))
def file_checksum(fn: Path, mode: str, filehash: str) -> bool:
h = hashlib.new(mode)
h.update(fn.read_bytes())
return h.hexdigest() == filehash
if __name__ == "__main__":
p = argparse.ArgumentParser()
p.add_argument("url", help="URL to file download")
p.add_argument("outfile", help="filename to download to")
p.add_argument("-hash", help="expected hash", nargs=2)
P = p.parse_args()
url_retrieve(P.url, P.outfile, P.hash)
#!/usr/bin/env python3
from pathlib import Path
import argparse
import zipfile
import tarfile
def extract_zip(fn: Path, outpath: Path, overwrite: bool = False):
outpath = Path(outpath).expanduser().resolve()
# need .resolve() in case intermediate relative dir doesn't exist
if outpath.is_dir() and not overwrite:
return
fn = Path(fn).expanduser().resolve()
with zipfile.ZipFile(fn) as z:
z.extractall(str(outpath.parent))
def extract_tar(fn: Path, outpath: Path, overwrite: bool = False):
outpath = Path(outpath).expanduser().resolve()
# need .resolve() in case intermediate relative dir doesn't exist
if outpath.is_dir() and not overwrite:
return
fn = Path(fn).expanduser().resolve()
if not fn.is_file():
raise FileNotFoundError(fn) # keep this, tarfile gives confusing error
with tarfile.open(fn) as z:
z.extractall(str(outpath.parent))
if __name__ == "__main__":
p = argparse.ArgumentParser()
p.add_argument("infile", help="compressed file to extract")
p.add_argument("outpath", help="path to extract into")
P = p.parse_args()
infile = Path(P.infile)
if infile.suffix.lower() == ".zip":
extract_zip(infile, P.outpath)
elif infile.suffix.lower() in (".tar", ".gz", ".bz2", ".xz"):
extract_tar(infile, P.outpath)
else:
raise ValueError("Not sure how to decompress {}".format(infile))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment