141 lines
4.5 KiB
Python
141 lines
4.5 KiB
Python
import os.path
|
|
import pathlib
|
|
|
|
import pytest
|
|
from conftest import check_symlink_impl
|
|
|
|
import click
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("type", "value", "expect"),
|
|
[
|
|
(click.IntRange(0, 5), "3", 3),
|
|
(click.IntRange(5), "5", 5),
|
|
(click.IntRange(5), "100", 100),
|
|
(click.IntRange(max=5), "5", 5),
|
|
(click.IntRange(max=5), "-100", -100),
|
|
(click.IntRange(0, clamp=True), "-1", 0),
|
|
(click.IntRange(max=5, clamp=True), "6", 5),
|
|
(click.IntRange(0, min_open=True, clamp=True), "0", 1),
|
|
(click.IntRange(max=5, max_open=True, clamp=True), "5", 4),
|
|
(click.FloatRange(0.5, 1.5), "1.2", 1.2),
|
|
(click.FloatRange(0.5, min_open=True), "0.51", 0.51),
|
|
(click.FloatRange(max=1.5, max_open=True), "1.49", 1.49),
|
|
(click.FloatRange(0.5, clamp=True), "-0.0", 0.5),
|
|
(click.FloatRange(max=1.5, clamp=True), "inf", 1.5),
|
|
],
|
|
)
|
|
def test_range(type, value, expect):
|
|
assert type.convert(value, None, None) == expect
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("type", "value", "expect"),
|
|
[
|
|
(click.IntRange(0, 5), "6", "6 is not in the range 0<=x<=5."),
|
|
(click.IntRange(5), "4", "4 is not in the range x>=5."),
|
|
(click.IntRange(max=5), "6", "6 is not in the range x<=5."),
|
|
(click.IntRange(0, 5, min_open=True), 0, "0<x<=5"),
|
|
(click.IntRange(0, 5, max_open=True), 5, "0<=x<5"),
|
|
(click.FloatRange(0.5, min_open=True), 0.5, "x>0.5"),
|
|
(click.FloatRange(max=1.5, max_open=True), 1.5, "x<1.5"),
|
|
],
|
|
)
|
|
def test_range_fail(type, value, expect):
|
|
with pytest.raises(click.BadParameter) as exc_info:
|
|
type.convert(value, None, None)
|
|
|
|
assert expect in exc_info.value.message
|
|
|
|
|
|
def test_float_range_no_clamp_open():
|
|
with pytest.raises(TypeError):
|
|
click.FloatRange(0, 1, max_open=True, clamp=True)
|
|
|
|
sneaky = click.FloatRange(0, 1, max_open=True)
|
|
sneaky.clamp = True
|
|
|
|
with pytest.raises(RuntimeError):
|
|
sneaky.convert("1.5", None, None)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("nargs", "multiple", "default", "expect"),
|
|
[
|
|
(2, False, None, None),
|
|
(2, False, (None, None), (None, None)),
|
|
(None, True, None, ()),
|
|
(None, True, (None, None), (None, None)),
|
|
(2, True, None, ()),
|
|
(2, True, [(None, None)], ((None, None),)),
|
|
(-1, None, None, ()),
|
|
],
|
|
)
|
|
def test_cast_multi_default(runner, nargs, multiple, default, expect):
|
|
if nargs == -1:
|
|
param = click.Argument(["a"], nargs=nargs, default=default)
|
|
else:
|
|
param = click.Option(["-a"], nargs=nargs, multiple=multiple, default=default)
|
|
|
|
cli = click.Command("cli", params=[param], callback=lambda a: a)
|
|
result = runner.invoke(cli, standalone_mode=False)
|
|
assert result.exception is None
|
|
assert result.return_value == expect
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("cls", "expect"),
|
|
[
|
|
(None, "a/b/c.txt"),
|
|
(str, "a/b/c.txt"),
|
|
(bytes, b"a/b/c.txt"),
|
|
(pathlib.Path, pathlib.Path("a", "b", "c.txt")),
|
|
],
|
|
)
|
|
def test_path_type(runner, cls, expect):
|
|
cli = click.Command(
|
|
"cli",
|
|
params=[click.Argument(["p"], type=click.Path(path_type=cls))],
|
|
callback=lambda p: p,
|
|
)
|
|
result = runner.invoke(cli, ["a/b/c.txt"], standalone_mode=False)
|
|
assert result.exception is None
|
|
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),
|
|
],
|
|
)
|
|
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)
|
|
|
|
# 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)
|
|
|
|
# test
|
|
ctx = click.Context(click.Command("do_stuff"))
|
|
rv = click.Path(resolve_path=True).convert(sym_path, None, ctx)
|
|
|
|
# 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)
|
|
|
|
assert rv == real_path
|