[perf] Widget classes lazy-loading follows a convention, rather than being implemented as a mapping

This commit is contained in:
Olivier Philippon
2022-06-17 14:10:36 +01:00
parent ca2fe2494d
commit 0bdd2be141
2 changed files with 27 additions and 35 deletions

View File

@@ -2,44 +2,40 @@ from __future__ import annotations
from importlib import import_module
import typing
from ..case import camel_to_snake
if typing.TYPE_CHECKING:
from ..widget import Widget
# Let's decrease startup time by lazy loading our Widgets:
# ⚠ For any new built-in Widget we create, not only we have to add them to the following dictionary, but also to the
# ⚠For any new built-in Widget we create, not only we have to add them to the following list, but also to the
# `__init__.pyi` file in this same folder - otherwise text editors and type checkers won't be able to "see" them.
_WIDGETS_LAZY_LOADING_MAPPING: dict[str, str] = {
"Footer": "._footer:Footer",
"Header": "._header:Header",
"Button": "._button:Button",
"Placeholder": "._placeholder:Placeholder",
"Static": "._static:Static",
"TreeControl": "._tree_control:TreeControl",
"TreeClick": "._tree_control:TreeClick",
"TreeNode": "._tree_control:TreeNode",
"NodeID": "._tree_control:NodeID",
"DirectoryTree": "._directory_tree:DirectoryTree",
"FileClick": "._directory_tree:FileClick",
}
__all__ = [
"Button",
"DirectoryTree",
"Footer",
"Header",
"Placeholder",
"Static",
"TreeControl",
]
_WIDGETS_LAZY_LOADING_CACHE: dict[str, type[Widget]] = {}
def __getattr__(widget_name: str) -> type[Widget]:
# Let's decrease startup time by lazy loading our Widgets:
def __getattr__(widget_class: str) -> type[Widget]:
try:
return _WIDGETS_LAZY_LOADING_CACHE[widget_name]
return _WIDGETS_LAZY_LOADING_CACHE[widget_class]
except KeyError:
pass
if widget_name not in _WIDGETS_LAZY_LOADING_MAPPING:
raise ImportError(f"Widget {widget_name} not found")
if widget_class not in __all__:
raise ImportError(f"Package 'textual.widgets' has no class '{widget_class}'")
module_name, class_name = _WIDGETS_LAZY_LOADING_MAPPING[widget_name].split(":")
module = import_module(module_name, package="textual.widgets")
class_ = getattr(module, class_name)
widget_module_path = f"._{camel_to_snake(widget_class)}"
module = import_module(widget_module_path, package="textual.widgets")
class_ = getattr(module, widget_class)
_WIDGETS_LAZY_LOADING_CACHE[widget_name] = class_
_WIDGETS_LAZY_LOADING_CACHE[widget_class] = class_
return class_
__all__ = tuple(_WIDGETS_LAZY_LOADING_MAPPING.keys())

View File

@@ -1,12 +1,8 @@
# This stub file must re-export every classes exposed in the __init__.py's `__all__` list:
from ._button import Button as Button
from ._directory_tree import DirectoryTree as DirectoryTree
from ._footer import Footer as Footer
from ._header import Header as Header
from ._button import Button as Button
from ._placeholder import Placeholder as Placeholder
from ._static import Static as Static
from ._tree_control import (
TreeControl as TreeControl,
TreeClick as TreeClick,
TreeNode as TreeNode,
NodeID as NodeID,
)
from ._directory_tree import DirectoryTree as DirectoryTree, FileClick as FileClick
from ._tree_control import TreeControl as TreeControl