Skip to content

Commit ca3bb4b

Browse files
committed
refactor: Use utils.call & utils.shell in macos.py & windows.py
This is taken from pypa#672
1 parent 412ea1a commit ca3bb4b

File tree

3 files changed

+133
-216
lines changed

3 files changed

+133
-216
lines changed

cibuildwheel/macos.py

Lines changed: 68 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,12 @@
22
import os
33
import platform
44
import re
5-
import shlex
65
import shutil
76
import subprocess
87
import sys
98
import tempfile
109
from pathlib import Path
11-
from typing import (
12-
Any,
13-
Dict,
14-
Iterator,
15-
List,
16-
NamedTuple,
17-
Optional,
18-
Sequence,
19-
Set,
20-
Tuple,
21-
cast,
22-
)
10+
from typing import Any, Dict, Iterator, List, NamedTuple, Sequence, Set, Tuple, cast
2311

2412
from filelock import FileLock
2513

@@ -33,33 +21,20 @@
3321
BuildFrontend,
3422
BuildSelector,
3523
NonPlatformWheelError,
24+
call,
3625
detect_ci_provider,
3726
download,
3827
get_build_verbosity_extra_flags,
3928
get_pip_version,
4029
install_certifi_script,
4130
prepare_command,
4231
read_python_configs,
32+
shell,
4333
unwrap,
4434
venv,
4535
)
4636

4737

