1. Robert Kern
  2. kernmagic

Commits

Robert Kern  committed 0402179

ENH: Use IPython's version of magic_arguments

  • Participants
  • Parent commits 8d0443b
  • Branches default

Comments (0)

Files changed (3)

File kernmagic/magic_arguments.py

-""" A decorator-based method of constructing IPython magics with argparse option
-handling.
-"""
-
-import shlex
-
-try:
-    from IPython.external import argparse
-except ImportError:
-    # Fall back onto a third-party installation of argparse.
-    import argparse
-from IPython.core.error import UsageError
-
-
-class MagicArgumentParser(argparse.ArgumentParser):
-    """ An ArgumentParser tweaked for use by IPython magics.
-    """
-    def __init__(self,
-                 prog=None,
-                 usage=None,
-                 description=None,
-                 epilog=None,
-                 version=None,
-                 parents=None,
-                 formatter_class=argparse.HelpFormatter,
-                 prefix_chars='-',
-                 argument_default=None,
-                 conflict_handler='error',
-                 add_help=False):
-        if parents is None:
-            parents = []
-        super(MagicArgumentParser, self).__init__(prog=prog, usage=usage,
-            description=description, epilog=epilog, version=version,
-            parents=parents, formatter_class=formatter_class,
-            prefix_chars=prefix_chars, argument_default=argument_default,
-            conflict_handler=conflict_handler, add_help=add_help)
-
-    def error(self, message):
-        """ Raise a catchable error instead of exiting.
-        """
-        raise UsageError(message)
-
-    def parse_argstring(self, argstring):
-        """ Split a string into an argument list and parse that argument list.
-        """
-        argv = shlex.split(argstring)
-        return self.parse_args(argv)
-
-
-def construct_parser(magic_func):
-    """ Construct an argument parser using the function decorations.
-    """
-    kwds = getattr(magic_func, 'argcmd_kwds', {})
-    if 'description' not in kwds:
-        kwds['description'] = getattr(magic_func, '__doc__', None)
-    arg_name = real_name(magic_func)
-    parser = MagicArgumentParser(arg_name, **kwds)
-    # Reverse the list of decorators in order to apply them in the
-    # order in which they appear in the source.
-    group = None
-    for deco in magic_func.decorators[::-1]:
-        result = deco.add_to_parser(parser, group)
-        if result is not None:
-            group = result
-
-    # Replace the starting 'usage: ' with IPython's %.
-    help_text = parser.format_help()
-    if help_text.startswith('usage: '):
-        help_text = help_text.replace('usage: ', '%', 1)
-    else:
-        help_text = '%' + help_text
-
-    # Replace the magic function's docstring with the full help text.
-    magic_func.__doc__ = help_text
-
-    return parser
-
-
-def parse_argstring(magic_func, argstring):
-    """ Parse the string of arguments for the given magic function.
-    """
-    args = magic_func.parser.parse_argstring(argstring)
-    return args
-
-
-def real_name(magic_func):
-    """ Find the real name of the magic.
-    """
-    magic_name = magic_func.__name__
-    if magic_name.startswith('magic_'):
-        magic_name = magic_name[len('magic_'):]
-    arg_name = getattr(magic_func, 'argcmd_name', magic_name)
-    return arg_name
-
-
-class ArgDecorator(object):
-    """ Base class for decorators to add ArgumentParser information to a method.
-    """
-
-    def __call__(self, func):
-        if not getattr(func, 'has_arguments', False):
-            func.has_arguments = True
-            func.decorators = []
-        func.decorators.append(self)
-        return func
-
-    def add_to_parser(self, parser, group):
-        """ Add this object's information to the parser, if necessary.
-        """
-        pass
-
-
-class magic_arguments(ArgDecorator):
-    """ Mark the magic as having argparse arguments and possibly adjust the
-    name.
-    """
-
-    def __init__(self, name=None):
-        self.name = name
-
-    def __call__(self, func):
-        if not getattr(func, 'has_arguments', False):
-            func.has_arguments = True
-            func.decorators = []
-        if self.name is not None:
-            func.argcmd_name = self.name
-        # This should be the first decorator in the list of decorators, thus the
-        # last to execute. Build the parser.
-        func.parser = construct_parser(func)
-        return func
-
-
-class argument(ArgDecorator):
-    """ Store arguments and keywords to pass to add_argument().
-
-    Instances also serve to decorate command methods.
-    """
-    def __init__(self, *args, **kwds):
-        self.args = args
-        self.kwds = kwds
-
-    def add_to_parser(self, parser, group):
-        """ Add this object's information to the parser.
-        """
-        if group is not None:
-            parser = group
-        parser.add_argument(*self.args, **self.kwds)
-        return None
-
-
-class argument_group(ArgDecorator):
-    """ Store arguments and keywords to pass to add_argument_group().
-
-    Instances also serve to decorate command methods.
-    """
-    def __init__(self, *args, **kwds):
-        self.args = args
-        self.kwds = kwds
-
-    def add_to_parser(self, parser, group):
-        """ Add this object's information to the parser.
-        """
-        group = parser.add_argument_group(*self.args, **self.kwds)
-        return group
-
-
-class kwds(ArgDecorator):
-    """ Provide other keywords to the sub-parser constructor.
-    """
-    def __init__(self, **kwds):
-        self.kwds = kwds
-
-    def __call__(self, func):
-        func = super(kwds, self).__call__(func)
-        func.argcmd_kwds = self.kwds
-        return func
-
-
-__all__ = ['magic_arguments', 'argument', 'argument_group', 'kwds',
-    'parse_argstring']

