mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-05-07 22:40:49 +08:00
149 lines
5.6 KiB
Python
149 lines
5.6 KiB
Python
"""Settings Controller Module."""
|
|
|
|
import argparse
|
|
from functools import partial, update_wrapper
|
|
from types import MethodType
|
|
from typing import Any, Literal, cast, 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()
|
|
|
|
|
|
def _get_extra(field: Any) -> dict[str, Any]:
|
|
"""Safely extract json_schema_extra as a dict."""
|
|
extra = field.json_schema_extra
|
|
return cast(dict[str, Any], extra) if isinstance(extra, dict) else {}
|
|
|
|
|
|
class SettingsController(BaseController):
|
|
"""Settings Controller class."""
|
|
|
|
_COMMANDS: dict[str, dict[str, Any]] = {
|
|
_get_extra(v).get("command", ""): {
|
|
"command": _get_extra(v).get("command"),
|
|
"group": _get_extra(v).get("group"),
|
|
"description": v.description,
|
|
"annotation": v.annotation,
|
|
"field_name": k,
|
|
}
|
|
for k, v in sorted(
|
|
session.settings.model_fields.items(),
|
|
key=lambda item: _get_extra(item[1]).get("command", ""),
|
|
)
|
|
if v.json_schema_extra
|
|
}
|
|
CHOICES_COMMANDS: list[str] = list(_COMMANDS.keys())
|
|
PATH = "/settings/"
|
|
CHOICES_GENERATION = True
|
|
|
|
def __init__(self, queue: list[str] | None = None):
|
|
"""Initialize the Constructor."""
|
|
super().__init__(queue)
|
|
for cmd, field in self._COMMANDS.items():
|
|
group = field.get("group")
|
|
if group == SettingGroups.feature_flags.value:
|
|
self._generate_command(cmd, field, "toggle")
|
|
elif group == SettingGroups.preferences.value:
|
|
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.value:
|
|
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.value:
|
|
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)
|