Skip to content

Commit 1b5f532

Browse files
authored
Merge pull request #8695 from bluetech/export-parser
argparsing: export Parser and OptionGroup for typing purposes
2 parents c5bf5f6 + 538b5c2 commit 1b5f532

File tree

11 files changed

+50
-24
lines changed

11 files changed

+50
-24
lines changed

changelog/7259.feature.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Added :meth:`cache.mkdir() <pytest.Cache.mkdir>`, which is similar to the existing :meth:`cache.makedir() <pytest.Cache.makedir>`,
22
but returns a :class:`pathlib.Path` instead of a legacy ``py.path.local``.
33

4-
Added a ``paths`` type to :meth:`parser.addini() <_pytest.config.argparsing.Parser.addini>`,
4+
Added a ``paths`` type to :meth:`parser.addini() <pytest.Parser.addini>`,
55
as in ``parser.addini("mypaths", "my paths", type="paths")``,
66
which is similar to the existing ``pathlist``,
77
but returns a list of :class:`pathlib.Path` instead of legacy ``py.path.local``.

changelog/7469.deprecation.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,7 @@ Directly constructing the following classes is now deprecated:
66
- ``_pytest.python.Metafunc``
77
- ``_pytest.runner.CallInfo``
88
- ``_pytest._code.ExceptionInfo``
9+
- ``_pytest.config.argparsing.Parser``
10+
- ``_pytest.config.argparsing.OptionGroup``
911

1012
These have always been considered private, but now issue a deprecation warning, which may become a hard error in pytest 7.0.0.

changelog/7469.feature.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ The newly-exported types are:
88
- ``pytest.Metafunc`` for the :class:`metafunc <pytest.MarkGenerator>` argument to the :func:`pytest_generate_tests <pytest.hookspec.pytest_generate_tests>` hook.
99
- ``pytest.CallInfo`` for the :class:`CallInfo <pytest.CallInfo>` type passed to various hooks.
1010
- ``pytest.ExceptionInfo`` for the :class:`ExceptionInfo <pytest.ExceptionInfo>` type returned from :func:`pytest.raises` and passed to various hooks.
11+
- ``pytest.Parser`` for the :class:`Parser <pytest.Parser>` type passed to the :func:`pytest_addoption <pytest.hookspec.pytest_addoption>` hook.
12+
- ``pytest.OptionGroup`` for the :class:`OptionGroup <pytest.OptionGroup>` type returned from the :func:`parser.addgroup <pytest.Parser.getgroup>` method.
1113

1214
Constructing them directly is not supported; they are only meant for use in type annotations.
1315
Doing so will emit a deprecation warning, and may become a hard-error in pytest 7.0.

changelog/8315.deprecation.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Several behaviors of :meth:`Parser.addoption <_pytest.config.argparsing.Parser.addoption>` are now
1+
Several behaviors of :meth:`Parser.addoption <pytest.Parser.addoption>` are now
22
scheduled for removal in pytest 7 (deprecated since pytest 2.4.0):
33

44
- ``parser.addoption(..., help=".. %default ..")`` - use ``%(default)s`` instead.

doc/en/deprecations.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Backward compatibilities in ``Parser.addoption``
4848

4949
.. deprecated:: 2.4
5050

51-
Several behaviors of :meth:`Parser.addoption <_pytest.config.argparsing.Parser.addoption>` are now
51+
Several behaviors of :meth:`Parser.addoption <pytest.Parser.addoption>` are now
5252
scheduled for removal in pytest 7 (deprecated since pytest 2.4.0):
5353

5454
- ``parser.addoption(..., help=".. %default ..")`` - use ``%(default)s`` instead.

doc/en/reference/reference.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -889,9 +889,14 @@ Node
889889
Parser
890890
~~~~~~
891891

892-
.. autoclass:: _pytest.config.argparsing.Parser()
892+
.. autoclass:: pytest.Parser()
893893
:members:
894894

895+
OptionGroup
896+
~~~~~~~~~~~
897+
898+
.. autoclass:: pytest.OptionGroup()
899+
:members:
895900

896901
PytestPluginManager
897902
~~~~~~~~~~~~~~~~~~~

