Permalink
Browse files

Mismatch between py zip() and _.zip()

In parse_known_args() consume_positionals()
the _.zip(positionals, argCounts)
behaves different from the python version when there aren't as many
argCounts as positionals.  Python zip iterates over the shortest, the
underscore version over the longest, adding undefines as needed.

The if (argCounts.length>0) takes care of some cases, but parsing
'X -f A Y', where arguments are -a, x, and y, is another case where
this JS zip is wrong.  At the start, there are 2 possible positional
actions [x, y], but only one [X] argument string.

Adding an argCount === undefined test is the simplest fix.
An alternative is to define a _zipShortest() as suggested in
http://stackoverflow.com/questions/4856717/javascript-equivalent-of-pythons-zip-function/13618399#13618399

I added a test case to base.js

I discovered this case when adapting 'TestArgumentsFromFile' from test_argparse.py
  • Loading branch information...
1 parent e702d5d commit 93dee3bb602ad0428b2cf08d8767092c796d0b44 @hpaulj hpaulj committed Jan 21, 2013
Showing with 20 additions and 4 deletions.
  1. +5 −4 lib/argument_parser.js
  2. +15 −0 test/base.js
View
@@ -489,17 +489,18 @@ ArgumentParser.prototype._parseKnownArgs = function (argStrings, namespace) {
// slice off the appropriate arg strings for each Positional
// and add the Positional and its args to the list
- if (argCounts.length > 0) {
- _.zip(positionals, argCounts).forEach(function (item) {
+ _.zip(positionals, argCounts).forEach(function (item) {
var action = item[0];
var argCount = item[1];
+ if (argCount === undefined) {
+ return;
+ }
var args = argStrings.slice(startIndex, startIndex + argCount);
startIndex += argCount;
takeAction(action, args);
});
- }
-
+
// slice off the Positionals that we just parsed and return the
// index at which the Positionals' string args stopped
positionals = positionals.slice(argCounts.length);
View
@@ -165,5 +165,20 @@ describe('base', function () {
assert.equal(parser.getDefault('goo'), 42);
assert.equal(parser.getDefault('help'), require('../lib/const').SUPPRESS);
});
+
+ it("should handle mixed positional and optional args", function () {
+ parser = new ArgumentParser({debug: true});
+ parser.addArgument(['-f', '--foo']);
+ parser.addArgument(['x']);
+ parser.addArgument(['y']);
+
+ args = parser.parseArgs(['X', 'Y']);
+ assert.deepEqual(args, {"foo": null, "x": "X", "y": "Y"});
+ args = parser.parseArgs(['-f', 'A', 'X', 'Y']);
+ assert.deepEqual(args, {"foo": "A", "x": "X", "y": "Y"});
+ args = parser.parseArgs(['X', '-f', 'A', 'Y']);
+ assert.deepEqual(args, {"foo": "A", "x": "X", "y": "Y"});
+ // was giving: Error: _mocha: error: Unrecognized arguments: X.
+ });
});

0 comments on commit 93dee3b

Please sign in to comment.