File kernmagic/mymagics.py

View file
 from IPython.lib import demo
 from IPython.core.error import UsageError
 from IPython.utils import io
+from IPython.core.magic_arguments import argument, magic_arguments, parse_argstring
 
-from .magic_arguments import argument, magic_arguments, parse_argstring
 from . import utils
 
 

File kernmagic/tests/test_magic_arguments.py

-from nose.tools import assert_equal, assert_true
-
-from IPython.external import argparse
-
-from kernmagic.magic_arguments import (argument, argument_group, kwds, magic_arguments, 
-    parse_argstring, real_name)
-
-
-@magic_arguments()
-@argument('-f', '--foo', help="an argument")
-def magic_foo1(self, args):
-    """ A docstring.
-    """
-    return parse_argstring(magic_foo1, args)
-
-@magic_arguments()
-def magic_foo2(self, args):
-    """ A docstring.
-    """
-    return parse_argstring(magic_foo2, args)
-
-@magic_arguments()
-@argument('-f', '--foo', help="an argument")
-@argument_group('Group')
-@argument('-b', '--bar', help="a grouped argument")
-@argument_group('Second Group')
-@argument('-z', '--baz', help="another grouped argument")
-def magic_foo3(self, args):
-    """ A docstring.
-    """
-    return parse_argstring(magic_foo3, args)
-
-@magic_arguments()
-@kwds(argument_default=argparse.SUPPRESS)
-@argument('-f', '--foo', help="an argument")
-def magic_foo4(self, args):
-    """ A docstring.
-    """
-    return parse_argstring(magic_foo4, args)
-
-@magic_arguments('frobnicate')
-@argument('-f', '--foo', help="an argument")
-def magic_foo5(self, args):
-    """ A docstring.
-    """
-    return parse_argstring(magic_foo5, args)
-
-@magic_arguments()
-@argument('-f', '--foo', help="an argument")
-def magic_magic_foo(self, args):
-    """ A docstring.
-    """
-    return parse_argstring(magic_magic_foo, args)
-
-@magic_arguments()
-@argument('-f', '--foo', help="an argument")
-def foo(self, args):
-    """ A docstring.
-    """
-    return parse_argstring(foo, args)
-
-def test_magic_arguments():
-    # Ideally, these would be doctests, but I could not get it to work.
-    yield assert_equal, magic_foo1.__doc__, '%foo1 [-f FOO]\n\nA docstring.\n\noptional arguments:\n  -f FOO, --foo FOO  an argument\n'
-    yield assert_equal, getattr(magic_foo1, 'argcmd_name', None), None
-    yield assert_equal, real_name(magic_foo1), 'foo1'
-    yield assert_equal, magic_foo1(None, ''), argparse.Namespace(foo=None)
-    yield assert_true, hasattr(magic_foo1, 'has_arguments')
-
-    yield assert_equal, magic_foo2.__doc__, '%foo2\n\nA docstring.\n'
-    yield assert_equal, getattr(magic_foo2, 'argcmd_name', None), None
-    yield assert_equal, real_name(magic_foo2), 'foo2'
-    yield assert_equal, magic_foo2(None, ''), argparse.Namespace()
-    yield assert_true, hasattr(magic_foo2, 'has_arguments')
-
-    yield assert_equal, magic_foo3.__doc__, '%foo3 [-f FOO] [-b BAR] [-z BAZ]\n\nA docstring.\n\noptional arguments:\n  -f FOO, --foo FOO  an argument\n\nGroup:\n  -b BAR, --bar BAR  a grouped argument\n\nSecond Group:\n  -z BAZ, --baz BAZ  another grouped argument\n'
-    yield assert_equal, getattr(magic_foo3, 'argcmd_name', None), None
-    yield assert_equal, real_name(magic_foo3), 'foo3'
-    yield assert_equal, magic_foo3(None, ''), argparse.Namespace(bar=None, baz=None, foo=None)
-    yield assert_true, hasattr(magic_foo3, 'has_arguments')
-
-    yield assert_equal, magic_foo4.__doc__, '%foo4 [-f FOO]\n\nA docstring.\n\noptional arguments:\n  -f FOO, --foo FOO  an argument\n'
-    yield assert_equal, getattr(magic_foo4, 'argcmd_name', None), None
-    yield assert_equal, real_name(magic_foo4), 'foo4'
-    yield assert_equal, magic_foo4(None, ''), argparse.Namespace()
-    yield assert_true, hasattr(magic_foo4, 'has_arguments')
-
-    yield assert_equal, magic_foo5.__doc__, '%frobnicate [-f FOO]\n\nA docstring.\n\noptional arguments:\n  -f FOO, --foo FOO  an argument\n'
-    yield assert_equal, getattr(magic_foo5, 'argcmd_name', None), 'frobnicate'
-    yield assert_equal, real_name(magic_foo5), 'frobnicate'
-    yield assert_equal, magic_foo5(None, ''), argparse.Namespace(foo=None)
-    yield assert_true, hasattr(magic_foo5, 'has_arguments')
-
-    yield assert_equal, magic_magic_foo.__doc__, '%magic_foo [-f FOO]\n\nA docstring.\n\noptional arguments:\n  -f FOO, --foo FOO  an argument\n'
-    yield assert_equal, getattr(magic_magic_foo, 'argcmd_name', None), None
-    yield assert_equal, real_name(magic_magic_foo), 'magic_foo'
-    yield assert_equal, magic_magic_foo(None, ''), argparse.Namespace(foo=None)
-    yield assert_true, hasattr(magic_magic_foo, 'has_arguments')
-
-    yield assert_equal, foo.__doc__, '%foo [-f FOO]\n\nA docstring.\n\noptional arguments:\n  -f FOO, --foo FOO  an argument\n'
-    yield assert_equal, getattr(foo, 'argcmd_name', None), None
-    yield assert_equal, real_name(foo), 'foo'
-    yield assert_equal, foo(None, ''), argparse.Namespace(foo=None)
-    yield assert_true, hasattr(foo, 'has_arguments')
-
-