diff --git a/mreg_cli/cli.py b/mreg_cli/cli.py index 650772bc..03814368 100644 --- a/mreg_cli/cli.py +++ b/mreg_cli/cli.py @@ -139,11 +139,8 @@ def parse(self, command: str) -> None: # after it prints a help msg. self.last_errno = e.code - except CliWarning as e: - print_formatted_text(HTML(f"{e}")) - - except CliError as e: - print_formatted_text(HTML(f"{e}")) + except (CliWarning, CliError) as exc: + exc.print_self() except CliExit: from sys import exit diff --git a/mreg_cli/exceptions.py b/mreg_cli/exceptions.py index d818cc4e..7517030a 100644 --- a/mreg_cli/exceptions.py +++ b/mreg_cli/exceptions.py @@ -1,13 +1,46 @@ +"""This module contains custom exceptions for the CLI.""" + +import sys + +from prompt_toolkit import print_formatted_text +from prompt_toolkit.formatted_text import HTML + + class CliException(Exception): - pass + """Base exception class for the CLI.""" + + def formatted_exception(self) -> str: + """Returns a formatted string representation of the exception. + + :returns: Formatted string for the exception message. + """ + raise NotImplementedError("This method should be implemented by subclasses") + + def print_self(self): + """Prints the exception with appropriate formatting.""" + print_formatted_text(HTML(self.formatted_exception()), file=sys.stdout) class CliError(CliException): - pass + """Exception class for CLI errors.""" + + def formatted_exception(self) -> str: + """Formatted string with ANSI red color for the error message. + + :returns: Formatted error message. + """ + return f"{super().__str__()}" class CliWarning(CliException): - pass + """Exception class for CLI warnings.""" + + def formatted_exception(self) -> str: + """Formatted string with HTML italic tag for the warning message. + + :returns: Formatted warning message. + """ + return f"{super().__str__()}" class HostNotFoundWarning(CliWarning): diff --git a/mreg_cli/main.py b/mreg_cli/main.py index 75ee9c87..2436e2de 100644 --- a/mreg_cli/main.py +++ b/mreg_cli/main.py @@ -8,6 +8,7 @@ from . import config, log, recorder, util from .cli import cli, source +from .exceptions import CliError, CliWarning from .outputmanager import OutputManager logger = logging.getLogger(__name__) @@ -187,8 +188,10 @@ def main(): cli.parse(cmd) # Render the output output.render() - except ValueError as e: - print(e) + except (CliWarning, CliError) as exc: + exc.print_self() + except ValueError as exc: + print(exc) if __name__ == "__main__": diff --git a/mreg_cli/outputmanager.py b/mreg_cli/outputmanager.py index 1d35eeb2..da4be65b 100644 --- a/mreg_cli/outputmanager.py +++ b/mreg_cli/outputmanager.py @@ -8,6 +8,8 @@ import re from typing import Any, List, Tuple +from mreg_cli.exceptions import CliError + class OutputManager: """Manages and formats output for display. @@ -42,7 +44,7 @@ def from_command(self, command: str) -> str: """Adds the command that generated the output. :param command: The command to add. - + :raises CliError: If the command is invalid. :return: The cleaned command, devoid of filters and other noise. """ self._command, self._filter_re, self._negate = self.get_filter(command) @@ -113,6 +115,7 @@ def get_filter(self, command: str) -> Tuple[str, Any, bool]: splitting. :param command: The command to parse for the filter. + :raises CliError: If the filter is invalid. :return: The command, the filter, and whether it is a negated filter. """ negate = False @@ -129,7 +132,17 @@ def get_filter(self, command: str) -> Tuple[str, Any, bool]: negate = True filter_str = filter_str[1:].strip() - filter_re = re.compile(filter_str) + try: + filter_re = re.compile(filter_str) + except re.error as exc: + if "|" in filter_str: + raise CliError( + "ERROR: Command parts that contain a pipe ('|') must be quoted.", + ) from exc + else: + raise CliError( + "ERROR: Unable to compile regex '{}': {}", filter_str, exc + ) from exc return (command, filter_re, negate)