From: W. Trevor King Date: Mon, 2 May 2011 21:48:18 +0000 (-0400) Subject: Revive the UserError/UsageError distinction X-Git-Tag: 1.1.0~197 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=1fcb1dd9114fba59a5d75570b9acc3b87d575821;p=be.git Revive the UserError/UsageError distinction UsageError was removed back in commit bf3d434b244c57556bec979acbc658c30eb58221 Author: W. Trevor King Date: Sat Dec 12 00:31:55 2009 -0500 Added libbe.command.base (with Command class)... because the distinction between UsageError and UserError was unclear. I've brought it back to satisfy a request by Christian Heinrich: On Sun, May 01, 2011 at 02:52:13AM +0200, Christian Heinrich wrote: > 3.) Using wrong syntax should receive better help messages. > > Current: > > "be new" -> ERROR: > Missing required argument SUMMARY > > Should be: > > "be new" -> usage: be new [options] SUMMARY > ... He suggested we print the full option list as well, but I've decided to just print the usage summary and remind the user how to get the full help message if they want it. --- diff --git a/libbe/command/__init__.py b/libbe/command/__init__.py index 1cad096..832218c 100644 --- a/libbe/command/__init__.py +++ b/libbe/command/__init__.py @@ -19,6 +19,7 @@ import base UserError = base.UserError +UsageError = base.UsageError UnknownCommand = base.UnknownCommand get_command = base.get_command get_command_class = base.get_command_class @@ -33,7 +34,7 @@ UnconnectedStorageGetter = base.UnconnectedStorageGetter StorageCallbacks = base.StorageCallbacks UserInterface = base.UserInterface -__all__ = [UserError, UnknownCommand, +__all__ = [UserError, UsageError, UnknownCommand, get_command, get_command_class, commands, Option, Argument, Command, InputOutput, StdInputOutput, StringInputOutput, diff --git a/libbe/command/base.py b/libbe/command/base.py index b5f5a22..48bb7ab 100644 --- a/libbe/command/base.py +++ b/libbe/command/base.py @@ -27,13 +27,36 @@ import libbe.ui.util.user import libbe.util.encoding import libbe.util.plugin -class UserError(Exception): + +class UserError (Exception): + "An error due to improper BE usage." pass -class UnknownCommand(UserError): - def __init__(self, cmd): - Exception.__init__(self, "Unknown command '%s'" % cmd) - self.cmd = cmd + +class UsageError (UserError): + """A serious parsing error due to invalid BE command construction. + + The distinction between `UserError`\s and the more specific + `UsageError`\s is that when displaying a `UsageError` to the user, + the user is pointed towards the command usage information. Use + the more general `UserError` if you feel that usage information + would not be particularly enlightening. + """ + def __init__(self, command=None, command_name=None, message=None): + super(UsageError, self).__init__(message) + self.command = command + if command_name is None and command is not None: + command_name = command.name + self.command_name = command_name + self.message = message + + +class UnknownCommand (UsageError): + def __init__(self, command_name): + super(UnknownCommand, self).__init__( + command_name=command_name, + message="Unknown command '%s'" % command_name) + def get_command(command_name): """Retrieves the module for a user command diff --git a/libbe/ui/command_line.py b/libbe/ui/command_line.py index 52daa4b..3f70962 100644 --- a/libbe/ui/command_line.py +++ b/libbe/ui/command_line.py @@ -137,8 +137,9 @@ class CmdOptionParser(optparse.OptionParser): raise libbe.command.UserError('Too many arguments') for arg in self.command.args[len(parsed_args):]: if arg.optional == False: - raise libbe.command.UserError( - 'Missing required argument %s' % arg.metavar) + raise libbe.command.UsageError( + command=self.command, + message='Missing required argument %s' % arg.metavar) return (options, parsed_args) def callback(self, option, opt, value, parser): @@ -289,6 +290,13 @@ def dispatch(ui, command, args): 'See http://docs.python.org/library/locale.html for details', ]) return 1 + except libbe.command.UsageError, e: + print >> ui.io.stdout, 'Usage Error:\n', e + if e.command: + print >> ui.io.stdout, e.command.usage() + print >> ui.io.stdout, 'For usage information, try' + print >> ui.io.stdout, ' be help %s' % e.command_name + return 1 except libbe.command.UserError, e: print >> ui.io.stdout, 'ERROR:\n', e return 1 @@ -314,15 +322,19 @@ def main(): options,args = parser.parse_args() except CallbackExit: return 0 - except libbe.command.UserError, e: - if str(e).endswith('COMMAND'): + except libbe.command.UsageError, e: + if isinstance(e.command, BE): # no command given, print usage string - print >> ui.io.stdout, 'ERROR:' - print >> ui.io.stdout, be.usage(), '\n', e + print >> ui.io.stdout, 'Usage Error:\n', e + print >> ui.io.stdout, be.usage() print >> ui.io.stdout, 'For example, try' print >> ui.io.stdout, ' be help' else: - print >> ui.io.stdout, 'ERROR:\n', e + print >> ui.io.stdout, 'Usage Error:\n', e + if e.command: + print >> ui.io.stdout, e.command.usage() + print >> ui.io.stdout, 'For usage information, try' + print >> ui.io.stdout, ' be help %s' % e.command_name return 1 command_name = args.pop(0)