https://github.com/python/cpython/commit/6d644e4453a907710e11f6f6b6b8890c197370d6
commit: 6d644e4453a907710e11f6f6b6b8890c197370d6
branch: main
author: Alex Prengère <[email protected]>
committer: savannahostrowski <[email protected]>
date: 2025-12-12T16:58:12Z
summary:

gh-141939: Add colors to interpolated values in argparse (#141940)

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Savannah Ostrowski <[email protected]>

files:
A Misc/NEWS.d/next/Library/2025-11-28-08-25-19.gh-issue-141939.BXPnFj.rst
M Lib/_colorize.py
M Lib/argparse.py
M Lib/test/test_argparse.py

diff --git a/Lib/_colorize.py b/Lib/_colorize.py
index 29d7cc67b6e39d..0b7047620b4556 100644
--- a/Lib/_colorize.py
+++ b/Lib/_colorize.py
@@ -169,7 +169,7 @@ class Argparse(ThemeSection):
     label: str = ANSIColors.BOLD_YELLOW
     action: str = ANSIColors.BOLD_GREEN
     default: str = ANSIColors.GREY
-    default_value: str = ANSIColors.YELLOW
+    interpolated_value: str = ANSIColors.YELLOW
     reset: str = ANSIColors.RESET
     error: str = ANSIColors.BOLD_MAGENTA
     warning: str = ANSIColors.BOLD_YELLOW
diff --git a/Lib/argparse.py b/Lib/argparse.py
index ed98aa9e974b2a..ee7ebc4696a0f7 100644
--- a/Lib/argparse.py
+++ b/Lib/argparse.py
@@ -668,6 +668,10 @@ def _expand_help(self, action):
                 params[name] = value.__name__
         if params.get('choices') is not None:
             params['choices'] = ', '.join(map(str, params['choices']))
+        # Before interpolating, wrap the values with color codes
+        t = self._theme
+        for name, value in params.items():
+            params[name] = f"{t.interpolated_value}{value}{t.reset}"
         return help_string % params
 
     def _iter_indented_subactions(self, action):
@@ -749,8 +753,8 @@ def _get_help_string(self, action):
                 default_str = _(" (default: %(default)s)")
                 prefix, suffix = default_str.split("%(default)s")
                 help += (
-                    f" {t.default}{prefix.lstrip()}"
-                    f"{t.default_value}%(default)s"
+                    f" {t.default}{prefix.lstrip()}{t.reset}"
+                    f"%(default)s"
                     f"{t.default}{suffix}{t.reset}"
                 )
         return help
diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py
index 24e8ab1c5cacbb..0f93e8ea740770 100644
--- a/Lib/test/test_argparse.py
+++ b/Lib/test/test_argparse.py
@@ -7308,6 +7308,13 @@ def test_argparse_color(self):
             choices=("Aaaaa", "Bbbbb", "Ccccc", "Ddddd"),
             help="pick one",
         )
+        parser.add_argument(
+            "--optional8",
+            default="A",
+            metavar="X",
+            choices=("A", "B", "C"),
+            help="among %(choices)s, default is %(default)s",
+        )
 
         parser.add_argument("+f")
         parser.add_argument("++bar")
@@ -7334,7 +7341,7 @@ def test_argparse_color(self):
         label_b = self.theme.label
         pos_b = self.theme.action
         default = self.theme.default
-        default_value = self.theme.default_value
+        interp = self.theme.interpolated_value
         reset = self.theme.reset
 
         # Act
