auto-coder 0.1.327__py3-none-any.whl → 0.1.329__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of auto-coder might be problematic. Click here for more details.
- {auto_coder-0.1.327.dist-info → auto_coder-0.1.329.dist-info}/METADATA +1 -1
- {auto_coder-0.1.327.dist-info → auto_coder-0.1.329.dist-info}/RECORD +27 -15
- autocoder/auto_coder_runner.py +1 -1
- autocoder/common/__init__.py +5 -0
- autocoder/common/auto_coder_lang.py +16 -0
- autocoder/common/stream_out_type.py +3 -0
- autocoder/common/v2/code_editblock_manager.py +92 -8
- autocoder/compilers/__init__.py +51 -0
- autocoder/compilers/base_compiler.py +107 -0
- autocoder/compilers/compiler_config_api.py +365 -0
- autocoder/compilers/compiler_config_manager.py +305 -0
- autocoder/compilers/compiler_factory.py +271 -0
- autocoder/compilers/java_compiler.py +680 -0
- autocoder/compilers/models.py +210 -0
- autocoder/compilers/provided_compiler.py +343 -0
- autocoder/compilers/python_compiler.py +413 -0
- autocoder/compilers/reactjs_compiler.py +491 -0
- autocoder/compilers/shadow_compiler.py +42 -0
- autocoder/compilers/vue_compiler.py +548 -0
- autocoder/memory/active_context_manager.py +3 -3
- autocoder/memory/active_package.py +2 -2
- autocoder/shadows/shadow_manager.py +251 -4
- autocoder/version.py +1 -1
- {auto_coder-0.1.327.dist-info → auto_coder-0.1.329.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.327.dist-info → auto_coder-0.1.329.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.327.dist-info → auto_coder-0.1.329.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.327.dist-info → auto_coder-0.1.329.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Module providing a high-level API for managing compiler.yml configurations.
|
|
3
|
+
This module offers functions to create, retrieve, update, and delete compiler configurations
|
|
4
|
+
through a simple API interface that can be used in web services or other applications.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import yaml
|
|
9
|
+
from typing import Dict, List, Any, Optional, Tuple, Union
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from autocoder.compilers.compiler_config_manager import CompilerConfigManager, get_compiler_config_manager
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class CompilerConfigAPI:
|
|
16
|
+
"""
|
|
17
|
+
A high-level API for managing compiler configurations through a service interface.
|
|
18
|
+
This class simplifies interacting with compiler.yml files and provides standardized
|
|
19
|
+
response formats suitable for API endpoints.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, config_path: Optional[str] = None):
|
|
23
|
+
"""
|
|
24
|
+
Initialize the CompilerConfigAPI.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
config_path (Optional[str]): Path to the compiler.yml file.
|
|
28
|
+
If None, will use .auto-coder/projects/compiler.yml.
|
|
29
|
+
"""
|
|
30
|
+
self.config_manager = get_compiler_config_manager(config_path)
|
|
31
|
+
|
|
32
|
+
def create_compiler(self,
|
|
33
|
+
name: str,
|
|
34
|
+
compiler_type: str,
|
|
35
|
+
triggers: List[str],
|
|
36
|
+
working_dir: str,
|
|
37
|
+
command: str,
|
|
38
|
+
args: List[str],
|
|
39
|
+
extract_regex: Optional[str] = None) -> Dict[str, Any]:
|
|
40
|
+
"""
|
|
41
|
+
Create a new compiler configuration.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
name (str): Name of the compiler.
|
|
45
|
+
compiler_type (str): Type of the compiler (e.g., 'frontend', 'backend').
|
|
46
|
+
working_dir (str): Working directory for the compiler.
|
|
47
|
+
command (str): The command to run.
|
|
48
|
+
args (List[str]): List of arguments for the command.
|
|
49
|
+
extract_regex (Optional[str]): Regular expression to extract error information.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
Dict[str, Any]: API response with status and result information.
|
|
53
|
+
"""
|
|
54
|
+
try:
|
|
55
|
+
# Validate inputs
|
|
56
|
+
if not name or not name.strip():
|
|
57
|
+
return self._error_response("Compiler name cannot be empty")
|
|
58
|
+
|
|
59
|
+
if not command or not command.strip():
|
|
60
|
+
return self._error_response("Command cannot be empty")
|
|
61
|
+
|
|
62
|
+
# Create compiler config
|
|
63
|
+
compiler_config = self.config_manager.create_compiler_config(
|
|
64
|
+
name=name,
|
|
65
|
+
type=compiler_type,
|
|
66
|
+
working_dir=working_dir,
|
|
67
|
+
command=command,
|
|
68
|
+
args=args,
|
|
69
|
+
triggers=triggers,
|
|
70
|
+
extract_regex=extract_regex
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# Add it to the configuration
|
|
74
|
+
success = self.config_manager.add_compiler(compiler_config)
|
|
75
|
+
|
|
76
|
+
if success:
|
|
77
|
+
return {
|
|
78
|
+
"status": "success",
|
|
79
|
+
"message": f"Compiler '{name}' created successfully",
|
|
80
|
+
"data": compiler_config
|
|
81
|
+
}
|
|
82
|
+
else:
|
|
83
|
+
return self._error_response(f"Failed to create compiler '{name}'")
|
|
84
|
+
|
|
85
|
+
except ValueError as e:
|
|
86
|
+
return self._error_response(str(e))
|
|
87
|
+
except Exception as e:
|
|
88
|
+
return self._error_response(f"Unexpected error: {str(e)}")
|
|
89
|
+
|
|
90
|
+
def get_compiler(self, name: str) -> Dict[str, Any]:
|
|
91
|
+
"""
|
|
92
|
+
Get a specific compiler configuration.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
name (str): Name of the compiler to retrieve.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
Dict[str, Any]: API response with status and compiler configuration.
|
|
99
|
+
"""
|
|
100
|
+
try:
|
|
101
|
+
compiler_config = self.config_manager.get_compiler_by_name(name)
|
|
102
|
+
|
|
103
|
+
if compiler_config:
|
|
104
|
+
return {
|
|
105
|
+
"status": "success",
|
|
106
|
+
"data": compiler_config
|
|
107
|
+
}
|
|
108
|
+
else:
|
|
109
|
+
return self._error_response(f"Compiler '{name}' not found", status_code=404)
|
|
110
|
+
|
|
111
|
+
except FileNotFoundError:
|
|
112
|
+
return self._error_response("Configuration file not found", status_code=404)
|
|
113
|
+
except Exception as e:
|
|
114
|
+
return self._error_response(f"Unexpected error: {str(e)}")
|
|
115
|
+
|
|
116
|
+
def list_compilers(self) -> Dict[str, Any]:
|
|
117
|
+
"""
|
|
118
|
+
List all compiler configurations.
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
Dict[str, Any]: API response with status and list of compilers.
|
|
122
|
+
"""
|
|
123
|
+
try:
|
|
124
|
+
compilers = self.config_manager.get_all_compilers()
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
"status": "success",
|
|
128
|
+
"data": compilers,
|
|
129
|
+
"count": len(compilers)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
except FileNotFoundError:
|
|
133
|
+
# Return empty list if file doesn't exist
|
|
134
|
+
return {
|
|
135
|
+
"status": "success",
|
|
136
|
+
"data": [],
|
|
137
|
+
"count": 0
|
|
138
|
+
}
|
|
139
|
+
except Exception as e:
|
|
140
|
+
return self._error_response(f"Unexpected error: {str(e)}")
|
|
141
|
+
|
|
142
|
+
def update_compiler(self,
|
|
143
|
+
name: str,
|
|
144
|
+
compiler_type: Optional[str] = None,
|
|
145
|
+
working_dir: Optional[str] = None,
|
|
146
|
+
command: Optional[str] = None,
|
|
147
|
+
args: Optional[List[str]] = None,
|
|
148
|
+
triggers: Optional[List[str]] = None,
|
|
149
|
+
extract_regex: Optional[str] = None) -> Dict[str, Any]:
|
|
150
|
+
"""
|
|
151
|
+
Update an existing compiler configuration.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
name (str): Name of the compiler to update.
|
|
155
|
+
compiler_type (Optional[str]): Type of the compiler.
|
|
156
|
+
working_dir (Optional[str]): Working directory for the compiler.
|
|
157
|
+
command (Optional[str]): The command to run.
|
|
158
|
+
args (Optional[List[str]]): List of arguments for the command.
|
|
159
|
+
extract_regex (Optional[str]): Regular expression to extract error information.
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
Dict[str, Any]: API response with status and result information.
|
|
163
|
+
"""
|
|
164
|
+
try:
|
|
165
|
+
# Get existing compiler
|
|
166
|
+
existing_config = self.config_manager.get_compiler_by_name(name)
|
|
167
|
+
if not existing_config:
|
|
168
|
+
return self._error_response(f"Compiler '{name}' not found", status_code=404)
|
|
169
|
+
|
|
170
|
+
# Create updated config by merging with existing values
|
|
171
|
+
updated_config = existing_config.copy()
|
|
172
|
+
|
|
173
|
+
if compiler_type is not None:
|
|
174
|
+
updated_config["type"] = compiler_type
|
|
175
|
+
|
|
176
|
+
if working_dir is not None:
|
|
177
|
+
updated_config["working_dir"] = working_dir
|
|
178
|
+
|
|
179
|
+
if command is not None:
|
|
180
|
+
updated_config["command"] = command
|
|
181
|
+
|
|
182
|
+
if args is not None:
|
|
183
|
+
updated_config["args"] = args
|
|
184
|
+
|
|
185
|
+
if extract_regex is not None:
|
|
186
|
+
updated_config["extract_regex"] = extract_regex
|
|
187
|
+
|
|
188
|
+
if triggers is not None:
|
|
189
|
+
updated_config["triggers"] = triggers
|
|
190
|
+
|
|
191
|
+
# Update the configuration
|
|
192
|
+
success = self.config_manager.update_compiler(name, updated_config)
|
|
193
|
+
|
|
194
|
+
if success:
|
|
195
|
+
return {
|
|
196
|
+
"status": "success",
|
|
197
|
+
"message": f"Compiler '{name}' updated successfully",
|
|
198
|
+
"data": updated_config
|
|
199
|
+
}
|
|
200
|
+
else:
|
|
201
|
+
return self._error_response(f"Failed to update compiler '{name}'")
|
|
202
|
+
|
|
203
|
+
except ValueError as e:
|
|
204
|
+
return self._error_response(str(e))
|
|
205
|
+
except FileNotFoundError:
|
|
206
|
+
return self._error_response("Configuration file not found", status_code=404)
|
|
207
|
+
except Exception as e:
|
|
208
|
+
return self._error_response(f"Unexpected error: {str(e)}")
|
|
209
|
+
|
|
210
|
+
def delete_compiler(self, name: str) -> Dict[str, Any]:
|
|
211
|
+
"""
|
|
212
|
+
Delete a compiler configuration.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
name (str): Name of the compiler to delete.
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
Dict[str, Any]: API response with status and result information.
|
|
219
|
+
"""
|
|
220
|
+
try:
|
|
221
|
+
success = self.config_manager.delete_compiler(name)
|
|
222
|
+
|
|
223
|
+
if success:
|
|
224
|
+
return {
|
|
225
|
+
"status": "success",
|
|
226
|
+
"message": f"Compiler '{name}' deleted successfully"
|
|
227
|
+
}
|
|
228
|
+
else:
|
|
229
|
+
return self._error_response(f"Failed to delete compiler '{name}'")
|
|
230
|
+
|
|
231
|
+
except ValueError as e:
|
|
232
|
+
return self._error_response(str(e))
|
|
233
|
+
except FileNotFoundError:
|
|
234
|
+
return self._error_response("Configuration file not found", status_code=404)
|
|
235
|
+
except Exception as e:
|
|
236
|
+
return self._error_response(f"Unexpected error: {str(e)}")
|
|
237
|
+
|
|
238
|
+
def initialize_config(self) -> Dict[str, Any]:
|
|
239
|
+
"""
|
|
240
|
+
Initialize a default compiler configuration file if it doesn't exist.
|
|
241
|
+
|
|
242
|
+
Returns:
|
|
243
|
+
Dict[str, Any]: API response with status and result information.
|
|
244
|
+
"""
|
|
245
|
+
try:
|
|
246
|
+
if self.config_manager.exists():
|
|
247
|
+
return {
|
|
248
|
+
"status": "success",
|
|
249
|
+
"message": "Configuration file already exists",
|
|
250
|
+
"data": self.config_manager.get_all_compilers()
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
success = self.config_manager.init_default_config()
|
|
254
|
+
|
|
255
|
+
if success:
|
|
256
|
+
return {
|
|
257
|
+
"status": "success",
|
|
258
|
+
"message": "Configuration file initialized with default settings",
|
|
259
|
+
"data": self.config_manager.get_all_compilers()
|
|
260
|
+
}
|
|
261
|
+
else:
|
|
262
|
+
return self._error_response("Failed to initialize configuration file")
|
|
263
|
+
|
|
264
|
+
except Exception as e:
|
|
265
|
+
return self._error_response(f"Unexpected error: {str(e)}")
|
|
266
|
+
|
|
267
|
+
def validate_config(self) -> Dict[str, Any]:
|
|
268
|
+
"""
|
|
269
|
+
Validate the structure of the compiler.yml file.
|
|
270
|
+
|
|
271
|
+
Returns:
|
|
272
|
+
Dict[str, Any]: API response with validation results.
|
|
273
|
+
"""
|
|
274
|
+
try:
|
|
275
|
+
if not self.config_manager.exists():
|
|
276
|
+
return self._error_response("Configuration file does not exist", status_code=404)
|
|
277
|
+
|
|
278
|
+
config = self.config_manager.read()
|
|
279
|
+
|
|
280
|
+
# Check if compilers section exists
|
|
281
|
+
if "compilers" not in config:
|
|
282
|
+
return self._error_response("Invalid configuration: missing 'compilers' section")
|
|
283
|
+
|
|
284
|
+
if not isinstance(config["compilers"], list):
|
|
285
|
+
return self._error_response("Invalid configuration: 'compilers' must be a list")
|
|
286
|
+
|
|
287
|
+
# Validate each compiler
|
|
288
|
+
validation_errors = []
|
|
289
|
+
for i, compiler in enumerate(config["compilers"]):
|
|
290
|
+
errors = self._validate_compiler_config(compiler, i)
|
|
291
|
+
validation_errors.extend(errors)
|
|
292
|
+
|
|
293
|
+
if validation_errors:
|
|
294
|
+
return {
|
|
295
|
+
"status": "error",
|
|
296
|
+
"message": "Configuration validation failed",
|
|
297
|
+
"errors": validation_errors
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return {
|
|
301
|
+
"status": "success",
|
|
302
|
+
"message": "Configuration validation passed",
|
|
303
|
+
"data": config
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
except yaml.YAMLError:
|
|
307
|
+
return self._error_response("Invalid YAML format in configuration file")
|
|
308
|
+
except Exception as e:
|
|
309
|
+
return self._error_response(f"Unexpected error: {str(e)}")
|
|
310
|
+
|
|
311
|
+
def _validate_compiler_config(self, compiler: Dict[str, Any], index: int) -> List[str]:
|
|
312
|
+
"""
|
|
313
|
+
Validate an individual compiler configuration.
|
|
314
|
+
|
|
315
|
+
Args:
|
|
316
|
+
compiler (Dict[str, Any]): The compiler configuration to validate.
|
|
317
|
+
index (int): Index of the compiler in the list (for error reporting).
|
|
318
|
+
|
|
319
|
+
Returns:
|
|
320
|
+
List[str]: List of validation error messages.
|
|
321
|
+
"""
|
|
322
|
+
errors = []
|
|
323
|
+
|
|
324
|
+
# Check required fields
|
|
325
|
+
if "name" not in compiler or not compiler["name"]:
|
|
326
|
+
errors.append(f"Compiler at index {index}: missing or empty 'name' field")
|
|
327
|
+
|
|
328
|
+
if "command" not in compiler or not compiler["command"]:
|
|
329
|
+
errors.append(f"Compiler '{compiler.get('name', f'at index {index}')}': missing or empty 'command' field")
|
|
330
|
+
|
|
331
|
+
# Check args is a list
|
|
332
|
+
if "args" in compiler and not isinstance(compiler["args"], list):
|
|
333
|
+
errors.append(f"Compiler '{compiler.get('name', f'at index {index}')}': 'args' must be a list")
|
|
334
|
+
|
|
335
|
+
return errors
|
|
336
|
+
|
|
337
|
+
def _error_response(self, message: str, status_code: int = 400) -> Dict[str, Any]:
|
|
338
|
+
"""
|
|
339
|
+
Create a standardized error response.
|
|
340
|
+
|
|
341
|
+
Args:
|
|
342
|
+
message (str): Error message.
|
|
343
|
+
status_code (int): HTTP-like status code.
|
|
344
|
+
|
|
345
|
+
Returns:
|
|
346
|
+
Dict[str, Any]: Standardized error response.
|
|
347
|
+
"""
|
|
348
|
+
return {
|
|
349
|
+
"status": "error",
|
|
350
|
+
"message": message,
|
|
351
|
+
"code": status_code
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def get_compiler_config_api(config_path: Optional[str] = None) -> CompilerConfigAPI:
|
|
356
|
+
"""
|
|
357
|
+
Factory function to get a CompilerConfigAPI instance.
|
|
358
|
+
|
|
359
|
+
Args:
|
|
360
|
+
config_path (Optional[str]): Path to the compiler.yml file.
|
|
361
|
+
|
|
362
|
+
Returns:
|
|
363
|
+
CompilerConfigAPI: An instance of the CompilerConfigAPI.
|
|
364
|
+
"""
|
|
365
|
+
return CompilerConfigAPI(config_path=config_path)
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Module providing utilities for managing compiler.yml configuration files.
|
|
3
|
+
This module offers functions to read, write, add, update, delete, and query compiler configurations.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import yaml
|
|
8
|
+
from typing import Dict, List, Any, Optional, Union
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class CompilerConfigManager:
|
|
13
|
+
"""
|
|
14
|
+
A utility class for managing compiler configuration files (compiler.yml).
|
|
15
|
+
Provides methods to read, write, add, modify, delete, and query compiler configurations.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, config_path: Optional[str] = None):
|
|
19
|
+
"""
|
|
20
|
+
Initialize the CompilerConfigManager.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
config_path (Optional[str]): Path to the compiler.yml file.
|
|
24
|
+
If None, will use .auto-coder/projects/compiler.yml.
|
|
25
|
+
"""
|
|
26
|
+
self.config_path = config_path or ".auto-coder/projects/compiler.yml"
|
|
27
|
+
|
|
28
|
+
def exists(self) -> bool:
|
|
29
|
+
"""
|
|
30
|
+
Check if the configuration file exists.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
bool: True if the configuration file exists, False otherwise.
|
|
34
|
+
"""
|
|
35
|
+
return os.path.exists(self.config_path)
|
|
36
|
+
|
|
37
|
+
def read(self) -> Dict[str, Any]:
|
|
38
|
+
"""
|
|
39
|
+
Read the compiler configuration from YAML file.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
Dict[str, Any]: The compiler configuration as a dictionary.
|
|
43
|
+
|
|
44
|
+
Raises:
|
|
45
|
+
FileNotFoundError: If the configuration file doesn't exist.
|
|
46
|
+
yaml.YAMLError: If the YAML file is invalid.
|
|
47
|
+
"""
|
|
48
|
+
if not self.exists():
|
|
49
|
+
raise FileNotFoundError(f"Configuration file not found: {self.config_path}")
|
|
50
|
+
|
|
51
|
+
with open(self.config_path, 'r', encoding='utf-8') as f:
|
|
52
|
+
config = yaml.safe_load(f)
|
|
53
|
+
|
|
54
|
+
# Ensure the config has a compilers section
|
|
55
|
+
if config is None:
|
|
56
|
+
config = {"compilers": []}
|
|
57
|
+
elif "compilers" not in config:
|
|
58
|
+
config["compilers"] = []
|
|
59
|
+
|
|
60
|
+
return config
|
|
61
|
+
|
|
62
|
+
def write(self, config: Dict[str, Any]) -> bool:
|
|
63
|
+
"""
|
|
64
|
+
Write a compiler configuration to the YAML file.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
config (Dict[str, Any]): The compiler configuration to write.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
bool: True if the write operation was successful, False otherwise.
|
|
71
|
+
"""
|
|
72
|
+
try:
|
|
73
|
+
# Ensure directory exists
|
|
74
|
+
os.makedirs(os.path.dirname(os.path.abspath(self.config_path)), exist_ok=True)
|
|
75
|
+
|
|
76
|
+
with open(self.config_path, 'w', encoding='utf-8') as f:
|
|
77
|
+
yaml.dump(config, f, allow_unicode=True, default_flow_style=False)
|
|
78
|
+
return True
|
|
79
|
+
except Exception:
|
|
80
|
+
return False
|
|
81
|
+
|
|
82
|
+
def get_all_compilers(self) -> List[Dict[str, Any]]:
|
|
83
|
+
"""
|
|
84
|
+
Get all compiler configurations from the file.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
List[Dict[str, Any]]: List of all compiler configurations.
|
|
88
|
+
|
|
89
|
+
Raises:
|
|
90
|
+
FileNotFoundError: If the configuration file doesn't exist.
|
|
91
|
+
"""
|
|
92
|
+
config = self.read()
|
|
93
|
+
return config.get("compilers", [])
|
|
94
|
+
|
|
95
|
+
def get_compiler_by_name(self, name: str) -> Optional[Dict[str, Any]]:
|
|
96
|
+
"""
|
|
97
|
+
Get a specific compiler configuration by name.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
name (str): The name of the compiler to find.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Optional[Dict[str, Any]]: The compiler configuration if found, None otherwise.
|
|
104
|
+
|
|
105
|
+
Raises:
|
|
106
|
+
FileNotFoundError: If the configuration file doesn't exist.
|
|
107
|
+
"""
|
|
108
|
+
compilers = self.get_all_compilers()
|
|
109
|
+
for compiler in compilers:
|
|
110
|
+
if compiler.get("name") == name:
|
|
111
|
+
return compiler
|
|
112
|
+
return None
|
|
113
|
+
|
|
114
|
+
def add_compiler(self, compiler_config: Dict[str, Any]) -> bool:
|
|
115
|
+
"""
|
|
116
|
+
Add a new compiler configuration to the file.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
compiler_config (Dict[str, Any]): The compiler configuration to add.
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
bool: True if the operation was successful, False otherwise.
|
|
123
|
+
|
|
124
|
+
Raises:
|
|
125
|
+
ValueError: If a compiler with the same name already exists.
|
|
126
|
+
FileNotFoundError: If the configuration file doesn't exist and couldn't be created.
|
|
127
|
+
"""
|
|
128
|
+
name = compiler_config.get("name")
|
|
129
|
+
if not name:
|
|
130
|
+
raise ValueError("Compiler configuration must have a 'name' field")
|
|
131
|
+
|
|
132
|
+
try:
|
|
133
|
+
# Try to read existing config or create a new one
|
|
134
|
+
try:
|
|
135
|
+
config = self.read()
|
|
136
|
+
except FileNotFoundError:
|
|
137
|
+
config = {"compilers": []}
|
|
138
|
+
|
|
139
|
+
# Check if a compiler with this name already exists
|
|
140
|
+
for existing in config.get("compilers", []):
|
|
141
|
+
if existing.get("name") == name:
|
|
142
|
+
raise ValueError(f"A compiler with name '{name}' already exists")
|
|
143
|
+
|
|
144
|
+
# Add the new compiler config
|
|
145
|
+
config["compilers"].append(compiler_config)
|
|
146
|
+
|
|
147
|
+
# Write back to file
|
|
148
|
+
return self.write(config)
|
|
149
|
+
except Exception:
|
|
150
|
+
return False
|
|
151
|
+
|
|
152
|
+
def update_compiler(self, name: str, updated_config: Dict[str, Any]) -> bool:
|
|
153
|
+
"""
|
|
154
|
+
Update an existing compiler configuration.
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
name (str): The name of the compiler to update.
|
|
158
|
+
updated_config (Dict[str, Any]): The updated compiler configuration.
|
|
159
|
+
|
|
160
|
+
Returns:
|
|
161
|
+
bool: True if the operation was successful, False otherwise.
|
|
162
|
+
|
|
163
|
+
Raises:
|
|
164
|
+
ValueError: If no compiler with the given name exists.
|
|
165
|
+
FileNotFoundError: If the configuration file doesn't exist.
|
|
166
|
+
"""
|
|
167
|
+
try:
|
|
168
|
+
config = self.read()
|
|
169
|
+
found = False
|
|
170
|
+
|
|
171
|
+
# Update the compiler with matching name
|
|
172
|
+
for i, compiler in enumerate(config.get("compilers", [])):
|
|
173
|
+
if compiler.get("name") == name:
|
|
174
|
+
# Preserve the original name
|
|
175
|
+
updated_config["name"] = name
|
|
176
|
+
config["compilers"][i] = updated_config
|
|
177
|
+
found = True
|
|
178
|
+
break
|
|
179
|
+
|
|
180
|
+
if not found:
|
|
181
|
+
raise ValueError(f"No compiler with name '{name}' found")
|
|
182
|
+
|
|
183
|
+
# Write back to file
|
|
184
|
+
return self.write(config)
|
|
185
|
+
except Exception:
|
|
186
|
+
return False
|
|
187
|
+
|
|
188
|
+
def delete_compiler(self, name: str) -> bool:
|
|
189
|
+
"""
|
|
190
|
+
Delete a compiler configuration from the file.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
name (str): The name of the compiler to delete.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
bool: True if the operation was successful, False otherwise.
|
|
197
|
+
|
|
198
|
+
Raises:
|
|
199
|
+
ValueError: If no compiler with the given name exists.
|
|
200
|
+
FileNotFoundError: If the configuration file doesn't exist.
|
|
201
|
+
"""
|
|
202
|
+
try:
|
|
203
|
+
config = self.read()
|
|
204
|
+
original_length = len(config.get("compilers", []))
|
|
205
|
+
|
|
206
|
+
# Filter out the compiler with the matching name
|
|
207
|
+
config["compilers"] = [
|
|
208
|
+
compiler for compiler in config.get("compilers", [])
|
|
209
|
+
if compiler.get("name") != name
|
|
210
|
+
]
|
|
211
|
+
|
|
212
|
+
if len(config["compilers"]) == original_length:
|
|
213
|
+
raise ValueError(f"No compiler with name '{name}' found")
|
|
214
|
+
|
|
215
|
+
# Write back to file
|
|
216
|
+
return self.write(config)
|
|
217
|
+
except Exception:
|
|
218
|
+
return False
|
|
219
|
+
|
|
220
|
+
def create_compiler_config(self,
|
|
221
|
+
name: str,
|
|
222
|
+
type: str,
|
|
223
|
+
working_dir: str,
|
|
224
|
+
command: str,
|
|
225
|
+
args: List[str],
|
|
226
|
+
triggers: List[str],
|
|
227
|
+
extract_regex: Optional[str] = None) -> Dict[str, Any]:
|
|
228
|
+
"""
|
|
229
|
+
Create a new compiler configuration dictionary.
|
|
230
|
+
|
|
231
|
+
Args:
|
|
232
|
+
name (str): Name of the compiler.
|
|
233
|
+
type (str): Type of the compiler (e.g., 'frontend', 'backend').
|
|
234
|
+
working_dir (str): Working directory for the compiler.
|
|
235
|
+
command (str): The command to run.
|
|
236
|
+
args (List[str]): List of arguments for the command.
|
|
237
|
+
extract_regex (Optional[str]): Regular expression to extract error information.
|
|
238
|
+
|
|
239
|
+
Returns:
|
|
240
|
+
Dict[str, Any]: A new compiler configuration dictionary.
|
|
241
|
+
"""
|
|
242
|
+
compiler_config = {
|
|
243
|
+
"name": name,
|
|
244
|
+
"type": type,
|
|
245
|
+
"working_dir": working_dir,
|
|
246
|
+
"command": command,
|
|
247
|
+
"args": args,
|
|
248
|
+
"triggers": triggers
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if extract_regex:
|
|
252
|
+
compiler_config["extract_regex"] = extract_regex
|
|
253
|
+
|
|
254
|
+
return compiler_config
|
|
255
|
+
|
|
256
|
+
def list_compiler_names(self) -> List[str]:
|
|
257
|
+
"""
|
|
258
|
+
Get a list of all compiler names from the configuration.
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
List[str]: List of compiler names.
|
|
262
|
+
|
|
263
|
+
Raises:
|
|
264
|
+
FileNotFoundError: If the configuration file doesn't exist.
|
|
265
|
+
"""
|
|
266
|
+
compilers = self.get_all_compilers()
|
|
267
|
+
return [compiler.get("name") for compiler in compilers if compiler.get("name")]
|
|
268
|
+
|
|
269
|
+
def init_default_config(self) -> bool:
|
|
270
|
+
"""
|
|
271
|
+
Initialize a default compiler configuration file if it doesn't exist.
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
bool: True if initialization was successful, False otherwise.
|
|
275
|
+
"""
|
|
276
|
+
if self.exists():
|
|
277
|
+
return True
|
|
278
|
+
|
|
279
|
+
default_config = {
|
|
280
|
+
"compilers": [
|
|
281
|
+
{
|
|
282
|
+
"name": "Frontend Build",
|
|
283
|
+
"type": "frontend",
|
|
284
|
+
"working_dir": "src/frontend",
|
|
285
|
+
"command": "npm",
|
|
286
|
+
"args": ["run", "build"],
|
|
287
|
+
"extract_regex": "(?P<severity>error|warning)\\s+in\\s+(?P<file>[^:]+):(?P<line>\\d+):(?P<column>\\d+)\\s*-\\s*(?P<message>.+)"
|
|
288
|
+
}
|
|
289
|
+
]
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return self.write(default_config)
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def get_compiler_config_manager(config_path: Optional[str] = None) -> CompilerConfigManager:
|
|
296
|
+
"""
|
|
297
|
+
Factory function to get a CompilerConfigManager instance.
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
config_path (Optional[str]): Path to the compiler.yml file.
|
|
301
|
+
|
|
302
|
+
Returns:
|
|
303
|
+
CompilerConfigManager: An instance of the CompilerConfigManager.
|
|
304
|
+
"""
|
|
305
|
+
return CompilerConfigManager(config_path=config_path)
|