diff --git a/AUTHORS b/AUTHORS index 25b55e5ae..f6e50003b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -185,6 +185,7 @@ Katerina Koukiou Keri Volans Kevin Cox Kevin J. Foley +Kevin Santana Kodi B. Arfer Kostis Anagnostopoulos Kristoffer Nordström diff --git a/changelog/9303.bugfix.rst b/changelog/9303.bugfix.rst new file mode 100644 index 000000000..cad5abf1f --- /dev/null +++ b/changelog/9303.bugfix.rst @@ -0,0 +1,2 @@ +`Parser.addoption` now throws a value error if an attempt is made at adding an option +after the pre_parsing process without including a default. diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index b0bb3f168..bd8b1ceb8 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -362,6 +362,11 @@ class OptionGroup: results in help showing ``--two-words`` only, but ``--twowords`` gets accepted **and** the automatic destination is in ``args.twowords``. """ + if getattr(self.parser, "after_preparse", False) and "default" not in attrs: + raise ValueError( + "Cannot add options without default after initial conftest discovery" + ) + conflict = set(optnames).intersection( name for opt in self.options for name in opt.names() ) diff --git a/testing/test_pluginmanager.py b/testing/test_pluginmanager.py index 9fe23d177..3ae997e92 100644 --- a/testing/test_pluginmanager.py +++ b/testing/test_pluginmanager.py @@ -78,6 +78,21 @@ class TestPytestPluginInteractions: ) assert config.option.test123 + def test_do_option_postinit_nodefault(self, pytester: Pytester) -> None: + config = pytester.parseconfigure() + assert not hasattr(config.option, "deadbeef") + p = pytester.makepyfile( + """ + def pytest_addoption(parser): + parser.addoption('--deadbeef', action="store_true") + """ + ) + with pytest.raises(ValueError): + config.pluginmanager._importconftest( + p, importmode="prepend", rootpath=pytester.path + ) + assert not hasattr(config.option, "deadbeef") + def test_configure(self, pytester: Pytester) -> None: config = pytester.parseconfig() values = []