diff options
Diffstat (limited to 'cli/openbb_cli/config/style.py')
-rw-r--r-- | cli/openbb_cli/config/style.py | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/cli/openbb_cli/config/style.py b/cli/openbb_cli/config/style.py new file mode 100644 index 00000000000..439d2a410d4 --- /dev/null +++ b/cli/openbb_cli/config/style.py @@ -0,0 +1,108 @@ +"""Chart and style helpers for Plotly.""" + +# pylint: disable=C0302,R0902,W3301 +import json +from pathlib import Path +from typing import Any, Dict, List, Optional + +from rich.console import Console + +from openbb_cli.config.constants import STYLES_DIRECTORY + +console = Console() + + +class Style: + """The class that helps with handling of style configurations. + + It serves styles for 2 libraries. For `Plotly` this class serves absolute paths + to the .pltstyle files. For `Plotly` and `Rich` this class serves custom + styles as python dictionaries. + """ + + STYLES_REPO = STYLES_DIRECTORY + + console_styles_available: Dict[str, Path] = {} + console_style: Dict[str, Any] = {} + + line_color: str = "" + up_color: str = "" + down_color: str = "" + up_colorway: List[str] = [] + down_colorway: List[str] = [] + up_color_transparent: str = "" + down_color_transparent: str = "" + + line_width: float = 1.5 + + def __init__( + self, + style: Optional[str] = "", + directory: Optional[Path] = None, + ): + """Initialize the class.""" + self._load(directory) + self.apply(style, directory) + + def apply( + self, style: Optional[str] = None, directory: Optional[Path] = None + ) -> None: + """Apply the style to the console.""" + if style: + if style in self.console_styles_available: + json_path: Optional[Path] = self.console_styles_available[style] + else: + self._load(directory) + if style in self.console_styles_available: + json_path = self.console_styles_available[style] + else: + console.print(f"\nInvalid console style '{style}', using default.") + json_path = self.console_styles_available.get("dark", None) + + if json_path: + self.console_style = self._from_json(json_path) + else: + console.print("Error loading default.") + + def _from_directory(self, folder: Optional[Path]) -> None: + """Load custom styles from folder. + + Parses the styles/default and styles/user folders and loads style files. + To be recognized files need to follow a naming convention: + *.pltstyle - plotly stylesheets + *.richstyle.json - rich stylesheets + + Parameters + ---------- + folder : str + Path to the folder containing the stylesheets + """ + if not folder or not folder.exists(): + return + + for attr, ext in zip( + ["console_styles_available"], + [".richstyle.json"], + ): + for file in folder.rglob(f"*{ext}"): + getattr(self, attr)[file.name.replace(ext, "")] = file + + def _load(self, directory: Optional[Path] = None) -> None: + """Load custom styles from default and user folders.""" + self._from_directory(self.STYLES_REPO) + self._from_directory(directory) + + def _from_json(self, file: Path) -> Dict[str, Any]: + """Load style from json file.""" + with open(file) as f: + json_style: dict = json.load(f) + for key, value in json_style.items(): + json_style[key] = value.replace( + " ", "" + ) # remove whitespaces so Rich can parse it + return json_style + + @property + def available_styles(self) -> List[str]: + """Return available styles.""" + return list(self.console_styles_available.keys()) |