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.
- {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/METADATA +2 -2
- {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/RECORD +39 -23
- autocoder/agent/base_agentic/tools/execute_command_tool_resolver.py +1 -1
- autocoder/auto_coder.py +46 -2
- autocoder/auto_coder_runner.py +2 -0
- autocoder/common/__init__.py +5 -0
- autocoder/common/file_checkpoint/__init__.py +21 -0
- autocoder/common/file_checkpoint/backup.py +264 -0
- autocoder/common/file_checkpoint/conversation_checkpoint.py +182 -0
- autocoder/common/file_checkpoint/examples.py +217 -0
- autocoder/common/file_checkpoint/manager.py +611 -0
- autocoder/common/file_checkpoint/models.py +156 -0
- autocoder/common/file_checkpoint/store.py +383 -0
- autocoder/common/file_checkpoint/test_backup.py +242 -0
- autocoder/common/file_checkpoint/test_manager.py +570 -0
- autocoder/common/file_checkpoint/test_models.py +360 -0
- autocoder/common/file_checkpoint/test_store.py +327 -0
- autocoder/common/file_checkpoint/test_utils.py +297 -0
- autocoder/common/file_checkpoint/utils.py +119 -0
- autocoder/common/rulefiles/autocoderrules_utils.py +114 -55
- autocoder/common/save_formatted_log.py +76 -5
- autocoder/common/utils_code_auto_generate.py +2 -1
- autocoder/common/v2/agent/agentic_edit.py +545 -225
- autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py +83 -43
- autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +116 -29
- autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +179 -48
- autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +101 -56
- autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py +322 -0
- autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +173 -132
- autocoder/common/v2/agent/agentic_edit_types.py +4 -0
- autocoder/compilers/normal_compiler.py +64 -0
- autocoder/events/event_manager_singleton.py +133 -4
- autocoder/linters/normal_linter.py +373 -0
- autocoder/linters/python_linter.py +4 -2
- autocoder/version.py +1 -1
- {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import os
|
|
3
|
+
import json
|
|
4
|
+
import tempfile
|
|
5
|
+
import shutil
|
|
6
|
+
from datetime import datetime, timedelta
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from autocoder.common.file_checkpoint.backup import FileBackupManager
|
|
10
|
+
|
|
11
|
+
@pytest.fixture
|
|
12
|
+
def temp_test_dir():
|
|
13
|
+
"""提供一个临时的测试目录"""
|
|
14
|
+
temp_dir = tempfile.mkdtemp()
|
|
15
|
+
yield temp_dir
|
|
16
|
+
shutil.rmtree(temp_dir)
|
|
17
|
+
|
|
18
|
+
@pytest.fixture
|
|
19
|
+
def temp_backup_dir():
|
|
20
|
+
"""提供一个临时的备份目录"""
|
|
21
|
+
temp_dir = tempfile.mkdtemp()
|
|
22
|
+
yield temp_dir
|
|
23
|
+
shutil.rmtree(temp_dir)
|
|
24
|
+
|
|
25
|
+
@pytest.fixture
|
|
26
|
+
def sample_file(temp_test_dir):
|
|
27
|
+
"""创建一个用于测试的样例文件"""
|
|
28
|
+
file_path = os.path.join(temp_test_dir, "sample.txt")
|
|
29
|
+
with open(file_path, 'w', encoding='utf-8') as f:
|
|
30
|
+
f.write("这是一个测试文件的内容")
|
|
31
|
+
return file_path
|
|
32
|
+
|
|
33
|
+
class TestFileBackupManager:
|
|
34
|
+
"""FileBackupManager类的单元测试"""
|
|
35
|
+
|
|
36
|
+
def test_init_with_custom_dir(self, temp_backup_dir):
|
|
37
|
+
"""测试使用自定义目录初始化"""
|
|
38
|
+
manager = FileBackupManager(backup_dir=temp_backup_dir)
|
|
39
|
+
|
|
40
|
+
assert manager.backup_dir == temp_backup_dir
|
|
41
|
+
assert os.path.exists(temp_backup_dir)
|
|
42
|
+
|
|
43
|
+
def test_init_with_default_dir(self, monkeypatch):
|
|
44
|
+
"""测试使用默认目录初始化"""
|
|
45
|
+
# 创建一个临时主目录
|
|
46
|
+
temp_home = tempfile.mkdtemp()
|
|
47
|
+
try:
|
|
48
|
+
# 模拟用户主目录
|
|
49
|
+
monkeypatch.setattr(os.path, 'expanduser', lambda path: temp_home)
|
|
50
|
+
|
|
51
|
+
manager = FileBackupManager()
|
|
52
|
+
|
|
53
|
+
expected_dir = os.path.join(temp_home, ".autocoder", "backups")
|
|
54
|
+
assert manager.backup_dir == expected_dir
|
|
55
|
+
assert os.path.exists(expected_dir)
|
|
56
|
+
finally:
|
|
57
|
+
# 清理临时目录
|
|
58
|
+
if os.path.exists(temp_home):
|
|
59
|
+
shutil.rmtree(temp_home)
|
|
60
|
+
|
|
61
|
+
def test_backup_file(self, temp_backup_dir, sample_file):
|
|
62
|
+
"""测试备份文件功能"""
|
|
63
|
+
manager = FileBackupManager(backup_dir=temp_backup_dir)
|
|
64
|
+
|
|
65
|
+
# 备份文件
|
|
66
|
+
backup_id = manager.backup_file(sample_file)
|
|
67
|
+
|
|
68
|
+
# 检查备份ID
|
|
69
|
+
assert backup_id is not None
|
|
70
|
+
assert len(backup_id) > 0
|
|
71
|
+
|
|
72
|
+
# 检查备份文件是否存在
|
|
73
|
+
backup_file_path = os.path.join(temp_backup_dir, backup_id)
|
|
74
|
+
assert os.path.exists(backup_file_path)
|
|
75
|
+
|
|
76
|
+
# 检查备份文件内容
|
|
77
|
+
with open(backup_file_path, 'r', encoding='utf-8') as f:
|
|
78
|
+
content = f.read()
|
|
79
|
+
assert content == "这是一个测试文件的内容"
|
|
80
|
+
|
|
81
|
+
# 检查元数据
|
|
82
|
+
assert backup_id in manager.metadata
|
|
83
|
+
assert manager.metadata[backup_id]["original_path"] == sample_file
|
|
84
|
+
assert "timestamp" in manager.metadata[backup_id]
|
|
85
|
+
assert "size" in manager.metadata[backup_id]
|
|
86
|
+
|
|
87
|
+
def test_backup_nonexistent_file(self, temp_backup_dir):
|
|
88
|
+
"""测试备份不存在的文件"""
|
|
89
|
+
manager = FileBackupManager(backup_dir=temp_backup_dir)
|
|
90
|
+
|
|
91
|
+
# 尝试备份不存在的文件
|
|
92
|
+
backup_id = manager.backup_file("nonexistent_file.txt")
|
|
93
|
+
|
|
94
|
+
# 应该返回None
|
|
95
|
+
assert backup_id is None
|
|
96
|
+
|
|
97
|
+
def test_restore_file(self, temp_backup_dir, temp_test_dir, sample_file):
|
|
98
|
+
"""测试恢复文件功能"""
|
|
99
|
+
manager = FileBackupManager(backup_dir=temp_backup_dir)
|
|
100
|
+
|
|
101
|
+
# 备份文件
|
|
102
|
+
backup_id = manager.backup_file(sample_file)
|
|
103
|
+
|
|
104
|
+
# 修改原始文件
|
|
105
|
+
with open(sample_file, 'w', encoding='utf-8') as f:
|
|
106
|
+
f.write("已修改的内容")
|
|
107
|
+
|
|
108
|
+
# 恢复到新位置
|
|
109
|
+
restore_path = os.path.join(temp_test_dir, "restored.txt")
|
|
110
|
+
success = manager.restore_file(restore_path, backup_id)
|
|
111
|
+
|
|
112
|
+
# 检查恢复结果
|
|
113
|
+
assert success is True
|
|
114
|
+
assert os.path.exists(restore_path)
|
|
115
|
+
|
|
116
|
+
# 检查恢复文件内容
|
|
117
|
+
with open(restore_path, 'r', encoding='utf-8') as f:
|
|
118
|
+
content = f.read()
|
|
119
|
+
assert content == "这是一个测试文件的内容"
|
|
120
|
+
|
|
121
|
+
def test_restore_with_invalid_backup_id(self, temp_backup_dir, temp_test_dir):
|
|
122
|
+
"""测试使用无效的备份ID恢复文件"""
|
|
123
|
+
manager = FileBackupManager(backup_dir=temp_backup_dir)
|
|
124
|
+
|
|
125
|
+
# 尝试恢复不存在的备份
|
|
126
|
+
restore_path = os.path.join(temp_test_dir, "restored.txt")
|
|
127
|
+
success = manager.restore_file(restore_path, "invalid_backup_id")
|
|
128
|
+
|
|
129
|
+
# 应该失败
|
|
130
|
+
assert success is False
|
|
131
|
+
assert not os.path.exists(restore_path)
|
|
132
|
+
|
|
133
|
+
def test_get_backup_content(self, temp_backup_dir, sample_file):
|
|
134
|
+
"""测试获取备份文件内容"""
|
|
135
|
+
manager = FileBackupManager(backup_dir=temp_backup_dir)
|
|
136
|
+
|
|
137
|
+
# 备份文件
|
|
138
|
+
backup_id = manager.backup_file(sample_file)
|
|
139
|
+
|
|
140
|
+
# 获取备份内容
|
|
141
|
+
content = manager.get_backup_content(backup_id)
|
|
142
|
+
|
|
143
|
+
# 检查内容
|
|
144
|
+
assert content == "这是一个测试文件的内容"
|
|
145
|
+
|
|
146
|
+
def test_get_backup_content_with_invalid_id(self, temp_backup_dir):
|
|
147
|
+
"""测试使用无效的备份ID获取内容"""
|
|
148
|
+
manager = FileBackupManager(backup_dir=temp_backup_dir)
|
|
149
|
+
|
|
150
|
+
# 尝试获取不存在的备份内容
|
|
151
|
+
content = manager.get_backup_content("invalid_backup_id")
|
|
152
|
+
|
|
153
|
+
# 应该返回None
|
|
154
|
+
assert content is None
|
|
155
|
+
|
|
156
|
+
def test_delete_backup(self, temp_backup_dir, sample_file):
|
|
157
|
+
"""测试删除备份"""
|
|
158
|
+
manager = FileBackupManager(backup_dir=temp_backup_dir)
|
|
159
|
+
|
|
160
|
+
# 备份文件
|
|
161
|
+
backup_id = manager.backup_file(sample_file)
|
|
162
|
+
backup_file_path = os.path.join(temp_backup_dir, backup_id)
|
|
163
|
+
|
|
164
|
+
# 检查备份文件是否存在
|
|
165
|
+
assert os.path.exists(backup_file_path)
|
|
166
|
+
assert backup_id in manager.metadata
|
|
167
|
+
|
|
168
|
+
# 删除备份
|
|
169
|
+
success = manager.delete_backup(backup_id)
|
|
170
|
+
|
|
171
|
+
# 检查删除结果
|
|
172
|
+
assert success is True
|
|
173
|
+
assert not os.path.exists(backup_file_path)
|
|
174
|
+
assert backup_id not in manager.metadata
|
|
175
|
+
|
|
176
|
+
def test_delete_nonexistent_backup(self, temp_backup_dir):
|
|
177
|
+
"""测试删除不存在的备份"""
|
|
178
|
+
manager = FileBackupManager(backup_dir=temp_backup_dir)
|
|
179
|
+
|
|
180
|
+
# 尝试删除不存在的备份
|
|
181
|
+
success = manager.delete_backup("nonexistent_backup_id")
|
|
182
|
+
|
|
183
|
+
# 应该返回False
|
|
184
|
+
assert success is False
|
|
185
|
+
|
|
186
|
+
def test_get_backups_for_file(self, temp_backup_dir, sample_file):
|
|
187
|
+
"""测试获取指定文件的所有备份"""
|
|
188
|
+
manager = FileBackupManager(backup_dir=temp_backup_dir)
|
|
189
|
+
|
|
190
|
+
# 创建多个备份
|
|
191
|
+
backup_ids = []
|
|
192
|
+
for i in range(3):
|
|
193
|
+
backup_id = manager.backup_file(sample_file)
|
|
194
|
+
backup_ids.append(backup_id)
|
|
195
|
+
|
|
196
|
+
# 获取文件的备份列表
|
|
197
|
+
backups = manager.get_backups_for_file(sample_file)
|
|
198
|
+
|
|
199
|
+
# 检查备份列表
|
|
200
|
+
assert len(backups) == 3
|
|
201
|
+
for backup_id, timestamp in backups:
|
|
202
|
+
assert backup_id in backup_ids
|
|
203
|
+
assert isinstance(timestamp, float)
|
|
204
|
+
|
|
205
|
+
@pytest.mark.parametrize("max_age_days", [1, 7, 30])
|
|
206
|
+
def test_clean_old_backups(self, temp_backup_dir, sample_file, max_age_days):
|
|
207
|
+
"""测试清理旧备份"""
|
|
208
|
+
manager = FileBackupManager(backup_dir=temp_backup_dir)
|
|
209
|
+
|
|
210
|
+
# 创建一个备份
|
|
211
|
+
backup_id = manager.backup_file(sample_file)
|
|
212
|
+
|
|
213
|
+
# 修改备份的时间戳为过去的时间
|
|
214
|
+
old_timestamp = (datetime.now() - timedelta(days=max_age_days+1)).timestamp()
|
|
215
|
+
manager.metadata[backup_id]["timestamp"] = old_timestamp
|
|
216
|
+
manager._save_metadata()
|
|
217
|
+
|
|
218
|
+
# 创建一个新备份
|
|
219
|
+
new_backup_id = manager.backup_file(sample_file)
|
|
220
|
+
|
|
221
|
+
# 清理旧备份
|
|
222
|
+
cleaned_count = manager.clean_old_backups(max_age_days)
|
|
223
|
+
|
|
224
|
+
# 检查清理结果
|
|
225
|
+
assert cleaned_count == 1
|
|
226
|
+
assert backup_id not in manager.metadata
|
|
227
|
+
assert not os.path.exists(os.path.join(temp_backup_dir, backup_id))
|
|
228
|
+
assert new_backup_id in manager.metadata
|
|
229
|
+
assert os.path.exists(os.path.join(temp_backup_dir, new_backup_id))
|
|
230
|
+
|
|
231
|
+
def test_metadata_persistence(self, temp_backup_dir, sample_file):
|
|
232
|
+
"""测试元数据持久化"""
|
|
233
|
+
# 创建一个备份
|
|
234
|
+
manager1 = FileBackupManager(backup_dir=temp_backup_dir)
|
|
235
|
+
backup_id = manager1.backup_file(sample_file)
|
|
236
|
+
|
|
237
|
+
# 创建另一个管理器实例,应该加载已存在的元数据
|
|
238
|
+
manager2 = FileBackupManager(backup_dir=temp_backup_dir)
|
|
239
|
+
|
|
240
|
+
# 检查元数据是否被正确加载
|
|
241
|
+
assert backup_id in manager2.metadata
|
|
242
|
+
assert manager2.metadata[backup_id]["original_path"] == sample_file
|