Skip to content

Commit efa9eff

Browse files
committed
Add strict_config, strict_markers ini options, same as CLI flags
We want to have ini versions of all strictness flags, since they're usually more sensible as project configuration, and as preparation for adding the `strict` ini option. Refs #13823.
1 parent 9453490 commit efa9eff

File tree

12 files changed

+128
-26
lines changed

12 files changed

+128
-26
lines changed

changelog/13823.improvement.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1-
Added :confval:`strict_xfail` as an alias to the ``xfail_strict`` option.
2-
This makes it consistent with other strictness options.
1+
Added :confval:`strict_xfail` as an alias to the ``xfail_strict`` option,
2+
:confval:`strict_config` as an alias to the ``--strict-config`` flag,
3+
and :confval:`strict_markers` as an alias to the ``--strict-markers`` flag.
4+
This makes all strictness options consistently have configuration options with the prefix ``strict_``.

doc/en/example/markers.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,7 @@ For an example on how to add and work with markers from a plugin, see
286286

287287
* Asking for existing markers via ``pytest --markers`` gives good output
288288

289-
* Typos in function markers are treated as an error if you use
290-
the ``--strict-markers`` option.
289+
* Typos in function markers are treated as an error if you use the :confval:`strict_markers` configuration option.
291290

292291
.. _`scoped-marking`:
293292

doc/en/how-to/mark.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,14 @@ surprising due to mistyped names. As described in the previous section, you can
8080
the warning for custom marks by registering them in your ``pytest.ini`` file or
8181
using a custom ``pytest_configure`` hook.
8282

83-
When the ``--strict-markers`` command-line flag is passed, any unknown marks applied
83+
When the :confval:`strict_markers` ini option is set, any unknown marks applied
8484
with the ``@pytest.mark.name_of_the_mark`` decorator will trigger an error. You can
85-
enforce this validation in your project by adding ``--strict-markers`` to ``addopts``:
85+
enforce this validation in your project by setting :confval:`strict_markers` in your configuration:
8686

8787
.. code-block:: ini
8888
8989
[pytest]
90-
addopts = --strict-markers
90+
strict_markers = True
9191
markers =
9292
slow: marks tests as slow (deselect with '-m "not slow"')
9393
serial

doc/en/reference/reference.rst

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1774,25 +1774,21 @@ passed multiple times. The expected format is ``name=value``. For example::
17741774

17751775
.. confval:: markers
17761776

1777-
When the ``--strict-markers`` or ``--strict`` command-line arguments are used,
1777+
When the :confval:`strict_markers` configuration option is set,
17781778
only known markers - defined in code by core pytest or some plugin - are allowed.
17791779

17801780
You can list additional markers in this setting to add them to the whitelist,
1781-
in which case you probably want to add ``--strict-markers`` to ``addopts``
1781+
in which case you probably want to set :confval:`strict_markers` to ``True``
17821782
to avoid future regressions:
17831783

17841784
.. code-block:: ini
17851785
17861786
[pytest]
1787-
addopts = --strict-markers
1787+
strict_markers = True
17881788
markers =
17891789
slow
17901790
serial
17911791
1792-
.. note::
1793-
The use of ``--strict-markers`` is highly preferred. ``--strict`` was kept for
1794-
backward compatibility only and may be confusing for others as it only applies to
1795-
markers and not to other options.
17961792
17971793
.. confval:: minversion
17981794

@@ -2086,6 +2082,27 @@ passed multiple times. The expected format is ``name=value``. For example::
20862082
Renamed from ``xfail_strict`` to ``strict_xfail``.
20872083
``xfail_strict`` is accepted as an alias for ``strict_xfail``.
20882084

2085+
2086+
.. confval:: strict_config
2087+
2088+
If set to ``True``, any warnings encountered while parsing the ``pytest`` section of the configuration file will raise errors.
2089+
2090+
.. code-block:: ini
2091+
2092+
[pytest]
2093+
strict_config = True
2094+
2095+
2096+
.. confval:: strict_markers
2097+
2098+
If set to ``True``, markers not registered in the ``markers`` section of the configuration file will raise errors.
2099+
2100+
.. code-block:: ini
2101+
2102+
[pytest]
2103+
strict_markers = True
2104+
2105+
20892106
.. confval:: strict_parametrization_ids
20902107

20912108
If set, pytest emits an error if it detects non-unique parameter set IDs.

pyproject.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ max_supported_python = "3.14"
355355

