def do_use( project: Project, python: Optional[str] = "", first: Optional[bool] = False ) -> None: """Use the specified python version and save in project config. The python can be a version string or interpreter path. """ def version_matcher(py_version: PythonInfo) -> bool: return project.python_requires.contains(str(py_version.version)) python = python.strip() found_interpreters = list( dict.fromkeys(filter(version_matcher, project.find_interpreters(python))) ) if not found_interpreters: raise NoPythonVersion("Python interpreter is not found on the system.") if first or len(found_interpreters) == 1: selected_python = found_interpreters[0] else: project.core.ui.echo("Please enter the Python interpreter to use") for i, py_version in enumerate(found_interpreters): project.core.ui.echo( f"{i}. {termui.green(py_version.executable)} ({py_version.identifier})" ) selection = click.prompt( "Please select:", type=click.Choice([str(i) for i in range(len(found_interpreters))]), default="0", show_choices=False, ) selected_python = found_interpreters[int(selection)] old_path = project.config.get("python.path") new_path = selected_python.executable project.core.ui.echo( "Using Python interpreter: {} ({})".format( termui.green(str(new_path)), selected_python.identifier, ) ) project.python = selected_python if old_path and Path(old_path) != Path(new_path) and not project.is_global: project.core.ui.echo(termui.cyan("Updating executable scripts...")) project.environment.update_shebangs(new_path)
def do_use( project: Project, python: str = "", first: bool = False, ignore_remembered: bool = False, ) -> None: """Use the specified python version and save in project config. The python can be a version string or interpreter path. """ if python: python = python.strip() def version_matcher(py_version: PythonInfo) -> bool: return project.python_requires.contains(str(py_version.version), True) if not project.cache_dir.exists(): project.cache_dir.mkdir(parents=True) use_cache: JSONFileCache[str, str] = JSONFileCache( project.cache_dir / "use_cache.json" ) selected_python: PythonInfo | None = None if python and not ignore_remembered: if use_cache.has_key(python): path = use_cache.get(python) cached_python = PythonInfo.from_path(path) if not cached_python.valid: project.core.ui.echo( f"The last selection is corrupted. {path!r}", fg="red", err=True, ) elif version_matcher(cached_python): project.core.ui.echo( "Using the last selection, add '-i' to ignore it.", fg="yellow", err=True, ) selected_python = cached_python if selected_python is None: found_interpreters = list(dict.fromkeys(project.find_interpreters(python))) matching_interperters = list(filter(version_matcher, found_interpreters)) if not found_interpreters: raise NoPythonVersion("Python interpreter is not found on the system.") if not matching_interperters: project.core.ui.echo("Interpreters found but not matching:", err=True) for py in found_interpreters: project.core.ui.echo(f" - {py.executable} ({py.identifier})", err=True) raise NoPythonVersion( "No python is found meeting the requirement " f"{termui.green('python' + str(project.python_requires))}" ) if first or len(matching_interperters) == 1: selected_python = matching_interperters[0] else: project.core.ui.echo("Please enter the Python interpreter to use") for i, py_version in enumerate(matching_interperters): project.core.ui.echo( f"{i}. {termui.green(str(py_version.executable))} " f"({py_version.identifier})" ) selection = click.prompt( "Please select:", type=click.Choice([str(i) for i in range(len(matching_interperters))]), default="0", show_choices=False, ) selected_python = matching_interperters[int(selection)] if python: use_cache.set(python, selected_python.path.as_posix()) if not selected_python.valid: path = str(selected_python.executable) raise InvalidPyVersion(f"Invalid Python interpreter: {path}") old_python = project.python if "python.path" in project.config else None project.core.ui.echo( "Using Python interpreter: {} ({})".format( termui.green(str(selected_python.executable)), selected_python.identifier, ) ) project.python = selected_python if ( old_python and old_python.path != selected_python.path and not project.environment.is_global ): project.core.ui.echo(termui.cyan("Updating executable scripts...")) project.environment.update_shebangs(selected_python.executable.as_posix())