Coverage for aipyapp/display/manager.py: 0%

1#!/usr/bin/env python

2# -*- coding: utf-8 -*-

3

4 import os

5 from typing import Dict, Type, Optional

6 from rich.console import Console

7

8 from loguru import logger

9

10 from .. import T

11 from .base import DisplayPlugin

12 from .themes import get_theme, THEMES

13

14 class DisplayManager:

15 """显示效果管理器"""

16

17 def __init__(self, display_config, console: Console = None, record: bool = True, quiet: bool = False):

18 """

19 Args:

20 console: 控制台对象

21 record: 是否记录输出，控制是否可以保存HTML文件

22 quiet: 是否安静模式，控制是否输出到控制台，不影响记录功能

23 display_config: display配置字典，包含style、theme等设置

24 """

25 # 处理display配置

26 config = display_config or {}

27 self.console = console

28 self.plugins = {}

29 self.style = config.get('style', 'classic')

30 self.theme = config.get('theme', 'default')

31 self.record = config.get('record', True)

32 self.quiet = config.get('quiet', False)

33 self._record_buffer = console._record_buffer[:] if console else []

34 self.logger = logger.bind(src='display_manager')

35 self.logger.info(f"DisplayManager initialized with style: {self.style}, theme: {self.theme}")

36

37 def set_style(self, style: str):

38 """设置显示风格"""

39 self.style = style

40 self.logger.info(f"Display style changed to: {self.style}")

41 return True

42

43 def get_available_styles(self) -> list:

44 """获取可用的显示风格列表"""

45 return [name for name in self.plugins.keys() if name not in ['null', 'agent']]

46

47 def get_available_themes(self) -> list:

48 """获取可用的主题列表"""

49 return list(THEMES.keys())

50

51 def create_display_plugin(self) -> Optional[DisplayPlugin]:

52 """获取当前显示插件"""

53 plugin_class = self.plugins[self.style]

54

55 if self.quiet:

56 if not self.record:

57 quiet = True

58 else:

59 quiet = False

60 file = open(os.devnull, 'w', encoding='utf-8')

61 else:

62 quiet = False

63 file = None

64

65 # 获取用户配置的主题

66 rich_theme = get_theme(self.theme)

67 console = Console(file=file, record=self.record, quiet=quiet, theme=rich_theme)

68 console._record_buffer.extend(self._record_buffer)

69 plugin = plugin_class(console, quiet=self.quiet)

70 try:

71 plugin.init()

72 except Exception as e:

73 self.logger.error(f"Failed to initialize display plugin {plugin_class.__name__}: {e}")

74 return None

75 return plugin

76

77 def register_plugin(self, plugin_class: Type[DisplayPlugin], name: str = None):

78 """注册新的显示效果插件"""

79 if name is None:

80 name = plugin_class.name or plugin_class.__class__.__name__

81

82 if name in self.plugins:

83 self.logger.warning(f"Display plugin {name} already registered")

84 return False

85

86 if not issubclass(plugin_class, DisplayPlugin):

87 self.logger.warning(f"Display plugin {name} is not a subclass of DisplayPlugin")

88 return False

89

90 self.plugins[name] = plugin_class

91 return True

92

93 def get_plugin_info(self) -> Dict[str, str]:

94 """获取插件信息"""

95 info = {}

96 for name, plugin_class in self.plugins.items():

97 info[name] = T(plugin_class.__doc__) or f"{name} display style"

98 return info

99

100