command: Cleanup

This commit is contained in:
Florian Bruhin 2014-09-15 08:16:19 +02:00
parent 8a51aa759e
commit 34b0cf429c

View File

@ -83,6 +83,8 @@ class Command:
help=argparser.SUPPRESS) help=argparser.SUPPRESS)
self._check_func() self._check_func()
self.opt_args = collections.OrderedDict() self.opt_args = collections.OrderedDict()
self.namespace = None
self.count = None
self.pos_args = [] self.pos_args = []
has_count, desc, type_conv, name_conv = self._inspect_func() has_count, desc, type_conv, name_conv = self._inspect_func()
self.has_count = has_count self.has_count = has_count
@ -291,26 +293,13 @@ class Command:
else: else:
return type(param.default) return type(param.default)
def _get_call_args(self, func, # noqa, pylint: disable=too-many-branches def _get_self_arg(self, param, args):
count, namespace): """Get the self argument for a function call.
"""Get arguments for a function call.
Args: Arguments:
func: The function to be called. param: The count parameter.
count: The count to be added to the call. args: The positional argument list. Gets modified directly.
namespace: The argparse namespace.
Return:
An (args, kwargs) tuple.
""" """
args = []
kwargs = {}
signature = inspect.signature(func)
for i, param in enumerate(signature.parameters.values()):
if i == 0 and self.instance is not None:
# Special case for 'self'.
assert param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD assert param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD
app = QCoreApplication.instance() app = QCoreApplication.instance()
if self.instance == '': if self.instance == '':
@ -318,34 +307,63 @@ class Command:
else: else:
obj = utils.dotted_getattr(app, self.instance) obj = utils.dotted_getattr(app, self.instance)
args.append(obj) args.append(obj)
continue
elif param.name == 'count': def _get_count_arg(self, param, args, kwargs):
# Special case for 'count'. """Add the count argument to a function call.
Arguments:
param: The count parameter.
args: The positional argument list. Gets modified directly.
kwargs: The keyword argument dict. Gets modified directly.
"""
if not self.has_count: if not self.has_count:
raise TypeError("{}: count argument given with a command " raise TypeError("{}: count argument given with a command which "
"which does not support count!".format( "does not support count!".format(self.name))
self.name))
if param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD: if param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD:
if count is not None: if self.count is not None:
args.append(count) args.append(self.count)
else: else:
args.append(param.default) args.append(param.default)
elif param.kind == inspect.Parameter.KEYWORD_ONLY: elif param.kind == inspect.Parameter.KEYWORD_ONLY:
if count is not None: if self.count is not None:
kwargs['count'] = count kwargs['count'] = self.count
else: else:
raise TypeError("{}: invalid parameter type {} for " raise TypeError("{}: invalid parameter type {} for argument "
"argument 'count'!".format( "'count'!".format(self.name, param.kind))
self.name, param.kind))
continue def _get_param_name_and_value(self, param):
"""Get the converted name and value for an inspect.Parameter."""
name = self.name_conv.get(param.name, param.name) name = self.name_conv.get(param.name, param.name)
value = getattr(namespace, name) value = getattr(self.namespace, name)
if param.name in self.type_conv: if param.name in self.type_conv:
# We convert enum types after getting the values from # We convert enum types after getting the values from
# argparse, because argparse's choices argument is # argparse, because argparse's choices argument is
# processed after type conversation, which is not what we # processed after type conversation, which is not what we
# want. # want.
value = self.type_conv[param.name](value) value = self.type_conv[param.name](value)
return name, value
def _get_call_args(self):
"""Get arguments for a function call.
Return:
An (args, kwargs) tuple.
"""
args = []
kwargs = {}
signature = inspect.signature(self.handler)
for i, param in enumerate(signature.parameters.values()):
if i == 0 and self.instance is not None:
# Special case for 'self'.
self._get_self_arg(param, args)
continue
elif param.name == 'count':
# Special case for 'count'.
self._get_count_arg(param, args, kwargs)
continue
name, value = self._get_param_name_and_value(param)
if param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD: if param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD:
args.append(value) args.append(value)
elif param.kind == inspect.Parameter.VAR_POSITIONAL: elif param.kind == inspect.Parameter.VAR_POSITIONAL:
@ -375,7 +393,7 @@ class Command:
dbgout.append("(count={})".format(count)) dbgout.append("(count={})".format(count))
log.commands.debug(' '.join(dbgout)) log.commands.debug(' '.join(dbgout))
try: try:
namespace = self.parser.parse_args(args) self.namespace = self.parser.parse_args(args)
except argparser.ArgumentParserError as e: except argparser.ArgumentParserError as e:
message.error('{}: {}'.format(self.name, e)) message.error('{}: {}'.format(self.name, e))
return return
@ -383,7 +401,8 @@ class Command:
log.commands.debug("argparser exited with status {}: {}".format( log.commands.debug("argparser exited with status {}: {}".format(
e.status, e)) e.status, e))
return return
posargs, kwargs = self._get_call_args(self.handler, count, namespace) self.count = count
posargs, kwargs = self._get_call_args()
self._check_prerequisites() self._check_prerequisites()
log.commands.debug('Calling {}'.format( log.commands.debug('Calling {}'.format(
debug.format_call(self.handler, posargs, kwargs))) debug.format_call(self.handler, posargs, kwargs)))