when calling command from python set not supplied options to proper defaults
authorAlexander Solovyov <piranha@piranha.org.ua>
Sun, 06 Sep 2009 16:32:32 +0300
changeset 87 ec9736668bca
parent 86 10399ada69e6
child 88 dbea34bde1f7
when calling command from python set not supplied options to proper defaults Earlier you would get full option spec (short, default, help) for every option, not supplied as argument (or keyword argument) in function call.
docs/changelog.rst
opster.py
test_cmd.py
--- a/docs/changelog.rst	Sun Sep 06 15:08:49 2009 +0300
+++ b/docs/changelog.rst	Sun Sep 06 16:32:32 2009 +0300
@@ -3,9 +3,11 @@
 
 0.9.9
 ~~~~~
- - globaloptions were simply dropped after parsing, fold them in regular options
- - replace _ with - in command names, same as in options names
- - respect empty strings as usage
+ - Now it's possible to call commands as regular function, where every
+   non-supplied option will receive proper default (defined in option spec)
+ - Globaloptions were simply dropped after parsing, fold them in regular options
+ - Replace _ with - in command names, same as in options names
+ - Respect empty strings as usage
 
 0.9.8
 ~~~~~
--- a/opster.py	Sun Sep 06 15:08:49 2009 +0300
+++ b/opster.py	Sun Sep 06 16:32:32 2009 +0300
@@ -56,7 +56,7 @@
             return help_cmd(func, replace_name(usage_, sysname()), options_)
 
         @wraps(func)
-        def inner(*arguments, **kwarguments):
+        def inner(*args, **opts):
             # look if we need to add 'help' option
             try:
                 (True for option in reversed(options_)
@@ -64,16 +64,21 @@
             except StopIteration:
                 options_.append(('h', 'help', False, 'show help'))
 
-            args = kwarguments.pop('args', None)
-            if arguments or kwarguments:
-                args, opts = arguments, kwarguments
-            else:
-                args = args or sys.argv[1:]
-                try:
-                    opts, args = catcher(lambda: parse(args, options_),
-                                         help_func)
-                except Abort:
-                    return -1
+            argv = opts.pop('args', None)
+            if opts.pop('help', False):
+                return help_func()
+
+            if args or opts:
+                # no catcher here because this is call from Python
+                return call_cmd_regular(func)(*args, **opts)
+
+            if argv is None:
+                argv = sys.argv[1:]
+
+            try:
+                opts, args = catcher(lambda: parse(argv, options_), help_func)
+            except Abort:
+                return -1
 
             try:
                 if opts.pop('help', False):
@@ -416,6 +421,8 @@
     return usage
 
 def catcher(target, help_func):
+    '''Catches all exceptions and prints human-readable information on them
+    '''
     try:
         return target()
     except UnknownCommand, e:
@@ -451,6 +458,18 @@
             raise
     return inner
 
+def call_cmd_regular(func):
+    def inner(*args, **kwargs):
+        funcargs, varargs, varkw, defaults = inspect.getargspec(func)
+
+        funckwargs = funcargs[len(args):]
+        funckwargs = dict(zip(funckwargs, (default for _, default, _
+                                           in defaults[-len(funckwargs):])))
+        funckwargs.update(kwargs)
+
+        return func(*args, **funckwargs)
+    return inner
+
 def replace_name(usage, name):
     if '%name' in usage:
         return usage.replace('%name', name, 1)
--- a/test_cmd.py	Sun Sep 06 15:08:49 2009 +0300
+++ b/test_cmd.py	Sun Sep 06 16:32:32 2009 +0300
@@ -21,4 +21,5 @@
     print opts
 
 
-opster.dispatch()
+if __name__ == '__main__':
+    opster.dispatch()