classification
Title: Add FlagAction to argparse
Type: enhancement Stage: resolved
Components: Library (Lib) Versions: Python 3.9
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: Jeremiah.Jordan, Ken Williams, berker.peksag, bethard, eric.araujo, eric.smith, matrixise, paul.j3, remi.lapeyre, vstinner, wolma
Priority: normal Keywords: easy, patch, patch, patch

Created on 2010-04-26 17:38 by eric.smith, last changed 2019-09-13 10:19 by matrixise. This issue is now closed.

Files
File name Uploaded Description Edit
argparse_bool.py eric.smith, 2010-04-26 17:38
Pull Requests
URL Status Linked Edit
PR 11478 merged remi.lapeyre, 2019-01-09 15:20
PR 11478 merged remi.lapeyre, 2019-01-09 15:20
PR 11478 merged remi.lapeyre, 2019-01-09 15:20
Messages (19)
msg104259 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2010-04-26 17:38
From a python-dev email from Neal Becker, copied here so it won't get lost.
----------------------------
steven.bethard@gmail.com made a very nice module for me to enhance argparse called argparse_bool.py, which contains ConfigureAction.  This will allow a boolean value to be set very like the gnu configure style:

--foo
--with-foo
--without-foo
--no-foo
--foo=yes
--foo=no

I've been happily using it, and I think it would be of sufficient general interest to include it with the standard library.
msg105032 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2010-05-05 13:57
Are we sure we want three or four ways to spell the same thing? --foo and --no-foo seem a useful couple to me, and --with-foo/--without-foo cater to different use cases. Perhaps it would be ok to have a SwitchAction (or FlagAction) for --thing/--no-hing and one ConfigureAction for the --with[out]-* style.
msg105620 - (view) Author: Yaniv Aknin (Yaniv.Aknin) Date: 2010-05-13 01:01
I'm looking into making a patch from this for py3k, and have the following observations:

1. I agree with merwok, at the moment the monolithic ConfigureAction is a bit excessive for most uses (other than maybe emulating ./Configure...). I vote we split it to FlagAction and ConfigureAction.
2. I don't think this should be added as an argparse builtin/registered action (like action='store' or action='count'), but rather as a ready-made user-action in a separate namespace (from argparse.actions import FlagAction)

Given feedback that these two decisions seem sane, I'd be happy to produce a patch against recent py3k.
msg107758 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2010-06-13 22:08
I think you can go ahead and produce a patch. Don’t start splitting argparse into a package now though, this is a sensible decision IMO but has to be agreed by the maintainer; just add FlagAction and ConfigureAction to argparse for now.
msg110610 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2010-07-17 22:41
Some useful tips to make patches: http://www.python.org/dev/patches/
msg113479 - (view) Author: Jeremiah Jordan (Jeremiah.Jordan) Date: 2010-08-09 21:28
I think this should be updated so that nargs=0 is allowed, so that you can only do --foo/--no-foo and don't clutter up the help/interface with --foo [FOO] --no-foo=[FOO]

You can do this by adding nargs to the ConfigureAction.__init__ and passing that through to super, and then updating __call__ to check 'if value is None or value == []:' instead of the None.
msg121530 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2010-11-19 15:16
I think FlagAction should implement strictly boolean options, that is --foo and --no-foo, without arguments at all.

For ConfigureAction, there is a precedent (unless I’m mistaken) in configure, which permits such things:
  --without-unicode
  --with-unicode=ucs4
  --with-unicode (uses default value for arg)

I say we focus on the simple FlagAction for this bug and keep ConfigureAction for another patch.

Yaniv: Can you give us a status update?
msg166165 - (view) Author: Steven Bethard (bethard) * (Python committer) Date: 2012-07-22 20:08
On the off chance that someone was waiting for feedback from me, I'll say:

(1) A simple boolean --foo/--no-foo action seems useful to me. I would probably call it BooleanOptionalAction rather than FlagAction. (Almost anything could be considered a "flag".)

(2) At the moment, argparse doesn't supply any actions, so I don't think we should make a separate namespace for them. If it starts to grow a list of such actions, we can add a separate namespace later. (And given that the name will end with "Action", I think it should be pretty clear without the namespace.)
msg270269 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2016-07-12 22:06
I'm sorry but there is no activity since 4 years, so I guess that the feature is not common enough to require a builtin support in argparse.
msg332621 - (view) Author: Ken Williams (Ken Williams) * Date: 2018-12-27 21:22
@vstinner - I don't think that conclusion is correct, here is a very highly-upvoted answer on SO that indicates a lot of people are still looking for this:

