Commits

Andy Mikhailenko committed 8001f1e

Added shortcut function `dispatch_commands`.

  • Participants
  • Parent commits d6e96a3

Comments (0)

Files changed (3)

 
 __all__ = [
     'ArghParser', 'add_commands', 'autocomplete', 'confirm', 'dispatch',
-    'dispatch_command', 'set_default_command', 'wrap_errors'
+    'dispatch_command', 'dispatch_commands', 'set_default_command',
+    'wrap_errors'
 ]
 
 
         def foo():
             return 1
 
-        parser = ArgumentParser()
-        set_default_command(parser, foo)
-        dispatch(parser)
+        parser = ArghParser()
+        parser.set_default_command(foo)
+        parser.dispatch()
 
     This function can also be used as a decorator. Here's a more or less
     sensible example::
             return args.name
 
     """
-    parser = argparse.ArgumentParser()
-    set_default_command(parser, function)
-    dispatch(parser, *args, **kwargs)
+    parser = ArghParser()
+    parser.set_default_command(function)
+    parser.dispatch(*args, **kwargs)
+
+
+def dispatch_commands(functions, *args, **kwargs):
+    """ A wrapper for :func:`dispatch` that creates a parser, adds commands to
+    the parser and dispatches them.
+
+    This::
+
+        @command
+        def foo():
+            return 1
+
+        def bar(args):
+            return 1
+
+        dispatch_commands([foo, bar])
+
+    ...is a shortcut for::
+
+        @command
+        def foo():
+            return 1
+
+        def bar(args):
+            return 1
+
+        parser = ArgumentParser()
+        parser.add_commands(parser, [foo, bar])
+        parser.dispatch(parser)
+
+    """
+    parser = ArghParser()
+    parser.add_commands(functions)
+    parser.dispatch(*args, **kwargs)
 
 
 def dispatch(parser, argv=None, add_help_command=True, encoding=None,

docs/tutorial.rst

     def load(path, format='json'):
         print loaders[format].load(path)
 
-    p = ArghParser()
-    p.add_commands([load, dump])
-
     if __name__ == '__main__':
-        p.dispatch()
+        dispatch_commands([load, dump])
 
 And then call your script like this::
 
 
 * why the ``@command`` decorator for just one of the two functions?
 * do ``return`` and ``print`` behave equally?
-* what's the difference between ``dispatch_command()`` from one example
-  and the more complex version from another one?
+* what's the difference between ``dispatch_command()``
+  and ``dispatch_commands()``? What's going on under the hood?
 
 Then, you'll want to provide help per command and per argument; to specify
 aliases, data types, namespaces and...
     $ ./prog.py www serve-rest
     $ ./prog.py www serve --port 6060 --noreload
 
+There's also a shortcut :func:`~argh.helpers.dispatch_commands` which isn't as
+flexible as the full version described above but helps reduce the code in many
+cases.  Please refer to the API documentation for details.
+
 Single-command application
 --------------------------
 
 import argh.helpers
 from argh import (
     alias, ArghParser, arg, command, CommandError, dispatch_command,
-    plain_signature, wrap_errors
+    dispatch_commands, plain_signature, wrap_errors
 )
 from argh import completion
 
 
 
 class DispatchCommandTestCase(BaseArghTestCase):
+    "Tests for :func:`argh.helpers.dispatch_command`"
 
     def _dispatch_and_capture(self, func, command_string, **kwargs):
         if isinstance(command_string, string_types):
         self.assert_cmd_returns(main, '--foo 2', b('2\n'))
 
 
+class DispatchCommandsTestCase(BaseArghTestCase):
+    "Tests for :func:`argh.helpers.dispatch_commands`"
+
+    def _dispatch_and_capture(self, funcs, command_string, **kwargs):
+        if isinstance(command_string, string_types):
+            args = command_string.split()
+        else:
+            args = command_string
+
+        io = BytesIO()
+        if 'output_file' not in kwargs:
+            kwargs['output_file'] = io
+
+        result = dispatch_commands(funcs, args, **kwargs)
+
+        if kwargs.get('output_file') is None:
+            return result
+        else:
+            io.seek(0)
+            return io.read()
+
+    def assert_cmd_returns(self, funcs, command_string, expected_result, **kwargs):
+        """Executes given command using given parser and asserts that it prints
+        given value.
+        """
+        try:
+            result = self._dispatch_and_capture(funcs, command_string, **kwargs)
+        except SystemExit as error:
+            self.fail('Argument parsing failed for {0!r}: {1!r}'.format(
+                command_string, error))
+        self.assertEqual(result, expected_result)
+
+    def test_dispatch_commands_shortcut(self):
+
+        @arg('-x', default=1)
+        def foo(args):
+            return args.x
+
+        @arg('-y', default=2)
+        def bar(args):
+            return args.y
+
+        self.assert_cmd_returns([foo, bar], 'foo', b('1\n'))
+        self.assert_cmd_returns([foo, bar], 'foo -x 5', b('5\n'))
+        self.assert_cmd_returns([foo, bar], 'bar', b('2\n'))
+
+
 class ConfirmTestCase(unittest.TestCase):
     def assert_choice(self, choice, expected, **kwargs):
         argh.helpers.raw_input = lambda prompt: choice