Skip to content

Commit da0d435

Browse files
committed
Simplify setupext.download_or_cache.
Instead of repeatedly unwrapping and rewrapping the file contents in a BytesIO that needs to be seek()ed, just pass around the bytes object itself.
1 parent 663a429 commit da0d435

File tree

1 file changed

+29
-72
lines changed

1 file changed

+29
-72
lines changed

setupext.py

Lines changed: 29 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,10 @@ def _get_xdg_cache_dir():
3636
return pathlib.Path(cache_dir, 'matplotlib')
3737

3838

39-
def get_fd_hash(fd):
40-
"""
41-
Compute the sha256 hash of the bytes in a file-like
42-
"""
43-
BLOCKSIZE = 1 << 16
39+
def _get_hash(data):
40+
"""Compute the sha256 hash of *data*."""
4441
hasher = hashlib.sha256()
45-
old_pos = fd.tell()
46-
fd.seek(0)
47-
buf = fd.read(BLOCKSIZE)
48-
while buf:
49-
hasher.update(buf)
50-
buf = fd.read(BLOCKSIZE)
51-
fd.seek(old_pos)
42+
hasher.update(data)
5243
return hasher.hexdigest()
5344

5445

@@ -59,10 +50,9 @@ def download_or_cache(url, sha):
5950
Parameters
6051
----------
6152
url : str
62-
The url to download
63-
53+
The url to download.
6454
sha : str
65-
The sha256 of the file
55+
The sha256 of the file.
6656
6757
Returns
6858
-------
@@ -71,52 +61,37 @@ def download_or_cache(url, sha):
7161
"""
7262
cache_dir = _get_xdg_cache_dir()
7363

74-
def get_from_cache(local_fn):
75-
if cache_dir is None:
76-
raise Exception("no cache dir")
77-
buf = BytesIO((cache_dir / local_fn).read_bytes())
78-
if get_fd_hash(buf) != sha:
79-
return None
80-
buf.seek(0)
81-
return buf
82-
83-
def write_cache(local_fn, data):
84-
if cache_dir is None:
85-
raise Exception("no cache dir")
86-
cache_dir.mkdir(parents=True, exist_ok=True)
87-
old_pos = data.tell()
88-
data.seek(0)
89-
with open(cache_dir / local_fn, "xb") as fout:
90-
fout.write(data.read())
91-
data.seek(old_pos)
92-
93-
try:
94-
return get_from_cache(sha)
95-
except Exception:
96-
pass
64+
if cache_dir is not None: # Try to read from cache.
65+
try:
66+
data = (cache_dir / sha).read_bytes()
67+
except IOError:
68+
pass
69+
else:
70+
if _get_hash(data) == sha:
71+
return BytesIO(data)
9772

9873
# jQueryUI's website blocks direct downloads from urllib.request's
9974
# default User-Agent, but not (for example) wget; so I don't feel too
10075
# bad passing in an empty User-Agent.
10176
with urllib.request.urlopen(
10277
Request(url, headers={"User-Agent": ""})) as req:
103-
file_contents = BytesIO(req.read())
104-
file_contents.seek(0)
105-
106-
file_sha = get_fd_hash(file_contents)
78+
data = req.read()
10779

80+
file_sha = _get_hash(data)
10881
if file_sha != sha:
10982
raise Exception(
11083
f"The download file does not match the expected sha. {url} was "
11184
f"expected to have {sha} but it had {file_sha}")
11285

113-
try:
114-
write_cache(sha, file_contents)
115-
except Exception:
116-
pass
86+
if cache_dir is not None: # Try to cache the downloaded file.
87+
try:
88+
cache_dir.mkdir(parents=True, exist_ok=True)
89+
with open(cache_dir / sha, "xb") as fout:
90+
fout.write(data)
91+
except IOError:
92+
pass
11793

118-
file_contents.seek(0)
119-
return file_contents
94+
return BytesIO(data)
12095

12196

12297
# SHA256 hashes of the FreeType tarballs
@@ -176,16 +151,6 @@ def print_status(package, status):
176151
subsequent_indent=indent))
177152

178153

179-
def get_buffer_hash(fd):
180-
BLOCKSIZE = 1 << 16
181-
hasher = hashlib.sha256()
182-
buf = fd.read(BLOCKSIZE)
183-
while buf:
184-
hasher.update(buf)
185-
buf = fd.read(BLOCKSIZE)
186-
return hasher.hexdigest()
187-
188-
189154
@functools.lru_cache(1) # We only need to compute this once.
190155
def get_pkg_config():
191156
"""
@@ -513,18 +478,13 @@ def do_custom_build(self):
513478
if not src_path.exists():
514479
os.makedirs('build', exist_ok=True)
515480

516-
url_fmts = [
517-
('https://downloads.sourceforge.net/project/freetype'
518-
'/freetype2/{version}/{tarball}'),
519-
('https://download.savannah.gnu.org/releases/freetype'
520-
'/{tarball}')
521-
]
522481
tarball = f'freetype-{LOCAL_FREETYPE_VERSION}.tar.gz'
523-
524482
target_urls = [
525-
url_fmt.format(version=LOCAL_FREETYPE_VERSION,
526-
tarball=tarball)
527-
for url_fmt in url_fmts]
483+
(f'https://downloads.sourceforge.net/project/freetype'
484+
f'/freetype2/{LOCAL_FREETYPE_VERSION}/{tarball}'),
485+
(f'https://download.savannah.gnu.org/releases/freetype'
486+
f'/{tarball}')
487+
]
528488

529489
for tarball_url in target_urls:
530490
try:
@@ -540,10 +500,7 @@ def do_custom_build(self):
540500
f"top-level of the source repository.")
541501

542502
print(f"Extracting {tarball}")
543-
# just to be sure
544-
tar_contents.seek(0)
545-
with tarfile.open(tarball, mode="r:gz",
546-
fileobj=tar_contents) as tgz:
503+
with tarfile.open(fileobj=tar_contents, mode="r:gz") as tgz:
547504
tgz.extractall("build")
548505

549506
print(f"Building freetype in {src_path}")

0 commit comments

Comments
 (0)