Improved error handling in the command system
This commit is contained in:
parent
ae0f32d922
commit
981572f79d
|
@ -25,6 +25,20 @@ from inspect import getargspec
|
||||||
class CommandInternalError(Exception):
|
class CommandInternalError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class CommandError(Exception):
|
||||||
|
def __init__(self, message=None, command=None, name=None):
|
||||||
|
if command:
|
||||||
|
self.command = command
|
||||||
|
self.name = command.first_name
|
||||||
|
elif name:
|
||||||
|
self.command = None
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
if message:
|
||||||
|
super(CommandError, self).__init__(message)
|
||||||
|
else:
|
||||||
|
super(CommandError, self).__init__()
|
||||||
|
|
||||||
class Command(object):
|
class Command(object):
|
||||||
|
|
||||||
DOC_STRIP_PATTERN = re.compile(r'(?:^[ \t]+|\A\n)', re.MULTILINE)
|
DOC_STRIP_PATTERN = re.compile(r'(?:^[ \t]+|\A\n)', re.MULTILINE)
|
||||||
|
@ -43,7 +57,13 @@ class Command(object):
|
||||||
self.empty = empty
|
self.empty = empty
|
||||||
|
|
||||||
def __call__(self, *args, **kwargs):
|
def __call__(self, *args, **kwargs):
|
||||||
return self.handler(*args, **kwargs)
|
try:
|
||||||
|
return self.handler(*args, **kwargs)
|
||||||
|
except CommandError, exception:
|
||||||
|
if not exception.command and not exception.name:
|
||||||
|
raise CommandError(exception.message, self)
|
||||||
|
except TypeError:
|
||||||
|
raise CommandError("Command received invalid arguments", self)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Command %s>" % ', '.join(self.names)
|
return "<Command %s>" % ', '.join(self.names)
|
||||||
|
@ -56,7 +76,7 @@ class Command(object):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def first_name(self):
|
def first_name(self):
|
||||||
return self.names[0]
|
return self.names[0]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def native_name(self):
|
def native_name(self):
|
||||||
|
@ -162,14 +182,6 @@ class Command(object):
|
||||||
|
|
||||||
return usage if not complete else self.ARG_USAGE_PATTERN % (names, usage)
|
return usage if not complete else self.ARG_USAGE_PATTERN % (names, usage)
|
||||||
|
|
||||||
class CommandError(Exception):
|
|
||||||
def __init__(self, command, *args, **kwargs):
|
|
||||||
if isinstance(command, Command):
|
|
||||||
self.command = command
|
|
||||||
self.name = command.first_name
|
|
||||||
self.name = command
|
|
||||||
super(Exception, self).__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
class Dispatcher(type):
|
class Dispatcher(type):
|
||||||
table = {}
|
table = {}
|
||||||
hosted = {}
|
hosted = {}
|
||||||
|
@ -180,7 +192,7 @@ class Dispatcher(type):
|
||||||
|
|
||||||
if Dispatcher.is_suitable(cls, dct):
|
if Dispatcher.is_suitable(cls, dct):
|
||||||
Dispatcher.register_processor(cls)
|
Dispatcher.register_processor(cls)
|
||||||
|
|
||||||
# Sanitize names even if processor is not suitable for registering,
|
# Sanitize names even if processor is not suitable for registering,
|
||||||
# because it might be inherited by an another processor.
|
# because it might be inherited by an another processor.
|
||||||
Dispatcher.sanitize_names(cls)
|
Dispatcher.sanitize_names(cls)
|
||||||
|
@ -226,7 +238,7 @@ class Dispatcher(type):
|
||||||
|
|
||||||
if 'HOSTED_BY' in proc.__dict__:
|
if 'HOSTED_BY' in proc.__dict__:
|
||||||
cls.register_adhocs(proc)
|
cls.register_adhocs(proc)
|
||||||
|
|
||||||
commands = cls.traverse_commands(proc, inherited)
|
commands = cls.traverse_commands(proc, inherited)
|
||||||
cls.register_commands(proc, commands)
|
cls.register_commands(proc, commands)
|
||||||
|
|
||||||
|
@ -362,7 +374,7 @@ class CommandProcessor(object):
|
||||||
name = cls.prepare_name(name)
|
name = cls.prepare_name(name)
|
||||||
command = Dispatcher.retrieve_command(cls, name)
|
command = Dispatcher.retrieve_command(cls, name)
|
||||||
if not command:
|
if not command:
|
||||||
raise CommandError(name, "Command does not exist")
|
raise CommandError("Command does not exist", name=name)
|
||||||
return command
|
return command
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -446,7 +458,7 @@ class CommandProcessor(object):
|
||||||
if len(spec_args) == 1:
|
if len(spec_args) == 1:
|
||||||
if arguments or command.empty:
|
if arguments or command.empty:
|
||||||
return (arguments,), {}
|
return (arguments,), {}
|
||||||
raise CommandError(command, "Can not be used without arguments")
|
raise CommandError("Can not be used without arguments", command)
|
||||||
raise CommandInternalError("Raw command must define no more then one argument")
|
raise CommandInternalError("Raw command must define no more then one argument")
|
||||||
|
|
||||||
if '__optional__' in spec_args:
|
if '__optional__' in spec_args:
|
||||||
|
@ -520,13 +532,10 @@ class CommandProcessor(object):
|
||||||
args, kwargs = self.parse_command_arguments(arguments) if arguments else ([], {})
|
args, kwargs = self.parse_command_arguments(arguments) if arguments else ([], {})
|
||||||
args, kwargs = self.adapt_command_arguments(command, arguments, args, kwargs)
|
args, kwargs = self.adapt_command_arguments(command, arguments, args, kwargs)
|
||||||
|
|
||||||
try:
|
if self.command_preprocessor(name, command, arguments, args, kwargs):
|
||||||
if self.command_preprocessor(name, command, arguments, args, kwargs):
|
return
|
||||||
return
|
value = command(self, *args, **kwargs)
|
||||||
value = command(self, *args, **kwargs)
|
self.command_postprocessor(name, command, arguments, args, kwargs, value)
|
||||||
self.command_postprocessor(name, command, arguments, args, kwargs, value)
|
|
||||||
except TypeError:
|
|
||||||
raise CommandError(name, "Command received invalid arguments")
|
|
||||||
|
|
||||||
def command_preprocessor(self, name, command, arguments, args, kwargs):
|
def command_preprocessor(self, name, command, arguments, args, kwargs):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -100,7 +100,7 @@ class ChatCommands(CommonCommands):
|
||||||
Send a ping to the contact
|
Send a ping to the contact
|
||||||
"""
|
"""
|
||||||
if self.account == gajim.ZEROCONF_ACC_NAME:
|
if self.account == gajim.ZEROCONF_ACC_NAME:
|
||||||
raise CommandError(ping, _('Command is not supported for zeroconf accounts'))
|
raise CommandError(_('Command is not supported for zeroconf accounts'))
|
||||||
gajim.connections[self.account].sendPing(self.contact)
|
gajim.connections[self.account].sendPing(self.contact)
|
||||||
|
|
||||||
class PrivateChatCommands(CommonCommands):
|
class PrivateChatCommands(CommonCommands):
|
||||||
|
|
Loading…
Reference in New Issue