def test_iter_candidates_empty_paths(self, test_interpreter1): # type: (str) -> None # Whereas `paths=None` should inspect $PATH, `paths=[]` means to search nothing. with environment_as(PATH=test_interpreter1): assert [] == list(PythonInterpreter.iter_candidates(paths=[])) assert [PythonInterpreter.from_binary(test_interpreter1) ] == list(PythonInterpreter.iter_candidates(paths=None))
def test_iter_interpreter_errors(self, invalid_interpreter): # type: (str) -> None results = list( PythonInterpreter.iter_candidates(paths=[invalid_interpreter])) assert len(results) == 1 self.assert_error(results[0], invalid_interpreter)
def _iter_interpreters(): # type: () -> Iterator[InterpreterOrError] seen = set() normalized_paths = (OrderedSet( PythonInterpreter.canonicalize_path(p) for p in path.split(os.pathsep)) if path else None) # Prefer the current interpreter, if valid. current_interpreter = preferred_interpreter or PythonInterpreter.get() if not _valid_path or _valid_path(current_interpreter.binary): if normalized_paths: candidate_paths = frozenset( (current_interpreter.binary, os.path.dirname(current_interpreter.binary))) candidate_paths_in_path = candidate_paths.intersection( normalized_paths) if candidate_paths_in_path: # In case the full path of the current interpreter binary was in the # `normalized_paths` we're searching, remove it to prevent identifying it again # just to then skip it as `seen`. normalized_paths.discard(current_interpreter.binary) seen.add(current_interpreter) yield current_interpreter else: seen.add(current_interpreter) yield current_interpreter for interp in PythonInterpreter.iter_candidates( paths=normalized_paths, path_filter=_valid_path): if interp not in seen: seen.add(interp) yield interp
def _iter_interpreters(): # type: () -> Iterator[InterpreterOrError] seen = set() normalized_paths = (OrderedSet( os.path.realpath(p) for p in path.split(os.pathsep)) if path else None) # Prefer the current interpreter, if valid. current_interpreter = PythonInterpreter.get() if not _valid_path or _valid_path(current_interpreter.binary): if normalized_paths: candidate_paths = frozenset( (current_interpreter.binary, os.path.dirname(current_interpreter.binary))) candidate_paths_in_path = candidate_paths.intersection( normalized_paths) if candidate_paths_in_path: for p in candidate_paths_in_path: normalized_paths.remove(p) seen.add(current_interpreter) yield current_interpreter else: seen.add(current_interpreter) yield current_interpreter for interp in PythonInterpreter.iter_candidates( paths=normalized_paths, path_filter=_valid_path): if interp not in seen: seen.add(interp) yield interp
def _iter_interpreters(): seen = set() paths = None current_interpreter = PythonInterpreter.get() if path: paths = OrderedSet(os.path.realpath(p) for p in path.split(os.pathsep)) # Prefer the current interpreter if present on the `path`. candidate_paths = frozenset( (current_interpreter.binary, os.path.dirname(current_interpreter.binary)) ) candidate_paths_in_path = candidate_paths.intersection(paths) if candidate_paths_in_path: for p in candidate_paths_in_path: paths.remove(p) seen.add(current_interpreter) yield current_interpreter else: # We may have been invoked with a specific interpreter, make sure our sys.executable is # included as a candidate in this case. seen.add(current_interpreter) yield current_interpreter for interp in PythonInterpreter.iter_candidates(paths=paths): if interp not in seen: seen.add(interp) yield interp
def test_iter_interpreter_path_filter(self, test_interpreter1, test_interpreter2): # type: (str, str) -> None assert [PythonInterpreter.from_binary(test_interpreter2)] == list( PythonInterpreter.iter_candidates( paths=[test_interpreter1, test_interpreter2], path_filter=lambda path: path == test_interpreter2, ))
def test_iter_interpreter_some(self, test_interpreter1, test_interpreter2): # type: (str, str) -> None assert [ PythonInterpreter.from_binary(test_interpreter1), PythonInterpreter.from_binary(test_interpreter2), ] == list( PythonInterpreter.iter_candidates( paths=[test_interpreter1, test_interpreter2]))
def test_iter_interpreter_path_filter_symlink(self, test_interpreter1, test_interpreter2): # type: (str, str) -> None with temporary_dir() as bin_dir: os.symlink(test_interpreter2, os.path.join(bin_dir, "jake")) # Verify path filtering happens before interpreter resolution, which os.path.realpaths # the interpreter binary. This supports specifying a path filter like # "basename is python2" where discovered interpreter binaries are symlinks to more # specific interpreter versions, e.g.: /usr/bin/python2 -> /usr/bin/python2.7. expected_interpreter = PythonInterpreter.from_binary(test_interpreter2) assert [expected_interpreter] == list( PythonInterpreter.iter_candidates( paths=[test_interpreter1, bin_dir], path_filter=lambda path: os.path.basename(path) == "jake", ) ) assert os.path.basename(expected_interpreter.binary) != "jake"
def test_iter_interpreter_mixed( self, test_interpreter1, test_interpreter2, invalid_interpreter ): # type: (str, str, str) -> None results = list( PythonInterpreter.iter_candidates( paths=[test_interpreter1, invalid_interpreter, test_interpreter2] ) ) assert len(results) == 3 assert [ PythonInterpreter.from_binary(path) for path in (test_interpreter1, test_interpreter2) ] == [result for result in results if isinstance(result, PythonInterpreter)] errors = [result for result in results if not isinstance(result, PythonInterpreter)] assert len(errors) == 1 self.assert_error(errors[0], invalid_interpreter)
def test_iter_interpreter_none(self): # type: () -> None assert [] == list( PythonInterpreter.iter_candidates(paths=[os.devnull]))