Coverage for src / turbo_themes / themes.py: 85%
38 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-17 07:32 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-17 07:32 +0000
1# SPDX-License-Identifier: MIT
2"""Theme registry for Turbo Themes.
4Provides runtime access to all theme definitions.
5"""
7from __future__ import annotations
9import json
10from pathlib import Path
11from typing import Any, Iterator
13from .models import TurboThemes, ThemeValue, turbo_themes_from_dict
15# Load tokens at import time
16_TOKENS_PATH = Path(__file__).parent / "tokens.json"
17_tokens_data: TurboThemes | None = None
20def _load_tokens() -> TurboThemes:
21 """Load tokens from bundled JSON file.
23 Returns:
24 TurboThemes object containing all theme definitions.
25 """
26 global _tokens_data
27 if _tokens_data is None:
28 with open(_TOKENS_PATH, encoding="utf-8") as f:
29 _tokens_data = turbo_themes_from_dict(json.load(f))
30 return _tokens_data
33def get_theme(theme_id: str) -> ThemeValue | None:
34 """Get a theme by ID.
36 Args:
37 theme_id: The theme identifier (e.g., 'dracula', 'catppuccin-mocha')
39 Returns:
40 ThemeValue if found, None otherwise
41 """
42 tokens = _load_tokens()
43 return tokens.themes.get(theme_id)
46def get_all_themes() -> dict[str, ThemeValue]:
47 """Get all available themes.
49 Returns:
50 Dict mapping theme IDs to ThemeValue objects
51 """
52 return _load_tokens().themes
55def get_theme_ids() -> list[str]:
56 """Get list of all theme IDs.
58 Returns:
59 List of theme ID strings
60 """
61 return list(_load_tokens().themes.keys())
64# Pre-defined theme IDs for convenience
65THEME_IDS: tuple[str, ...] = tuple(
66 [
67 "bulma-dark",
68 "bulma-light",
69 "catppuccin-frappe",
70 "catppuccin-latte",
71 "catppuccin-macchiato",
72 "catppuccin-mocha",
73 "dracula",
74 "github-dark",
75 "github-light",
76 ]
77)
80# Lazy-loaded THEMES dict for backwards compatibility
81class _ThemesProxy:
82 """Lazy proxy for THEMES dict."""
84 _cache: dict[str, ThemeValue] | None = None
86 def __getitem__(self, key: str) -> ThemeValue:
87 return get_all_themes()[key]
89 def __iter__(self) -> Iterator[str]:
90 return iter(get_all_themes())
92 def __len__(self) -> int:
93 return len(THEME_IDS)
95 def keys(self) -> Any:
96 return get_all_themes().keys()
98 def values(self) -> Any:
99 return get_all_themes().values()
101 def items(self) -> Any:
102 return get_all_themes().items()
104 def get(self, key: str, default: ThemeValue | None = None) -> ThemeValue | None:
105 return get_all_themes().get(key, default)
108THEMES = _ThemesProxy()
111__all__ = [
112 "get_theme",
113 "get_all_themes",
114 "get_theme_ids",
115 "THEME_IDS",
116 "THEMES",
117 "ThemeValue",
118 "TurboThemes",
119]