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:
parent
c198a7a67e
commit
538b5c2499
|
@ -1,7 +1,7 @@
|
|||
Added :meth:`cache.mkdir() <pytest.Cache.mkdir>`, which is similar to the existing :meth:`cache.makedir() <pytest.Cache.makedir>`,
|
||||
but returns a :class:`pathlib.Path` instead of a legacy ``py.path.local``.
|
||||
|
||||
Added a ``paths`` type to :meth:`parser.addini() <_pytest.config.argparsing.Parser.addini>`,
|
||||
Added a ``paths`` type to :meth:`parser.addini() <pytest.Parser.addini>`,
|
||||
as in ``parser.addini("mypaths", "my paths", type="paths")``,
|
||||
which is similar to the existing ``pathlist``,
|
||||
but returns a list of :class:`pathlib.Path` instead of legacy ``py.path.local``.
|
||||
|
|
|
@ -6,5 +6,7 @@ Directly constructing the following classes is now deprecated:
|
|||
- ``_pytest.python.Metafunc``
|
||||
- ``_pytest.runner.CallInfo``
|
||||
- ``_pytest._code.ExceptionInfo``
|
||||
- ``_pytest.config.argparsing.Parser``
|
||||
- ``_pytest.config.argparsing.OptionGroup``
|
||||
|
||||
These have always been considered private, but now issue a deprecation warning, which may become a hard error in pytest 7.0.0.
|
||||
|
|
|
@ -8,6 +8,8 @@ The newly-exported types are:
|
|||
- ``pytest.Metafunc`` for the :class:`metafunc <pytest.MarkGenerator>` argument to the :func:`pytest_generate_tests <pytest.hookspec.pytest_generate_tests>` hook.
|
||||
- ``pytest.CallInfo`` for the :class:`CallInfo <pytest.CallInfo>` type passed to various hooks.
|
||||
- ``pytest.ExceptionInfo`` for the :class:`ExceptionInfo <pytest.ExceptionInfo>` type returned from :func:`pytest.raises` and passed to various hooks.
|
||||
- ``pytest.Parser`` for the :class:`Parser <pytest.Parser>` type passed to the :func:`pytest_addoption <pytest.hookspec.pytest_addoption>` hook.
|
||||
- ``pytest.OptionGroup`` for the :class:`OptionGroup <pytest.OptionGroup>` type returned from the :func:`parser.addgroup <pytest.Parser.getgroup>` method.
|
||||
|
||||
Constructing them directly is not supported; they are only meant for use in type annotations.
|
||||
Doing so will emit a deprecation warning, and may become a hard-error in pytest 7.0.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Several behaviors of :meth:`Parser.addoption <_pytest.config.argparsing.Parser.addoption>` are now
|
||||
Several behaviors of :meth:`Parser.addoption <pytest.Parser.addoption>` are now
|
||||
scheduled for removal in pytest 7 (deprecated since pytest 2.4.0):
|
||||
|
||||
- ``parser.addoption(..., help=".. %default ..")`` - use ``%(default)s`` instead.
|
||||
|
|
|
@ -48,7 +48,7 @@ Backward compatibilities in ``Parser.addoption``
|
|||
|
||||
.. deprecated:: 2.4
|
||||
|
||||
Several behaviors of :meth:`Parser.addoption <_pytest.config.argparsing.Parser.addoption>` are now
|
||||
Several behaviors of :meth:`Parser.addoption <pytest.Parser.addoption>` are now
|
||||
scheduled for removal in pytest 7 (deprecated since pytest 2.4.0):
|
||||
|
||||
- ``parser.addoption(..., help=".. %default ..")`` - use ``%(default)s`` instead.
|
||||
|
|
|
@ -889,9 +889,14 @@ Node
|
|||
Parser
|
||||
~~~~~~
|
||||
|
||||
.. autoclass:: _pytest.config.argparsing.Parser()
|
||||
.. autoclass:: pytest.Parser()
|
||||
:members:
|
||||
|
||||
OptionGroup
|
||||
~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: pytest.OptionGroup()
|
||||
:members:
|
||||
|
||||
PytestPluginManager
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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.
|
||||
"""
|
||||
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -14,12 +14,12 @@ from _pytest.pytester import Pytester
|
|||
|
||||
@pytest.fixture
|
||||
def parser() -> parseopt.Parser:
|
||||
return parseopt.Parser()
|
||||
return parseopt.Parser(_ispytest=True)
|
||||
|
||||
|
||||
class TestParser:
|
||||
def test_no_help_by_default(self) -> None:
|
||||
parser = parseopt.Parser(usage="xyz")
|
||||
parser = parseopt.Parser(usage="xyz", _ispytest=True)
|
||||
pytest.raises(UsageError, lambda: parser.parse(["-h"]))
|
||||
|
||||
def test_custom_prog(self, parser: parseopt.Parser) -> None:
|
||||
|
@ -90,13 +90,13 @@ class TestParser:
|
|||
assert groups_names == list("132")
|
||||
|
||||
def test_group_addoption(self) -> None:
|
||||
group = parseopt.OptionGroup("hello")
|
||||
group = parseopt.OptionGroup("hello", _ispytest=True)
|
||||
group.addoption("--option1", action="store_true")
|
||||
assert len(group.options) == 1
|
||||
assert isinstance(group.options[0], parseopt.Argument)
|
||||
|
||||
def test_group_addoption_conflict(self) -> None:
|
||||
group = parseopt.OptionGroup("hello again")
|
||||
group = parseopt.OptionGroup("hello again", _ispytest=True)
|
||||
group.addoption("--option1", "--option-1", action="store_true")
|
||||
with pytest.raises(ValueError) as err:
|
||||
group.addoption("--option1", "--option-one", action="store_true")
|
||||
|
@ -188,7 +188,7 @@ class TestParser:
|
|||
elif option.type is str:
|
||||
option.default = "world"
|
||||
|
||||
parser = parseopt.Parser(processopt=defaultget)
|
||||
parser = parseopt.Parser(processopt=defaultget, _ispytest=True)
|
||||
parser.addoption("--this", dest="this", type=int, action="store")
|
||||
parser.addoption("--hello", dest="hello", type=str, action="store")
|
||||
parser.addoption("--no", dest="no", action="store_true")
|
||||
|
|
Loading…
Reference in New Issue