[issue14156] argparse.FileType for '-' doesn't work for a mode of 'rb'
Changes by paul j3 ajipa...@gmail.com: -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue14156 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue20970] contradictory documentation for prog option of argparse
paul j3 added the comment: Cross reference for sys.argv[0] is http://docs.python.org/3.4/library/sys.html ___ -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue20970 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue20970] contradictory documentation for prog option of argparse
paul j3 added the comment: Yes, the documentation is accurate but a bit vague. It doesn't say how 'it uses sys.arg[0]'. The example implies it uses 'basename'. So the question is, whether that implementation detail should be more explicit? -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue20970 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue20970] contradictory documentation for prog option of argparse
paul j3 added the comment: The relevant code is: prog = _os.path.basename(_sys.argv[0]) -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue20970 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11588] Add necessarily inclusive groups to argparse
paul j3 added the comment: A couple more thoughts on an expanded argument testing mechanism: - do we need both 'seen_actions' and 'seen_non_default_actions'? 'seen_actions' is used only to test whether all required actions have been seen. These 2 sets differ in how positionals with '?*' are categorized. Positionals like this are always 'seen', even if they just get the default value. But they are not required (the case of a '*' positional without default needs to be revisited.) - If 'seen_non_default_actions' is changed to a list (currently its a set), users could test for repeated use on an optional, or even the order of arguments. - One way to make this testing mechanism more user-friendly is to provide convenience functions via a decorator. For example the decorator could wrap the 'seen_non_default_actions' argument in a 'seen' function. Such a function could accept either an Action or a 'dest' string, it could accept a single Action, or a list of them, etc. There could be other functions like 'count', 'unique', 'mutually_exclusive', 'inclusive', etc. def testwfnc(func): # decorator to register function and provide 'seen' name = func.__name__ def wrapped(parser, seen_actions, *args): def seen(*args): actions = seen_actions if isinstance(args[0], str): actions = [a.dest for a in actions] if len(args)1: return [a in actions for a in args] else: return args[0] in actions return func(parser, seen) parser.register('cross_tests', name, wrapped) return wrapped #@testwfnc def test(parser, seen, *args): if seen(a_file): print(seen(a_dir, a_pat, a_suf)) cnt = sum(seen(a_dir, a_pat, a_suf)) if cnt0: parser.error('FILE cannot have DIR, PATTERN or SUFFIX') ... The attached script experiments with several versions of decorators. Some sort of testing Class is probably the way to go if we want to provide many convenience methods. -- Added file: http://bugs.python.org/file34285/issue11588_4.py ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11588 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18943] argparse: default args in mutually exclusive groups
paul j3 added the comment: I need to tweak the last patch so 'using_default' is also set when an nargs='*' positional is set to the '[]' default. if action.default is not None: value = action.default +using_default = True else: value = arg_strings +using_default = True # tweak -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18943 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue10984] argparse add_mutually_exclusive_group should accept existing arguments to register conflicts
paul j3 added the comment: In http://bugs.python.org/issue11588 (Add necessarily inclusive groups to argparse) I propose a generalization to these testing groups that would solve your 'conflicter' case as follows: usage = 'prog [ --conflicter | [ --opt1 ] [ --opt2 ] ]' parser = argparse.ArgumentParser(usage=usage) conflicter = parser.add_argument(--conflicter, action='store_true') opt1 = parser.add_argument(--opt1, action='store_true') opt2 = parser.add_argument(--opt2, action='store_true') @parser.crosstest def test(parser, seen_actions, *args): if conflicter in seen_actions: if 0len(seen_actions.intersection([opt1, opt2])): parser.error('--conflicter cannot be used with --opt1 or --opt2') Groups, as currently defined, cannot handle nesting, and as a consequence cannot handle complex logic. My proposal is to replace groups with user defined conflict tests that would be run near the end of 'parse_args'. This example shows, I think, that the proposal is powerful enough. I'm not sure about ease of use and logical transparency. Formatting the usage line is a different issue, though the MultiGroupHelpFormatter that I propose here is a step in the right direction. For now a user written 'usage' is the simplest solution. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue10984 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11588] Add necessarily inclusive groups to argparse
paul j3 added the comment: The addition of a simple decorator to the 'ArgumentParser' class, would simplify registering the tests: def crosstest(self, func): # decorator to facilitate adding these functions name = func.__name__ self.register('cross_tests', name, func) which would be used as: @parser.crosstest def pat_or_suf(parser, seen_actions, *args): if 2==len(seen_actions.intersection([a_pat, a_suf])): parser.error('only one of PATTERN and SUFFIX allowed') -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11588 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11588] Add necessarily inclusive groups to argparse
paul j3 added the comment: This is an example of using 'patch_w_mxg2.diff' to handle the inclusive group case proposed by the OP. Since 'seen_non_default_actions' (and 'seen_actions') is a set of 'Actions', it is convenient to use 'set' methods with pointers to the actions that a collected during setup. Tests could also be done with the 'dest' or other action attributes. In this example I wrote 3 simple tests corresponding to the 3 proposed groups, but they could also have been written as one test. a_file= parser.add_argument(-o, --outfile, metavar='FILE') a_dir = parser.add_argument(-O, --outdir, metavar='DIR') a_pat = parser.add_argument(-p, --outpattern, metavar='PATTERN') a_suf = parser.add_argument(-s, --outsuffix, metavar='SUFFIX') ... def dir_inclusive(parser, seen_actions, *args): if a_dir in seen_actions: if 0==len(seen_actions.intersection([a_pat, a_suf])): parser.error('DIR requires PATTERN or SUFFIX') parser.register('cross_tests', 'dir_inclusive', dir_inclusive) ... In theory tests like this could be generated from groups as proposed by the OP. There is one case in 'test_argparse.py' where a mutually_exclusive_group is nested in an argument_group. But the current groups do not implement nesting. A (plain) argument_group does not share its '_group_actions' list with its 'container'. A mutually_exclusive_group shares its '_group_actions' but the result is a flat list (no nesting). For now I think it is more useful to give users tools to write custom 'cross_tests' than to generalize the 'group' classes. -- Added file: http://bugs.python.org/file34193/example1.py ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11588 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11588] Add necessarily inclusive groups to argparse
paul j3 added the comment: This patch uses: tests = self._registries['cross_tests'].values() to get a list of functions to run at the end of '_parse_known_args'. I replaced all of the mutually_exclusive_group tests (3 places) in the ArgumentParser with a static function defined in class _MutuallyExclusiveGroup, and registered this function. This refactoring should make it easier to add other specialized groups (e.g. inclusive) in the future. I'm using the _registries because they are already being shared among groups. A user can also register a custom testing function. For example: def inclusive_test(parser, seen, *args): # require an argument from one of the 2 groups, g0 and g1 g0seen = seen.intersection(g0._group_actions) g1seen = seen.intersection(g1._group_actions) if len(g0seen.union(g1seen))==0: parser.error('one of the 2 groups is required') parser.register('cross_tests','inclusive', inclusive_test) This patched 'argparse.py' runs 'test_argparse.py' without error. This patch does not include the issue18943 changes, which make setting 'seen_non_default_actions' more reliable. -- keywords: +patch Added file: http://bugs.python.org/file34176/patch_w_mxg2.diff ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11588 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18943] argparse: default args in mutually exclusive groups
paul j3 added the comment: This patch corrects the handling of `seen_non_default_action` in another case - a positional with '?' and `type=int` (or other conversion). if parser.add_argument('badger', type=int, nargs='?', default=2) # or '2' and the original test 'seen_non_default_actions' is: if argument_values is not action.default 'argument_values' will be an 'int' regardless of the default. But it will pass the 'is' test with the (small) int default but not the string default. With the patch proposed here, both defaults behave the same - 'badger' will not appear in 'seen_non_default_actions' if it did not occur in the argument_strings (i.e. match an empty string). I may add case like this to `test_argparse.py` for this patch. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18943 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11588] Add necessarily inclusive groups to argparse
paul j3 added the comment: The suggestion in this issue is to add a 'mutually_inclusive_group' mechanism, one that would let users specify that certain sets of arguments must occur together. Furthermore there was mention of allowing some sort of nesting. Modeling it on the mutually_exclusive_group would be straight forward. But should it affect the usage and help display?mutually_exclusive_groups add a messy layer to the usage formatting. The only place such a group would act would be at the end of '_parse_known_args', where the current code checks for things like required actions (and mxgroups). A test at this point could use 'namespace', 'seen_actions' and 'seen_non_default_actions' to check whether the required group actions were seen. But the only thing that the argument_group contributes to this test is a list of argument names ('dest'?). Why not provide this list directly? And what if the user wants A to occur together with either B or C, but not both? Or make the inclusivity conditional on the value of A? Currently users can define argument interactions in a couple of ways. They can define custom Actions. In test_argparse.py there's a custom Actions test that does something like this (using '--spam' and 'badger'). But tests in Actions depend on the order in which arguments are given. An alternative is to test for interactions of arguments after `parse_args`. However the only information that the user has at this point is the args namespace. Reliably distinguishing between non-occurrence of arguments and default values can be difficult. I am proposing 'cross_test' mechanism that would give the user access to the 'seen_actions' and 'seen_non_default_actions' sets that 'mutually_exclusive_groups' use. Specifically an optional function can be called at the end of '_parse_known_args' that has access to these sets as well as the parser and the namespace. The core of the change would be adding cross_test = getattr(self, 'cross_test', None) if cross_test: cross_test(self, namespace, extras, seen_actions, seen_non_default_actions) at the end of 'parser._parse_known_args'. In addition 'cross_test' (or some other name) could be added to the 'ArgumentParser.__init__' arguments. The feature could be used by defining such a 'cross_test' function and adding it to the parser (either instance or subclass) def foobar(self, namespace, extras, seen_actions, seen_non_default_actions): ... (raise self.error(...)) parser.cross_test = foobar The patch proposed http://bugs.python.org/issue18943 should be included with any changes here since it refines the setting of 'seen_non_default_actions'. I am working on tests and examples of such functionality. -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11588 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11588] Add necessarily inclusive groups to argparse
paul j3 added the comment: Regarding a usage line like: (-o FILE | (-O DIR (-p PATTERN | -s SUFFIX)) The simplest option is to just a custom written 'usage' parameter. With the existing HelpFormatter, a nested grouping like this is next to impossible. It formats the arguments (e.g.'-O DIR'), interleaves the group symbols, and then trims out the excess spaces and symbols. http://bugs.python.org/issue10984 is a request to allow overlapping mutually_exclusive_groups. It loops on the groups, formatting each. It would be easier with that to format several different types of groups, and to handle nested ones. What would it take to convert a usage string like that into a logical expression that tests for the proper occurrence (or non-occurrence) of the various arguments. It might, for example be converted to exc(file, inc(dir, exc(pattern, suffix))) where 'exc' and 'inc' are exclusive and inclusive tests, and 'file','dir' etc are booleans. And what would be the error message(s) if this expression fails? I can imagine a factory function that would take usage line (or other expression of groupings), and produce a function that would implement a cross_test (as outlined in my previous post). It would be, in effect, a micro-language compiler. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11588 ___ ___ 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: The attached file shows how the default argument groups could be redefined, using 'required' as the criteria. I've implemented it as a method that is added to a subclass of ArgumentParser. This method is invoked after arguments are defined, prior to generating the help. The help looks something like this: usage: alt_grouping.py [-h] [-f FOO] -g GOO pos [baz] required: posrequired positional -g GOO, --goo GOO required optional optional: -h, --help show this help message and exit -f FOO, --foo FOO optional bazoptional positional I was thinking of implementing this as a formatter subclass, but given the way the help is assembled, invoking this method from the parser is simpler. -- Added file: http://bugs.python.org/file34065/alt_grouping.py ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9694 ___ ___ 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: Here's another possible solution: add a `help_groups` parameter to ArgumentParser. It is a list of base argument group names. `parser.add_argument(...)' places the action in one of those groups. This is a generalization of the current code which creates two groups titled 'positional arguments' and 'optional arguments', and assigns actions based on 'optional strings' (e.g. '-f','--foo'). 'help_groups' could have 1, 2, or 3 items. 1 - just one argument group 2 - the current postional/optional split, but with user chosen names 3 - a 'positional', 'required', and 'optional' split. A 4 way split that distinguishes splits positionals between those that allow 0 values and 1 or more, is possible, but probably not that useful. The changes are in the ArgumentParser.__init__ and _add_action methods. 'subparsers' do not inherit this parameter. I have not explored how it plays out with 'parents'. 'test_argparse.py' runs fine. -- keywords: +patch Added file: http://bugs.python.org/file34073/helpgroups.diff ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9694 ___ ___ 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
Changes by paul j3 ajipa...@gmail.com: Added file: http://bugs.python.org/file34074/alt_grouping2.py ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9694 ___ ___ 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: As Steven pointed out, the existing `add_argument_group` mechanism can be used to group required arguments. For example - temp.py -- parser = argparse.ArgumentParser(description = 'Do something') group1 = parser.add_argument_group('required arguments') group1.add_argument('--reqarg', '-r', required=True) parser.add_argument('--optarg','-o') parser.add_argument('foo') parser.print_help() usage: ipython [-h] --reqarg REQARG [--optarg OPTARG] foo Do something positional arguments: foo optional arguments: -h, --helpshow this help message and exit --optarg OPTARG, -o OPTARG required arguments: --reqarg REQARG, -r REQARG Positional 'foo' can also be put in the 'required' group: group1.add_argument('foo') required arguments: --reqarg REQARG, -r REQARG foo The distinction between 'positionals' and 'optionals' (or flagged) is essential to the parsing, but it is not necessary for Help Formatting. I can imagine grouping arguments by 'required/not-required' properties. It might be worth constructing an alternative HelpFormatter class that regroups the arguments in this way. Subclassing the HelpFormatter is the established way of adding features to the help display. The existing HelpFormatter flags 'required' arguments in the usage line with '[]'. There it is has the added task of flagging Mutually Exclusive Groups in the same way. It's worth keeping in mind that whether an argument is 'required' or not is determined in 2 different ways. There is an optional 'required' flag (default False). But this flag is not allowed for 'positionals'. Instead with those 'argparse' looks at 'nargs' ('?*' are not required). The 'required' attribute of an argument (Action) is ignored during 'parse_args' until the end. At that time it makes an inventory of 'required' arguments that have not been seen, and potentially raises an error. That testing was changed in a relatively recent patch, and produced an unintended change in whether 'subparsers' were required or not. (I could look up those issues in needed). I'll think about creating the alternative HelpFormatter. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9694 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue20039] Missing documentation for argparse.ArgumentTypeError
paul j3 added the comment: In argparse.py the status of ArgumentTypeError is ambiguous. ArgumentError is listed as a public class, ArgumentTypeError is not. It also says 'All other classes in this module are considered implementation details.' ArgumentTypeError is a subclass of Exception (with no added functionality). ArgumentTypeError is raised only once, in the FileType class (which is both a scripting convenience and example of a custom type). As you note it is also used in the documentation example. There is also one such example in test_argparse.py. It is caught once, where it is converted into an ArgumentError. It is handled much like a ValueError or TypeError - except that its message is passed through unchanged. In http://bugs.python.org/issue13824 I use it several times in the FileContext class for just this reason. In fact ArgumentTypeError could be documented as a footnote to the `type` block, saying to the effect: 'An ArgumentTypeError may be raised (instead of a ValueError or TypeError) to produce a custom error message.' Normally an ArgumentTypeError is not passed back to the user code, consistent with the claim that it is not public. -- Along the same line, should ArgumentError be documented better? Currently it is just mentioned at the end, as a replacement for an optparse error class. As best I can tell, the user code will only see an ArgumentError if the ArgumentParser.error method is customized. Otherwise that error is caught and converted into a system exit. Maybe the `error` paragraph in the documentation should get a sentence about ArgumentError. In test_argparse.py, ArgumentError is used extensively (with a custom error method). -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue20039 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue19959] argparse.FileType does not expand tilde ~
paul j3 added the comment: Normally the unix shell takes care of this expansion. If I call a simple script that prints sys.argv and runs a simple parser, I get: 2135:~/mypy$ python2.7 filetypetest.py ~/mypy/test.txt ['filetypetest.py', '/home/paul/mypy/test.txt'] Namespace(file=open file '/home/paul/mypy/test.txt', mode 'r'...) I have to quote the argument '~/mypy/test.blog' to bypass this expansion. This is under Linux (bash). Is Windows or Mac different? My impression is that `FileType` has been provided as an example of a custom `type`, as opposed to a comprehensive file handler. But I can't quote a developer on this. http://bugs.python.org/issue13824 is a bug report that worries that 'argparse.FileType opens a file and never closes it'. There are some comments there about whether it is appropriate to expand on the capabilities of FileType. -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue19959 ___ ___ 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: With a minor tweak to `argparse._is_mnrep()`, `nargs='{3}'` would also work. This means the same as `nargs=3`, so it isn't needed. But it is consistent with the idea of accepting Regular Expression syntax where it makes sense. `nargs='{2,3}?'` also works, though I think that's just the same as `nargs=2`. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11354 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue19814] Document prefix matching behavior of argparse, particularly for parse_known_args
paul j3 added the comment: `parse_args` just calls `parse_known_args`, and then raises an error if `rest` is not empty. So it is `parse_known_args` that is doing the abbreviation matching. Abbreviation matching is done relatively early, when `_parse_known_args` first loops through the strings, trying to decide which are arguments ('A') and which are options ('O'). This matching is done in `_parse_optional`. It's not something it does at the end on the 'leftovers'. http://bugs.python.org/issue14910, a disable abbreviation option, might be a better solution. Your example is an argument in favor of implementing that feature. Unless a reader has your example in mind, the proposed documentation warning might be more confusing than helpful. -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue19814 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14910] argparse: disable abbreviation
paul j3 added the comment: For a programmer who needs to turn off this abbreviation matching now, a simple solution is to subclass ArgumentParser: class MyParser(ArgumentParser): def _get_option_tuples(self, option_string): return [] This could be the place to implement more specialized matching (e.g. do not match on strings like '--sync'). -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue14910 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue17204] argparser's subparsers.add_parser() should accept an ArgumentParser
paul j3 added the comment: http://stackoverflow.com/a/20167038/901925 is an example of using `_parser_class` to produce different behavior in the subparsers. parser = ArgumentParser() parser.add_argument('foo') sp = parser.add_subparsers(dest='cmd') sp._parser_class = SubParser # use different parser class for subparsers spp1 = sp.add_parser('cmd1') spp1.add_argument('-x') spp1.add_argument('bar') spp1.add_argument('vars',nargs='*') In this case the SubParser class implements a `parse_intermixed_known_args` method that handles that `nargs='*'` argument. http://bugs.python.org/issue14191 It shouldn't be hard to add `parser_class` as a documented optional argument to `add_subparsers`. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue17204 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue19462] Add remove_argument() method to argparse.ArgumentParser
paul j3 added the comment: f.nargs = '?' f.default = argparse.SUPPRESS f.help = argparse.SUPPRESS may be best set of tweaks to a positional Action `f`. In quick tests it removes `f` from the help, suppresses any complaints about a missing string, and does not put anything in the namespace. But if there is a string in the input that could match this positional, it will be use. f.nargs = 0 is another option. This puts a `[]` (empty list) in the namespace, since 'nothing' matches `f`. If there is an input string that might have matched it before, you will not get an 'unrecognized argument' error. `parse_known_args` can be used to get around that issue. I should stress, though, that fiddling with `nargs` like this is not part of the API. Tweak this at your own risk. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue19462 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue19462] Add remove_argument() method to argparse.ArgumentParser
paul j3 added the comment: `argparse.SUPPRESS` should do the trick. According to the documentation it can be used with `default` and `help` parameters. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue19462 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue19462] Add remove_argument() method to argparse.ArgumentParser
paul j3 added the comment: When you add an argument, argparse creates an `Action`, and returns it. It also places that action in various lists (e.g. parse._actions) and dictionaries. A `remove_argument` function would have to trace and remove all of those links. That's a non-trivial task. However modifying an argument (or Action) is much easier, since there is only one instance. Obviously some modifications will be safer than others. For example: parser = ArgumentParser() a = parser.add_argument('--foo') print a produces: _StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None) `vars(a)` gives a somewhat longer list of attributes. Within reason, those attributes can be changed directly. I think the 'dest', 'help', 'nargs', 'metavar' could all be changed without hidden effects. There's also a 'required' attribute that could be changed for optionals. Changing the 'option_strings' might be problematic, since the parser has a dictionary using those strings as keys. The constant `argparse.SUPPRESS` is used in several places to alter actions. For example, to suppress the help, or to suppress default values in the Namespace. So it might be possible to 'hide' arguments in the subclass, even if you can't remove them. In http://bugs.python.org/issue14191 I explored a couple of ways of temporarily 'deactivating' certain groups of arguments, so as to parse the optionals and positionals separately. It's an advance issue, but might still give some ideas. Another possibility is to use 'parent' parsers to define clusters of arguments. Your base class could create a parser with one set of parents, and the subclass could use a different set. -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue19462 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue19462] Add remove_argument() method to argparse.ArgumentParser
paul j3 added the comment: Just hang on the Action object that the `add_argument` returned, and change its `help` attribute. a = parser.add_argument('--foo', help='initial help') a.help = 'new help' If using a custom parser class and subclass, I'd do something like: self.changeablearg = self.parser.add_argument... in the class, and self.changeablearg.help = 'new help' in the subclass You can test the help message with print parser.format_help() -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue19462 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9338] argparse optionals with nargs='?', '*' or '+' can't be followed by positionals
paul j3 added the comment: parse_args() would see ['-foo', 'bar1,bar2,bar3', 'pos1', 'pos2']. The splitting on space is done by the shell. So having your own code split 'bar1,bar2,bar3' is simplest. But that would be messed up if the user entered 'bar1, bar2, bar3...'. You could also ask the user to use quotes - bar1, bar2, bar3. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9338 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue15613] argparse ArgumentDefaultsHelpFormatter interacts badly with --arg and nargs=+
paul j3 added the comment: Looks like this behavior is intentional. This subclass adds a '%(default)s' string to the help lines if: if '%(default)' not in action.help: if action.default is not SUPPRESS: defaulting_nargs = [OPTIONAL, ZERO_OR_MORE] if action.option_strings or action.nargs in defaulting_nargs: help += ' (default: %(default)s)' So it adds the default if it is an `optional`, or a `positional` with '*' or '?'. A `default` value for a required positional (including '+') does not make sense, since the user input always overwrites the default. (I recommend closing this issue). -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue15613 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14365] argparse: subparsers, argument abbreviations and ambiguous option
paul j3 added the comment: I think the correction to the problem that I noted in the previous post is to return 'None, arg_string, None', rather than 'action, arg_string, None' in the case where the action is found in a subparser. This is what '_parse_optional' does at the end: # it was meant to be an optional but there is no such option # in this parser (though it might be a valid option in a subparser) return None, arg_string, None An input like '--foo baz' would then produce an 'invalid choice' error. Since '--foo' is an optional that the primary parser does not recognize, 'baz' in interpreted as a positional, in this case an invalid subparser choice. I'm working on cleaning up a test script. -- Added file: http://bugs.python.org/file31888/subparser_patch.diff ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue14365 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14365] argparse: subparsers, argument abbreviations and ambiguous option
paul j3 added the comment: In the last patch, 'parser.scan = True' is needed to activate this fix. I left that switch in for testing convenience. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue14365 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14365] argparse: subparsers, argument abbreviations and ambiguous option
Changes by paul j3 ajipa...@gmail.com: Removed file: http://bugs.python.org/file31888/subparser_patch.diff ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue14365 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14365] argparse: subparsers, argument abbreviations and ambiguous option
paul j3 added the comment: This the argparse patch as described in the previous post, along with test_argparse tests. For now the tests handle both subparser required cases and not required ones ( http://bugs.python.org/issue9253 ). While error messages can differ based on this requirement, it does not affect the 'ambiguity' that underlies the current issue. -- Added file: http://bugs.python.org/file31901/subparser_patch.diff ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue14365 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14365] argparse: subparsers, argument abbreviations and ambiguous option
paul j3 added the comment: Steven's patch (subparse_optionals.diff) run with jakub's test case (argparse_subparses_ambiguous_bug.py) works. But if the input string is print(parser.parse_args('--foo baz'.split())) produces Namespace(cmd=None, foo='baz', foo1=None, foo2=None) (I added the 'cmd' subparse 'dest'). Two things seem to be going on now: 1) '--foo' is being parsed even though its subparser is not invoked, 2) and the subparser is not required. The issue of whether subparsers are required or not is another issue. They used to be required, but the testing for 'required' was changed, and subparsers fell through the crack. I suspect that if the missing subparser error were raised, the first issue wouldn't be apparent. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue14365 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue13824] argparse.FileType opens a file and never closes it
paul j3 added the comment: An alternative way to delay the file opening, is to return an instance that has a `filename` attribute, and has an `open` method. This can be compactly added to the `FileContext` that I defined in the previous patch. The `FileContext` provides the `_ostest` function (testing using os.access), and wrapper for stdin/out. class FileOpener(argparse.FileContext): # delayed FileType; alt to use of partial() # sample use: # with args.input.open() as f: f.read() def __call__(self, string): string = self._ostest(string) self.filename = string return self def open(self): return self.__delay_call__(self.filename)() file = property(open, None, None, 'open file property') -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue13824 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue13824] argparse.FileType opens a file and never closes it
paul j3 added the comment: In this patch I implement a FileContext class. It differs from FileType in 2 key areas: - it returns a 'partial(open, filename, ...)' - it wraps '-' (stdin/out) in a dummy context protecting the file from closure. The resulting argument is meant to be used as: with args.input() as f: f.read() etc The file is not opened until value is called, and it will be closed after the block. stdin/out can also be used in this context, but without closing. The signature for this class is the same as for FileType, with one added parameter, 'style'. (alternative name suggestions welcomed). class argparse.FileContext(mode='r', bufsize=-1, encoding=None, errors=None, style='delayed') The default behavior, style='delayed', is as described above. style='evaluate' immediately calls the partial, returning an opened file. This is essentially the same as FileType, except for the stdin/out context wrapping. style='osaccess', adds os.acccess testing to determine whether the 'delayed' file can be read or written. It attempts to catch the same sort of OS errors that FileType would, but without actually opening or creating the file. Most of the added tests in test_argparse.py copy the FileType tests. I had to make some modifications to the testing framework to handle the added levels of indirection. I have not written the documentation changes yet. A sample use case is: import argparse, sys p = argparse.ArgumentParser() p.add_argument('-d','--delayed', type=argparse.FileContext('r')) p.add_argument('-e','--evaluated', type=argparse.FileContext('r', style='evaluate')) p.add_argument('-t','--test', dest='delayed', type=argparse.FileContext('r', style='osaccess')) p.add_argument('-o','--output', type=argparse.FileContext('w', style='osaccess'), default='-') p.add_argument('--unused', type=argparse.FileContext('w', style='osaccess'),help='unused write file') args = p.parse_args() with args.output() as o: if args.delayed: with args.delayed() as f: print(f.read(), file=o) if args.evaluated: with args.evaluated as f: print(f.read(), file=o) # f and o will be closed if regular files # but not if stdin/out # the file referenced by args.unused will not be created -- keywords: +patch Added file: http://bugs.python.org/file31852/patch_3.diff ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue13824 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue16878] argparse: positional args with nargs='*' defaults to []
paul j3 added the comment: On a related point, the 'action.required' value is set differently for '?' and '*' positionals. 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 OPTIONAL is always not required, ZERO_OR_MORE is not required if it has a default. But for reasons discussed here, that 'required' value makes little difference. `parse_args` checks that all 'required' arguments have been seen, but a ZERO_OR_MORE positional is always seen (i.e. it matches an empty string). Usage formatting always uses '[%s [%s ...]]' with ZERO_OR_MORE, regardless of the 'required' attribute. The only place where this 'required' value seems to matter is when adding such an argument to a mutually exclusive group. But if an unused '*' positional is going to get a '[]' value anyways, why should it be excluded from such a use? If I remove the if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs: test, test_argparse.py still runs fine. http://bugs.python.org/issue18943 is a possibly related issue, involving a 'is not action.default' test in a mutually exclusive group. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16878 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11708] argparse: suggestion for formatting optional positional args
paul j3 added the comment: This is a HelpFormatter function that takes a list of formatted actions, and groups contiguous blocks of optional positional actions. It accounts for optionals (via prefix_chars) and mutually exclusive groups. Since it assumes 'parts' is a list, rather than string, it works best with the '_format_actions_usage' method in the patch that I submitted to http://bugs.python.org/issue11874 def _positionals_regroup(self, parts): # change '[arg1] [arg2]' to '[arg1 [arg2]]' # apply to a list of formatted arguments # don't apply to optionals (with prefix chars) or groups chars = getattr(self, 'prefix_chars',set('-')) R = _re.compile(r'\] \[(.*)\]') result = [] text = None while parts: part = parts.pop() if part: if part[0]=='[' and part[1] not in chars and '|' not in part: if text: text = ' '.join([part, text]) else: text = part if R.search(text): text = R.sub(' [\g1]]',text) else: if text: result.insert(0,text) text = None result.insert(0,part) if text: result.insert(0,text) return result To avoid compatibility issues it could implemented in a subclassed HelpFormatter. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11708 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11708] argparse: suggestion for formatting optional positional args
Changes by paul j3 ajipa...@gmail.com: -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11708 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue13824] argparse.FileType opens a file and never closes it
Changes by paul j3 ajipa...@gmail.com: -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue13824 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14365] argparse: subparsers, argument abbreviations and ambiguous option
Changes by paul j3 ajipa...@gmail.com: -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue14365 ___ ___ 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
Changes by paul j3 ajipa...@gmail.com: -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9694 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue10984] argparse add_mutually_exclusive_group should accept existing arguments to register conflicts
paul j3 added the comment: Another situation in which this MultiGroupHelpFormatter helps is when one or more of the groups includes an optional positional. The regular formatter moves all the positionals to the end, after the optionals. This move could easily break up a mutually exclusive group, and make formatting it impossible. But the MultiGroupHelpFormatter gives the group order priority. Thus for example: p=argparse.ArgumentParser() # (formatter_class=argparse.MultiGroupHelpFormatter) g=p.add_mutually_exclusive_group() g.add_argument('-f') g.add_argument('foo',nargs='?') g=p.add_mutually_exclusive_group() g.add_argument('-b') g.add_argument('-c') g.add_argument('bar',nargs='*',default='X') print(p.format_usage()) produces (positionals at end, no group markings) usage: PROG [-h] [-f F] [-b B] [-c C] [foo] [bar [bar ...]] But the MultiGroupHelpFormatter produces: usage: PROG [-h] [-f F | foo] [-b B | -c C | bar [bar ...]] In this last case, the positionals are listed with their respective groups, and the groups are ordered by the relative ordering of the positionals. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue10984 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18943] argparse: default args in mutually exclusive groups
paul j3 added the comment: At the very least the `is not action.default` needs to be changed. Else where in argparse `is` is only used with `None` or constant like `SUPPRESS`. So using it with a user defined parameter is definitely not a good idea. Possible variations on how `is` behaves across implementations (pypy, ironpython) only complicates the issue. I'm also familiar with a Javascript translation of argparse (that uses its `!==` in this context). -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18943 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18943] argparse: default args in mutually exclusive groups
paul j3 added the comment: This patch uses a narrow criteria - if `_get_values()` sets the value to `action.default`, then argument counts as 'not present'. I am setting a `using_default` flag in `_get_values`, and return it for use by `take_action`. In effect, the only change from previous behavior is that small ints (257) now behave like large ints, strings and other objects. It removes the nonstandard 'is not action.default' test, and should behave consistently across all platforms (including pypy). -- keywords: +patch Added file: http://bugs.python.org/file31704/patch_1.diff ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18943 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18943] argparse: default args in mutually exclusive groups
paul j3 added the comment: Changing the test from if argument_values is not action.default: to if argument_values is not action.default and \ (action.default is None or argument_values != action.default): makes the behavior more consistent. Strings and large ints behave like small ints, matching the default and not counting as present Simply using `argument_values != action.default` was not sufficient, since it raised errors in existing test cases (such as ones involving Nones). -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18943 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18943] argparse: default args in mutually exclusive groups
paul j3 added the comment: A possibly unintended consequence to this `seen_non_default_actions` testing is that default values do not qualify as 'present' when testing for a required mutually exclusive group. p=argparse.ArgumentParser() g=p.add_mutually_exclusive_group(required=True) g.add_argument('--foo',default='test') g.add_argument('--bar',type=int,default=42) p.parse_args('--bar 42'.split()) raises an `error: one of the arguments --foo --bar is required` In the original code p.parse_args('--foo test'.split()) does not raise an error because 'test' does not qualify as default. But with the change I proposed, it does raise the error. This issue may require adding a `failures_when_required` category to the test_argparse.py MEMixin class. Currently nothing in test_argparse.py tests for this issue. Note that this contrasts with the handling of ordinarily required arguments. p.add_argument('--baz',type=int,default=42,required=True) '--baz 42' does not raise an error. It is 'present' regardless of whether its value matches the default or not. This argues against tightening the `seen_non_default_actions` test. Because the current testing only catches a few defaults (None and small ints) it is likely that no user has come across the required group issue. There might actually be fewer compatibility issues if we simply drop the default test (or limit it to the case where the default=None). -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18943 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18943] argparse: default args in mutually exclusive groups
paul j3 added the comment: I should add that defaults with required arguments (or groups?) doesn't make much sense. Still there's nothing in the code that prevents it. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18943 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18943] argparse: default args in mutually exclusive groups
paul j3 added the comment: This `argument_values` comes from `_get_values()`. Most of the time is derived from the `argument_strings`. But in a few cases it is set to `action.default`, specifically when the action is an optional postional with an empty `argument_strings`. test_argparse.TestMutuallyExclusiveOptionalAndPositional is such a case. `badger` is an optional positional in a mutually exclusive group. As such it can be 'present' without really being there (tricky). Positionals are always processed - otherwise it raises an error. If this is the case, what we need is a more reliable way of knowing whether `_get_values()` is doing this, one that isn't fooled by this small int caching. We could rewrite the `is not` test as: if not argument_strings and action.nargs in ['*','?'] and argument_values is action.default: pass # _get_values() has set: argument_values=action.default else: seen_non_default_actions.add(action) ... is a little better, but still feels like a kludge. Having `_get_values` return a flag that says I am actually returning action.default would be clearer, but, I think, too big of a change. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18943 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18943] argparse: default args in mutually exclusive groups
paul j3 added the comment: The patch isn't a good unittest case because it produces an Error, not a Failure. It does, though, raise a valid question about how a Mutually_exclusive_group tests for the use of its arguments. As you note, argparse does use the `is` test: `argument_values is not action.default`. argument_values is the result of passing an argument_string through its 'type' function. This reworks your test case a bit: group = parser.add_mutually_exclusive_group() group.add_argument('--foo', default='test') group.add_argument('--bar', type=int, default=256) group.add_argument('--baz', type=int, default=257) '--foo test --baz 257' will give the `argument --foo: not allowed with argument --baz` error message, but '--foo test --baz 256' does not. So which is right? Should it complain because 2 exclusive arguments are being used? Or should it be excused from complaining because the values match their defaults? The other issue is whether the values really match the defaults or not. With an `is` test, the `id`s must match. The ids for small integers match all the time, while ones 256 differ. Strings might have the same id or not, depending on how they are created. If I create `x='test'`, and `y='--foo test'.split()[1]`. `x==y` is True, but `x is y` is False. So '--foo test' argument_value does not match the 'foo.default'. So large integers (256) behave like strings when used as defaults in this situation. It's the small integers that have unique ids, and hence don't trigger mutually_exclusive_group errors when they should. This mutually_exclusive_group 'is' test might not be ideal (free from all ambiguities), but I'm not sure it needs to be changed. Maybe there needs to be a warning in the docs about mutually_exclusive_groups and defaults other than None. -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18943 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18943] argparse: default args in mutually exclusive groups
paul j3 added the comment: A further complication on this. With the arguments I defined in the previous post p.parse_args('--foo test --baz 257'.split()) gives the mutually exclusive error message. `sys.argv` does the same. p.parse_args(['--foo', 'test', '--baz', '257']) does not give an error, because here the 'test' argument string is the same as the default 'test'. So the m_x_g test thinks `--foo' is the default, and does not count as an input. Usually in testing an argparse setup I use the list and split arguments interchangeably, but this shows they are not equivalent. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18943 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue10984] argparse add_mutually_exclusive_group should accept existing arguments to register conflicts
paul j3 added the comment: A possible further tweak is, in take_action(), test for conflicts before adding the action to 'seen_non_default_actions' 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: ... seen_non_default_actions.add(action) This does not cause problems with any existing tests, but makes it possible to add an action twice to a group. Why do that? To prevent an action from occurring more than once. For some actions like 'count' and 'append' repeated use is expected, but for others it isn't expected, and may sometimes be a nuisance (the last occurrence is the one that sticks). An example use would be: parser = argparse.ArgumentParser(prog=PROG, formatter_class=argparse.MultiGroupHelpFormatter) action = parser.add_argument('--arg', help='use this argument only once') group1 = parser.add_mutually_exclusive_group(action, action) args = parser.parse_args() calling this with: python3 test_once.py --arg test --arg next would produce this error message: usage: PROG [-h] [--arg ARG | --arg ARG] PROG: error: argument --arg: not allowed with argument --arg The usage and error message aren't as clear as they might be if this feature was added 'from scratch'. But for a minor change like this, that may be an acceptable price. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue10984 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue15112] argparse: nargs='*' positional argument doesn't accept any items if preceded by an option and another positional
paul j3 added the comment: These three changes end up testing for the same thing. The initial 'if' catches different test cases. 'subparsers' or 'remainder' might 'confuse' the 'O' test. The zero-width test ends up weeding out everything but the test cases added for this issue. # if we haven't hit the end of the command line strings, if start_index + sum(arg_counts) != len(arg_strings_pattern): while arg_counts and arg_counts[-1] == 0: arg_counts.pop() # same test using selected_pattern (= arg_strings_pattern[start_index:]) if len(selected_pattern) != sum(arg_counts): while arg_counts and arg_counts[-1] == 0: arg_counts.pop() # alt test: test for optional in the remaining pattern if 'O' in selected_pattern: while arg_counts and arg_counts[-1] == 0: arg_counts.pop() -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue15112 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue15112] argparse: nargs='*' positional argument doesn't accept any items if preceded by an option and another positional
Changes by paul j3 ajipa...@gmail.com: -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue15112 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14191] argparse doesn't allow optionals within positionals
paul j3 added the comment: Above in http://bugs.python.org/issue14191#msg187051 I proposed a patch that is quite close to bethard's patch in http://bugs.python.org/issue15112#msg166173 Both modify the same place, doing the same (pop items off arg_counts). The logic is a little different. I'd have to look at them more carefully to see whether one is more robust. Thanks for linking that issue. The main issue here is different, allowing for complete intermixing of optionals and positionals. Over at 15112 the issue is intermixing of optionals and 'whole' positionals. My 187051 patch belongs over there. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue14191 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14191] argparse doesn't allow optionals within positionals
Changes by paul j3 ajipa...@gmail.com: Added file: http://bugs.python.org/file29880/mixed.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue14191 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue15112] argparse: nargs='*' positional argument doesn't accept any items if preceded by an option and another positional
paul j3 added the comment: I originally posted this on http://bugs.python.org/issue14191, but I think it belongs here. The patch I proposed is similar to berthard's, popping items off the end of 'args_counts'. I intend to check whether the logic is equivalent. copy from http://bugs.python.org/msg187051 This patch permits the mixing of optionals with positionals, with the caveat that a particular positional cannot be split up. If: parser = ArgumentParser() parser.add_argument('-f','--foo') parser.add_argument('cmd') parser.add_argument('rest', nargs='*') '-f1 cmd 1 2 3', 'cmd -f1 1 2 3', 'cmd 1 2 3 -f1' all give {cmd='cmd', rest=['1','2','3'], foo='1'}. But 'cmd 1 -f1 2 3', does not recognize ['2','3']. Previously 'cmd -f1 1 2 3' would return rest=[], and not recognize ['1','2','3']. With this change the nargs='*' behaves more like nargs='+', surviving to parse the 2nd group of positional strings. The trick is to modify arg_counts in consume_positionals(), removing matches that don't do anything (don't consume argument strings). if 'O' in arg_strings_pattern[start_index:]: # if there is an optional after this, remove # 'empty' positionals from the current match while len(arg_counts)1 and arg_counts[-1]==0: arg_counts = arg_counts[:-1] This change passes all of the existing test_argparse.py tests. It also passes the optparse tests that I added in http://bugs.python.org/issue9334#msg184987 I added 4 cases to illustrate this change. -- Added file: http://bugs.python.org/file31457/mixed.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue15112 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14191] argparse doesn't allow optionals within positionals
Changes by paul j3 ajipa...@gmail.com: Removed file: http://bugs.python.org/file29880/mixed.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue14191 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14191] argparse doesn't allow optionals within positionals
paul j3 added the comment: It's everything I intend to add. Now I'm just waiting for a committer to act, either with suggested changes, or a merge. I'm watching more than a dozen argparse patches. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue14191 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue15428] add Name Collision section to argparse docs
Changes by paul j3 ajipa...@gmail.com: -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue15428 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue13280] argparse should use the new Formatter class
Changes by paul j3 ajipa...@gmail.com: -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue13280 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue12806] argparse: Hybrid help text formatter
Changes by paul j3 ajipa...@gmail.com: -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue12806 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9253] argparse: optional subparsers
paul j3 added the comment: msg113512 - (view) Author: Steven Bethard (bethard) Seems like there's minimally the bug that argparse should currently throw an error if you add an argument after subparsers (since that argument will never be parsed under the current semantics). This isn't quite right. If the main usage signature is: usage: PROG [-h] foo {one,two} ... baz the parser._match_arguments_partial() method will allocate the 1st string to 'foo', the last to 'baz', and pass the rest to the subparser(s). It doesn't know how many the subparsers can use, but it knows that 'baz' requires one. From the standpoint of matching argument strings and arguments, a subparser is essentially a '+' positional. On the other hand if 'baz' (the positional after the subparser) was '*' or '?' it would not get any strings. If it is possible that subparser(s) doesn't need all the strings passed to it, the user could use 'parse_known_args', and deal with the unparsed strings themselves (possibly with another parser). -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9253 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11955] 3.3 : test_argparse.py fails 'make test'
paul j3 added the comment: The test names are: FAIL: test_failures_many_groups_listargs (__main__.TestFileTypeW) FAIL: test_failures_many_groups_sysargs (__main__.TestFileTypeW) FAIL: test_failures_no_groups_listargs (__main__.TestFileTypeW) FAIL: test_failures_no_groups_sysargs (__main__.TestFileTypeW) FAIL: test_failures_one_group_listargs (__main__.TestFileTypeW) FAIL: test_failures_one_group_sysargs (__main__.TestFileTypeW) So they differ by [many_groups, no_groups, one_group] and [listargs, sysargs] There are about 170 tests in test_argparse that get multiplied by 6 in this way. If this replication was removed it would cut the number of tests and time to nearly a third. This replication is not useful. listargs and sysargs differ only in how a list of arguments is passed to parse_args, either directly, or via sys.argv. It should be sufficient to test these alternatives once, not 170 times. 'one group' creates an argument group, and adds all arguments to that. 'many groups' creates an argument group for each added argument. But argument groups are not used for 'parse_args'. They are only used when formatting help. By default all the arguments of parser are already put into one of two groups, 'optional arguments' or 'positional arguments'. There are tests for the help formatting, but they don't use this ParserTesterMetaclass. I would recommend removing this test replication. It is both unnecessary and a source of confusion. The simplest would be to change the end of the ParserTesterMetaclass. class ParserTesterMetaclass def __init__() for add_arguments in [no_groups]: for parse_args in [listargs]: AddTests(cls, add_arguments, parse_args) I suspect there is some confusion among users and developers as to what argument groups do. As for the TestFileTypeW error, I suspect it has to do with file writing privileges. I haven't encountered it, but I running tests in my own directory. -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11955 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14074] argparse allows nargs1 for positional arguments but doesn't allow metavar to be a tuple
Changes by paul j3 ajipa...@gmail.com: -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue14074 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue16360] argparse: comma in metavar causes assertion failure when formatting long usage message
paul j3 added the comment: My rewrite of _format_actions_usage in http://bugs.python.org/issue11874 should take care of this issue. It keeps the groups and actions separate until the final formatting step, bypassing the regular expression parsing. -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16360 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14074] argparse allows nargs1 for positional arguments but doesn't allow metavar to be a tuple
paul j3 added the comment: This patch fixes the problem by joining the metavar terms with '|'. So the help for the test case (adapted from an existing tuple test) looks like: usage: PROG [-h] W1 [W2 ...] [X1 [X2 ...]] Y1 Y2 Y3 [Z1] positional arguments: W1|W2 w X1|X2 x Y1|Y2|Y3y Z1 z Alternatives include: - use ',',' ',or '/' instead of '|' - use just the 1st item of the tuple - use the default (non-tuple) metavar in the help line These all pass existing tests. The last alternative would use: #metavar = '|'.join(metavar) if len(metavar)1: metavar = default else: metavar = metavar[0] -- keywords: +patch Added file: http://bugs.python.org/file31042/issue14074.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue14074 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18467] argparse - problematic 'default' behavior
paul j3 added the comment: Since parse_args takes an optional Namespace argument, you can set the its initial value to almost anything. For example, with the functions defined previously: parser = argparse.ArgumentParser() parser.add_argument('-a','--algorithm', choices=['Q','S'], action=FooAction, type=bar) NS = parser.parse_args(['-a','S']) args = parser.parse_args(None, NS) The first parse_args uses FooAction to create a default Namespace, which is then passed to the second. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18467 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue10984] argparse add_mutually_exclusive_group should accept existing arguments to register conflicts
paul j3 added the comment: This patch produces the same usage as before, but I have rewritten _format_actions_usage() for both HelpFormatter and MultiGroupFormater. The original HelpFormatter._format_actions_usage() formats the actions, splices in group markings, cleans up the text, if needed, tries to break it down into parts. But this is fragile, as shown here and in issues 11874, 18349). Now _format_group_usage() and _format_just_actions_usage() format groups and actions directly, without the splice and divide steps. _format_actions_usage() for both classes call these to build a list of usage parts. This change also solves http://bugs.python.org/issue11874 and http://bugs.python.org/issue18349, since it does not have to break up a formatted text line (and in the process get confused by [] and ()). -- Added file: http://bugs.python.org/file30940/multigroup_4.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue10984 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11874] argparse assertion failure with brackets in metavars
paul j3 added the comment: Here's a patch that takes a different approach - rewrite _format_actions_usage() so it formats groups (and unattached actions) directly. It uses the same logic to determine when to format a group, but then it calls _format_group_usage() to format the group, without the error prone insert and cleanup business. And by keeping a list of the parts, it avoids the complications of parsing the text. The only cleanup regex removes () from single element groups. In the nested get_lines function, I added 'line and' to if line and line_len + 1 + len(part) text_width: so it does not create a blank line before an extra long entry (e.g. 'c'*76). I'm using the _format_group_usage() and _format_just_actions_usage() in the Issue 10984 MultiGroupFormatter, just rearranging the logic in its _format_actions_usage() method. That patch could be rewritten to depend on this one. This patch also fixes http://bugs.python.org/issue18349, since the metavar is never parsed. -- Added file: http://bugs.python.org/file30941/format_usage.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11874 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18349] argparse usage should preserve () in metavars such as range(20)
paul j3 added the comment: I just submitted at patch to http://bugs.python.org/issue11874 that takes care of this issue as well. I rewrote _format_actions_usage() so it formats the parts directly, so there is no need cleanup or parse the full text string. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18349 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue16468] argparse only supports iterable choices
paul j3 added the comment: I just submitted a patch to http://bugs.python.org/issue11874 which rewrites _format_actions_usage(). It now formats the groups and actions directly, keeping a list of these parts. It no longer has to cleanup or split a usage line into parts. So it is not sensitive to special characters (space, [] or () ) in the choices metavar. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16468 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue17890] argparse: mutually exclusive groups full of suppressed args can cause AssertionErrors
paul j3 added the comment: I just submitted a patch to http://bugs.python.org/issue11874 that substantially rewrites _format_actions_usage(). It generates the group and action parts separately, and does not do the kind of cleanup that produces this issue. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue17890 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18467] argparse - problematic 'default' behavior
Changes by paul j3 ajipa...@gmail.com: -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18467 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18467] argparse - problematic 'default' behavior
paul j3 added the comment: I think this example illustrates your issue: class FooAction(argparse.Action): def __call__(self, parser, namespace, values, option_string = None): if values=='Q': setattr(namespace, self.dest, {'type':values, 'quick':True, 'slow':False}) else: setattr(namespace, self.dest, {'type':values, 'quick':False, 'slow':True}) def bar(string): return string.upper()[0] parser = argparse.ArgumentParser() parser.add_argument('-a','--algorithm', choices=['Q','S'], default='s', action=FooAction, type=bar) parser.add_argument('foo', choices=['Q','S'], default='s', action=FooAction, nargs='?', type=bar) print(parser.parse_args([])) # Namespace(algorithm='S', # foo={'slow': True, 'type': 'S', 'quick': False}) For both the optional and positional, the lower case default is converted into an upper case letter. For the positional with nargs='?', the action is called with the converted default value. But for the optional, the converted default is assigned to the dest algorithm='S' but action is not called, which would have assigned algorithm={'type': 'S', 'quick': False, 'slow': True} That is consistent with what I remember from the code. A next function 'take_action' is called only if there is an appropriate argument string. For this optional that would be '-a' (or the likes). For the '?' positional and empty argument list enough. There is a relatively recent change that delayed when a default was converted by type (so a filetype wouldn't be opened unnecessarily). But I can't think anyway that the action would be invoked on the default in the absence of '-a'. In this example, would it be possible shift code from the custom action to the custom type? -- Added file: http://bugs.python.org/file30944/issue18467.py ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18467 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18349] argparse usage should preserve () in metavars such as range(20)
paul j3 added the comment: This issue should also preserve a metavar like: '(one)two', i.e. '(' at the start. In http://bugs.python.org/issue10984 these _re replacements are applied to individual action strings as well as the whole usage line. So if () are to be removed from '[-h] (-y)', they should also be removed from '(-y)'. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18349 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11874] argparse assertion failure with brackets in metavars
paul j3 added the comment: If the arg_parts are passed through the same cleanup as the 'text' (and empty strings removed), then text = ' '.join(arg_parts) In that case there would be no need to return both (text, arg_parts). Parenthesis in the metavar could also create the problem addressed in this thread, except as noted in http://bugs.python.org/issue18349 that 'text' cleanup removes them. nargs='*' or '+' or integer is another way in which [] could be introduced into the metavar. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11874 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue10984] argparse add_mutually_exclusive_group should accept existing arguments to register conflicts
paul j3 added the comment: This patch adds a MultiGroupHelpFormatter that formats groups even if they share actions or the actions are not in the same order as in the parse._actions list. It sorts the groups so positional actions, if any appear in the correct order. A long test case generates this help: usage: PROG [-h] [-a A | -c C] [-a A | -d D] [-a A | -b B] [-b B | -d D] [-d D | x] foo [-b B | y] positional arguments: x x help foo foo help y y help optional arguments: -h, --help show this help message and exit -a Aa help -b Bb help -c Cc help -d Dd help In the 2nd usage line, the 2 groups, and action foo, are shown in the order in which x, foo, y were defined (and hence will be parsed), even though the groups were not defined in that order. The default formatter could not format these groups, generating '[-h] [-a A] [-b B] ... x foo y' instead. I have included the latest patch from http://bugs.python.org/issue11874. This splits the usage line generated by _format_actions_usage into parts that are groups or independent actions. The goal there is to correctly split long usage lines into multiple lines. Here it makes it easier to format groups and actions in new order. If existing actions are added to new group as in the original patch for this issue, that group gets a no_usage = True attribute. The default formatter then will not attempt to format this group. The MultiGroupHelpFormatter ignores this attribute. This patch needs better documentation. Test cases also need refinement, improving the names, and eliminating redundancies. Some of the new tests are copies of existing ones, but using the new formatter. -- Added file: http://bugs.python.org/file30921/multigroup_1.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue10984 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11874] argparse assertion failure with brackets in metavars
paul j3 added the comment: I just filed a patch with http://bugs.python.org/issue10984 (argparse add_mutually_exclusive_group should accept existing arguments to register conflicts) that includes the latest patch from this issue. I tweaked it so _format_actions_usage only returns arg_parts. The block of _re. statements (# clean up separators for mutually exclusive groups) are in a nested function so it can be applied to each of the parts. In that issue I wrote a custom formatter that handles groups even if they share actions, or the action order does not match definition order. For that it is easier to work with the arg_parts as generated here rather than the whole usage line. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11874 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11874] argparse assertion failure with brackets in metavars
Changes by paul j3 ajipa...@gmail.com: -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11874 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue10984] argparse add_mutually_exclusive_group should accept existing arguments to register conflicts
paul j3 added the comment: While playing with some examples, I found that exclusive group formatting has another failure case. If the usage line is long enough to wrap, optionals and positionals are formatted separately, with positionals appearing on a separate line(s). That means that if a group includes a positional, it will not be marked. So (shortening lines for convenience sake), instead of: usage: [-h] ... (-a | -b | x) we get usage: [-h] ... [-a] [-b] x This is true even if arguments are added to the group in the normal way. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue10984 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue10984] argparse add_mutually_exclusive_group should accept existing arguments to register conflicts
paul j3 added the comment: One usage option is to make a subclass of HelpFormatter (the accepted way of customizing a formatter), and write a function that formats each group independently. For the example case, the resulting format might be: usage: PROG [-h] [-b] [-a | -c] [-a | -d] -h and -b are not part of any group. These are followed by the two groups. -a is repeated because it appears in both groups. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue10984 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue10984] argparse add_mutually_exclusive_group should accept existing arguments to register conflicts
paul j3 added the comment: This approach of simply adding the existing actions to the group's _group_actions works fine, at least when it comes catching the error. It may be difficult to get a useful usage line. In usage, arguments appear in the order in which they were created, optionals first, positionals after. Group notation is added if the subset of the arguments appear in its list in the same order. In the patch .rst, usage: PROG [-h] (--foo | --bar) [--baz] the foo,bar group is marked correctly; the foo,baz group is not contiguous and is omited. In bethard's example neither group will be marked (class TestMutuallyExclusiveGroupWithExistingArguments) But the problem isn't just with adding existing arguments. class TestMutuallyExclusiveOptionalsMixed illustrates this with a case where group and parser arguments overlap. In class TestMutuallyExclusiveOptionalsAndPositionalsMixed, the mix of optionals and positionals makes group marking impossible. If the groups are in order, but overlap, usage can be a confusing mix Groups ab, bc, cd, produce: [-a A | [-b B | [-c C | -d D] But if created in a different order, the usage can be: [-a A | [-b B | -c C] -d D] So there are 2 issues - if groups are not continuous or overlap, what is a meaningful usage? - any choice is likely to require a major reworking of the formatting logic. Since confusing group markings are worse than none, a first step might be to flag a group added via this patch as 'do not mark'. Also add a note to the documentation that user may need to write their own grouping instructions (in usage, description or epilog). -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue10984 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue16468] argparse only supports iterable choices
paul j3 added the comment: This patch generally deals with the choices option, and specifically the problems with formatting long lists, or objects that have __contains__ but not __iter__. But it also incorporates issues 9849 (better add_argument testing) and 9625 (choices with *). It may be too broad for this issue, but the changes all relate to 'choices'. As noted by other posters, there are 3 places where choices is formatted with a comprehension. I have refactored these into one _format_choices function. _format_choices() is a utility function that formats the choices by iteration, and failing that using repr(). It raises an error if choices does not even have a __contains__. It also has a summarize option ({1,2,3,...,19,20}). I did not make this an action method because it only uses the choices object. _metavar_formatter() - calls _format_choices for Usage with the default compact form. Its use of metavar gives the user full control of the choices display. _expand_help() - calls _format_choices with the looser format. This form is used only if the user puts '%(choices)s' in the help string. This is not documented, and only appears a few times in the test file. Again the user has ultimate control over the contents. _check_value() - calls _format_choices with a 'summarize=15' option. Normally this error message appears with the usage message. So it does not need to use the metavar. The MetavarTypeHelpFormatter subclass is an example of how formats can be customized without changing normal behavior. Such a subclass could even be used to set custom parameters, or modify any of the above methods. other changes: formatter _format_actions_usage() - I tweaked the regex that trims excess notation from mutually exclusive groups. This removed '()' from other parts of the usage line, for example a metavar like 'range(20)'. Issue 18349. formatter _format_args() - I included issue 9849 changes which improve testing for nargs, and array metavars. This calls the _metavar_formatter. Thus any errors in formatting choices pass back through this. Issue 9849 also changes container add_argument() to call the parser _check_argument(). This in turn calls _format_args() to test action options like nargs, metavars, and now choices. If there are problems it raises an ArgumentError. parser _get_values() - issue 9625 changes this to correctly handle choices when nargs='*'. parser _check_value() - I rewrote this to give better errors if there are problems with __contains__. If choices is a string (e.g. 'abc') it converts it to a list, so __contains__ is more consistent. For example, 'bc' in 'abc' is True, but 'bc' in ['a','b','c'] is False (issue 16977) -- test_argparse change examples with string choices to lists class TestAddArgumentMetavar change EXPECTED_MESSAGE and EXPECTED_ERROR to reflect issue 9849 changes class TestMetavarWithParen tests 'range(n)' choices makes sure () in the metavar are preserved tests that metavar is used in Usage as given tests summarized list of choices in the error message tests the %(choices)s help line case class TestNonIterableChoices tests a choices container that has __contains__ but not __iter__ tests that repr() is used as needed class TestBareChoices tests a class without even __contains__ tests for an add_argument error class TestStringChoices tests the expansion of 'abc' to ['a','b','c'] -- Added file: http://bugs.python.org/file30872/choice2.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16468 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue16977] argparse: mismatch between choices parsing and usage/error message
paul j3 added the comment: I just posted a patch to http://bugs.python.org/issue16468 that deals with this 'bc' in 'abc' issue. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16977 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18349] argparse usage should preserve () in metavars such as range(20)
paul j3 added the comment: I just posted a patch to http://bugs.python.org/issue16468 that uses (and tests) this fix. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18349 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9625] argparse: Problem with defaults for variable nargs when using choices
paul j3 added the comment: The patch I just posted to http://bugs.python.org/issue16468 uses this fix. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9625 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue16418] argparse with many choices can generate absurdly long usage message
paul j3 added the comment: In the patch I just posted to http://bugs.python.org/issue16468 I address this long list issue in several ways: In the Usage line, the metavar gives the user an alternative In the expanded help line the user can just omit the '%(choices)s' In _check_value(), I implemented a numpy like summarize format for choice lists longer than 15 '{1,2,3,...,18,19}'. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16418 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9849] Argparse needs better error handling for nargs
paul j3 added the comment: I included this patch (with minor changes) in a patch that I just posted to http://bugs.python.org/issue16468. That issue deals with the argument choices option, which can be tested along with nargs and metavars. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9849 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue16977] argparse: mismatch between choices parsing and usage/error message
paul j3 added the comment: Changing _check_value from: def _check_value(self, action, value): # converted value must be one of the choices (if specified) if action.choices is not None and value not in action.choices: ... to def _check_value(self, action, value): # converted value must be one of the choices (if specified) if action.choices is not None: choices = action.choices if isinstance(choices, str): choices = list(choices) if value not in action.choices: ... would correct the string search without affecting other types of choices. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16977 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18349] argparse usage should preserve () in metavars such as range(20)
New submission from paul j3: As discussed in issue 16468, a metavar may be used to provide an alternative representation of a choices option. However if a metvar like 'range(20)' is used, usage formatter strips off the '()'. parser.add_argument('foo', type=int, choices=range(20), metavar='range(0,20)') parser.format_usage() # expect: 'usage: PROG [-h] range(0,20)\n' # actual: 'usage: PROG [-h] range0,20\n' This is done by a line in the help formater that removes excess mutually exclusive group notation: HelpFormatter._format_actions_usage ... text = _re.sub(r'\(([^|]*)\)', r'\1', text) A solution is to change this line to distinguish between a case like ' (...)' and 'range(...)' text = _re.sub(r'( )\(([^|]*)\)', r'\1\2', text) -- files: metaparen.patch keywords: patch messages: 19 nosy: paul.j3 priority: normal severity: normal status: open title: argparse usage should preserve () in metavars such as range(20) Added file: http://bugs.python.org/file30754/metaparen.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18349 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18349] argparse usage should preserve () in metavars such as range(20)
Changes by paul j3 ajipa...@gmail.com: -- components: +Library (Lib) type: - behavior versions: +Python 3.4 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18349 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue16933] argparse: remove magic from examples
paul j3 added the comment: There still is one choices='XYZ' example (16.4.5.1. Sub-commands) but the focus isn't on choices. -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16933 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue16977] argparse: mismatch between choices parsing and usage/error message
paul j3 added the comment: test_argparse.py has some choices='abc' cases. In those should parser.parse_args(['--foo','bc']) be considered a success or failure? The underlying issue here is that while string iteration behaves like list iteration, string __contains__ looks for substrings, not just one character that matches. (String __contains__ also returns a TypeError if its argument is not a string.) But other than removing poor examples in documentation and tests, I'm not sure this issue requires a change. -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16977 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9625] argparse: Problem with defaults for variable nargs when using choices
paul j3 added the comment: Change choices='abc' to choices=['a', 'b', 'c'], as discussed in issue 16977 (use of string choices is a bad example) -- Added file: http://bugs.python.org/file30762/issue9625_2.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9625 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue16468] argparse only supports iterable choices
paul j3 added the comment: I'd suggest not worrying about the default metavar in the _expand_help() method. The formatted choice string created in that method is only used if the help line includes a '%(choices)s' string. The programmer can easily omit that if he isn't happy with the expanded list. TestHelpVariableExpansion is the only test in test_argparse.py that uses it. Sig('--foo', choices=['a', 'b', 'c'], help='foo %(prog)s %(default)s %(choices)s') -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16468 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue16468] argparse only supports iterable choices
paul j3 added the comment: chris.jerdonek wrote: Also, to answer a previous question, the three places in which the choices string is used are: in the usage string (separator=','), in the help string when expanding %(choices)s (separator=', '), and in the error message text (separator=', ' with repr() instead of str()). In the usage string, the ',' is used to make a compact representation of the choices. The ', ' separator is used in the help line, where space isn't as tight. This 'choices formatting' is called during 'add_argument()' simply as a side effect of checking for valid parameters, especially 'nargs' (that it, is an integer or an acceptable string). Previously 'nargs' errors were not caught until 'parse_args' was used. This is discussed in http://bugs.python.org/issue9849 Argparse needs better error handling for nargs http://bugs.python.org/issue16970 argparse: bad nargs value raises misleading message On the issue of what error type to raise, my understanding is that 'ArgumentError' is the preferred choice when it affects a particular argument. parse_args() nearly always raises an ArgumentError. Once add_argument has created an action, it too can raise an ArgumentError. ArgumentError provides a standard way of identifying which action is giving the problem. While testing 'metavar=range(0,20)', I discovered that the usage formatter strips off parenthesis. A regex expression that removes excess 'mutually exclusive group' notation is responsible for this. The simple fix is to modify the regex so it distinguishes between ' (...)' and 'range(...)'. I intend to create a new issue for this, since it affects any metavar the includes (). -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16468 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9938] Documentation for argparse interactive use
paul j3 added the comment: The exit and error methods are mentioned in the 3.4 documentation, but there are no examples of modifying them. 16.4.5.9. Exiting methods ArgumentParser.exit(status=0, message=None) ArgumentParser.error(message) test_argparse.py has a subclass that redefines these methods, though I think it is more complex than necessary. class ErrorRaisingArgumentParser(argparse.ArgumentParser): In http://bugs.python.org/file30204/test_intermixed.py , part of http://bugs.python.org/issue14191 , which creates a parser mode that is closer to optparse in style, I simply use: def error(self, message): usage = self.format_usage() raise Exception('%s%s'%(usage, message)) ArgumentParser.error = error to catch errors. https://github.com/nodeca/argparse a Javascript port of argparse, adds a 'debug' option to the ArgumentParser, that effectively redefines this error method. They use that extensively in testing. Another approach is to trap the sysexit. Ipython does that when argparse is run interactively. Even the simple try block works, though the SystemExit 2 has no information about the error. try: args = parser.parse_args('X'.split()) except SystemExit as e: print(e) Finally, plac ( https://pypi.python.org/pypi/plac ) is a pypi package that is built on argparse. It has a well developed interactive mode, and integrates threads and multiprocessing. -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9938 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue16418] argparse with many choices can generate absurdly long usage message
Changes by paul j3 ajipa...@gmail.com: -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16418 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9625] argparse: Problem with defaults for variable nargs when using choices
paul j3 added the comment: I've added 2 more tests, one with default='c', which worked before. one with default=['a','b'], which only works with this change. http://bugs.python.org/issue16878 is useful reference, since it documents the differences between nargs=? and nargs=*, and their handling of their defaults. -- Added file: http://bugs.python.org/file30709/issue9625_1.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9625 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com