-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
Argparse incorrectly handles '--' as argument to option #58572
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
Comments
http://docs.python.org/library/argparse.html#arguments-containing tumbolandia:cpython maker$ python foo.py --test=-- foo The same is for single-dash arguments. tumbolandia:cpython maker$ python foo.py -t -- foo Obviously argparse should return an error in both cases. |
It does look like there's anomalous behavior here of some sort, but I'd expect --test=-- to result in test="--", myself, rather than an error. My intuition is that '--' would need to be preceded by a space to function as the 'end of options' marker. Because of that, I've never tried the above scenario with a unix command, so maybe my intuition is wrong :) Just for reference (the code paths may be different), there is another open issue about -- parsing, bpo-13922. |
I just tried this with grep's "-e" and "--regexp": $ cat > temp.txt
a--b
cdef
$ grep -e-- -v temp.txt
cdef
$ grep --regexp=-- -v temp.txt
cdef
$ grep -e -- -v temp.txt
cdef
$ grep --regexp -- -v temp.txt
cdef And with diff's "-I" and "--ignore-matching-lines": $ cat > temp2.txt
cdef
a--b
$ diff temp.txt temp2.txt
1d0
< a--b
2a2
> a--b
$ diff -I-- temp.txt temp2.txt
$ diff -I -- temp.txt temp2.txt
$ diff --ignore-matching-lines -- temp.txt temp2.txt
$ diff --ignore-matching-lines=-- temp.txt temp2.txt
$ Note though that for options that don't take an argument, the "--" is just removed: $ grep -v -- a temp.txt
cdef
$ diff -i -- temp.txt temp2.txt
1d0
< a--b
2a2
> a--b So I guess the unix rule is: if an option that takes an argument is followed by "--", use that as the option's argument and continue parsing as usual. If an option that takes no argument is followed by "--", then delete the "--" and treat all following flags as positional arguments. Argparse can't follow this directly, because then people who are using "--" to signal the end of an option with nargs="*" would start getting "--" included in that list. (And I know people have used "--" this way for a while.) I guess my preference is what R. David Murray suggests: "--" when part of an argument (i.e. not separated by spaces) is treated like any other characters, and only a lone "--" signals the end of options (and is ignored otherwise). That would mean that both "--test=--" and "-t--" in your example would give you ["--"], and the other errors would stay as you saw them. |
+1 also for me. |
@michele could you provide a patch for this? |
The patch that I recently submitted for http://bugs.python.org/issue13922 With: parser = argparse.ArgumentParser()
parser.add_argument('-f','--foo')
print(parser.parse_args(['-f--']))
print(parser.parse_args(['--foo=--']))
print(parser.parse_args(['-f', '--'])) I get: Namespace(foo='--')
Namespace(foo='--')
usage: foodash.py [-h] [-f FOO]
foodash.py: error: argument -f/--foo: expected one argument |
wow, I was just writing the unittests, thanks paul. |
Yes, http://bugs.python.org/file29845/dbldash.patch seems to fix this. |
In Python 3.5, this does not seem fixed. bpo-13922 is marked as resolved and fixed, but Pauls’s patch has not actually been committed. >>> ap = ArgumentParser()
>>> ap.add_argument("-t", "--test", type=str, nargs=1)
_StoreAction(option_strings=['-t', '--test'], dest='test', nargs=1, const=None, default=None, type=<class 'str'>, choices=None, help=None, metavar=None)
>>> ap.add_argument('yuri', nargs='?')
_StoreAction(option_strings=[], dest='yuri', nargs='?', const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> ap.parse_args(["--test=--", "foo"])
Namespace(test=[], yuri='foo')
>>> ap.parse_args(["--test", "--", "foo"])
usage: [-h] [-t TEST] [yuri]
: error: argument -t/--test: expected 1 argument
argparse.ArgumentError: argument -t/--test: expected 1 argument
During handling of the above exception, another exception occurred:
__main__.SystemExit: 2
>>> ap.parse_args(["-t--", "foo"])
Namespace(test=[], yuri='foo')
>>> ap.parse_args(["-t", "--", "foo"])
usage: [-h] [-t TEST] [yuri]
: error: argument -t/--test: expected 1 argument
argparse.ArgumentError: argument -t/--test: expected 1 argument
During handling of the above exception, another exception occurred: __main__.SystemExit: 2 |
I made a mistake of trying to add to or refine a closed patch. Maybe I need to move the dbldash.patch over here for more formal consideration. |
I've copied 'dbldash.patch' over from http://bugs.python.org/issue13922. I mistakenly added it to a closed issue. The patch is old, and should be revised. It is also missing tests for this '--opt=--' case, even though it solves it. I also reference this patch in http://bugs.python.org/issue9571, which tries to refine dbldash handling for PARSER, REMAINDER nargs. I'm raising the priority on this because the issue has a come up a couple of times on Stackoverflow: http://stackoverflow.com/questions/40685320/python-argparse-with-as-the-value |
some test cases which paul provided looks doesn't keep compatible. In TestDoubleDashRemoval: # output in my env is Namespace(cmd='--', foo='1', rest=['1', '2']) # output in my env is Namespace(cmd='--foo', foo=None, rest=['--bar', '2']) # output in my env is Namespace(cmd='cmd', foo=None, rest=['--foo', '-f2']) In TestDoubleDashRemoval1: my python's version is: 2.7.5, 3.6.8 |
Since I have been adversely affected by this bug (1), I looked at the patches. I combined bpo-14364.test.patch (which adds test cases for --foo=--) and dbldash.patch in my local working tree and that seems to resolve the issue (tests pass if and only if I apply dbldash.patch and my reproducer from 1) passes too). The patches do not contain any type of metainformation, so I’m not comfortable with submitting this as a PR. I am also not at all familiar with the process of managing the changelog etc. This should serve as a confirmation that this issue can be resolved with the patches. Someone more familiar than me with the process could take up the task to get this merged. Note: As you can see in 1, this issue has already caused data loss. |
Hi, Jonas. Thanks for your report. |
Paul and David, is the current PR complete in your opinion? Are there known cases where the PR would break existing, working code? Also there needs to be doc entry that is clear on both new and old strategy for distinguishing options from arguments when a dash or dashdash is present. The PR's Misc/NEWS entry, "Fix behavior of argparse when '--' as argument to option", is insufficient. |
Thanks for your comment, Raymond. I would continue update the desc. |
Unassigning because I haven't been able to make time for this one. |
I expect this is now fixed for 3.11+ via #109475 |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: