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

1# SPDX-License-Identifier: MIT 

2"""Theme registry for Turbo Themes. 

3 

4Provides runtime access to all theme definitions. 

5""" 

6 

7from __future__ import annotations 

8 

9import json 

10from pathlib import Path 

11from typing import Any, Iterator 

12 

13from .models import TurboThemes, ThemeValue, turbo_themes_from_dict 

14 

15# Load tokens at import time 

16_TOKENS_PATH = Path(__file__).parent / "tokens.json" 

17_tokens_data: TurboThemes | None = None 

18 

19 

20def _load_tokens() -> TurboThemes: 

21 """Load tokens from bundled JSON file. 

22 

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 

31 

32 

33def get_theme(theme_id: str) -> ThemeValue | None: 

34 """Get a theme by ID. 

35 

36 Args: 

37 theme_id: The theme identifier (e.g., 'dracula', 'catppuccin-mocha') 

38 

39 Returns: 

40 ThemeValue if found, None otherwise 

41 """ 

42 tokens = _load_tokens() 

43 return tokens.themes.get(theme_id) 

44 

45 

46def get_all_themes() -> dict[str, ThemeValue]: 

47 """Get all available themes. 

48 

49 Returns: 

50 Dict mapping theme IDs to ThemeValue objects 

51 """ 

52 return _load_tokens().themes 

53 

54 

55def get_theme_ids() -> list[str]: 

56 """Get list of all theme IDs. 

57 

58 Returns: 

59 List of theme ID strings 

60 """ 

61 return list(_load_tokens().themes.keys()) 

62 

63 

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) 

78 

79 

80# Lazy-loaded THEMES dict for backwards compatibility 

81class _ThemesProxy: 

82 """Lazy proxy for THEMES dict.""" 

83 

84 _cache: dict[str, ThemeValue] | None = None 

85 

86 def __getitem__(self, key: str) -> ThemeValue: 

87 return get_all_themes()[key] 

88 

89 def __iter__(self) -> Iterator[str]: 

90 return iter(get_all_themes()) 

91 

92 def __len__(self) -> int: 

93 return len(THEME_IDS) 

94 

95 def keys(self) -> Any: 

96 return get_all_themes().keys() 

97 

98 def values(self) -> Any: 

99 return get_all_themes().values() 

100 

101 def items(self) -> Any: 

102 return get_all_themes().items() 

103 

104 def get(self, key: str, default: ThemeValue | None = None) -> ThemeValue | None: 

105 return get_all_themes().get(key, default) 

106 

107 

108THEMES = _ThemesProxy() 

109 

110 

111__all__ = [ 

112 "get_theme", 

113 "get_all_themes", 

114 "get_theme_ids", 

115 "THEME_IDS", 

116 "THEMES", 

117 "ThemeValue", 

118 "TurboThemes", 

119]