https://stackoverflow.com/a/15008806/169947

I myself asked a related (more focused?) question where I was directed here:

https://stackoverflow.com/q/53937481/169947

I'm guessing the right thing to do now would be refocus the merge request in a new ticket - is this still the right tracker?
msg332625 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2018-12-27 22:34
Let me highlight something about

https://stackoverflow.com/a/15008806/169947

The original question was how to implement an Action that accepts 'True' or 'False' as an argument.  Users often try `type=bool`, which doesn't work because of the normal behavior of the Python bool(astr) function.  That's been the subject of several other bug/issues.

https://bugs.python.org/issue14392
https://bugs.python.org/issue26994
https://bugs.python.org/issue24754
https://bugs.python.org/issue21208

My answer in that SO question is

https://stackoverflow.com/a/19233287/901925

----

@mgilson's answer proposes a '--foo', '--no-foo' alternative.  That is in line with this bug/issue.

    parser.add_argument('--feature', dest='feature', action='store_true')
    parser.add_argument('--no-feature', dest='feature', action='store_false')
    parser.set_defaults(feature=True)

So the question here is whether mgilson's simple answer is enough, or do we need to add Eric's ConfigureAction class?  

On a casual reading the patch proposed here shouldn't have backward compatibility issues, since it is an addon class, and doesn't modify existing classes.  But it lacks tests and documentation.  

Documentation for argparse is a tough issue.  While advanced users want more features and more documented details, most of the SO questions come from beginners, who's eyes glaze over when they read the existing documentation.
msg332627 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2018-12-27 23:19
Yes, this is the correct bug tracker.

And note that this code isn't mine, I just posted it here so it wouldn't be lost. It looks like the original message was from https://mail.python.org/pipermail/python-dev/2010-April/099704.html
msg332628 - (view) Author: Ken Williams (Ken Williams) * Date: 2018-12-28 00:04
Thanks, Paul and Eric, for your very quick replies.

You're quite correct, the original question in https://stackoverflow.com/a/15008806/169947 is indeed hoping for `--foo TRUE` and `--foo False` etc. to work.  Personally I don't like that as much as the GNU-style `--foo` and `--no-foo` technique, because when you let people type `TRUE` or `True` or `T` or `1`, etc., it gets a bit confusing about exactly what is accepted as a true value, what's false, is a zero interpreted as 0 or "0", whether a failure to parse the value as True or False will be reported as an error or not, and so on.  The user typically can't really know these answers without reading the actual code, or running it to see what generates an error (or triggers whatever behavior they're looking for), which is certainly not ideal.

By contrast, with `--foo` and `--no-foo`, the options are strict and clear.  And supplying an argument will trigger a parse failure.

For @mgilson's proposal, I think the main thing I find unsatisfactory (besides the fact that it takes 3 lines to define, and I'll have to come back to that SO answer every time to make sure I get them right...) is that the `--help` output can't be made clear.  With the following specification:

    parser.add_argument('--foo', dest='foo', help="Do foo", action='store_true')
    parser.add_argument('--no-foo', dest='foo', help="Don't foo", action='store_false')
    parser.set_defaults(foo=True)

we get the following --help text (when using ArgumentDefaultsHelpFormatter):

    --foo       Do foo (default: True)
    --no-foo    Don't foo (default: True)

and that last line seems to be a contradiction, or at least very confusing.  The only alternative I see is to turn off ArgumentDefaultsHelpFormatter, but I think the defaults are generally helpful information for the user.

To fix that --help issue seems to require quite a bit more complicated registration of arguments, so it's probably not going to happen in most people's scripts.

I should be clear: I haven't vetted the `argparse_bool.py` proposal in detail either, so I'm not specifically asking for it to be adopted.  Just hoping for a nice resolution to the `--foo` `--no-foo` issue that codifies best-practices in a way that makes it trivial to get nice behavior in scripts.


