convert option names with dashes to underscores when used a kwargs
2 files changed, 29 insertions(+), 3 deletions(-)

M test/test_cli_commands.py
M vanity/commander.py
M test/test_cli_commands.py +13 -3
@@ 29,6 29,10 @@ def cmd3(**opts):
     return xxx(3)
 
 
+def fishfunc(in_water, verbose=None, quiet=None):
+    return in_water
+
+
 CMDTABLE_A = [
     ('foo', cmd1, '', [], 'FILENAME'),
     ('bar', cmd2, '', [], 'bar breaks it'),

          
@@ 45,7 49,9 @@ CMDTABLE_B = [
 
 CMDTABLE_C = {
     'snorkel': {'target': cmd1, 'opts': [], 'help': 'magic stuff'},
-    'fish': {'target': cmd2, 'opts': [], 'help': 'other stuff'},
+    'fish': {'target': fishfunc, 'opts': [
+        ('in-water', 'i', None, 'is it in the water'),
+        ], 'help': 'other stuff'},
     }
 
 CMDTABLE_D = [

          
@@ 117,9 123,9 @@ class TestCliCommands(unittest.TestCase)
     def test_dict_table_style(self):
         arguments = 'fish -v yes yes'.split()
         cmd, opts, args = commander.parse(GOPT_A, CMDTABLE_C, arguments)
-        self.assertEqual(cmd.target, cmd2)
+        self.assertEqual(cmd.target, fishfunc)
         self.assertEqual(args, ['yes', 'yes'])
-        self.assertEqual(opts, dict(verbose=True, quiet=None))
+        self.assertEqual(opts, {'verbose': True, 'quiet': None, 'in-water': None})
 
 
     def test_decorated_table(self):

          
@@ 250,6 256,10 @@ class TestCliCommands(unittest.TestCase)
             caught = True
         self.assertTrue(caught)
 
+    def test_dispatch_option_dashes(self):
+        v = commander.main(GOPT_A, CMDTABLE_C, 'fish --in-water'.split())
+        self.assertEqual(v, True)
+
     def test_main_dispatch_raises(self):
         self.assertRaises(TypeError,
             commander.main, GOPT_A, CMDTABLE_A, 'baz'.split())

          
M vanity/commander.py +16 -0
@@ 225,6 225,21 @@ def usage(cmd, short=False, prefix=''):
             yield line
 
 
+def cleanopts(opts, dropkeys=None):
+    """Convert raw options dictionary to one suitable for use a keyword
+    arguments to a python function.
+
+    * ``opts`` - The options dictionary to clean
+    * ``dropkeys`` - A list of keys to drop if they are in the opts
+    """
+    opts = dict([(k.replace('-', '_'), v) for k, v in opts.iteritems()])
+    if dropkeys:
+        for key in dropkeys:
+            if key in opts:
+                del opts[key]
+    return opts
+
+
 class Command(object):
     """A thin class representing a command.
 

          
@@ 241,6 256,7 @@ class Command(object):
         self.strict = strict
 
     def __call__(self, opts, args):
+        opts = cleanopts(opts, ('help',))
         try:
             return self.target(*args, **opts)
         except TypeError, err: