auto-coder 0.1.363__py3-none-any.whl → 0.1.365__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.

Files changed (39) hide show
  1. {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/METADATA +2 -2
  2. {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/RECORD +39 -23
  3. autocoder/agent/base_agentic/tools/execute_command_tool_resolver.py +1 -1
  4. autocoder/auto_coder.py +46 -2
  5. autocoder/auto_coder_runner.py +2 -0
  6. autocoder/common/__init__.py +5 -0
  7. autocoder/common/file_checkpoint/__init__.py +21 -0
  8. autocoder/common/file_checkpoint/backup.py +264 -0
  9. autocoder/common/file_checkpoint/conversation_checkpoint.py +182 -0
  10. autocoder/common/file_checkpoint/examples.py +217 -0
  11. autocoder/common/file_checkpoint/manager.py +611 -0
  12. autocoder/common/file_checkpoint/models.py +156 -0
  13. autocoder/common/file_checkpoint/store.py +383 -0
  14. autocoder/common/file_checkpoint/test_backup.py +242 -0
  15. autocoder/common/file_checkpoint/test_manager.py +570 -0
  16. autocoder/common/file_checkpoint/test_models.py +360 -0
  17. autocoder/common/file_checkpoint/test_store.py +327 -0
  18. autocoder/common/file_checkpoint/test_utils.py +297 -0
  19. autocoder/common/file_checkpoint/utils.py +119 -0
  20. autocoder/common/rulefiles/autocoderrules_utils.py +114 -55
  21. autocoder/common/save_formatted_log.py +76 -5
  22. autocoder/common/utils_code_auto_generate.py +2 -1
  23. autocoder/common/v2/agent/agentic_edit.py +545 -225
  24. autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py +83 -43
  25. autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +116 -29
  26. autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +179 -48
  27. autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +101 -56
  28. autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py +322 -0
  29. autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +173 -132
  30. autocoder/common/v2/agent/agentic_edit_types.py +4 -0
  31. autocoder/compilers/normal_compiler.py +64 -0
  32. autocoder/events/event_manager_singleton.py +133 -4
  33. autocoder/linters/normal_linter.py +373 -0
  34. autocoder/linters/python_linter.py +4 -2
  35. autocoder/version.py +1 -1
  36. {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/LICENSE +0 -0
  37. {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/WHEEL +0 -0
  38. {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/entry_points.txt +0 -0
  39. {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,373 @@
1
+ """
2
+ 用于对文件进行代码检查的模块。
3
+ """
4
+
5
+ import os
6
+ import time
7
+ from typing import Dict, List, Any, Optional, Tuple
8
+ from datetime import datetime
9
+
10
+ from autocoder.linters.linter_factory import LinterFactory
11
+ from autocoder.linters.models import (
12
+ LintIssue,
13
+ FileLintResult,
14
+ ProjectLintResult,
15
+ IssuePosition,
16
+ IssueSeverity
17
+ )
18
+ from loguru import logger as global_logger
19
+
20
+ class NormalLinter:
21
+ """
22
+ 用于对文件进行代码检查的类。
23
+ """
24
+
25
+ def __init__(self, project_dir: str, verbose: bool = False):
26
+ """
27
+ 初始化。
28
+
29
+ 参数:
30
+ project_dir (str): 项目根目录路径
31
+ verbose (bool): 是否启用详细输出
32
+ """
33
+ self.project_dir = project_dir
34
+ self.verbose = verbose
35
+ self.logger = global_logger.bind(name="NormalLinter")
36
+
37
+ def lint_file(self, file_path: str, fix: bool = False) -> FileLintResult:
38
+ """
39
+ 对单个文件进行代码检查。
40
+
41
+ 参数:
42
+ file_path (str): 文件的路径
43
+ fix (bool): 是否自动修复问题
44
+
45
+ 返回:
46
+ FileLintResult: 代码检查结果
47
+ """
48
+ try:
49
+ # 记录开始时间以计算执行时间
50
+ start_time = time.time()
51
+
52
+ # 对文件运行代码检查
53
+ raw_lint_result = LinterFactory.lint_file(file_path, fix=fix, verbose=self.verbose)
54
+
55
+ # 如果lint过程返回None,创建一个空的结果对象,而不是直接返回None
56
+ if raw_lint_result is None:
57
+ language = self._detect_language(file_path)
58
+ return FileLintResult(
59
+ file_path=file_path,
60
+ success=False,
61
+ language=language,
62
+ issues=[], # 空问题列表
63
+ error=None,
64
+ error_count=0,
65
+ warning_count=0,
66
+ info_count=0
67
+ )
68
+
69
+ # 计算执行时间(毫秒)
70
+ execution_time_ms = int((time.time() - start_time) * 1000)
71
+ raw_lint_result['execution_time_ms'] = execution_time_ms
72
+
73
+ # 将原始结果转换为Pydantic模型
74
+ return self._convert_raw_lint_result(raw_lint_result, file_path)
75
+ except Exception as e:
76
+ if self.verbose:
77
+ print(f"检查 {file_path} 时出错: {str(e)}")
78
+
79
+ language = self._detect_language(file_path)
80
+ return FileLintResult(
81
+ file_path=file_path,
82
+ success=False,
83
+ language=language,
84
+ error=str(e),
85
+ issues=[], # 添加空问题列表
86
+ error_count=0,
87
+ warning_count=0,
88
+ info_count=0
89
+ )
90
+
91
+ def lint_all_files(self, fix: bool = False) -> ProjectLintResult:
92
+ """
93
+ 对项目目录中的所有文件进行代码检查。
94
+
95
+ 参数:
96
+ fix (bool): 是否自动修复问题
97
+
98
+ 返回:
99
+ ProjectLintResult: 所有文件的汇总代码检查结果
100
+ """
101
+ all_files = self._get_all_files()
102
+ file_results = {}
103
+ total_files = len(all_files)
104
+ files_with_issues = 0
105
+ total_issues = 0
106
+ total_errors = 0
107
+ total_warnings = 0
108
+ total_infos = 0
109
+ fixed_issues_count = 0
110
+
111
+ # 处理每个文件
112
+ for file_path in all_files:
113
+ self.logger.info(f"正在检查文件: {file_path}")
114
+ try:
115
+ file_result = self.lint_file(file_path, fix=fix)
116
+ self.logger.info(f"检查完成: {file_path}")
117
+
118
+ file_results[file_path] = file_result
119
+
120
+ # 更新统计数据
121
+ if file_result.success:
122
+ issue_count = len(file_result.issues)
123
+ if issue_count > 0:
124
+ files_with_issues += 1
125
+ total_issues += issue_count
126
+ total_errors += file_result.error_count
127
+ total_warnings += file_result.warning_count
128
+ total_infos += file_result.info_count
129
+
130
+ if file_result.fixed_issues_count:
131
+ fixed_issues_count += file_result.fixed_issues_count
132
+ except Exception as e:
133
+ if self.verbose:
134
+ import traceback
135
+ traceback.print_exc()
136
+ print(f"处理 {file_path} 时出错: {str(e)}")
137
+
138
+ language = self._detect_language(file_path)
139
+ file_results[file_path] = FileLintResult(
140
+ file_path=file_path,
141
+ success=False,
142
+ language=language,
143
+ error=str(e),
144
+ issues=[],
145
+ error_count=0,
146
+ warning_count=0,
147
+ info_count=0
148
+ )
149
+
150
+ # 创建项目结果
151
+ return ProjectLintResult(
152
+ project_path=self.project_dir,
153
+ file_results=file_results,
154
+ total_files=total_files,
155
+ files_with_issues=files_with_issues,
156
+ total_issues=total_issues,
157
+ total_errors=total_errors,
158
+ total_warnings=total_warnings,
159
+ total_infos=total_infos,
160
+ fixed_issues_count=fixed_issues_count if fix else None
161
+ )
162
+
163
+ def lint_dir(self, directory: str, fix: bool = False) -> ProjectLintResult:
164
+ """
165
+ 对特定目录中的所有文件进行代码检查。
166
+
167
+ 参数:
168
+ directory (str): 目录的路径
169
+ fix (bool): 是否自动修复问题
170
+
171
+ 返回:
172
+ ProjectLintResult: 目录中所有文件的汇总代码检查结果
173
+ """
174
+ files = self._get_files_in_dir(directory)
175
+ file_results = {}
176
+ total_files = len(files)
177
+ files_with_issues = 0
178
+ total_issues = 0
179
+ total_errors = 0
180
+ total_warnings = 0
181
+ total_infos = 0
182
+ fixed_issues_count = 0
183
+
184
+ for file_path in files:
185
+ try:
186
+ file_result = self.lint_file(file_path, fix=fix)
187
+
188
+ file_results[file_path] = file_result
189
+
190
+ # 更新统计数据
191
+ if file_result.success:
192
+ issue_count = len(file_result.issues)
193
+ if issue_count > 0:
194
+ files_with_issues += 1
195
+ total_issues += issue_count
196
+ total_errors += file_result.error_count
197
+ total_warnings += file_result.warning_count
198
+ total_infos += file_result.info_count
199
+
200
+ if file_result.fixed_issues_count:
201
+ fixed_issues_count += file_result.fixed_issues_count
202
+ except Exception as e:
203
+ if self.verbose:
204
+ print(f"处理 {file_path} 时出错: {str(e)}")
205
+
206
+ language = self._detect_language(file_path)
207
+ file_results[file_path] = FileLintResult(
208
+ file_path=file_path,
209
+ success=False,
210
+ language=language,
211
+ error=str(e),
212
+ issues=[],
213
+ error_count=0,
214
+ warning_count=0,
215
+ info_count=0
216
+ )
217
+
218
+ # 创建项目结果
219
+ return ProjectLintResult(
220
+ project_path=directory,
221
+ file_results=file_results,
222
+ total_files=total_files,
223
+ files_with_issues=files_with_issues,
224
+ total_issues=total_issues,
225
+ total_errors=total_errors,
226
+ total_warnings=total_warnings,
227
+ total_infos=total_infos,
228
+ fixed_issues_count=fixed_issues_count if fix else None
229
+ )
230
+
231
+ def _get_all_files(self) -> List[str]:
232
+ """
233
+ 获取项目目录中的所有文件。
234
+
235
+ 返回:
236
+ List[str]: 文件的绝对路径列表
237
+ """
238
+ all_files = []
239
+
240
+ for root, _, files in os.walk(self.project_dir):
241
+ for file in files:
242
+ # 跳过隐藏文件和目录
243
+ if file.startswith('.'):
244
+ continue
245
+
246
+ file_path = os.path.join(root, file)
247
+ all_files.append(file_path)
248
+
249
+ return all_files
250
+
251
+ def _get_files_in_dir(self, directory: str) -> List[str]:
252
+ """
253
+ 获取目录及其子目录中的所有文件。
254
+
255
+ 参数:
256
+ directory (str): 目录路径
257
+
258
+ 返回:
259
+ List[str]: 绝对文件路径列表
260
+ """
261
+ all_files = []
262
+
263
+ for root, _, files in os.walk(directory):
264
+ for file in files:
265
+ # 跳过隐藏文件
266
+ if file.startswith('.'):
267
+ continue
268
+
269
+ file_path = os.path.join(root, file)
270
+ all_files.append(file_path)
271
+
272
+ return all_files
273
+
274
+ def _detect_language(self, file_path: str) -> str:
275
+ """
276
+ 根据文件扩展名检测文件的语言。
277
+
278
+ 参数:
279
+ file_path (str): 文件路径
280
+
281
+ 返回:
282
+ str: 检测到的语言或"unknown"
283
+ """
284
+ try:
285
+ language = LinterFactory._detect_language_from_file(file_path)
286
+ # 确保返回值是字符串
287
+ return language if isinstance(language, str) else "unknown"
288
+ except ValueError:
289
+ # 如果语言检测失败,返回默认值
290
+ return "unknown"
291
+ except Exception:
292
+ # 捕获所有其他异常并返回默认值
293
+ return "unknown"
294
+
295
+ def _convert_raw_lint_result(self, raw_result: Dict[str, Any], file_path: str) -> FileLintResult:
296
+ """
297
+ 将原始的linter输出转换为FileLintResult Pydantic模型。
298
+
299
+ 参数:
300
+ raw_result (Dict[str, Any]): Linter的原始输出
301
+ file_path (str): 文件的路径
302
+
303
+ 返回:
304
+ FileLintResult: 标准化的lint结果模型
305
+ """
306
+ # 提取语言信息
307
+ language = raw_result.get('language')
308
+ if not isinstance(language, str):
309
+ language = self._detect_language(file_path)
310
+
311
+ # 初始化计数器
312
+ error_count = 0
313
+ warning_count = 0
314
+ info_count = 0
315
+
316
+ # 处理问题
317
+ issues = []
318
+ raw_issues = raw_result.get('issues', [])
319
+
320
+ for raw_issue in raw_issues:
321
+ # 确定严重性
322
+ severity_str = raw_issue.get('severity', 'error').lower()
323
+ if severity_str in ('error', 'critical', 'fatal'):
324
+ severity = IssueSeverity.ERROR
325
+ error_count += 1
326
+ elif severity_str in ('warning', 'warn'):
327
+ severity = IssueSeverity.WARNING
328
+ warning_count += 1
329
+ else:
330
+ severity = IssueSeverity.INFO
331
+ info_count += 1
332
+
333
+ # 提取位置信息
334
+ line = raw_issue.get('line', 1)
335
+ column = raw_issue.get('column')
336
+ end_line = raw_issue.get('end_line')
337
+ end_column = raw_issue.get('end_column')
338
+
339
+ position = IssuePosition(
340
+ line=line,
341
+ column=column,
342
+ end_line=end_line,
343
+ end_column=end_column
344
+ )
345
+
346
+ # 创建问题
347
+ issue = LintIssue(
348
+ code=raw_issue.get('code', ''),
349
+ message=raw_issue.get('message', '未知问题'),
350
+ severity=severity,
351
+ position=position,
352
+ file_path=file_path,
353
+ rule_name=raw_issue.get('rule_name'),
354
+ source=raw_issue.get('source'),
355
+ fix_available=raw_issue.get('fix_available', False),
356
+ fix_description=raw_issue.get('fix_description')
357
+ )
358
+
359
+ issues.append(issue)
360
+
361
+ # 创建文件结果
362
+ return FileLintResult(
363
+ file_path=file_path,
364
+ success=raw_result.get('success', True),
365
+ language=language,
366
+ issues=issues,
367
+ error=raw_result.get('error'),
368
+ warning_count=warning_count,
369
+ error_count=error_count,
370
+ info_count=info_count,
371
+ execution_time_ms=raw_result.get('execution_time_ms'),
372
+ fixed_issues_count=raw_result.get('fixed_issues_count')
373
+ )
@@ -11,6 +11,7 @@ import tempfile
11
11
  from typing import Dict, List, Any, Optional, Tuple
12
12
 
13
13
  from autocoder.linters.base_linter import BaseLinter
14
+ from loguru import logger
14
15
 
15
16
  class PythonLinter(BaseLinter):
16
17
  """
@@ -142,6 +143,8 @@ class PythonLinter(BaseLinter):
142
143
  'warning_count': 0,
143
144
  'issues': []
144
145
  }
146
+
147
+ logger.info(f"Running pylint on {target}")
145
148
 
146
149
  try:
147
150
  # Create a temp file to store JSON output
@@ -152,8 +155,7 @@ class PythonLinter(BaseLinter):
152
155
  cmd = [
153
156
  sys.executable,
154
157
  "-m",
155
- "pylint",
156
- "--disable=import-error",
158
+ "pylint",
157
159
  "--output-format=json",
158
160
  target
159
161
  ]
autocoder/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.363"
1
+ __version__ = "0.1.365"