auto-coder 0.1.288__py3-none-any.whl → 0.1.290__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.288.dist-info → auto_coder-0.1.290.dist-info}/METADATA +2 -2
- {auto_coder-0.1.288.dist-info → auto_coder-0.1.290.dist-info}/RECORD +25 -21
- autocoder/auto_coder_rag.py +10 -0
- autocoder/chat_auto_coder_lang.py +16 -16
- autocoder/common/__init__.py +4 -0
- autocoder/common/auto_coder_lang.py +16 -4
- autocoder/common/mcp_hub.py +99 -77
- autocoder/common/mcp_server.py +162 -61
- autocoder/index/filter/quick_filter.py +373 -3
- autocoder/rag/api_server.py +48 -0
- autocoder/rag/cache/byzer_storage_cache.py +254 -44
- autocoder/rag/cache/cache_result_merge.py +265 -0
- autocoder/rag/cache/file_monitor_cache.py +117 -4
- autocoder/rag/cache/local_byzer_storage_cache.py +286 -58
- autocoder/rag/cache/rag_file_meta.py +494 -0
- autocoder/rag/cache/simple_cache.py +67 -3
- autocoder/rag/conversation_to_queries.py +139 -0
- autocoder/rag/long_context_rag.py +31 -12
- autocoder/rag/qa_conversation_strategy.py +21 -10
- autocoder/rag/searchable.py +58 -0
- autocoder/version.py +1 -1
- {auto_coder-0.1.288.dist-info → auto_coder-0.1.290.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.288.dist-info → auto_coder-0.1.290.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.288.dist-info → auto_coder-0.1.290.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.288.dist-info → auto_coder-0.1.290.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
from typing import List, Dict, Any, Optional, Set, Tuple
|
|
2
|
+
import logging
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from collections import defaultdict, Counter
|
|
5
|
+
from loguru import logger
|
|
6
|
+
class MergeStrategy(str, Enum):
|
|
7
|
+
"""合并策略枚举类"""
|
|
8
|
+
SIMPLE_EXTEND = "simple_extend" # 简单扩展(当前实现)
|
|
9
|
+
FREQUENCY_RANK = "frequency_rank" # 按频率排序
|
|
10
|
+
WEIGHTED_RANK = "weighted_rank" # 加权排序
|
|
11
|
+
INTERLEAVE = "interleave" # 交错合并
|
|
12
|
+
DEDUPLICATE = "deduplicate" # 去重合并
|
|
13
|
+
QUERY_WEIGHTED = "query_weighted" # 按查询加权
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class CacheResultMerger:
|
|
17
|
+
"""
|
|
18
|
+
缓存结果合并策略模块
|
|
19
|
+
|
|
20
|
+
本模块提供了多种合并搜索结果的策略,用于处理多查询场景下的结果整合。
|
|
21
|
+
|
|
22
|
+
主要包括:
|
|
23
|
+
1. 简单扩展 (SIMPLE_EXTEND): 直接合并所有结果列表
|
|
24
|
+
2. 频率排序 (FREQUENCY_RANK): 根据文件路径出现频率排序
|
|
25
|
+
3. 加权排序 (WEIGHTED_RANK): 考虑结果排名位置的加权排序
|
|
26
|
+
4. 交错合并 (INTERLEAVE): 交错合并多个查询结果
|
|
27
|
+
5. 去重合并 (DEDUPLICATE): 合并结果并去除重复文件
|
|
28
|
+
6. 查询加权 (QUERY_WEIGHTED): 考虑查询重要性的加权排序
|
|
29
|
+
|
|
30
|
+
使用示例:
|
|
31
|
+
```python
|
|
32
|
+
from cache_result_merge import CacheResultMerger, MergeStrategy
|
|
33
|
+
|
|
34
|
+
# 创建合并器
|
|
35
|
+
merger = CacheResultMerger(max_results=100)
|
|
36
|
+
|
|
37
|
+
# 假设有多个查询结果
|
|
38
|
+
query_results = [
|
|
39
|
+
("query1", [result1, result2, ...]),
|
|
40
|
+
("query2", [result3, result4, ...])
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
# 使用特定策略合并
|
|
44
|
+
merged_results = merger.merge(
|
|
45
|
+
query_results,
|
|
46
|
+
strategy=MergeStrategy.WEIGHTED_RANK
|
|
47
|
+
)
|
|
48
|
+
```
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def __init__(self, max_results: int = None):
|
|
52
|
+
"""
|
|
53
|
+
初始化结果合并器
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
max_results: 最大结果数,如果为None则不限制
|
|
57
|
+
"""
|
|
58
|
+
self.max_results = max_results
|
|
59
|
+
|
|
60
|
+
def merge(self, query_results: List[Tuple[str, List[Dict[str, Any]]]],
|
|
61
|
+
strategy: MergeStrategy = MergeStrategy.WEIGHTED_RANK) -> List[Dict[str, Any]]:
|
|
62
|
+
"""
|
|
63
|
+
根据指定策略合并查询结果
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
query_results: 查询结果列表,每项为(查询, 结果列表)的元组
|
|
67
|
+
strategy: 合并策略
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
合并后的结果列表
|
|
71
|
+
"""
|
|
72
|
+
if strategy == MergeStrategy.SIMPLE_EXTEND:
|
|
73
|
+
return self._simple_extend_merge(query_results)
|
|
74
|
+
elif strategy == MergeStrategy.FREQUENCY_RANK:
|
|
75
|
+
return self._frequency_rank_merge(query_results)
|
|
76
|
+
elif strategy == MergeStrategy.WEIGHTED_RANK:
|
|
77
|
+
return self._weighted_rank_merge(query_results)
|
|
78
|
+
elif strategy == MergeStrategy.INTERLEAVE:
|
|
79
|
+
return self._interleave_merge(query_results)
|
|
80
|
+
elif strategy == MergeStrategy.DEDUPLICATE:
|
|
81
|
+
return self._deduplicate_merge(query_results)
|
|
82
|
+
elif strategy == MergeStrategy.QUERY_WEIGHTED:
|
|
83
|
+
return self._query_weighted_merge(query_results)
|
|
84
|
+
else:
|
|
85
|
+
logger.warning(f"未知的合并策略: {strategy},使用简单扩展策略")
|
|
86
|
+
return self._simple_extend_merge(query_results)
|
|
87
|
+
|
|
88
|
+
def _simple_extend_merge(self, query_results: List[Tuple[str, List[Dict[str, Any]]]]) -> List[Dict[str, Any]]:
|
|
89
|
+
"""
|
|
90
|
+
简单扩展策略:将所有结果简单合并
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
query_results: 查询结果列表
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
合并后的结果列表
|
|
97
|
+
"""
|
|
98
|
+
all_results = []
|
|
99
|
+
for query, results in query_results:
|
|
100
|
+
all_results.extend(results)
|
|
101
|
+
|
|
102
|
+
logger.info(f"简单扩展策略合并结果: 从 {sum(len(r) for _, r in query_results)} 条到 {len(all_results)} 条")
|
|
103
|
+
return all_results[:self.max_results] if self.max_results else all_results
|
|
104
|
+
|
|
105
|
+
def _frequency_rank_merge(self, query_results: List[Tuple[str, List[Dict[str, Any]]]]) -> List[Dict[str, Any]]:
|
|
106
|
+
"""
|
|
107
|
+
频率排序策略:按文件路径出现频率排序
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
query_results: 查询结果列表
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
合并后的结果列表
|
|
114
|
+
"""
|
|
115
|
+
# 合并所有结果
|
|
116
|
+
all_results = []
|
|
117
|
+
for _, results in query_results:
|
|
118
|
+
all_results.extend(results)
|
|
119
|
+
|
|
120
|
+
# 按文件路径计数
|
|
121
|
+
file_path_counts = Counter(result["file_path"] for result in all_results)
|
|
122
|
+
|
|
123
|
+
# 建立文件路径到结果的映射,保留每个文件路径的第一个结果
|
|
124
|
+
file_to_result = {}
|
|
125
|
+
for result in all_results:
|
|
126
|
+
file_path = result["file_path"]
|
|
127
|
+
if file_path not in file_to_result:
|
|
128
|
+
file_to_result[file_path] = result
|
|
129
|
+
|
|
130
|
+
# 按频率排序
|
|
131
|
+
sorted_results = [file_to_result[file_path] for file_path, _ in file_path_counts.most_common()]
|
|
132
|
+
|
|
133
|
+
logger.info(f"频率排序策略合并结果: 从 {len(all_results)} 条到 {len(sorted_results)} 条,按文件出现频率排序")
|
|
134
|
+
return sorted_results[:self.max_results] if self.max_results else sorted_results
|
|
135
|
+
|
|
136
|
+
def _weighted_rank_merge(self, query_results: List[Tuple[str, List[Dict[str, Any]]]]) -> List[Dict[str, Any]]:
|
|
137
|
+
"""
|
|
138
|
+
加权排序策略:考虑结果位置和频率的加权排序
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
query_results: 查询结果列表
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
合并后的结果列表
|
|
145
|
+
"""
|
|
146
|
+
# 按文件路径评分
|
|
147
|
+
file_path_scores = defaultdict(float)
|
|
148
|
+
file_to_result = {}
|
|
149
|
+
|
|
150
|
+
for _, results in query_results:
|
|
151
|
+
for rank, result in enumerate(results):
|
|
152
|
+
file_path = result["file_path"]
|
|
153
|
+
# 排名越高,得分越高(排名从0开始,所以用1/(rank+1))
|
|
154
|
+
rank_score = 1.0 / (rank + 1)
|
|
155
|
+
file_path_scores[file_path] += rank_score
|
|
156
|
+
|
|
157
|
+
# 保存每个文件路径的第一个结果
|
|
158
|
+
if file_path not in file_to_result:
|
|
159
|
+
file_to_result[file_path] = result
|
|
160
|
+
|
|
161
|
+
# 按分数排序
|
|
162
|
+
sorted_results = [file_to_result[file_path]
|
|
163
|
+
for file_path, _ in sorted(file_path_scores.items(), key=lambda x: x[1], reverse=True)]
|
|
164
|
+
|
|
165
|
+
logger.info(f"加权排序策略合并结果: 得到 {len(sorted_results)} 条结果,按位置加权排序")
|
|
166
|
+
return sorted_results[:self.max_results] if self.max_results else sorted_results
|
|
167
|
+
|
|
168
|
+
def _interleave_merge(self, query_results: List[Tuple[str, List[Dict[str, Any]]]]) -> List[Dict[str, Any]]:
|
|
169
|
+
"""
|
|
170
|
+
交错合并策略:交错合并各查询的结果
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
query_results: 查询结果列表
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
合并后的结果列表
|
|
177
|
+
"""
|
|
178
|
+
# 获取每个查询的结果列表
|
|
179
|
+
result_lists = [results for _, results in query_results]
|
|
180
|
+
if not result_lists:
|
|
181
|
+
return []
|
|
182
|
+
|
|
183
|
+
# 交错合并结果
|
|
184
|
+
interleaved = []
|
|
185
|
+
seen_files = set()
|
|
186
|
+
|
|
187
|
+
# 找出最长列表长度
|
|
188
|
+
max_len = max(len(results) for results in result_lists)
|
|
189
|
+
|
|
190
|
+
# 交错合并
|
|
191
|
+
for i in range(max_len):
|
|
192
|
+
for results in result_lists:
|
|
193
|
+
if i < len(results):
|
|
194
|
+
result = results[i]
|
|
195
|
+
file_path = result["file_path"]
|
|
196
|
+
if file_path not in seen_files:
|
|
197
|
+
seen_files.add(file_path)
|
|
198
|
+
interleaved.append(result)
|
|
199
|
+
|
|
200
|
+
logger.info(f"交错合并策略合并结果: 得到 {len(interleaved)} 条唯一结果")
|
|
201
|
+
return interleaved[:self.max_results] if self.max_results else interleaved
|
|
202
|
+
|
|
203
|
+
def _deduplicate_merge(self, query_results: List[Tuple[str, List[Dict[str, Any]]]]) -> List[Dict[str, Any]]:
|
|
204
|
+
"""
|
|
205
|
+
去重合并策略:合并并去除重复的文件路径
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
query_results: 查询结果列表
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
合并后的结果列表
|
|
212
|
+
"""
|
|
213
|
+
all_results = []
|
|
214
|
+
seen_files = set()
|
|
215
|
+
|
|
216
|
+
for _, results in query_results:
|
|
217
|
+
for result in results:
|
|
218
|
+
file_path = result["file_path"]
|
|
219
|
+
if file_path not in seen_files:
|
|
220
|
+
seen_files.add(file_path)
|
|
221
|
+
all_results.append(result)
|
|
222
|
+
|
|
223
|
+
logger.info(f"去重合并策略合并结果: 从 {sum(len(r) for _, r in query_results)} 条到 {len(all_results)} 条唯一结果")
|
|
224
|
+
return all_results[:self.max_results] if self.max_results else all_results
|
|
225
|
+
|
|
226
|
+
def _query_weighted_merge(self, query_results: List[Tuple[str, List[Dict[str, Any]]]]) -> List[Dict[str, Any]]:
|
|
227
|
+
"""
|
|
228
|
+
查询加权策略:根据查询的重要性加权排序结果
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
query_results: 查询结果列表,包含(查询, 结果)对
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
合并后的结果列表
|
|
235
|
+
"""
|
|
236
|
+
# 按照查询词加权
|
|
237
|
+
file_path_scores = defaultdict(float)
|
|
238
|
+
file_to_result = {}
|
|
239
|
+
query_weights = {}
|
|
240
|
+
|
|
241
|
+
# 计算每个查询的权重 (可以根据查询的长度、特殊性等调整)
|
|
242
|
+
total_queries = len(query_results)
|
|
243
|
+
for i, (query, _) in enumerate(query_results):
|
|
244
|
+
# 默认权重,可以根据查询特性调整
|
|
245
|
+
query_weights[query] = 1.0
|
|
246
|
+
|
|
247
|
+
# 计算文件得分
|
|
248
|
+
for query, results in query_results:
|
|
249
|
+
query_weight = query_weights[query]
|
|
250
|
+
for rank, result in enumerate(results):
|
|
251
|
+
file_path = result["file_path"]
|
|
252
|
+
# 排名越高,得分越高
|
|
253
|
+
rank_score = 1.0 / (rank + 1)
|
|
254
|
+
file_path_scores[file_path] += rank_score * query_weight
|
|
255
|
+
|
|
256
|
+
# 保存每个文件路径的第一个结果
|
|
257
|
+
if file_path not in file_to_result:
|
|
258
|
+
file_to_result[file_path] = result
|
|
259
|
+
|
|
260
|
+
# 按分数排序
|
|
261
|
+
sorted_results = [file_to_result[file_path]
|
|
262
|
+
for file_path, _ in sorted(file_path_scores.items(), key=lambda x: x[1], reverse=True)]
|
|
263
|
+
|
|
264
|
+
logger.info(f"查询加权策略合并结果: 得到 {len(sorted_results)} 条结果,按查询加权排序")
|
|
265
|
+
return sorted_results[:self.max_results] if self.max_results else sorted_results
|
|
@@ -11,6 +11,17 @@ from watchfiles import Change, DefaultFilter, awatch, watch
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class AutoCoderRAGDocListener(BaseCacheManager):
|
|
14
|
+
"""
|
|
15
|
+
基于文件系统实时监控的代码缓存管理器。
|
|
16
|
+
|
|
17
|
+
此类实现了对代码库的实时监控,当文件发生变化时(新增、修改、删除)自动更新缓存。
|
|
18
|
+
与其他缓存管理器不同,它使用 watchfiles 库进行文件变更监控,无需定期扫描文件系统。
|
|
19
|
+
|
|
20
|
+
类属性:
|
|
21
|
+
cache: 缓存字典,存储处理后的文件内容
|
|
22
|
+
ignore_dirs: 需要忽略的目录列表
|
|
23
|
+
ignore_entity_patterns: 需要忽略的文件模式列表
|
|
24
|
+
"""
|
|
14
25
|
cache: Dict[str, Dict] = {}
|
|
15
26
|
ignore_dirs = [
|
|
16
27
|
"__pycache__",
|
|
@@ -38,6 +49,43 @@ class AutoCoderRAGDocListener(BaseCacheManager):
|
|
|
38
49
|
]
|
|
39
50
|
|
|
40
51
|
def __init__(self, path: str, ignore_spec, required_exts: List) -> None:
|
|
52
|
+
"""
|
|
53
|
+
初始化文件监控缓存管理器。
|
|
54
|
+
|
|
55
|
+
参数:
|
|
56
|
+
path: 需要监控的代码库根目录
|
|
57
|
+
ignore_spec: 指定哪些文件/目录应被忽略的规则
|
|
58
|
+
required_exts: 需要处理的文件扩展名列表
|
|
59
|
+
|
|
60
|
+
缓存结构 (self.cache):
|
|
61
|
+
self.cache 是一个字典,其结构比其他缓存管理器更简单:
|
|
62
|
+
{
|
|
63
|
+
"file_path1": { # 键为文件的绝对路径
|
|
64
|
+
"file_path": str, # 文件的绝对路径
|
|
65
|
+
"content": List[Dict], # 文件内容的结构化表示,每个元素是 SourceCode 对象的序列化
|
|
66
|
+
},
|
|
67
|
+
"file_path2": { ... },
|
|
68
|
+
...
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
与其他缓存管理器的主要区别:
|
|
72
|
+
1. 不需要存储 MD5 哈希或修改时间,因为文件变更通过监控系统直接获取
|
|
73
|
+
2. 没有本地持久化机制,所有缓存在内存中维护
|
|
74
|
+
3. 缓存更新基于事件驱动,而非定期扫描
|
|
75
|
+
|
|
76
|
+
文件监控机制:
|
|
77
|
+
- 使用 watchfiles 库监控文件系统变更
|
|
78
|
+
- 支持三种事件类型: 添加(added)、修改(modified)、删除(deleted)
|
|
79
|
+
- 使用单独线程进行监控,不阻塞主线程
|
|
80
|
+
- 监控遵循配置的忽略规则和所需扩展名过滤
|
|
81
|
+
- 初始化时会先加载所有符合条件的文件
|
|
82
|
+
|
|
83
|
+
源代码处理:
|
|
84
|
+
使用 process_file_local 函数处理单个文件:
|
|
85
|
+
- 参数: file_path (文件路径)
|
|
86
|
+
- 返回值: List[SourceCode]
|
|
87
|
+
- 文件处理后,直接更新内存中的缓存
|
|
88
|
+
"""
|
|
41
89
|
self.path = path
|
|
42
90
|
self.ignore_spec = ignore_spec
|
|
43
91
|
self.required_exts = required_exts
|
|
@@ -59,13 +107,27 @@ class AutoCoderRAGDocListener(BaseCacheManager):
|
|
|
59
107
|
self.watch_thread.start()
|
|
60
108
|
|
|
61
109
|
def stop(self):
|
|
110
|
+
"""
|
|
111
|
+
停止文件监控线程。
|
|
112
|
+
|
|
113
|
+
设置停止事件并等待监控线程结束,用于在对象销毁前优雅地关闭监控。
|
|
114
|
+
"""
|
|
62
115
|
self.stop_event.set()
|
|
63
116
|
self.watch_thread.join()
|
|
64
117
|
|
|
65
118
|
def __del__(self):
|
|
119
|
+
"""
|
|
120
|
+
析构函数,确保在对象被销毁时停止监控线程。
|
|
121
|
+
"""
|
|
66
122
|
self.stop()
|
|
67
123
|
|
|
68
124
|
def load_first(self):
|
|
125
|
+
"""
|
|
126
|
+
初始化时加载所有符合条件的文件。
|
|
127
|
+
|
|
128
|
+
获取所有符合过滤条件的文件,并将它们添加到缓存中。
|
|
129
|
+
这确保了缓存在开始监控前已经包含所有现有文件。
|
|
130
|
+
"""
|
|
69
131
|
files_to_process = self.get_all_files()
|
|
70
132
|
if not files_to_process:
|
|
71
133
|
return
|
|
@@ -73,6 +135,17 @@ class AutoCoderRAGDocListener(BaseCacheManager):
|
|
|
73
135
|
self.update_cache(item)
|
|
74
136
|
|
|
75
137
|
def update_cache(self, file_path):
|
|
138
|
+
"""
|
|
139
|
+
处理单个文件并更新缓存。
|
|
140
|
+
|
|
141
|
+
参数:
|
|
142
|
+
file_path: 文件的绝对路径
|
|
143
|
+
|
|
144
|
+
处理流程:
|
|
145
|
+
1. 使用 process_file_local 函数解析文件内容
|
|
146
|
+
2. 将解析结果序列化并存储在缓存中
|
|
147
|
+
3. 日志记录更新的文件及当前缓存状态
|
|
148
|
+
"""
|
|
76
149
|
source_code = process_file_local(file_path)
|
|
77
150
|
self.cache[file_path] = {
|
|
78
151
|
"file_path": file_path,
|
|
@@ -82,11 +155,25 @@ class AutoCoderRAGDocListener(BaseCacheManager):
|
|
|
82
155
|
logger.info(f"current cache: {self.cache.keys()}")
|
|
83
156
|
|
|
84
157
|
def remove_cache(self, file_path):
|
|
158
|
+
"""
|
|
159
|
+
从缓存中移除指定文件。
|
|
160
|
+
|
|
161
|
+
参数:
|
|
162
|
+
file_path: 要移除的文件的绝对路径
|
|
163
|
+
"""
|
|
85
164
|
del self.cache[file_path]
|
|
86
165
|
logger.info(f"remove cache: {file_path}")
|
|
87
166
|
logger.info(f"current cache: {self.cache.keys()}")
|
|
88
167
|
|
|
89
168
|
def open_watch(self):
|
|
169
|
+
"""
|
|
170
|
+
启动文件系统监控线程。
|
|
171
|
+
|
|
172
|
+
此方法会持续监控文件系统变更,直到 stop_event 被设置。
|
|
173
|
+
当检测到文件变更时,会根据变更类型执行相应的操作:
|
|
174
|
+
- 添加/修改文件: 调用 update_cache 更新缓存
|
|
175
|
+
- 删除文件: 调用 remove_cache 从缓存中移除
|
|
176
|
+
"""
|
|
90
177
|
logger.info(f"start monitor: {self.path}...")
|
|
91
178
|
for changes in watch(
|
|
92
179
|
self.path, watch_filter=self.file_filter, stop_event=self.stop_event
|
|
@@ -98,26 +185,52 @@ class AutoCoderRAGDocListener(BaseCacheManager):
|
|
|
98
185
|
elif action == Change.deleted:
|
|
99
186
|
self.remove_cache(path)
|
|
100
187
|
|
|
101
|
-
def get_cache(self,options:Optional[Dict[str,Any]]=None):
|
|
188
|
+
def get_cache(self, options: Optional[Dict[str, Any]] = None):
|
|
189
|
+
"""
|
|
190
|
+
获取当前缓存。
|
|
191
|
+
|
|
192
|
+
参数:
|
|
193
|
+
options: 可选的参数,指定获取缓存时的选项
|
|
194
|
+
|
|
195
|
+
返回:
|
|
196
|
+
当前内存中的缓存字典
|
|
197
|
+
"""
|
|
102
198
|
return self.cache
|
|
103
199
|
|
|
104
200
|
def _load_ignore_file(self):
|
|
201
|
+
"""
|
|
202
|
+
加载忽略文件规则。
|
|
203
|
+
|
|
204
|
+
首先尝试加载 .serveignore 文件,如果不存在,则尝试加载 .gitignore 文件。
|
|
205
|
+
|
|
206
|
+
返回:
|
|
207
|
+
包含忽略规则的字符串列表
|
|
208
|
+
"""
|
|
105
209
|
serveignore_path = os.path.join(self.path, ".serveignore")
|
|
106
210
|
gitignore_path = os.path.join(self.path, ".gitignore")
|
|
107
211
|
|
|
108
212
|
if os.path.exists(serveignore_path):
|
|
109
|
-
with open(serveignore_path, "r",encoding="utf-8") as ignore_file:
|
|
213
|
+
with open(serveignore_path, "r", encoding="utf-8") as ignore_file:
|
|
110
214
|
patterns = ignore_file.readlines()
|
|
111
215
|
return [pattern.strip() for pattern in patterns]
|
|
112
216
|
elif os.path.exists(gitignore_path):
|
|
113
|
-
with open(gitignore_path, "r",encoding="utf-8") as ignore_file:
|
|
217
|
+
with open(gitignore_path, "r", encoding="utf-8") as ignore_file:
|
|
114
218
|
patterns = ignore_file.readlines()
|
|
115
219
|
return [pattern.strip() for pattern in patterns]
|
|
116
220
|
return []
|
|
117
221
|
|
|
118
222
|
def get_all_files(self) -> List[str]:
|
|
223
|
+
"""
|
|
224
|
+
获取所有符合条件的文件路径。
|
|
225
|
+
|
|
226
|
+
遍历指定目录,应用忽略规则和扩展名过滤,
|
|
227
|
+
返回所有符合条件的文件的绝对路径。
|
|
228
|
+
|
|
229
|
+
返回:
|
|
230
|
+
符合条件的文件路径列表
|
|
231
|
+
"""
|
|
119
232
|
all_files = []
|
|
120
|
-
for root, dirs, files in os.walk(self.path,followlinks=True):
|
|
233
|
+
for root, dirs, files in os.walk(self.path, followlinks=True):
|
|
121
234
|
dirs[:] = [d for d in dirs if not d.startswith(".")]
|
|
122
235
|
|
|
123
236
|
if self.ignore_spec:
|