##// END OF EJS Templates
s/write_prompt/draw_prompt
s/write_prompt/draw_prompt

File last commit:

r12547:45e2dad1
r12687:10f331d2
Show More
magic_arguments.py
246 lines | 7.4 KiB | text/x-python | PythonLexer
/ IPython / core / magic_arguments.py
Robert Kern
ENH: Add the argparse-based option parsing for magics.
r3229 ''' A decorator-based method of constructing IPython magics with `argparse`
option handling.
New magic functions can be defined like so::
from IPython.core.magic_arguments import (argument, magic_arguments,
parse_argstring)
@magic_arguments()
@argument('-o', '--option', help='An optional argument.')
@argument('arg', type=int, help='An integer positional argument.')
def magic_cool(self, arg):
""" A really cool magic command.
"""
args = parse_argstring(magic_cool, arg)
...
The `@magic_arguments` decorator marks the function as having argparse arguments.
The `@argument` decorator adds an argument using the same syntax as argparse's
`add_argument()` method. More sophisticated uses may also require the
`@argument_group` or `@kwds` decorator to customize the formatting and the
parsing.
Help text for the magic is automatically generated from the docstring and the
arguments::
In[1]: %cool?
%cool [-o OPTION] arg
A really cool magic command.
positional arguments:
arg An integer positional argument.
optional arguments:
-o OPTION, --option OPTION
An optional argument.
Thomas Kluyver
Only include inheritance diagram where it's useful.
r8795 Inheritance diagram:
.. inheritance-diagram:: IPython.core.magic_arguments
:parts: 3
Robert Kern
ENH: Add the argparse-based option parsing for magics.
r3229 '''
#-----------------------------------------------------------------------------
Matthias BUSSONNIER
update copyright to 2011/20xx-2011...
r5390 # Copyright (C) 2010-2011, IPython Development Team.
Robert Kern
ENH: Add the argparse-based option parsing for magics.
r3229 #
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------
Thomas Kluyver
Import argparse directly from stdlib
r12547 import argparse
Robert Kern
ENH: Add the argparse-based option parsing for magics.
r3229
# Our own imports
from IPython.core.error import UsageError
Robert Kern
BUG: Use arg_split instead of shlex.split
r3292 from IPython.utils.process import arg_split
Bradley M. Froehle
magic_arguments: dedent but otherwise preserve indentation....
r7490 from IPython.utils.text import dedent
Robert Kern
ENH: Add the argparse-based option parsing for magics.
r3229
Bradley M. Froehle
magic_arguments: dedent but otherwise preserve indentation....
r7490 class MagicHelpFormatter(argparse.RawDescriptionHelpFormatter):
""" A HelpFormatter which dedents but otherwise preserves indentation.
"""
def _fill_text(self, text, width, indent):
return argparse.RawDescriptionHelpFormatter._fill_text(self, dedent(text), width, indent)
Robert Kern
ENH: Add the argparse-based option parsing for magics.
r3229
class MagicArgumentParser(argparse.ArgumentParser):
""" An ArgumentParser tweaked for use by IPython magics.
"""
def __init__(self,
prog=None,
usage=None,
description=None,
epilog=None,
parents=None,
Bradley M. Froehle
magic_arguments: dedent but otherwise preserve indentation....
r7490 formatter_class=MagicHelpFormatter,
Robert Kern
ENH: Add the argparse-based option parsing for magics.
r3229 prefix_chars='-',
argument_default=None,
conflict_handler='error',
add_help=False):
if parents is None:
parents = []
super(MagicArgumentParser, self).__init__(prog=prog, usage=usage,
Andrew Spiers
Update IPython/core/magic_arguments.py...
r8295 description=description, epilog=epilog,
Robert Kern
ENH: Add the argparse-based option parsing for magics.
r3229 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.
"""
Robert Kern
BUG: Use arg_split instead of shlex.split
r3292 argv = arg_split(argstring)
Robert Kern
ENH: Add the argparse-based option parsing for magics.
r3229 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.
"""
Fernando Perez
Simplify return form of some functions - avoid unnecessary variables.
r3431 return magic_func.parser.parse_argstring(argstring)
Robert Kern
ENH: Add the argparse-based option parsing for magics.
r3229
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_'):]
Fernando Perez
Simplify return form of some functions - avoid unnecessary variables.
r3431 return getattr(magic_func, 'argcmd_name', magic_name)
Robert Kern
ENH: Add the argparse-based option parsing for magics.
r3229
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
Takafumi Arakaki
Refactor magic_arguments.py
r8427 class ArgMethodWrapper(ArgDecorator):
Robert Kern
ENH: Add the argparse-based option parsing for magics.
r3229
"""
Takafumi Arakaki
Refactor magic_arguments.py
r8427 Base class to define a wrapper for ArgumentParser method.
Child class must define either `_method_name` or `add_to_parser`.
"""
_method_name = None
Robert Kern
ENH: Add the argparse-based option parsing for magics.
r3229 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
Takafumi Arakaki
Refactor magic_arguments.py
r8427 getattr(parser, self._method_name)(*self.args, **self.kwds)
Robert Kern
ENH: Add the argparse-based option parsing for magics.
r3229 return None
Takafumi Arakaki
Refactor magic_arguments.py
r8427 class argument(ArgMethodWrapper):
""" Store arguments and keywords to pass to add_argument().
Takafumi Arakaki
Add new decorator magic_arguments.defaults
r8426
Instances also serve to decorate command methods.
"""
Takafumi Arakaki
Refactor magic_arguments.py
r8427 _method_name = 'add_argument'
Takafumi Arakaki
Add new decorator magic_arguments.defaults
r8426
Takafumi Arakaki
Refactor magic_arguments.py
r8427 class defaults(ArgMethodWrapper):
""" Store arguments and keywords to pass to set_defaults().
Takafumi Arakaki
Add new decorator magic_arguments.defaults
r8426
Takafumi Arakaki
Refactor magic_arguments.py
r8427 Instances also serve to decorate command methods.
"""
_method_name = 'set_defaults'
class argument_group(ArgMethodWrapper):
Robert Kern
ENH: Add the argparse-based option parsing for magics.
r3229 """ Store arguments and keywords to pass to add_argument_group().
Instances also serve to decorate command methods.
"""
def add_to_parser(self, parser, group):
""" Add this object's information to the parser.
"""
Fernando Perez
Simplify return form of some functions - avoid unnecessary variables.
r3431 return parser.add_argument_group(*self.args, **self.kwds)
Robert Kern
ENH: Add the argparse-based option parsing for magics.
r3229
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']