import optparse
import inspect


class Magic(object):

    def __init__(self, kernel):
        self.kernel = kernel
        self.evaluate = True
        self.code = ''

    def call_magic(self, mtype, name, code, args):
        self.code = code
        func = getattr(self, mtype + '_' + name)
        args, kwargs = _parse_args(func, args)
        try:
            func(*args, **kwargs)
        except TypeError as error:
            self.kernel.Error(error.message)
            self.kernel.Error(self.get_help(name, mtype))
            # return dummy magic to end processing:
            return Magic(self.kernel)
        return self

    def get_help(self, mtype, name, level=0):
        if hasattr(self, mtype + '_' + name):
            func = getattr(self, mtype + '_' + name)
            if func.__doc__:
                if level == 0:
                    return func.__doc__.lstrip().split("\n", 1)[0]
                else:
                    return func.__doc__.lstrip()
            else:
                return "No help available for magic '%s' for %ss." % (name, mtype)
        else:
            return "No such magic '%s' for %ss." % (name, mtype)

    def get_magics(self, mtype):
        magics = []
        for name in dir(self):
            if name.startswith(mtype + '_'):
                magics.append(name.replace(mtype + '_', ''))
        return magics

    def get_code(self):
        return self.code

    def post_process(self, retval):
        return retval


def option(*args, **kwargs):
    """Return decorator that adds a magic option to a function.
    """
    def decorator(func):
        if not getattr(func, 'has_options', False):
            func.has_options = True
            func.options = []
            func.__doc__ += '\nOptions:\n-------'
        try:
            option = optparse.Option(*args, **kwargs)
        except optparse.OptionError:
            func.__doc__ += '\n' + args[0]
        else:
            func.__doc__ += '\n' + _format_option(option)
            func.options.append(option)
        return func
    return decorator


def _parse_args(func, args):
    """Parse the arguments given to a magic function"""
    if not isinstance(args, list):
        args = args.split()

    if not getattr(func, 'has_options', False):
        kwargs = dict()
    else:
        parser = optparse.OptionParser()
        parser.add_options(func.options)
        value, args = parser.parse_args(args)
        kwargs = value.__dict__

    argspec = inspect.getargspec(func)
    if not argspec.defaults is None:
        valid_kwargs = argspec.args[-len(argspec.defaults):]
        total_args = len(argspec.args) - len(argspec.defaults)
    else:
        valid_kwargs = []
        total_args = len(argspec.args)
    args = args[:total_args]

    for key in kwargs.keys():
        if not key in valid_kwargs:
            del kwargs[key]

    return args, kwargs


def _format_option(option):
    output = ''
    if option._short_opts:
        output = option._short_opts[0] + ' '
    output += option.get_opt_string() + ' '
    output += ' ' * (15 - len(output))
    output += option.help + ' '
    if not option.default == ('NO', 'DEFAULT'):
        output += '[default: %s]' % option.default
    return output

@@ -13,23 +13,8 @@
 rse%0A
-import inspect%0A
 %0A%0Acl
@@ -2454,408 +2454,8 @@
 __%0A%0A
-    argspec = inspect.getargspec(func)%0A    if not argspec.defaults is None:%0A        valid_kwargs = argspec.args%5B-len(argspec.defaults):%5D%0A        total_args = len(argspec.args) - len(argspec.defaults)%0A    else:%0A        valid_kwargs = %5B%5D%0A        total_args = len(argspec.args)%0A    args = args%5B:total_args%5D%0A%0A    for key in kwargs.keys():%0A        if not key in valid_kwargs:%0A            del kwargs%5Bkey%5D%0A%0A
     

Remove getargspec in favor of try/catch