[issue16468] argparse only supports iterable choices
Changes by paul j3 ajipa...@gmail.com: -- nosy: +paul.j3 ___ 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
[issue9625] argparse: Problem with defaults for variable nargs when using choices
Changes by paul j3 ajipa...@gmail.com: -- nosy: +paul.j3 ___ 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
[issue14191] argparse doesn't allow optionals within positionals
paul j3 added the comment: This is a refinement of the patch with Message188609. In parse_known_intermixed_args, the temporary capture of formatted usage has been put in a try/finally structure. Positionals are now 'deactivated' with action.nargs = SUPPRESS action.default = SUPPRESS To use this, a 'nargs==SUPPRESS' case has been added to the relevant methods. In _get_args_pattern() it acts just like 'nargs=0'. In '_get_values()' it returns 'value=SUPPRESS'. The net effect is that, in take_action(), 'action' is not invoked, and that positional is not added to the namespace. Previously I used nargs=0, which put a [] value in the namespace, which then had to be deleted. I have not added anything about this SUPPRESS option to the documentation (PARSER isn't there either). When the parser uses incompatible features (e.g. REMAINDER), this now raises a TypeError. The effect is similar to giving add_argument incompatible definitions. The 'fallback' that I used earlier can be implemented with a simple 'try/except TypeError'. Other parsing errors go through the usual ArgumentParser.error() method. test_argparse.py has been changed to handle this TypeError. -- Added file: http://bugs.python.org/file30422/intermixed.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
[issue9338] argparse optionals with nargs='?', '*' or '+' can't be followed by positionals
paul j3 added the comment: Here's another approach to the problem, using an iterative localized search. For simple cases it produces the same thing, but in complex cases it is more robust. It is based on two ideas: - if the action in consume_optional() is being 'greedy', use slots = self._match_arguments_partial([action]+positionals, selected_patterns) to determine if this action can share arguments with any of the remaining positionals. This is similar to how consume_positionals() allocates arguments to the set of positionals. - try this 'sharing' with the last optional. If that is not enough, try the penultimate optional as well, and continue working toward the start as needed. Since the normal parsing is from left to right, figuring out when to start 'sharing' requires some sort of search strategy. I have moved the start_index loop into a consume_loop() function, and added a switch so it can parse the arguments without invoking take_action() (so arguments are not evaluated, and namespace is not changed). If there is a suspected 'greed' problem, consume_loop() is called (in test mode) one or more times to determine the right-most optionals to use, and once more (with take_action) to parse and evaluate the arguments. As in the previous patch this writes a log file for debugging purposes. test_argparse.py now has a number of tests for this issue. It is more robust than the previous patch, and does not need special handling for things like subparsers and explicit arguments. -- Added file: http://bugs.python.org/file30349/argparse_7.py ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9338 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9338] argparse optionals with nargs='?', '*' or '+' can't be followed by positionals
Changes by paul j3 ajipa...@gmail.com: Removed file: http://bugs.python.org/file30349/argparse_7.py ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9338 ___ ___ Python-bugs-list mailing list Unsubscribe: http://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: Oops, I attached the wrong file. Here's the correct one. -- Added file: http://bugs.python.org/file30350/issue9338_7.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9338 ___ ___ Python-bugs-list mailing list Unsubscribe: http://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: This patch implements, I think, the ideas bethard proposed. It is test patch, not intended for production. Most of work is in ArgumentParser._get_alt_length() which - generates a pattern along the lines bethard proposed - generates a string like arg_strings_pattern, but with optionals strings ('-x') instead of 'O'. - runs a match - from groups like '-xAAA', creates dict entries like: alt_opt_length['x'] = 3 Later, in consume_optionals(), this alternative count replaces arg_count if it is lower. The next consume_positionals() then takes care of consuming the unconsumed arguments. If _get_alt_length() has any problems, it logs an error, and returns an otherwise empty dict. So it 'fails' quietly without affecting regular parsing. Reasons for failing include (for now) the use of subparsers, optionals with explicit args, and special prefix_chars. With exclusions like this, test_argparse.py runs without errors or failures. Since this is still a testing vehicle, it writes an issue9338.log file with debugging entries. This version works, but is both not sufficiently general and too general. As bethard notes, the testing pattern could get very large if there are many optionals. Ideally the pattern will allow the optionals in any order and combination between positionals. The ambiguities that I discussed in the previous 2 posts disappear if the patching pattern is sufficiently general. But I also suspect it is too general. It does not need to match every case, just those where an optional is consuming arguments that should go to a positional. But if we come up with something more specific, this could still be a useful testing tool. -- Added file: http://bugs.python.org/file30296/issue9338_3.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9338 ___ ___ Python-bugs-list mailing list Unsubscribe: http://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: This is a test file for the patch I just submitted. It is not a formal unitttest, but uses print output as much as assert. Cases include the example bethard used, as well as ones from test_argparse.py that initially caused problems. -- Added file: http://bugs.python.org/file30297/test_9338.py ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9338 ___ ___ Python-bugs-list mailing list Unsubscribe: http://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: I need to make one correction to my last post: '-x 1 2 -w 3 4 5 6', # w:3, x:[1,2], y:4, z:[5,6] + # w:3, x:[1], y:2, z:[4,5,6] - The second solution is only possible if 'z' is not consumed when 'y' is being processed. In current version, if consume_positionals() is called with a 'AO' pattern, 'y' will match the first 'A', and 'z' will match ''. That means '4 5 6' will be left over. It's only when I use the patch in http://bugs.python.org/issue14191#msg187051 (argparse doesn't allow optionals within positionals) that the processing 'z' is delayed, so it can get [4,5,6]. So at least with the 4 arguments in this example, bethard's idea only seems to make a difference in the case of '-w 1 -x 2 3 4 5', where 'y' lays claim to the last string, and '-x' gets the rest. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9338 ___ ___ 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
[issue17965] argparse does not dest.replace('-', '_') for positionals
Changes by paul j3 ajipa...@gmail.com: -- title: argparse does not dest.replace('-', '_') for postionals - argparse does not dest.replace('-', '_') for positionals ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue17965 ___ ___ Python-bugs-list mailing list Unsubscribe: http://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: I've played a bit the idea that barthard sketched. I don't have all the details worked out, but I believe this is what will happen: With parser = argparse.ArgumentParser() parser.add_argument('-w') parser.add_argument('-x', nargs='+') parser.add_argument('y') parser.add_argument('z', nargs='*') some possible parses are '-w 1 -x 2 3 4 5', # w:1, x:[2,3,4], y:5, z:[] - # fail + '-w 1 2 -x 3 4 5', # w:1, y:2, x:[3 4 5], z:[] + '-w 1 -x 2 3', # w:1, x:[2], y:3, z:[] - # fail + '-x 1 2 -w 3 4 5 6', # w:3, x:[1,2], y:4, z:[5,6] + # w:3, x:[1], y:2, z:[4,5,6] - '-x 1 2 3 4 -w 5 6 7', # w:5, x:[1,2,3,4], y:5, z:[7] + # w:5, x:[1,2,3], y:4, z:[6,7] - '1 2 3 -x 4 5 -w 6', # w:6, x:[4,5], y:1, z:[2,3] + '+' lines are those currently produced '-' lines are ones that would be produced by these ideas '-w 1 -x 2 3 4 5' is the protypical problem case. The current parser allocates all [2,3,4,5] to -x, leaving none for y, thus failing. So desired solution is to give 5 to y, leaving -x with the rest. '-x 1 2 -w 3 4 5 6' is a potentially ambiguous case. The current parser lets -x grab [1,2]; y then gets 4, and z the remainder. But the alternative is to give 2 to y, leaving -x with just [1]. In this case arg_strings_pattern = 'OAAO' replacing the Os with the option flags: '-xAA-w' I match this with a refined version of bethard's regex: pat1='((?:-wA)|(?:-xA+)|(?:-wA-xA+)|(?:-xA+-wA))' pat = _re.compile('%s?(?PyA)%s?(?PzA*)%s?'%(pat1,pat1,pat1)) groups (without the Nones) and groupdict are ['-xA', 'A', '-wA', 'AAA'] {'z': 'AAA', 'y': 'A'} So this does effectively give y the 2nd argument, leaving -x with just the 1st. The current parser effectively groups the arguments as ['-xAA, '-wA', 'A', 'AA'] In the real world, generating and apply a global pattern like this could get complicated. For example there are long option names ('--water'), and combined argument strings ('-x1', '-x=1'). -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9338 ___ ___ 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'm following a dozen argparse issues with patches. I haven't seen much posting by argparse experts (like bethard, david.murry) since last December. -- ___ 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
[issue17940] extra code in argparse.py
paul j3 added the comment: I was wondering about that block of code earlier. It would be a good idea to look at what func() does, just to make sure there aren't any side effects - e.g. set maximum line length, required indention, etc. -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue17940 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue17965] argparse does not dest.replace('-', '_') for postionals
New submission from paul j3: 16.4.3.11. dest For optional argument actions,... Any internal - characters will be converted to _ characters to make sure the string is a valid attribute name. In _get_optional_kwargs(), dest = dest.replace('-', '_'); but there is nothing like this in _get_positional_kwargs() Thus if parser.add_argument('foo-bar',...) this attribute can only be accessed with getattr(namespace, 'foo-bar'). Alternatives: - ignore this since no one has complained about it - stress in the documentation that the positionals name should be a valid python attribute name - test the name during add_argument - add the dest.replace('-','_') to positionals But as things stand, even an optional can be given a weird dest - a=p.add_argument('--foo*[]-bar') requiring getattr(args,'foo*[]_bar') I assume that optionals have this dash replacement because historically some unix (or other) programs have accepted options like '--foo-bar' (though off hand I can't think of any). -- components: Library (Lib) messages: 189090 nosy: paul.j3 priority: normal severity: normal status: open title: argparse does not dest.replace('-', '_') for postionals type: behavior versions: Python 3.4 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue17965 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14046] argparse: assertion failure if optional argument has square/round brackets in metavar
Changes by paul j3 ajipa...@gmail.com: -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue14046 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9338] argparse optionals with nargs='?', '*' or '+' can't be followed by positionals
Changes by paul j3 ajipa...@gmail.com: -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9338 ___ ___ 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: 'parse_fallback_args()' function is only in the 'test_intermixed.py' file, not the patch. It should be in the 'if __name__' section of that file, along with the modified 'exit()' method, since it is part of these testing suit, not meant to be imported. 'test_intermixed.py' is more of an example and discussion tool, not a formal test. I added the '_fallback' optional argument because the normal exit from 'parse_args' using SystemExit is remarkably uninformative. It's hard to distinguish between the 'fallback' errors, and the ones generated by 'parse_known_args' (that have more to do with the argument strings). One is a programming error, the other a user generated error. It is possible to redefine ArgumentParser.error() so it gives more information, for example by raising an Exception(message). I have added to test_intermixed.py an alternative 'parse_fallback_args' that uses such a modified error rather than the _fallback option. But that ends up modifying the normal parsing error generation as well. I used the 'fallback' idea to test 'parse_intermixed_args' against the whole set 'test_argparse.py' tests. It would nice to have a way of doing that automatically anytime other features are added to 'parse_args'. But I can't think of a clean way of doing that. Regarding earlier versions of these files - I do not see a way of deleting them. I have attached a modified test_intermixed.py that has these changes. I also modified how 'parse_known_intermixed_args' restores the original value of self.usage, using an outer 'try:finally:' block. I need to make a note to myself to put that in the patch. -- Added file: http://bugs.python.org/file30204/test_intermixed.py ___ 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: I should note one caveat: As a consequence of setting nargs to 0 for the first 'parse_know_args' step, all positional entries in the namespace get an empty list value ([]). This is produced by 'ArgumentParser._get_values'. With the builtin action classes this does not cause any problems. However a custom action class might have problems with this [] value. For example in 'test_argparse.py', TestActionUserDefined the PositionalAction class does check the values and throws an error with this [] value. The positional arguments are removed from the namespace before it is passed on to the 2nd 'parse_known_args', so these [] in the first don't affect the final namespace. I don't think anything about this should be added to main documentation, since it could confuse most readers. I might add a note of warning to the code itself. -- ___ 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
[issue11354] argparse: nargs could accept range of options count
paul j3 added the comment: I think this patch should build on http://bugs.python.org/issue9849, which seeks to improve the error checking for nargs. There, add_argument returns an ArgumentError if the nargs value is not a valid string, interger, or it there is mismatch between a tuple metavar and nargs. This range nargs should be tested at the same time, and return a ArgumentError if possible. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11354 ___ ___ Python-bugs-list mailing list Unsubscribe: http://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: This patch adds this `nargs='{m,n}'` or `nargs=(m,n)` feature. It builds on the `better nargs error message` patch in http://bugs.python.org/msg187754 It includes an argparse.rst paragraph, changes to argparse.py, and additions to test_argparse.py. The tests include those proposed by wm, rewritten to use the ParserTestCase framework where possible. I did not give a lot of thought to test names. The coverage could also use further thought. As WM noted some range cases are the equivalent to existing nargs options ('{1,}'=='+'). I did not attempt to code or test such equivalences. Since the '{0,}' form uses regex matching just like '*', I don't think there is any advantage to making such a translation. I convert the tuple version (m,n) to the re string '{m,n}' during the add_argument() testing. So it is the string form that is added to the parser action. This is also the format that appears in usage. The documentation paragraph is: '{m,n}'. m to n command-line arguments are gathered into a list. This is modeled on the Regular Expression use. '{,n}' gathers up to n arguments. '{m,}' gathers m or more. Thus '{1,}' is the equivalent to '+', and '{,1}' to '?'. A tuple notation is also accepted, '(m,n)', '(None,n)', '(m,None)'. For example: parser = argparse.ArgumentParser(prog='PROG') parser.add_argument('--foo', nargs='{2,4}') parser.parse_args('--foo a b c'.split()) Namespace(foo=['a', 'b', 'c']) parser.parse_args('--foo a'.split()) usage: PROG [-h] [--foo FOO{2,4}] PROG: error: argument --foo: expected {2,4} arguments -- Added file: http://bugs.python.org/file30187/nargsrange.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11354 ___ ___ Python-bugs-list mailing list Unsubscribe: http://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: Wouldn't it be simpler to use the re {m,n} notation to grab the appropriate number of arguments? In ArgumentParser _get_nargs_pattern we could add: +# n to m arguments, nargs is re like {n,m} +elif is_mnrep(nargs): +nargs_pattern = '([-A]%s)'%nargs # all others should be integers where is_mnrep() tests that the nargs string looks like '{m,n}' (or '{,n}' or '{m,}'). The resulting nargs_pattern will look like '([-A]{m,n})' In _format_args() a similar addition would be: +elif is_mnrep(action.nargs): +result = '%s%s' % (get_metavar(1)[0], action.nargs) 'FOO{2,5}' It would take more code to generate FOO FOO [FOO [FOO [FOO]]] A matching programmer input would be: parser.add_argument('Foo', nargs='{2,5}') though it wouldn't be much work to also translate a tuple. parser.add_argument('Foo', nargs=(2,5)) I'll try to test this implementation against wm's tests. -- nosy: +paul.j3 Added file: http://bugs.python.org/file30181/prelimary.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11354 ___ ___ 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: This is a revision of the test_intermixed.py that I submitted earlier. Now `parse_intermixed_args` acts like `parse_args', and calls `parse_known_intermixed_args`. Again it is form that can exercise the idea without modifying `argparse.py`. If the parser has incompatible features (REMAINDER, PARSER, or certain exclusive groups), it raises an error. However to facilitate testing I included a `_fallback` backdoor. If not default None it will be called instead of raising the error. While making documentation changes, I got to wondering whether 'interspersed' would be a better term than 'intermixed'. optparse has an 'interspersed' option and api. However the getopt documentation does use 'intermixed'. -- Added file: http://bugs.python.org/file30159/test_intermixed.py ___ 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: This is the formal patch corresponding to the `test_intermixed.py`. It includes changes to `argparse.rst`, plus tests in `test_argparse.py`. These tests are near the end, after those for `parse_known_args`. They are roughly equivalent to the examples in `test_intermixed.py`. - The new documentation section is: Some users expect to freely intermix optional and positional argument strings. For example, optparse, by default, allows interspersed argument strings. GNU getopt() permutes the argument strings so non-options are at the end. The parse_intermixed_args() method emulates this behavior by first calling parse_known_args() with just the optional arguments being active. It is then called a second time to parse the list of remaining argument strings using the positional arguments. parse_intermixed_args() raises an error if the parser uses features that are incompatible with this two step parsing. These include subparsers, argparse.REMAINDER, and mutually exclusive groups that include both optionals and positionals. In this example, parse_known_args() returns an unparsed list of arguments [‘2’, ‘3’], while parse_intermixed_args() returns rest=[1, 2, 3]. parser = argparse.ArgumentParser() parser.add_argument('--foo') parser.add_argument('cmd') parser.add_argument('rest', nargs='*', type=int) parser.parse_known_args('cmd1 1 --foo bar 2 3'.split()) (Namespace(cmd='cmd1', foo='bar', rest=[1]), ['2', '3']) parser.parse_intermixed_args('cmd1 1 --foo bar 2 3'.split()) Namespace(cmd='cmd1', foo='bar', rest=[1, 2, 3]) parse_known_intermixed_args() method, returns a two item tuple containing the populated namespace and the list of remaining argument strings. parse_intermixed_args() raises an error if there are any remaining unparsed argument strings. -- Added file: http://bugs.python.org/file30160/intermixed.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
[issue17890] argparse: mutually exclusive groups full of suppressed args can cause AssertionErrors
paul j3 added the comment: I see three solutions - 1) gholms' patch which removes '() ' and [] ' 2) Yogesh's patch which removes all duplicated spaces. 3) remove the 2 asserts. The first 2 do the same thing most of the time, but may differ if the user somehow inserts spaces into names. The third leaves the extra blanks, but renders them innocuous. I doubt if the asserts were written to catch this problem. They probably were included to verify the usage line had been split up as expected prior to reassembling on multiple lines. As best I can tell test_argparse.py does not test for these spaces. Curiously though a port of argparse to javascript does have a test case with the extra space. -- ___ 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
[issue17890] argparse: mutually exclusive groups full of suppressed args can cause AssertionErrors
paul j3 added the comment: Looks like the text = text.strip() at the end of the set of regex (in _format_actions_usage) needs to be replaced with something that removes all excess spaces, e.g. text = _re.sub( '\s+', ' ', text ).strip() -- nosy: +paul.j3 ___ 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
[issue17890] argparse: mutually exclusive groups full of suppressed args can cause AssertionErrors
paul j3 added the comment: In the test case: class TestMutuallyExclusiveManySuppressed even with a short 'eggs' argument, there is a difference Old usage would be: usage: PROG [-h] [--eggs EGGS] new usage: PROG [-h] [--eggs EGGS] i.e. 2 v 1 space. But extra spaces are not as dramatic a failure as an assertion error. It would also be good to check what happens when there are 2 suppressed groups. If the text before all trimming is: [ -h ] [] () [ --eggs EGGS ] does it reduce to? [-h] [--eggs EGGS] The old code would have left 3 spaces. I can't think of a situation in which a user would want a (generated) usage line with multiple spaces. If some sort of special formatting is needed, there is always the option of specifying an explicit usage line. parser = ArugmentParser(usage='one \ttwo \nthree four') -- ___ 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
[issue16142] ArgumentParser inconsistent with parse_known_args
paul j3 added the comment: Correction: The patch I gave in the last message produces: parser.parse_known_args(['-ku']) (Namespace(known=False), ['u']) It doesn't take action on the '-k', and puts 'u' in extras, not '-u'. This new patch gets it right: parser.parse_known_args(['-ku']) (Namespace(known=True), ['-u']) We need more test cases, including ones that work as expected with optparse or other unix parsers. -- Added file: http://bugs.python.org/file30056/dashku.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16142 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue16970] argparse: bad nargs value raises misleading message
paul j3 added the comment: An integer nargs value is only used in one of 2 ways, range(nargs) '%s'*nargs In both a negative value acts the same as a 0. I don't think the original authors though much about 'what if the code user gives a negative value?', because nargs is counting things - the number of expected arguments. For some actions that number is 0. For other some sort of positive integer, or variable numbers like '*','+' make most sense. To some degree nargs is modeled on the regex sequences, '*','+','?','{n}'. '{-1}' does not produce a regex error, though I can't make anything match it. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16970 ___ ___ 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: This patch adds a value test for nargs during add_argument. The core of the new test is in ArgumentParser._check_argument. add_argument() now calls ArgumentParser._check_argument(), which calls _format_args(). If it gets a TypeError, it raises a metavar ValueError as before. But if it gets an ValueError, it raises an ArgumentError. An argument group gets the _check_argument method from its container. This way, check_argument() works for both parsers and groups. HelpFormater _format_args() now raises a ValueError if the nargs is not an integer (or one of the recognized strings). What kind of error should we produce when there is a problem with nargs? An ArgumentError has the advantage that it includes the action name. But the metavar tuple test was coded to raise ValueError. Plus the test_argparse.py TestInvalidArgumentConstructors class tests all check for TypeError or ValueError. I have kept the metavar tuple case as ValueError. That way, test_argparse.py runs without a change. I still need to add tests for invalid string nargs values. And I think the case could be made for returning ArgumentValue errors. -- keywords: +patch Added file: http://bugs.python.org/file29998/nargswarn.patch ___ 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
[issue9849] Argparse needs better error handling for nargs
paul j3 added the comment: The attached test_nargswarn.py file tests the argparse.py patch. It tries out various nargs values, both for parsers, groups, and mutually exclusive groups. I intend to recast these to work in test_argparse.py -- Added file: http://bugs.python.org/file2/test_nargswarn.py ___ 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
[issue9849] Argparse needs better error handling for nargs
paul j3 added the comment: This is a revision of yesterday's patch. It includes a couple of test cases that check that parser, groups, and exclusive groups all produce the error message. I also changed the metavar tuple case to return an ArgumentError, and changed test_argparse.py accordingly. (this metavar testing was added in http://bugs.python.org/issue9348). This issue overlaps with http://bugs.python.org/issue16970, 'argparse: bad nargs value raises misleading message'. There, though, the focus is more on the error message when nargs=0. While nargs1 might not make much sense, it technically does not break anything. -- Added file: http://bugs.python.org/file30010/nargswarn.patch ___ 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
[issue16970] argparse: bad nargs value raises misleading message
paul j3 added the comment: http://bugs.python.org/issue9849 also deals with nargs values. However there the focus is on string values like '1', not whether an integer value can be 0 or 0. I submitted a patch that moves the nargs testing to a ArgumentParser._check_argument() method. It still depends on _format_args to do the actual testing of nargs. I also make sure that group.add_argument() does this test. Regarding this issue, can nargs=0 or 0? _Store_action objects to 0, not because it causes runtime errors, but because it does not make sense. Code with nargs=-1 runs without error, not consuming a string and returning [], just as a nargs=0 would. In http://bugs.python.org/issue14191 I found it useful to temporarily set nargs=0 to 'turn off' a positional. I would vote for leaving this error message as is: ValueError: nargs for store actions must be 0; if you have nothing to store, actions such as store true or store const may be more appropriate even though the test is actually nargs==0. For normal use the recommendation that nargs0 makes sense. -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16970 ___ ___ 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: This nargs test using the formater applies only when the container has a help formatter. That is true for a ArgumentParser, but not for an argument_group. group = parser.add_argument_group('g') group.add_argument('bar', nargs='test') does not raise an error. format_help will produce an error: ... File ./argparse.py, line 585, in _format_args formats = ['%s' for _ in range(action.nargs)] TypeError: 'str' object cannot be interpreted as an integer while parse_args produces the error: ... File ./argparse.py, line 2200, in _get_nargs_pattern nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs) TypeError: can't multiply sequence by non-int of type 'str' -- ___ 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
[issue14191] argparse doesn't allow optionals within positionals
paul j3 added the comment: Yes, http://bugs.python.org/msg166175 does use 'parse_args' in the second call. But I think things would be more flexible if we had a second function: def parse_???(self, args=None, namespace=None): args, argv = self.parse_intermixed_args(args, namespace) if argv: msg = _('unrecognized arguments: %s') self.error(msg % ' '.join(argv)) return args But then what would a be a good pair of names? parse??? and parse_intermixed_args versus parse_intermixed_args and parse_known_intermixed_args or something else? -- ___ 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: The attached file has a 'parse_intermixed_args()' that has the same API as 'parse_known_args()'. It follows the two parse step model args, remaining_args = optionals.parse_known_args() args, extras = positionals.parse_known_args(remaining_args, args) except that the 'optionals parser' is self with the positional arguments 'deactivated' by setting their nargs to 0. Similarly the 'positionals parser' is self with the optional arguments set to 'required=false'. Here it is in a standalone test module illustrating its functionality and limitations. I could provide a patch, but this form might easier to test in your own code. When used to run test_argparse.py, it had problems in the cases where the distinction between positionals and optionals is blurred. For example, PARSER and REMAINDER are supposed to grab everything that follows regardless of what it looks like. I choose to fall back on a single 'parse_know_args' call. Raising an error would the alternative. Similarly, a mutually exclusive group that includes a positional is difficult to handle. Again I fall back on the single step. So the two issues to be discussed are: - does it provide the desired freedom to mix optionals and positionals? - in the difficult cases, should it punt, or raise an error? -- Added file: http://bugs.python.org/file29982/test_intermixed.py ___ 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
[issue14364] Argparse incorrectly handles '--'
paul j3 added the comment: The patch that I recently submitted for http://bugs.python.org/issue13922 appears to solve this issue. It only removes the '--' that marked the end of options. With: parser = argparse.ArgumentParser() parser.add_argument('-f','--foo') print(parser.parse_args(['-f--'])) print(parser.parse_args(['--foo=--'])) print(parser.parse_args(['-f', '--'])) I get: Namespace(foo='--') Namespace(foo='--') usage: foodash.py [-h] [-f FOO] foodash.py: error: argument -f/--foo: expected one argument -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue14364 ___ ___ Python-bugs-list mailing list Unsubscribe: http://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: The 'subparsers' object has a _parser_class attribute that is normally set to the class of the parent parser. In the attached file I create a class CustomParser(argparse.ArgumentParser) that makes a parser instance which copies all of the attributes of prototype parser. proto1 = argparse.ArgumentParser(prog='SUBPROG1') proto1.add_argument('--foo') subparsers._parser_class = CustomParser sub1 = subparsers.add_parser('cmd1', proto=proto1, help='parser based on proto1') 'sub1' is a functional copy of 'proto1'. I think this does what you want without changing the argparse code. There probably is a way of defining CustomParser (maybe its '__new__' method) so 'sub1' is actually 'proto1'. But the copy approach appears to work just fine. -- nosy: +paul.j3 Added file: http://bugs.python.org/file29916/issue17204.py ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue17204 ___ ___ 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: Glenn Take a look at http://bugs.python.org/issue15427 I took a stab at changing the documentation, including recommending parse_known_args when porting optparse uses. -- ___ 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
[issue14364] Argparse incorrectly handles '--'
Changes by paul j3 ajipa...@gmail.com: -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue14364 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue16308] Undocumented (?) behaviour change in argparse from 3.2.3 to 3.3.0
paul j3 added the comment: I submitted a patch to http://bugs.python.org/issue9253 The reason why subparser became optional in the latest release is that a old test for missing positionals was phased out, and new one added. Subparsers have always had a default 'required=False', but the old test did not actually pay attention to that attribute. It is easy to change the default attribute, but that ends up exposing a bug in the new test (trying to ','.join[...,None,...]). My patch corrects that, and exposes the 'required' attribute. It also has doc changes and test additions. I could rewrite it so it does not change the API or the doc. -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16308 ___ ___ Python-bugs-list mailing list Unsubscribe: http://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: In this example: p.add_argument('--foo', nargs='*', default=None) p.parse_args([]) Namespace(foo=None) p.parse_args(['--foo']) Namespace(foo=[]) 'p.parse_args([])' just assigns the default to 'foo' in the Namespace. p.parse_args(['--foo']) invokes 'take_action(dest='foo',[]). That is, it 'assigns' an empty array to 'foo'. The same thing would happen if 'foo' was a positional. 'take_action' then passes these arguments to '_get_values'. That is where the differences between '?' and '*' arise. The key pieces of code in '_get_values' when arg_strings==[] are: # optional argument produces a default when not present if not arg_strings and action.nargs == OPTIONAL: value = action.default # and evaluate 'value' if is a string # when nargs='*' on a positional, if there were no command-line # args, use the default if it is anything other than None elif (not arg_strings and action.nargs == ZERO_OR_MORE ...): if action.default is not None: value = action.default else: value = arg_strings # i.e. [] In other words, if nargs='?', the attribute gets its default value. But for '*', this is true only if the default is not None. So in: parse([], nargs='?')# get the default value: None parse([], nargs='*')# default is None, get arg_strings [] parse([], nargs='*', default=None) # same case parse([], nargs='*', default=False) # default is not None, get default parse([], nargs='*', default=0) # same case I tried changing the _get_values() so '*' got the default (like '?' does), and got 54 failures when running test_argparse.py. -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16878 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue17050] argparse.REMAINDER doesn't work as first argument
paul j3 added the comment: The problem isn't with REMAINDER, but with the distinction between optionals and arguments. If you change '--def' to 'def', the parse should work: p = ArgumentParser(prog='test.py') p.add_argument('remainder', nargs=argparse.REMAINDER) p.parse_args(['def']) '--def' would give problems with almost all of the nargs options, especially '*' and '?'. The issue is that '--def' looks like an optional. Since it is not found in the defined arguments, it is classed as an unknown extra and skipped (try p.parse_known_args(['--def'])). All of this takes place before 'REMAINDER' has a chance to look at the argument strings. In http://bugs.python.org/issue9334 I submitted a patch that defines a 'args_default_to_positional' parser option. If this is True, that unrecognized '--def' would be classed as a 'positional' and would be captured by the REMAINDER. -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue17050 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue17050] argparse.REMAINDER doesn't work as first argument
paul j3 added the comment: Here's a way of passing an optional-like argument to a subparser: parser = argparse.ArgumentParser() subparsers = parser.add_subparsers(dest='cmd') sub1 = subparsers.add_parser('cmd') sub1.add_argument('foo',nargs='*') args = parser.parse_args('cmd -- --def 1 2 3'.split()) producing Namespace(cmd='cmd', foo=['--def', '1', '2', '3']) The '--' forces the parser to treat '--def' as a positional. If nargs='REMAINDER', foo=['--', '--def', ...]. But the following subparser definition would be even better: sub1.add_argument('--def', action='store_true') sub1.add_argument('rest',nargs='...') Here the '--def' is handle explicitly, as opposed to being passed on. You don't need the whole subparsers mechanism if you are just going to pass those arguments (unparsed) to another program. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue17050 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14174] argparse.REMAINDER fails to parse remainder correctly
paul j3 added the comment: An alternative to Jason's example: parser = argparse.ArgumentParser() parser.add_argument('app') parser.add_argument('--config') parser.add_argument('app_args', nargs=argparse.REMAINDER) args = parser.parse_args(['--config', 'bar', 'app']) print vars(args) # as expected: {'app': 'app', 'app_args': [], 'config': 'bar'} When you have several positionals, one or more of which may have 0 arguments (*,?,...), it is best to put all of the optional arguments first. With 'app --config bar', parse_args identifies a 'AOA' pattern (argument, optional, argument). It then checks which positional arguments match. 'app' claims 1, 'app_args' claims 2 (REMAINDER means match everything that follows). That leaves nothing for '--config'. What you expected was that 'app' would match with the 1st string, '--config' would match the next 2, leaving nothing for 'app_args'. In http://bugs.python.org/issue14191 I wrote a patch that would give the results you want if 'app_args' uses '*'. That is makes it possible to interleave positional and optional argument strings. But it does not change the behavior of REMAINDER. parser.add_argument('app_args', nargs='*') -- Maybe the documentation example for REMAINDER needs to modified to show just how 'greedy' REMAINDER is. Adding a: parser.add_argument('--arg1',action='store_true') does not change the outcome. REMAINDER still grabs '--arg1' even though it is a defined argument. Namespace(arg1=False, args=['--arg1', 'XX', 'ZZ'], command='cmd', foo='B') -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue14174 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14174] argparse.REMAINDER fails to parse remainder correctly
paul j3 added the comment: By the way, parser.parse_args() uses parse_known_arg(). parse_known_args returns a Namespace and a list of unknown arguments. If that list is empty, parse_args returns the Namespace. If the list is not empty, parse_args raises an error. So parse_known_args does not change how arguments are parsed. It just changes how the unknowns are handled. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue14174 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue16142] ArgumentParser inconsistent with parse_known_args
paul j3 added the comment: parser = argparse.ArgumentParser() parser.add_argument('-k','--known',action='store_true') print(parser.parse_known_args(['-k','-u'])) print(parser.parse_known_args(['-ku'])) print(parser.parse_known_args(['-uk'])) I think you want these 3 cases to produce the same output: (Namespace(known=True), ['-u']) With the attached patch, '-ku' produces the same result as '-k -u'. Instead of raising the ignored explicit argument 'u' error, if puts '-u' in the 'extras' list. 'parse_args' then raises a error: unrecognized arguments: u error. That's an easy change, and does not break anything in the 'test_argparse.py' file. But keep in mind that this test file mostly uses 'parse_args', and usually it ignores the failure messages. Getting '-uk' to work this way would be much harder. While it isn't obvious from the documentation, '-uk' is a valid option string, and '-u' is a valid abbreviation. Notice in 16.4.4.1. of the documentation, the difference between long and short options is based on the number of characters, not whether there it starts with '-' or '--'. So identifying what is wrong with '-uk' would require ambiguous reasoning. I wonder what optparse does. -- keywords: +patch nosy: +paul.j3 Added file: http://bugs.python.org/file29910/dashku.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16142 ___ ___ 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: 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/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
[issue9849] Argparse needs better error handling for nargs
paul j3 added the comment: It does shift the error from parse_args to add_argument, but the message 'ValueError: length of metavar tuple does not match nargs', indicates that it's a side effect of checking on the tuple form of `metavar`. http://bugs.python.org/issue9348 There is still room for cleaning up these tests. There are 2 functions that define what are acceptable values for nargs, [None, OPTIONAL, ZERO_OR_MORE, ONE_OR_MORE, REMAINDER, PARSER, integer]. Should one or other explicitly check nargs is an integer if it does not match one of the other strings? And the test in _ActionContainer.add_argument() # raise an error if the metavar does not match the type if hasattr(self, _get_formatter): try: self._get_formatter()._format_args(action, None) except TypeError: raise ValueError(length of metavar tuple does not match nargs) uses an ArgumentParser._get_formatter method (though 'hasattr' prevents runtime errors). In fact both functions that use nargs belong to the parser, not the container. I wonder if `add_argument` should be moved to ArgumentParser. -- nosy: +paul.j3 ___ 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
[issue16988] argparse: PARSER option for nargs not documented
paul j3 added the comment: I've experimented with an argparse adaptation of profile.py: parser = argparse.ArgumentParser(usage=usage) parser.add_argument('-o', '--outfile', dest=outfile, help=Save stats to outfile, metavar=path) parser.add_argument('-s', '--sort', dest=sort, help=Sort order when printing to stdout ..., default=-1) parser.add_argument('args', nargs=argparse.PARSER, metavar=scriptfile [arg] ...) # expect at least one positional, a py module It is somewhat like subparsers, but without defined subparser choices. Or you could say that PARSER (A...) is to REMAINDER (...) as '+' is to '*'. It requires at least one argument. I could, just as well, have created two arguments, 'scriptfile' and 'args' (with '...'). I don't know if that is an argument for documenting it or not. -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16988 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue13922] argparse handling multiple -- in args improperly
paul j3 added the comment: This patch removes only one '--', the one that put a '-' in the 'arg_strings_pattern'. It does this in 'consume_positionals' right before calling 'take_action'. As before it does not do this if nargs is PARSER or REMAINDER. test_argparse.py has two DoubleDashRemoval cases, that attempt to highlight the changes from production (delete all --) and development (delete first -- in each positional group) versions. I have not made any changes to the documentation. All it says now is: If you have positional arguments that must begin with - and don’t look like negative numbers, you can insert the pseudo-argument '--' which tells parse_args() that everything after that is a positional argument: -- Added file: http://bugs.python.org/file29845/dbldash.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue13922 ___ ___ 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: This patch addresses both issues raised here: - throw an error when the subparser argument is missing - allow the subparser argument to be optional argparse.py: _SubParsersAction - add 'required=True' keyword. name(self) method - creates a name of the form {cmd1,cmd2} for error messages. _get_action_name() - try action.name() if it can't get a name from option_strings, dest or metavar. Still can return None. 2 error cases do a join on a list of action_names. If a name is None, this will choke. Add a ['%s'%x for x in list] guard. test_argparse.py: add cases to the subparser block to test the 'required' keyword, and to test the error message changes. argparse.rst: add a summary of the add_subparsers() arguments. -- Added file: http://bugs.python.org/file29793/required.patch ___ 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
[issue9253] argparse: optional subparsers
paul j3 added the comment: Further observations: parser.add_subparsers() accepts a 'dest' keyword arg, but not a 'required' one. Default of 'dest' is SUPPRESS, so the name does not appear in the Namespace. Changing it to something like 'command' will produce an entry, e.g. Namespace(command=foo, ...). Is this a problem? Assuming we have a clean way of assigning a name to 'subparsers', what should it be? 'command', '{cmd}', '{foo,bar,baz}' (like in the usage line)? This name also could be used when telling the user the subparser choice is invalid (parser._check_value). This issue exposes a problem with '_get_action_name()'. This function gets a name from the action's option_strings, metavar or dest. If it can't get a string, it returns None. ArgumentError pays attention to whether this action name is a string or None, and adjusts its message accordingly. But the new replacement for the 'too few arguments' error message does a ', '.join([action names]), which chokes if one of those names is None. There is a mutually_exclusive_groups test that also uses this 'join'. This bug should be fixed regardless of what is done with subparsers error messages. So the issues are: - making 'subparsers' a required argument - choosing or generating an appropriate name for 'subparsers' - passing this name to the error message (via _get_action_name?) - correcting the handling of action names when they are unknown (None). -- ___ 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
[issue9253] argparse: optional subparsers
paul j3 added the comment: I think this problem arises from a change made in http://bugs.python.org/issue10424 Changeset to default (i.e. development) is http://hg.python.org/cpython/rev/cab204a79e09 Near the end of _parse_known_args it removes a: if positionals: self.error(_('too few arguments')) with a scan for required options that have not been seen. Ordinary positionals are required. But a SubParsersAction is not required. So we no longer get a warning. http://bugs.python.org/issue12776 changed this block of code as well. Notice the 2.7 and 3.2 branches have this 'too few arguments' error, but the default does not. The default value for Action.required is False. In _get_positional_kwargs(), a positional's required is set based on nargs (e.g. '+' is required, '*' not). But add_subparsers() does not use this, so its 'required' ends up False. This fudge seems to do the trick: parser = ArgumentParser(prog='test') subparsers = parser.add_subparsers() subparsers.required = True subparsers.dest = 'command' subparser = subparsers.add_parser(foo, help=run foo) parser.parse_args() producing an error message: usage: test [-h] {foo} ... test: error: the following arguments are required: command subparsers.dest is set so the error message can give this positional a name. I'll try to write a patch to do something similar in argparse itself. -- nosy: +paul.j3 ___ 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
[issue13922] argparse handling multiple -- in args improperly
paul j3 added the comment: I am working on an alternative solution that moves the '--' removal to the consume_positionals() method, and only does it if there is a corresponding '-' in the arg_strings_pattern. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue13922 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue13922] argparse handling multiple -- in args improperly
paul j3 added the comment: There are several problems with the patch provided in msg156315 This description: Added patch so that only the first '--' is removed by an argparse.PARSE or argparse.REMAINDER argument. should read Added patch so that only the first '--' is removed by arguments that are not argparse.PARSER or argparse.REMAINDER . The test that adds a third subparser with a nargs='...' argument does not test this change. It exercises both nargs types that are not affected by the change in argparse.py. As such older versions of argparse pass this test. I thinking argparse.py change is correct (delete only the 1st '--'), though I'm not sure it addresses the concern of the original poster. -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue13922 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue13922] argparse handling multiple -- in args improperly
paul j3 added the comment: There's another 'feature' to the patch proposed here. It only deletes the first '--' in the list of strings passed to '_get_values' for a particular action. parser = argparse.ArgumentParser() parser.add_argument('foo') parser.add_argument('bar', nargs='*') print(parser.parse_args('-- 1 -- 2 3 4'.split(' '))) # Namespace(bar=['2', '3', '4'], foo='1') '_get_values' first gets ('foo',['--','1']), then ('bar',['--','2','3','4']) print(parser.parse_args('-- -- 1 -- 2 -- 3 4'.split(' '))) # with this '1st only' change # Namespace(bar=['1', '2', '--', '3', '4'], foo='--') # without it, deleting all '--'; note foo is empty # Namespace(bar=['1', '2', '3', '4'], foo=[]) And to confuse things a bit more: print(parser.parse_args('1 -- 2 3 4'.split(' '))) # Namespace(bar=['2', '3', '4'], foo='1') passes ['1','--'] with 'foo' If 'bar' nargs='...', bar gets all of the '--' (with or without this patch). The handling of '--' is complex because it is used in one place to mean, 'everything else is an argument', effectively adding '-AA...' to the arg_strings_pattern. It also matches with the nargs_pattern (e.g. '(-*A-*)...'). And then it may or may not be removed in _get_values(). -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue13922 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue13966] Add disable_interspersed_args() to argparse.ArgumentParser
paul j3 added the comment: Looking further at test_argparse.py, I should say that the behavior of multiple positionals when there is one cluster of positional argstrings is well illustrated in the tests. It's the behavior when there are multiple clusters (interspersed positionals) that can go against some intuitions. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue13966 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue15427] Describe use of args parameter of argparse.ArgumentParser.parse_args
paul j3 added the comment: This patch to argparse.rst adds the argument points to parse_args(). It also adds two points to the 'Upgrading optparse code' section, one about using 'nargs=argparse.REMAINDER', and other about 'parse_known_args()'. I'm not entirely happy with the format of the internal hyperlinks. -- keywords: +patch Added file: http://bugs.python.org/file29661/remainder.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue15427 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue15427] Describe use of args parameter of argparse.ArgumentParser.parse_args
paul j3 added the comment: I changed the reference to the optparse allow_interspersed_args attribute to the disable_interspersed_args() method. -- Added file: http://bugs.python.org/file29662/remainder.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue15427 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue13966] Add disable_interspersed_args() to argparse.ArgumentParser
paul j3 added the comment: The optparse page gives a reason for disable_interspersed_args(): Use this if you have a command processor which runs another command which has options of its own and you want to make sure these options don’t get confused. For example, each command might have a different set of options. In argparse: argparse.REMAINDER. All the remaining command-line arguments are gathered into a list. This is commonly useful for command line utilities that dispatch to other command line utilities: If you have only one positional argument, and its nargs is REMAINDER, you have effectively disabled interspersed. Argparse doesn't prohibit all interspersed positionals. You could, for example, have one or more positionals with other nargs that could be interspersed. But the REMAINDER one has to be last. In the library, profile.py uses 'optparse.disable_interspersed'. I just replaced optparse with argparse using the REMAINDER, and got the same behavior. (Actually I used argparse.PARSER which effectively requires at least one argument.) -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue13966 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue16399] argparse: append action with default list adds to list instead of overriding
paul j3 added the comment: The test file, test_argparse.py, has a test case for this: 'class TestOptionalsActionAppendWithDefault' argument_signatures = [Sig('--baz', action='append', default=['X'])] successes = [ ('--baz a --baz b', NS(baz=['X', 'a', 'b'])), ] -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16399 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue13966] Add disable_interspersed_args() to argparse.ArgumentParser
paul j3 added the comment: Oops, I was wrong about this: Argparse doesn't prohibit all interspersed positionals. You could, for example, have one or more positionals with other nargs that could be interspersed. But the REMAINDER one has to be last. parser.add_argument('a') parser.add_argument('--foo') parser.add_argument('rest', nargs='...') parser.parse_args('a --foo b c'.split(' ') produces: Namespace(a='a', foo=None, rest=['--foo', 'b', 'c']) That is because, 'rest' matches an empty list of arguments. With an nargs='*' or '?', the same thing happens, both 'a' and 'rest' are used up when processing the first positional argument string. nargs=argparse.PARSER (= 'A...') gives the expected Namespace(a='a', foo='b', rest=['c']) In this case, 'rest' has to wait till the second set of positionals. Documentation warns Note that it generally doesn’t make much sense to have more than one positional argument with nargs='*'. Maybe it should warn against combining any of the 'zero or more' positionals with other positionals. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue13966 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue15427] Describe use of args parameter of argparse.ArgumentParser.parse_args
paul j3 added the comment: The 'args=' parameter is the same as the first positional parameter used in most of the examples. That is normal Python behavior. 15.4.4.5. Beyond sys.argv explains this alternative way of specifying argv. Still 2 bullet points could be added to 15.4.4. - args - A list of strings, default is sys.argv[1:] (link to 15.4.4.5.) - namespace - A Namespace object, default is a new Namespace (link to 15.4.4.6.) Maybe a 15.4.4.5. example using args=['1', '2', '3', '4'] would also be helpful. -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue15427 ___ ___ 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: Glenn I looked at your t18a.py test case parser = ArgumentParser() parser.add_argument('--foo', dest='foo') parser.add_argument('--bar', dest='bar') parser.add_argument('foz') parser.add_argument('baz', nargs='*') and parse variations on 'a b c d --foo x --bar 1' I think your main problem is with the 'baz', nargs='*'. If nargs was changed to '+', 'a --foo x b c d --bar 1' would work, returning {foz='a', bar=['b','c','d']}. argparse alternates between consuming positional and optionals until it runs out of arguments or argument strings. But with '*', both 'foz' and 'baz' are consumed with the first set of positional strings {foz='a', baz=[]}. When it gets to 'b c d' there are no more positional arguments to consume, so they get put into 'extras'. With nargs='+', 'a b --foo x c d --bar 1' would assign {foz='a', baz=[b]}, and extras=['c','d']. So while optionals can be interspersed with positionals, they can't be placed within the set of strings intended for one positional. That seems to me to very reasonable (why break up 'b c d'?). And as your file demonstrates, you can fall back on parse_known_args to handle the extras. -- nosy: +paul.j3 ___ 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
[issue9334] argparse does not accept options taking arguments beginning with dash (regression from optparse)
paul j3 added the comment: This patch makes two changes to argparse.py ArgumentParser._parse_optional() - accept negative scientific and complex numbers - add the args_default_to_positional parser option _negative_number_matcher only matches integers and simple floats. This is fine for detecting number-like options like '-1'. But as used in _parse_optional() it prevents strings like '-1e4' and '-1-4j' from being classed as positionals (msg184174). In this patch it is replaced with try: complex(arg_string) return None except ValueError: pass Immediately before this number test I added if self.args_default_to_positional: return None to implement the idea suggested in msg169978. I added the args_default_to_positional parser option to the documentation, along with some notes on its implications in the `Arguments containing -` section. A few of the examples that I added use scientific or complex numbers. I tested test_argparse.py with args_default_to_positional=True default. A number of the 'failures' no longer failed. class TestDefaultToPositionalWithOptionLike illustrates this in the Option-Like situation. The only 'successes' to fail were in the TestAddSubparsers case. There an argument string '0.5 -p 1 b -w 7' produced 'wrong choice' error, since the '-p' was assumed to be a commands choice, rather than an unknown optional. I translated the TestStandard cases from the optparse test file. argparse ran most of these without problem. The value of args_default_to_positional makes no difference. There a few optparse tests that use '--' or a valid optional as positional that argparse does not handle. -- keywords: +patch Added file: http://bugs.python.org/file29548/final.patch ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9334 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9334] argparse does not accept options taking arguments beginning with dash (regression from optparse)
paul j3 added the comment: I think the `re.compile(r'^-.+$')` behavior could be better achieved by inserting a simple test in `_parse_optional` before the `_negative_number_matcher` test. # behave more like optparse even if the argument looks like a option if self.args_default_to_positional: return None In effect, if the string does not match an action string, say it is a positional. Making this patch to argparse.py is simple. How much to test it, and how document it requires more thought. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9334 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9334] argparse does not accept options taking arguments beginning with dash (regression from optparse)
paul j3 added the comment: If nargs=2, type=float, an argv like '1e4 -.002' works, but '1e4 -2e-3' produces the same error as discussed here. The problem is that _negative_number_matcher does not handle scientific notation. The proposed generalize matcher, r'^-.+$', would solve this, but may be overkill. I'm not as familiar with optparse and other argument processes, but I suspect argparse is different in that it processes the argument strings twice. On one loop it parses them, producing an arg_strings_pattern that looks like 'OAA' (or 'OAO' in these problem cases). On the second loop is consumes the strings (optionals and positionals). This gives it more power, but produces problems like this if the parsing does not match expectations. -- nosy: +paul.j3 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9334 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9334] argparse does not accept options taking arguments beginning with dash (regression from optparse)
paul j3 added the comment: We need to be careful about when or where _negative_number_match is changed. We basically do: parser = argparse.ArgumentParser(...) parser._negative_number_matcher = re.compile(r'^-.+$') This changes the value for the parser itself, but not for the groups (_optionals, _positionals) or any subparsers. The code takes special care to make sure that the related property: _has_negative_number_optionals is properly shared among all these ActionContainers. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9334 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9334] argparse does not accept options taking arguments beginning with dash (regression from optparse)
paul j3 added the comment: While parser._negative_number_matcher is used during parser.parse_args() to check whether an argument string is a 'negative number' (and hence whether to classify it as A or O). parser._optionals._negative_number_matcher is used during parser.add_argument() to determine whether an option_string is a 'negative number', and hence whether to modify the _hasNegativeNumberOptionals flag. If this matcher is the general r'^-.+$', adding the default '-h' will set this flag. We don't want that. Using a different matcher for these two containers might work, but is awfully kludgy. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue9334 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue17250] argparse: Issue 15906 patch; positional with nargs='*' and string default
New submission from paul j3: The production argparse applies the type conversion to a string default whether it is needed or not. With the 12776 and 15906 patch, that conversion is postponed, so that it is applied only once. However, for a positional argument with nargs='*', that conversion is never applied. For example, with: add_argument('foo', type=FileType('r'), default='anyfile', nargs='*') the development version, with parse_args([]) produces Namespace(foo='anyfile') The previous code tested this default, raising an error if there was an IOError. But even if it successfully opened the file, the namespace would get the string value, not the opened file. With nargs = '?', the result is an IOError, or an opened file. It is evident from the code (but not the documentation) that the best default for the '*' positional is a list of appropriate type of objects. In the case of FileTypes, about the only choices, without opening a file, are: [] and [sys.stdin]. -- components: Library (Lib) messages: 182469 nosy: paul.j3 priority: normal severity: normal status: open title: argparse: Issue 15906 patch; positional with nargs='*' and string default type: behavior versions: Python 2.7, Python 3.4 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue17250 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue16940] argparse 15.4.5.1. Sub-commands documentation missing indentation
New submission from paul j3: Argparse 15.4.5.1. Sub-commands In the example: parser.parse_args(['--help']) usage: PROG [-h] [--foo] {a,b} ... positional arguments: {a,b} sub-command help a a help b b help optional arguments: -h, --help show this help message and exit --foo foo help The 'a help', 'b help' lines should be indented -- assignee: docs@python components: Documentation messages: 179766 nosy: docs@python, paul.j3 priority: normal severity: normal status: open title: argparse 15.4.5.1. Sub-commands documentation missing indentation versions: Python 2.7 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue16940 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue12954] Multiprocessing logging under Windows
New submission from paul j3 ajipa...@gmail.com: The Windows programming guidelines for the multiprocessing module documentation should include a warning that any logging initialization should be protected by the 'if __name__' block. Otherwise you will get duplicate logging entries for the child processes. This is because the multiprocessing.forking.prepare() function explicitly calls log_to_stderr(), and may implicitly do so again when it imports the parent module, resulting in duplicate logging handlers. -- assignee: docs@python components: Documentation messages: 143815 nosy: docs@python, paul.j3 priority: normal severity: normal status: open title: Multiprocessing logging under Windows ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue12954 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com