Permalink
Browse files

Merge pull request #45 from hpaulj/user_type

Bug in user defined argument type error message
  • Loading branch information...
2 parents 2141d0a + f94a0de commit cf4a2e0305e56259dbf09d3f224c6ff65727a6f1 @shkuropat shkuropat committed Feb 4, 2013
Showing with 130 additions and 8 deletions.
  1. +15 −8 lib/argument_parser.js
  2. +115 −0 test/user_defined_type.js
View
@@ -938,15 +938,22 @@ ArgumentParser.prototype._getValue = function (action, argString) {
result = typeFunction(argString);
// ArgumentTypeErrors indicate errors
+ // If action.type is not a registered string, it is a function
+ // Try to deduce its name for inclusion in the error message
+ // Failing that, include the error message it raised.
} catch (e) {
-
- throw argumentErrorHelper(
- action,
- _.str.sprintf('Invalid %(type)s value: %(value)s', {
- type: action.type,
- value: argString
- })
- );
+ var name = null;
+ if (_.isString(action.type)) {
+ name = action.type;
+ } else {
+ name = action.type.name || action.type.displayName || '<function>';
+ }
+ var msg = _.str.sprintf('Invalid %(type)s value: %(value)s', {
+ type: name,
+ value: argString
+ });
+ if (name === '<function>') {msg += '\n' + e.message; }
+ throw argumentErrorHelper(action, msg);
}
// return the converted value
return result;
View
@@ -0,0 +1,115 @@
+/*global describe, it*/
+
+'use strict';
+
+var assert = require('assert');
+
+var ArgumentParser = require('../lib/argparse').ArgumentParser;
+
+describe('base', function () {
+ var parser;
+ var args;
+
+ it("should handle builtin types", function () {
+ parser = new ArgumentParser({debug: true});
+ parser.addArgument(['--eggs'], {type: 'int'});
+ parser.addArgument(['spam'], {type: 'float'});
+
+ args = parser.parseArgs(['--eggs=42', '42']);
+ assert.deepEqual(args, {eggs: 42, spam: 42.0});
+ args = parser.parseArgs(['1024.675']);
+ assert.deepEqual(args, {eggs: null, spam: 1024.675});
+ assert.throws(
+ function () { parser.parseArgs(['--eggs', 'a']); },
+ /Invalid int value: a/i
+ );
+ });
+ it("should handle user-defined type", function () {
+ function myType(arg) {
+ return arg;
+ }
+ parser = new ArgumentParser({debug: true});
+ parser.addArgument(['-x'], {type: myType});
+ parser.addArgument(['spam'], {type: myType});
+
+ args = parser.parseArgs(['a', '-x', 'b']);
+ assert.deepEqual(args, {x: myType('b'), spam: myType('a')});
+ args = parser.parseArgs(['-xf', 'g']);
+ assert.deepEqual(args, {x: myType('f'), spam: myType('g')});
+ });
+ it("should give consistent type errors", function () {
+ function dateType(arg) {
+ var x = new Date(arg);
+ if (x.toString().match('Invalid')) {
+ throw new TypeError("" + arg + " is not a valid date.");
+ }
+ return x;
+ }
+ parser = new ArgumentParser({debug: true});
+ parser.addArgument(['-i'], {type: 'int', defaultValue: 0});
+ parser.addArgument(['-f'], {type: 'float', defaultValue: 0});
+ parser.addArgument(['-d'], {type: dateType, defaultValue: new Date(0)});
+ assert.throws(
+ function () { parser.parseArgs(['-f', 'abc']); },
+ /Invalid float value: abc/i
+ );
+ assert.throws(
+ function () { parser.parseArgs(['-i', 'abc']); },
+ /Invalid int value: abc/i
+ );
+ args = parser.parseArgs([]);
+ assert.deepEqual(args, {i: 0, f: 0, d: new Date(0)});
+ args = parser.parseArgs(['-d', '1/1/2012']);
+ assert.deepEqual(args, {i: 0, f: 0, d: new Date('1/1/2012')});
+ assert.throws(
+ function () {parser.parseArgs(['-d', '13/1/2000']); },
+ /Invalid dateType value: (.*)/i
+ /*
+ it used to insert the function code rather than its name
+ Invalid <dateType.toString()> value: 13/1/2000
+ */
+ );
+ assert.throws(
+ function () { parser.parseArgs(['-d', 'abc']); },
+ /Invalid dateType value: (.*)/i
+ );
+ });
+ it("Test a user-defined type by registering it", function () {
+ function dateType(arg) {
+ var x = new Date(arg);
+ if (x.toString().match('Invalid')) {
+ throw new TypeError("" + arg + " is not a valid date.");
+ }
+ return x;
+ }
+ parser = new ArgumentParser({debug: true});
+ parser.register('type', 'dateType', dateType);
+ parser.addArgument(['-d'], {type: 'dateType'});
+ args = parser.parseArgs(['-d', '1/1/2012']);
+ assert.deepEqual(args, {d: new Date('1/1/2012')});
+ assert.throws(
+ function () { parser.parseArgs(['-d', '13/1/2000']); },
+ /Invalid dateType value: (.*)/
+ );
+ });
+ it("Test an anonymous user-defined type", function () {
+ var dateType = function (arg) {
+ var x = new Date(arg);
+ if (x.toString().match('Invalid')) {
+ throw new TypeError("" + arg + " is not a valid date.");
+ }
+ return x;
+ };
+ //dateType.displayName = 'dateType';
+ parser = new ArgumentParser({debug: true});
+ parser.addArgument(['-d'], {type: dateType});
+ args = parser.parseArgs(['-d', '1/1/2012']);
+ assert.deepEqual(args, {d: new Date('1/1/2012')});
+ assert.throws(
+ function () { parser.parseArgs(['-d', 'abc']); },
+ /Invalid <function> value: abc\nabc is not a valid date/im
+ );
+ });
+});
+// could test for: Error: "dateType" is not callable
+// by using an unregistered string or other nonfunction

0 comments on commit cf4a2e0

Please sign in to comment.