| """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": |
| |
| 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_, |
| choices=choices, |
| ) |
| ns_parser, _ = self.parse_simple_args(parser, other_args) |
| if ns_parser: |
| if ns_parser.value: |
| |
| 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) |
|
|