Skip to content

gh-130645: Add colour to argparse help #132323

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 2, 2025

Conversation

hugovk
Copy link
Member

@hugovk hugovk commented Apr 9, 2025

Add color parameter to argparse.ArgumentParser, which by default is False. When set to True, the help text is in colour if allowed (for example, we're not piping, NO_COLOR=1 is not set).

Example output

Using this script:

import argparse

parser = argparse.ArgumentParser(
    description="calculate X to the power of Y",
    formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    prefix_chars="-+",
    prog="PROG",
)
parser.color = True
group = parser.add_mutually_exclusive_group()
group.add_argument("-v", "--verbose", action="store_true", help="more spam")
group.add_argument("-q", "--quiet", action="store_true", help="less spam")
parser.add_argument("x", type=int, help="the base")
parser.add_argument("y", type=int, help="the exponent", deprecated=True)
parser.add_argument(
    "this_indeed_is_a_very_long_action_name", type=int, help="the exponent"
)
parser.add_argument("-o", "--optional1", action="store_true", deprecated=True)
parser.add_argument("--optional2", help="pick one")
parser.add_argument("--optional3", choices=("X", "Y", "Z"))
parser.add_argument("--optional4", choices=("X", "Y", "Z"), help="pick one")
parser.add_argument("--optional5", choices=("X", "Y", "Z"), help="pick one")
parser.add_argument("--optional6", choices=("X", "Y", "Z"), help="pick one")
parser.add_argument(
    "-p", "--optional7", choices=("Aaaaa", "Bbbbb", "Ccccc", "Ddddd"), help="pick one"
)

parser.add_argument("+f")
parser.add_argument("++bar")
parser.add_argument("-+baz")
parser.add_argument("-c", "--count")

subparsers = parser.add_subparsers(
    title="subcommands", description="valid subcommands", help="additional help"
)
subparsers.add_parser("sub1", deprecated=True, help="sub1 help")
sub2 = subparsers.add_parser("sub2", deprecated=True, help="sub2 help")
sub2.add_argument("--baz", choices=("X", "Y", "Z"), help="baz help")

args = parser.parse_args()
image

Performance

With the same script and PGO+LTO on macOS, running it once (time ./python.exe argparse-cli.py --help) and 100 times (time ./100.sh):

# 100.sh
for i in $(seq 1 100); do
    ./python.exe argparse-cli.py -h
done

main (3feac7a):

./python.exe argparse-cli.py --help  0.03s user 0.01s system 88% cpu 0.046 total
./100.sh  1.51s user 0.39s system 93% cpu 2.041 total

PR and colour not enabled:

./python.exe argparse-cli.py --help  0.02s user 0.02s system 58% cpu 0.072 total
./100.sh  1.52s user 0.40s system 92% cpu 2.070 total

PR and colour enabled:

./python.exe argparse-cli.py --help  0.04s user 0.02s system 70% cpu 0.080 total
./100.sh  1.57s user 0.40s system 93% cpu 2.106 total

Something like 0.65 ms difference per run between before and after, averaging from 100.sh.


📚 Documentation preview 📚: https://cpython-previews--132323.org.readthedocs.build/

@hugovk hugovk added the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Apr 9, 2025
@bedevere-bot
Copy link

🤖 New build scheduled with the buildbot fleet by @hugovk for commit 3d174b7 🤖

Results will be shown at:

https://buildbot.python.org/all/#/grid?branch=refs%2Fpull%2F132323%2Fmerge

If you want to schedule another build, you need to add the 🔨 test-with-buildbots label again.

@bedevere-bot bedevere-bot removed the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Apr 9, 2025
@hugovk hugovk added type-feature A feature request or enhancement stdlib Python modules in the Lib dir labels Apr 9, 2025
@hugovk hugovk marked this pull request as ready for review April 9, 2025 18:12
@python-cla-bot
Copy link

python-cla-bot bot commented Apr 18, 2025

All commit authors signed the Contributor License Agreement.

CLA signed

@bedevere-app
Copy link

bedevere-app bot commented Apr 21, 2025

When you're done making the requested changes, leave the comment: I have made the requested changes; please review again.

Copy link
Member

@savannahostrowski savannahostrowski left a comment

Choose a reason for hiding this comment

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

A comment about the approach and whether we can simplify a bit.

@hugovk
Copy link
Member Author

hugovk commented Apr 30, 2025

ArgumentParser() has a lot of parameters, color is its 16th.

Many argparse CLIs I see already use keywords for most parameters, but I think we should make these new ones keyword-only, especially for new bools, as a long list of (..., True, False, True, ...) is best avoided.

suggest_on_error was added in 3.14, I suggest we also make that keyword-only (in another PR).

What do you think?

@ambv ambv dismissed savannahostrowski’s stale review May 2, 2025 13:03

Commandeering this to make the beta 1 cut. Code owner's feedback can be addressed in follow-up PRs.

@ambv ambv merged commit 4701ff9 into python:main May 2, 2025
51 of 52 checks passed
@hugovk hugovk deleted the 3.14-argparse-colour-help branch May 2, 2025 13:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stdlib Python modules in the Lib dir type-feature A feature request or enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants