未验证 提交 264102b4 编写于 作者: F Frost Ming

better python selector

上级 ec7fd6a8
Improve the user interface of selecting Python interpreter.
......@@ -443,22 +443,41 @@ def do_init(
project.write_pyproject()
def do_use(project: Project, python: str) -> None:
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.
"""
if Path(python).is_absolute():
python_path = python
else:
python_path = shutil.which(python)
if not all(c.isdigit() for c in python.split(".")):
if Path(python).exists():
python_path = Path(python).absolute().as_posix()
else:
python_path = shutil.which(python)
if not python_path:
finder = pythonfinder.Finder()
try:
python_path = finder.find_python_version(python).path.as_posix()
except AttributeError:
raise NoPythonVersion(f"Python {python} is not found on the system.")
raise NoPythonVersion(f"{python} is not a valid Python.")
python_version = get_python_version(python_path, True)
else:
finder = pythonfinder.Finder()
pythons = []
args = [int(v) for v in python.split(".")]
for i, entry in enumerate(finder.find_all_python_versions(*args)):
python_version = get_python_version(entry.path.as_posix(), True)
pythons.append((entry.path.as_posix(), python_version))
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) in enumerate(pythons):
context.io.echo(f"{i}: {context.io.green(path)} ({python_version})")
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 = pythons[int(selection)]
python_version = get_python_version(python_path, True)
if not project.python_requires.contains(python_version):
raise NoPythonVersion(
"The target Python version {} doesn't satisfy "
......
......@@ -285,17 +285,12 @@ def build(project, sdist, wheel, dest, clean):
@cli.command()
@verbose_option
@click.option(
"-p",
"--python",
help="Specify the Python interperter version or path to use.",
metavar="PYTHON",
)
@pass_project
def init(project, python):
def init(project):
"""Initialize a pyproject.toml for PDM."""
if python:
actions.do_use(project, python)
python = click.prompt("Please enter the Python interpreter to use")
actions.do_use(project, python)
if project.pyproject_file.exists():
context.io.echo(
"{}".format(
......@@ -324,11 +319,14 @@ def init(project, python):
@cli.command()
@click.option(
"-f", "--first", is_flag=True, help="Select the first matched interpreter."
)
@click.argument("python")
@pass_project
def use(project, python):
def use(project, first, python):
"""Use the given python version or path as base interpreter."""
actions.do_use(project, python)
actions.do_use(project, python, first)
@cli.command()
......
......@@ -116,12 +116,12 @@ def test_uncaught_error(invoke, mocker):
def test_use_command(project, invoke):
python_path = Path(shutil.which("python")).as_posix()
result = invoke(["use", "python"], obj=project)
result = invoke(["use", "-f", "python"], obj=project)
assert result.exit_code == 0
config_content = project.root.joinpath(".pdm.toml").read_text()
assert python_path in config_content
result = invoke(["use", python_path], obj=project)
result = invoke(["use", "-f", python_path], obj=project)
assert result.exit_code == 0
project.tool_settings["python_requires"] = ">=3.6"
......@@ -130,6 +130,12 @@ def test_use_command(project, invoke):
assert result.exit_code == 1
def test_use_python_by_version(project, invoke):
python_version = ".".join(map(str, sys.version_info[:2]))
result = invoke(["use", "-f", python_version], obj=project)
assert result.exit_code == 0
def test_install_with_lockfile(project, invoke, working_set, repository):
result = invoke(["lock"], obj=project)
assert result.exit_code == 0
......@@ -149,7 +155,10 @@ def test_init_command(project_no_init, invoke, mocker):
return_value=("Testing", "me@example.org"),
)
do_init = mocker.patch.object(actions, "do_init")
result = invoke(["init"], input="test-project\n\n\n\n\n\n", obj=project_no_init)
result = invoke(
["init"], input="python\ntest-project\n\n\n\n\n\n", obj=project_no_init
)
print(result.output)
assert result.exit_code == 0
python_version = ".".join(
map(str, get_python_version(project_no_init.environment.python_executable)[:2])
......@@ -163,27 +172,3 @@ def test_init_command(project_no_init, invoke, mocker):
"me@example.org",
f">={python_version}",
)
def test_init_command_python_option(project_no_init, invoke, mocker):
mocker.patch(
"pdm.cli.commands.get_user_email_from_git",
return_value=("Testing", "me@example.org"),
)
do_init = mocker.patch.object(actions, "do_init")
result = invoke(
["init", "--python", sys.executable],
input="test-project\n\n\n\n\n\n",
obj=project_no_init,
)
assert result.exit_code == 0
python_version = ".".join(map(str, sys.version_info[:2]))
do_init.assert_called_with(
project_no_init,
"test-project",
"0.0.0",
"MIT",
"Testing",
"me@example.org",
f">={python_version}",
)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册