48-
def call(
49-
args: Sequence[PathOrStr],
50-
env: Optional[Dict[str, str]] = None,
51-
cwd: Optional[PathOrStr] = None,
52-
shell: bool = False,
53-
) -> None:
54-
# print the command executing for the logs
55-
if shell:
56-
print(f"+ {args}")
57-
else:
58-
print("+ " + " ".join(shlex.quote(str(a)) for a in args))
59-
60-
subprocess.run(args, env=env, cwd=cwd, shell=shell, check=True)
61-
62-
6338
def get_macos_version() -> Tuple[int, int]:
6439
"""
6540
Returns the macOS major/minor version, as a tuple, e.g. (10, 15) or (11, 0)
@@ -75,13 +50,7 @@ def get_macos_version() -> Tuple[int, int]:
7550

7651

7752
def get_macos_sdks() -> List[str]:
78-
output = subprocess.run(
79-
["xcodebuild", "-showsdks"],
80-
universal_newlines=True,
81-
check=True,
82-
stdout=subprocess.PIPE,
83-
).stdout
84-
53+
output = call("xcodebuild", "-showsdks", text=True)
8554
return [m.group(1) for m in re.finditer(r"-sdk (macosx\S+)", output)]
8655

8756

@@ -111,9 +80,7 @@ def get_python_configurations(
11180

11281

11382
def install_cpython(version: str, url: str) -> Path:
114-
installed_system_packages = subprocess.run(
115-
["pkgutil", "--pkgs"], universal_newlines=True, check=True, stdout=subprocess.PIPE
116-
).stdout.splitlines()
83+
installed_system_packages = call("pkgutil", "--pkgs", text=True).splitlines()
11784

11885
# if this version of python isn't installed, get it from python.org and install
11986
python_package_identifier = f"org.python.Python.PythonFramework-{version}"
@@ -134,8 +101,8 @@ def install_cpython(version: str, url: str) -> Path:
134101
# download the pkg
135102
download(url, Path("/tmp/Python.pkg"))
136103
# install
137-
call(["sudo", "installer", "-pkg", "/tmp/Python.pkg", "-target", "/"])
138-
call(["sudo", str(installation_path / "bin" / "python3"), str(install_certifi_script)])
104+
call("sudo", "installer", "-pkg", "/tmp/Python.pkg", "-target", "/")
105+
call("sudo", installation_path / "bin" / "python3", install_certifi_script)
139106

140107
return installation_path
141108

@@ -150,7 +117,7 @@ def install_pypy(version: str, url: str) -> Path:
150117
downloaded_tar_bz2 = Path("/tmp") / pypy_tar_bz2
151118
download(url, downloaded_tar_bz2)
152119
installation_path.parent.mkdir(parents=True, exist_ok=True)
153-
call(["tar", "-C", installation_path.parent, "-xf", downloaded_tar_bz2])
120+
call("tar", "-C", installation_path.parent, "-xf", downloaded_tar_bz2)
154121

155122
return installation_path
156123

@@ -196,20 +163,18 @@ def setup_python(
196163
requires_reinstall = not (venv_bin_path / "pip").exists()
197164
if requires_reinstall:
198165
# maybe pip isn't installed at all. ensurepip resolves that.
199-
call(["python", "-m", "ensurepip"], env=env, cwd=venv_path)
166+
call("python", "-m", "ensurepip", env=env, cwd=venv_path)
200167

201168
# upgrade pip to the version matching our constraints
202169
# if necessary, reinstall it to ensure that it's available on PATH as 'pip'
203170
call(
204-
[
205-
"python",
206-
"-m",
207-
"pip",
208-
"install",
209-
"--force-reinstall" if requires_reinstall else "--upgrade",
210-
"pip",
211-
*dependency_constraint_flags,
212-
],
171+
"python",
172+
"-m",
173+
"pip",
174+
"install",
175+
"--force-reinstall" if requires_reinstall else "--upgrade",
176+
"pip",
177+
*dependency_constraint_flags,
213178
env=env,
214179
cwd=venv_path,
215180
)
@@ -219,11 +184,9 @@ def setup_python(
219184

220185
# check what pip version we're on
221186
assert (venv_bin_path / "pip").exists()
222-
call(["which", "pip"], env=env)
223-
call(["pip", "--version"], env=env)
224-
which_pip = subprocess.run(
225-
["which", "pip"], env=env, universal_newlines=True, check=True, stdout=subprocess.PIPE
226-
).stdout.strip()
187+
call("which", "pip", env=env)
188+
call("pip", "--version", env=env)
189+
which_pip = call("which", "pip", env=env, text=True).strip()
227190
if which_pip != str(venv_bin_path / "pip"):
228191
print(
229192
"cibuildwheel: pip available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert pip above it.",
@@ -232,15 +195,9 @@ def setup_python(
232195
sys.exit(1)
233196

234197
# check what Python version we're on
235-
call(["which", "python"], env=env)
236-
call(["python", "--version"], env=env)
237-
which_python = subprocess.run(
238-
["which", "python"],
239-
env=env,
240-
universal_newlines=True,
241-
check=True,
242-
stdout=subprocess.PIPE,
243-
).stdout.strip()
198+
call("which", "python", env=env)
199+
call("python", "--version", env=env)
200+
which_python = call("which", "python", env=env, text=True).strip()
244201
if which_python != str(venv_bin_path / "python"):
245202
print(
246203
"cibuildwheel: python available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert python above it.",
@@ -295,27 +252,23 @@ def setup_python(
295252
log.step("Installing build tools...")
296253
if build_frontend == "pip":
297254
call(
298-
[
299-
"pip",
300-
"install",
301-
"--upgrade",
302-
"setuptools",
303-
"wheel",
304-
"delocate",
305-
*dependency_constraint_flags,
306-
],
255+
"pip",
256+
"install",
257+
"--upgrade",
258+
"setuptools",
259+
"wheel",
260+
"delocate",
261+
*dependency_constraint_flags,
307262
env=env,
308263
)
309264
elif build_frontend == "build":
310265
call(
311-
[
312-
"pip",
313-
"install",
314-
"--upgrade",
315-
"delocate",
316-
"build[virtualenv]",
317-
*dependency_constraint_flags,
318-
],
266+
"pip",
267+
"install",
268+
"--upgrade",
269+
"delocate",
270+
"build[virtualenv]",
271+
*dependency_constraint_flags,
319272
env=env,
320273
)
321274
else:
@@ -344,7 +297,7 @@ def build(options: Options) -> None:
344297
before_all_prepared = prepare_command(
345298
before_all_options.before_all, project=".", package=before_all_options.package_dir
346299
)
347-
call([before_all_prepared], shell=True, env=env)
300+
shell(before_all_prepared, env=env)
348301

349302
for config in python_configurations:
350303
build_options = options.build_options(config.identifier)
@@ -372,7 +325,7 @@ def build(options: Options) -> None:
372325
before_build_prepared = prepare_command(
373326
build_options.before_build, project=".", package=build_options.package_dir
374327
)
375-
call(before_build_prepared, env=env, shell=True)
328+
shell(before_build_prepared, env=env)
376329

377330
log.step("Building wheel...")
378331
if built_wheel_dir.exists():
@@ -385,16 +338,14 @@ def build(options: Options) -> None:
385338
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
386339
# see https://github.com/pypa/cibuildwheel/pull/369
387340
call(
388-
[
389-
"python",
390-
"-m",
391-
"pip",
392-
"wheel",
393-
build_options.package_dir.resolve(),
394-
f"--wheel-dir={built_wheel_dir}",
395-
"--no-deps",
396-
*verbosity_flags,
397-
],
341+
"python",
342+
"-m",
343+
"pip",
344+
"wheel",
345+
build_options.package_dir.resolve(),
346+
f"--wheel-dir={built_wheel_dir}",
347+
"--no-deps",
348+
*verbosity_flags,
398349
env=env,
399350
)
400351
elif build_options.build_frontend == "build":
@@ -409,15 +360,13 @@ def build(options: Options) -> None:
409360
build_env["PIP_CONSTRAINT"] = constraint_path.as_uri()
410361
build_env["VIRTUALENV_PIP"] = get_pip_version(env)
411362
call(
412-
[
413-
"python",
414-
"-m",
415-
"build",
416-
build_options.package_dir,
417-
"--wheel",
418-
f"--outdir={built_wheel_dir}",
419-
f"--config-setting={config_setting}",
420-
],
363+
"python",
364+
"-m",
365+
"build",
366+
build_options.package_dir,
367+
"--wheel",
368+
f"--outdir={built_wheel_dir}",
369+
f"--config-setting={config_setting}",
421370
env=build_env,
422371
)
423372
else:
@@ -448,7 +397,7 @@ def build(options: Options) -> None:
448397
dest_dir=repaired_wheel_dir,
449398
delocate_archs=delocate_archs,
450399
)
451-
call(repair_command_prepared, env=env, shell=True)
400+
shell(repair_command_prepared, env=env)
452401
else:
453402
shutil.move(str(built_wheel), repaired_wheel_dir)
454403

@@ -513,9 +462,7 @@ def build(options: Options) -> None:
513462

514463
# set up a virtual environment to install and test from, to make sure
515464
# there are no dependencies that were pulled in at build time.
516-
call(
517-
["pip", "install", "virtualenv", *dependency_constraint_flags], env=env
518-
)
465+
call("pip", "install", "virtualenv", *dependency_constraint_flags, env=env)
519466
venv_dir = Path(tempfile.mkdtemp())
520467

521468
arch_prefix = []
@@ -529,17 +476,17 @@ def build(options: Options) -> None:
529476
)
530477

531478
# define a custom 'call' function that adds the arch prefix each time
532-
def call_with_arch(args: Sequence[PathOrStr], **kwargs: Any) -> None:
533-
if isinstance(args, str):
534-
args = " ".join(arch_prefix) + " " + args
535-
else:
536-
args = [*arch_prefix, *args]
537-
call(args, **kwargs)
479+
def call_with_arch(*args: PathOrStr, **kwargs: Any) -> None:
480+
call(*arch_prefix, *args, **kwargs)
481+
482+
def shell_with_arch(command: str, **kwargs: Any) -> None:
483+
command = " ".join(arch_prefix) + " " + command
484+
shell(command, **kwargs)
538485

539486
# Use --no-download to ensure determinism by using seed libraries
540487
# built into virtualenv
541488
call_with_arch(
542-
["python", "-m", "virtualenv", "--no-download", venv_dir], env=env
489+
"python", "-m", "virtualenv", "--no-download", venv_dir, env=env
543490
)
544491

545492
virtualenv_env = env.copy()
@@ -551,26 +498,28 @@ def call_with_arch(args: Sequence[PathOrStr], **kwargs: Any) -> None:
551498
)
552499

553500
# check that we are using the Python from the virtual environment
554-
call_with_arch(["which", "python"], env=virtualenv_env)
501+
call_with_arch("which", "python", env=virtualenv_env)
555502

556503
if build_options.before_test:
557504
before_test_prepared = prepare_command(
558505
build_options.before_test,
559506
project=".",
560507
package=build_options.package_dir,
561508
)
562-
call_with_arch(before_test_prepared, env=virtualenv_env, shell=True)
509+
shell_with_arch(before_test_prepared, env=virtualenv_env)
563510

564511
# install the wheel
565512
call_with_arch(
566-
["pip", "install", f"{repaired_wheel}{build_options.test_extras}"],
513+
"pip",
514+
"install",
515+
f"{repaired_wheel}{build_options.test_extras}",
567516
env=virtualenv_env,
568517
)
569518

570519
# test the wheel
571520
if build_options.test_requires:
572521
call_with_arch(
573-
["pip", "install"] + build_options.test_requires, env=virtualenv_env
522+
"pip", "install", *build_options.test_requires, env=virtualenv_env
574523
)
575524

576525
# run the tests from $HOME, with an absolute path in the command
@@ -581,11 +530,10 @@ def call_with_arch(args: Sequence[PathOrStr], **kwargs: Any) -> None:
581530
project=Path(".").resolve(),
582531
package=build_options.package_dir.resolve(),
583532
)
584-
call_with_arch(
533+
shell_with_arch(
585534
test_command_prepared,
586535
cwd=os.environ["HOME"],
587536
env=virtualenv_env,
588-
shell=True,
589537
)
590538

591539
# clean up

cibuildwheel/util.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ def call(
114114
return cast(str, result.stdout)
115115

116116

117+
def shell(
118+
command: str, env: Optional[Dict[str, str]] = None, cwd: Optional[PathOrStr] = None
119+
) -> None:
120+
print(f"+ {command}")
121+
subprocess.run(command, env=env, cwd=cwd, shell=True, check=True)
122+
123+
117124
def format_safe(template: str, **kwargs: Any) -> str:
118125
"""
119126
Works similarly to `template.format(**kwargs)`, except that unmatched

0 commit comments

Comments
 (0)