This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: argparse BooleanOptionalAction displays default=SUPPRESS unlike other action types
Type: behavior Stage: patch review
Components: Library (Lib) Versions: Python 3.11
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: a.badger, lukasz.langa, mhils, paul.j3, rhettinger
Priority: normal Keywords: patch

Created on 2021-07-09 05:07 by a.badger, last changed 2022-04-11 14:59 by admin.

Pull Requests
URL Status Linked Edit
PR 27672 mhils, 2021-08-16 23:09
PR 27808 open a.badger, 2021-08-18 05:20
Messages (4)
msg397184 - (view) Author: Toshio Kuratomi (a.badger) * Date: 2021-07-09 05:07
This is related to https://bugs.python.org/issue38956 but a different symptom (and the current proposed fix for 38956 will not fix this.  My proposed fixes for this would also fix 38956).

I have the following code which uses BooleanOptionalAction along with a default of SUPPRESS (I use SUPPRESS because I merge these with settings from config and environment variables and then validate and add default values using a schema.  SUPPRESS allows me to tell when a value was not specified at the command line by the user):

    whole_site_parser.add_argument('--indexes',    
                                   dest='indexes', action=BooleanOptionalAction,    
                                   default=argparse.SUPPRESS,    
                                   help='Test')


That code outputs:

  --indexes, --no-indexes
                        Test (default: ==SUPPRESS==)

Similar code that does not use BooleanOptionalAction does not show default: ==SUPPRESS == even when formatter_class=ArgumentDefaultsHelpFormatter is used.

Looking at the code, this is occurring because BooleanOptionalArgument has its own code to add default: on its own (instead of leaving formatting as the responsibility of the formatter_class). The code in BooleanOptionalArgument handles less cases where the default should be skipped than the ArgumentDefaultsHelpFormatter code; SUPPRESS is one of the missing cases.

I can see two ways of fixing this:

(1) Remove the code from BooleanOptionalArgument that adds the default values.  It seems to violate the architecture of argparse which delegates modifications to the help message to the formatter_class so this is a special case which could cause issues for future modifications as well.

(2) If the usefulness of outputting the default values without changing the formatter_class is deemed too important to relinquish, then moving the code that ArgumentDefaultsHelpFormatter uses to determine when to skip adding default to the help message can be extracted from ArgumentDefaultsHelpFormatter and called by both ArgumentDefaultsHelpFormatter and BooleanOptionalArgument .

In a review of a fix for https://github.com/python/cpython/pull/17447/files#r429630944 raymond hettinger thought that outputting of the default values was important to keep although I'm not clear on whether he considered that the usefulness comes at the price of possibly violating argparse's architecture.  If he hasn't changed his mind, then #2 is probably the way to resolve this.

I can submit a PR for either of these once I know which direction to take (the first is just removing a few lines of code and I've already written the second one since it seemed like the direction that raymond had last asked for).

Please let me know how you'd like me to proceed.
msg399730 - (view) Author: Łukasz Langa (lukasz.langa) * (Python committer) Date: 2021-08-17 10:04
Toshio, as I commented on GH-27672, that PR was merged because it's a rather trivial improvement over the status quo. I intend to also release this fix in 3.9.7 on August 30th.

Your idea in this issue to further improve the situation while retaining displaying the default value (option 2 described above) is interesting. If you prepare a PR we can work with, I'll look into merging that as well.
msg399731 - (view) Author: Łukasz Langa (lukasz.langa) * (Python committer) Date: 2021-08-17 10:07
Oh, I forgot to say this explicitly: an important reason why the trivial fix was desirable is that it was a clear-cut bugfix, making it easy to backport all the way to the 3.9 branch where BooleanOptionalAction was introduced.

Having this in place, your potential PR here might be a cleaner refactor without having to worry about backporting. Of course, if we manage to keep it small and isolated, we can bring it to 3.9 and 3.10 as well.
msg399822 - (view) Author: Toshio Kuratomi (a.badger) * Date: 2021-08-18 05:26
PR Opened.

A fix for this should be backported as well.  However, if you decide you don't want the refactor backported, you can merely continue to change the condition inside of BooleanOptionalAction to repeat all of the same checks as are contained in the older versions' ArgumentDefaultsHelpFormatter.
History
Date User Action Args
2022-04-11 14:59:47adminsetgithub: 88753
2021-09-03 01:01:18paul.j3setnosy: + paul.j3
2021-08-18 05:26:33a.badgersetmessages: + msg399822
2021-08-18 05:20:47a.badgersetpull_requests: + pull_request26275
2021-08-17 10:07:36lukasz.langasetmessages: + msg399731
versions: + Python 3.11, - Python 3.9, Python 3.10
2021-08-17 10:04:48lukasz.langasetnosy: + lukasz.langa
messages: + msg399730
2021-08-16 23:09:12mhilssetkeywords: + patch
nosy: + mhils

pull_requests: + pull_request26259
stage: patch review
2021-07-10 01:41:27ned.deilysetnosy: + rhettinger

title: BooleanOptionalAction displays default=SUPPRESS unlike other action types -> argparse BooleanOptionalAction displays default=SUPPRESS unlike other action types
2021-07-09 17:04:13jacobtylerwallssettype: behavior
components: + Library (Lib)
2021-07-09 05:07:37a.badgercreate