356356
[tool.pytest.ini_options]
357357
minversion = "2.0"
358-
addopts = "-rfEX -p pytester --strict-markers"
358+
addopts = "-rfEX -p pytester"
359359
python_files = [
360360
"test_*.py",
361361
"*_test.py",
@@ -380,6 +380,8 @@ norecursedirs = [
380380
]
381381
strict_xfail = true
382382
strict_parametrization_ids = true
383+
strict_markers = true
384+
strict_config = true
383385
filterwarnings = [
384386
"error",
385387
"default:Using or importing the ABCs:DeprecationWarning:unittest2.*",

src/_pytest/config/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1515,7 +1515,8 @@ def _validate_plugins(self) -> None:
15151515
)
15161516

15171517
def _warn_or_fail_if_strict(self, message: str) -> None:
1518-
if self.known_args_namespace.strict_config:
1518+
strict_config = self.getini("strict_config")
1519+
if strict_config:
15191520
raise UsageError(message)
15201521

15211522
self.issue_config_time_warning(PytestConfigWarning(message), stacklevel=3)

src/_pytest/config/argparsing.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,3 +547,40 @@ def _split_lines(self, text, width):
547547
for line in text.splitlines():
548548
lines.extend(textwrap.wrap(line.strip(), width))
549549
return lines
550+
551+
552+
class OverrideIniAction(argparse.Action):
553+
"""Custom argparse action that makes a CLI flag equivalent to overriding an
554+
option, in addition to behaving like `store_true`.
555+
556+
This can simplify things since code only needs to inspect the ini option
557+
and not consider the CLI flag.
558+
"""
559+
560+
def __init__(
561+
self,
562+
option_strings: Sequence[str],
563+
dest: str,
564+
nargs: int | str | None = None,
565+
*args,
566+
ini_option: str,
567+
ini_value: str,
568+
**kwargs,
569+
) -> None:
570+
super().__init__(option_strings, dest, 0, *args, **kwargs)
571+
self.ini_option = ini_option
572+
self.ini_value = ini_value
573+
574+
def __call__(
575+
self,
576+
parser: argparse.ArgumentParser,
577+
namespace: argparse.Namespace,
578+
*args,
579+
**kwargs,
580+
) -> None:
581+
setattr(namespace, self.dest, True)
582+
current_overrides = getattr(namespace, "override_ini", None)
583+
if current_overrides is None:
584+
current_overrides = []
585+
current_overrides.append(f"{self.ini_option}={self.ini_value}")
586+
setattr(namespace, "override_ini", current_overrides)

src/_pytest/main.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
from _pytest.config import hookimpl
3333
from _pytest.config import PytestPluginManager
3434
from _pytest.config import UsageError
35+
from _pytest.config.argparsing import OverrideIniAction
3536
from _pytest.config.argparsing import Parser
3637
from _pytest.config.compat import PathAwareHookProxy
3738
from _pytest.outcomes import exit
@@ -75,21 +76,37 @@ def pytest_addoption(parser: Parser) -> None:
7576
)
7677
group.addoption(
7778
"--strict-config",
78-
action="store_true",
79-
help="Any warnings encountered while parsing the `pytest` section of the "
80-
"configuration file raise errors",
79+
action=OverrideIniAction,
80+
ini_option="strict_config",
81+
ini_value="true",
82+
help="Enables the strict_config option",
8183
)
8284
group.addoption(
8385
"--strict-markers",
84-
action="store_true",
85-
help="Markers not registered in the `markers` section of the configuration "
86-
"file raise errors",
86+
action=OverrideIniAction,
87+
ini_option="strict_markers",
88+
ini_value="true",
89+
help="Enables the strict_markers option",
8790
)
8891
group.addoption(
8992
"--strict",
9093
action="store_true",
9194
help="(Deprecated) alias to --strict-markers",
9295
)
96+
parser.addini(
97+
"strict_config",
98+
"Any warnings encountered while parsing the `pytest` section of the "
99+
"configuration file raise errors",
100+
type="bool",
101+
default=False,
102+
)
103+
parser.addini(
104+
"strict_markers",
105+
"Markers not registered in the `markers` section of the configuration "
106+
"file raise errors",
107+
type="bool",
108+
default=False,
109+
)
93110

94111
group = parser.getgroup("pytest-warnings")
95112
group.addoption(

src/_pytest/mark/structures.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,10 @@ def __getattr__(self, name: str) -> MarkDecorator:
580580
# If the name is not in the set of known marks after updating,
581581
# then it really is time to issue a warning or an error.
582582
if name not in self._markers:
583-
if self._config.option.strict_markers or self._config.option.strict:
583+
strict_markers = (
584+
self._config.getini("strict_markers") or self._config.option.strict
585+
)
586+
if strict_markers:
584587
fail(
585588
f"{name!r} not found in `markers` configuration option",
586589
pytrace=False,

testing/plugins_integration/pytest.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[pytest]
2-
addopts = --strict-markers
2+
strict_markers = True
33
asyncio_mode = strict
44
filterwarnings =
55
error::pytest.PytestWarning

0 commit comments

Comments
 (0)