Skip to content

Commit d12cdd3

Browse files
committed
Make InvocationParams.args a tuple
This avoids mutating the original list to reflect on InvocationParams, which is supposed to be an immutable snapshot of the state of pytest.main() at the moment of invocation (see pytest-dev/pytest-xdist#478).
1 parent 119bf66 commit d12cdd3

File tree

3 files changed

+14
-8
lines changed

3 files changed

+14
-8
lines changed

changelog/6008.improvement.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
``Config.InvocationParams.args`` is now always a ``tuple`` to better convey that it should be
2+
immutable and avoid accidental modifications.

src/_pytest/config/__init__.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ def get_config(args=None, plugins=None):
169169
config = Config(
170170
pluginmanager,
171171
invocation_params=Config.InvocationParams(
172-
args=args, plugins=plugins, dir=Path().resolve()
172+
args=args or (), plugins=plugins, dir=Path().resolve()
173173
),
174174
)
175175

@@ -654,7 +654,7 @@ class Config:
654654
655655
Contains the following read-only attributes:
656656
657-
* ``args``: list of command-line arguments as passed to ``pytest.main()``.
657+
* ``args``: tuple of command-line arguments as passed to ``pytest.main()``.
658658
* ``plugins``: list of extra plugins, might be None.
659659
* ``dir``: directory where ``pytest.main()`` was invoked from.
660660
"""
@@ -667,13 +667,13 @@ class InvocationParams:
667667
668668
.. note::
669669
670-
Currently the environment variable PYTEST_ADDOPTS is also handled by
671-
pytest implicitly, not being part of the invocation.
670+
Note that the environment variable ``PYTEST_ADDOPTS`` and the ``addopts``
671+
ini option are handled by pytest, not being included in the ``args`` attribute.
672672
673673
Plugins accessing ``InvocationParams`` must be aware of that.
674674
"""
675675

676-
args = attr.ib()
676+
args = attr.ib(converter=tuple)
677677
plugins = attr.ib()
678678
dir = attr.ib(type=Path)
679679

@@ -938,7 +938,6 @@ def parse(self, args, addopts=True):
938938
assert not hasattr(
939939
self, "args"
940940
), "can only parse cmdline args at most once per Config object"
941-
assert self.invocation_params.args == args
942941
self.hook.pytest_addhooks.call_historic(
943942
kwargs=dict(pluginmanager=self.pluginmanager)
944943
)

testing/test_config.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import pytest
88
from _pytest.compat import importlib_metadata
99
from _pytest.config import _iter_rewritable_modules
10+
from _pytest.config import Config
1011
from _pytest.config.exceptions import UsageError
1112
from _pytest.config.findpaths import determine_setup
1213
from _pytest.config.findpaths import get_common_ancestor
@@ -456,7 +457,7 @@ def test_invocation_params_args(self, _sys_snapshot):
456457

457458
config = Config.fromdictargs(option_dict, args)
458459
assert config.args == ["a", "b"]
459-
assert config.invocation_params.args == args
460+
assert config.invocation_params.args == tuple(args)
460461
assert config.option.verbose == 4
461462
assert config.option.capture == "no"
462463

@@ -1235,14 +1236,18 @@ class DummyPlugin:
12351236
call = calls[0]
12361237
config = call.item.config
12371238

1238-
assert config.invocation_params.args == [p, "-v"]
1239+
assert config.invocation_params.args == (p, "-v")
12391240
assert config.invocation_params.dir == Path(str(testdir.tmpdir))
12401241

12411242
plugins = config.invocation_params.plugins
12421243
assert len(plugins) == 2
12431244
assert plugins[0] is plugin
12441245
assert type(plugins[1]).__name__ == "Collect" # installed by testdir.inline_run()
12451246

1247+
# args cannot be None
1248+
with pytest.raises(TypeError):
1249+
Config.InvocationParams(args=None, plugins=None, dir=Path())
1250+
12461251

12471252
@pytest.mark.parametrize(
12481253
"plugin",

0 commit comments

Comments
 (0)