Skip to content

Commit 632c8e6

Browse files
authored
Move CrossBuildEnvManager._download to common.download_and_unpack_achive (#82)
Split from #81, non functional.
1 parent 198fcaa commit 632c8e6

File tree

3 files changed

+55
-57
lines changed

3 files changed

+55
-57
lines changed

pyodide_build/common.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@
1010
import sys
1111
import textwrap
1212
import tomllib
13+
import warnings
1314
import zipfile
1415
from collections import deque
1516
from collections.abc import Generator, Iterable, Iterator, Mapping
1617
from contextlib import contextmanager
1718
from pathlib import Path
18-
from tempfile import TemporaryDirectory
19+
from tempfile import NamedTemporaryFile, TemporaryDirectory
1920
from typing import Any, NoReturn
21+
from urllib.request import urlopen
2022
from zipfile import ZipFile
2123

2224
from packaging.tags import Tag
@@ -447,3 +449,45 @@ def to_bool(value: str) -> bool:
447449
Convert a string to a boolean value. Useful for parsing environment variables.
448450
"""
449451
return value.lower() not in {"", "0", "false", "no", "off"}
452+
453+
454+
def download_and_unpack_archive(url: str, path: Path, descr: str) -> None:
455+
"""
456+
Download the cross-build environment from the given URL and extract it to the given path.
457+
458+
Parameters
459+
----------
460+
url
461+
URL to download the cross-build environment from.
462+
path
463+
Path to extract the cross-build environment to.
464+
If the path already exists, raise an error.
465+
"""
466+
logger.info("Downloading %s from %s", descr, url)
467+
468+
if path.exists():
469+
raise FileExistsError(f"Path {path} already exists")
470+
471+
try:
472+
resp = urlopen(url)
473+
data = resp.read()
474+
except Exception as e:
475+
raise ValueError(f"Failed to download {descr} from {url}") from e
476+
477+
# FIXME: requests makes a verbose output (see: https://github.com/pyodide/pyodide/issues/4810)
478+
# r = requests.get(url)
479+
480+
# if r.status_code != 200:
481+
# raise ValueError(
482+
# f"Failed to download cross-build environment from {url} (status code: {r.status_code})"
483+
# )
484+
485+
with NamedTemporaryFile(suffix=".tar") as f:
486+
f_path = Path(f.name)
487+
f_path.write_bytes(data)
488+
with warnings.catch_warnings():
489+
# Python 3.12-3.13 emits a DeprecationWarning when using shutil.unpack_archive without a filter,
490+
# but filter doesn't work well for zip files, so we suppress the warning until we find a better solution.
491+
# https://github.com/python/cpython/issues/112760
492+
warnings.simplefilter("ignore")
493+
shutil.unpack_archive(str(f_path), path)

pyodide_build/tests/test_xbuildenv.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import pytest
44

5+
from pyodide_build.common import download_and_unpack_archive
56
from pyodide_build.xbuildenv import CrossBuildEnvManager, _url_to_version
67

78

@@ -91,24 +92,20 @@ def test_current_version(self, tmp_path):
9192
assert manager.current_version == "0.25.0"
9293

9394
def test_download(self, tmp_path, dummy_xbuildenv_url):
94-
manager = CrossBuildEnvManager(tmp_path)
95-
9695
download_path = tmp_path / "test"
97-
manager._download(dummy_xbuildenv_url, download_path)
96+
download_and_unpack_archive(dummy_xbuildenv_url, download_path, "")
9897

9998
assert download_path.exists()
10099
assert (download_path / "xbuildenv").exists()
101100
assert (download_path / "xbuildenv" / "pyodide-root").exists()
102101

103102
def test_download_path_exists(self, tmp_path):
104-
manager = CrossBuildEnvManager(tmp_path)
105-
106103
download_path = tmp_path / "test"
107104
download_path.mkdir()
108105

109106
with pytest.raises(FileExistsError, match="Path .* already exists"):
110-
manager._download(
111-
"https://example.com/xbuildenv-0.25.0.tar.bz2", download_path
107+
download_and_unpack_archive(
108+
"https://example.com/xbuildenv-0.25.0.tar.bz2", download_path, ""
112109
)
113110

114111
def test_find_latest_version(self, tmp_path, fake_xbuildenv_releases_compatible):
@@ -224,7 +221,7 @@ def test_install_cross_build_packages(
224221
manager = CrossBuildEnvManager(tmp_path)
225222

226223
download_path = tmp_path / "test"
227-
manager._download(dummy_xbuildenv_url, download_path)
224+
download_and_unpack_archive(dummy_xbuildenv_url, download_path, "")
228225

229226
xbuildenv_root = download_path / "xbuildenv"
230227
xbuildenv_pyodide_root = xbuildenv_root / "pyodide-root"
@@ -248,7 +245,7 @@ def test_create_package_index(self, tmp_path, dummy_xbuildenv_url):
248245
manager = CrossBuildEnvManager(tmp_path)
249246

250247
download_path = tmp_path / "test"
251-
manager._download(dummy_xbuildenv_url, download_path)
248+
download_and_unpack_archive(dummy_xbuildenv_url, download_path, "")
252249

253250
xbuildenv_root = download_path / "xbuildenv"
254251
xbuildenv_pyodide_root = xbuildenv_root / "pyodide-root"

pyodide_build/xbuildenv.py

Lines changed: 4 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
import json
22
import shutil
33
import subprocess
4-
import warnings
54
from pathlib import Path
6-
from tempfile import NamedTemporaryFile
7-
from urllib.request import urlopen
85

96
from pyodide_lock import PyodideLockSpec
107

118
from pyodide_build import build_env
9+
from pyodide_build.common import download_and_unpack_archive
1210
from pyodide_build.create_package_index import create_package_index
1311
from pyodide_build.logger import logger
1412
from pyodide_build.xbuildenv_releases import (
@@ -194,7 +192,9 @@ def install(
194192
download_path,
195193
)
196194
else:
197-
self._download(download_url, download_path)
195+
download_and_unpack_archive(
196+
download_url, download_path, "Pyodide cross-build environment"
197+
)
198198

199199
try:
200200
# there is an redundant directory "xbuildenv" inside the xbuildenv archive
@@ -240,49 +240,6 @@ def _find_latest_version(self) -> str:
240240

241241
return latest.version
242242

243-
def _download(self, url: str, path: Path) -> None:
244-
"""
245-
Download the cross-build environment from the given URL and extract it to the given path.
246-
247-
Parameters
248-
----------
249-
url
250-
URL to download the cross-build environment from.
251-
path
252-
Path to extract the cross-build environment to.
253-
If the path already exists, raise an error.
254-
"""
255-
logger.info("Downloading Pyodide cross-build environment from %s", url)
256-
257-
if path.exists():
258-
raise FileExistsError(f"Path {path} already exists")
259-
260-
try:
261-
resp = urlopen(url)
262-
data = resp.read()
263-
except Exception as e:
264-
raise ValueError(
265-
f"Failed to download cross-build environment from {url}"
266-
) from e
267-
268-
# FIXME: requests makes a verbose output (see: https://github.com/pyodide/pyodide/issues/4810)
269-
# r = requests.get(url)
270-
271-
# if r.status_code != 200:
272-
# raise ValueError(
273-
# f"Failed to download cross-build environment from {url} (status code: {r.status_code})"
274-
# )
275-
276-
with NamedTemporaryFile(suffix=".tar") as f:
277-
f_path = Path(f.name)
278-
f_path.write_bytes(data)
279-
with warnings.catch_warnings():
280-
# Python 3.12-3.13 emits a DeprecationWarning when using shutil.unpack_archive without a filter,
281-
# but filter doesn't work well for zip files, so we suppress the warning until we find a better solution.
282-
# https://github.com/python/cpython/issues/112760
283-
warnings.simplefilter("ignore")
284-
shutil.unpack_archive(str(f_path), path)
285-
286243
def _install_cross_build_packages(
287244
self, xbuildenv_root: Path, xbuildenv_pyodide_root: Path
288245
) -> None:

0 commit comments

Comments
 (0)