Example #1
0
 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))
Example #2
0
    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)
Example #3
0
    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
Example #4
0
    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
Example #5
0
    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
Example #6
0
 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,
         ))
Example #7
0
 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]))
Example #8
0
    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"
Example #9
0
    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)
Example #10
0
 def test_iter_interpreter_none(self):
     # type: () -> None
     assert [] == list(
         PythonInterpreter.iter_candidates(paths=[os.devnull]))