[issue47002] argparse - "expected one argument" when used -: in argument
paul j3 added the comment: '-1' and '-1.23' are recognized as numbers, and treated as arguments. '-1' requires some special handling because it is allowed as a flag, as in parser.add_argument('-1','--one') '-1:00' on the other hand is no different from a string like '-foo'. Default is to parse it as a flag. If you don't get this error argument -f: expected one argument you are likely to get: error: unrecognized arguments: -1:23 This can probably be closed as a duplicate of: https://bugs.python.org/issue9334 argparse does not accept options taking arguments beginning with dash (regression from optparse) -- ___ Python tracker <https://bugs.python.org/issue47002> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue46228] argparse docs: default for prog= in ArgumentParser() should be basename of argv[0], not argv[0], to match behaviour
Change by paul j3 : -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue46228> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue46101] argparse: using parents & subcommands, options can be ignored
Change by paul j3 : -- resolution: -> rejected stage: patch review -> resolved status: open -> closed ___ Python tracker <https://bugs.python.org/issue46101> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue46080] argparse.BooleanOptionalAction with default=argparse.SUPPRESS and help specified raises exception
Change by paul j3 : -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue46080> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue46440] ArgumentParser.parse_args exits on missing required argument with exit_on_error=False
paul j3 added the comment: Duplicate of https://bugs.python.org/issue41255 Argparse.parse_args exits on unrecognized option with exit_on_error=False -- nosy: +paul.j3 resolution: -> duplicate stage: patch review -> resolved status: open -> closed ___ Python tracker <https://bugs.python.org/issue46440> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue46057] argparse: embedded groups may prevent options from being in help output
paul j3 added the comment: "I tried to create a group hierarchy in a way that I can pass the responsibility of argument validation to the argument parser." I looked at your example in: https://bugs.python.org/issue46058 The many levels of nesting groups was confusing, but now I realize that by nesting argument_groups in a mutually_exlusive_group you were try to implement some sort of any/all group within the xor group. This cannot be done within argparse. Mutually_exclusive only implements a flat xor. Argument_groups are used for help display, but play no role in parsing. Some years ago I explored the use of nest parsing groups: https://bugs.python.org/issue11588 Add "necessarily inclusive" groups to argparse I was trying to allow for nested groups that implemented all logical options - xor, or, and, not. Defining such groups wasn't hard. And I think I got the testing logic working right. But usage display required too big of a change to the formatter, and left too many loose ends. So I have let that languish. Now I recommend focusing on doing the testing after parsing. Use meaningful defaults where possible, and use `is None` to test whether a users has provided a value or not. -- ___ Python tracker <https://bugs.python.org/issue46057> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue46101] argparse: using parents & subcommands, options can be ignored
paul j3 added the comment: This patch should be rejected. By using `common_opts_parser` as parent to both the main and subparsers, you have defined the same argument in both. By a long standing patch, the value assigned in the subparser has precedence (whether it's the default or user supplied). https://bugs.python.org/issue9351 argparse set_defaults on subcommands should override top level set_defaults Partial retraction of this override has been explored, but any changes are still up for debate https://bugs.python.org/issue45235 argparse does not preserve namespace with subparser defaults The bottom line is that we should not try to define the same argument (or more specifically the same `dest`) in both main and subparsers. Duplicate flags are ok. But resolving the conflicting values should be done after parsing. Some users will want to give priority to the main parser's values, others to the subparser's. Or their own defaults. argparse cannot handle all cases cleanly. -- ___ Python tracker <https://bugs.python.org/issue46101> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue46057] argparse: embedded groups may prevent options from being in help output
paul j3 added the comment: Don't add an argument_group to another argument_group. While input allows this nesting, the formatting is not designed to handle it. Nor does the documentation illustrate such nesting. Nesting a mutually_exclusive_group in an argument_group works because the exclusive_group is not used in formatting the help lines. The two class of groups have very different purposes. Note that the add_argument_group() method is defined for the parent _ActionsContainer class. ArgumentParser inherits from this, as do both of the group classes. While one could make a case for changing the group's inheritance of this method to Not-implemented, it's only a problem when users, like you, try to push for undocumented usage. In general argparse has a clean and powerful class structure. But it doesn't do a lot of checking and pruning, so there loose ends like this. The Action class and its subclasses is similarly powerful, with enough loose ends to allow adventurous users to hang themselves :). -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue46057> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue46058] argparse: arg groups and mutually exclusive groups behave inconsitently
paul j3 added the comment: At least until these latest deprecations, the only nesting that made sense was to put a mutually_exclusive_group inside an argument_group. This was a way of providing a title and description for the exclusive_group. (And not documented.) I don't know if that's still possible. 'required' only makes sense for the exclusive_group. I don't know what happens when one tries to give it to an argument_group. If it doesn't raise an error, I expect it to be ignored. argument_groups are only used for help formatting; they have no role in parsing. exclusive_groups are primarily a parsing checking tool. Usage formatting tries to display exclusive groups, but is easily broken. While mutually_exclusive_group is a subclass of argument_group (and that in turn a subclass of argument_container), very little usage or behavior is inherited. Don't expect any consistency. A key point, that is easily lost, is that all groups share the _actions list with the parser. When an argument is added a group (either kind), it is, in effect, added to the parser's _actions list. So when parsing, there's only one list of Actions. A group will also keep the Action in its own _group_actions list, which is used for formatting or for exclusive checking. But otherwise the _group_actions list not used for parsing. Another point, is that there are 2 default argument_groups. Thus every Action is in an _group_actions list. If an exclusive_group is not nested in an argument_group, its Actions will be added to one of the defaults (optionals or positionals). -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue46058> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue46101] argparse: using parents & subcommands, options can be ignored
Change by paul j3 : -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue46101> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45673] argparse error with option with optional value
paul j3 added the comment: Put the required positional first $ myapp myfile -s or one of the store_true arguments $ myapp -s -j myfile I think $ myapp -s -- myfile will work as well, but that needs to be tested. The '-s' has to be followed by something won't be confused for an argument, such as nothing, or a flag. -- ___ Python tracker <https://bugs.python.org/issue45673> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45673] argparse error with option with optional value
paul j3 added the comment: https://bugs.python.org/issue9338 argparse optionals with nargs='?', '*' or '+' can't be followed by positionals As you can see this is an old issue, but still too big for a quick fix. As a general rule, don't use `nargs` like this where there's ambiguity as to how many values will be allocated to the argument. -- ___ Python tracker <https://bugs.python.org/issue45673> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45656] argparse bug: prefix_chars argument to add_argument_group doesn't really work
paul j3 added the comment: prefix_chars is a parameter of the parent _ActionsContainer class _ActionsContainer(object): def __init__(self, description, prefix_chars, argument_default, conflict_handler): super(_ActionsContainer, self).__init__() self.description = description self.argument_default = argument_default self.prefix_chars = prefix_chars self.conflict_handler = conflict_handler add_argument is also a method in this class. It uses its own prefix_chars to categorize arguments as optional/positional chars = self.prefix_chars if not args or len(args) == 1 and args[0][0] not in chars: see also _get_optional_kwargs method. class _ArgumentGroup(_ActionsContainer): inherits from _ActionsContainer, and usually gets the prefix_chars from its container (the parser) update('prefix_chars', container.prefix_chars) The parser is created with class ArgumentParser(_AttributeHolder, _ActionsContainer): and documents the use of prefix_chars. In addition to passing prefix_chars to its Super, it uses default_prefix = '-' if '-' in prefix_chars else prefix_chars[0] to define the -h help argument. Early in parsing, args strings are categorized as 'O' or 'A'. That is done in, which uses: def _parse_optional(self, arg_string): # if it doesn't start with a prefix, it was meant to be positional if not arg_string[0] in self.prefix_chars: return None def _get_option_tuples(self, option_string): also uses the parser's own prefix_chars. During parsing (several layers down) def consume_optional(start_index): # if the action is a single-dash option and takes no # arguments, try to parse more single-dash options out # of the tail of the option string chars = self.prefix_chars if arg_count == 0 and option_string[1] not in chars: Here, the parser's own prefix_chars is used to handle the chained short-dash options. --- In sum, while Argument_Group can have its own prefix_chars, that is only used for help formatting. It's the parser's prefix_chars that is used when parsing. The group's chars is ignored. The _ArgumentGroup__init__ suggests something more than simple inheritance may have been intended for prefix_chars, but in practice all it affects is the help. I haven't seen this issue raised before, and since this group parameter is not documented, I think it's safe to ignore it. An alternative is to have add_argument_group (or _ArgumentGroup__init__) explicitly reject the prefix_chars parameter. -- ___ Python tracker <https://bugs.python.org/issue45656> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45690] Argparse exclusive group inside required exclusive group displays incorrectly
paul j3 added the comment: https://bugs.python.org/issue29553 Argparser does not display closing parentheses in nested mutex groups supposedly fixed the parentheses for nested groups. You can read its discussion and patches to see why it does not handle your case. I don't see any examples have required groups. [] is used for un-required, () for required. This patch did not change how the usage was generated. It just refined how excess [()] were removed. Proper handling of groups requires a major rewrite of the usage formatter. -- ___ Python tracker <https://bugs.python.org/issue45690> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45656] argparse bug: prefix_chars argument to add_argument_group doesn't really work
paul j3 added the comment: Use of 'prefix_chars' as a argument_group parameter is not documented, nor intended. If it does appear to work in the help formatting, it is probably the result of inheritance, since both ArgumentParser and Argument_group subclass a _Actions_Container class. I'd have to examine the code to see what's happening. Argument_groups are used only for help formatting, not for parsing. In any case, I don't think anything needs to be changed or fixed. -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue45656> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45673] argparse error with option with optional value
paul j3 added the comment: This is too big of an example for this board; I think it should have been asked on StackOverFlow. Or maybe trimmed do to a more compact example. But in any case, this is normal behavior for argparse. Type checking, here 'int', is done after the string is allocated to the '-s' argument. Reserving that string for the required positional requires a form of look ahead that argparse does not currently do. I think there's an old bug/issue on the topic, but the fix was, if I remember correctly, too complex to simply drop in. I may look that up later. -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue45673> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45690] Argparse exclusive group inside required exclusive group displays incorrectly
paul j3 added the comment: There was a bug/issue that addressed problems with nested mutually_exclusive_groups. It should be easy to find. The problem is that the usage formatter is brittle, building a string and then striping out "unnecessary" characters. I assume the fix handled the default case (not required), but apparently it missed this variation. I wasn't too involved with that, since in my opinion nesting these groups is useless, and should be avoided. You might as well use one union group. Test the parsing for yourself. -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue45690> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9351] argparse set_defaults on subcommands should override top level set_defaults
paul j3 added the comment: A new patch, https://bugs.python.org/issue45235 has clobbered this patch. It has also exposed the inadequate unittesting for the case(s) where the 'dest' of main namespace, subparser namespace, user provided namespace overlap. -- ___ Python tracker <https://bugs.python.org/issue9351> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45235] argparse does not preserve namespace with subparser defaults
paul j3 added the comment: I should study previous posts in more detail, but here are some thoughts on correctly handling user namespace. At the start of `parse_known_args`, there's a if namespace is None: namespace = Namespace() We need to hang on to a copy of this namespace, e.g. call it import copy orig_namespace = copy.copy(namespace) In _SubParsersAction.__call__, pass this copy to the subparser (instead of None): subnamespace, arg_strings = parser.parse_known_args(arg_strings, orig_namespace) for key, value in vars(subnamespace).items(): setattr(namespace, key, value) Prior to 9351, the main namespace was passed to the subparser namespace, arg_strings = parser.parse_known_args(arg_strings, namespace) The trick is to get orig_namespace from the main parse_known_args to SubParsersAction.__call__ method. in a 9351 post I explore the idea of allowing the user to specify a 'sub_namespace' for the subparser. https://bugs.python.org/msg230056 In any case, this is a complicated issue that needs careful thought and more extensive testing. I didn't entirely like the original 9351 change, but since that's been part of argparse for many years, we need to very careful about clobbering it. -- status: pending -> open ___ Python tracker <https://bugs.python.org/issue45235> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45631] missing unittests for overlapping dest when using subparsers
New submission from paul j3 : https://bugs.python.org/issue45235 argparse does not preserve namespace with subparser defaults was passed and put into the latest release with rather obvious buggy behavior. This means that the unittest file does not adequately test for overlapping 'dest' in the main and subparsers. It probably also does not test many (any?) cases of user provided namespace. Issue9351 added a test, but it only tested defaults set with parser.set_defaults(foo=1) xparser.set_defaults(foo=2) not the more common practice of setting defaults in add_argument. 45235 adds one test, but again only for xparser.set_defaults(foo=1) It doesn't test for user inputs, as with ['X','--foo=3'] -- messages: 405110 nosy: ALSchwalm, paul.j3, rhettinger priority: normal severity: normal stage: needs patch status: open title: missing unittests for overlapping dest when using subparsers ___ Python tracker <https://bugs.python.org/issue45631> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue34046] subparsers -> add_parser doesn't support hyphen char '-'
paul j3 added the comment: Артём Иконников, developers and experienced users are familiar with other programs, such as 'svn' which is used as an example svn checkout, svn update, and svn commit Also the use of '--foo' as flagged/optional(s) argument is so familiar to developers, that it does nor occur us that new users might want to use that form here. While there's no explicit prohibition of using the dash, non of the examples use it. Examples are a good starting place when using new features. If this problem came up more often, I'd recommend modifying the `add_parser` method to raise an error if the user provides a dashed command name (or alias). -- ___ Python tracker <https://bugs.python.org/issue34046> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45504] [argparse] Entering a partial config_parser flag works with subparsers
Change by paul j3 : -- stage: -> resolved status: open -> closed ___ Python tracker <https://bugs.python.org/issue45504> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45235] argparse does not preserve namespace with subparser defaults
Change by paul j3 : -- stage: resolved -> test needed status: closed -> pending ___ Python tracker <https://bugs.python.org/issue45235> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41592] Make _SubParsersAction public
paul j3 added the comment: A _SubParsersAction is private to the extent that users should not attempt to create it directly, and thus don't need to know the details - beyond what's documented: "The add_subparsers() method is normally called with no arguments and returns a special action object. This object has a single method, add_parser(), which takes a command name and any ArgumentParser constructor arguments, and returns an ArgumentParser object that can be modified as usual." All action objects have methods like __call__ and format_usage. The subparsers Action has other methods, but add_parser is the only new "public" method. There's a tension in writing documentation between getting all details just right, and providing just enough for most users. As it is, many new users are over whelmed by the documentation. My understanding is that the "private/public" designation is a convenience for users, and not enforced by Python developers. I gather though that some corporate users have policies that prohibit modification of "private" objects, supposedly due to a fear that Python could modify or eliminate those objects without proper notification. Somehow the "public" documentation sets that part of the code in stone. My experience here is that it's easier modify the documentation to fit the code than the other way around :) -- ___ Python tracker <https://bugs.python.org/issue41592> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45235] argparse does not preserve namespace with subparser defaults
paul j3 added the comment: parser = argparse.ArgumentParser() sub = parser.add_subparsers() example_subparser = sub.add_parser("example") example_subparser.add_argument("--flag", default=10) print(parser.parse_args(["example","--flag=15"], argparse.Namespace(flag=20))) still returns flag=20 User input should override values set by the provided Namespace. -- ___ Python tracker <https://bugs.python.org/issue45235> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45235] argparse does not preserve namespace with subparser defaults
paul j3 added the comment: I just downloaded this `argparse.py`. This change makes it impossible to use a subparser argument if it is defined in the user provided namespace, or by the main parser. It blocks not only subparser default, but also user input. It has reverted the 9351 patch which dates to 2014. -- ___ Python tracker <https://bugs.python.org/issue45235> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45235] argparse does not preserve namespace with subparser defaults
paul j3 added the comment: I haven't studied or tested this change, but it looks like a partial retraction of https://bugs.python.org/issue9351 argparse set_defaults on subcommands should override top level set_defaults Originally the main namespace was passed to the subparser. Steven Bethard changed it so that the subparser got a fresh namespace, and all values were copied to the main namespace. I and others raised the question of how it affected user provided values https://bugs.python.org/issue27859 argparse - subparsers does not retain namespace Looks like this patch tries to solve some problems by moving the self._defaults step to the end of parser_know_args. I view that change with some trepidation. Handling defaults is tricky enough, with setting them at the start, but then only passing them through 'type' at the end if they still match the original strings. Mostly I've been telling StackOverflow questioners that it best not to use the same argument 'dest' in both the main and subparsers. Flags can be the same, but the 'dest' should be different to avoid conflicts over which default has priority. Again, I haven't tested this change, but I have a gut feeling it could have backward compatibility issues. -- ___ Python tracker <https://bugs.python.org/issue45235> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45235] argparse does not preserve namespace with subparser defaults
Change by paul j3 : -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue45235> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45504] [argparse] Entering a partial config_parser flag works with subparsers
paul j3 added the comment: As a default option flags can be abbreviated (unless there's a conflict). Recent version have a allow_abbrev parameter that lets you turn this off. -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue45504> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45275] Make argparse print description of subcommand when invoke help doc on subcommand
paul j3 added the comment: Are you expecting the subcommand help to show the 'help' line that the main help shows? subparsers.add_parser('a', help='a help') add_parser takes all of the parameters that `ArgumentParser` takes, including description and epilog. I don't think we need to add anything to add_parser. -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue45275> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45580] argparse.ArgumentParser.add_mutually_exclusive_group : metavar create parenthesis undefined behavior
paul j3 added the comment: The usage formatting is fragile, with many associated bug reports. Until someone does a major rewrite, it is best to avoid special characters, especially `()` and `[]` in the `dest` or `metavar`. Usage uses () to encolde mutually_exclusive_groups and [] to mark non-required arguments. Don't confuse your users (or argparse) with other uses of these characters. -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue45580> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41592] Make _SubParsersAction public
paul j3 added the comment: `add_argument` also returns a Action subclass object. All of those subclasses are "private". While that return reference is usually ignored, sometimes it is useful to it, assigning it to a variable or list. The documentation could be clearer about access to Action objects. -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue41592> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45587] argparse add_argument_group: distinguish title and description from **kwargs
Change by paul j3 : -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue45587> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue24739] allow argparse.FileType to accept newline argument
paul j3 added the comment: Adding `newline` to `FileType` requires modifying both the `__init__` and `__call__` methods. That's nearly the whole class. I'd copy and edit, and forget about subclassing. -- ___ Python tracker <https://bugs.python.org/issue24739> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41255] Argparse.parse_args exits on unrecognized option with exit_on_error=False
Change by paul j3 : -- Removed message: https://bugs.python.org/msg401554 ___ Python tracker <https://bugs.python.org/issue41255> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41255] Argparse.parse_args exits on unrecognized option with exit_on_error=False
paul j3 added the comment: In https://stackoverflow.com/questions/69108632/unable-to-catch-exception-error-for-argparse it looked like `exit_on_error` does not work when using subparsers. On on further thought, I realized that it has to included in the definition of the subparser. As with other `ArgumentParser` parameters, the subparsers does not inherit from the main parser. So it's basically a documentation issue. The `add_parser` method is described briefly as: which takes a command name and any ArgumentParser constructor arguments, and returns an ArgumentParser object that can be modified as usual. But as my experience shows, its relevance is easily missed, even by an experienced users. -- ___ Python tracker <https://bugs.python.org/issue41255> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41255] Argparse.parse_args exits on unrecognized option with exit_on_error=False
paul j3 added the comment: In https://stackoverflow.com/questions/69108632/unable-to-catch-exception-error-for-argparse we found that `exit_on_error` does not work when the error occurs in a subparser. Unless someone wants to take time to get this right, I think this feature should be removed. It's too buggy. -- ___ Python tracker <https://bugs.python.org/issue41255> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45110] argparse repeats itself when formatting help metavars
paul j3 added the comment: The idea of combining help features by defining a subclass that inherits from other subclasses was endorsed by the original developer (we could dig up an old bug/issue to prove that). The provided subclasses all tweak a "private" method, often one that's buried deep in the calling stack. I can't quote any official policy, but my sense is that Python developers are ok with users subclassing and modifying "private" methods. Methods, functions and classes (and variables) with leading '_' aren't documented, or imported via `__all__`, but otherwise the boundary between what is part of the user API and what's "hidden" is loose in Python. Apparently some corporate policies prohibit use or modification of things that aren't in the public API, but I don't think that policy protects you from changes. 'argparse' changes at a glacial rate, with a lot of concern for backward compatibility. In fact it's that fear of unintended consequences that slows down the pace of change. Subclassing a help formatter is preferred because it minimizes the chance of hurting existing users. -- ___ Python tracker <https://bugs.python.org/issue45110> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45110] argparse repeats itself when formatting help metavars
paul j3 added the comment: https://bugs.python.org/issue42980 argparse: GNU-style help formatter https://bugs.python.org/issue33389 argparse redundant help string https://bugs.python.org/issue29626 Issue with spacing in argparse module while using help https://bugs.python.org/issue27303 [argparse] Unify options in help output https://stackoverflow.com/questions/23936145/python-argparse-help-message-disable-metavar-for-short-options https://stackoverflow.com/questions/18275023/dont-show-long-options-twice-in-print-help-from-argparse -- ___ Python tracker <https://bugs.python.org/issue45110> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue45110] argparse repeats itself when formatting help metavars
paul j3 added the comment: This is has been requested various times on StackOverflow, and possibly here (I'd have to do a search). The closest thing to making a compact action_invocation is to set the metavar to '', and even thing we get a space, eg. -f , --foo Help text This repeat has been a part of argparse from the beginning, so I can't see changing the default behavior. But we could add a HelpFormatter subclass that changes one (or two methods) such as _format_action_invocation. Subclassing the formatter is the accepted way of adding help features. I, and possibly others, must have suggested such a change on SO. Of course people can use such a subclass without it being part of the standard module. -- ___ Python tracker <https://bugs.python.org/issue45110> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue44587] argparse BooleanOptionalAction displays default=SUPPRESS unlike other action types
Change by paul j3 : -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue44587> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue44986] Date formats in help messages of argparse
Change by paul j3 : -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue44986> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue44748] argparse: a bool indicating if arg was encountered
paul j3 added the comment: Another way to play with the defaults is to use argparse.SUPPRESS. With such a default, the argument does not appear in the namespace, unless provided by the user. In [2]: p = argparse.ArgumentParser() ...: p.add_argument('--foo', default=argparse.SUPPRESS, help='foo help') ...: p.add_argument('--bar', default='default') ...: p.add_argument('--baz'); In [3]: args = p.parse_args([]) In [4]: args Out[4]: Namespace(bar='default', baz=None) Such a namespace can be used to update an existing dict (such as from a config file), changing only keys provided by user (and ones where SUPPRESS does not make sense, such as store_true and positionals). In [5]: adict = {'foo':'xxx', 'bar':'yyy', 'baz':'zzz'} In [6]: adict.update(vars(args)) In [7]: adict Out[7]: {'foo': 'xxx', 'bar': 'default', 'baz': None} User provided value: In [8]: args = p.parse_args(['--foo','foo','--baz','baz']) In [9]: args Out[9]: Namespace(bar='default', baz='baz', foo='foo') In this code sample I used Ipython. That IDE uses (or at least did some years ago) a custom integration of config and argparse. System default config file(s) set a large number of parameters. Users are encouraged to write their own profile configs (using provided templates). On starting a session, the config is loaded, and used to populate a parser, with arguments, helps and defaults. Thus values are set or reset upto 3 times - default, profile and commandline. I for example, usually start an ipython session with an alias alias inumpy3='ipython3 --pylab qt --nosep --term-title --InteractiveShellApp.pylab_import_all=False --TerminalInteractiveShell.xmode=Plain' Regarding this bug/issue, if someone can come up with a clever tweak that satisfies Thermi, is potentially useful to others, and is clearly backward compatible, great. But if this issue requires a less-than-ideal-compatible patch, or greater integration of config and argparse, then it needs to be developed as a separate project and tested on PyPi. Also search PyPi; someone may have already done the work. -- ___ Python tracker <https://bugs.python.org/issue44748> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue44748] argparse: a bool indicating if arg was encountered
paul j3 added the comment: More on the refactoring of error handling in _parse_known_args https://bugs.python.org/issue29670#msg288990 This is in a issue wanting better handling of the pre-populated "required" arguments, https://bugs.python.org/issue29670 argparse: does not respect required args pre-populated into namespace -- ___ Python tracker <https://bugs.python.org/issue44748> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue44748] argparse: a bool indicating if arg was encountered
paul j3 added the comment: I've explored something similar in https://bugs.python.org/issue11588 Add "necessarily inclusive" groups to argparse There is a local variable in parser._parse_known_args seen_non_default_actions that's a set of the actions that have been seen. It is used for testing for required actions, and for mutually_exclusive groups. But making it available to users without altering user API code is awkward. My latest idea was to add it as an attribute to the parser, or (conditionally) as attribute of the namespace https://bugs.python.org/issue11588#msg265734 I've also thought about tweaking the interface between parser._parse_known_args parser.parse_known_args to do of more of the error checking in the caller, and give the user more opportunity to do their checks. This variable would be part of _parse_known_args output. Usually though when testing like this comes up on SO, I suggest leaving the defaults as None, and then just using a if args.foobar is None: # not seen Defaults are written to the namespace at the start of parsing, and seen arguments overwrite those values (with an added type 'eval' step of remaining defaults at the end). Keep in mind, though, that the use of subparsers could complicate any of these tweaks. In reading my posts on https://bugs.python.org/issue26394, I remembered the IPython uses argparse (subclassed) with config. I believe it uses config inputs (default and user) to define the arguments for the parser. So unless someone comes up with a really clever idea, this is bigger request than it first impressions suggest. -- ___ Python tracker <https://bugs.python.org/issue44748> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue44748] argparse: a bool indicating if arg was encountered
paul j3 added the comment: Joker 'type=bool' has been discussed in other issues. 'bool' is an existing python function. Only 'bool("")' returns False. Write your own 'type' function if you want to test for specific strings. It's too language-specific to add as a general purpose function. -- ___ Python tracker <https://bugs.python.org/issue44748> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue43192] Argparse complains argument required when default is provided
paul j3 added the comment: To a large degree the Action parameters operate independently. That is, different parts of the code use the parameters for their own purposes. The composite behavior is a result of those individual actors, rather than some sort of overall coordinated plan. First your Action is 'positional' (no flag string), and "store" type. nargs is the default None. The only extra is the default value (the default default is None). _ActionsContainer._get_positional_kwargs processes such an argument, setting the 'required' parameter with: # mark positional arguments as required if at least one is # always required if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]: kwargs['required'] = True if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs: kwargs['required'] = True At the start of parsing, all 'default' values are added to the 'args' Namespace. If an Action is "seen", either via the appropriate flag string, or a positional value, it is added to the "seen_actions" list. At the end of parsing, it iterates through all the '_actions'. If it is not in the 'seen_actions' list, and is marked "required", it gets added to the 'reqiuired_action' error list. So even though your Action has a 'default' it is still required. The default is, in effect, ignored. The nargs value (default or not) has priority in setting the 'required' value. '?/*' nargs require special handling. This nargs requirement is satisfied by an empty list. Such a positional will, in effect, always be seen. But if a explicit default is provided, that will over write the empty list. Handling defaults is inherently tricky. But except for the special '?/*' case, specifying a 'default' with a positional doesn't make much sense. -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue43192> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue43942] RawDescriptionHelpFormatter seems to be ignored for argument descriptions
paul j3 added the comment: You test with RawDescriptionHelpFormatter, but quote from the RawTextHelpFormatter. -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue43942> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11354] argparse: nargs could accept range of options count
paul j3 added the comment: Post parsing testing for the correct number of strings is the easy part. It's the auto-generate usage that's harder to do right, especially if we wanted to enable the metavar tuple option. Clean usage for '+' is messy enough. -- ___ Python tracker <https://bugs.python.org/issue11354> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue43876] argparse documentation contrasting nargs '*' vs. '+' is misleading
paul j3 added the comment: Let's see if I can clarify somethings. But first, I should say that I've worked with this code for so long, that I may miss things that could confuse a beginner. A basic distinction is between "optionals" and "positionals". I put those in quotes because that's not the same as "required or not". Talk about "options" in commandline arguments goes way back (see getopt, and optparse). An "optional" is identified by a flag string, such as "-f" or "--foo", short or long, single or double dash. I prefer to call these "flagged arguments". "optionals" can occur in any order, and even repeatedly. A "postional" is identified by position, without any sort of flag string. In earlier parsers, these where the extras, the strings that weren't handled by "options". These can only occur in the defined order. Conventionally, optionals come first, and positionals at the end. That's how most "help/usage" messages display them. But argparse tries to handle them in any order. Both kinds can take a "nargs" parameter. This specifies how many arguments (or strings) are required, either following the flag string, or as part of position. Obviously if you don't specify the flag, you don't have to provide its arguments either. There's another point of confusion. "parse.add_argument" creates an "Action", also called an "argument". And each "action" has a 'nargs' that specifies how many "arguments" go along with it. Sorry. The default "nargs" value is "None", which means 1 string. "?" means zro or one (optional, but in a different sense than flagged). "*" means any number. "+" means one or more. nargs could also be a number, e.g. "2". There isn't anything that specifies "2 or more" or "2 or 3" (though that has been requested). "?+*" are used in basically the same sense as in regex/re patterns. There's another parameter, "action", which also controls the number of required strings. With "store_true" no string is allowed after the flag, effectively "nargs=0" (this action makes no sense for positionals). It's actually of subclass of "store_const", with a default "False" and const "True". With a flagged argument, you may also specify a "required" parameter. That's convenient, but does lead to confusing terminology. "optionals" may be "required", and a "positional" with "?" is optional/not-required. Since "+" and "*" allow many strings, something has to define the end of that list. That end is either the end of the input, or the next flag string. If you are just using flagged arguments this isn't a problem. But with "positionals", it is hard to handle more than one open-end nargs. Or to use such a "positional" after an open-ended "optional". As with regex, these nargs are "greedy". In some ways, the documentation is more complicated than the code itself. The code is well written, with different methods and classes handling different issues. The code itself does not have a lot of complicated rules and conditions. The complexity comes from how the different pieces interact. "flagged vs positional", nargs, and "required" are separate specifications, though they do have significant interactions. In your example: parser.add_argument("outdata", help="Path to output data file") parser.add_argument("plotTimes", nargs='*', help="Times to plot") parser.add_argument("outplot", help="Path to output plot file") "outdata" takes one string. "outplot" takes another. "plotTimes" then gets anything left over in between. An empty list of strings satisfies its "nargs". The strings are actually allocated with a regex expression. With `arg_argument('--foo', nargs='+')`, --foo one --foo one two three are both allowed. With "*", --foo is also allowed. For a "positional" omit the "--foo". That means that a "positional" with "*" is always seen (which can require some special edge case handling). -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue43876> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue43874] argparse crashes on subparsers with no dest/metava
paul j3 added the comment: This is a well known (if not fixed) issue - if subparsers is required, then a dest is needed to give a working error message. Looks like we've variously talked about documenting the requirement, or using some sort of substitute for the missing name. One of my higher-voted SO answers: https://stackoverflow.com/questions/23349349/argparse-with-required-subparser/23354355#23354355 https://bugs.python.org/issue29298 https://github.com/python/cpython/pull/18564 https://github.com/python/cpython/pull/3027 https://github.com/python/cpython/pull/3680 -- ___ Python tracker <https://bugs.python.org/issue43874> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue43220] Argparse: Explicit default required arguments with add_mutually_exclusive_group are rejected
paul j3 added the comment: An overlapping issue https://bugs.python.org/issue18943 argparse: default args in mutually exclusive groups That issue shows that this problem arises with small integers as well (<257), which in cpython have unique ids. It's an implementation detail, pypy for example does not have this issue. The whole purpose of this extra default testing is to allow '?/*' positionals in mutually_exclusive_groups. The patch I proposed in 2013 is basically the same thing, except I called the new flag variable 'using_default'. We should review the discussion in that issue to see if it raises any additional issues or concerns. -- ___ Python tracker <https://bugs.python.org/issue43220> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue43259] argparse: allow add_mutually_exclusive_group on add_argument_group
paul j3 added the comment: I've added a script that does what you want, but with a simple utility function instead of a parent (or lots of copy-n-paste). I explored the code a bit, and have an idea that might correct the [parent] behavior. In the method that copies a parent's groups and actions def _add_container_actions(self, container): It might be enough to change for group in container._mutually_exclusive_groups: mutex_group = self.add_mutually_exclusive_group( required=group.required) to for group in container._mutually_exclusive_groups: pgroup = group._container mutex_group = pgroup.add_mutually_exclusive_group( required=group.required) The mutually group records where it was create in its '._container' attribute. Usually that would a parser, but in your example would the 'inputs' action group. I haven't tested this idea. In https://bugs.python.org/issue11588 (request for inclusive groups), I explored adding a Usage_Group class that could nest. That project become too large, especially when considering help formatting. And I did not give any thought to dealing with parents there. Another issue involving parents (and the potential problems caused by copy-by-reference). https://bugs.python.org/issue22401 argparse: 'resolve' conflict handler damages the actions of the parent parser Belatedly I look for other issues involving 'parent', and found these duplicates https://bugs.python.org/issue25882 argparse help error: arguments created by add_mutually_exclusive_group() are shown outside their parent group created by add_argument_group() https://bugs.python.org/issue16807 argparse group nesting lost on inheritance -- Added file: https://bugs.python.org/file49827/issue43259_utility.py ___ Python tracker <https://bugs.python.org/issue43259> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue43259] argparse: allow add_mutually_exclusive_group on add_argument_group
paul j3 added the comment: The parents mechanism is not elaborate. It copies groups and actions by reference. The comments that I quoted actually come from that method that does this copying. >From a quick glance at that code I see that it does not preserve the group >nesting. Mutually_exclusive groups are added directly the parser. Parents is primarily a convenience tool, especially if used entirely with your own code. It's most valuable when importing the parent, and you don't have direct access to the code that constructed it. But it seems to be used most often as a way of creating a number of similar subparsers. For that it can be easily replaced with your own utility function(s). There's no virtue in trying to do everything with the tools that argparse provides. -- ___ Python tracker <https://bugs.python.org/issue43259> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue43259] argparse: allow add_mutually_exclusive_group on add_argument_group
paul j3 added the comment: The mutually exclusive arguments are displayed with in the argument group, at least in my testing. From a copy-n-paste of your example: In [8]: parser.print_help() usage: ipython3 [-h] [--from-args FROM_ARGS | --from-files FROM_FILES | --from-stdin FROM_STDIN] [-0 0] optional arguments: -h, --helpshow this help message and exit INPUT OPTIONS: --from-args FROM_ARGS --from-files FROM_FILES --from-stdin FROM_STDIN -0 0 null delimited pathnames I've had occasion to note that this is the only kind of group nesting that works (or makes sense). In add_container_actions, there is a comment: # add container's mutually exclusive groups # NOTE: if add_mutually_exclusive_group ever gains title= and # description= then this code will need to be expanded as above So the original developer envisioned giving a mutually exclusive group a formatting role, but with this nesting this isn't needed (that I can tell). But I don't think this has been documented. -- ___ Python tracker <https://bugs.python.org/issue43259> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue43160] argparse: add extend_const action
paul j3 added the comment: It's not clear what your patch does that the existing 'store_const' doesn't. Even 'append_const' does the same except for a extra level of list/tuple nesting. But I'll admit that I didn't much need for 'extend' addition, but others, including the original developer liked it. I suspect users of your addition will get a surprise if they aren't careful to provide a list or tuple 'const': const='foobar' const=str -- ___ Python tracker <https://bugs.python.org/issue43160> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42973] argparse: mixing optional and positional arguments... not again
paul j3 added the comment: Sometimes patches have unforeseen benefits. My earlier patch for this issue, parse_intermixed_args, has been useful beyond the OP's case. https://stackoverflow.com/questions/50916124/allow-positional-command-line-arguments-with-nargs-to-be-seperated-by-a-flag https://bugs.python.org/issue15112 argparse: nargs='*' positional argument doesn't accept any items if preceded by an option and another positional With usage: test.py [-h] [-a A] b [c] and test.py B -a A C has problems because the optional '[c]' positional is used up when 'b' is processed. Intermixed gets around this by first processing '-a', and then handling 'b [c]' together. -- ___ Python tracker <https://bugs.python.org/issue42973> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42973] argparse: mixing optional and positional arguments... not again
paul j3 added the comment: So in the big picture, the purpose of this change is to treat the inputs like a kind of state-machine. In the bigger example, the `**` positional values are processed one by one, using the interspersed optionals to set state parameters. `args.sources` then ends up as a list of dicts, each of the form: {'name': 'input3.txt', 'frobnicate': None, 'massage_level': 5} where 'name' is the positional value, and 'frobnicate' and 'massage_level' are the latest values (default or user supplied). The optionals can be specified in any order or repeatedly. While the proposed change to the core parser is (apparently) minor, it does occur at the center of the action. That is not the place we want any (new) bugs or backward incompatibility. And the full implementation requires a new Action subclass that is quite different from existing ones. Given how different this is from the normal argparse parsing (and the POSIX parsing argparse seeks to emulate), I question the wisdom of adding this, in part or whole, to the stock distribution. It could certainly be published as a pypi. That already has a number of parsers, some built on argparse, others stand alone. I also wonder whether it would be simpler to do this kind of parsing directly from sys.argv. Just step through that list, consuming the values and flags in sequence. Sorry to sound like a wet blanket, but I've seen too many seemingly innocent patches that caused unforeseen problems down the line. -- ___ Python tracker <https://bugs.python.org/issue42973> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42973] argparse: mixing optional and positional arguments... not again
paul j3 added the comment: I haven't had a chance to study your longer posts, but it seems to me that the AddFruitAction example could just as well be implemented with parser.add_argument('--color', nargs='*', action='append') with post parsing processing to create the 'fruits' dicts from the appended lists. The basic logic of argparse is to accept optionals in any order, and positionals in strict positional order. 'nargs' allows us to pair any number of strings with each optional's flag. While custom Action classes can implement interactions between arguments based on values in the namespace, it is usually easier to do this after parsing. But back to your core change, I wonder if adding a new nargs, such as '**' would be better than than the new parameter 'greedy_star=True'. I prefer not to add parameters that are hard to document. At this point in the argparse development, changes should be minimally invasive. -- ___ Python tracker <https://bugs.python.org/issue42973> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42966] argparse: customizable help formatter
paul j3 added the comment: Years ago I proposed a `format_wrapper`, a Format class factory https://bugs.python.org/issue12806#msg218395 also https://bugs.python.org/issue39809 There I show that the formatter may be lambda formatter = lambda prog: argparse.HelpFormatter(prog, width=100) The need for improving help customization has been around for a long time: https://bugs.python.org/issue11695 Improve argparse usage/help customization https://bugs.python.org/issue32123 Make the API of argparse.HelpFormatter public -- ___ Python tracker <https://bugs.python.org/issue42966> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42875] argparse incorrectly shows help string on a new line in case of long command string
paul j3 added the comment: This issue is discussed in: https://bugs.python.org/issue34724 argparse subparser help indent too short and https://stackoverflow.com/questions/3215/max-help-position-is-not-works-in-python-argparse-library -- ___ Python tracker <https://bugs.python.org/issue42875> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42980] argparse: GNU-style help formatter
paul j3 added the comment: I was thinking of a refactoring that included the ', '.join(...) loop, but on further thought your refactoring might be enough for the case I raised. For example: def _format_option_with_args(self, option_string, args_string): if option_string.startswith('--'): return '%s %s' % (option_string, args_string) return '%s' % option_string would produce a -f, --foo FOOsomething and def _format_option_with_args(self, option_string, args_string): return option_string would produce -f, --foo something I wonder if this refactoring merits some mention in the documentation. Or maybe the GnuStyleLongOptionsHelpFormatter subclass is enough of an example. The details of how other formatter subclasses work aren't documented, but they are available to developers who can read the code. -- ___ Python tracker <https://bugs.python.org/issue42980> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42980] argparse: GNU-style help formatter
paul j3 added the comment: The refactoring looks reasonable. But while we are tweaking: def _format_action_invocation(self, action): I wonder if we also give users more control over how multiple option strings are formatted. Currently if parser.add_argument('-f', '--foo', help='something') the help line will be -f FOO, --foo FOO something with this alternate formatter it would be (I think) -f FOO, --foo=FOO something But with longer option strings users often want -f, --foo FOO something or even just -f, --foo something we can almost get the last with `metavar=''` -f , --foosomething which has a superfluous space before the comma. I don't recall if there's already a bug/issue for this or not. Maybe the fix is a subclass with a complete replacement of this _format_action_invocation method. I'll have do more research (here and on Stackoverflow). -- ___ Python tracker <https://bugs.python.org/issue42980> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42973] argparse: mixing optional and positional arguments... not again
paul j3 added the comment: Your patch is incomplete, without documentation or tests. Your example is incomplete. That is _CustomAction? What namespace does your patch produce. It's been a while since I worked on the intermixed patch, but as I recall the OP was happy with the fix. Also I don't recall any talk about 'matching "optionals" with "positionals" with they relate to. Was that part of the discussion? On Stackoverflow I have seen questions about pairing arguments, and answered some. I don't recall the best answers. The tough version is when some of the grouped inputs may be missing In your example I'd suggest making '--tracks' a nargs=2 and 'append' option. 'choices' would have to be replaced with a either a custom 'type', a custom Action, or post-parsing testing. I haven't had time yet to test your patch. One question I frequently ask posters who want to parse complex inputs is: 'how are going to explain this to your users?' 'What kind of usage and help do you want see?' -- ___ Python tracker <https://bugs.python.org/issue42973> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9694] argparse required arguments displayed under "optional arguments"
paul j3 added the comment: Since this issue is closed it might be a good idea to open a new one with this problem. And if possible identify the failed tests. We forgot to allow for the fact that working code/tests might be checking for specific help messages, checks the will fail when this group label is changed. -- ___ Python tracker <https://bugs.python.org/issue9694> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42650] Can people use dest=argparse.SUPPRESS in custom Action classes?
paul j3 added the comment: I'd have to study the code (and docs), but I'm not sure setting the `dest` to 'SUPPRESS' does anything meaningful. default=argparse.SUPPRESS is useful, keeping the default out of the namespace. That argument appears only if the user has used the option. But with `dest` (in a default 'store'), I get a namespace like Namespace(**{'==SUPPRESS==': 'foo'}) 'help' and 'version' exit right after displaying their message, so I'm no sure the 'SUPPRESS' is doing anything. The parser doesn't return a namespace. It appears that the 'dest' is passed to the Action. A custom Action could act on that 'dest'. The default 'store' just uses it as the attribute for storing the value in the namespace. Anyways, this is not the kind of thing that we'll be tweaking in the source. I don't recall any bug/issue touching on this behavior (but we could do a search). -- ___ Python tracker <https://bugs.python.org/issue42650> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue37717] argparse subcommand docs has non-existent parameter "action"
paul j3 added the comment: I'm closing the is as a duplicate of https://bugs.python.org/issue23487, which is already closed. -- resolution: -> duplicate stage: -> resolved status: open -> closed ___ Python tracker <https://bugs.python.org/issue37717> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42677] Support comments in argparse fromfile_prefix_chars files
paul j3 added the comment: https://docs.python.org/3/library/argparse.html#customizing-file-parsing in the docs describes how to customize the @file reading. This particular extension handles several strings on a line, but that's not the limit of what you could do. You can also read a file before parsing and construct a custom `argv` list, as described in https://docs.python.org/3/library/argparse.html#beyond-sys-argv -- ___ Python tracker <https://bugs.python.org/issue42677> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42622] Add support to add existing parser to ArgumentParser.subparsers
paul j3 added the comment: An existing parser can be included in a new subparser via the 'parents' mechanism. With that the _actions and groups of the parent are copied (by reference) to the new subparser. There are some rough edges to the parents mechanism, but people have used it to add a common subset of arguments to all subparsers. -- ___ Python tracker <https://bugs.python.org/issue42622> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue39106] Add suggestions to argparse error message output for unrecognized arguments
paul j3 added the comment: In the subparser example, it's the `build` subparser that puts '--overwritte' in the unrecognized list. That is then passed back to the main parser, which then issues the 'unrecognized' error, along with its own usage. The subparser is called with `parse_known_args` while the proposed patch is run in the `parse_args` method of the main parser. It doesn't have access to the subparser's arguments. So implementing the proposed matching will be much harder. For some types of error, such as type or choices, the subparser itself raises the error, with the appropriate usage. === https://bugs.python.org/issue42297 [argparse] Bad error message formatting when using custom usage text is another case where error messages produced by the subparser differ from messages produced by the main. In this case the unrecognized error usage message is clearer since it is produced by the main parser. === I didn't close this issue, but it does feel like an enhancement that's too big for the bug/issues forum. The proposed patch could be developed as a separate 'parser.parse_args_with_hints' method, and distributed as a pypi addition. During development and testing, the regular 'parser.parse_args()' does not need to be touched. -- ___ Python tracker <https://bugs.python.org/issue39106> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42572] Better path handling with argparse
paul j3 added the comment: One caution - the type parameter is a callable (function) that takes one string as argument. I proposed `pathlib.Path` because it does that, returning a Path object. It's a class instance creator. I believe the module has other class initiators. bool() has confused many users. While it returns a bool class instance, True or False, the only string that returns False is the empty one, with argparse can't supply. It does not convert strings like 'False' or 'no' to boolean False. -- ___ Python tracker <https://bugs.python.org/issue42572> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42572] Better path handling with argparse
paul j3 added the comment: The pathlib.Path is new since I paid much attention to os matters (I cut my teeth on py2.5). Off hand it looks like the user could import pathlib parser.add_argument('-p', type=pathlib.Path) to convert a string into a Path object. A custom type function could call this, and apply any desired methods before returning the Path object. But that should be up to the user, not the `argparse` developers. Importing path specific modules such as pathlib (which in turn has a lot of imports) goes against the attempt to reduce the number of unnecessary imports with modules like argparse. https://bugs.python.org/issue30152 Reduce the number of imports for argparse After this diet argparse still imports os, and uses: os.path.basename I might also note that argparse has only one custom 'type' function, the FileType factory. Other common type functions like 'int' and 'float' are Python builtin's. Adding a custom 'bool' (to be used instead of the builtin 'bool') has been rejected. https://bugs.python.org/issue37564 json, yaml, and datetime types have also been rejected https://bugs.python.org/issue35005 -- ___ Python tracker <https://bugs.python.org/issue42572> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42572] Better path handling with argparse
paul j3 added the comment: What exactly do you do with a path argument? Admittedly I'm not expert with os and os.path modules, but isn't a path just a string passed to a function such as cwd(), or joined to another create a filename. I don't know what a 'path' type or action would do. -- ___ Python tracker <https://bugs.python.org/issue42572> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42547] argparse: add_argument(... nargs='+', metavar=) does not work with positional arguments
paul j3 added the comment: I'll reopen it - your patch, while not a complete resolution, does take care of the immediate error. -- resolution: duplicate -> status: closed -> open ___ Python tracker <https://bugs.python.org/issue42547> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42547] argparse: add_argument(... nargs='+', metavar=) does not work with positional arguments
paul j3 added the comment: Duplicate of https://bugs.python.org/issue14074 argparse allows nargs>1 for positional arguments but doesn't allow metavar to be a tuple -- resolution: -> duplicate stage: patch review -> resolved status: open -> closed ___ Python tracker <https://bugs.python.org/issue42547> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42501] Improve error messages for argparse choices using enum
paul j3 added the comment: choices is fine for a few strings, but quickly becomes awkward with other types and large numbers. The testing isn't an issue, since it just does a simple `in/contains` test. But display, whether in usage, help or error, is problematic if you try anything too fancy. metavar gets around some of those issues, but doesn't change the error messages. Custom type or action is the best alternative. I'm in favor omitting the enums mention in the docs, since it seems to be more confusing than helpful. -- ___ Python tracker <https://bugs.python.org/issue42501> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42297] [argparse] Bad error message formatting when using custom usage text
paul j3 added the comment: We could look into using a different more compact 'prog' for these error messages. Currently the subparser 'prog' uses the main prog plus positionals plus the subparser name. The goal is to construct a subparser usage that reflects required input. This is fine for the usage line, but could be too verbose for some errors. In an error, the 'prog' just helps identify which argument has problems, and doesn't need the extra usage information. Most of the time that isn't an issue, since we don't use positional much in the main parser (and when used can't have variable nargs). But I don't have immediate ideas as to what can be conveniently (and safely) changed. -- ___ Python tracker <https://bugs.python.org/issue42297> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42297] [argparse] Bad error message formatting when using custom usage text
paul j3 added the comment: It's the subparser that's producing this error, specifically its 'prog' attribute. If I use a custom usage with a simple parser: 1129:~/mypy$ python3 issue42297.py --foo=on usage: issue42297.py one two three issue42297.py: error: argument --foo: ignored explicit argument 'on' Notice that the error line includes the 'prog'. With subparsers, the main usage is included in the subcommand prog: print(subcmd_parser.prog) produces: test usage string ending in newlines foo --bar foo --bar foo --bar foo That's the usage plus the subcommand name, 'foo'. Generating the explicit error in the subcommand: 1244:~/mypy$ python3 issue42297.py foo --bar=on test usage string ending in newlines foo --bar foo --bar foo --bar foo: error: argument --bar: ignored explicit argument 'on' 'issue42297.py: ' has been replaced by the usage+'foo', and no newline. We don't see this in the 'unrecognized' case because that error issued by the main parser. issue42297.py: error: unrecognized arguments: on If I explicitly set the prog of the subcommand: subcmd_parser = subparser.add_parser('foo', prog='myscript foo') The error becomes: 1256:~/mypy$ python3 issue42297.py foo --bar=on usage: myscript foo [-h] [--bar] myscript foo: error: argument --bar: ignored explicit argument 'on' I can also add 'usage=usage_string' to the add_parser. For the most part add_parser takes the same parameters as ArgumentParser. Alternatively we can specify prog in subparser = parser.add_subparsers(dest='subcmd', metavar='subcmd', prog='myscript') resulting in: myscript foo: error: argument --bar: ignored explicit argument 'on' I recently explored how 'prog' is set with subparsers in https://bugs.python.org/issue41980 I don't think anything needs to be corrected in argparse. There are enough options for setting prog and usage in subcommands to get around this issue. In the worse case, you might want to create an alternative _SubParsersAction Action subclass that defines the prog/usage differently. -- ___ Python tracker <https://bugs.python.org/issue42297> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42297] [argparse] Bad error message formatting when using custom usage text
paul j3 added the comment: Provide a minimal reproducible example. I can't reproduce that run on error message. Also test with arguments like '--all-logs on', which issues an 'unrecognizeable argument' error (with a different error reporting path). Stripping excess newlines is normal, both in the full help and error. That's done at the end of help formatting. -- ___ Python tracker <https://bugs.python.org/issue42297> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42191] lib.argparse._check_value() using repr instead of str
paul j3 added the comment: Do you realize that `choices` can be a dictionary? And since you want the user to supply a key, not a value, you might not want to use a type that does the conversion. To illustrate consider two ways of using a simple dictionary. import argparse adict = {'a': [1,2,3], 'b': 'astring'} parser = argparse.ArgumentParser() parser.add_argument('-f', type = lambda x: adict.get(x,x), choices = list(adict.values()) ) parser.add_argument('-g', choices = adict) args = parser.parse_args() print(args) print(args.f, adict[args.g]) sample runs: valid key: 0942:~/mypy$ python3 issue42191.py -f a -g a Namespace(f=[1, 2, 3], g='a') [1, 2, 3] [1, 2, 3] help: 0945:~/mypy$ python3 issue42191.py -h usage: issue42191.py [-h] [-f {[1, 2, 3],astring}] [-g {a,b}] optional arguments: -h, --helpshow this help message and exit -f {[1, 2, 3],astring} -g {a,b} Error cases: 0945:~/mypy$ python3 issue42191.py -f x usage: issue42191.py [-h] [-f {[1, 2, 3],astring}] [-g {a,b}] issue42191.py: error: argument -f: invalid choice: 'x' (choose from [1, 2, 3], 'astring') 0945:~/mypy$ python3 issue42191.py -g x usage: issue42191.py [-h] [-f {[1, 2, 3],astring}] [-g {a,b}] issue42191.py: error: argument -g: invalid choice: 'x' (choose from 'a', 'b') With -g, we have to perform the dictionary lookup after parsing, but choices, {a,b}, are clear in both the help and error. With -f, both the help (which uses str) and the error, give wrong user choices, the dictionary values rather than the keys. -- ___ Python tracker <https://bugs.python.org/issue42191> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42191] lib.argparse._check_value() using repr instead of str
paul j3 added the comment: In the Help formatting, choice_strs = [str(choice) for choice in action.choices] The use of `repr` in this check_value() error message was, I think, deliberate. For simple choices like strings and numbers it doesn't matter. But for other cases, it may help to know more about the identify of the choice objects, such as their class. The actual parsing test is just a 'in' test. value not in action.choices There is the added complication that the _get_value() function has already applied the type function the argument string, converting it to a compatible object (for testing). Should argparse be changed, or should it be up to the developer to use a type/choices pairing that gives the desired help and error messages? To improve the discussion, I think your 'self.admin' example should be replaced by a self contained type and class. In the spirit of a StackOverFlow question I'd like concrete minimal example that I can test and play with. I don't want to write a pseudo-account class. -- ___ Python tracker <https://bugs.python.org/issue42191> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42105] allow_abbrev not working as intended in "argparse.ArgumentParser" in Python 3.9.0
paul j3 added the comment: argparse : allow_abbrev behavior between 3.7 and 3.8 https://bugs.python.org/issue41534 covers this issue well enough. That latest change to `allow_abbrev` was prompted by: argparse: allow_abbrev=False stops -vv from working https://bugs.python.org/issue26967 You also raised this issue on StackOverFlow. That may be a better place to discuss this. -- stage: -> resolved status: open -> closed ___ Python tracker <https://bugs.python.org/issue42105> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue40509] In argparse, allow REMAINDER(...) arguments in a mutually exclusive group
paul j3 added the comment: A more recent issue shows that the use of a '*' positional in a multually_exclusive_group is poorly understood and documented. https://bugs.python.org/issue41854 That's part of why I am not enthusiastic about extending this to include REMAINDER. And on rereading Shani's posts, I realize I don't understand what this has to do with subcommands. Is this the 'add_subparsers' mechanism, or just the idea of using a trailing part of sys.argv as input to another parser or script? I think discussion of this topic can only proceed with some concrete examples, and may be even a proposed code change (not necessarily a formal patch or pull request). -- ___ Python tracker <https://bugs.python.org/issue40509> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41854] argparse.add_mutually_exclusive_group fails for optional positional arguments
paul j3 added the comment: Give the positional a non-none default: e.g. group.add_argument('args', metavar='ARGUMENT', nargs='*', default=[], help='arguments to PROGRAM') Since a '*' or '?' positional works with an empty list of arguments, it is "always seen". It requires some special handling to allow it to work in the mutually exclusive context. It's a tricky piece of code that might not be well documented (if at all). -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue41854> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42023] Argparse: Add a "display" arg
paul j3 added the comment: Some StackOverFlow answers cusomizing this help method: https://stackoverflow.com/questions/23936145/python-argparse-help-message-disable-metavar-for-short-options https://stackoverflow.com/questions/18275023/dont-show-long-options-twice-in-print-help-from-argparse -- ___ Python tracker <https://bugs.python.org/issue42023> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42023] Argparse: Add a "display" arg
paul j3 added the comment: That method could be customized in a HelpFormatter subclass. There already are several subclasses (documented), and writing your own is allowed, if not actually encouraged. https://docs.python.org/3/library/argparse.html#formatter-class Adding an extra parameter to 'add_argument', and passing that on through the Action class (and subclasses) is, potentially, a bigger task. So if you can get by with just customizing _format_action_invocation, there's no need for further action here. I'll look for some examples, here or on SO, of customizing this method. -- ___ Python tracker <https://bugs.python.org/issue42023> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42023] Argparse: Add a "display" arg
paul j3 added the comment: I'm not following this request either, especially the colored part. However, I can imagine adding a variable that gives the user full control over the action-invocation. In: argparse.HelpFormatter._format_action_invocation method. Currently it accepts the metavar (but not the tuple version) for a positional, but for optionals constructs: -s ARGS, --long ARGS This can be quite long and ugly if the ARGS is a long choices, or there are many flag alternatives. A number of SO users have asked for something simpler, usually with just on flag or -s, --long ARGS There may even be a bug/issue(s) related to this already. -- ___ Python tracker <https://bugs.python.org/issue42023> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41980] Argparse documentation is slightly misleading
paul j3 added the comment: For ArgumentParser, prog is defined as: prog - The name of the program (default: sys.argv[0]) The comment in the `add_subparsers` method is: # prog defaults to the usage message of this parser, skipping # optional arguments and with no "usage:" prefix if kwargs.get('prog') is None: formatter = self._get_formatter() positionals = self._get_positional_actions() groups = self._mutually_exclusive_groups formatter.add_usage(self.usage, positionals, groups, '') kwargs['prog'] = formatter.format_help().strip() and this keyword is saved as the action `self._prog_prefix. Later in `add_parser` this is amended with: kwargs['prog'] = '%s %s' % (self._prog_prefix, name) The intent is to provide the string required to run a particular subparser (sub-command), the `prog` of the main, positionals, and the subcommand. (It doesn't handle all 'required' arguments correctly.) The programmer has three places where they can customize this 'prog'. So the default 'prog' as the 'add_subarsers' level is indeed just the main 'prog' plus 'positionals'. The default 'prog' display with the subcommand usage add the subcommand's name. It's a complicated sequence, but I think the description for the 'add_subparsers' 'prog' is enough. -- ___ Python tracker <https://bugs.python.org/issue41980> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41769] Positional arguments with boolean actions behave differently
paul j3 added the comment: 'store_true/false' are subclasses of 'store_const'. All have a 'nargs=0' value. It's that value which explains their behavior. ('append_const' would also fall in this category) In [2]: parser = argparse.ArgumentParser() In [3]: parser.add_argument('foo', action='store_const', default='xxx', const='yyy') Out[3]: _StoreConstAction(option_strings=[], dest='foo', nargs=0, const='yyy', default='xxx', type=None, choices=None, help=None, metavar=None) In [4]: _.required Out[4]: True In [5]: parser.print_help() usage: ipython3 [-h] positional arguments: foo optional arguments: -h, --help show this help message and exit In [6]: parser.parse_args([]) Out[6]: Namespace(foo='yyy') In [7]: parser.parse_args(['zzz']) usage: ipython3 [-h] ipython3: error: unrecognized arguments: zzz --- Like '*' and '?' this argument is 'satisfied' with nothing, an empty list of values. For those nargs, 'get_values' takes a the special step of assigning the default. For 'store_const' it's the 'const' that's placed in the namespace. 'store_true' does store True, and 'store_false' does store False. Providing a string produces an error because there isn't any Action to consume it. With nargs=0, this Action can't use it. Usage is also correct since we can't provide any string to meet this Action's needs. Technically then the Action behaves correctly - both in usage and what it does. That said, it normally isn't useful, since it will always assign the 'const/True/False' to the namespace. Even without an in depth knowledge of how parsing is done, this should be logically evident (if not obvious). I don't recall any previous issues like this, though I wouldn't be surprised if there were. I don't recall anything on Stackoverflow either. I think adding an error would be overkill. It doesn't come up often, and some user might have their own obscure reason for using it. A note to the docs might be in order, but until a user has encountered this behavior as you have, such a note might be more confusing than useful. As a general rule, parameter checking in add_argument() is rather loose (and multilayered). While 'action' is used to select the Action subclass, most of the rest are passed on to that Action. The Action __init__ check a few key parameters (for example 'store_const' will complain if we don't provide a 'const'), but accept or ignore the rest. -- nosy: +paul.j3 ___ Python tracker <https://bugs.python.org/issue41769> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41684] argparse: unexpected subparser behaviour on parse_args with namespace option
Change by paul j3 : -- stage: -> resolved status: open -> closed ___ Python tracker <https://bugs.python.org/issue41684> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41534] argparse : allow_abbrev behavior between 3.7 and 3.8
paul j3 added the comment: I'm going to close this. 3.8 works as expected/documented, provided we use the normal double dash protocol for long options. Single dash is best reserved for single character options, where chaining is allowed. -- stage: -> resolved status: open -> closed ___ Python tracker <https://bugs.python.org/issue41534> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41684] argparse: unexpected subparser behaviour on parse_args with namespace option
paul j3 added the comment: When there are potential conflicts between arguments set by the main parser and those set by a subparser, I often recommend giving the sub ones different "dest" parameters. Then you can reconcile the different values after parsing. There's nothing wrong with a bit of post-parsing value checking and adjustment. The primary purpose of the parser is to identify what the user wants, and secondarily to give useful help and error messages. -- ___ Python tracker <https://bugs.python.org/issue41684> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41684] argparse: unexpected subparser behaviour on parse_args with namespace option
paul j3 added the comment: I've noted this behavior before. https://bugs.python.org/issue27859 argparse - subparsers does not retain namespace https://bugs.python.org/issue9351 argparse set_defaults on subcommands should override top level set_defaults Due to a change 2012, the subparser gets a new blank `namespace`. When done those values are copied to the main namespace. That gives subparser defaults priority over both the main ones, and the user provided namespace. I don't entirely like that change, but it was made by the original developer. -- ___ Python tracker <https://bugs.python.org/issue41684> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41534] argparse : allow_abbrev behavior between 3.7 and 3.8
paul j3 added the comment: In your first example: In [29]: parser = argparse39.ArgumentParser(allow_abbrev=True) In [30]: parser.add_argument('-o'); In [32]: parser.parse_known_args(['-o','test']) Out[32]: (Namespace(o='test'), []) In [33]: parser.parse_known_args(['-object','test']) Out[33]: (Namespace(o='bject'), ['test']) Here the '-object' is interpreted as '-o' flag, with value the rest of the string. That's normal behavior for a short option. In [34]: parser.parse_known_args(['-o','test1','-object','test2']) Out[34]: (Namespace(o='bject'), ['test2']) Same thing only '-object' has overwritten the 'test1' value. In your second example: In [39]: parser = argparse39.ArgumentParser(allow_abbrev=False) In [40]: parser.add_argument('-verbose'); In [42]: parser.parse_known_args(['-v', '-verbose=2']) usage: ipython3 [-h] [-verbose VERBOSE] ipython3: error: argument -verbose: expected one argument Expected uses: In [46]: parser.parse_known_args(['-verbose','two']) Out[46]: (Namespace(verbose='two'), []) In [47]: parser.parse_known_args(['-verbose=2']) Out[47]: (Namespace(verbose='2'), []) The '-ver' is not accepted as abbreviation: In [48]: parser.parse_known_args(['-ver=2']) Out[48]: (Namespace(verbose=None), ['-ver=2']) 'allow_abbrev' doesn't have effect because of '-verbose' If instead I define '--verbose', I can turn the abbrev on/off: In [49]: parser = argparse39.ArgumentParser(allow_abbrev=False) In [50]: parser.add_argument('--verbose'); In [51]: parser.parse_known_args(['-ver=2']) Out[51]: (Namespace(verbose=None), ['-ver=2']) In [52]: parser.parse_known_args(['--ver=2']) Out[52]: (Namespace(verbose=None), ['--ver=2']) In [53]: parser.allow_abbrev=True In [54]: parser.parse_known_args(['--ver=2']) Out[54]: (Namespace(verbose='2'), []) There are a lot of variations to examine here. The original, the 3.7, and 3.8 versions. abbrev False or True. Proper long option (--), improper etc. -- ___ Python tracker <https://bugs.python.org/issue41534> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41600] Expected behavior of argparse given quoted strings
paul j3 added the comment: I'd say the problem is with the deployment tool. Inputs like that should be split regardless of who's doing the commandline parsing. With normal shell input, quotes are used to prevent splitting, or to otherwise prevent substitutions and special character handling. -- ___ Python tracker <https://bugs.python.org/issue41600> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41359] argparse mutually exclusive group does not exclude in some cases
paul j3 added the comment: This is the result of how default values are handled with '?' (and '*') nargs. At the start of nested `take_action` function (which handles all actions) is this code: argument_values = self._get_values(action, argument_strings) # error if this argument is not allowed with other previously # seen arguments, assuming that actions that use the default # value don't really count as "present" if argument_values is not action.default: seen_non_default_actions.add(action) for conflict_action in action_conflicts.get(action, []): if conflict_action in seen_non_default_actions: msg = _('not allowed with argument %s') action_name = _get_action_name(conflict_action) raise ArgumentError(action, msg % action_name) 'get_values' gets the values for this action. A bare '-b' will be given its 'default'. An optional positional is always 'seen', since an empty list satisfies its 'nargs'. 'get_values' assigns the default instead. This code in take_action allows us to include such positionals in a mutually exclusive group. This handing of the '?' optional is a byproduct of that code. Normally we provide both a 'default' and a 'const' with such an argument, giving us a 3-way switch (default, const or user-value). If either 'default' or 'const' is provided, your '-b' will behave as expected. I have a feeling that trying to document this edge case will just make things more confusing. -- ___ Python tracker <https://bugs.python.org/issue41359> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9351] argparse set_defaults on subcommands should override top level set_defaults
paul j3 added the comment: I just realized if the subparser argument used default=argparse.SUPPRESS it would not clobber values (default or user) set by the main parser. (a 'store_true' would have to be replaced with a 'store_const' to do this) -- ___ Python tracker <https://bugs.python.org/issue9351> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41255] Argparse.parse_args exits on unrecognized option with exit_on_error=False
paul j3 added the comment: The docs could change "catch errors manually" to "catch ArgumentError manually" But while 'argparse.ArgumentError' is imported, it is not documented. We have to study the code to learn when it is raised. Its class def: def __init__(self, argument, message): shows it's tied to a specific 'argument', an Action object. Most commonly it is produced by reraising a ValueError, TypeError or ArgumentTypeError during the check_values step. Unrecognized arguments, and missing required arguments errors aren't produced while processing an argument, but rather while checking things after parsing. So they can't raise an ArgumentError, and aren't handled by this new parameter. I found a old issue that discusses this https://bugs.python.org/issue9938, https://github.com/python/cpython/pull/15362 There wasn't much discussion about the scope of this change, or about the documentation wording. My only comment was in 2013, https://bugs.python.org/msg192147 Until we iron out the wording I think this patch should be reverted. While exploring other problems, I thought it would be a good idea of refactor parse_known_args and _parse_known_args. Specifically I'd move the 'required' testing and self.error() calls out of _parse_known_args, allowing a developer to write their own versions of parse_known_args. The goal was to make it easier to test for mixes of seen and unseen arguments. In light of the current issue, we might want to look into consolidating all (or at least most) of the calls to self.error() in one function. Until then, the documented idea of modifying the error() method itself is the best user/developer tool, https://docs.python.org/3.10/library/argparse.html#exiting-methods -- ___ Python tracker <https://bugs.python.org/issue41255> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41255] Argparse.parse_args exits on unrecognized option with exit_on_error=False
paul j3 added the comment: For custom handling of unrecognized arguments, use parser_known_args(). You don't need this new parameter. -- ___ Python tracker <https://bugs.python.org/issue41255> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41255] Argparse.parse_args exits on unrecognized option with exit_on_error=False
paul j3 added the comment: I didn't pay attention to the patch that added this "exit_on_error" parameter. So I don't know exactly what error handling it was supposed to handle or why. But given the location of the code change, it does not handle every possible error. Specifically it's in parser.parse_known_args() where it calls _parse_known_args(). With this parameter True, a argparse.ArgumentError is caught and converted to parse.error() call. That's the original behavior. With False, there's no special handling for ArgumentError. Catching that is left to the developer, as illustrated in the docs. In the documented example, it's a 'type' error. 'choices' would also behave this way. 'nargs' errors also. But not all errors are handled like this. Inside _parse_known_args(), `self.error()` is called several times, once for 'required' arguments failure, and for a required mutually_exclusive_group error. I count 9 self.error() calls; exit_on_error only changes one of those. The error highlighted in this issue is called in parser.parse_args(). This calls parse_known_args(), and raises an error if there are 'extras', unrecognized strings. So clearly the new docs is is describing this new parameter in overly broad terms. It only changes the handling of a subset of parser.error() calls. Off hand I can't think of clean way of refining the description without getting overly technical about the error handling. Developers already had the documented option of changing the parse.error() and parse.exit() methods. -- ___ Python tracker <https://bugs.python.org/issue41255> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com