As for documentation - I had poked around in the code a bit and seen the `register` method, but I thought since it wasn't documented, I'd better not use it.  Is it for public consumption?  If so, I'd say it's better documented than undocumented, even if it provides more info than most people need.  My guess is that enough people are probably using it to make it impossible to eliminate, which is a good test for whether something should be documented too.
msg333022 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-01-04 23:06
I reopen the issue since it seems like there are people requesting the feature. (I also removed myself from the issue, I'm not interested to implement it.)
msg333071 - (view) Author: Rémi Lapeyre (remi.lapeyre) * Date: 2019-01-05 19:32
> I also removed myself from the issue, I'm not interested to implement it.

I would like to try and implement the change. I will open a PR shortly.
msg333325 - (view) Author: Rémi Lapeyre (remi.lapeyre) * Date: 2019-01-09 15:40
I made a first proposal for this feature in PR 11478, I had to adapt argparse.Action to customize how the action is represented in the usage string by adding a format_usage() method that would default to the current behavior if not overridden.

Other methods to do this may be better but I did not find them.
msg352259 - (view) Author: Stéphane Wirtel (matrixise) * (Python committer) Date: 2019-09-13 09:37
I am also interested by this feature.
msg352277 - (view) Author: Stéphane Wirtel (matrixise) * (Python committer) Date: 2019-09-13 10:17
New changeset 6a517c674907c195660fa9178a7b561de49cc721 by Stéphane Wirtel (Rémi Lapeyre) in branch 'master':
bpo-8538: Add support for boolean actions to argparse (GH-11478)
https://github.com/python/cpython/commit/6a517c674907c195660fa9178a7b561de49cc721
msg352278 - (view) Author: Stéphane Wirtel (matrixise) * (Python committer) Date: 2019-09-13 10:19
I have merged the PR 11478 and this feature will be included into 3.9.

Thank you for your proposal of Remi and thank you to Eric for the idea of this feature.
History
Date User Action Args
2019-09-13 10:19:40matrixisesetstatus: open -> closed
messages: + msg352278

keywords: patch, patch, patch, easy
resolution: fixed
stage: patch review -> resolved
2019-09-13 10:17:46matrixisesetmessages: + msg352277
2019-09-13 09:37:55matrixisesetkeywords: patch, patch, patch, easy
nosy: + matrixise
messages: + msg352259

2019-09-13 09:20:56matrixisesetkeywords: patch, patch, patch, easy
versions: + Python 3.9, - Python 3.7, Python 3.8
2019-01-09 15:40:14remi.lapeyresetmessages: + msg333325
versions: + Python 3.7, Python 3.8, - Python 3.2
2019-01-09 15:20:44remi.lapeyresetkeywords: + patch
stage: needs patch -> patch review
pull_requests: + pull_request10989
2019-01-09 15:20:25remi.lapeyresetkeywords: + patch
stage: needs patch -> needs patch
pull_requests: + pull_request10988
2019-01-09 15:20:06remi.lapeyresetkeywords: + patch
stage: needs patch -> needs patch
pull_requests: + pull_request10987
2019-01-05 19:32:24remi.lapeyresetnosy: + remi.lapeyre
messages: + msg333071
2019-01-04 23:06:15vstinnersetstatus: closed -> open

messages: + msg333022
resolution: out of date -> (no value)
nosy: bethard, vstinner, eric.smith, eric.araujo, Jeremiah.Jordan, berker.peksag, paul.j3, wolma, Ken Williams
2018-12-28 00:04:25Ken Williamssetmessages: + msg332628
2018-12-27 23:19:19eric.smithsetmessages: + msg332627
2018-12-27 22:34:51paul.j3setmessages: + msg332625
2018-12-27 21:38:39Yaniv.Akninsetnosy: - Yaniv.Aknin
2018-12-27 21:22:40Ken Williamssetnosy: + Ken Williams
messages: + msg332621
2016-07-12 22:06:51vstinnersetstatus: open -> closed

nosy: + vstinner
messages: + msg270269

resolution: out of date
2016-06-21 03:01:39paul.j3setnosy: + paul.j3
2015-04-29 08:15:49wolmasetnosy: + wolma
2012-07-22 20:08:21bethardsetmessages: + msg166165
2011-12-12 01:30:50berker.peksagsetnosy: + berker.peksag
2010-11-19 15:16:15eric.araujosetkeywords: + easy

messages: + msg121530
title: Add ConfigureAction to argparse -> Add FlagAction to argparse
2010-08-09 21:28:40Jeremiah.Jordansetnosy: + Jeremiah.Jordan
messages: + msg113479
2010-07-17 22:41:11eric.araujosetmessages: + msg110610
2010-06-13 22:08:33eric.araujosetmessages: + msg107758
stage: needs patch
2010-05-13 01:01:20Yaniv.Akninsetmessages: + msg105620
2010-05-05 13:57:20eric.araujosetnosy: + eric.araujo
messages: + msg105032
2010-05-02 12:07:26Yaniv.Akninsetnosy: + Yaniv.Aknin
2010-04-26 18:52:52eric.smithsetpriority: normal
2010-04-26 17:38:05eric.smithcreate