|
9 | 9 | import logging
|
10 | 10 | import os
|
11 | 11 |
|
| 12 | +from pip._vendor import contextlib2 |
| 13 | + |
12 | 14 | from pip._internal.utils.temp_dir import TempDirectory
|
13 | 15 | from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
14 | 16 |
|
15 | 17 | if MYPY_CHECK_RUNNING:
|
16 | 18 | from types import TracebackType
|
17 |
| - from typing import Iterator, Optional, Set, Type |
| 19 | + from typing import Dict, Iterator, Optional, Set, Type, Union |
18 | 20 | from pip._internal.req.req_install import InstallRequirement
|
19 | 21 | from pip._internal.models.link import Link
|
20 | 22 |
|
21 | 23 | logger = logging.getLogger(__name__)
|
22 | 24 |
|
23 | 25 |
|
| 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 | + |
24 | 69 | class RequirementTracker(object):
|
25 | 70 |
|
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 |
36 | 74 | self._entries = set() # type: Set[InstallRequirement]
|
| 75 | + logger.debug("Created build tracker: %s", self._root) |
37 | 76 |
|
38 | 77 | def __enter__(self):
|
39 | 78 | # type: () -> RequirementTracker
|
| 79 | + logger.debug("Entered build tracker: %s", self._root) |
40 | 80 | return self
|
41 | 81 |
|
42 | 82 | def __exit__(
|
@@ -100,13 +140,6 @@ def cleanup(self):
|
100 | 140 | for req in set(self._entries):
|
101 | 141 | self.remove(req)
|
102 | 142 |
|
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() |
110 | 143 | logger.debug("Removed build tracker: %r", self._root)
|
111 | 144 |
|
112 | 145 | @contextlib.contextmanager
|
|
0 commit comments