From 7185e2930df848da7ec8a9237c6f9cfde312aa6b Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Mon, 20 Mar 2023 11:21:56 +0000 Subject: [PATCH] Driver class environ (#2036) * Driver class environment variable * comments --- CHANGELOG.md | 1 + src/textual/app.py | 20 +++++++++++++++++++- src/textual/constants.py | 6 ++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2dfb8feb7..f2a362f93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Added `TabbedContent` widget https://github.com/Textualize/textual/pull/2059 - Added `get_child_by_type` method to widgets / app https://github.com/Textualize/textual/pull/2059 - Added `Widget.render_str` method https://github.com/Textualize/textual/pull/2059 +- Added TEXTUAL_DRIVER environment variable ## [0.15.1] - 2023-03-14 diff --git a/src/textual/app.py b/src/textual/app.py index 34a9538ea..ecb6d7ee6 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -1,6 +1,7 @@ from __future__ import annotations import asyncio +import importlib import inspect import io import os @@ -47,7 +48,7 @@ from rich.protocol import is_renderable from rich.segment import Segment, Segments from rich.traceback import Traceback -from . import Logger, LogGroup, LogVerbosity, actions, events, log, messages +from . import Logger, LogGroup, LogVerbosity, actions, constants, events, log, messages from ._animator import DEFAULT_EASING, Animatable, Animator, EasingFunction from ._ansi_sequences import SYNC_END, SYNC_START from ._asyncio import create_task @@ -590,7 +591,24 @@ class App(Generic[ReturnType], DOMNode): Returns: A Driver class which manages input and display. """ + driver_class: Type[Driver] + + driver_import = constants.DRIVER + if driver_import is not None: + # The driver class is set from the environment + # Syntax should be foo.bar.baz:MyDriver + module_import, colon, driver_symbol = driver_import.partition(":") + driver_module = importlib.import_module(module_import) + driver_class = getattr(driver_module, driver_symbol) + if not inspect.isclass(driver_class) or not issubclass( + driver_class, Driver + ): + raise RuntimeError( + f"Unable to import {driver_import!r}; {driver_class!r} is not a Driver class " + ) + return driver_class + if WINDOWS: from .drivers.windows_driver import WindowsDriver diff --git a/src/textual/constants.py b/src/textual/constants.py index 2e57942a7..26a00e6c1 100644 --- a/src/textual/constants.py +++ b/src/textual/constants.py @@ -3,6 +3,8 @@ Constants that we might want to expose via the public API. """ +from __future__ import annotations + import os from typing_extensions import Final @@ -11,6 +13,8 @@ from ._border import BORDER_CHARS __all__ = ["BORDERS"] +get_environ = os.environ.get + def get_environ_bool(name: str) -> bool: """Check an environment variable switch. @@ -28,3 +32,5 @@ def get_environ_bool(name: str) -> bool: BORDERS = list(BORDER_CHARS) DEBUG: Final[bool] = get_environ_bool("TEXTUAL_DEBUG") + +DRIVER: Final[str | None] = get_environ("TEXTUAL_DRIVER", None)