OpenBB / cli /openbb_cli /controllers /settings_controller.py
CatPtain's picture
Upload 70 files
b93364a verified
"""Settings Controller Module."""
import argparse
from functools import partial, update_wrapper
from types import MethodType
from typing import List, Literal, Optional, get_origin
from openbb_cli.config.menu_text import MenuText
from openbb_cli.controllers.base_controller import BaseController
from openbb_cli.models.settings import SettingGroups
from openbb_cli.session import Session
session = Session()
class SettingsController(BaseController):
"""Settings Controller class."""
_COMMANDS = {
v.json_schema_extra.get("command"): {
"command": (v.json_schema_extra or {}).get("command"),
"group": (v.json_schema_extra or {}).get("group"),
"description": v.description,
"annotation": v.annotation,
"field_name": k,
}
for k, v in sorted(
session.settings.model_fields.items(),
key=lambda item: (item[1].json_schema_extra or {}).get("command", ""),
)
if v.json_schema_extra
}
CHOICES_COMMANDS: List[str] = list(_COMMANDS.keys())
PATH = "/settings/"
CHOICES_GENERATION = True
def __init__(self, queue: Optional[List[str]] = None):
"""Initialize the Constructor."""
super().__init__(queue)
for cmd, field in self._COMMANDS.items():
group = field.get("group")
if group == SettingGroups.feature_flags:
self._generate_command(cmd, field, "toggle")
elif group == SettingGroups.preferences:
self._generate_command(cmd, field, "set")
self.update_completer(self.choices_default)
def print_help(self):
"""Print help."""
mt = MenuText("settings/")
mt.add_info("Feature Flags")
for k, f in self._COMMANDS.items():
if f.get("group") == SettingGroups.feature_flags:
mt.add_setting(
name=k,
status=getattr(session.settings, f["field_name"]),
description=f["description"],
)
mt.add_raw("\n")
mt.add_info("Preferences")
for k, f in self._COMMANDS.items():
if f.get("group") == SettingGroups.preferences:
mt.add_cmd(
name=k,
description=f["description"],
)
session.console.print(text=mt.menu_text, menu="Settings")
def _generate_command(
self, cmd_name: str, field: dict, action_type: Literal["toggle", "set"]
):
"""Generate command call."""
def _toggle(self, other_args: List[str], field=field) -> None:
"""Toggle setting value."""
field_name = field["field_name"]
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog=field["command"],
description=field["description"],
add_help=False,
)
ns_parser, _ = self.parse_simple_args(parser, other_args)
if ns_parser:
session.settings.set_item(
field_name, not getattr(session.settings, field_name)
)
def _set(self, other_args: List[str], field=field) -> None:
"""Set preference value."""
field_name = field["field_name"]
annotation = field["annotation"]
command = field["command"]
type_ = str if get_origin(annotation) is Literal else annotation
choices = None
if get_origin(annotation) is Literal:
choices = annotation.__args__
elif command == "console_style":
# To have updated choices for console style
choices = session.style.available_styles
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog=command,
description=field["description"],
add_help=False,
)
parser.add_argument(
"-v",
"--value",
dest="value",
action="store",
required=False,
type=type_, # type: ignore[arg-type]
choices=choices,
)
ns_parser, _ = self.parse_simple_args(parser, other_args)
if ns_parser:
if ns_parser.value:
# Console style is applied immediately
if command == "console_style":
session.style.apply(ns_parser.value)
session.settings.set_item(field_name, ns_parser.value)
session.console.print(
f"[info]Current value:[/info] {getattr(session.settings, field_name)}"
)
elif not other_args:
session.console.print(
f"[info]Current value:[/info] {getattr(session.settings, field_name)}"
)
action = None
if action_type == "toggle":
action = _toggle
elif action_type == "set":
action = _set
else:
raise ValueError(f"Action type '{action_type}' not allowed.")
bound_method = update_wrapper(
wrapper=partial(MethodType(action, self), field=field), wrapped=action
)
setattr(self, f"call_{cmd_name}", bound_method)