auto-coder 0.1.316__py3-none-any.whl → 0.1.318__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 (41) hide show
  1. {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/METADATA +2 -2
  2. {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/RECORD +41 -20
  3. autocoder/auto_coder_runner.py +1 -2
  4. autocoder/common/__init__.py +3 -0
  5. autocoder/common/auto_coder_lang.py +24 -0
  6. autocoder/common/code_auto_merge_editblock.py +2 -42
  7. autocoder/common/git_utils.py +2 -2
  8. autocoder/common/token_cost_caculate.py +103 -42
  9. autocoder/common/v2/__init__.py +0 -0
  10. autocoder/common/v2/code_auto_generate.py +199 -0
  11. autocoder/common/v2/code_auto_generate_diff.py +361 -0
  12. autocoder/common/v2/code_auto_generate_editblock.py +380 -0
  13. autocoder/common/v2/code_auto_generate_strict_diff.py +269 -0
  14. autocoder/common/v2/code_auto_merge.py +211 -0
  15. autocoder/common/v2/code_auto_merge_diff.py +354 -0
  16. autocoder/common/v2/code_auto_merge_editblock.py +523 -0
  17. autocoder/common/v2/code_auto_merge_strict_diff.py +259 -0
  18. autocoder/common/v2/code_diff_manager.py +266 -0
  19. autocoder/common/v2/code_editblock_manager.py +282 -0
  20. autocoder/common/v2/code_manager.py +238 -0
  21. autocoder/common/v2/code_strict_diff_manager.py +241 -0
  22. autocoder/dispacher/actions/action.py +16 -0
  23. autocoder/dispacher/actions/plugins/action_regex_project.py +6 -0
  24. autocoder/events/event_manager_singleton.py +2 -2
  25. autocoder/helper/__init__.py +0 -0
  26. autocoder/helper/project_creator.py +570 -0
  27. autocoder/linters/linter_factory.py +44 -25
  28. autocoder/linters/models.py +220 -0
  29. autocoder/linters/python_linter.py +1 -7
  30. autocoder/linters/reactjs_linter.py +580 -0
  31. autocoder/linters/shadow_linter.py +390 -0
  32. autocoder/linters/vue_linter.py +576 -0
  33. autocoder/memory/active_context_manager.py +0 -4
  34. autocoder/memory/active_package.py +12 -12
  35. autocoder/shadows/__init__.py +0 -0
  36. autocoder/shadows/shadow_manager.py +235 -0
  37. autocoder/version.py +1 -1
  38. {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/LICENSE +0 -0
  39. {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/WHEEL +0 -0
  40. {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/entry_points.txt +0 -0
  41. {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,390 @@
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.shadows.shadow_manager import ShadowManager
12
+ from autocoder.linters.models import (
13
+ LintIssue,
14
+ FileLintResult,
15
+ ProjectLintResult,
16
+ IssuePosition,
17
+ IssueSeverity
18
+ )
19
+
20
+ class ShadowLinter:
21
+ """
22
+ 用于对ShadowManager管理的文件进行代码检查并将结果转换回项目路径的类。
23
+ """
24
+
25
+ def __init__(self, shadow_manager: ShadowManager, verbose: bool = False):
26
+ """
27
+ 使用ShadowManager实例初始化。
28
+
29
+ 参数:
30
+ shadow_manager (ShadowManager): 用于管理文件路径映射的实例
31
+ verbose (bool): 是否启用详细输出
32
+ """
33
+ self.shadow_manager = shadow_manager
34
+ self.verbose = verbose
35
+
36
+ def lint_shadow_file(self, shadow_path: str, fix: bool = False) -> FileLintResult:
37
+ """
38
+ 对单个影子文件进行代码检查并将结果中的路径转换为项目路径。
39
+
40
+ 参数:
41
+ shadow_path (str): 影子文件的路径
42
+ fix (bool): 是否自动修复问题
43
+
44
+ 返回:
45
+ FileLintResult: 包含项目路径的代码检查结果
46
+ """
47
+ # 检查路径是否为影子路径
48
+ if not self.shadow_manager.is_shadow_path(shadow_path):
49
+ raise ValueError(f"不是影子路径: {shadow_path}")
50
+
51
+ try:
52
+ # 获取此影子文件的项目路径
53
+ project_path = self.shadow_manager.from_shadow_path(shadow_path)
54
+
55
+ # 记录开始时间以计算执行时间
56
+ start_time = time.time()
57
+
58
+ # 对影子文件运行代码检查
59
+ raw_lint_result = LinterFactory.lint_file(shadow_path, fix=fix, verbose=self.verbose)
60
+
61
+ # 如果lint过程返回None,创建一个空的结果对象,而不是直接返回None
62
+ if raw_lint_result is None:
63
+ language = self._detect_language(shadow_path)
64
+ return FileLintResult(
65
+ file_path=project_path,
66
+ success=False,
67
+ language=language,
68
+ issues=[], # 空问题列表
69
+ error=None,
70
+ error_count=0,
71
+ warning_count=0,
72
+ info_count=0
73
+ )
74
+
75
+ # 计算执行时间(毫秒)
76
+ execution_time_ms = int((time.time() - start_time) * 1000)
77
+ raw_lint_result['execution_time_ms'] = execution_time_ms
78
+
79
+ # 将原始结果转换为Pydantic模型
80
+ return self._convert_raw_lint_result(raw_lint_result, shadow_path, project_path)
81
+ except Exception as e:
82
+ if self.verbose:
83
+ print(f"检查 {shadow_path} 时出错: {str(e)}")
84
+
85
+ project_path = self.shadow_manager.from_shadow_path(shadow_path)
86
+ language = self._detect_language(shadow_path)
87
+ return FileLintResult(
88
+ file_path=project_path,
89
+ success=False,
90
+ language=language,
91
+ error=str(e),
92
+ issues=[], # 添加空问题列表
93
+ error_count=0,
94
+ warning_count=0,
95
+ info_count=0
96
+ )
97
+
98
+ def lint_all_shadow_files(self, fix: bool = False) -> ProjectLintResult:
99
+ """
100
+ 对影子目录中的所有文件进行代码检查并返回包含项目路径的结果。
101
+
102
+ 参数:
103
+ fix (bool): 是否自动修复问题
104
+
105
+ 返回:
106
+ ProjectLintResult: 所有文件的汇总代码检查结果
107
+ """
108
+ shadow_files = self._get_all_shadow_files()
109
+ file_results = {}
110
+ total_files = len(shadow_files)
111
+ files_with_issues = 0
112
+ total_issues = 0
113
+ total_errors = 0
114
+ total_warnings = 0
115
+ total_infos = 0
116
+ fixed_issues_count = 0
117
+
118
+ # 处理每个影子文件
119
+ for shadow_path in shadow_files:
120
+ try:
121
+ file_result = self.lint_shadow_file(shadow_path, fix=fix)
122
+ # lint_shadow_file现在总是返回有效的FileLintResult,不再需要检查None
123
+ project_path = self.shadow_manager.from_shadow_path(shadow_path)
124
+
125
+ file_results[project_path] = file_result
126
+
127
+ # 更新统计数据
128
+ if file_result.success:
129
+ issue_count = len(file_result.issues)
130
+ if issue_count > 0:
131
+ files_with_issues += 1
132
+ total_issues += issue_count
133
+ total_errors += file_result.error_count
134
+ total_warnings += file_result.warning_count
135
+ total_infos += file_result.info_count
136
+
137
+ if file_result.fixed_issues_count:
138
+ fixed_issues_count += file_result.fixed_issues_count
139
+ except Exception as e:
140
+ if self.verbose:
141
+ import traceback
142
+ traceback.print_exc()
143
+ print(f"处理 {shadow_path} 时出错: {str(e)}")
144
+
145
+ # 加载的是影子文件,但是要转换成项目的路径
146
+ project_path = self.shadow_manager.from_shadow_path(shadow_path)
147
+ language = self._detect_language(shadow_path)
148
+ file_results[project_path] = FileLintResult(
149
+ file_path=project_path,
150
+ success=False,
151
+ language=language,
152
+ error=str(e),
153
+ issues=[],
154
+ error_count=0,
155
+ warning_count=0,
156
+ info_count=0
157
+ )
158
+
159
+ # 创建项目结果
160
+ return ProjectLintResult(
161
+ project_path=self.shadow_manager.source_dir,
162
+ file_results=file_results,
163
+ total_files=total_files,
164
+ files_with_issues=files_with_issues,
165
+ total_issues=total_issues,
166
+ total_errors=total_errors,
167
+ total_warnings=total_warnings,
168
+ total_infos=total_infos,
169
+ fixed_issues_count=fixed_issues_count if fix else None
170
+ )
171
+
172
+ def lint_shadow_dir(self, shadow_dir: str, fix: bool = False) -> ProjectLintResult:
173
+ """
174
+ 对特定影子目录中的所有文件进行代码检查。
175
+
176
+ 参数:
177
+ shadow_dir (str): 影子目录的路径
178
+ fix (bool): 是否自动修复问题
179
+
180
+ 返回:
181
+ ProjectLintResult: 目录中所有文件的汇总代码检查结果
182
+ """
183
+ if not self.shadow_manager.is_shadow_path(shadow_dir):
184
+ raise ValueError(f"不是影子路径: {shadow_dir}")
185
+
186
+ shadow_files = self._get_files_in_dir(shadow_dir)
187
+ file_results = {}
188
+ total_files = len(shadow_files)
189
+ files_with_issues = 0
190
+ total_issues = 0
191
+ total_errors = 0
192
+ total_warnings = 0
193
+ total_infos = 0
194
+ fixed_issues_count = 0
195
+
196
+ for shadow_path in shadow_files:
197
+ try:
198
+ file_result = self.lint_shadow_file(shadow_path, fix=fix)
199
+ # lint_shadow_file现在总是返回有效的FileLintResult,不再需要检查None
200
+ project_path = self.shadow_manager.from_shadow_path(shadow_path)
201
+
202
+ file_results[project_path] = file_result
203
+
204
+ # 更新统计数据
205
+ if file_result.success:
206
+ issue_count = len(file_result.issues)
207
+ if issue_count > 0:
208
+ files_with_issues += 1
209
+ total_issues += issue_count
210
+ total_errors += file_result.error_count
211
+ total_warnings += file_result.warning_count
212
+ total_infos += file_result.info_count
213
+
214
+ if file_result.fixed_issues_count:
215
+ fixed_issues_count += file_result.fixed_issues_count
216
+ except Exception as e:
217
+ if self.verbose:
218
+ print(f"处理 {shadow_path} 时出错: {str(e)}")
219
+
220
+ project_path = self.shadow_manager.from_shadow_path(shadow_path)
221
+ language = self._detect_language(shadow_path)
222
+ file_results[project_path] = FileLintResult(
223
+ file_path=project_path,
224
+ success=False,
225
+ language=language,
226
+ error=str(e),
227
+ issues=[],
228
+ error_count=0,
229
+ warning_count=0,
230
+ info_count=0
231
+ )
232
+
233
+ # 创建项目结果
234
+ project_path = self.shadow_manager.from_shadow_path(shadow_dir)
235
+ return ProjectLintResult(
236
+ project_path=project_path,
237
+ file_results=file_results,
238
+ total_files=total_files,
239
+ files_with_issues=files_with_issues,
240
+ total_issues=total_issues,
241
+ total_errors=total_errors,
242
+ total_warnings=total_warnings,
243
+ total_infos=total_infos,
244
+ fixed_issues_count=fixed_issues_count if fix else None
245
+ )
246
+
247
+ def _get_all_shadow_files(self) -> List[str]:
248
+ """
249
+ 获取影子目录中的所有文件。
250
+
251
+ 返回:
252
+ List[str]: 影子文件的绝对路径列表
253
+ """
254
+ all_files = []
255
+
256
+ for root, _, files in os.walk(self.shadow_manager.shadows_dir):
257
+ for file in files:
258
+ # 跳过隐藏文件和目录
259
+ if file.startswith('.'):
260
+ continue
261
+
262
+ file_path = os.path.join(root, file)
263
+ all_files.append(file_path)
264
+
265
+ return all_files
266
+
267
+ def _get_files_in_dir(self, directory: str) -> List[str]:
268
+ """
269
+ 获取目录及其子目录中的所有文件。
270
+
271
+ 参数:
272
+ directory (str): 目录路径
273
+
274
+ 返回:
275
+ List[str]: 绝对文件路径列表
276
+ """
277
+ all_files = []
278
+
279
+ for root, _, files in os.walk(directory):
280
+ for file in files:
281
+ # 跳过隐藏文件
282
+ if file.startswith('.'):
283
+ continue
284
+
285
+ file_path = os.path.join(root, file)
286
+ all_files.append(file_path)
287
+
288
+ return all_files
289
+
290
+ def _detect_language(self, file_path: str) -> str:
291
+ """
292
+ 根据文件扩展名检测文件的语言。
293
+
294
+ 参数:
295
+ file_path (str): 文件路径
296
+
297
+ 返回:
298
+ str: 检测到的语言或"unknown"
299
+ """
300
+ try:
301
+ language = LinterFactory._detect_language_from_file(file_path)
302
+ # 确保返回值是字符串
303
+ return language if isinstance(language, str) else "unknown"
304
+ except ValueError:
305
+ # 如果语言检测失败,返回默认值
306
+ return "unknown"
307
+ except Exception:
308
+ # 捕获所有其他异常并返回默认值
309
+ return "unknown"
310
+
311
+ def _convert_raw_lint_result(self, raw_result: Dict[str, Any], shadow_path: str, project_path: str) -> FileLintResult:
312
+ """
313
+ 将原始的linter输出转换为FileLintResult Pydantic模型。
314
+
315
+ 参数:
316
+ raw_result (Dict[str, Any]): Linter的原始输出
317
+ shadow_path (str): 影子文件的路径
318
+ project_path (str): 项目文件的路径
319
+
320
+ 返回:
321
+ FileLintResult: 标准化的lint结果模型
322
+ """
323
+ # 提取语言信息
324
+ language = raw_result.get('language')
325
+ if not isinstance(language, str):
326
+ language = self._detect_language(shadow_path)
327
+
328
+ # 初始化计数器
329
+ error_count = 0
330
+ warning_count = 0
331
+ info_count = 0
332
+
333
+ # 处理问题
334
+ issues = []
335
+ raw_issues = raw_result.get('issues', [])
336
+
337
+ for raw_issue in raw_issues:
338
+ # 确定严重性
339
+ severity_str = raw_issue.get('severity', 'error').lower()
340
+ if severity_str in ('error', 'critical', 'fatal'):
341
+ severity = IssueSeverity.ERROR
342
+ error_count += 1
343
+
344
+ # 提取位置信息
345
+ line = raw_issue.get('line', 1)
346
+ column = raw_issue.get('column')
347
+ end_line = raw_issue.get('end_line')
348
+ end_column = raw_issue.get('end_column')
349
+
350
+ position = IssuePosition(
351
+ line=line,
352
+ column=column,
353
+ end_line=end_line,
354
+ end_column=end_column
355
+ )
356
+
357
+ # 创建问题
358
+ issue = LintIssue(
359
+ code=raw_issue.get('code', ''),
360
+ message=raw_issue.get('message', '未知问题'),
361
+ severity=severity,
362
+ position=position,
363
+ file_path=project_path, # 使用项目路径而不是影子路径
364
+ rule_name=raw_issue.get('rule_name'),
365
+ source=raw_issue.get('source'),
366
+ fix_available=raw_issue.get('fix_available', False),
367
+ fix_description=raw_issue.get('fix_description')
368
+ )
369
+
370
+ issues.append(issue)
371
+ elif severity_str in ('warning', 'warn'):
372
+ severity = IssueSeverity.WARNING
373
+ warning_count += 1
374
+ else:
375
+ severity = IssueSeverity.INFO
376
+ info_count += 1
377
+
378
+ # 创建文件结果
379
+ return FileLintResult(
380
+ file_path=project_path,
381
+ success=raw_result.get('success', True),
382
+ language=language,
383
+ issues=issues,
384
+ error=raw_result.get('error'),
385
+ warning_count=warning_count,
386
+ error_count=error_count,
387
+ info_count=info_count,
388
+ execution_time_ms=raw_result.get('execution_time_ms'),
389
+ fixed_issues_count=raw_result.get('fixed_issues_count')
390
+ )