Coverage for src/rtflite/services/text_conversion_service.py: 93%

45 statements  

« prev     ^ index     » next       coverage.py v7.10.3, created at 2025-08-14 16:35 +0000

1""" 

2Text conversion service for the RTF encoding pipeline. 

3 

4This service provides a clean interface for text conversion operations 

5within the RTF document generation process. It integrates the text 

6conversion functionality with the broader service architecture. 

7""" 

8 

9from ..text_conversion import LaTeXSymbolMapper, TextConverter 

10 

11 

12class TextConversionService: 

13 """ 

14 Service for handling text conversion operations in RTF documents. 

15 

16 This service provides a unified interface for text conversion that 

17 can be used throughout the RTF encoding pipeline. It handles the 

18 conversion of LaTeX commands to Unicode characters with proper 

19 error handling and logging capabilities. 

20 """ 

21 

22 def __init__(self): 

23 """Initialize the text conversion service.""" 

24 self.converter = TextConverter() 

25 self.symbol_mapper = LaTeXSymbolMapper() 

26 

27 def convert_text_content( 

28 self, text: str | list[str] | None, enable_conversion: bool = True 

29 ) -> str | list[str] | None: 

30 """ 

31 Convert text content with LaTeX commands to Unicode. 

32 

33 This method handles various text input formats commonly found 

34 in RTF components and applies conversion consistently. 

35 

36 Args: 

37 text: Text content to convert (string, list of strings, or None) 

38 enable_conversion: Whether to enable LaTeX to Unicode conversion 

39 

40 Returns: 

41 Converted text in the same format as input 

42 

43 Examples: 

44 >>> service = TextConversionService() 

45 >>> service.convert_text_content("\\alpha test", True) 

46 "\\u03b1 test" 

47 

48 >>> service.convert_text_content(["\\alpha", "\\beta"], True) 

49 ["\\u03b1", "\\u03b2"] 

50 """ 

51 if not enable_conversion or text is None: 

52 return text 

53 

54 if isinstance(text, str): 

55 return self._convert_single_text(text) 

56 elif isinstance(text, list): 

57 return self._convert_text_list(text) 

58 else: 

59 # Handle other types by converting to string first 

60 return self._convert_single_text(str(text)) 

61 

62 def _convert_single_text(self, text: str) -> str: 

63 """ 

64 Convert a single text string. 

65 

66 Args: 

67 text: Text string to convert 

68 

69 Returns: 

70 Converted text string 

71 """ 

72 if not text: 

73 return text 

74 

75 try: 

76 return self.converter.convert_latex_to_unicode(text) 

77 except Exception as e: 

78 # Log the error but don't fail the conversion 

79 # In a production environment, this would use proper logging 

80 print(f"Warning: Text conversion failed for '{text}': {e}") 

81 return text 

82 

83 def _convert_text_list(self, text_list: list[str]) -> list[str]: 

84 """ 

85 Convert a list of text strings. 

86 

87 Args: 

88 text_list: List of text strings to convert 

89 

90 Returns: 

91 List of converted text strings 

92 """ 

93 return [self._convert_single_text(item) for item in text_list] 

94 

95 def get_supported_symbols(self) -> list[str]: 

96 """ 

97 Get a list of all supported LaTeX symbols. 

98 

99 Returns: 

100 List of supported LaTeX commands 

101 """ 

102 return self.symbol_mapper.get_all_supported_commands() 

103 

104 def get_symbol_categories(self) -> dict: 

105 """ 

106 Get LaTeX symbols organized by category. 

107 

108 Returns: 

109 Dictionary mapping categories to symbol lists 

110 """ 

111 return self.symbol_mapper.get_commands_by_category() 

112 

113 def validate_latex_commands(self, text: str) -> dict: 

114 """ 

115 Validate LaTeX commands in text and provide feedback. 

116 

117 This method analyzes text for LaTeX commands and reports 

118 which ones will be converted and which ones are unsupported. 

119 

120 Args: 

121 text: Text to validate 

122 

123 Returns: 

124 Dictionary with validation results 

125 """ 

126 if not text: 

127 return { 

128 "valid_commands": [], 

129 "invalid_commands": [], 

130 "validation_status": "empty_text", 

131 } 

132 

133 stats = self.converter.get_conversion_statistics(text) 

134 

135 # Extract valid commands from the stats (need to get the actual converted commands) 

136 import re 

137 

138 latex_pattern = re.compile(r"\\[a-zA-Z]+(?:\{[^}]*\})?") 

139 all_commands = latex_pattern.findall(text) 

140 

141 valid_commands = [] 

142 for cmd in all_commands: 

143 if self.symbol_mapper.has_mapping(cmd): 

144 valid_commands.append(cmd) 

145 

146 return { 

147 "valid_commands": valid_commands, 

148 "invalid_commands": stats.get("unconverted", []), 

149 "total_commands": stats.get("total_commands", 0), 

150 "conversion_rate": stats.get("conversion_rate", 0), 

151 "validation_status": "analyzed", 

152 } 

153 

154 def convert_with_validation( 

155 self, text: str, enable_conversion: bool = True 

156 ) -> dict: 

157 """ 

158 Convert text and return both result and validation information. 

159 

160 This method provides comprehensive information about the conversion 

161 process, useful for debugging and quality assurance. 

162 

163 Args: 

164 text: Text to convert 

165 enable_conversion: Whether to enable conversion 

166 

167 Returns: 

168 Dictionary with converted text and validation info 

169 """ 

170 if not enable_conversion: 

171 return { 

172 "original_text": text, 

173 "converted_text": text, 

174 "conversion_enabled": False, 

175 "validation": {"status": "conversion_disabled"}, 

176 } 

177 

178 validation = self.validate_latex_commands(text) 

179 converted_text = self.convert_text_content(text, enable_conversion) 

180 

181 return { 

182 "original_text": text, 

183 "converted_text": converted_text, 

184 "conversion_enabled": True, 

185 "validation": validation, 

186 "conversion_applied": converted_text != text, 

187 }