From f9a00ffecc7133a88382bf589d5b59944f7d04f2 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Mon, 2 Nov 2020 03:08:56 +0100 Subject: [PATCH] Fix handling of empty help with `addini` Fixes https://github.com/pytest-dev/pytest/issues/7394 --- src/_pytest/config/argparsing.py | 5 +++-- src/_pytest/helpconfig.py | 10 ++++++---- testing/test_helpconfig.py | 30 ++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index ef5543480d8..af19c8a9de4 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -44,7 +44,7 @@ def __init__( self._groups = [] # type: List[OptionGroup] self._processopt = processopt self._usage = usage - self._inidict = {} # type: Dict[str, Tuple[str, Optional[str], Any]] + self._inidict = {} # type: Dict[str, Tuple[Optional[str], Optional[str], Any]] self._ininames = [] # type: List[str] self.extra_info = {} # type: Dict[str, Any] @@ -195,7 +195,7 @@ def parse_known_and_unknown_args( def addini( self, name: str, - help: str, + help: "Optional[str]", type: Optional["Literal['pathlist', 'args', 'linelist', 'bool', 'int']"] = None, *args, **kwargs @@ -203,6 +203,7 @@ def addini( """ register an ini-file option. :param str name: name of the ini-variable + :param help: help text to display (``None`` suppresses it). :param str type: type of the variable, one of ``pathlist``, ``args``, ``linelist``, ``bool``, or ``int``. :kwparam default: default value if no ini-file option exists but is queried. diff --git a/src/_pytest/helpconfig.py b/src/_pytest/helpconfig.py index d0a5541183c..e6fa38d89f5 100644 --- a/src/_pytest/helpconfig.py +++ b/src/_pytest/helpconfig.py @@ -161,6 +161,8 @@ def showhelp(config: Config) -> None: indent = " " * indent_len for name in config._parser._ininames: help, type, default = config._parser._inidict[name] + if help is None: + continue if type is None: type = "string" spec = "{} ({}):".format(name, type) @@ -183,10 +185,10 @@ def showhelp(config: Config) -> None: # Display help starting after the spec, following lines indented. print(" " * (indent_len - spec_len - 2), end="") wrapped = textwrap.wrap(help, wrap_width, break_on_hyphens=False) - - print(wrapped[0]) - for line in wrapped[1:]: - print(indent + line) + if wrapped: + print(wrapped[0]) + for line in wrapped[1:]: + print(indent + line) print() print("environment variables:") diff --git a/testing/test_helpconfig.py b/testing/test_helpconfig.py index a41d0f32738..7843b82f5ae 100644 --- a/testing/test_helpconfig.py +++ b/testing/test_helpconfig.py @@ -50,6 +50,36 @@ def test_help(testdir: Testdir) -> None: result.stdout.no_fnmatch_line("logging:") +def test_help_for_empty_ini_params(testdir: "Testdir") -> None: + testdir.makeconftest( + """ + from argparse import SUPPRESS + + def pytest_addoption(parser): + parser.addini("t_ini_none", None, default=True, type="bool") + parser.addini("t_ini_empty", "", default=True, type="bool") + + parser.addoption("--t_opt_none", help=None) + parser.addoption("--t_opt_empty", help="") + parser.addoption("--t_opt_suppress", help=SUPPRESS) + """ + ) + result = testdir.runpytest("--help") + result.stdout.fnmatch_lines( + [ + "custom options:", + " --t_opt_none=T_OPT_NONE", + " --t_opt_empty=T_OPT_EMPTY", + "", + "[pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg file found:", + " t_ini_empty (bool): ", + ] + ) + result_str = result.stdout.str() + assert "t_ini_none" not in result_str + assert "t_opt_suppress" not in result_str + + @pytest.mark.parametrize("method", ("runpytest_inprocess", "runpytest_subprocess")) def test_help_unconfigures_always(method: str, testdir: Testdir) -> None: testdir.makeconftest(