diff --git a/amanuensis/__main__.py b/amanuensis/__main__.py index dbd3ce7..79160ed 100644 --- a/amanuensis/__main__.py +++ b/amanuensis/__main__.py @@ -8,6 +8,7 @@ import amanuensis.cli as cli from amanuensis.cli.helpers import ( USER_ARGS, USER_KWARGS, LEXICON_ARGS, LEXICON_KWARGS) import amanuensis.config as config +from amanuensis.errors import AmanuensisError def repl(args): @@ -127,7 +128,11 @@ def main(argv): config.logger.debug(" {}: {}".format(key, val)) # Execute command. - args.func(args) + try: + args.func(args) + except AmanuensisError as e: + config.logger.error('Unexpected internal {}: {}'.format( + type(e).__name__, str(e))) if __name__ == "__main__": import sys diff --git a/amanuensis/cli/user.py b/amanuensis/cli/user.py index 78656ab..ae3054e 100644 --- a/amanuensis/cli/user.py +++ b/amanuensis/cli/user.py @@ -81,7 +81,7 @@ def command_list(args): continue with json_ro('user', uid, 'config.json') as user: users.append(user) - + # Output users.sort(key=lambda u: u['username']) for user in users: @@ -140,5 +140,5 @@ def command_passwd(args): args.user.set_password(pw) # Output - logger.info('Updated password for "{}"'.format(args.user.username)) + logger.info('Updated password for {}'.format(args.user.username)) return 0 diff --git a/amanuensis/errors.py b/amanuensis/errors.py index 370c116..0e1a1d4 100644 --- a/amanuensis/errors.py +++ b/amanuensis/errors.py @@ -10,8 +10,8 @@ class MalformedConfigError(AmanuensisError): class ReadOnlyError(AmanuensisError): """A config was edited in readonly mode""" -class InternalMisuseError(AmanuensisError): - """An internal helper method was called wrongly""" +class ArgumentError(AmanuensisError): + """An internal call was made with invalid arguments""" class IndexMismatchError(AmanuensisError): """An id was obtained from an index, but the object doesn't exist""" diff --git a/amanuensis/lexicon/__init__.py b/amanuensis/lexicon/__init__.py index 08818b8..c7953dc 100644 --- a/amanuensis/lexicon/__init__.py +++ b/amanuensis/lexicon/__init__.py @@ -2,7 +2,7 @@ import os import time from amanuensis.errors import ( - InternalMisuseError, IndexMismatchError, MissingConfigError) + ArgumentError, IndexMismatchError, MissingConfigError) from amanuensis.config import prepend, json_ro, json_rw class LexiconModel(): @@ -16,10 +16,10 @@ class LexiconModel(): the lexicon's config, raises an error. """ if lid and name: - raise InternalMisuseError("lid and name both specified to Lexicon" + raise ArgumentError("lid and name both specified to Lexicon" "Model.by()") if not lid and not name: - raise ValueError("One of lid or name must be not None") + raise ArgumentError("One of lid or name must be not None") if not lid: with json_ro('lexicon', 'index.json') as index: lid = index.get(name) diff --git a/amanuensis/lexicon/manage.py b/amanuensis/lexicon/manage.py index a0e6487..f403e45 100644 --- a/amanuensis/lexicon/manage.py +++ b/amanuensis/lexicon/manage.py @@ -11,6 +11,7 @@ import uuid from amanuensis.config import prepend, json_rw, json_ro, logger from amanuensis.config.loader import AttrOrderedDict +from amanuensis.errors import ArgumentError from amanuensis.lexicon import LexiconModel from amanuensis.resources import get_stream @@ -19,7 +20,7 @@ def valid_name(name): Validates that a lexicon name consists only of alpahnumerics, dashes, underscores, and spaces """ - return name is not None and re.match(r"^[A-Za-z0-9-_ ]+$", name) is not None + return re.match(r"^[A-Za-z0-9-_ ]+$", name) is not None def create_lexicon(name, editor): @@ -27,10 +28,16 @@ def create_lexicon(name, editor): Creates a lexicon with the given name and sets the given user as its editor """ # Verify arguments + if not name: + raise ArgumentError('Empty lexicon name: "{}"'.format(name)) if not valid_name(name): - raise ValueError("Invalid lexicon name: '{}'".format(name)) + raise ArgumentError('Invalid lexicon name: "{}"'.format(name)) + with json_ro('lexicon', 'index.json') as index: + if name in index.keys(): + raise ArgumentError('Lexicon name already taken: "{}"'.format( + name)) if editor is None: - raise ValueError("Invalid editor: '{}'".format(editor)) + raise ArgumentError("Invalid editor: '{}'".format(editor)) # Create the lexicon directory and initialize it with a blank lexicon lid = uuid.uuid4().hex @@ -79,7 +86,7 @@ def delete_lexicon(lex, purge=False): """ # Verify arguments if lex is None: - raise ValueError("Invalid lexicon: '{}'".format(lex)) + raise ArgumentError("Invalid lexicon: '{}'".format(lex)) # Delete the lexicon from the index with json_rw('lexicon', 'index.json') as j: @@ -140,9 +147,9 @@ def add_player(lex, player): """ # Verify arguments if lex is None: - raise ValueError("Invalid lexicon: '{}'".format(lex)) + raise ArgumentError("Invalid lexicon: '{}'".format(lex)) if player is None: - raise ValueError("Invalid player: '{}'".format(player)) + raise ArgumentError("Invalid player: '{}'".format(player)) # Idempotently add player added = False @@ -162,11 +169,11 @@ def remove_player(lex, player): """ # Verify arguments if lex is None: - raise ValueError("Invalid lexicon: '{}'".format(lex)) + raise ArgumentError("Invalid lexicon: '{}'".format(lex)) if player is None: - raise ValueError("Invalid player: '{}'".format(player)) + raise ArgumentError("Invalid player: '{}'".format(player)) if lex.editor == player.id: - raise ValueError( + raise ArgumentError( "Can't remove the editor '{}' from lexicon '{}'".format( player.username, lex.name)) @@ -186,16 +193,16 @@ def add_character(lex, player, charinfo={}): """ # Verify arguments if lex is None: - raise ValueError("Invalid lexicon: '{}'".format(lex)) + raise ArgumentError("Invalid lexicon: '{}'".format(lex)) if player is None: - raise ValueError("Invalid player: '{}'".format(player)) + raise ArgumentError("Invalid player: '{}'".format(player)) if not charinfo or not charinfo.get("name"): - raise ValueError("Invalid character info: '{}'".format(charinfo)) + raise ArgumentError("Invalid character info: '{}'".format(charinfo)) charname = charinfo.get("name") if any([ char.name for char in lex.character.values() if char.name == charname]): - raise ValueError("Duplicate character name: '{}'".format(charinfo)) + raise ArgumentError("Duplicate character name: '{}'".format(charinfo)) # Load the character template with get_stream('character.json') as template: @@ -223,16 +230,16 @@ def delete_character(lex, charname): """ # Verify arguments if lex is None: - raise ValueError("Invalid lexicon: '{}'".format(lex)) + raise ArgumentError("Invalid lexicon: '{}'".format(lex)) if charname is None: - raise ValueError("Invalid character name: '{}'".format(charname)) + raise ArgumentError("Invalid character name: '{}'".format(charname)) # Find character in this lexicon matches = [ char for cid, char in lex.character.items() if char.name == charname] if len(matches) != 1: - raise ValueError(matches) + raise ArgumentError(matches) char = matches[0] # Remove character from character list diff --git a/amanuensis/user.py b/amanuensis/user.py index 70adc43..eb0de05 100644 --- a/amanuensis/user.py +++ b/amanuensis/user.py @@ -7,7 +7,7 @@ from flask_login import UserMixin from werkzeug.security import generate_password_hash, check_password_hash from amanuensis.errors import ( - InternalMisuseError, MissingConfigError, IndexMismatchError) + ArgumentError, MissingConfigError, IndexMismatchError) from amanuensis.config import prepend, json_ro, json_rw from amanuensis.resources import get_stream from amanuensis.lexicon.manage import get_all_lexicons @@ -23,9 +23,9 @@ class UserModel(UserMixin): the user's config, raises an error. """ if uid and name: - raise InternalMisuseError("uid and name both specified to UserModel.by()") + raise ArgumentError("uid and name both specified to UserModel.by()") if not uid and not name: - raise ValueError("One of uid or name must be not None") + raise ArgumentError("One of uid or name must be not None") if not uid: with json_ro('user', 'index.json') as index: uid = index.get(name)