Coverage for src/rtflite/services/text_conversion_service.py: 93%
46 statements
« prev ^ index » next coverage.py v7.10.5, created at 2025-08-25 22:35 +0000
« prev ^ index » next coverage.py v7.10.5, created at 2025-08-25 22:35 +0000
1"""
2Text conversion service for the RTF encoding pipeline.
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"""
9from collections.abc import Mapping, Sequence
11from ..text_conversion import LaTeXSymbolMapper, TextConverter
14class TextConversionService:
15 """
16 Service for handling text conversion operations in RTF documents.
18 This service provides a unified interface for text conversion that
19 can be used throughout the RTF encoding pipeline. It handles the
20 conversion of LaTeX commands to Unicode characters with proper
21 error handling and logging capabilities.
22 """
24 def __init__(self):
25 """Initialize the text conversion service."""
26 self.converter = TextConverter()
27 self.symbol_mapper = LaTeXSymbolMapper()
29 def convert_text_content(
30 self, text: str | Sequence[str] | None, enable_conversion: bool = True
31 ) -> str | Sequence[str] | None:
32 """
33 Convert text content with LaTeX commands to Unicode.
35 This method handles various text input formats commonly found
36 in RTF components and applies conversion consistently.
38 Args:
39 text: Text content to convert (string, list of strings, or None)
40 enable_conversion: Whether to enable LaTeX to Unicode conversion
42 Returns:
43 Converted text in the same format as input
45 Examples:
46 >>> service = TextConversionService()
47 >>> service.convert_text_content("\\alpha test", True)
48 "\\u03b1 test"
50 >>> service.convert_text_content(["\\alpha", "\\beta"], True)
51 ["\\u03b1", "\\u03b2"]
52 """
53 if not enable_conversion or text is None:
54 return text
56 if isinstance(text, str):
57 return self._convert_single_text(text)
58 elif isinstance(text, list):
59 return self._convert_text_list(text)
60 else:
61 # Handle other types by converting to string first
62 return self._convert_single_text(str(text))
64 def _convert_single_text(self, text: str) -> str:
65 """
66 Convert a single text string.
68 Args:
69 text: Text string to convert
71 Returns:
72 Converted text string
73 """
74 if not text:
75 return text
77 try:
78 return self.converter.convert_latex_to_unicode(text)
79 except Exception as e:
80 # Log the error but don't fail the conversion
81 # In a production environment, this would use proper logging
82 print(f"Warning: Text conversion failed for '{text}': {e}")
83 return text
85 def _convert_text_list(self, text_list: Sequence[str]) -> list[str]:
86 """
87 Convert a list of text strings.
89 Args:
90 text_list: List of text strings to convert
92 Returns:
93 List of converted text strings
94 """
95 return [self._convert_single_text(item) for item in text_list]
97 def get_supported_symbols(self) -> Sequence[str]:
98 """
99 Get a list of all supported LaTeX symbols.
101 Returns:
102 List of supported LaTeX commands
103 """
104 return self.symbol_mapper.get_all_supported_commands()
106 def get_symbol_categories(self) -> Mapping[str, Sequence[str]]:
107 """
108 Get LaTeX symbols organized by category.
110 Returns:
111 Dictionary mapping categories to symbol lists
112 """
113 return self.symbol_mapper.get_commands_by_category()
115 def validate_latex_commands(self, text: str) -> Mapping[str, object]:
116 """
117 Validate LaTeX commands in text and provide feedback.
119 This method analyzes text for LaTeX commands and reports
120 which ones will be converted and which ones are unsupported.
122 Args:
123 text: Text to validate
125 Returns:
126 Dictionary with validation results
127 """
128 if not text:
129 return {
130 "valid_commands": [],
131 "invalid_commands": [],
132 "validation_status": "empty_text",
133 }
135 stats = self.converter.get_conversion_statistics(text)
137 # Extract valid commands from the stats (need to get the actual converted commands)
138 import re
140 latex_pattern = re.compile(r"\\[a-zA-Z]+(?:\{[^}]*\})?")
141 all_commands = latex_pattern.findall(text)
143 valid_commands = []
144 for cmd in all_commands:
145 if self.symbol_mapper.has_mapping(cmd):
146 valid_commands.append(cmd)
148 return {
149 "valid_commands": valid_commands,
150 "invalid_commands": stats.get("unconverted", []),
151 "total_commands": stats.get("total_commands", 0),
152 "conversion_rate": stats.get("conversion_rate", 0),
153 "validation_status": "analyzed",
154 }
156 def convert_with_validation(
157 self, text: str, enable_conversion: bool = True
158 ) -> Mapping[str, object]:
159 """
160 Convert text and return both result and validation information.
162 This method provides comprehensive information about the conversion
163 process, useful for debugging and quality assurance.
165 Args:
166 text: Text to convert
167 enable_conversion: Whether to enable conversion
169 Returns:
170 Dictionary with converted text and validation info
171 """
172 if not enable_conversion:
173 return {
174 "original_text": text,
175 "converted_text": text,
176 "conversion_enabled": False,
177 "validation": {"status": "conversion_disabled"},
178 }
180 validation = self.validate_latex_commands(text)
181 converted_text = self.convert_text_content(text, enable_conversion)
183 return {
184 "original_text": text,
185 "converted_text": converted_text,
186 "conversion_enabled": True,
187 "validation": validation,
188 "conversion_applied": converted_text != text,
189 }