@@ -7347,8 +7354,8 @@ def test_argparse_color(self):
                 f"""\
                 {heading}usage: {reset}{prog}PROG{reset} [{short}-h{reset}] 
[{short}-v{reset} | {short}-q{reset}] [{short}-o{reset}] [{long}--optional2 
{label}OPTIONAL2{reset}] [{long}--optional3 {label}{{X,Y,Z}}{reset}]
                             [{long}--optional4 {label}{{X,Y,Z}}{reset}] 
[{long}--optional5 {label}{{X,Y,Z}}{reset}] [{long}--optional6 
{label}{{X,Y,Z}}{reset}]
-                            [{short}-p 
{label}{{Aaaaa,Bbbbb,Ccccc,Ddddd}}{reset}] [{short}+f {label}F{reset}] 
[{long}++bar {label}BAR{reset}] [{long}-+baz {label}BAZ{reset}]
-                            [{short}-c {label}COUNT{reset}]
+                            [{short}-p 
{label}{{Aaaaa,Bbbbb,Ccccc,Ddddd}}{reset}] [{long}--optional8 {label}X{reset}] 
[{short}+f {label}F{reset}] [{long}++bar {label}BAR{reset}]
+                            [{long}-+baz {label}BAZ{reset}] [{short}-c 
{label}COUNT{reset}]
                             {pos}x{reset} {pos}y{reset} 
{pos}this_indeed_is_a_very_long_action_name{reset} {pos}{{sub1,sub2}} ...{reset}
 
                 Colorful help
@@ -7361,17 +7368,18 @@ def test_argparse_color(self):
 
                 {heading}options:{reset}
                   {short_b}-h{reset}, {long_b}--help{reset}            show 
this help message and exit
-                  {short_b}-v{reset}, {long_b}--verbose{reset}         more 
spam {default}(default: {default_value}False{default}){reset}
-                  {short_b}-q{reset}, {long_b}--quiet{reset}           less 
spam {default}(default: {default_value}False{default}){reset}
+                  {short_b}-v{reset}, {long_b}--verbose{reset}         more 
spam {default}(default: {reset}{interp}False{reset}{default}){reset}
+                  {short_b}-q{reset}, {long_b}--quiet{reset}           less 
spam {default}(default: {reset}{interp}False{reset}{default}){reset}
                   {short_b}-o{reset}, {long_b}--optional1{reset}
                   {long_b}--optional2{reset} {label_b}OPTIONAL2{reset}
-                                        pick one {default}(default: 
{default_value}None{default}){reset}
+                                        pick one {default}(default: 
{reset}{interp}None{reset}{default}){reset}
                   {long_b}--optional3{reset} {label_b}{{X,Y,Z}}{reset}
-                  {long_b}--optional4{reset} {label_b}{{X,Y,Z}}{reset}   pick 
one {default}(default: {default_value}None{default}){reset}
-                  {long_b}--optional5{reset} {label_b}{{X,Y,Z}}{reset}   pick 
one {default}(default: {default_value}None{default}){reset}
-                  {long_b}--optional6{reset} {label_b}{{X,Y,Z}}{reset}   pick 
one {default}(default: {default_value}None{default}){reset}
+                  {long_b}--optional4{reset} {label_b}{{X,Y,Z}}{reset}   pick 
one {default}(default: {reset}{interp}None{reset}{default}){reset}
+                  {long_b}--optional5{reset} {label_b}{{X,Y,Z}}{reset}   pick 
one {default}(default: {reset}{interp}None{reset}{default}){reset}
+                  {long_b}--optional6{reset} {label_b}{{X,Y,Z}}{reset}   pick 
one {default}(default: {reset}{interp}None{reset}{default}){reset}
                   {short_b}-p{reset}, {long_b}--optional7{reset} 
{label_b}{{Aaaaa,Bbbbb,Ccccc,Ddddd}}{reset}
-                                        pick one {default}(default: 
{default_value}None{default}){reset}
+                                        pick one {default}(default: 
{reset}{interp}None{reset}{default}){reset}
+                  {long_b}--optional8{reset} {label_b}X{reset}         among 
{interp}A, B, C{reset}, default is {interp}A{reset}
                   {short_b}+f{reset} {label_b}F{reset}
                   {long_b}++bar{reset} {label_b}BAR{reset}
                   {long_b}-+baz{reset} {label_b}BAZ{reset}
diff --git 
a/Misc/NEWS.d/next/Library/2025-11-28-08-25-19.gh-issue-141939.BXPnFj.rst 
b/Misc/NEWS.d/next/Library/2025-11-28-08-25-19.gh-issue-141939.BXPnFj.rst
new file mode 100644
index 00000000000000..1015d90c501fd0
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-11-28-08-25-19.gh-issue-141939.BXPnFj.rst
@@ -0,0 +1 @@
+Add color to all interpolated values in :mod:`argparse` help, like 
``%(default)s`` or ``%(choices)s``. Patch by Alex Prengère.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to