"""Base controller for the CLI."""
import argparse
import difflib
import os
import re
import shlex
from abc import ABCMeta, abstractmethod
from datetime import datetime
from pathlib import Path
from typing import Any, Dict, List, Literal, Optional, Union
import pandas as pd
from openbb_cli.config.completer import NestedCompleter
from openbb_cli.config.constants import SCRIPT_TAGS
from openbb_cli.controllers.choices import build_controller_choice_map
from openbb_cli.controllers.hub_service import upload_routine
from openbb_cli.controllers.utils import (
check_file_type_saved,
check_positive,
get_flair_and_username,
parse_and_split_input,
print_guest_block_msg,
print_rich_table,
remove_file,
system_clear,
)
from openbb_cli.session import Session
from prompt_toolkit.formatted_text import HTML
from prompt_toolkit.styles import Style
# pylint: disable=C0301,C0302,R0902,global-statement,too-many-boolean-expressions
# pylint: disable=R0912
controllers: Dict[str, Any] = {}
session = Session()
# TODO: We should try to avoid these global variables
RECORD_SESSION = False
RECORD_SESSION_LOCAL_ONLY = False
SESSION_RECORDED = list()
SESSION_RECORDED_NAME = ""
SESSION_RECORDED_DESCRIPTION = ""
SESSION_RECORDED_TAGS = ""
SESSION_RECORDED_PUBLIC = False
class BaseController(metaclass=ABCMeta):
"""Base class for a cli controller."""
CHOICES_COMMON = [
"cls",
"home",
"h",
"?",
"help",
"q",
"quit",
"..",
"e",
"exit",
"r",
"reset",
"stop",
"whoami",
"results",
]
CHOICES_COMMANDS: List[str] = []
CHOICES_MENUS: List[str] = []
NEWS_CHOICES: dict = {}
COMMAND_SEPARATOR = "/"
KEYS_MENU = "keys" + COMMAND_SEPARATOR
PATH: str = ""
FILE_PATH: str = ""
CHOICES_GENERATION = False
@property
def choices_default(self):
"""Return the default choices."""
choices = (
build_controller_choice_map(controller=self)
if self.CHOICES_GENERATION
else {}
)
return choices
def __init__(self, queue: Optional[List[str]] = None) -> None:
"""Create the base class for any controller in the codebase.
Used to simplify the creation of menus.
queue: List[str]
The current queue of jobs to process separated by "/"
E.g. /stocks/load gme/dps/sidtc/../exit
"""
self.check_path()
self.path = [x for x in self.PATH.split("/") if x != ""]
self.queue = (
self.parse_input(an_input="/".join(queue))
if (queue and self.PATH != "/")
else list()
)
controller_choices = self.CHOICES_COMMANDS + self.CHOICES_MENUS
if controller_choices:
self.controller_choices = controller_choices + self.CHOICES_COMMON
else:
self.controller_choices = self