Finds the base system interpreter used to create a virtual environment. If this interpreter is not homed in a virtual environment, returns itself.
(self)
| 1461 | """Indicates the base interpreter for a virtual environment could not be resolved.""" |
| 1462 | |
| 1463 | def resolve_base_interpreter(self): |
| 1464 | # type: () -> PythonInterpreter |
| 1465 | """Finds the base system interpreter used to create a virtual environment. |
| 1466 | |
| 1467 | If this interpreter is not homed in a virtual environment, returns itself. |
| 1468 | """ |
| 1469 | if not self.is_venv: |
| 1470 | return self |
| 1471 | |
| 1472 | # In the case of PyPy, the <base_prefix> dir might contain one of the following: |
| 1473 | # |
| 1474 | # 1. On a system with PyPy 2.7 series and one PyPy 3.x series |
| 1475 | # bin/ |
| 1476 | # pypy |
| 1477 | # pypy3 |
| 1478 | # |
| 1479 | # 2. On a system with PyPy 2.7 series and more than one PyPy 3.x series |
| 1480 | # bin/ |
| 1481 | # pypy |
| 1482 | # pypy3 |
| 1483 | # pypy3.6 |
| 1484 | # pypy3.7 |
| 1485 | # |
| 1486 | # In both cases, bin/pypy is a 2.7 series interpreter. In case 2 bin/pypy3 could be either |
| 1487 | # PyPy 3.6 series or PyPy 3.7 series. In order to ensure we pick the correct base executable |
| 1488 | # of a PyPy virtual environment, we always try to resolve the most specific basename first |
| 1489 | # to the least specific basename last and we also verify that, if the basename resolves, it |
| 1490 | # resolves to an equivalent interpreter. We employ the same strategy for CPython, but only |
| 1491 | # for uniformity in the algorithm. It appears to always be the case for CPython that |
| 1492 | # python<major>.<minor> is present in any given <prefix>/bin/ directory; so the algorithm |
| 1493 | # gets a hit on 1st try for CPython binaries incurring ~no extra overhead. |
| 1494 | |
| 1495 | implementation = self._identity.implementation |
| 1496 | version = self._identity.version |
| 1497 | abi_tag = self._identity.abi_tag |
| 1498 | |
| 1499 | versions = version[:2], version[:1], None |
| 1500 | candidate_binaries = tuple( |
| 1501 | script_name(implementation.calculate_binary_name(version)) for version in versions |
| 1502 | ) |
| 1503 | |
| 1504 | def iter_base_candidate_binary_paths(interpreter): |
| 1505 | # type: (PythonInterpreter) -> Iterator[str] |
| 1506 | bin_dir = ( |
| 1507 | interpreter._identity.base_prefix |
| 1508 | if WINDOWS |
| 1509 | else os.path.join(interpreter._identity.base_prefix, SCRIPT_DIR) |
| 1510 | ) |
| 1511 | for candidate_binary in candidate_binaries: |
| 1512 | candidate_binary_path = os.path.join(bin_dir, candidate_binary) |
| 1513 | if is_exe(candidate_binary_path): |
| 1514 | yield candidate_binary_path |
| 1515 | |
| 1516 | resolution_path = [] # type: List[str] |
| 1517 | base_interpreter = self |
| 1518 | while base_interpreter.is_venv: |
| 1519 | resolved = None # type: Optional[PythonInterpreter] |
| 1520 | maybe_reinstalled_interpreters = [] # type: List[PythonInterpreter] |