argparsing: export Parser and OptionGroup for typing purposes

`Parser` is used by many plugins and custom hooks. `OptionGroup` is
exposed by the `parser.addgroup` API.

The constructors of both are marked private, they are not meant to be
constructed directly.
This commit is contained in:
Ran Benita
2021-05-23 23:45:49 +03:00
parent c198a7a67e
commit 538b5c2499
11 changed files with 50 additions and 24 deletions

View File

@@ -909,6 +909,7 @@ class Config:
self._parser = Parser(
usage=f"%(prog)s [options] [{_a}] [{_a}] [...]",
processopt=self._processopt,
_ispytest=True,
)
self.pluginmanager = pluginmanager
"""The plugin manager handles plugin registration and hook invocation.
@@ -1380,8 +1381,8 @@ class Config:
"""Return configuration value from an :ref:`ini file <configfiles>`.
If the specified name hasn't been registered through a prior
:py:func:`parser.addini <_pytest.config.argparsing.Parser.addini>`
call (usually from a plugin), a ValueError is raised.
:func:`parser.addini <pytest.Parser.addini>` call (usually from a
plugin), a ValueError is raised.
"""
try:
return self._inicache[name]

View File

@@ -21,6 +21,7 @@ from _pytest.config.exceptions import UsageError
from _pytest.deprecated import ARGUMENT_PERCENT_DEFAULT
from _pytest.deprecated import ARGUMENT_TYPE_STR
from _pytest.deprecated import ARGUMENT_TYPE_STR_CHOICE
from _pytest.deprecated import check_ispytest
if TYPE_CHECKING:
from typing import NoReturn
@@ -43,8 +44,11 @@ class Parser:
self,
usage: Optional[str] = None,
processopt: Optional[Callable[["Argument"], None]] = None,
*,
_ispytest: bool = False,
) -> None:
self._anonymous = OptionGroup("custom options", parser=self)
check_ispytest(_ispytest)
self._anonymous = OptionGroup("custom options", parser=self, _ispytest=True)
self._groups: List[OptionGroup] = []
self._processopt = processopt
self._usage = usage
@@ -67,14 +71,14 @@ class Parser:
:after: Name of another group, used for ordering --help output.
The returned group object has an ``addoption`` method with the same
signature as :py:func:`parser.addoption
<_pytest.config.argparsing.Parser.addoption>` but will be shown in the
respective group in the output of ``pytest. --help``.
signature as :func:`parser.addoption <pytest.Parser.addoption>` but
will be shown in the respective group in the output of
``pytest. --help``.
"""
for group in self._groups:
if group.name == name:
return group
group = OptionGroup(name, description, parser=self)
group = OptionGroup(name, description, parser=self, _ispytest=True)
i = 0
for i, grp in enumerate(self._groups):
if grp.name == after:
@@ -334,9 +338,17 @@ class Argument:
class OptionGroup:
"""A group of options shown in its own section."""
def __init__(
self, name: str, description: str = "", parser: Optional[Parser] = None
self,
name: str,
description: str = "",
parser: Optional[Parser] = None,
*,
_ispytest: bool = False,
) -> None:
check_ispytest(_ispytest)
self.name = name
self.description = description
self.options: List[Argument] = []
@@ -346,9 +358,9 @@ class OptionGroup:
"""Add an option to this group.
If a shortened version of a long option is specified, it will
be suppressed in the help. addoption('--twowords', '--two-words')
results in help showing '--two-words' only, but --twowords gets
accepted **and** the automatic destination is in args.twowords.
be suppressed in the help. ``addoption('--twowords', '--two-words')``
results in help showing ``--two-words`` only, but ``--twowords`` gets
accepted **and** the automatic destination is in ``args.twowords``.
"""
conflict = set(optnames).intersection(
name for opt in self.options for name in opt.names()

View File

@@ -88,11 +88,11 @@ def pytest_addoption(parser: "Parser", pluginmanager: "PytestPluginManager") ->
files situated at the tests root directory due to how pytest
:ref:`discovers plugins during startup <pluginorder>`.
:param _pytest.config.argparsing.Parser parser:
:param pytest.Parser parser:
To add command line options, call
:py:func:`parser.addoption(...) <_pytest.config.argparsing.Parser.addoption>`.
:py:func:`parser.addoption(...) <pytest.Parser.addoption>`.
To add ini-file values call :py:func:`parser.addini(...)
<_pytest.config.argparsing.Parser.addini>`.
<pytest.Parser.addini>`.
:param _pytest.config.PytestPluginManager pluginmanager:
pytest plugin manager, which can be used to install :py:func:`hookspec`'s
@@ -193,7 +193,7 @@ def pytest_load_initial_conftests(
:param _pytest.config.Config early_config: The pytest config object.
:param List[str] args: Arguments passed on the command line.
:param _pytest.config.argparsing.Parser parser: To add command line options.
:param pytest.Parser parser: To add command line options.
"""

View File

@@ -13,6 +13,8 @@ from _pytest.config import hookimpl
from _pytest.config import hookspec
from _pytest.config import main
from _pytest.config import UsageError
from _pytest.config.argparsing import OptionGroup
from _pytest.config.argparsing import Parser
from _pytest.debugging import pytestPDB as __pytestPDB
from _pytest.fixtures import _fillfuncargs
from _pytest.fixtures import fixture
@@ -103,8 +105,10 @@ __all__ = [
"Metafunc",
"Module",
"MonkeyPatch",
"OptionGroup",
"Package",
"param",
"Parser",
"PytestAssertRewriteWarning",
"PytestCacheWarning",
"PytestCollectionWarning",