Skip to content

Commit 711cf4d

Browse files
authored
Merge pull request #7517 from sbidoul/wheel-builder-disentangle-6-sbi
Move final wheel builder copy operation to wheel command
2 parents 7420629 + 1f39950 commit 711cf4d

File tree

5 files changed

+35
-37
lines changed

5 files changed

+35
-37
lines changed

news/7517.feature

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
The build step of ``pip wheel`` now builds all wheels to a cache first,
2+
then copies them to the wheel directory all at once.
3+
Before, it built them to a temporary direcory and moved
4+
them to the wheel directory one by one.

src/pip/_internal/commands/install.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def build_wheels(
8383
should_build_legacy = is_wheel_installed()
8484

8585
# Always build PEP 517 requirements
86-
build_failures = builder.build(
86+
_, build_failures = builder.build(
8787
pep517_requirements,
8888
should_unpack=True,
8989
)

src/pip/_internal/commands/wheel.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77

88
import logging
99
import os
10+
import shutil
1011

1112
from pip._internal.cache import WheelCache
1213
from pip._internal.cli import cmdoptions
1314
from pip._internal.cli.req_command import RequirementCommand
1415
from pip._internal.exceptions import CommandError, PreviousBuildDirError
1516
from pip._internal.req import RequirementSet
1617
from pip._internal.req.req_tracker import get_requirement_tracker
18+
from pip._internal.utils.misc import ensure_dir
1719
from pip._internal.utils.temp_dir import TempDirectory
1820
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
1921
from pip._internal.wheel_builder import WheelBuilder
@@ -161,10 +163,23 @@ def run(self, options, args):
161163
build_options=options.build_options or [],
162164
global_options=options.global_options or [],
163165
)
164-
build_failures = wb.build(
166+
build_successes, build_failures = wb.build(
165167
requirement_set.requirements.values(),
166168
should_unpack=False,
167169
)
170+
for req in build_successes:
171+
assert req.link and req.link.is_wheel
172+
assert req.local_file_path
173+
# copy from cache to target directory
174+
try:
175+
ensure_dir(options.wheel_dir)
176+
shutil.copy(req.local_file_path, options.wheel_dir)
177+
except OSError as e:
178+
logger.warning(
179+
"Building wheel for %s failed: %s",
180+
req.name, e,
181+
)
182+
build_failures.append(req)
168183
if len(build_failures) != 0:
169184
raise CommandError(
170185
"Failed to build one or more wheels"

src/pip/_internal/wheel_builder.py

Lines changed: 13 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
from pip._vendor.pep517.wrappers import Pep517HookCaller
3939

4040
BinaryAllowedPredicate = Callable[[InstallRequirement], bool]
41+
BuildResult = Tuple[List[InstallRequirement], List[InstallRequirement]]
4142

4243
logger = logging.getLogger(__name__)
4344

@@ -216,8 +217,6 @@ def __init__(
216217
self.preparer = preparer
217218
self.wheel_cache = wheel_cache
218219

219-
self._wheel_dir = preparer.wheel_download_dir
220-
221220
self.build_options = build_options or []
222221
self.global_options = global_options or []
223222
self.check_binary_allowed = check_binary_allowed
@@ -311,31 +310,23 @@ def build(
311310
requirements, # type: Iterable[InstallRequirement]
312311
should_unpack, # type: bool
313312
):
314-
# type: (...) -> List[InstallRequirement]
313+
# type: (...) -> BuildResult
315314
"""Build wheels.
316315
317316
:param should_unpack: If True, after building the wheel, unpack it
318317
and replace the sdist with the unpacked version in preparation
319318
for installation.
320-
:return: The list of InstallRequirement that failed to build.
319+
:return: The list of InstallRequirement that succeeded to build and
320+
the list of InstallRequirement that failed to build.
321321
"""
322-
# pip install uses should_unpack=True.
323-
# pip install never provides a _wheel_dir.
324-
# pip wheel uses should_unpack=False.
325-
# pip wheel always provides a _wheel_dir (via the preparer).
326-
assert (
327-
(should_unpack and not self._wheel_dir) or
328-
(not should_unpack and self._wheel_dir)
329-
)
330-
331322
buildset = _collect_buildset(
332323
requirements,
333324
wheel_cache=self.wheel_cache,
334325
check_binary_allowed=self.check_binary_allowed,
335326
need_wheel=not should_unpack,
336327
)
337328
if not buildset:
338-
return []
329+
return [], []
339330

340331
# TODO by @pradyunsg
341332
# Should break up this method into 2 separate methods.
@@ -347,7 +338,7 @@ def build(
347338
)
348339

349340
with indent_log():
350-
build_success, build_failure = [], []
341+
build_successes, build_failures = [], []
351342
for req, cache_dir in buildset:
352343
wheel_file = self._build_one(req, cache_dir)
353344
if wheel_file:
@@ -376,32 +367,20 @@ def build(
376367
)
377368
# extract the wheel into the dir
378369
unpack_file(req.link.file_path, req.source_dir)
379-
else:
380-
# copy from cache to target directory
381-
try:
382-
ensure_dir(self._wheel_dir)
383-
shutil.copy(wheel_file, self._wheel_dir)
384-
except OSError as e:
385-
logger.warning(
386-
"Building wheel for %s failed: %s",
387-
req.name, e,
388-
)
389-
build_failure.append(req)
390-
continue
391-
build_success.append(req)
370+
build_successes.append(req)
392371
else:
393-
build_failure.append(req)
372+
build_failures.append(req)
394373

395374
# notify success/failure
396-
if build_success:
375+
if build_successes:
397376
logger.info(
398377
'Successfully built %s',
399-
' '.join([req.name for req in build_success]),
378+
' '.join([req.name for req in build_successes]),
400379
)
401-
if build_failure:
380+
if build_failures:
402381
logger.info(
403382
'Failed to build %s',
404-
' '.join([req.name for req in build_failure]),
383+
' '.join([req.name for req in build_failures]),
405384
)
406385
# Return a list of requirements that failed to build
407-
return build_failure
386+
return build_successes, build_failures

tests/unit/test_command_install.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def check_build_wheels(
2626
"""
2727
def build(reqs, **kwargs):
2828
# Fail the first requirement.
29-
return [reqs[0]]
29+
return ([], [reqs[0]])
3030

3131
builder = Mock()
3232
builder.build.side_effect = build

0 commit comments

Comments
 (0)