Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/14773.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed a crash in ``Argument.dest`` when accessing an option with an invalid option string (for example, one that starts with a digit). Previously, this would raise an ``AttributeError`` because the underlying ``argparse.Action`` may not have a ``dest`` attribute when initialization fails.
2 changes: 1 addition & 1 deletion src/_pytest/config/argparsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ def names(self) -> Sequence[str]:

@property
def dest(self) -> str:
return self._action.dest
return getattr(self._action, "dest", "<missing>")

@property
def default(self) -> Any:
Expand Down
15 changes: 15 additions & 0 deletions testing/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2487,6 +2487,21 @@ def test_help_formatter_uses_py_get_terminal_width(monkeypatch: MonkeyPatch) ->
assert formatter._width == 42


def test_argument_dest_does_not_crash_on_invalid_option() -> None:
"""``Argument.dest`` should not raise ``AttributeError`` when accessed on an
Action that failed to initialize (e.g. with an invalid option string)."""
from _pytest.config.argparsing import Argument

# Simulate the crash path: an option name that fails _set_opt_strings
# may result in an Action without a `dest` attribute.
class BrokenAction:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i need a p practical example of this failure - i never saw this in the wild

pass

action = BrokenAction()
arg = Argument(action) # type: ignore[arg-type]
assert arg.dest == "<missing>"


def test_config_does_not_load_blocked_plugin_from_args(pytester: Pytester) -> None:
"""This tests that pytest's config setup handles "-p no:X"."""
p = pytester.makepyfile("def test(capfd): pass")
Expand Down