Skip to content

Commit 40ca446

Browse files
authored
Updated monkey patch to match how CPython fixed the argparse bug. (#1662)
1 parent 26786be commit 40ca446

2 files changed

Lines changed: 16 additions & 7 deletions

File tree

cmd2/argparse_utils.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -371,21 +371,27 @@ def _validate_completion_callable(self: argparse.Action, value: Any) -> Any:
371371

372372
############################################################################################################
373373
# Workaround for Python 3.15.0b1 argparse bug
374-
# _ColorlessTheme.__getattr__ incorrectly returns "" for dunder methods, which breaks
374+
# _ColorlessTheme.__getattr__ incorrectly returns "" for non-public attributes, which breaks
375375
# protocols like copy.deepcopy().
376376
############################################################################################################
377377

378378
if sys.version_info >= (3, 15):
379379

380-
def _ColorlessTheme_getattr(_self: argparse._ColorlessTheme, name: str) -> Any: # noqa: N802
381-
"""Patched __getattr__ that allows dunder lookups to fail correctly."""
382-
if name.startswith("__") and name.endswith("__"):
380+
def _ColorlessTheme_getattr( # noqa: N802
381+
_self: argparse._ColorlessTheme, # type: ignore[name-defined]
382+
name: str,
383+
) -> Any:
384+
"""Patched __getattr__ that allows non-public lookups to fail correctly.
385+
386+
This matches the implementation in CPython for their next release.
387+
"""
388+
if name.startswith("_"):
383389
raise AttributeError(name)
384390
return ""
385391

386392
# If the bug still exists, then install the patch.
387-
if getattr(argparse._ColorlessTheme(), "__deepcopy__", None) == "":
388-
argparse._ColorlessTheme.__getattr__ = _ColorlessTheme_getattr
393+
if getattr(argparse._ColorlessTheme(), "__deepcopy__", None) == "": # type: ignore[attr-defined]
394+
argparse._ColorlessTheme.__getattr__ = _ColorlessTheme_getattr # type: ignore[attr-defined]
389395

390396

391397
############################################################################################################

tests/test_argparse_utils.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,9 @@ def test_colorless_theme_monkeypatch() -> None:
761761
# We can remove the patch function and this test.
762762
assert argparse._ColorlessTheme.__getattr__ == argparse_utils._ColorlessTheme_getattr
763763

764-
# Our patch raises an Attribute error for dunder attributes.
764+
# Our patch raises an Attribute error for non-public.
765+
with pytest.raises(AttributeError):
766+
getattr(argparse._ColorlessTheme(), "_fake") # noqa: B009
767+
765768
with pytest.raises(AttributeError):
766769
getattr(argparse._ColorlessTheme(), "__deepcopy__") # noqa: B009

0 commit comments

Comments
 (0)