-
Notifications
You must be signed in to change notification settings - Fork 0
/
start.sh
executable file
·498 lines (442 loc) · 16 KB
/
start.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
#!/bin/bash
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 检查并创建必要的目录
ensure_directories() {
local dirs=("database" "migrations" "logs")
for dir in "${dirs[@]}"; do
if [ ! -d "$dir" ]; then
echo -e "${YELLOW}创建${dir}目录...${NC}"
mkdir -p "$dir"
if [ $? -eq 0 ]; then
echo -e "${GREEN}${dir}目录创建成功${NC}"
else
echo -e "${RED}${dir}目录创建失败${NC}"
return 1
fi
fi
done
return 0
}
# 检查conda是否已安装
check_conda() {
if ! command -v conda &> /dev/null; then
echo -e "${RED}错误: 未找到conda,请先安装Anaconda或Miniconda${NC}"
exit 1
fi
}
# 检查并创建conda环境
setup_conda_env() {
if ! conda env list | grep -q "^fund "; then
echo -e "${YELLOW}创建新的conda环境: fund${NC}"
if ! conda create -n fund python=3.10 -y; then
echo -e "${RED}创建conda环境失败${NC}"
read -p "按回车键继续..."
return 1
fi
echo -e "${GREEN}conda环境创建成功${NC}"
else
echo -e "${GREEN}fund环境已存在${NC}"
fi
return 0
}
# 激活conda环境
activate_conda_env() {
echo -e "${YELLOW}激活fund环境${NC}"
source "$(conda info --base)/etc/profile.d/conda.sh"
if ! conda activate fund; then
echo -e "${RED}激活conda环境失败${NC}"
read -p "按回车键继续..."
exit 1
fi
echo -e "${GREEN}conda环境激活成功${NC}"
return 0
}
# 检查poetry是否已安装
check_poetry() {
if ! command -v poetry &> /dev/null; then
echo -e "${RED}错误: 未找到poetry,正在安装...${NC}"
# 获取当前conda环境信息
conda_env=$(conda info --envs | grep "*" | awk '{print $1}')
echo -e "${YELLOW}当前conda环境: ${conda_env}${NC}"
if ! conda install -y poetry; then
echo -e "${RED}安装poetry失败${NC}"
exit 1
fi
fi
return 0
}
# 创建并配置环境
setup_env() {
echo -e "${YELLOW}配置开发环境...${NC}"
# 获取poetry版本
poetry_version=$(poetry --version | cut -d' ' -f3)
echo -e "${GREEN}当前poetry版本: $poetry_version${NC}"
# 配置poetry不使用虚拟环境
echo -e "${YELLOW}配置poetry...${NC}"
poetry config virtualenvs.create false
# 安装项目依赖
echo -e "${YELLOW}安装项目依赖...${NC}"
if ! poetry install; then
echo -e "${RED}安装依赖失败${NC}"
echo -e "按回车键返回主菜单..."
read
return 1
fi
echo -e "${GREEN}环境配置成功${NC}"
read -p "按回车键继续..."
return 0
}
# 初始化数据库
init_database() {
echo -e "${YELLOW}迁移数据库...${NC}"
# 确保必要的目录存在
ensure_directories || return 1
# 运行数据库迁移
if ! python -m migrations.migrate; then
echo -e "${RED}数据库迁移失败!${NC}"
read -p "按回车键继续..."
return 1
fi
echo -e "${GREEN}数据库迁移完成!${NC}"
return 0
}
# 运行代码格式检查
run_code_check() {
echo -e "${YELLOW}运行代码检查...${NC}"
local has_error=0
local python_files=$(find . -type f -name "*.py" ! -path "*/\.*" ! -path "*/migrations/*" ! -path "*/venv/*" ! -path "*/env/*")
# 运行isort检查代码格式
echo -e "\n${YELLOW}[1/2] 运行isort检查代码格式...${NC}"
if ! isort --check $python_files; then
echo -e "${YELLOW}代码格式需要调整,正在格式化...${NC}"
if ! isort $python_files; then
echo -e "${RED}isort 格式化失败${NC}"
has_error=1
fi
fi
# 运行black检查代码格式
echo -e "\n${YELLOW}[1/2] 运行black检查代码格式...${NC}"
if ! black --check $python_files; then
echo -e "${YELLOW}代码格式需要调整,正在格式化...${NC}"
if ! black $python_files; then
echo -e "${RED}black 格式化失败${NC}"
has_error=1
else
echo -e "${GREEN}代码格式化完成${NC}"
fi
else
echo -e "${GREEN}代码格式检查通过${NC}"
fi
# 运行pylint检查代码质量
echo -e "\n${YELLOW}[2/2] 运行pylint检查代码质量...${NC}"
# 创建临时文件存储pylint输出
local temp_file=$(mktemp)
local prev_rate=""
local curr_rate=""
local total_files=0
local total_errors=0
local total_warnings=0
local total_conventions=0
local total_refactors=0
# 统计Python文件总数
total_files=$(echo "$python_files" | wc -w)
if ! pylint $python_files > "$temp_file" 2>&1; then
echo -e "\n${RED}发现以下问题:${NC}"
# 统计各类问题数量
while IFS= read -r line; do
if [[ $line =~ :[0-9]+:[0-9]+:[[:space:]][E] ]]; then
((total_errors++))
elif [[ $line =~ :[0-9]+:[0-9]+:[[:space:]][W] ]]; then
((total_warnings++))
elif [[ $line =~ :[0-9]+:[0-9]+:[[:space:]][C] ]]; then
((total_conventions++))
elif [[ $line =~ :[0-9]+:[0-9]+:[[:space:]][R] ]]; then
((total_refactors++))
fi
done < "$temp_file"
# 提取评分信息
curr_rate=$(grep "Your code has been rated at" "$temp_file" | tail -n1)
# 显示详细错误信息
echo -e "\n${YELLOW}=== 详细错误信息 ===${NC}"
while IFS= read -r line; do
if [[ $line =~ ^\*+[[:space:]]Module[[:space:]] ]]; then
# 提取模块名
module_name=$(echo "$line" | sed 's/\*\+ Module //')
echo -e "\n文件: ${module_name}"
elif [[ $line =~ ^[[:space:]]*[A-Za-z0-9/_.-]+:[0-9]+:[0-9]+:[[:space:]] ]]; then
# 格式化错误信息
error_line=$(echo "$line" | sed -E 's/^[[:space:]]*([^:]+):([0-9]+):([0-9]+): ([A-Z][0-9]+): (.+)/ ✗ \1:\2:\3: \4: \5/')
# 根据错误类型添加颜色
if [[ $line =~ :[[:space:]][E][0-9] ]]; then
echo -e "${RED}$error_line${NC}"
elif [[ $line =~ :[[:space:]][W][0-9] ]]; then
echo -e "${YELLOW}$error_line${NC}"
elif [[ $line =~ :[[:space:]][R][0-9] ]]; then
echo -e "${BLUE}$error_line${NC}"
else
echo -e "${GREEN}$error_line${NC}"
fi
fi
done < "$temp_file"
# 显示错误和警告汇总
echo -e "\n${YELLOW}=== 错误和警告汇总 ===${NC}"
# 创建临时文件存储汇总信息
local summary_file=$(mktemp)
grep -E "^[[:space:]]*[A-Za-z0-9/_.-]+:[0-9]+:[0-9]+:[[:space:]][EWCR][0-9]+" "$temp_file" | \
sed -E 's/.*:[0-9]+:[0-9]+: ([A-Z][0-9]+): .*/\1/' | \
sort | uniq -c | sort -nr > "$summary_file"
if [ -s "$summary_file" ]; then
while IFS= read -r line; do
count=$(echo "$line" | awk '{print $1}')
code=$(echo "$line" | awk '{print $2}')
msg=$(grep -m 1 ": $code: " "$temp_file" | sed -E 's/.*: [A-Z][0-9]+: (.*)/\1/')
# 根据错误代码类型添加颜色
if [[ $code =~ ^E ]]; then
echo -e "${RED}$count 个 $code: $msg${NC}"
elif [[ $code =~ ^W ]]; then
echo -e "${YELLOW}$count 个 $code: $msg${NC}"
elif [[ $code =~ ^R ]]; then
echo -e "${BLUE}$count 个 $code: $msg${NC}"
else
echo -e "${GREEN}$count 个 $code: $msg${NC}"
fi
done < "$summary_file"
else
echo -e "${GREEN}未发现错误和警告${NC}"
fi
# 清理临时文件
rm -f "$summary_file"
# 显示统计信息
echo -e "\n${YELLOW}=== 问题统计 ===${NC}"
printf "检查文件数: %8d\n" "${total_files}"
printf "${RED}错误(E): %8d${NC}\n" "${total_errors}"
printf "${YELLOW}警告(W): %8d${NC}\n" "${total_warnings}"
printf "${GREEN}规范(C): %8d${NC}\n" "${total_conventions}"
printf "${BLUE}重构(R): %8d${NC}\n" "${total_refactors}"
printf "问题总数: %8d\n" "$((total_errors + total_warnings + total_conventions + total_refactors))"
# 显示代码质量评分
echo -e "\n${YELLOW}=== 代码质量评分 ===${NC}"
if [ -n "$curr_rate" ]; then
# 解析评分信息
current=$(echo "$curr_rate" | sed -E 's/.*rated at ([0-9]+\.[0-9]+).*/\1/')
previous=$(echo "$curr_rate" | sed -E 's/.*previous run: ([0-9]+\.[0-9]+).*/\1/')
change=$(echo "$curr_rate" | sed -E 's/.*[0-9]+\.[0-9]+\/10 \((.*)\)/\1/' | grep -o '[+-][0-9.]\+')
# 显示评分信息
if [ -n "$previous" ] && [ -n "$change" ]; then
if [[ "$change" == +* ]]; then
echo -e "${GREEN}当前评分: $current/10${NC}"
echo -e "${GREEN}评分提升: $change (上次: $previous/10)${NC}"
elif [[ "$change" == -* ]]; then
echo -e "${RED}当前评分: $current/10${NC}"
echo -e "${RED}评分下降: $change (上次: $previous/10)${NC}"
else
echo -e "${YELLOW}当前评分: $current/10${NC}"
echo -e "${YELLOW}评分未变 (上次: $previous/10)${NC}"
fi
else
echo -e "${YELLOW}当前评分: $current/10${NC}"
echo -e "${YELLOW}首次检查,无历史评分${NC}"
fi
# 根据评分显示状态
if (( $(echo "$current >= 9.0" | bc -l) )); then
echo -e "\n${GREEN}✨ 代码质量优秀!继续保持${NC}"
elif (( $(echo "$current >= 8.0" | bc -l) )); then
echo -e "\n${GREEN}👍 代码质量良好${NC}"
elif (( $(echo "$current >= 7.0" | bc -l) )); then
echo -e "\n${YELLOW}⚠️ 代码质量一般,建议改进${NC}"
else
echo -e "\n${RED}⚠️ 代码质量需要改进${NC}"
echo -e "\n${YELLOW}改进建议:${NC}"
echo -e "1. 优先修复 ${RED}错误(E)${NC} 级别问题"
echo -e "2. 处理重要的 ${YELLOW}警告(W)${NC} 问题"
echo -e "3. 考虑优化 ${GREEN}规范(C)${NC} 建议"
echo -e "4. 关注需要 ${BLUE}重构(R)${NC} 的代码"
fi
else
echo -e "${RED}无法解析评分信息${NC}"
fi
# 保存当前分
echo "$curr_rate" > .pylint_rate
has_error=1
echo -e "\n${YELLOW}提示: 使用 pylint --help-msg=<msg-id> 查看具体错误说明${NC}"
else
echo -e "${GREEN}代码质量检查通过${NC}"
# 清除之前的评分记录
rm -f .pylint_rate
fi
# 清理临时文件
rm -f "$temp_file"
if [ $has_error -eq 1 ]; then
return 1
fi
return 0
}
# 启动应用
start_app() {
echo -e "${YELLOW}启动基金分析应用...${NC}"
if ! python app.py; then
echo -e "${RED}应用启动失败${NC}"
read -p "按回车键继续..."
return 1
fi
return 0
}
# 启动测试
start_test() {
echo -e "${YELLOW}启动测试代码...${NC}"
if ! python test.py; then
return 1
fi
return 0
}
# 显示菜单
show_menu() {
clear
echo -e "${GREEN}基金分析系统管理脚本${NC}"
echo "------------------------"
echo "1) 初始化环境"
echo "2) 迁移数据库"
echo "3) 运行代码检查"
echo "4) 启动应用"
echo "5) 完整安装(1-4步骤)"
echo "6) 备份数据库"
echo "------------"
echo "8) 清理日志"
echo "9) 测试"
echo "0) 退出"
echo "------------------------"
}
# 执行完整安装
do_full_install() {
echo -e "${YELLOW}开始完整安装...${NC}"
ensure_directories || return 1
check_conda || return 1
setup_conda_env || return 1
activate_conda_env || return 1
check_poetry || return 1
setup_env || return 1
init_database || return 1
run_code_check || return 1
start_app || return 1
return 0
}
# 添加清理日志文件的函数
clean_logs() {
echo -e "${YELLOW}开始清理日志文件...${NC}"
if [ -d "logs" ]; then
rm -f logs/*
if [ $? -eq 0 ]; then
echo -e "${GREEN}日志文件清理完成${NC}"
else
echo -e "${RED}日志文件清理失败${NC}"
return 1
fi
else
echo -e "${YELLOW}logs目录不存在,无需清理${NC}"
fi
return 0
}
# 修改backup_database函数
backup_database() {
echo -e "${YELLOW}开始备份数据库...${NC}"
# 检查database目录是否存在
if [ ! -d "database" ]; then
echo -e "${RED}错误: database目录不存在${NC}"
return 1
fi
# 创建backups目录(如果不存在)
if [ ! -d "backups" ]; then
mkdir -p backups
fi
# 生成备份文件名(使用当前时间戳)
backup_file="backups/db_backup_$(date +%Y%m%d_%H%M%S).zip"
# 执行备份
if zip -r "$backup_file" database/*.db > /dev/null 2>&1; then
echo -e "${GREEN}数据库备份成功: $backup_file${NC}"
# 保留最近5个备份文件
echo -e "${YELLOW}清理旧备份文件...${NC}"
backup_count=$(ls -t backups/db_backup_*.zip 2>/dev/null | wc -l)
if [ "$backup_count" -gt 5 ]; then
ls -t backups/db_backup_*.zip | tail -n +6 | xargs rm -f
echo -e "${GREEN}已清理旧备份文件,保留最近5个备份${NC}"
fi
return 0
else
echo -e "${RED}数据库备份失败${NC}"
return 1
fi
}
# 主循环
while true; do
show_menu
read -p "请选择操作 (0-5): " choice
case $choice in
1)
echo -e "${YELLOW}开始初始化环境...${NC}"
ensure_directories || continue
check_conda || continue
setup_conda_env || continue
activate_conda_env || continue
check_poetry || continue
setup_env || continue
if [ $? -eq 0 ]; then
echo -e "${GREEN}环境初始化完成!${NC}"
fi
;;
2)
backup_database
echo -e "${YELLOW}开始迁移数据库...${NC}"
init_database || continue
;;
3)
echo -e "${YELLOW}开始运行代码检查...${NC}"
if run_code_check; then
echo -e "\n${GREEN}所有代码检查完成,未发现问题${NC}"
else
echo -e "\n${RED}代码检查发现问题,请根据上方提示进行修复${NC}"
echo -e "\n${YELLOW}提示: 使用 pylint --help-msg=<msg-id> 查看具体错误说明${NC}"
fi
echo -e "\n按回车键返回主菜单..."
read
;;
4)
echo -e "${YELLOW}开始启动应用...${NC}"
ensure_directories || continue
activate_conda_env || continue
clean_logs
backup_database
start_app
;;
5)
do_full_install || continue
;;
6)
backup_database
;;
8)
clean_logs
;;
9)
start_test
;;
0)
echo -e "${GREEN}再见!${NC}"
exit 0
;;
*)
echo -e "${RED}无效的选择,请重试${NC}"
echo -e "按回车键返回主菜单..."
;;
esac
# 如果不是启动应用,则等待用户按回车继续
if [ "$choice" != "3" ] && [ "$choice" != "4" ] && [ "$choice" != "5" ]; then
echo
echo -e "按回车键返回主菜单..."
read
fi
done