commands.cmdutils: Clean up decorator.

This commit is contained in:
Florian Bruhin 2014-09-04 17:59:29 +02:00
parent 03a0a1c599
commit 32e24479b9

View File

@ -135,6 +135,8 @@ class register: # pylint: disable=invalid-name
self.needs_js = needs_js self.needs_js = needs_js
self.debug = debug self.debug = debug
self.ignore_args = ignore_args self.ignore_args = ignore_args
self.parser = None
self.func = None
if modes is not None: if modes is not None:
for m in modes: for m in modes:
if not isinstance(m, usertypes.KeyMode): if not isinstance(m, usertypes.KeyMode):
@ -158,23 +160,25 @@ class register: # pylint: disable=invalid-name
Return: Return:
The original function (unmodified). The original function (unmodified).
""" """
names = self._get_names(func) self.func = func
names = self._get_names()
log.commands.vdebug("Registering command {}".format(names[0])) log.commands.vdebug("Registering command {}".format(names[0]))
for name in names: for name in names:
if name in cmd_dict: if name in cmd_dict:
raise ValueError("{} is already registered!".format(name)) raise ValueError("{} is already registered!".format(name))
has_count, desc, parser, type_conv = self._inspect_func(func) self.parser = argparser.ArgumentParser(names[0])
has_count, desc, type_conv = self._inspect_func()
cmd = command.Command( cmd = command.Command(
name=names[0], split=self.split, hide=self.hide, count=has_count, name=names[0], split=self.split, hide=self.hide, count=has_count,
desc=desc, instance=self.instance, handler=func, desc=desc, instance=self.instance, handler=func,
completion=self.completion, modes=self.modes, completion=self.completion, modes=self.modes,
not_modes=self.not_modes, needs_js=self.needs_js, not_modes=self.not_modes, needs_js=self.needs_js,
is_debug=self.debug, parser=parser, type_conv=type_conv) is_debug=self.debug, parser=self.parser, type_conv=type_conv)
for name in names: for name in names:
cmd_dict[name] = cmd cmd_dict[name] = cmd
return func return func
def _get_names(self, func): def _get_names(self):
"""Get the name(s) which should be used for the current command. """Get the name(s) which should be used for the current command.
If the name hasn't been overridden explicitely, the function name is If the name hasn't been overridden explicitely, the function name is
@ -183,41 +187,33 @@ class register: # pylint: disable=invalid-name
If it has been set, it can either be a string which is If it has been set, it can either be a string which is
used directly, or an iterable. used directly, or an iterable.
Args:
func: The function to get the name for.
Return: Return:
A list of names, with the main name being the first item. A list of names, with the main name being the first item.
""" """
if self.name is None: if self.name is None:
return [func.__name__.lower().replace('_', '-')] return [self.func.__name__.lower().replace('_', '-')]
elif isinstance(self.name, str): elif isinstance(self.name, str):
return [self.name] return [self.name]
else: else:
return self.name return self.name
def _inspect_func(self, func): def _inspect_func(self):
"""Inspect a function to get useful informations from it. """Inspect the function to get useful informations from it.
Args:
func: The function to look at.
Return: Return:
A (has_count, desc, parser, type_conv) tuple. A (has_count, desc, parser, type_conv) tuple.
has_count: Whether the command supports a count. has_count: Whether the command supports a count.
desc: The description of the command. desc: The description of the command.
parser: The ArgumentParser to use when parsing the commandline.
type_conv: A mapping of args to type converter callables. type_conv: A mapping of args to type converter callables.
""" """
type_conv = {} type_conv = {}
signature = inspect.signature(func) signature = inspect.signature(self.func)
if 'self' in signature.parameters and self.instance is None: if 'self' in signature.parameters and self.instance is None:
raise ValueError("{} is a class method, but instance was not " raise ValueError("{} is a class method, but instance was not "
"given!".format(self.name[0])) "given!".format(self.name[0]))
has_count = 'count' in signature.parameters has_count = 'count' in signature.parameters
parser = argparser.ArgumentParser() if self.func.__doc__ is not None:
if func.__doc__ is not None: desc = self.func.__doc__.splitlines()[0].strip()
desc = func.__doc__.splitlines()[0].strip()
else: else:
desc = "" desc = ""
if not self.ignore_args: if not self.ignore_args:
@ -236,12 +232,12 @@ class register: # pylint: disable=invalid-name
type_conv[param.name] = argparser.enum_getter(typ) type_conv[param.name] = argparser.enum_getter(typ)
elif isinstance(typ, tuple): elif isinstance(typ, tuple):
type_conv[param.name] = argparser.multitype_conv(typ) type_conv[param.name] = argparser.multitype_conv(typ)
callsig = debugutils.format_call(parser.add_argument, args, callsig = debugutils.format_call(self.parser.add_argument,
kwargs, full=False) args, kwargs, full=False)
log.commands.vdebug('Adding arg {} of type {} -> {}'.format( log.commands.vdebug('Adding arg {} of type {} -> {}'.format(
param.name, typ, callsig)) param.name, typ, callsig))
parser.add_argument(*args, **kwargs) self.parser.add_argument(*args, **kwargs)
return has_count, desc, parser, type_conv return has_count, desc, type_conv
def _param_to_argparse_pos(self, param, annotation_info): def _param_to_argparse_pos(self, param, annotation_info):
"""Get a list of positional argparse arguments. """Get a list of positional argparse arguments.