New upstream version 8.0.3
This commit is contained in:
parent
46bc5bd117
commit
4555a76448
13
CHANGES.rst
13
CHANGES.rst
|
@ -1,5 +1,18 @@
|
|||
.. currentmodule:: click
|
||||
|
||||
Version 8.0.3
|
||||
-------------
|
||||
|
||||
Released 2021-10-10
|
||||
|
||||
- Fix issue with ``Path(resolve_path=True)`` type creating invalid
|
||||
paths. :issue:`2088`
|
||||
- Importing ``readline`` does not cause the ``confirm()`` prompt to
|
||||
disappear when pressing backspace. :issue:`2092`
|
||||
- Any default values injected by ``invoke()`` are cast to the
|
||||
corresponding parameter's type. :issue:`2089, 2090`
|
||||
|
||||
|
||||
Version 8.0.2
|
||||
-------------
|
||||
|
||||
|
|
|
@ -72,4 +72,4 @@ from .utils import get_os_args as get_os_args
|
|||
from .utils import get_text_stream as get_text_stream
|
||||
from .utils import open_file as open_file
|
||||
|
||||
__version__ = "8.0.2"
|
||||
__version__ = "8.0.3"
|
||||
|
|
|
@ -739,7 +739,9 @@ class Context:
|
|||
|
||||
for param in other_cmd.params:
|
||||
if param.name not in kwargs and param.expose_value:
|
||||
kwargs[param.name] = param.get_default(ctx) # type: ignore
|
||||
kwargs[param.name] = param.type_cast_value( # type: ignore
|
||||
ctx, param.get_default(ctx)
|
||||
)
|
||||
|
||||
# Track all kwargs as params, so that forward() will pass
|
||||
# them on in subsequent calls.
|
||||
|
|
|
@ -231,8 +231,10 @@ def confirm(
|
|||
try:
|
||||
# Write the prompt separately so that we get nice
|
||||
# coloring through colorama on Windows
|
||||
echo(prompt, nl=False, err=err)
|
||||
value = visible_prompt_func("").lower().strip()
|
||||
echo(prompt.rstrip(" "), nl=False, err=err)
|
||||
# Echo a space to stdout to work around an issue where
|
||||
# readline causes backspace to clear the whole line.
|
||||
value = visible_prompt_func(" ").lower().strip()
|
||||
except (KeyboardInterrupt, EOFError):
|
||||
raise Abort() from None
|
||||
if value in ("y", "yes"):
|
||||
|
|
|
@ -836,20 +836,11 @@ class Path(ParamType):
|
|||
|
||||
if not is_dash:
|
||||
if self.resolve_path:
|
||||
# Get the absolute directory containing the path.
|
||||
dir_ = os.path.dirname(os.path.abspath(rv))
|
||||
# os.path.realpath doesn't resolve symlinks on Windows
|
||||
# until Python 3.8. Use pathlib for now.
|
||||
import pathlib
|
||||
|
||||
# Resolve a symlink. realpath on Windows Python < 3.9
|
||||
# doesn't resolve symlinks. This might return a relative
|
||||
# path even if the path to the link is absolute.
|
||||
if os.path.islink(rv):
|
||||
rv = os.readlink(rv)
|
||||
|
||||
# Join dir_ with the resolved symlink if the resolved
|
||||
# path is relative. This will make it relative to the
|
||||
# original containing directory.
|
||||
if not os.path.isabs(rv):
|
||||
rv = os.path.join(dir_, rv)
|
||||
rv = os.fsdecode(pathlib.Path(rv).resolve())
|
||||
|
||||
try:
|
||||
st = os.stat(rv)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
import pytest
|
||||
|
@ -12,20 +11,17 @@ def runner(request):
|
|||
return CliRunner()
|
||||
|
||||
|
||||
def check_symlink_impl():
|
||||
"""This function checks if using symlinks is allowed
|
||||
on the host machine"""
|
||||
tempdir = tempfile.mkdtemp(prefix="click-")
|
||||
test_pth = os.path.join(tempdir, "check_sym_impl")
|
||||
sym_pth = os.path.join(tempdir, "link")
|
||||
open(test_pth, "w").close()
|
||||
rv = True
|
||||
try:
|
||||
os.symlink(test_pth, sym_pth)
|
||||
except (NotImplementedError, OSError):
|
||||
# Creating symlinks on Windows require elevated access.
|
||||
# OSError is thrown if the function is called without it.
|
||||
rv = False
|
||||
finally:
|
||||
shutil.rmtree(tempdir, ignore_errors=True)
|
||||
return rv
|
||||
def _check_symlinks_supported():
|
||||
with tempfile.TemporaryDirectory(prefix="click-pytest-") as tempdir:
|
||||
target = os.path.join(tempdir, "target")
|
||||
open(target, "w").close()
|
||||
link = os.path.join(tempdir, "link")
|
||||
|
||||
try:
|
||||
os.symlink(target, link)
|
||||
return True
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
|
||||
symlinks_supported = _check_symlinks_supported()
|
||||
|
|
|
@ -246,15 +246,17 @@ def test_other_command_invoke_with_defaults(runner):
|
|||
return ctx.invoke(other_cmd)
|
||||
|
||||
@click.command()
|
||||
@click.option("--foo", type=click.INT, default=42)
|
||||
@click.option("-a", type=click.INT, default=42)
|
||||
@click.option("-b", type=click.INT, default="15")
|
||||
@click.option("-c", multiple=True)
|
||||
@click.pass_context
|
||||
def other_cmd(ctx, foo):
|
||||
assert ctx.info_name == "other-cmd"
|
||||
click.echo(foo)
|
||||
def other_cmd(ctx, a, b, c):
|
||||
return ctx.info_name, a, b, c
|
||||
|
||||
result = runner.invoke(cli, [])
|
||||
assert not result.exception
|
||||
assert result.output == "42\n"
|
||||
result = runner.invoke(cli, standalone_mode=False)
|
||||
# invoke should type cast default values, str becomes int, empty
|
||||
# multiple should be empty tuple instead of None
|
||||
assert result.return_value == ("other-cmd", 42, 15, ())
|
||||
|
||||
|
||||
def test_invoked_subcommand(runner):
|
||||
|
|
|
@ -2,7 +2,7 @@ import os.path
|
|||
import pathlib
|
||||
|
||||
import pytest
|
||||
from conftest import check_symlink_impl
|
||||
from conftest import symlinks_supported
|
||||
|
||||
import click
|
||||
|
||||
|
@ -104,37 +104,27 @@ def test_path_type(runner, cls, expect):
|
|||
assert result.return_value == expect
|
||||
|
||||
|
||||
@pytest.mark.skipif(not check_symlink_impl(), reason="symlink not allowed on device")
|
||||
@pytest.mark.parametrize(
|
||||
("sym_file", "abs_fun"),
|
||||
[
|
||||
(("relative_symlink",), os.path.basename),
|
||||
(("test", "absolute_symlink"), lambda x: x),
|
||||
],
|
||||
@pytest.mark.skipif(
|
||||
not symlinks_supported, reason="The current OS or FS doesn't support symlinks."
|
||||
)
|
||||
def test_symlink_resolution(tmpdir, sym_file, abs_fun):
|
||||
"""This test ensures symlinks are properly resolved by click"""
|
||||
tempdir = str(tmpdir)
|
||||
real_path = os.path.join(tempdir, "test_file")
|
||||
sym_path = os.path.join(tempdir, *sym_file)
|
||||
def test_path_resolve_symlink(tmp_path, runner):
|
||||
test_file = tmp_path / "file"
|
||||
test_file_str = os.fsdecode(test_file)
|
||||
test_file.write_text("")
|
||||
|
||||
# create dirs and files
|
||||
os.makedirs(os.path.join(tempdir, "test"), exist_ok=True)
|
||||
open(real_path, "w").close()
|
||||
os.symlink(abs_fun(real_path), sym_path)
|
||||
path_type = click.Path(resolve_path=True)
|
||||
param = click.Argument(["a"], type=path_type)
|
||||
ctx = click.Context(click.Command("cli", params=[param]))
|
||||
|
||||
# test
|
||||
ctx = click.Context(click.Command("do_stuff"))
|
||||
rv = click.Path(resolve_path=True).convert(sym_path, None, ctx)
|
||||
test_dir = tmp_path / "dir"
|
||||
test_dir.mkdir()
|
||||
|
||||
# os.readlink prepends path prefixes to absolute
|
||||
# links in windows.
|
||||
# https://docs.microsoft.com/en-us/windows/win32/
|
||||
# ... fileio/naming-a-file#win32-file-namespaces
|
||||
#
|
||||
# Here we strip win32 path prefix from the resolved path
|
||||
rv_drive, rv_path = os.path.splitdrive(rv)
|
||||
stripped_rv_drive = rv_drive.split(os.path.sep)[-1]
|
||||
rv = os.path.join(stripped_rv_drive, rv_path)
|
||||
abs_link = test_dir / "abs"
|
||||
abs_link.symlink_to(test_file)
|
||||
abs_rv = path_type.convert(os.fsdecode(abs_link), param, ctx)
|
||||
assert abs_rv == test_file_str
|
||||
|
||||
assert rv == real_path
|
||||
rel_link = test_dir / "rel"
|
||||
rel_link.symlink_to(pathlib.Path("..") / "file")
|
||||
rel_rv = path_type.convert(os.fsdecode(rel_link), param, ctx)
|
||||
assert rel_rv == test_file_str
|
||||
|
|
|
@ -275,8 +275,8 @@ def test_echo_writing_to_standard_error(capfd, monkeypatch):
|
|||
emulate_input("y\n")
|
||||
click.confirm("Prompt to stderr", err=True)
|
||||
out, err = capfd.readouterr()
|
||||
assert out == ""
|
||||
assert err == "Prompt to stderr [y/N]: "
|
||||
assert out == " "
|
||||
assert err == "Prompt to stderr [y/N]:"
|
||||
|
||||
monkeypatch.setattr(click.termui, "isatty", lambda x: True)
|
||||
monkeypatch.setattr(click.termui, "getchar", lambda: " ")
|
||||
|
|
Loading…
Reference in a new issue