src/_pytest/config/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,7 @@ def __init__(
909909
self._parser = Parser(
910910
usage=f"%(prog)s [options] [{_a}] [{_a}] [...]",
911911
processopt=self._processopt,
912+
_ispytest=True,
912913
)
913914
self.pluginmanager = pluginmanager
914915
"""The plugin manager handles plugin registration and hook invocation.
@@ -1380,8 +1381,8 @@ def getini(self, name: str):
13801381
"""Return configuration value from an :ref:`ini file <configfiles>`.
13811382
13821383
If the specified name hasn't been registered through a prior
1383-
:py:func:`parser.addini <_pytest.config.argparsing.Parser.addini>`
1384-
call (usually from a plugin), a ValueError is raised.
1384+
:func:`parser.addini <pytest.Parser.addini>` call (usually from a
1385+
plugin), a ValueError is raised.
13851386
"""
13861387
try:
13871388
return self._inicache[name]

src/_pytest/config/argparsing.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from _pytest.deprecated import ARGUMENT_PERCENT_DEFAULT
2222
from _pytest.deprecated import ARGUMENT_TYPE_STR
2323
from _pytest.deprecated import ARGUMENT_TYPE_STR_CHOICE
24+
from _pytest.deprecated import check_ispytest
2425

2526
if TYPE_CHECKING:
2627
from typing import NoReturn
@@ -43,8 +44,11 @@ def __init__(
4344
self,
4445
usage: Optional[str] = None,
4546
processopt: Optional[Callable[["Argument"], None]] = None,
47+
*,
48+
_ispytest: bool = False,
4649
) -> None:
47-
self._anonymous = OptionGroup("custom options", parser=self)
50+
check_ispytest(_ispytest)
51+
self._anonymous = OptionGroup("custom options", parser=self, _ispytest=True)
4852
self._groups: List[OptionGroup] = []
4953
self._processopt = processopt
5054
self._usage = usage
@@ -67,14 +71,14 @@ def getgroup(
6771
:after: Name of another group, used for ordering --help output.
6872
6973
The returned group object has an ``addoption`` method with the same
70-
signature as :py:func:`parser.addoption
71-
<_pytest.config.argparsing.Parser.addoption>` but will be shown in the
72-
respective group in the output of ``pytest. --help``.
74+
signature as :func:`parser.addoption <pytest.Parser.addoption>` but
75+
will be shown in the respective group in the output of
76+
``pytest. --help``.
7377
"""
7478
for group in self._groups:
7579
if group.name == name:
7680
return group
77-
group = OptionGroup(name, description, parser=self)
81+
group = OptionGroup(name, description, parser=self, _ispytest=True)
7882
i = 0
7983
for i, grp in enumerate(self._groups):
8084
if grp.name == after:
@@ -334,9 +338,17 @@ def __repr__(self) -> str:
334338

335339

336340
class OptionGroup:
341+
"""A group of options shown in its own section."""
342+
337343
def __init__(
338-
self, name: str, description: str = "", parser: Optional[Parser] = None
344+
self,
345+
name: str,
346+
description: str = "",
347+
parser: Optional[Parser] = None,
348+
*,
349+
_ispytest: bool = False,
339350
) -> None:
351+
check_ispytest(_ispytest)
340352
self.name = name
341353
self.description = description
342354
self.options: List[Argument] = []
@@ -346,9 +358,9 @@ def addoption(self, *optnames: str, **attrs: Any) -> None:
346358
"""Add an option to this group.
347359
348360
If a shortened version of a long option is specified, it will
349-
be suppressed in the help. addoption('--twowords', '--two-words')
350-
results in help showing '--two-words' only, but --twowords gets
351-
accepted **and** the automatic destination is in args.twowords.
361+
be suppressed in the help. ``addoption('--twowords', '--two-words')``
362+
results in help showing ``--two-words`` only, but ``--twowords`` gets
363+
accepted **and** the automatic destination is in ``args.twowords``.
352364
"""
353365
conflict = set(optnames).intersection(
354366
name for opt in self.options for name in opt.names()

src/_pytest/hookspec.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,11 @@ def pytest_addoption(parser: "Parser", pluginmanager: "PytestPluginManager") ->
8888
files situated at the tests root directory due to how pytest
8989
:ref:`discovers plugins during startup <pluginorder>`.
9090
91-
:param _pytest.config.argparsing.Parser parser:
91+
:param pytest.Parser parser:
9292
To add command line options, call
93-
:py:func:`parser.addoption(...) <_pytest.config.argparsing.Parser.addoption>`.
93+
:py:func:`parser.addoption(...) <pytest.Parser.addoption>`.
9494
To add ini-file values call :py:func:`parser.addini(...)
95-
<_pytest.config.argparsing.Parser.addini>`.
95+
<pytest.Parser.addini>`.
9696
9797
:param _pytest.config.PytestPluginManager pluginmanager:
9898
pytest plugin manager, which can be used to install :py:func:`hookspec`'s
@@ -193,7 +193,7 @@ def pytest_load_initial_conftests(
193193
194194
:param _pytest.config.Config early_config: The pytest config object.
195195
:param List[str] args: Arguments passed on the command line.
196-
:param _pytest.config.argparsing.Parser parser: To add command line options.
196+
:param pytest.Parser parser: To add command line options.
197197
"""
198198

199199

src/pytest/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
from _pytest.config import hookspec
1414
from _pytest.config import main
1515
from _pytest.config import UsageError
16+
from _pytest.config.argparsing import OptionGroup
17+
from _pytest.config.argparsing import Parser
1618
from _pytest.debugging import pytestPDB as __pytestPDB
1719
from _pytest.fixtures import _fillfuncargs
1820
from _pytest.fixtures import fixture
@@ -103,8 +105,10 @@
103105
"Metafunc",
104106
"Module",
105107
"MonkeyPatch",
108+
"OptionGroup",
106109
"Package",
107110
"param",
111+
"Parser",
108112
"PytestAssertRewriteWarning",
109113
"PytestCacheWarning",
110114
"PytestCollectionWarning",

0 commit comments

Comments
 (0)