Source code for command_line_assistant.client

"""Main module for the cli."""

import logging
import os
import sys
from argparse import ArgumentParser, Namespace

from dasbus.error import DBusError

from command_line_assistant.commands.chat import chat_command
from command_line_assistant.commands.cli import (
    add_default_command,
    create_argument_parser,
    read_stdin,
    register_all_commands,
)
from command_line_assistant.commands.feedback import feedback_command
from command_line_assistant.commands.history import history_command
from command_line_assistant.commands.shell import shell_command
from command_line_assistant.logger import setup_client_logging
from command_line_assistant.rendering.renderers import Renderer
from command_line_assistant.rendering.theme import Theme


[docs] def register_subcommands() -> ArgumentParser: """Register all the subcommands for the CLI Returns: ArgumentParser: The parser with all the subcommands registered. """ parser, commands_parser = create_argument_parser() # Register all decorator-based commands (includes chat, feedback, history, shell, example) register_all_commands( commands_parser, [chat_command, feedback_command, history_command, shell_command], ) return parser
logger = logging.getLogger(__name__)
[docs] def main() -> int: """Main function for the cli entrypoint Returns: int: Status code of the execution """ parser = register_subcommands() # Create the error and warning renderers, checking very early if the user # specified the --plain flag. This allows the exceptions below that use # these renders to follow the user's preference. plain_in_argv = "-p" in sys.argv or "--plain" in sys.argv renderer = Renderer(plain=plain_in_argv, theme=Theme()) try: stdin = read_stdin() modified_args = add_default_command(stdin, sys.argv) # In case that the user only calls `chat`, or anything else, # we just print help and return with os.EX_USAGE. if ( len(modified_args) <= 1 and not stdin and all(word not in modified_args for word in ("feedback", "history")) ): parser.print_help() return os.EX_USAGE # Small workaround to include the stdin in the namespace object. If it # exists, it will have the value of the stdin redirection, otherwise, # it will be None. namespace = Namespace(stdin=stdin) parsed_args = parser.parse_args(modified_args, namespace=namespace) if not hasattr(parsed_args, "func"): parser.print_help() return os.EX_USAGE # In case the uder specify the --debug, we will enable the logging here. if parsed_args.debug: setup_client_logging() return parsed_args.func(parsed_args) except ValueError as e: renderer.error(str(e)) return os.EX_DATAERR except DBusError as e: renderer.error(str(e)) return os.EX_UNAVAILABLE except RuntimeError as e: logger.debug(str(e)) renderer.error("Oops! Something went wrong while processing your request.") renderer.warning( "Try submitting your request one more time or contact an administrator." ) return os.EX_SOFTWARE except KeyboardInterrupt: renderer.error("Keyboard interrupt detected. Exiting...") return os.EX_OK
if __name__ == "__main__": sys.exit(main())