From af2a32947710ce591a689c70f999d94e2eddcfcb Mon Sep 17 00:00:00 2001 From: Adrian Sampson Date: Mon, 27 Aug 2012 22:45:28 -0700 Subject: [PATCH] handle user-visible exceptions at top level This makes error messages more friendly (i.e., traceback-free) when exceptions occur during UI setup -- e.g., unopenable database. --- beets/ui/__init__.py | 21 ++++++++++++++++----- test/test_ui.py | 2 +- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/beets/ui/__init__.py b/beets/ui/__init__.py index 0b7cbcae2..d6a29a2e1 100644 --- a/beets/ui/__init__.py +++ b/beets/ui/__init__.py @@ -76,6 +76,9 @@ NULL_REPLACE = '' class UserError(Exception): pass +# Main logger. +log = logging.getLogger('beets') + # Utilities. @@ -674,8 +677,10 @@ class SubcommandsOptionParser(optparse.OptionParser): # The root parser and its main function. -def main(args=None, configfh=None): - """Run the main command-line interface for beets.""" +def _raw_main(args, configfh): + """A helper function for `main` without top-level exception + handling. + """ # Get the default subcommands. from beets.ui.commands import default_commands @@ -750,7 +755,6 @@ def main(args=None, configfh=None): plugins.send("library_opened", lib=lib) # Configure the logger. - log = logging.getLogger('beets') if options.verbose: log.setLevel(logging.DEBUG) else: @@ -760,11 +764,18 @@ def main(args=None, configfh=None): log.debug(u'library directory: %s' % util.displayable_path(lib.directory)) # Invoke the subcommand. + subcommand.func(lib, config, suboptions, subargs) + +def main(args=None, configfh=None): + """Run the main command-line interface for beets. Includes top-level + exception handlers that print friendly error messages. + """ try: - subcommand.func(lib, config, suboptions, subargs) + _raw_main(args, configfh) except UserError as exc: message = exc.args[0] if exc.args else None - subcommand.parser.error(message) + log.error(u'error: {0}'.format(message)) + sys.exit(1) except util.HumanReadableException as exc: exc.log(log) sys.exit(1) diff --git a/test/test_ui.py b/test/test_ui.py index 0d673a30b..98204771b 100644 --- a/test/test_ui.py +++ b/test/test_ui.py @@ -507,7 +507,7 @@ class ConfigTest(unittest.TestCase): commands.default_commands.pop() def _run_main(self, args, config, func): self.test_cmd.func = func - ui.main(args + ['test'], StringIO(config)) + ui._raw_main(args + ['test'], StringIO(config)) def test_paths_section_respected(self): def func(lib, config, opts, args):