2024-01-28 21:12:42 +08:00
|
|
|
# mypy: allow-untyped-defs
|
2017-12-27 11:47:26 +08:00
|
|
|
import argparse
|
2023-06-20 19:55:39 +08:00
|
|
|
import locale
|
2013-10-04 00:02:54 +08:00
|
|
|
import os
|
2021-03-14 03:22:54 +08:00
|
|
|
from pathlib import Path
|
2019-09-23 23:56:09 +08:00
|
|
|
import shlex
|
2020-07-20 22:24:39 +08:00
|
|
|
import subprocess
|
2018-10-25 15:01:29 +08:00
|
|
|
import sys
|
|
|
|
|
2018-06-05 16:20:36 +08:00
|
|
|
from _pytest.config import argparsing as parseopt
|
2019-01-18 05:06:45 +08:00
|
|
|
from _pytest.config.exceptions import UsageError
|
2020-12-01 06:27:39 +08:00
|
|
|
from _pytest.monkeypatch import MonkeyPatch
|
|
|
|
from _pytest.pytester import Pytester
|
2018-06-05 16:20:36 +08:00
|
|
|
import pytest
|
2009-02-27 18:18:27 +08:00
|
|
|
|
2017-07-17 07:25:09 +08:00
|
|
|
|
2013-08-01 22:21:33 +08:00
|
|
|
@pytest.fixture
|
2019-11-17 20:35:33 +08:00
|
|
|
def parser() -> parseopt.Parser:
|
2021-05-24 04:45:49 +08:00
|
|
|
return parseopt.Parser(_ispytest=True)
|
2013-08-01 22:21:33 +08:00
|
|
|
|
2017-07-17 07:25:09 +08:00
|
|
|
|
2017-02-17 02:41:51 +08:00
|
|
|
class TestParser:
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_no_help_by_default(self) -> None:
|
2021-05-24 04:45:49 +08:00
|
|
|
parser = parseopt.Parser(usage="xyz", _ispytest=True)
|
2019-01-18 05:06:45 +08:00
|
|
|
pytest.raises(UsageError, lambda: parser.parse(["-h"]))
|
2009-02-27 18:18:27 +08:00
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_custom_prog(self, parser: parseopt.Parser) -> None:
|
2018-12-11 11:54:54 +08:00
|
|
|
"""Custom prog can be set for `argparse.ArgumentParser`."""
|
|
|
|
assert parser._getparser().prog == os.path.basename(sys.argv[0])
|
|
|
|
parser.prog = "custom-prog"
|
|
|
|
assert parser._getparser().prog == "custom-prog"
|
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_argument(self) -> None:
|
2013-07-25 21:33:43 +08:00
|
|
|
with pytest.raises(parseopt.ArgumentError):
|
|
|
|
# need a short or long option
|
|
|
|
argument = parseopt.Argument()
|
|
|
|
argument = parseopt.Argument("-t")
|
|
|
|
assert argument._short_opts == ["-t"]
|
|
|
|
assert argument._long_opts == []
|
|
|
|
assert argument.dest == "t"
|
|
|
|
argument = parseopt.Argument("-t", "--test")
|
|
|
|
assert argument._short_opts == ["-t"]
|
|
|
|
assert argument._long_opts == ["--test"]
|
|
|
|
assert argument.dest == "test"
|
|
|
|
argument = parseopt.Argument("-t", "--test", dest="abc")
|
|
|
|
assert argument.dest == "abc"
|
2018-06-26 21:35:27 +08:00
|
|
|
assert str(argument) == (
|
|
|
|
"Argument(_short_opts: ['-t'], _long_opts: ['--test'], dest: 'abc')"
|
2016-06-23 03:59:56 +08:00
|
|
|
)
|
2013-07-25 21:33:43 +08:00
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_argument_type(self) -> None:
|
2017-03-21 09:01:22 +08:00
|
|
|
argument = parseopt.Argument("-t", dest="abc", type=int)
|
2013-07-25 21:33:43 +08:00
|
|
|
assert argument.type is int
|
2017-03-21 09:01:22 +08:00
|
|
|
argument = parseopt.Argument("-t", dest="abc", type=str)
|
2013-07-25 21:33:43 +08:00
|
|
|
assert argument.type is str
|
|
|
|
argument = parseopt.Argument("-t", dest="abc", type=float)
|
|
|
|
assert argument.type is float
|
2017-03-21 09:01:22 +08:00
|
|
|
argument = parseopt.Argument(
|
|
|
|
"-t", dest="abc", type=str, choices=["red", "blue"]
|
2013-07-25 21:33:43 +08:00
|
|
|
)
|
|
|
|
assert argument.type is str
|
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_argument_processopt(self) -> None:
|
2013-07-25 21:33:43 +08:00
|
|
|
argument = parseopt.Argument("-t", type=int)
|
|
|
|
argument.default = 42
|
|
|
|
argument.dest = "abc"
|
|
|
|
res = argument.attrs()
|
|
|
|
assert res["default"] == 42
|
|
|
|
assert res["dest"] == "abc"
|
2013-07-26 14:59:31 +08:00
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_group_add_and_get(self, parser: parseopt.Parser) -> None:
|
2010-10-14 00:41:53 +08:00
|
|
|
group = parser.getgroup("hello", description="desc")
|
2009-02-27 18:18:27 +08:00
|
|
|
assert group.name == "hello"
|
|
|
|
assert group.description == "desc"
|
2009-10-17 23:43:33 +08:00
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_getgroup_simple(self, parser: parseopt.Parser) -> None:
|
2009-04-13 18:33:01 +08:00
|
|
|
group = parser.getgroup("hello", description="desc")
|
|
|
|
assert group.name == "hello"
|
|
|
|
assert group.description == "desc"
|
|
|
|
group2 = parser.getgroup("hello")
|
|
|
|
assert group2 is group
|
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_group_ordering(self, parser: parseopt.Parser) -> None:
|
2013-10-12 21:39:22 +08:00
|
|
|
parser.getgroup("1")
|
|
|
|
parser.getgroup("2")
|
|
|
|
parser.getgroup("3", after="1")
|
2009-10-17 23:43:33 +08:00
|
|
|
groups = parser._groups
|
|
|
|
groups_names = [x.name for x in groups]
|
|
|
|
assert groups_names == list("132")
|
2009-02-27 18:18:27 +08:00
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_group_addoption(self) -> None:
|
2021-05-24 04:45:49 +08:00
|
|
|
group = parseopt.OptionGroup("hello", _ispytest=True)
|
2009-02-27 18:18:27 +08:00
|
|
|
group.addoption("--option1", action="store_true")
|
|
|
|
assert len(group.options) == 1
|
2013-07-25 21:33:43 +08:00
|
|
|
assert isinstance(group.options[0], parseopt.Argument)
|
2009-02-27 18:18:27 +08:00
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_group_addoption_conflict(self) -> None:
|
2021-05-24 04:45:49 +08:00
|
|
|
group = parseopt.OptionGroup("hello again", _ispytest=True)
|
2016-06-22 15:52:48 +08:00
|
|
|
group.addoption("--option1", "--option-1", action="store_true")
|
|
|
|
with pytest.raises(ValueError) as err:
|
|
|
|
group.addoption("--option1", "--option-one", action="store_true")
|
|
|
|
assert str({"--option1"}) in str(err.value)
|
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_group_shortopt_lowercase(self, parser: parseopt.Parser) -> None:
|
2010-10-14 00:41:53 +08:00
|
|
|
group = parser.getgroup("hello")
|
2018-11-23 02:05:10 +08:00
|
|
|
with pytest.raises(ValueError):
|
2009-02-27 18:18:27 +08:00
|
|
|
group.addoption("-x", action="store_true")
|
|
|
|
assert len(group.options) == 0
|
|
|
|
group._addoption("-x", action="store_true")
|
|
|
|
assert len(group.options) == 1
|
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_parser_addoption(self, parser: parseopt.Parser) -> None:
|
2009-03-26 20:21:05 +08:00
|
|
|
group = parser.getgroup("custom options")
|
2009-02-27 18:18:27 +08:00
|
|
|
assert len(group.options) == 0
|
|
|
|
group.addoption("--option1", action="store_true")
|
|
|
|
assert len(group.options) == 1
|
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_parse(self, parser: parseopt.Parser) -> None:
|
2009-02-27 18:18:27 +08:00
|
|
|
parser.addoption("--hello", dest="hello", action="store")
|
2013-07-25 21:33:43 +08:00
|
|
|
args = parser.parse(["--hello", "world"])
|
|
|
|
assert args.hello == "world"
|
2013-09-28 15:52:41 +08:00
|
|
|
assert not getattr(args, parseopt.FILE_OR_DIR)
|
2009-02-27 18:18:27 +08:00
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_parse2(self, parser: parseopt.Parser) -> None:
|
2021-03-14 03:22:54 +08:00
|
|
|
args = parser.parse([Path(".")])
|
|
|
|
assert getattr(args, parseopt.FILE_OR_DIR)[0] == "."
|
2009-02-27 18:18:27 +08:00
|
|
|
|
2024-03-09 14:51:52 +08:00
|
|
|
# Warning ignore because of:
|
|
|
|
# https://github.com/python/cpython/issues/85308
|
|
|
|
# Can be removed once Python<3.12 support is dropped.
|
|
|
|
@pytest.mark.filterwarnings("ignore:'encoding' argument not specified")
|
|
|
|
def test_parse_from_file(self, parser: parseopt.Parser, tmp_path: Path) -> None:
|
|
|
|
tests = [".", "some.py::Test::test_method[param0]", "other/test_file.py"]
|
|
|
|
args_file = tmp_path / "tests.txt"
|
|
|
|
args_file.write_text("\n".join(tests), encoding="utf-8")
|
|
|
|
args = parser.parse([f"@{args_file.absolute()}"])
|
|
|
|
assert getattr(args, parseopt.FILE_OR_DIR) == tests
|
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_parse_known_args(self, parser: parseopt.Parser) -> None:
|
2021-03-14 03:22:54 +08:00
|
|
|
parser.parse_known_args([Path(".")])
|
2013-09-30 19:14:16 +08:00
|
|
|
parser.addoption("--hello", action="store_true")
|
2015-08-28 06:35:32 +08:00
|
|
|
ns = parser.parse_known_args(["x", "--y", "--hello", "this"])
|
2013-09-30 19:14:16 +08:00
|
|
|
assert ns.hello
|
2015-08-26 09:08:05 +08:00
|
|
|
assert ns.file_or_dir == ["x"]
|
2015-08-28 06:35:32 +08:00
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_parse_known_and_unknown_args(self, parser: parseopt.Parser) -> None:
|
2015-08-28 06:35:32 +08:00
|
|
|
parser.addoption("--hello", action="store_true")
|
|
|
|
ns, unknown = parser.parse_known_and_unknown_args(
|
|
|
|
["x", "--y", "--hello", "this"]
|
|
|
|
)
|
|
|
|
assert ns.hello
|
|
|
|
assert ns.file_or_dir == ["x"]
|
|
|
|
assert unknown == ["--y", "this"]
|
2013-09-30 19:14:16 +08:00
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_parse_will_set_default(self, parser: parseopt.Parser) -> None:
|
2009-02-27 18:18:27 +08:00
|
|
|
parser.addoption("--hello", dest="hello", default="x", action="store")
|
2013-07-25 21:33:43 +08:00
|
|
|
option = parser.parse([])
|
2009-02-27 18:18:27 +08:00
|
|
|
assert option.hello == "x"
|
|
|
|
del option.hello
|
2013-10-12 21:39:22 +08:00
|
|
|
parser.parse_setoption([], option)
|
2009-02-27 18:18:27 +08:00
|
|
|
assert option.hello == "x"
|
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_parse_setoption(self, parser: parseopt.Parser) -> None:
|
2009-02-27 18:18:27 +08:00
|
|
|
parser.addoption("--hello", dest="hello", action="store")
|
|
|
|
parser.addoption("--world", dest="world", default=42)
|
2016-11-21 04:59:15 +08:00
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
option = argparse.Namespace()
|
2009-02-27 18:18:27 +08:00
|
|
|
args = parser.parse_setoption(["--hello", "world"], option)
|
|
|
|
assert option.hello == "world"
|
|
|
|
assert option.world == 42
|
|
|
|
assert not args
|
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_parse_special_destination(self, parser: parseopt.Parser) -> None:
|
2013-10-12 21:39:22 +08:00
|
|
|
parser.addoption("--ultimate-answer", type=int)
|
2013-07-25 21:33:43 +08:00
|
|
|
args = parser.parse(["--ultimate-answer", "42"])
|
|
|
|
assert args.ultimate_answer == 42
|
2013-07-26 14:59:31 +08:00
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_parse_split_positional_arguments(self, parser: parseopt.Parser) -> None:
|
2013-07-30 17:26:15 +08:00
|
|
|
parser.addoption("-R", action="store_true")
|
|
|
|
parser.addoption("-S", action="store_false")
|
|
|
|
args = parser.parse(["-R", "4", "2", "-S"])
|
2013-09-28 15:52:41 +08:00
|
|
|
assert getattr(args, parseopt.FILE_OR_DIR) == ["4", "2"]
|
2013-07-30 17:26:15 +08:00
|
|
|
args = parser.parse(["-R", "-S", "4", "2", "-R"])
|
2013-09-28 15:52:41 +08:00
|
|
|
assert getattr(args, parseopt.FILE_OR_DIR) == ["4", "2"]
|
2017-07-17 07:25:10 +08:00
|
|
|
assert args.R is True
|
|
|
|
assert args.S is False
|
2013-07-30 17:26:15 +08:00
|
|
|
args = parser.parse(["-R", "4", "-S", "2"])
|
2013-09-28 15:52:41 +08:00
|
|
|
assert getattr(args, parseopt.FILE_OR_DIR) == ["4", "2"]
|
2017-07-17 07:25:10 +08:00
|
|
|
assert args.R is True
|
|
|
|
assert args.S is False
|
2013-07-30 17:26:15 +08:00
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_parse_defaultgetter(self) -> None:
|
2009-02-27 18:18:27 +08:00
|
|
|
def defaultget(option):
|
2013-07-25 21:33:43 +08:00
|
|
|
if not hasattr(option, "type"):
|
|
|
|
return
|
|
|
|
if option.type is int:
|
2009-02-27 18:18:27 +08:00
|
|
|
option.default = 42
|
2013-07-25 21:33:43 +08:00
|
|
|
elif option.type is str:
|
2009-02-27 18:18:27 +08:00
|
|
|
option.default = "world"
|
2018-05-23 22:48:46 +08:00
|
|
|
|
2021-05-24 04:45:49 +08:00
|
|
|
parser = parseopt.Parser(processopt=defaultget, _ispytest=True)
|
2017-03-21 09:01:22 +08:00
|
|
|
parser.addoption("--this", dest="this", type=int, action="store")
|
|
|
|
parser.addoption("--hello", dest="hello", type=str, action="store")
|
2009-02-27 18:18:27 +08:00
|
|
|
parser.addoption("--no", dest="no", action="store_true")
|
2013-07-25 21:33:43 +08:00
|
|
|
option = parser.parse([])
|
2009-02-27 18:18:27 +08:00
|
|
|
assert option.hello == "world"
|
|
|
|
assert option.this == 42
|
2013-07-25 21:33:43 +08:00
|
|
|
assert option.no is False
|
2010-10-31 01:23:50 +08:00
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_drop_short_helper(self) -> None:
|
2017-12-27 11:47:26 +08:00
|
|
|
parser = argparse.ArgumentParser(
|
2019-06-25 11:51:33 +08:00
|
|
|
formatter_class=parseopt.DropShorterLongHelpFormatter, allow_abbrev=False
|
2017-12-27 11:47:26 +08:00
|
|
|
)
|
2013-08-01 22:21:33 +08:00
|
|
|
parser.add_argument(
|
|
|
|
"-t", "--twoword", "--duo", "--two-word", "--two", help="foo"
|
2019-11-20 22:03:32 +08:00
|
|
|
)
|
2013-08-01 22:21:33 +08:00
|
|
|
# throws error on --deux only!
|
|
|
|
parser.add_argument(
|
|
|
|
"-d", "--deuxmots", "--deux-mots", action="store_true", help="foo"
|
2019-11-20 22:03:32 +08:00
|
|
|
)
|
2013-08-01 22:21:33 +08:00
|
|
|
parser.add_argument("-s", action="store_true", help="single short")
|
|
|
|
parser.add_argument("--abc", "-a", action="store_true", help="bar")
|
|
|
|
parser.add_argument("--klm", "-k", "--kl-m", action="store_true", help="bar")
|
|
|
|
parser.add_argument(
|
|
|
|
"-P", "--pq-r", "-p", "--pqr", action="store_true", help="bar"
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"--zwei-wort", "--zweiwort", "--zweiwort", action="store_true", help="bar"
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"-x", "--exit-on-first", "--exitfirst", action="store_true", help="spam"
|
2019-11-20 22:03:32 +08:00
|
|
|
)
|
2013-08-01 22:21:33 +08:00
|
|
|
parser.add_argument("files_and_dirs", nargs="*")
|
|
|
|
args = parser.parse_args(["-k", "--duo", "hallo", "--exitfirst"])
|
|
|
|
assert args.twoword == "hallo"
|
|
|
|
assert args.klm is True
|
|
|
|
assert args.zwei_wort is False
|
|
|
|
assert args.exit_on_first is True
|
|
|
|
assert args.s is False
|
|
|
|
args = parser.parse_args(["--deux-mots"])
|
|
|
|
with pytest.raises(AttributeError):
|
|
|
|
assert args.deux_mots is True
|
|
|
|
assert args.deuxmots is True
|
|
|
|
args = parser.parse_args(["file", "dir"])
|
|
|
|
assert "|".join(args.files_and_dirs) == "file|dir"
|
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_drop_short_0(self, parser: parseopt.Parser) -> None:
|
2013-08-01 22:21:33 +08:00
|
|
|
parser.addoption("--funcarg", "--func-arg", action="store_true")
|
|
|
|
parser.addoption("--abc-def", "--abc-def", action="store_true")
|
|
|
|
parser.addoption("--klm-hij", action="store_true")
|
2019-06-25 11:51:33 +08:00
|
|
|
with pytest.raises(UsageError):
|
|
|
|
parser.parse(["--funcarg", "--k"])
|
2013-08-01 22:21:33 +08:00
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_drop_short_2(self, parser: parseopt.Parser) -> None:
|
2013-08-01 22:21:33 +08:00
|
|
|
parser.addoption("--func-arg", "--doit", action="store_true")
|
|
|
|
args = parser.parse(["--doit"])
|
|
|
|
assert args.func_arg is True
|
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_drop_short_3(self, parser: parseopt.Parser) -> None:
|
2013-08-01 22:21:33 +08:00
|
|
|
parser.addoption("--func-arg", "--funcarg", "--doit", action="store_true")
|
|
|
|
args = parser.parse(["abcd"])
|
|
|
|
assert args.func_arg is False
|
|
|
|
assert args.file_or_dir == ["abcd"]
|
|
|
|
|
2020-01-22 22:03:45 +08:00
|
|
|
def test_drop_short_help0(self, parser: parseopt.Parser) -> None:
|
2017-07-17 07:25:08 +08:00
|
|
|
parser.addoption("--func-args", "--doit", help="foo", action="store_true")
|
2013-08-01 22:21:33 +08:00
|
|
|
parser.parse([])
|
|
|
|
help = parser.optparser.format_help()
|
2017-07-17 07:25:09 +08:00
|
|
|
assert "--func-args, --doit foo" in help
|
2013-08-01 22:21:33 +08:00
|
|
|
|
|
|
|
# testing would be more helpful with all help generated
|
2020-01-22 22:03:45 +08:00
|
|
|
def test_drop_short_help1(self, parser: parseopt.Parser) -> None:
|
2013-08-01 22:21:33 +08:00
|
|
|
group = parser.getgroup("general")
|
|
|
|
group.addoption("--doit", "--func-args", action="store_true", help="foo")
|
|
|
|
group._addoption(
|
|
|
|
"-h",
|
|
|
|
"--help",
|
|
|
|
action="store_true",
|
|
|
|
dest="help",
|
2017-07-17 07:25:07 +08:00
|
|
|
help="show help message and configuration info",
|
|
|
|
)
|
2013-08-01 22:21:33 +08:00
|
|
|
parser.parse(["-h"])
|
|
|
|
help = parser.optparser.format_help()
|
2016-10-21 06:26:14 +08:00
|
|
|
assert "-doit, --func-args foo" in help
|
|
|
|
|
2019-11-17 20:35:33 +08:00
|
|
|
def test_multiple_metavar_help(self, parser: parseopt.Parser) -> None:
|
2016-10-21 06:26:14 +08:00
|
|
|
"""
|
|
|
|
Help text for options with a metavar tuple should display help
|
|
|
|
in the form "--preferences=value1 value2 value3" (#2004).
|
|
|
|
"""
|
|
|
|
group = parser.getgroup("general")
|
|
|
|
group.addoption(
|
|
|
|
"--preferences", metavar=("value1", "value2", "value3"), nargs=3
|
|
|
|
)
|
|
|
|
group._addoption("-h", "--help", action="store_true", dest="help")
|
|
|
|
parser.parse(["-h"])
|
|
|
|
help = parser.optparser.format_help()
|
|
|
|
assert "--preferences=value1 value2 value3" in help
|
2013-08-01 22:21:33 +08:00
|
|
|
|
2009-10-15 22:18:57 +08:00
|
|
|
|
2020-12-01 06:27:39 +08:00
|
|
|
def test_argcomplete(pytester: Pytester, monkeypatch: MonkeyPatch) -> None:
|
2023-11-28 23:36:05 +08:00
|
|
|
if sys.version_info >= (3, 11):
|
2023-08-27 20:40:24 +08:00
|
|
|
# New in Python 3.11, ignores utf-8 mode
|
2023-11-28 23:36:05 +08:00
|
|
|
encoding = locale.getencoding()
|
|
|
|
else:
|
2023-06-20 19:55:39 +08:00
|
|
|
encoding = locale.getpreferredencoding(False)
|
2020-07-20 22:24:39 +08:00
|
|
|
try:
|
|
|
|
bash_version = subprocess.run(
|
|
|
|
["bash", "--version"],
|
|
|
|
stdout=subprocess.PIPE,
|
2020-07-22 02:21:09 +08:00
|
|
|
stderr=subprocess.DEVNULL,
|
|
|
|
check=True,
|
2021-12-26 04:25:42 +08:00
|
|
|
text=True,
|
2023-06-20 19:55:39 +08:00
|
|
|
encoding=encoding,
|
2020-07-20 22:24:39 +08:00
|
|
|
).stdout
|
2020-07-22 02:21:09 +08:00
|
|
|
except (OSError, subprocess.CalledProcessError):
|
2020-07-20 22:24:39 +08:00
|
|
|
pytest.skip("bash is not available")
|
|
|
|
if "GNU bash" not in bash_version:
|
|
|
|
# See #7518.
|
|
|
|
pytest.skip("not a real bash")
|
|
|
|
|
2020-12-01 06:27:39 +08:00
|
|
|
script = str(pytester.path.joinpath("test_argcomplete"))
|
2013-10-04 00:02:54 +08:00
|
|
|
|
2023-06-20 19:55:40 +08:00
|
|
|
with open(str(script), "w", encoding="utf-8") as fp:
|
2013-07-30 17:26:15 +08:00
|
|
|
# redirect output from argcomplete to stdin and stderr is not trivial
|
|
|
|
# http://stackoverflow.com/q/12589419/1307905
|
|
|
|
# so we use bash
|
2019-09-23 22:23:14 +08:00
|
|
|
fp.write(
|
|
|
|
f'COMP_WORDBREAKS="$COMP_WORDBREAKS" {shlex.quote(sys.executable)} -m pytest 8>&1 9>&2'
|
|
|
|
)
|
2020-12-16 12:16:05 +08:00
|
|
|
# alternative would be extended Pytester.{run(),_run(),popen()} to be able
|
2013-07-31 22:03:53 +08:00
|
|
|
# to handle a keyword argument env that replaces os.environ in popen or
|
|
|
|
# extends the copy, advantage: could not forget to restore
|
2013-08-01 03:33:13 +08:00
|
|
|
monkeypatch.setenv("_ARGCOMPLETE", "1")
|
2017-07-17 07:25:08 +08:00
|
|
|
monkeypatch.setenv("_ARGCOMPLETE_IFS", "\x0b")
|
2013-08-01 03:33:13 +08:00
|
|
|
monkeypatch.setenv("COMP_WORDBREAKS", " \\t\\n\"\\'><=;|&(:")
|
2018-05-23 22:48:46 +08:00
|
|
|
|
2013-07-30 18:33:38 +08:00
|
|
|
arg = "--fu"
|
2016-06-21 22:16:57 +08:00
|
|
|
monkeypatch.setenv("COMP_LINE", "pytest " + arg)
|
|
|
|
monkeypatch.setenv("COMP_POINT", str(len("pytest " + arg)))
|
2020-12-01 06:27:39 +08:00
|
|
|
result = pytester.run("bash", str(script), arg)
|
2013-07-30 17:26:15 +08:00
|
|
|
if result.ret == 255:
|
|
|
|
# argcomplete not found
|
2013-07-30 18:33:38 +08:00
|
|
|
pytest.skip("argcomplete not available")
|
2013-09-06 04:32:35 +08:00
|
|
|
elif not result.stdout.str():
|
2019-02-27 23:07:11 +08:00
|
|
|
pytest.skip(
|
|
|
|
f"bash provided no output on stdout, argcomplete not available? (stderr={result.stderr.str()!r})"
|
|
|
|
)
|
2013-07-30 17:26:15 +08:00
|
|
|
else:
|
2017-10-10 13:54:56 +08:00
|
|
|
result.stdout.fnmatch_lines(["--funcargs", "--fulltrace"])
|
2013-07-30 18:33:38 +08:00
|
|
|
os.mkdir("test_argcomplete.d")
|
|
|
|
arg = "test_argc"
|
2016-06-21 22:16:57 +08:00
|
|
|
monkeypatch.setenv("COMP_LINE", "pytest " + arg)
|
|
|
|
monkeypatch.setenv("COMP_POINT", str(len("pytest " + arg)))
|
2020-12-01 06:27:39 +08:00
|
|
|
result = pytester.run("bash", str(script), arg)
|
2013-07-30 18:33:38 +08:00
|
|
|
result.stdout.fnmatch_lines(["test_argcomplete", "test_argcomplete.d/"])
|