diff options
author | Andy Grover <agrover@redhat.com> | 2014-03-03 12:21:21 -0800 |
---|---|---|
committer | Andy Grover <agrover@redhat.com> | 2014-03-03 12:21:21 -0800 |
commit | 283db6ba1cd32f4d34b8cf791502bf3497a04c3e (patch) | |
tree | 67a8aca141610b8dcbfbeca91da6bae0ee38a459 | |
parent | 84c9cebeddfd21b238f5200d787041fbb1cf94da (diff) | |
download | configshell-fb-283db6ba1cd32f4d34b8cf791502bf3497a04c3e.tar.gz |
Let exceptions through to callers of run_interactive
Change logic in run_interactive() to not recursively call itself, and to
let exceptions through to callers.
Raising ExecutionError instead of printing a message but not raising an
exception is now allowed. This lets us reorganize a few functions for
less nested logic.
Change log.error()s to exceptions.
Signed-off-by: Andy Grover <agrover@redhat.com>
-rw-r--r-- | configshell/node.py | 313 | ||||
-rw-r--r-- | configshell/shell.py | 62 |
2 files changed, 182 insertions, 193 deletions
diff --git a/configshell/node.py b/configshell/node.py index 121e5dd..38922a4 100644 --- a/configshell/node.py +++ b/configshell/node.py @@ -486,48 +486,46 @@ class ConfigNode(object): %s ''' % ' '.join(self.list_config_groups())) elif not parameter: - if group in self.list_config_groups(): - section = "%s CONFIG GROUP" % group.upper() - underline1 = ''.ljust(len(section), '=') - parameters = '' - for p_name in self.list_group_params(group, writable=True): - p_def = self.get_group_param(group, p_name) - type_method = self.get_type_method(p_def['type']) - parameter = "%s=I{%s}" % (p_def['name'], p_def['type']) - underline2 = ''.ljust(len(parameter), '-') - parameters += '%s\n%s\n%s\n\n' \ - % (parameter, underline2, p_def['description']) - self.shell.con.epy_write('''%s\n%s\n%s\n''' - % (section, underline1, parameters)) - else: - self.shell.log.error("Unknown configuration group: %s" % group) - elif group in self.list_config_groups(): - for param, value in parameter.iteritems(): - if param in self.list_group_params(group): - p_def = self.get_group_param(group, param) - type_method = self.get_type_method(p_def['type']) - if p_def['writable']: - try: - value = type_method(value) - except ValueError as msg: - self.shell.log.error("Not setting %s! %s" - % (param, msg)) - else: - group_setter = self.get_group_setter(group) - group_setter(param, value) - group_getter = self.get_group_getter(group) - value = group_getter(param) - value = type_method(value, reverse=True) - self.shell.con.display("Parameter %s is now '%s'." - % (param, value)) - else: - self.shell.log.error("Parameter %s is read-only." - % param) - else: - self.shell.log.error("Unknown parameter %s in group '%s'." - % (param, group)) - else: - self.shell.log.error("Unknown configuration group: %s" % group) + if group not in self.list_config_groups(): + raise ExecutionError("Unknown configuration group: %s" % group) + + section = "%s CONFIG GROUP" % group.upper() + underline1 = ''.ljust(len(section), '=') + parameters = '' + for p_name in self.list_group_params(group, writable=True): + p_def = self.get_group_param(group, p_name) + type_method = self.get_type_method(p_def['type']) + parameter = "%s=I{%s}" % (p_def['name'], p_def['type']) + underline2 = ''.ljust(len(parameter), '-') + parameters += '%s\n%s\n%s\n\n' \ + % (parameter, underline2, p_def['description']) + self.shell.con.epy_write('''%s\n%s\n%s\n''' + % (section, underline1, parameters)) + + elif group not in self.list_config_groups(): + raise ExecutionError("Unknown configuration group: %s" % group) + + for param, value in parameter.iteritems(): + if param not in self.list_group_params(group): + raise ExecutionError("Unknown parameter %s in group '%s'." + % (param, group)) + + p_def = self.get_group_param(group, param) + type_method = self.get_type_method(p_def['type']) + if not p_def['writable']: + raise ExecutionError("Parameter %s is read-only." % param) + + try: + value = type_method(value) + except ValueError as msg: + raise ExecutionError("Not setting %s! %s" % (param, msg)) + + group_setter = self.get_group_setter(group) + group_setter(param, value) + group_getter = self.get_group_getter(group) + value = group_getter(param) + value = type_method(value, reverse=True) + self.shell.con.display("Parameter %s is now '%s'." % (param, value)) def ui_complete_set(self, parameters, text, current_param): ''' @@ -596,48 +594,49 @@ class ConfigNode(object): %s ''' % ' '.join(self.list_config_groups())) elif not parameter: - if group in self.list_config_groups(): - section = "%s CONFIG GROUP" % group.upper() - underline1 = ''.ljust(len(section), '=') - parameters = '' - params = [self.get_group_param(group, p_name) - for p_name in self.list_group_params(group)] - for p_def in params: - group_getter = self.get_group_getter(group) - value = group_getter(p_def['name']) - type_method = self.get_type_method(p_def['type']) - value = type_method(value, reverse=True) - parameter = "%s=%s" % (p_def['name'], value) - if p_def['writable'] is False: - parameter += " [ro]" - underline2 = ''.ljust(len(parameter), '-') - parameters += '%s\n%s\n%s\n\n' \ - % (parameter, underline2, p_def['description']) - - self.shell.con.epy_write('''%s\n%s\n%s\n''' - % (section, underline1, parameters)) + if group not in self.list_config_groups(): + raise ExecutionError("Unknown configuration group: %s" % group) + + section = "%s CONFIG GROUP" % group.upper() + underline1 = ''.ljust(len(section), '=') + parameters = '' + params = [self.get_group_param(group, p_name) + for p_name in self.list_group_params(group)] + for p_def in params: + group_getter = self.get_group_getter(group) + value = group_getter(p_def['name']) + type_method = self.get_type_method(p_def['type']) + value = type_method(value, reverse=True) + parameter = "%s=%s" % (p_def['name'], value) + if p_def['writable'] is False: + parameter += " [ro]" + underline2 = ''.ljust(len(parameter), '-') + parameters += '%s\n%s\n%s\n\n' \ + % (parameter, underline2, p_def['description']) + + self.shell.con.epy_write('''%s\n%s\n%s\n''' + % (section, underline1, parameters)) + + elif group not in self.list_config_groups(): + raise ExecutionError("Unknown configuration group: %s" % group) + + for param in parameter: + if param not in self.list_group_params(group): + raise ExecutionError("No parameter '%s' in group '%s'." + % (param, group)) + + self.shell.log.debug("About to get the parameter's value.") + group_getter = self.get_group_getter(group) + value = group_getter(param) + p_def = self.get_group_param(group, param) + type_method = self.get_type_method(p_def['type']) + value = type_method(value, reverse=True) + if p_def['writable']: + writable = "" else: - self.shell.log.error("Unknown configuration group: %s" % group) - elif group in self.list_config_groups(): - for param in parameter: - if param in self.list_group_params(group): - self.shell.log.debug("About to get the parameter's value.") - group_getter = self.get_group_getter(group) - value = group_getter(param) - p_def = self.get_group_param(group, param) - type_method = self.get_type_method(p_def['type']) - value = type_method(value, reverse=True) - if p_def['writable']: - writable = "" - else: - writable = "[ro]" - self.shell.con.display("%s=%s %s" - % (param, value, writable)) - else: - self.shell.log.error("No parameter '%s' in group '%s'." - % (param, group)) - else: - self.shell.log.error("Unknown configuration group: %s" % group) + writable = "[ro]" + self.shell.con.display("%s=%s %s" + % (param, value, writable)) def ui_complete_get(self, parameters, text, current_param): ''' @@ -699,20 +698,19 @@ class ConfigNode(object): try: target = self.get_node(path) except ValueError as msg: - self.shell.log.error(msg) - return + raise ExecutionError(str(msg)) if depth is None: depth = self.shell.prefs['tree_max_depth'] try: depth = int(depth) except ValueError: - self.shell.log.error('The tree depth must be a number.') - else: - if depth == 0: - depth = None - tree = self._render_tree(target, depth=depth) - self.shell.con.display(tree) + raise ExecutionError('The tree depth must be a number.') + + if depth == 0: + depth = None + tree = self._render_tree(target, depth=depth) + self.shell.con.display(tree) def _render_tree(self, root, margin=None, depth=None, do_list=False): ''' @@ -1036,21 +1034,20 @@ class ConfigNode(object): try: target_node = self.get_node(path) except ValueError as msg: - self.shell.log.error(msg) - return None - else: - index = self.shell.prefs['path_history_index'] - if target_node.path != self.shell.prefs['path_history'][index]: - # Truncate the hostory to retain current path as last one - self.shell.prefs['path_history'] = \ - self.shell.prefs['path_history'][:index+1] - # Append the new path and update the index - self.shell.prefs['path_history'].append(target_node.path) - self.shell.prefs['path_history_index'] = index + 1 - self.shell.log.debug("After cd, path history is: %s, index is %d" - % (str(self.shell.prefs['path_history']), - self.shell.prefs['path_history_index'])) - return target_node + raise ExecutionError(str(msg)) + + index = self.shell.prefs['path_history_index'] + if target_node.path != self.shell.prefs['path_history'][index]: + # Truncate the hostory to retain current path as last one + self.shell.prefs['path_history'] = \ + self.shell.prefs['path_history'][:index+1] + # Append the new path and update the index + self.shell.prefs['path_history'].append(target_node.path) + self.shell.prefs['path_history_index'] = index + 1 + self.shell.log.debug("After cd, path history is: %s, index is %d" + % (str(self.shell.prefs['path_history']), + self.shell.prefs['path_history_index'])) + return target_node def _lines_walker(self, lines, start_pos): ''' @@ -1136,33 +1133,34 @@ class ConfigNode(object): for command in commands: msg += " - %s\n" % self.get_command_syntax(command)[0] self.shell.con.epy_write(msg) - elif topic in commands: - syntax, comments, defaults = self.get_command_syntax(topic) - msg = self.shell.con.dedent(''' - SYNTAX - ====== - %s - - ''' % syntax) - for comment in comments: - msg += comment + '\n' - - if defaults: - msg += self.shell.con.dedent(''' - DEFAULT VALUES - ============== - %s - - ''' % defaults) + + elif topic not in commands: + raise ExecutionError("Cannot find help topic %s." % topic) + + syntax, comments, defaults = self.get_command_syntax(topic) + msg = self.shell.con.dedent(''' + SYNTAX + ====== + %s + + ''' % syntax) + for comment in comments: + msg += comment + '\n' + + if defaults: msg += self.shell.con.dedent(''' - DESCRIPTION - =========== - ''') - msg += self.get_command_description(topic) - msg += "\n" - self.shell.con.epy_write(msg) - else: - self.shell.log.error("Cannot find help topic %s." % topic) + DEFAULT VALUES + ============== + %s + + ''' % defaults) + msg += self.shell.con.dedent(''' + DESCRIPTION + =========== + ''') + msg += self.get_command_description(topic) + msg += "\n" + self.shell.con.epy_write(msg) def ui_complete_help(self, parameters, text, current_param): ''' @@ -1234,27 +1232,26 @@ class ConfigNode(object): ''' if action == 'add' and bookmark: if bookmark in self.shell.prefs['bookmarks']: - self.shell.log.error("Bookmark %s already exists." % bookmark) - else: - self.shell.prefs['bookmarks'][bookmark] = self.path - # No way Prefs is going to account for that :-( - self.shell.prefs.save() - self.shell.log.info("Bookmarked %s as %s." - % (self.path, bookmark)) + raise ExecutionError("Bookmark %s already exists." % bookmark) + + self.shell.prefs['bookmarks'][bookmark] = self.path + # No way Prefs is going to account for that :-( + self.shell.prefs.save() + self.shell.log.info("Bookmarked %s as %s." + % (self.path, bookmark)) elif action == 'del' and bookmark: - if bookmark in self.shell.prefs['bookmarks']: - del self.shell.prefs['bookmarks'][bookmark] - # No way Prefs is going to account for that deletion - self.shell.prefs.save() - self.shell.log.info("Deleted bookmark %s." % bookmark) - else: - self.shell.log.error("No such bookmark %s." % bookmark) + if bookmark not in self.shell.prefs['bookmarks']: + raise ExecutionError("No such bookmark %s." % bookmark) + + del self.shell.prefs['bookmarks'][bookmark] + # No way Prefs is going to account for that deletion + self.shell.prefs.save() + self.shell.log.info("Deleted bookmark %s." % bookmark) elif action == 'go' and bookmark: - if bookmark in self.shell.prefs['bookmarks']: - return self.ui_command_cd( - self.shell.prefs['bookmarks'][bookmark]) - else: - self.shell.log.error("No such bookmark %s." % bookmark) + if bookmark not in self.shell.prefs['bookmarks']: + raise ExecutionError("No such bookmark %s." % bookmark) + return self.ui_command_cd( + self.shell.prefs['bookmarks'][bookmark]) elif action == 'show': bookmarks = self.shell.con.dedent(''' BOOKMARKS @@ -1272,7 +1269,7 @@ class ConfigNode(object): bookmarks += "%s\n%s\n%s\n\n" % (bookmark, underline, path) self.shell.con.epy_write(bookmarks) else: - self.shell.log.error("Syntax error, see 'help bookmarks'.") + raise ExecutionError("Syntax error, see 'help bookmarks'.") def ui_complete_bookmarks(self, parameters, text, current_param): ''' @@ -1409,16 +1406,10 @@ class ConfigNode(object): if command in self.list_commands(): method = self.get_command_method(command) else: - self.shell.log.error("Command not found %s" % command) - return + raise ExecutionError("Command not found %s" % command) - try: - self.assert_params(method, pparams, kparams) - result = method(*pparams, **kparams) - except ExecutionError as msg: - self.shell.log.error(msg) - else: - return result + self.assert_params(method, pparams, kparams) + return method(*pparams, **kparams) def assert_params(self, method, pparams, kparams): ''' diff --git a/configshell/shell.py b/configshell/shell.py index 878d24a..e4bd9ea 100644 --- a/configshell/shell.py +++ b/configshell/shell.py @@ -853,24 +853,24 @@ class ConfigShell(object): try: target = self._current_node.get_node(path) except ValueError as msg: - self.log.error(msg) + raise ExecutionError(str(msg)) + + result = None + if not iterall: + targets = [target] else: - result = None - if not iterall: - targets = [target] - else: - targets = target.children - for target in targets: - if iterall: - self.con.display("[%s]" % target.path) - result = target.execute_command(command, pparams, kparams) - self.log.debug("Command execution returned %r" % result) - if isinstance(result, ConfigNode): - self._current_node = result - elif result == 'EXIT': - self._exit = True - elif result is not None: - raise ExecutionError("Unexpected result: %r" % result) + targets = target.children + for target in targets: + if iterall: + self.con.display("[%s]" % target.path) + result = target.execute_command(command, pparams, kparams) + self.log.debug("Command execution returned %r" % result) + if isinstance(result, ConfigNode): + self._current_node = result + elif result == 'EXIT': + self._exit = True + elif result is not None: + raise ExecutionError("Unexpected result: %r" % result) # Public methods @@ -923,10 +923,9 @@ class ConfigShell(object): except Exception as msg: self.log.error(msg) if exit_on_error is True: - self.log.exception("Aborting run on error.") - break - else: - self.log.exception("Keep running after an error.") + raise ExecutionError("Aborting run on error.") + + self.log.exception("Keep running after an error.") def run_interactive(self): ''' @@ -942,17 +941,16 @@ class ConfigShell(object): self._current_node = self._root_node else: self._current_node = target - try: - old_completer = readline.get_completer() - self._cli_loop() - except KeyboardInterrupt: - self.con.raw_write('\n') - self.run_interactive() - except Exception: - self.log.exception() - self.run_interactive() - finally: - readline.set_completer(old_completer) + + while True: + try: + old_completer = readline.get_completer() + self._cli_loop() + break + except KeyboardInterrupt: + self.con.raw_write('\n') + finally: + readline.set_completer(old_completer) def attach_root_node(self, root_node): ''' |