Coverage for aipyapp/display/manager.py: 0%
62 statements
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-11 12:02 +0200
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-11 12:02 +0200
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
4import os
5from typing import Dict, Type, Optional
6from rich.console import Console
8from loguru import logger
10from .. import T
11from .base import DisplayPlugin
12from .themes import get_theme, THEMES
14class DisplayManager:
15 """显示效果管理器"""
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}")
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
43 def get_available_styles(self) -> list:
44 """获取可用的显示风格列表"""
45 return [name for name in self.plugins.keys() if name not in ['null', 'agent']]
47 def get_available_themes(self) -> list:
48 """获取可用的主题列表"""
49 return list(THEMES.keys())
51 def create_display_plugin(self) -> Optional[DisplayPlugin]:
52 """获取当前显示插件"""
53 plugin_class = self.plugins[self.style]
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
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
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__
82 if name in self.plugins:
83 self.logger.warning(f"Display plugin {name} already registered")
84 return False
86 if not issubclass(plugin_class, DisplayPlugin):
87 self.logger.warning(f"Display plugin {name} is not a subclass of DisplayPlugin")
88 return False
90 self.plugins[name] = plugin_class
91 return True
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