def test_find_python_in_path(tmp_path): assert (cli_utils.find_python_in_path(sys.executable) == pathlib.Path( sys.executable).as_posix()) assert (cli_utils.find_python_in_path(sys.prefix).lower().startswith( pathlib.Path(sys.executable).as_posix().lower())) with pytest.raises(PdmException): cli_utils.find_python_in_path(tmp_path)
def do_use(project: Project, python: str, first: bool = False) -> None: """Use the specified python version and save in project config. The python can be a version string or interpreter path. """ import pythonfinder python = python.strip() if python and not all(c.isdigit() for c in python.split(".")): if Path(python).exists(): python_path = find_python_in_path(python) else: python_path = shutil.which(python) if not python_path: raise NoPythonVersion(f"{python} is not a valid Python.") python_version, is_64bit = get_python_version(python_path, True) else: finder = pythonfinder.Finder() pythons = [] args = [int(v) for v in python.split(".") if v != ""] for i, entry in enumerate(finder.find_all_python_versions(*args)): python_version, is_64bit = get_python_version(entry.path.as_posix(), True) pythons.append((entry.path.as_posix(), python_version, is_64bit)) if not pythons: raise NoPythonVersion(f"Python {python} is not available on the system.") if not first and len(pythons) > 1: for i, (path, python_version, is_64bit) in enumerate(pythons): stream.echo( f"{i}. {stream.green(path)} " f"({get_python_version_string(python_version, is_64bit)})" ) selection = click.prompt( "Please select:", type=click.Choice([str(i) for i in range(len(pythons))]), default="0", show_choices=False, ) else: selection = 0 python_path, python_version, is_64bit = pythons[int(selection)] if not project.python_requires.contains(python_version): raise NoPythonVersion( "The target Python version {} doesn't satisfy " "the Python requirement: {}".format(python_version, project.python_requires) ) stream.echo( "Using Python interpreter: {} ({})".format( stream.green(python_path), get_python_version_string(python_version, is_64bit), ) ) old_path = project.config.get("python.path") new_path = python_path project.project_config["python.path"] = Path(new_path).as_posix() if old_path and Path(old_path) != Path(new_path) and not project.is_global: stream.echo(stream.cyan("Updating executable scripts...")) project.environment.update_shebangs(new_path)