Skip to content

Commit deecb36

Browse files
authored
Reduce RequirementTracker responsibilities (#7278)
2 parents 2ed5d56 + 031ed90 commit deecb36

File tree

5 files changed

+150
-106
lines changed

5 files changed

+150
-106
lines changed

src/pip/_internal/commands/download.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from pip._internal.cli.cmdoptions import make_target_python
1111
from pip._internal.cli.req_command import RequirementCommand
1212
from pip._internal.req import RequirementSet
13-
from pip._internal.req.req_tracker import RequirementTracker
13+
from pip._internal.req.req_tracker import get_requirement_tracker
1414
from pip._internal.utils.filesystem import check_path_owner
1515
from pip._internal.utils.misc import ensure_dir, normalize_path, write_output
1616
from pip._internal.utils.temp_dir import TempDirectory
@@ -111,7 +111,7 @@ def run(self, options, args):
111111
)
112112
options.cache_dir = None
113113

114-
with RequirementTracker() as req_tracker, TempDirectory(
114+
with get_requirement_tracker() as req_tracker, TempDirectory(
115115
options.build_dir, delete=build_delete, kind="download"
116116
) as directory:
117117

src/pip/_internal/commands/install.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from pip._internal.locations import distutils_scheme
3232
from pip._internal.operations.check import check_install_conflicts
3333
from pip._internal.req import RequirementSet, install_given_reqs
34-
from pip._internal.req.req_tracker import RequirementTracker
34+
from pip._internal.req.req_tracker import get_requirement_tracker
3535
from pip._internal.utils.filesystem import check_path_owner, test_writable_dir
3636
from pip._internal.utils.misc import (
3737
ensure_dir,
@@ -343,7 +343,7 @@ def run(self, options, args):
343343
)
344344
options.cache_dir = None
345345

346-
with RequirementTracker() as req_tracker, TempDirectory(
346+
with get_requirement_tracker() as req_tracker, TempDirectory(
347347
options.build_dir, delete=build_delete, kind="install"
348348
) as directory:
349349
requirement_set = RequirementSet(

src/pip/_internal/commands/wheel.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from pip._internal.cli.req_command import RequirementCommand
1414
from pip._internal.exceptions import CommandError, PreviousBuildDirError
1515
from pip._internal.req import RequirementSet
16-
from pip._internal.req.req_tracker import RequirementTracker
16+
from pip._internal.req.req_tracker import get_requirement_tracker
1717
from pip._internal.utils.temp_dir import TempDirectory
1818
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
1919
from pip._internal.wheel_builder import WheelBuilder
@@ -157,7 +157,7 @@ def run(self, options, args):
157157
build_delete = (not (options.no_clean or options.build_dir))
158158
wheel_cache = WheelCache(options.cache_dir, options.format_control)
159159

160-
with RequirementTracker() as req_tracker, TempDirectory(
160+
with get_requirement_tracker() as req_tracker, TempDirectory(
161161
options.build_dir, delete=build_delete, kind="wheel"
162162
) as directory:
163163

src/pip/_internal/req/req_tracker.py

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,34 +9,74 @@
99
import logging
1010
import os
1111

12+
from pip._vendor import contextlib2
13+
1214
from pip._internal.utils.temp_dir import TempDirectory
1315
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
1416

1517
if MYPY_CHECK_RUNNING:
1618
from types import TracebackType
17-
from typing import Iterator, Optional, Set, Type
19+
from typing import Dict, Iterator, Optional, Set, Type, Union
1820
from pip._internal.req.req_install import InstallRequirement
1921
from pip._internal.models.link import Link
2022

2123
logger = logging.getLogger(__name__)
2224

2325

26+
@contextlib.contextmanager
27+
def update_env_context_manager(**changes):
28+
# type: (str) -> Iterator[None]
29+
target = os.environ
30+
31+
# Save values from the target and change them.
32+
non_existent_marker = object()
33+
saved_values = {} # type: Dict[str, Union[object, str]]
34+
for name, new_value in changes.items():
35+
try:
36+
saved_values[name] = target[name]
37+
except KeyError:
38+
saved_values[name] = non_existent_marker
39+
target[name] = new_value
40+
41+
try:
42+
yield
43+
finally:
44+
# Restore original values in the target.
45+
for name, original_value in saved_values.items():
46+
if original_value is non_existent_marker:
47+
del target[name]
48+
else:
49+
assert isinstance(original_value, str) # for mypy
50+
target[name] = original_value
51+
52+
53+
@contextlib.contextmanager
54+
def get_requirement_tracker():
55+
# type: () -> Iterator[RequirementTracker]
56+
root = os.environ.get('PIP_REQ_TRACKER')
57+
with contextlib2.ExitStack() as ctx:
58+
if root is None:
59+
root = ctx.enter_context(
60+
TempDirectory(kind='req-tracker')
61+
).path
62+
ctx.enter_context(update_env_context_manager(PIP_REQ_TRACKER=root))
63+
logger.debug("Initialized build tracking at %s", root)
64+
65+
with RequirementTracker(root) as tracker:
66+
yield tracker
67+
68+
2469
class RequirementTracker(object):
2570

26-
def __init__(self):
27-
# type: () -> None
28-
self._root = os.environ.get('PIP_REQ_TRACKER')
29-
if self._root is None:
30-
self._temp_dir = TempDirectory(delete=False, kind='req-tracker')
31-
self._root = os.environ['PIP_REQ_TRACKER'] = self._temp_dir.path
32-
logger.debug('Created requirements tracker %r', self._root)
33-
else:
34-
self._temp_dir = None
35-
logger.debug('Re-using requirements tracker %r', self._root)
71+
def __init__(self, root):
72+
# type: (str) -> None
73+
self._root = root
3674
self._entries = set() # type: Set[InstallRequirement]
75+
logger.debug("Created build tracker: %s", self._root)
3776

3877
def __enter__(self):
3978
# type: () -> RequirementTracker
79+
logger.debug("Entered build tracker: %s", self._root)
4080
return self
4181

4282
def __exit__(
@@ -100,13 +140,6 @@ def cleanup(self):
100140
for req in set(self._entries):
101141
self.remove(req)
102142

103-
if self._temp_dir is None:
104-
# Did not setup the directory. No action needed.
105-
logger.debug("Cleaned build tracker: %r", self._root)
106-
return
107-
108-
# Cleanup the directory.
109-
self._temp_dir.cleanup()
110143
logger.debug("Removed build tracker: %r", self._root)
111144

112145
@contextlib.contextmanager

0 commit comments

Comments
 (0)