Coverage for src/prosemark/templates/application/use_cases/create_from_template_use_case.py: 100%
68 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-09-30 23:09 +0000
« prev ^ index » next coverage.py v7.8.0, created at 2025-09-30 23:09 +0000
1"""Use case for creating content from templates."""
3from typing import Any
5from prosemark.templates.domain.exceptions.template_exceptions import (
6 InvalidPlaceholderError,
7 InvalidPlaceholderValueError,
8 PlaceholderProcessingError,
9 TemplateDirectoryNotFoundError,
10 TemplateNotFoundError,
11 TemplateParseError,
12 TemplateValidationError,
13 UserCancelledError,
14)
15from prosemark.templates.domain.services.template_service import TemplateService
18class CreateFromTemplateUseCase:
19 """Use case orchestrating template content creation."""
21 def __init__(self, template_service: TemplateService) -> None:
22 """Initialize use case with template service.
24 Args:
25 template_service: Service providing template operations
27 """
28 self._template_service = template_service
30 @staticmethod
31 def _raise_missing_placeholder_error(missing_placeholders: list[str]) -> None:
32 """Raise an error for missing placeholder values.
34 Args:
35 missing_placeholders: List of missing placeholder names
37 Raises:
38 InvalidPlaceholderValueError: Always raised with context
40 """
41 msg = f'Missing values for required placeholders: {", ".join(missing_placeholders)}'
42 raise InvalidPlaceholderValueError(
43 msg,
44 placeholder_name=missing_placeholders[0], # Use first for error context
45 )
47 def create_single_template(
48 self,
49 template_name: str,
50 placeholder_values: dict[str, str] | None = None,
51 *,
52 interactive: bool = True,
53 ) -> dict[str, Any]:
54 """Create content from a single template.
56 Args:
57 template_name: Name of template to use
58 placeholder_values: Optional predefined placeholder values
59 interactive: Whether to prompt user for missing values
61 Returns:
62 Dictionary containing generated content and metadata
64 """
65 try:
66 # Generate content using template service
67 if interactive:
68 content = self._template_service.create_from_template(template_name, placeholder_values)
69 else:
70 # In non-interactive mode, we must have all required values
71 template_info = self._template_service.get_template_info(template_name)
72 required_placeholders = template_info.get('required_placeholders', [])
74 provided_values = placeholder_values or {}
75 missing_placeholders = [name for name in required_placeholders if name not in provided_values]
77 if missing_placeholders:
78 CreateFromTemplateUseCase._raise_missing_placeholder_error(missing_placeholders)
79 else:
80 content = self._template_service.create_from_template(template_name, provided_values)
82 except (
83 TemplateNotFoundError,
84 InvalidPlaceholderValueError,
85 TemplateValidationError,
86 PlaceholderProcessingError,
87 UserCancelledError,
88 TemplateParseError,
89 InvalidPlaceholderError,
90 ) as e:
91 return {
92 'success': False,
93 'template_name': template_name,
94 'template_type': 'single',
95 'error': str(e),
96 'error_type': type(e).__name__,
97 }
98 else:
99 # Get template metadata
100 template_info = self._template_service.get_template_info(template_name)
102 return {
103 'success': True,
104 'template_name': template_name,
105 'template_type': 'single',
106 'content': content,
107 'metadata': template_info,
108 'placeholder_values': placeholder_values or {},
109 }
111 def create_directory_template(
112 self,
113 template_directory_name: str,
114 placeholder_values: dict[str, str] | None = None,
115 *,
116 interactive: bool = True,
117 ) -> dict[str, Any]:
118 """Create content from a directory template.
120 Args:
121 template_directory_name: Name of template directory to use
122 placeholder_values: Optional predefined placeholder values
123 interactive: Whether to prompt user for missing values
125 Returns:
126 Dictionary containing generated content and metadata
128 """
129 try:
130 # Generate content using template service
131 if interactive:
132 content_map = self._template_service.create_from_directory_template(
133 template_directory_name, placeholder_values
134 )
135 else:
136 # In non-interactive mode, we must have all required values
137 directory_info = self._template_service.get_directory_template_info(template_directory_name)
138 required_placeholders = directory_info.get('required_placeholders', [])
140 provided_values = placeholder_values or {}
141 missing_placeholders = [name for name in required_placeholders if name not in provided_values]
143 if missing_placeholders:
144 CreateFromTemplateUseCase._raise_missing_placeholder_error(missing_placeholders)
145 else:
146 content_map = self._template_service.create_from_directory_template(
147 template_directory_name, provided_values
148 )
150 except (
151 TemplateDirectoryNotFoundError,
152 InvalidPlaceholderValueError,
153 TemplateValidationError,
154 PlaceholderProcessingError,
155 UserCancelledError,
156 TemplateParseError,
157 InvalidPlaceholderError,
158 ) as e:
159 return {
160 'success': False,
161 'template_name': template_directory_name,
162 'template_type': 'directory',
163 'error': str(e),
164 'error_type': type(e).__name__,
165 }
166 else:
167 # Get directory metadata
168 directory_info = self._template_service.get_directory_template_info(template_directory_name)
170 return {
171 'success': True,
172 'template_name': template_directory_name,
173 'template_type': 'directory',
174 'content': content_map,
175 'file_count': len(content_map),
176 'metadata': directory_info,
177 'placeholder_values': placeholder_values or {},
178 }
180 def validate_template_before_creation(self, template_name: str) -> dict[str, Any]:
181 """Validate a template before attempting to create content from it.
183 Args:
184 template_name: Name of template to validate
186 Returns:
187 Dictionary containing validation results
189 """
190 try:
191 # Get template info to validate it exists and is valid
192 template_info = self._template_service.get_template_info(template_name)
194 except TemplateNotFoundError as e:
195 return {
196 'success': False,
197 'template_name': template_name,
198 'template_type': 'single',
199 'valid': False,
200 'error': str(e),
201 'error_type': type(e).__name__,
202 }
203 else:
204 # Check if it has placeholders that would require user input
205 required_placeholders = template_info.get('required_placeholders', [])
206 optional_placeholders = template_info.get('optional_placeholders', [])
207 placeholder_count = template_info.get('placeholder_count', 0)
209 return {
210 'success': True,
211 'template_name': template_name,
212 'template_type': 'single',
213 'valid': True,
214 'has_placeholders': placeholder_count > 0,
215 'required_placeholders': required_placeholders,
216 'optional_placeholders': optional_placeholders,
217 'placeholder_count': placeholder_count,
218 'metadata': template_info,
219 }
221 def validate_directory_template_before_creation(self, template_directory_name: str) -> dict[str, Any]:
222 """Validate a directory template before attempting to create content from it.
224 Args:
225 template_directory_name: Name of template directory to validate
227 Returns:
228 Dictionary containing validation results
230 """
231 try:
232 # Get directory info to validate it exists and is valid
233 directory_info = self._template_service.get_directory_template_info(template_directory_name)
235 # Check if it has placeholders that would require user input
236 required_placeholders = directory_info.get('required_placeholders', [])
237 optional_placeholders = directory_info.get('optional_placeholders', [])
238 template_count = directory_info.get('template_count', 0)
240 return {
241 'success': True,
242 'template_name': template_directory_name,
243 'template_type': 'directory',
244 'valid': True,
245 'template_count': template_count,
246 'required_placeholders': required_placeholders,
247 'optional_placeholders': optional_placeholders,
248 'shared_placeholders': directory_info.get('shared_placeholders', []),
249 'metadata': directory_info,
250 }
252 except TemplateDirectoryNotFoundError as e:
253 return {
254 'success': False,
255 'template_name': template_directory_name,
256 'template_type': 'directory',
257 'valid': False,
258 'error': str(e),
259 'error_type': type(e).__name__,
260 }
262 def get_template_preview(
263 self,
264 template_name: str,
265 placeholder_values: dict[str, str] | None = None,
266 ) -> dict[str, Any]:
267 """Get a preview of what would be generated from a template.
269 Args:
270 template_name: Name of template to preview
271 placeholder_values: Optional placeholder values for preview
273 Returns:
274 Dictionary containing preview information
276 """
277 try:
278 # Get template info
279 template_info = self._template_service.get_template_info(template_name)
281 # Identify what placeholders would need values
282 required_placeholders = template_info.get('required_placeholders', [])
283 optional_placeholders = template_info.get('optional_placeholders', [])
284 provided_values = placeholder_values or {}
286 missing_required = [name for name in required_placeholders if name not in provided_values]
288 return {
289 'success': True,
290 'template_name': template_name,
291 'template_type': 'single',
292 'can_generate': len(missing_required) == 0,
293 'missing_required_placeholders': missing_required,
294 'provided_placeholders': list(provided_values.keys()),
295 'all_required_placeholders': required_placeholders,
296 'all_optional_placeholders': optional_placeholders,
297 'placeholder_values': provided_values,
298 'metadata': template_info,
299 }
301 except TemplateNotFoundError as e:
302 return {
303 'success': False,
304 'template_name': template_name,
305 'template_type': 'single',
306 'error': str(e),
307 'error_type': type(e).__name__,
308 }