Skip to content
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

argparse drops "|" when a positional, then a special "-" argument (order-sensitive), are defined in a mutually exclusive group #113008

Closed
keeeeymann opened this issue Dec 12, 2023 · 3 comments
Labels
3.14 new features, bugs and security fixes stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@keeeeymann
Copy link

keeeeymann commented Dec 12, 2023

Bug report

Bug description:

I'm defining a argparse parser that works like vim:

support a file as a positional:

vim file.py

or reading from stdin:

cat file.py | vim -

So I write a mutually exclusive group:

import argparse
ap = argparse.ArgumentParser(description="fake vim")
mg = ap.add_mutually_exclusive_group(required=True)
mg.add_argument("input", nargs="?")
mg.add_argument("-", dest="from_stdin", action="store_true")
args = ap.parse_args()

When I use "-h" to show the help message, the "|" in usage line is dropped, as if the 2 arguments are not mutually exclusive:

usage: fake_vim.py [-h] [-] [input]

However, if I swap the 2 add_argument lines in the source code:

import argparse
ap = argparse.ArgumentParser(description="fake vim")
mg = ap.add_mutually_exclusive_group(required=True)
mg.add_argument("-", dest="from_stdin", action="store_true")
mg.add_argument("input", nargs="?")
args = ap.parse_args()

It magically behaves correctly:

usage: fake_vim.py [-h] (- | input)

CPython versions tested on:

3.9, 3.11

Operating systems tested on:

Windows

Linked PRs

@keeeeymann keeeeymann added the type-bug An unexpected behavior, bug, or error label Dec 12, 2023
@Eclips4 Eclips4 added the stdlib Python modules in the Lib dir label Dec 12, 2023
@savannahostrowski
Copy link
Member

I can repro with 3.9, 3.10 and 3.11.

@hpaulj
Copy link

hpaulj commented Feb 14, 2024

two things

A mutually exclusive group can handle only one positional argument, and it should be the last one added to the group.. I don't recall if that's more a limitation in the testing or the usage. Usage formatting is know to be brittle, especially with regard to the MXGs.

A bare '-' dest is not encouraged. It may be possible, but usually should something like '-f', dash plus single character.

Usage formatting needs a complete rewrite - one of these days.

paytonward6 added a commit to paytonward6/cpython that referenced this issue Sep 24, 2024
@serhiy-storchaka
Copy link
Member

Fixed in 3.14. Not sure if it's worth doing the backport -- it's only a minor improvement to the help output, and there's already a known workaround.

As for the original example, I do not recommend to use option "-" to solve this problem. It would work weird if you have more than one positional arguments. It is easier to simply check the positional argument value after parsing:

args.from_stdin = (args.input == '-')

@serhiy-storchaka serhiy-storchaka added the 3.14 new features, bugs and security fixes label Sep 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.14 new features, bugs and security fixes stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
Projects
Status: Doc issues
Development

No branches or pull requests

5 participants