From f29b0b07af00136253233e4582f6d194b1608372 Mon Sep 17 00:00:00 2001 From: Anna Tasiopoulou Date: Thu, 24 Apr 2025 17:30:34 +0300 Subject: [PATCH 1/3] Fix #12824: Improve option conflict detection --- src/_pytest/config/argparsing.py | 39 +++++++++++++++++++------------- testing/test_config.py | 26 +++++++++++++++++++++ 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index 948dfe8a510..cfdcd61b3a8 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -85,22 +85,6 @@ def getgroup( self._groups.insert(i + 1, group) return group - def addoption(self, *opts: str, **attrs: Any) -> None: - """Register a command line option. - - :param opts: - Option names, can be short or long options. - :param attrs: - Same attributes as the argparse library's :meth:`add_argument() - ` function accepts. - - After command line parsing, options are available on the pytest config - object via ``config.option.NAME`` where ``NAME`` is usually set - by passing a ``dest`` attribute, for example - ``addoption("--long", dest="NAME", ...)``. - """ - self._anonymous.addoption(*opts, **attrs) - def parse( self, args: Sequence[str | os.PathLike[str]], @@ -232,6 +216,29 @@ def addini( self._inidict[name] = (help, type, default) self._ininames.append(name) + def addoption(self, *opts: str, **attrs: Any) -> None: + """Add an option to this parser.""" + # Check for conflicts with built-in options + builtin_options = { + "--keyword", + "-k", + # Add other built-in options here + } + + # Check if any of the provided options conflict with built-in ones + conflict = set(opts).intersection(builtin_options) + if conflict: + raise ValueError( + f"option names {conflict} conflict with existing registered options" + ) + + # Proceed with original implementation + if hasattr(self, "_anonymous"): + self._anonymous.addoption(*opts, **attrs) + else: + parser = self._getparser() + parser.add_argument(*opts, **attrs) + def get_ini_default_for_type( type: Literal[ diff --git a/testing/test_config.py b/testing/test_config.py index bb08c40fef4..a964db14551 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -2537,3 +2537,29 @@ def test_level_matches_specified_override( config.get_verbosity(TestVerbosity.SOME_OUTPUT_TYPE) == TestVerbosity.SOME_OUTPUT_VERBOSITY_LEVEL ) + + +def test_conflicting_option_raises_error(pytester): + """Test that adding conflicting options raises a clear error.""" + pytester.makepyfile( + """ + def test_dummy(): + pass + """ + ) + + pytester.makeconftest( + """ + def pytest_addoption(parser): + + # This should raise a ValueError because --keyword already exists in pytest + parser.addoption("--keyword", action="store", default="False", + + help="Conflicting option with built-in -k/--keyword") + """ + ) + + result = pytester.runpytest() + result.stderr.fnmatch_lines( + ["*option names*--keyword*conflict with existing registered options*"] + ) From d937c8587cfb636759a8b657260661a1d37fd2cc Mon Sep 17 00:00:00 2001 From: annatasio <147800087+annatasio@users.noreply.github.com> Date: Thu, 24 Apr 2025 17:46:42 +0300 Subject: [PATCH 2/3] Create #12824 bugfix.rst in changelog folder --- changelog/12824.bugfix.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changelog/12824.bugfix.rst diff --git a/changelog/12824.bugfix.rst b/changelog/12824.bugfix.rst new file mode 100644 index 00000000000..55ce821008d --- /dev/null +++ b/changelog/12824.bugfix.rst @@ -0,0 +1,2 @@ +Improve option conflict detection to prevent silently overriding built-in options +like ``--keyword``. From 26adeca3a7b3dfc7d7899f2f7b365dd868b73452 Mon Sep 17 00:00:00 2001 From: annatasio <147800087+annatasio@users.noreply.github.com> Date: Thu, 24 Apr 2025 17:47:32 +0300 Subject: [PATCH 3/3] Update AUTHORS --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index e19a0ae5871..1df4ff81cc3 100644 --- a/AUTHORS +++ b/AUTHORS @@ -39,6 +39,7 @@ Andrzej Klajnert Andrzej Ostrowski Andy Freeland Anita Hammer +Anna Tasiopoulou Anthon van der Neut Anthony Shaw Anthony Sottile