From 144f4160a5521e59bcdfffcf3c2b8558963a6323 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Mon, 22 Jul 2024 14:42:58 +0100 Subject: [PATCH] wip --- src/textual/app.py | 6 ++++++ src/textual/config.py | 50 +++++++++++++++++++++++++++++++++++++++++++ src/textual/widget.py | 2 +- 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/textual/config.py diff --git a/src/textual/app.py b/src/textual/app.py index 9f38dcb3af..28507e685c 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -278,6 +278,12 @@ def fileno(self) -> int: class App(Generic[ReturnType], DOMNode): """The base class for Textual Applications.""" + CONFIG_PATH: str | None = None + """Path to app config, or `None` for no app config.""" + + APP_ID: str | None = None + """A unique identifier used in the config system, or `None` to use the name of the App sub-class.""" + CSS: ClassVar[str] = "" """Inline CSS, useful for quick scripts. This is loaded after CSS_PATH, and therefore takes priority in the event of a specificity clash.""" diff --git a/src/textual/config.py b/src/textual/config.py new file mode 100644 index 0000000000..4b1b007211 --- /dev/null +++ b/src/textual/config.py @@ -0,0 +1,50 @@ +from __future__ import annotations + +import tomllib +from os import PathLike + + +class Config: + def __init__(self, *paths: PathLike) -> None: + self.paths = paths + self._data: dict | None = None + self._attempted_read = False + + def _read(self) -> dict: + configs: list[dict] = [] + for path in self.paths: + try: + with open(path, "rb") as config_file: + configs.append(tomllib.load(config_file)) + except IOError: + pass + config = configs[0] + for overlay_config in configs[1:]: + if isinstance(overlay_config, dict): + for key, value in overlay_config.items(): + config[key] = value + return config + + @property + def data(self) -> dict: + if not self._attempted_read: + self._attempted_read = True + self._data = self._read() + if self._data is None: + return {} + return self._data + + def get(self, *keys: str, default: object = None) -> object: + data = self.data + for key in keys: + if key not in data: + return default + data = data[key] + return data + + +if __name__ == "__main__": + config = Config("config.toml") + from rich import print + + print(config.data) diff --git a/src/textual/widget.py b/src/textual/widget.py index 8c4f1598d5..73bdcef143 100644 --- a/src/textual/widget.py +++ b/src/textual/widget.py @@ -834,7 +834,7 @@ def render_str(self, text_content: str | Text) -> Text: A text object. """ text = ( - Text.from_markup(text_content) + Text.from_markup(text_content, end="") if isinstance(text_content, str) else text_content )