From b12c6297f0b2ed851a4509b8da74ed59501ff0c7 Mon Sep 17 00:00:00 2001 From: Olivier Mangin Date: Sun, 6 Dec 2015 00:27:11 -0500 Subject: [PATCH] Adds exception catching in main command. --- pubs/commands/export_cmd.py | 32 ++++++------- pubs/pubs_cmd.py | 96 ++++++++++++++++++------------------- pubs/repo.py | 27 ++++++++--- pubs/uis.py | 8 ++++ tests/test_repo.py | 4 +- 5 files changed, 93 insertions(+), 74 deletions(-) diff --git a/pubs/commands/export_cmd.py b/pubs/commands/export_cmd.py index 61c5db5..46394c6 100644 --- a/pubs/commands/export_cmd.py +++ b/pubs/commands/export_cmd.py @@ -21,21 +21,17 @@ def command(conf, args): ui = get_ui() rp = repo.Repository(conf) - try: - papers = [] - if len(args.citekeys) < 1: - papers = rp.all_papers() - else: - for key in resolve_citekey_list(repo=rp, citekeys=args.citekeys, ui=ui, exit_on_fail=True): - papers.append(rp.pull_paper(key)) - - bib = {} - for p in papers: - bib[p.citekey] = p.bibdata - - exporter = endecoder.EnDecoder() - bibdata_raw = exporter.encode_bibdata(bib) - ui.message(bibdata_raw) - - except Exception as e: - ui.error(e.message) + papers = [] + if len(args.citekeys) < 1: + papers = rp.all_papers() + else: + for key in resolve_citekey_list(repo=rp, citekeys=args.citekeys, ui=ui, exit_on_fail=True): + papers.append(rp.pull_paper(key)) + + bib = {} + for p in papers: + bib[p.citekey] = p.bibdata + + exporter = endecoder.EnDecoder() + bibdata_raw = exporter.encode_bibdata(bib) + ui.message(bibdata_raw) diff --git a/pubs/pubs_cmd.py b/pubs/pubs_cmd.py index e06edce..1591c21 100644 --- a/pubs/pubs_cmd.py +++ b/pubs/pubs_cmd.py @@ -32,56 +32,56 @@ CORE_CMDS = collections.OrderedDict([ def execute(raw_args=sys.argv): - conf_parser = argparse.ArgumentParser(prog="pubs", add_help=False) - conf_parser.add_argument("-c", "--config", help="path to config file", - type=str, metavar="FILE") - conf_parser.add_argument('--force-colors', dest='force_colors', - action='store_true', default=False, - help='color are not disabled when piping to a file or other commands') - #conf_parser.add_argument("-u", "--update", help="update config if needed", - # default=False, action='store_true') - top_args, remaining_args = conf_parser.parse_known_args(raw_args[1:]) - - if top_args.config: - conf_path = top_args.config - else: - conf_path = config.get_confpath(verify=False) # will be checked on load - - # Loading config - if len(remaining_args) > 0 and remaining_args[0] != 'init': - try: + try: + conf_parser = argparse.ArgumentParser(prog="pubs", add_help=False) + conf_parser.add_argument("-c", "--config", help="path to config file", + type=str, metavar="FILE") + conf_parser.add_argument('--force-colors', dest='force_colors', + action='store_true', default=False, + help='color are not disabled when piping to a file or other commands') + #conf_parser.add_argument("-u", "--update", help="update config if needed", + # default=False, action='store_true') + top_args, remaining_args = conf_parser.parse_known_args(raw_args[1:]) + + if top_args.config: + conf_path = top_args.config + else: + conf_path = config.get_confpath(verify=False) # will be checked on load + + # Loading config + if len(remaining_args) > 0 and remaining_args[0] != 'init': conf = config.load_conf(path=conf_path, check=False) if update.update_check(conf, path=conf.filename): # an update happened, reload conf. conf = config.load_conf(path=conf_path, check=False) config.check_conf(conf) - except IOError as e: - print('error: {}'.format(str(e))) - sys.exit() - else: - conf = config.load_default_conf() - conf.filename = conf_path - - uis.init_ui(conf, force_colors=top_args.force_colors) - ui = uis.get_ui() - - parser = argparse.ArgumentParser(description="research papers repository", - prog="pubs", add_help=True) - parser.add_argument('--version', action='version', version=__version__) - subparsers = parser.add_subparsers(title="valid commands", dest="command") - subparsers.required = True - - # Populate the parser with core commands - for cmd_name, cmd_mod in CORE_CMDS.items(): - cmd_parser = cmd_mod.parser(subparsers) - cmd_parser.set_defaults(func=cmd_mod.command) - - # Extend with plugin commands - plugins.load_plugins(conf, ui) - for p in plugins.get_plugins().values(): - p.update_parser(subparsers) - - # Parse and run appropriate command - args = parser.parse_args(remaining_args) - args.prog = "pubs" # FIXME? - args.func(conf, args) + else: + conf = config.load_default_conf() + conf.filename = conf_path + + uis.init_ui(conf, force_colors=top_args.force_colors) + ui = uis.get_ui() + + parser = argparse.ArgumentParser(description="research papers repository", + prog="pubs", add_help=True) + parser.add_argument('--version', action='version', version=__version__) + subparsers = parser.add_subparsers(title="valid commands", dest="command") + subparsers.required = True + + # Populate the parser with core commands + for cmd_name, cmd_mod in CORE_CMDS.items(): + cmd_parser = cmd_mod.parser(subparsers) + cmd_parser.set_defaults(func=cmd_mod.command) + + # Extend with plugin commands + plugins.load_plugins(conf, ui) + for p in plugins.get_plugins().values(): + p.update_parser(subparsers) + + # Parse and run appropriate command + args = parser.parse_args(remaining_args) + args.prog = "pubs" # FIXME? + args.func(conf, args) + + except Exception as e: + uis.get_ui().handle_exception(e) diff --git a/pubs/repo.py b/pubs/repo.py index 4bf4a3d..6aac55a 100644 --- a/pubs/repo.py +++ b/pubs/repo.py @@ -12,12 +12,26 @@ def _base27(n): return _base27((n - 1) // 26) + chr(ord('a') + ((n - 1) % 26)) if n else '' +class CiteKeyError(Exception): + + default_message = "Wrong citekey: {}." + + def __init__(self, citekey, message=None): + self.message = message + self.citekey = citekey + + def __repr__(self): + return self.message or self.default_msg.format(self.citekey) + + class CiteKeyCollision(Exception): - pass + default_message = "Citekey already in use: {}." + + +class CiteKeyNotFound(Exception): -class InvalidReference(Exception): - pass + default_message = "Could not find citekey: {}." class Repository(object): @@ -63,7 +77,7 @@ class Repository(object): citekey=citekey, metadata=self.databroker.pull_metadata(citekey)) else: - raise InvalidReference('{} citekey not found'.format(citekey)) + raise CiteKeyNotFound(citekey) def push_paper(self, paper, overwrite=False, event=True): """ Push a paper to disk @@ -73,7 +87,7 @@ class Repository(object): """ bibstruct.check_citekey(paper.citekey) if (not overwrite) and (paper.citekey in self): - raise CiteKeyCollision('citekey {} already in use'.format(paper.citekey)) + raise CiteKeyCollision(paper.citekey) if not paper.added: paper.added = datetime.now() self.databroker.push_bibentry(paper.citekey, paper.bibentry) @@ -130,7 +144,8 @@ class Repository(object): else: # check if new_citekey does not exists if new_citekey in self: - raise CiteKeyCollision("can't rename paper to {}, conflicting files exists".format(new_citekey)) + msg = "Can't rename paper to {}, citekey already exists.".format(new_citekey) + raise CiteKeyCollision(new_citekey, message=msg) # move doc file if necessary if self.databroker.in_docsdir(paper.docpath): diff --git a/pubs/uis.py b/pubs/uis.py index 4951af4..1392050 100644 --- a/pubs/uis.py +++ b/pubs/uis.py @@ -62,6 +62,7 @@ class PrintUI(object): errors='replace') self._stderr = codecs.getwriter(self.encoding)(_get_raw_stderr(), errors='replace') + self.debug = conf.get('debug', False) def message(self, *messages, **kwargs): kwargs['file'] = self._stdout @@ -82,6 +83,13 @@ class PrintUI(object): def exit(self, error_code=1): sys.exit(error_code) + def handle_exception(self, exc): + if self.debug: + raise exc + else: + self.error(exc) + self.exit() + class InputUI(PrintUI): """UI class. Stores configuration parameters and system information. diff --git a/tests/test_repo.py b/tests/test_repo.py index 86e175d..e02f1b0 100644 --- a/tests/test_repo.py +++ b/tests/test_repo.py @@ -5,7 +5,7 @@ import dotdot import fake_env import fixtures -from pubs.repo import Repository, _base27, CiteKeyCollision, InvalidReference +from pubs.repo import Repository, _base27, CiteKeyCollision, CiteKeyNotFound from pubs.paper import Paper from pubs import config @@ -77,7 +77,7 @@ class TestUpdatePaper(TestRepo): def test_update_new_key_removes_old(self): paper = self.repo.pull_paper('turing1950computing') self.repo.rename_paper(paper, 'Turing1950') - with self.assertRaises(InvalidReference): + with self.assertRaises(CiteKeyNotFound): self.repo.pull_paper('turing1950computing') self.assertNotIn('turing1950computing', self.repo)