Coverage for src / turbo_themes / themes.py: 88%
38 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-02-10 07:26 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-02-10 07:26 +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 derived from tokens.json — always in sync
65# Preserves canonical vendor-grouped ordering from tokens.json
66THEME_IDS: tuple[str, ...] = tuple(get_theme_ids())
69# Lazy-loaded THEMES dict for backwards compatibility
70class _ThemesProxy:
71 """Lazy proxy for THEMES dict."""
73 _cache: dict[str, ThemeValue] | None = None
75 def __getitem__(self, key: str) -> ThemeValue:
76 return get_all_themes()[key]
78 def __iter__(self) -> Iterator[str]:
79 return iter(get_all_themes())
81 def __len__(self) -> int:
82 return len(get_all_themes())
84 def keys(self) -> Any:
85 return get_all_themes().keys()
87 def values(self) -> Any:
88 return get_all_themes().values()
90 def items(self) -> Any:
91 return get_all_themes().items()
93 def get(self, key: str, default: ThemeValue | None = None) -> ThemeValue | None:
94 return get_all_themes().get(key, default)
97THEMES = _ThemesProxy()
100__all__ = [
101 "get_theme",
102 "get_all_themes",
103 "get_theme_ids",
104 "THEME_IDS",
105 "THEMES",
106 "ThemeValue",
107 "TurboThemes",
108]