Skip to content

Commit b395c9f

Browse files
authored
Merge pull request #7696 from chrahunt/refactor/auto-cleanup-source-dir
Globally manage InstallRequirement.source_dir
2 parents 1966579 + 85ab574 commit b395c9f

File tree

11 files changed

+40
-101
lines changed

11 files changed

+40
-101
lines changed

src/pip/_internal/commands/download.py

-4
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,4 @@ def run(self, options, args):
140140
if downloaded:
141141
write_output('Successfully downloaded %s', downloaded)
142142

143-
# Clean up
144-
if not options.no_clean:
145-
requirement_set.cleanup_files()
146-
147143
return requirement_set

src/pip/_internal/commands/install.py

-4
Original file line numberDiff line numberDiff line change
@@ -443,10 +443,6 @@ def run(self, options, args):
443443
except PreviousBuildDirError:
444444
options.no_clean = True
445445
raise
446-
finally:
447-
# Clean up
448-
if not options.no_clean:
449-
requirement_set.cleanup_files()
450446

451447
if options.target_dir:
452448
self._handle_target_dir(

src/pip/_internal/commands/wheel.py

-3
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,3 @@ def run(self, options, args):
191191
except PreviousBuildDirError:
192192
options.no_clean = True
193193
raise
194-
finally:
195-
if not options.no_clean:
196-
requirement_set.cleanup_files()

src/pip/_internal/legacy_resolve.py

-3
Original file line numberDiff line numberDiff line change
@@ -327,9 +327,6 @@ def _resolve_one(
327327

328328
req_to_install.prepared = True
329329

330-
# register tmp src for cleanup in case something goes wrong
331-
requirement_set.reqs_to_cleanup.append(req_to_install)
332-
333330
abstract_dist = self._get_abstract_dist_for(req_to_install)
334331

335332
# Parse and return dependencies

src/pip/_internal/operations/prepare.py

+20-23
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
from pip._internal.utils.filesystem import copy2_fixed
2929
from pip._internal.utils.hashes import MissingHashes
3030
from pip._internal.utils.logging import indent_log
31-
from pip._internal.utils.marker_files import write_delete_marker_file
3231
from pip._internal.utils.misc import (
3332
ask_path_exists,
3433
backup_dir,
@@ -416,14 +415,33 @@ def prepare_linked_requirement(
416415
else:
417416
logger.info('Collecting %s', req.req or req)
418417

418+
download_dir = self.download_dir
419+
if link.is_wheel and self.wheel_download_dir:
420+
# when doing 'pip wheel` we download wheels to a
421+
# dedicated dir.
422+
download_dir = self.wheel_download_dir
423+
424+
if link.is_wheel:
425+
if download_dir:
426+
# When downloading, we only unpack wheels to get
427+
# metadata.
428+
autodelete_unpacked = True
429+
else:
430+
# When installing a wheel, we use the unpacked
431+
# wheel.
432+
autodelete_unpacked = False
433+
else:
434+
# We always delete unpacked sdists after pip runs.
435+
autodelete_unpacked = True
436+
419437
with indent_log():
420438
# @@ if filesystem packages are not marked
421439
# editable in a req, a non deterministic error
422440
# occurs when the script attempts to unpack the
423441
# build directory
424442
# Since source_dir is only set for editable requirements.
425443
assert req.source_dir is None
426-
req.ensure_has_source_dir(self.build_dir)
444+
req.ensure_has_source_dir(self.build_dir, autodelete_unpacked)
427445
# If a checkout exists, it's unwise to keep going. version
428446
# inconsistencies are logged later, but do not fail the
429447
# installation.
@@ -471,12 +489,6 @@ def prepare_linked_requirement(
471489
# showing the user what the hash should be.
472490
hashes = MissingHashes()
473491

474-
download_dir = self.download_dir
475-
if link.is_wheel and self.wheel_download_dir:
476-
# when doing 'pip wheel` we download wheels to a
477-
# dedicated dir.
478-
download_dir = self.wheel_download_dir
479-
480492
try:
481493
local_file = unpack_url(
482494
link, req.source_dir, self.downloader, download_dir,
@@ -498,21 +510,6 @@ def prepare_linked_requirement(
498510
if local_file:
499511
req.local_file_path = local_file.path
500512

501-
if link.is_wheel:
502-
if download_dir:
503-
# When downloading, we only unpack wheels to get
504-
# metadata.
505-
autodelete_unpacked = True
506-
else:
507-
# When installing a wheel, we use the unpacked
508-
# wheel.
509-
autodelete_unpacked = False
510-
else:
511-
# We always delete unpacked sdists after pip runs.
512-
autodelete_unpacked = True
513-
if autodelete_unpacked:
514-
write_delete_marker_file(req.source_dir)
515-
516513
abstract_dist = _get_prepared_distribution(
517514
req, self.req_tracker, self.finder, self.build_isolation,
518515
)

src/pip/_internal/req/req_install.py

+17-23
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,6 @@
3333
from pip._internal.utils.deprecation import deprecated
3434
from pip._internal.utils.hashes import Hashes
3535
from pip._internal.utils.logging import indent_log
36-
from pip._internal.utils.marker_files import (
37-
PIP_DELETE_MARKER_FILENAME,
38-
has_delete_marker_file,
39-
)
4036
from pip._internal.utils.misc import (
4137
ask_path_exists,
4238
backup_dir,
@@ -46,7 +42,6 @@
4642
get_installed_version,
4743
hide_url,
4844
redact_auth_from_url,
49-
rmtree,
5045
)
5146
from pip._internal.utils.packaging import get_metadata
5247
from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds
@@ -348,8 +343,8 @@ def from_path(self):
348343
s += '->' + comes_from
349344
return s
350345

351-
def ensure_build_location(self, build_dir):
352-
# type: (str) -> str
346+
def ensure_build_location(self, build_dir, autodelete):
347+
# type: (str, bool) -> str
353348
assert build_dir is not None
354349
if self._temp_build_dir is not None:
355350
assert self._temp_build_dir.path
@@ -372,7 +367,16 @@ def ensure_build_location(self, build_dir):
372367
if not os.path.exists(build_dir):
373368
logger.debug('Creating directory %s', build_dir)
374369
os.makedirs(build_dir)
375-
return os.path.join(build_dir, name)
370+
actual_build_dir = os.path.join(build_dir, name)
371+
# `None` indicates that we respect the globally-configured deletion
372+
# settings, which is what we actually want when auto-deleting.
373+
delete_arg = None if autodelete else False
374+
return TempDirectory(
375+
path=actual_build_dir,
376+
delete=delete_arg,
377+
kind=tempdir_kinds.REQ_BUILD,
378+
globally_managed=True,
379+
).path
376380

377381
def _set_requirement(self):
378382
# type: () -> None
@@ -412,16 +416,6 @@ def warn_on_mismatching_name(self):
412416
)
413417
self.req = Requirement(metadata_name)
414418

415-
def remove_temporary_source(self):
416-
# type: () -> None
417-
"""Remove the source files from this requirement, if they are marked
418-
for deletion"""
419-
if self.source_dir and has_delete_marker_file(self.source_dir):
420-
logger.debug('Removing source in %s', self.source_dir)
421-
rmtree(self.source_dir)
422-
self.source_dir = None
423-
self._temp_build_dir = None
424-
425419
def check_if_exists(self, use_user_site):
426420
# type: (bool) -> None
427421
"""Find an installed distribution that satisfies or conflicts
@@ -599,8 +593,8 @@ def assert_source_matches_version(self):
599593
)
600594

601595
# For both source distributions and editables
602-
def ensure_has_source_dir(self, parent_dir):
603-
# type: (str) -> None
596+
def ensure_has_source_dir(self, parent_dir, autodelete=False):
597+
# type: (str, bool) -> None
604598
"""Ensure that a source_dir is set.
605599
606600
This will create a temporary build dir if the name of the requirement
@@ -611,7 +605,9 @@ def ensure_has_source_dir(self, parent_dir):
611605
:return: self.source_dir
612606
"""
613607
if self.source_dir is None:
614-
self.source_dir = self.ensure_build_location(parent_dir)
608+
self.source_dir = self.ensure_build_location(
609+
parent_dir, autodelete
610+
)
615611

616612
# For editable installations
617613
def update_editable(self, obtain=True):
@@ -755,8 +751,6 @@ def archive(self, build_dir):
755751
zipdir.external_attr = 0x1ED << 16 # 0o755
756752
zip_output.writestr(zipdir, '')
757753
for filename in filenames:
758-
if filename == PIP_DELETE_MARKER_FILENAME:
759-
continue
760754
file_arcname = self._get_archive_name(
761755
filename, parentdir=dirpath, rootdir=dir,
762756
)

src/pip/_internal/req/req_set.py

-11
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from pip._internal import pep425tags
1212
from pip._internal.exceptions import InstallationError
1313
from pip._internal.models.wheel import Wheel
14-
from pip._internal.utils.logging import indent_log
1514
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
1615

1716
if MYPY_CHECK_RUNNING:
@@ -34,7 +33,6 @@ def __init__(self, check_supported_wheels=True):
3433

3534
self.unnamed_requirements = [] # type: List[InstallRequirement]
3635
self.successfully_downloaded = [] # type: List[InstallRequirement]
37-
self.reqs_to_cleanup = [] # type: List[InstallRequirement]
3836

3937
def __str__(self):
4038
# type: () -> str
@@ -162,7 +160,6 @@ def add_requirement(
162160
)
163161
)
164162
if does_not_satisfy_constraint:
165-
self.reqs_to_cleanup.append(install_req)
166163
raise InstallationError(
167164
"Could not satisfy constraints for '{}': "
168165
"installation from path or url cannot be "
@@ -199,11 +196,3 @@ def get_requirement(self, name):
199196
return self.requirements[project_name]
200197

201198
raise KeyError("No project with the name %r" % name)
202-
203-
def cleanup_files(self):
204-
# type: () -> None
205-
"""Clean up files, remove builds."""
206-
logger.debug('Cleaning up...')
207-
with indent_log():
208-
for req in self.reqs_to_cleanup:
209-
req.remove_temporary_source()

src/pip/_internal/utils/marker_files.py

-25
This file was deleted.

tests/functional/test_install_cleanup.py

-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import pytest
55

66
from pip._internal.cli.status_codes import PREVIOUS_BUILD_DIR_ERROR
7-
from pip._internal.utils.marker_files import write_delete_marker_file
87
from tests.lib import need_mercurial, windows_workaround_7667
98
from tests.lib.local_repos import local_checkout
109

@@ -126,7 +125,6 @@ def test_cleanup_prevented_upon_build_dir_exception(script, data):
126125
build = script.venv_path / 'build'
127126
build_simple = build / 'simple'
128127
os.makedirs(build_simple)
129-
write_delete_marker_file(build_simple)
130128
build_simple.joinpath("setup.py").write_text("#")
131129
result = script.pip(
132130
'install', '-f', data.find_links, '--no-index', 'simple',

tests/functional/test_wheel.py

-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import pytest
77

88
from pip._internal.cli.status_codes import ERROR, PREVIOUS_BUILD_DIR_ERROR
9-
from pip._internal.utils.marker_files import write_delete_marker_file
109
from tests.lib import pyversion
1110

1211

@@ -225,7 +224,6 @@ def test_pip_wheel_fail_cause_of_previous_build_dir(script, data):
225224
# Given that I have a previous build dir of the `simple` package
226225
build = script.venv_path / 'build' / 'simple'
227226
os.makedirs(build)
228-
write_delete_marker_file(script.venv_path / 'build' / 'simple')
229227
build.joinpath('setup.py').write_text('#')
230228

231229
# When I call pip trying to install things again

tests/unit/test_req_install.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ def test_tmp_build_directory(self):
2020
# Make sure we're handling it correctly with real path.
2121
requirement = InstallRequirement(None, None)
2222
tmp_dir = tempfile.mkdtemp('-build', 'pip-')
23-
tmp_build_dir = requirement.ensure_build_location(tmp_dir)
23+
tmp_build_dir = requirement.ensure_build_location(
24+
tmp_dir, autodelete=False
25+
)
2426
assert (
2527
os.path.dirname(tmp_build_dir) ==
2628
os.path.realpath(os.path.dirname(tmp_dir))

0 commit comments

Comments
 (0)