--- a/opster.py Tue Sep 15 13:56:35 2009 -0700
+++ b/opster.py Tue Sep 15 17:22:19 2009 -0700
@@ -6,7 +6,7 @@
from itertools import imap
__all__ = ['command', 'dispatch']
-__version__ = '0.9.8'
+__version__ = '0.9.9'
__author__ = 'Alexander Solovyov'
__email__ = 'piranha@piranha.org.ua'
@@ -37,15 +37,20 @@
with multiple subcommands, overrides ``shortlist``
'''
def wrapper(func):
- # copy option list
try:
- options_ = list(options or guess_options(func))
+ options_ = list(guess_options(func))
+ except TypeError:
+ options_ = []
+ try:
+ options_ = options_ + list(options)
except TypeError:
- # no options supplied and no options present in func
- options_ = []
+ pass
- name_ = name or func.__name__
- usage_ = usage or guess_usage(func, options_)
+ name_ = name or func.__name__.replace('_', '-')
+ if usage is None:
+ usage_ = guess_usage(func, options_)
+ else:
+ usage_ = usage
prefix = hide and '~' or (shortlist and '^' or '')
CMDTABLE[prefix + name_] = (func, options_, usage_)
@@ -53,7 +58,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_)
@@ -61,16 +66,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('argv', 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, options_)(*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):
@@ -316,10 +326,9 @@
# --------
def _dispatch(args, cmdtable, globalopts):
- cmd, func, args, options, globaloptions = cmdparse(args, cmdtable,
- globalopts)
+ cmd, func, args, options = cmdparse(args, cmdtable, globalopts)
- if globaloptions['help']:
+ if options.pop('help', False):
return 'help', cmdtable['help'][0], [cmd], {}
elif not cmd:
return 'help', cmdtable['help'][0], ['shortlist'], {}
@@ -350,12 +359,7 @@
except getopt.GetoptError, e:
raise ParseError(cmd, e)
- globaloptions = {}
- for o in globalopts:
- name = o[1]
- globaloptions[name] = options.pop(name)
-
- return (cmd, cmd and info[0] or None, args, options, globaloptions)
+ return (cmd, cmd and info[0] or None, args, options)
def findpossible(cmd, table):
"""
@@ -401,8 +405,12 @@
def guess_options(func):
args, varargs, varkw, defaults = inspect.getargspec(func)
- for lname, (sname, default, hlp) in zip(args[-len(defaults):], defaults):
- yield (sname, lname.replace('_', '-'), default, hlp)
+ for name, option in zip(args[-len(defaults):], defaults):
+ try:
+ sname, default, hlp = option
+ yield (sname, name.replace('_', '-'), default, hlp)
+ except TypeError:
+ pass
def guess_usage(func, options):
usage = '%name '
@@ -419,6 +427,8 @@
return usage
def catcher(target, help_func):
+ '''Catches all exceptions and prints human-readable information on them
+ '''
try:
return target()
except UnknownCommand, e:
@@ -454,6 +464,21 @@
raise
return inner
+def call_cmd_regular(func, opts):
+ def inner(*args, **kwargs):
+ funcargs, _, varkw, defaults = inspect.getargspec(func)
+ if len(args) > len(funcargs):
+ raise TypeError('You have supplied more positional arguments'
+ ' than applicable')
+
+ funckwargs = dict((lname.replace('-', '_'), default)
+ for _, lname, default, _ in opts)
+ if 'help' not in (defaults or ()) and not varkw:
+ funckwargs.pop('help', None)
+ funckwargs.update(kwargs)
+ return func(*args, **funckwargs)
+ return inner
+
def replace_name(usage, name):
if '%name' in usage:
return usage.replace('%name', name, 1)