File size: 5,486 Bytes
b93364a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
"""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)
|