From 95e0e2ba8ce842fa01b017901379d6c4891f8cca Mon Sep 17 00:00:00 2001 From: Kevin Santana Date: Tue, 7 Dec 2021 21:44:10 -0500 Subject: [PATCH] throw if addoption called after preparse with no default --- AUTHORS | 1 + changelog/9303.bugfix.rst | 2 ++ src/_pytest/config/argparsing.py | 5 +++++ testing/test_pluginmanager.py | 15 +++++++++++++++ 4 files changed, 23 insertions(+) create mode 100644 changelog/9303.bugfix.rst 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 = []