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

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 derived from tokens.json — always in sync 

65# Preserves canonical vendor-grouped ordering from tokens.json 

66THEME_IDS: tuple[str, ...] = tuple(get_theme_ids()) 

67 

68 

69# Lazy-loaded THEMES dict for backwards compatibility 

70class _ThemesProxy: 

71 """Lazy proxy for THEMES dict.""" 

72 

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

74 

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

76 return get_all_themes()[key] 

77 

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

79 return iter(get_all_themes()) 

80 

81 def __len__(self) -> int: 

82 return len(get_all_themes()) 

83 

84 def keys(self) -> Any: 

85 return get_all_themes().keys() 

86 

87 def values(self) -> Any: 

88 return get_all_themes().values() 

89 

90 def items(self) -> Any: 

91 return get_all_themes().items() 

92 

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

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

95 

96 

97THEMES = _ThemesProxy() 

98 

99 

100__all__ = [ 

101 "get_theme", 

102 "get_all_themes", 

103 "get_theme_ids", 

104 "THEME_IDS", 

105 "THEMES", 

106 "ThemeValue", 

107 "TurboThemes", 

108]