Source code for pytablewriter.style._theme

import importlib
import pkgutil
import re
from typing import Any, Dict, NamedTuple, Optional, Sequence

from .._logger import logger
from ..style import Cell, Style


try:
    from typing import Protocol
except ImportError:
    # typing.Protocol is only available starting from Python 3.8.
    from .._typing import Protocol  # type: ignore

PLUGIN_NAME_PEFIX = "pytablewriter"
PLUGIN_NAME_SUFFIX = "theme"
KNOWN_PLUGINS = (
    f"{PLUGIN_NAME_PEFIX}_altrow_{PLUGIN_NAME_SUFFIX}",
    f"{PLUGIN_NAME_PEFIX}_altcol_{PLUGIN_NAME_SUFFIX}",
)


[docs] class StyleFilterFunc(Protocol):
[docs] def __call__(self, cell: Cell, **kwargs: Any) -> Optional[Style]: ...
[docs] class ColSeparatorStyleFilterFunc(Protocol):
[docs] def __call__( self, left_cell: Optional[Cell], right_cell: Optional[Cell], **kwargs: Any ) -> Optional[Style]: ...
[docs] class CheckStyleFilterKeywordArgsFunc(Protocol):
[docs] def __call__(self, **kwargs: Any) -> None: ...
[docs] class Theme(NamedTuple): style_filter: Optional[StyleFilterFunc] col_separator_style_filter: Optional[ColSeparatorStyleFilterFunc] check_style_filter_kwargs: Optional[CheckStyleFilterKeywordArgsFunc]
def list_themes() -> Sequence[str]: return list(load_ptw_plugins()) def load_ptw_plugins() -> Dict[str, Theme]: plugin_regexp = re.compile( rf"^{PLUGIN_NAME_PEFIX}[_-].+[_-]{PLUGIN_NAME_SUFFIX}", re.IGNORECASE ) discovered_plugins = { name: importlib.import_module(name) for _finder, name, _ispkg in pkgutil.iter_modules() if plugin_regexp.search(name) is not None } logger.debug(f"discovered_plugins: {list(discovered_plugins)}") themes: Dict[str, Theme] = {} for theme, plugin in discovered_plugins.items(): style_filter = plugin.style_filter if hasattr(plugin, "style_filter") else None col_sep_style_filter = ( plugin.col_separator_style_filter if hasattr(plugin, "col_separator_style_filter") else None ) check_kwargs_func = ( plugin.check_style_filter_kwargs if hasattr(plugin, "check_style_filter_kwargs") else None ) themes[theme] = Theme(style_filter, col_sep_style_filter, check_kwargs_func) return themes def fetch_theme(plugin_name: str) -> Theme: loaded_themes = load_ptw_plugins() theme_regexp = re.compile( rf"^{PLUGIN_NAME_PEFIX}[_-]{plugin_name}[_-]{PLUGIN_NAME_SUFFIX}", re.IGNORECASE ) matched_theme = None for loaded_theme in loaded_themes: if theme_regexp.search(loaded_theme): matched_theme = loaded_theme break else: err_msgs = [f"{plugin_name} theme is not installed."] if plugin_name in KNOWN_PLUGINS: err_msgs.append(f"try 'pip install {plugin_name}' to install the theme.") raise RuntimeError(" ".join(err_msgs)) return loaded_themes[matched_theme]