style: auto-format code with ruff (cron)

This commit is contained in:
AutoFix Bot
2026-03-02 18:13:08 +08:00
parent 98527c4de4
commit dc783c9d8e
22 changed files with 685 additions and 590 deletions

View File

@@ -123,7 +123,12 @@ class CodeFixer:
if line.rstrip() != line and line.strip(): if line.rstrip() != line and line.strip():
self.issues.append( self.issues.append(
CodeIssue( CodeIssue(
str(file_path), i, "trailing_whitespace", "行尾有空格", "info", line str(file_path),
i,
"trailing_whitespace",
"行尾有空格",
"info",
line,
) )
) )
@@ -198,7 +203,9 @@ class CodeFixer:
for i, line in enumerate(lines, 1): for i, line in enumerate(lines, 1):
if "allow_origins" in line and '["*"]' in line: if "allow_origins" in line and '["*"]' in line:
# 排除扫描工具自身的代码 # 排除扫描工具自身的代码
if "code_reviewer" in str(file_path) or "auto_code_fixer" in str(file_path): if "code_reviewer" in str(file_path) or "auto_code_fixer" in str(
file_path
):
continue continue
self.manual_issues.append( self.manual_issues.append(
CodeIssue( CodeIssue(
@@ -238,10 +245,13 @@ class CodeFixer:
if "os.getenv" in line or "os.environ" in line: if "os.getenv" in line or "os.environ" in line:
continue continue
# 排除示例/测试代码中的占位符 # 排除示例/测试代码中的占位符
if any(x in line.lower() for x in ["your_", "example", "placeholder", "test", "demo"]): if any(
x in line.lower()
for x in ["your_", "example", "placeholder", "test", "demo"]
):
continue continue
# 排除 Enum 定义 # 排除 Enum 定义
if re.search(r'^\s*[A-Z_]+\s* = ', line.strip()): if re.search(r"^\s*[A-Z_]+\s* = ", line.strip()):
continue continue
self.manual_issues.append( self.manual_issues.append(
CodeIssue( CodeIssue(
@@ -303,7 +313,9 @@ class CodeFixer:
line = lines[line_idx] line = lines[line_idx]
# 将 except Exception: 改为 except Exception: # 将 except Exception: 改为 except Exception:
if re.search(r"except\s*:\s*$", line.strip()): if re.search(r"except\s*:\s*$", line.strip()):
lines[line_idx] = line.replace("except Exception:", "except Exception:") lines[line_idx] = line.replace(
"except Exception:", "except Exception:"
)
fixed_lines.add(line_idx) fixed_lines.add(line_idx)
issue.fixed = True issue.fixed = True
self.fixed_issues.append(issue) self.fixed_issues.append(issue)
@@ -355,9 +367,13 @@ class CodeFixer:
report.append("## 问题分类统计") report.append("## 问题分类统计")
report.append("") report.append("")
report.append(f"- 🔴 Critical: {len(categories['critical']) + len(manual_critical)}") report.append(
f"- 🔴 Critical: {len(categories['critical']) + len(manual_critical)}"
)
report.append(f"- 🟠 Error: {len(categories['error'])}") report.append(f"- 🟠 Error: {len(categories['error'])}")
report.append(f"- 🟡 Warning: {len(categories['warning']) + len(manual_warning)}") report.append(
f"- 🟡 Warning: {len(categories['warning']) + len(manual_warning)}"
)
report.append(f"- 🔵 Info: {len(categories['info'])}") report.append(f"- 🔵 Info: {len(categories['info'])}")
report.append(f"- **总计: {len(self.issues) + len(self.manual_issues)}**") report.append(f"- **总计: {len(self.issues) + len(self.manual_issues)}**")
report.append("") report.append("")
@@ -393,11 +409,7 @@ class CodeFixer:
# 其他问题 # 其他问题
report.append("## 📋 其他发现的问题") report.append("## 📋 其他发现的问题")
report.append("") report.append("")
other_issues = [ other_issues = [i for i in self.issues if i not in self.fixed_issues]
i
for i in self.issues
if i not in self.fixed_issues
]
# 按类型分组 # 按类型分组
by_type = {} by_type = {}

View File

@@ -11,16 +11,18 @@ from pathlib import Path
PROJECT_DIR = Path("/root/.openclaw/workspace/projects/insightflow") PROJECT_DIR = Path("/root/.openclaw/workspace/projects/insightflow")
BACKEND_DIR = PROJECT_DIR / "backend" BACKEND_DIR = PROJECT_DIR / "backend"
def run_flake8(): def run_flake8():
"""运行 flake8 检查""" """运行 flake8 检查"""
result = subprocess.run( result = subprocess.run(
["flake8", "--max-line-length=120", "--ignore=E501,W503", "."], ["flake8", "--max-line-length=120", "--ignore=E501,W503", "."],
cwd=BACKEND_DIR, cwd=BACKEND_DIR,
capture_output=True, capture_output=True,
text=True text=True,
) )
return result.stdout return result.stdout
def fix_missing_imports(): def fix_missing_imports():
"""修复缺失的导入""" """修复缺失的导入"""
fixes = [] fixes = []
@@ -31,13 +33,13 @@ def fix_missing_imports():
content = workflow_file.read_text() content = workflow_file.read_text()
if "import urllib" not in content and "urllib" in content: if "import urllib" not in content and "urllib" in content:
# 在文件开头添加导入 # 在文件开头添加导入
lines = content.split('\n') lines = content.split("\n")
import_idx = 0 import_idx = 0
for i, line in enumerate(lines): for i, line in enumerate(lines):
if line.startswith('import ') or line.startswith('from '): if line.startswith("import ") or line.startswith("from "):
import_idx = i + 1 import_idx = i + 1
lines.insert(import_idx, 'import urllib.parse') lines.insert(import_idx, "import urllib.parse")
workflow_file.write_text('\n'.join(lines)) workflow_file.write_text("\n".join(lines))
fixes.append("workflow_manager.py: 添加 urllib.parse 导入") fixes.append("workflow_manager.py: 添加 urllib.parse 导入")
# 检查 plugin_manager.py 中的 urllib # 检查 plugin_manager.py 中的 urllib
@@ -45,31 +47,38 @@ def fix_missing_imports():
if plugin_file.exists(): if plugin_file.exists():
content = plugin_file.read_text() content = plugin_file.read_text()
if "import urllib" not in content and "urllib" in content: if "import urllib" not in content and "urllib" in content:
lines = content.split('\n') lines = content.split("\n")
import_idx = 0 import_idx = 0
for i, line in enumerate(lines): for i, line in enumerate(lines):
if line.startswith('import ') or line.startswith('from '): if line.startswith("import ") or line.startswith("from "):
import_idx = i + 1 import_idx = i + 1
lines.insert(import_idx, 'import urllib.parse') lines.insert(import_idx, "import urllib.parse")
plugin_file.write_text('\n'.join(lines)) plugin_file.write_text("\n".join(lines))
fixes.append("plugin_manager.py: 添加 urllib.parse 导入") fixes.append("plugin_manager.py: 添加 urllib.parse 导入")
# 检查 main.py 中的 PlainTextResponse # 检查 main.py 中的 PlainTextResponse
main_file = BACKEND_DIR / "main.py" main_file = BACKEND_DIR / "main.py"
if main_file.exists(): if main_file.exists():
content = main_file.read_text() content = main_file.read_text()
if "PlainTextResponse" in content and "from fastapi.responses import" in content: if (
"PlainTextResponse" in content
and "from fastapi.responses import" in content
):
# 检查是否已导入 # 检查是否已导入
if "PlainTextResponse" not in content.split('from fastapi.responses import')[1].split('\n')[0]: if (
"PlainTextResponse"
not in content.split("from fastapi.responses import")[1].split("\n")[0]
):
# 添加导入 # 添加导入
content = content.replace( content = content.replace(
"from fastapi.responses import JSONResponse, PlainTextResponse, StreamingResponse", "from fastapi.responses import JSONResponse, PlainTextResponse, StreamingResponse",
"from fastapi.responses import JSONResponse, PlainTextResponse, StreamingResponse" "from fastapi.responses import JSONResponse, PlainTextResponse, StreamingResponse",
) )
# 实际上已经导入了,可能是误报 # 实际上已经导入了,可能是误报
return fixes return fixes
def fix_unused_imports(): def fix_unused_imports():
"""修复未使用的导入""" """修复未使用的导入"""
fixes = [] fixes = []
@@ -80,15 +89,16 @@ def fix_unused_imports():
content = code_reviewer.read_text() content = code_reviewer.read_text()
original = content original = content
# 移除未使用的导入 # 移除未使用的导入
content = re.sub(r'^import os\n', '', content, flags=re.MULTILINE) content = re.sub(r"^import os\n", "", content, flags=re.MULTILINE)
content = re.sub(r'^import subprocess\n', '', content, flags=re.MULTILINE) content = re.sub(r"^import subprocess\n", "", content, flags=re.MULTILINE)
content = re.sub(r'^from typing import Any\n', '', content, flags=re.MULTILINE) content = re.sub(r"^from typing import Any\n", "", content, flags=re.MULTILINE)
if content != original: if content != original:
code_reviewer.write_text(content) code_reviewer.write_text(content)
fixes.append("code_reviewer.py: 移除未使用的导入") fixes.append("code_reviewer.py: 移除未使用的导入")
return fixes return fixes
def fix_formatting(): def fix_formatting():
"""使用 autopep8 修复格式问题""" """使用 autopep8 修复格式问题"""
fixes = [] fixes = []
@@ -98,7 +108,7 @@ def fix_formatting():
["autopep8", "--in-place", "--aggressive", "--max-line-length=120", "."], ["autopep8", "--in-place", "--aggressive", "--max-line-length=120", "."],
cwd=BACKEND_DIR, cwd=BACKEND_DIR,
capture_output=True, capture_output=True,
text=True text=True,
) )
if result.returncode == 0: if result.returncode == 0:
@@ -106,6 +116,7 @@ def fix_formatting():
return fixes return fixes
def main(): def main():
print("=" * 60) print("=" * 60)
print("InsightFlow 代码自动修复") print("InsightFlow 代码自动修复")
@@ -142,12 +153,13 @@ def main():
print("\n重新运行 flake8 检查...") print("\n重新运行 flake8 检查...")
remaining = run_flake8() remaining = run_flake8()
if remaining: if remaining:
lines = remaining.strip().split('\n') lines = remaining.strip().split("\n")
print(f" 仍有 {len(lines)} 个问题需要手动处理") print(f" 仍有 {len(lines)} 个问题需要手动处理")
else: else:
print(" ✓ 所有问题已修复!") print(" ✓ 所有问题已修复!")
return all_fixes return all_fixes
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@@ -350,7 +350,8 @@ class AIManager:
"""获取训练样本""" """获取训练样本"""
with self._get_db() as conn: with self._get_db() as conn:
rows = conn.execute( rows = conn.execute(
"SELECT * FROM training_samples WHERE model_id = ? ORDER BY created_at", (model_id, ) "SELECT * FROM training_samples WHERE model_id = ? ORDER BY created_at",
(model_id,),
).fetchall() ).fetchall()
return [self._row_to_training_sample(row) for row in rows] return [self._row_to_training_sample(row) for row in rows]

View File

@@ -211,7 +211,8 @@ class DatabaseManager:
"""查找相似实体""" """查找相似实体"""
conn = self.get_conn() conn = self.get_conn()
rows = conn.execute( rows = conn.execute(
"SELECT * FROM entities WHERE project_id = ? AND name LIKE ?", (project_id, f"%{name}%") "SELECT * FROM entities WHERE project_id = ? AND name LIKE ?",
(project_id, f"%{name}%"),
).fetchall() ).fetchall()
conn.close() conn.close()
@@ -387,7 +388,8 @@ class DatabaseManager:
def list_project_transcripts(self, project_id: str) -> list[dict]: def list_project_transcripts(self, project_id: str) -> list[dict]:
conn = self.get_conn() conn = self.get_conn()
rows = conn.execute( rows = conn.execute(
"SELECT * FROM transcripts WHERE project_id = ? ORDER BY created_at DESC", (project_id, ) "SELECT * FROM transcripts WHERE project_id = ? ORDER BY created_at DESC",
(project_id,),
).fetchall() ).fetchall()
conn.close() conn.close()
return [dict(r) for r in rows] return [dict(r) for r in rows]
@@ -475,7 +477,9 @@ class DatabaseManager:
conn.execute(query, values) conn.execute(query, values)
conn.commit() conn.commit()
row = conn.execute("SELECT * FROM entity_relations WHERE id = ?", (relation_id, )).fetchone() row = conn.execute(
"SELECT * FROM entity_relations WHERE id = ?", (relation_id,)
).fetchone()
conn.close() conn.close()
return dict(row) if row else None return dict(row) if row else None

View File

@@ -1474,7 +1474,8 @@ class DeveloperEcosystemManager:
# 统计模板数量 # 统计模板数量
template_row = conn.execute( template_row = conn.execute(
"SELECT COUNT(*) as count FROM template_market WHERE author_id = ?", (developer_id, ) "SELECT COUNT(*) as count FROM template_market WHERE author_id = ?",
(developer_id,),
).fetchone() ).fetchone()
# 统计总下载量 # 统计总下载量
@@ -1581,7 +1582,9 @@ class DeveloperEcosystemManager:
def get_code_example(self, example_id: str) -> CodeExample | None: def get_code_example(self, example_id: str) -> CodeExample | None:
"""获取代码示例""" """获取代码示例"""
with self._get_db() as conn: with self._get_db() as conn:
row = conn.execute("SELECT * FROM code_examples WHERE id = ?", (example_id, )).fetchone() row = conn.execute(
"SELECT * FROM code_examples WHERE id = ?", (example_id,)
).fetchone()
if row: if row:
return self._row_to_code_example(row) return self._row_to_code_example(row)
@@ -1695,7 +1698,9 @@ class DeveloperEcosystemManager:
def get_api_documentation(self, doc_id: str) -> APIDocumentation | None: def get_api_documentation(self, doc_id: str) -> APIDocumentation | None:
"""获取 API 文档""" """获取 API 文档"""
with self._get_db() as conn: with self._get_db() as conn:
row = conn.execute("SELECT * FROM api_documentation WHERE id = ?", (doc_id, )).fetchone() row = conn.execute(
"SELECT * FROM api_documentation WHERE id = ?", (doc_id,)
).fetchone()
if row: if row:
return self._row_to_api_documentation(row) return self._row_to_api_documentation(row)

View File

@@ -677,7 +677,9 @@ class GrowthManager:
) -> FunnelAnalysis | None: ) -> FunnelAnalysis | None:
"""分析漏斗转化率""" """分析漏斗转化率"""
with self._get_db() as conn: with self._get_db() as conn:
funnel_row = conn.execute("SELECT * FROM funnels WHERE id = ?", (funnel_id, )).fetchone() funnel_row = conn.execute(
"SELECT * FROM funnels WHERE id = ?", (funnel_id,)
).fetchone()
if not funnel_row: if not funnel_row:
return None return None
@@ -1573,7 +1575,8 @@ class GrowthManager:
"""触发自动化工作流""" """触发自动化工作流"""
with self._get_db() as conn: with self._get_db() as conn:
row = conn.execute( row = conn.execute(
"SELECT * FROM automation_workflows WHERE id = ? AND is_active = 1", (workflow_id, ) "SELECT * FROM automation_workflows WHERE id = ? AND is_active = 1",
(workflow_id,),
).fetchone() ).fetchone()
if not row: if not row:

View File

@@ -1505,7 +1505,8 @@ class LocalizationManager:
params.append(tenant_id) params.append(tenant_id)
cursor = conn.cursor() cursor = conn.cursor()
cursor.execute( cursor.execute(
f"UPDATE localization_settings SET {', '.join(updates)} WHERE tenant_id = ?", params f"UPDATE localization_settings SET {', '.join(updates)} WHERE tenant_id = ?",
params,
) )
conn.commit() conn.commit()
return self.get_localization_settings(tenant_id) return self.get_localization_settings(tenant_id)

View File

@@ -2258,7 +2258,9 @@ class OpsManager:
def get_failover_event(self, event_id: str) -> FailoverEvent | None: def get_failover_event(self, event_id: str) -> FailoverEvent | None:
"""获取故障转移事件""" """获取故障转移事件"""
with self._get_db() as conn: with self._get_db() as conn:
row = conn.execute("SELECT * FROM failover_events WHERE id = ?", (event_id, )).fetchone() row = conn.execute(
"SELECT * FROM failover_events WHERE id = ?", (event_id,)
).fetchone()
if row: if row:
return self._row_to_failover_event(row) return self._row_to_failover_event(row)
@@ -2427,7 +2429,9 @@ class OpsManager:
def get_backup_record(self, record_id: str) -> BackupRecord | None: def get_backup_record(self, record_id: str) -> BackupRecord | None:
"""获取备份记录""" """获取备份记录"""
with self._get_db() as conn: with self._get_db() as conn:
row = conn.execute("SELECT * FROM backup_records WHERE id = ?", (record_id, )).fetchone() row = conn.execute(
"SELECT * FROM backup_records WHERE id = ?", (record_id,)
).fetchone()
if row: if row:
return self._row_to_backup_record(row) return self._row_to_backup_record(row)

View File

@@ -318,7 +318,8 @@ class PluginManager:
# 检查是否已存在 # 检查是否已存在
existing = conn.execute( existing = conn.execute(
"SELECT id FROM plugin_configs WHERE plugin_id = ? AND config_key = ?", (plugin_id, key) "SELECT id FROM plugin_configs WHERE plugin_id = ? AND config_key = ?",
(plugin_id, key),
).fetchone() ).fetchone()
if existing: if existing:
@@ -416,7 +417,9 @@ class ChromeExtensionHandler:
token_id = str(uuid.uuid4())[:UUID_LENGTH] token_id = str(uuid.uuid4())[:UUID_LENGTH]
# 生成随机令牌 # 生成随机令牌
raw_token = f"if_ext_{base64.urlsafe_b64encode(os.urandom(32)).decode('utf-8').rstrip(' = ')}" raw_token = (
f"if_ext_{base64.urlsafe_b64encode(os.urandom(32)).decode('utf-8').rstrip(' = ')}"
)
# 哈希存储 # 哈希存储
token_hash = hashlib.sha256(raw_token.encode()).hexdigest() token_hash = hashlib.sha256(raw_token.encode()).hexdigest()

View File

@@ -1203,7 +1203,8 @@ class EntityPathDiscovery:
# 验证目标实体也在同一项目 # 验证目标实体也在同一项目
row = conn.execute( row = conn.execute(
"SELECT 1 FROM entities WHERE id = ? AND project_id = ?", (target_entity_id, project_id) "SELECT 1 FROM entities WHERE id = ? AND project_id = ?",
(target_entity_id, project_id),
).fetchone() ).fetchone()
if not row: if not row:
@@ -1278,7 +1279,9 @@ class EntityPathDiscovery:
paths = [] paths = []
def dfs(current_id: str, target_id: str, path: list[str], visited: set[str], depth: int) -> None: def dfs(
current_id: str, target_id: str, path: list[str], visited: set[str], depth: int
) -> None:
if depth > max_depth: if depth > max_depth:
return return

View File

@@ -14,11 +14,8 @@ from typing import Any
PROJECT_PATH = Path("/root/.openclaw/workspace/projects/insightflow") PROJECT_PATH = Path("/root/.openclaw/workspace/projects/insightflow")
# 修复报告 # 修复报告
report = { report = {"fixed": [], "manual_review": [], "errors": []}
"fixed": [],
"manual_review": [],
"errors": []
}
def find_python_files() -> list[Path]: def find_python_files() -> list[Path]:
"""查找所有 Python 文件""" """查找所有 Python 文件"""
@@ -28,57 +25,61 @@ def find_python_files() -> list[Path]:
py_files.append(py_file) py_files.append(py_file)
return py_files return py_files
def check_duplicate_imports(content: str, file_path: Path) -> list[dict]: def check_duplicate_imports(content: str, file_path: Path) -> list[dict]:
"""检查重复导入""" """检查重复导入"""
issues = [] issues = []
lines = content.split('\n') lines = content.split("\n")
imports = {} imports = {}
for i, line in enumerate(lines, 1): for i, line in enumerate(lines, 1):
line_stripped = line.strip() line_stripped = line.strip()
if line_stripped.startswith('import ') or line_stripped.startswith('from '): if line_stripped.startswith("import ") or line_stripped.startswith("from "):
if line_stripped in imports: if line_stripped in imports:
issues.append({ issues.append(
{
"line": i, "line": i,
"type": "duplicate_import", "type": "duplicate_import",
"content": line_stripped, "content": line_stripped,
"original_line": imports[line_stripped] "original_line": imports[line_stripped],
}) }
)
else: else:
imports[line_stripped] = i imports[line_stripped] = i
return issues return issues
def check_bare_excepts(content: str, file_path: Path) -> list[dict]: def check_bare_excepts(content: str, file_path: Path) -> list[dict]:
"""检查裸异常捕获""" """检查裸异常捕获"""
issues = [] issues = []
lines = content.split('\n') lines = content.split("\n")
for i, line in enumerate(lines, 1): for i, line in enumerate(lines, 1):
stripped = line.strip() stripped = line.strip()
# 检查 except Exception: 或 except Exception: # 检查 except Exception: 或 except Exception:
if re.match(r'^except\s*:', stripped): if re.match(r"^except\s*:", stripped):
issues.append({ issues.append({"line": i, "type": "bare_except", "content": stripped})
"line": i,
"type": "bare_except",
"content": stripped
})
return issues return issues
def check_line_length(content: str, file_path: Path) -> list[dict]: def check_line_length(content: str, file_path: Path) -> list[dict]:
"""检查行长度PEP8: 79字符这里放宽到 100""" """检查行长度PEP8: 79字符这里放宽到 100"""
issues = [] issues = []
lines = content.split('\n') lines = content.split("\n")
for i, line in enumerate(lines, 1): for i, line in enumerate(lines, 1):
if len(line) > 100: if len(line) > 100:
issues.append({ issues.append(
{
"line": i, "line": i,
"type": "line_too_long", "type": "line_too_long",
"length": len(line), "length": len(line),
"content": line[:80] + "..." "content": line[:80] + "...",
}) }
)
return issues return issues
def check_unused_imports(content: str, file_path: Path) -> list[dict]: def check_unused_imports(content: str, file_path: Path) -> list[dict]:
"""检查未使用的导入""" """检查未使用的导入"""
issues = [] issues = []
@@ -94,130 +95,161 @@ def check_unused_imports(content: str, file_path: Path) -> list[dict]:
elif isinstance(node, ast.ImportFrom): elif isinstance(node, ast.ImportFrom):
for alias in node.names: for alias in node.names:
name = alias.asname or alias.name name = alias.asname or alias.name
if name != '*': if name != "*":
imports[name] = node imports[name] = node
elif isinstance(node, ast.Name): elif isinstance(node, ast.Name):
used_names.add(node.id) used_names.add(node.id)
for name, node in imports.items(): for name, node in imports.items():
if name not in used_names and not name.startswith('_'): if name not in used_names and not name.startswith("_"):
issues.append({ issues.append(
"line": node.lineno, {"line": node.lineno, "type": "unused_import", "name": name}
"type": "unused_import", )
"name": name
})
except SyntaxError: except SyntaxError:
pass pass
return issues return issues
def check_string_formatting(content: str, file_path: Path) -> list[dict]: def check_string_formatting(content: str, file_path: Path) -> list[dict]:
"""检查混合字符串格式化(建议使用 f-string""" """检查混合字符串格式化(建议使用 f-string"""
issues = [] issues = []
lines = content.split('\n') lines = content.split("\n")
for i, line in enumerate(lines, 1): for i, line in enumerate(lines, 1):
# 检查 % 格式化 # 检查 % 格式化
if re.search(r'["\'].*%\s*\w+', line) and '%' in line: if re.search(r'["\'].*%\s*\w+', line) and "%" in line:
if not line.strip().startswith('#'): if not line.strip().startswith("#"):
issues.append({ issues.append(
{
"line": i, "line": i,
"type": "percent_formatting", "type": "percent_formatting",
"content": line.strip()[:60] "content": line.strip()[:60],
}) }
)
# 检查 .format() # 检查 .format()
if '.format(' in line: if ".format(" in line:
if not line.strip().startswith('#'): if not line.strip().startswith("#"):
issues.append({ issues.append(
"line": i, {"line": i, "type": "format_method", "content": line.strip()[:60]}
"type": "format_method", )
"content": line.strip()[:60]
})
return issues return issues
def check_magic_numbers(content: str, file_path: Path) -> list[dict]: def check_magic_numbers(content: str, file_path: Path) -> list[dict]:
"""检查魔法数字""" """检查魔法数字"""
issues = [] issues = []
lines = content.split('\n') lines = content.split("\n")
# 常见魔法数字模式(排除常见索引和简单值) # 常见魔法数字模式(排除常见索引和简单值)
magic_pattern = re.compile(r'(?<![\w\d_])(\d{3, })(?![\w\d_])') magic_pattern = re.compile(r"(?<![\w\d_])(\d{3, })(?![\w\d_])")
for i, line in enumerate(lines, 1): for i, line in enumerate(lines, 1):
if line.strip().startswith('#'): if line.strip().startswith("#"):
continue continue
matches = magic_pattern.findall(line) matches = magic_pattern.findall(line)
for match in matches: for match in matches:
num = int(match) num = int(match)
# 排除常见值 # 排除常见值
if num not in [200, 201, 204, 301, 302, 400, 401, 403, 404, 429, 500, 502, 503, 3600, 86400]: if num not in [
issues.append({ 200,
201,
204,
301,
302,
400,
401,
403,
404,
429,
500,
502,
503,
3600,
86400,
]:
issues.append(
{
"line": i, "line": i,
"type": "magic_number", "type": "magic_number",
"value": match, "value": match,
"content": line.strip()[:60] "content": line.strip()[:60],
}) }
)
return issues return issues
def check_sql_injection(content: str, file_path: Path) -> list[dict]: def check_sql_injection(content: str, file_path: Path) -> list[dict]:
"""检查 SQL 注入风险""" """检查 SQL 注入风险"""
issues = [] issues = []
lines = content.split('\n') lines = content.split("\n")
for i, line in enumerate(lines, 1): for i, line in enumerate(lines, 1):
# 检查字符串拼接的 SQL # 检查字符串拼接的 SQL
if 'execute(' in line or 'executescript(' in line or 'executemany(' in line: if "execute(" in line or "executescript(" in line or "executemany(" in line:
# 检查是否有 f-string 或 .format 在 SQL 中 # 检查是否有 f-string 或 .format 在 SQL 中
if 'f"' in line or "f'" in line or '.format(' in line or '%' in line: if 'f"' in line or "f'" in line or ".format(" in line or "%" in line:
if 'SELECT' in line.upper() or 'INSERT' in line.upper() or 'UPDATE' in line.upper() or 'DELETE' in line.upper(): if (
issues.append({ "SELECT" in line.upper()
or "INSERT" in line.upper()
or "UPDATE" in line.upper()
or "DELETE" in line.upper()
):
issues.append(
{
"line": i, "line": i,
"type": "sql_injection_risk", "type": "sql_injection_risk",
"content": line.strip()[:80], "content": line.strip()[:80],
"severity": "high" "severity": "high",
}) }
)
return issues return issues
def check_cors_config(content: str, file_path: Path) -> list[dict]: def check_cors_config(content: str, file_path: Path) -> list[dict]:
"""检查 CORS 配置""" """检查 CORS 配置"""
issues = [] issues = []
lines = content.split('\n') lines = content.split("\n")
for i, line in enumerate(lines, 1): for i, line in enumerate(lines, 1):
if 'allow_origins' in line and '["*"]' in line: if "allow_origins" in line and '["*"]' in line:
issues.append({ issues.append(
{
"line": i, "line": i,
"type": "cors_wildcard", "type": "cors_wildcard",
"content": line.strip(), "content": line.strip(),
"severity": "medium" "severity": "medium",
}) }
)
return issues return issues
def fix_bare_excepts(content: str) -> str: def fix_bare_excepts(content: str) -> str:
"""修复裸异常捕获""" """修复裸异常捕获"""
lines = content.split('\n') lines = content.split("\n")
new_lines = [] new_lines = []
for line in lines: for line in lines:
stripped = line.strip() stripped = line.strip()
if re.match(r'^except\s*:', stripped): if re.match(r"^except\s*:", stripped):
# 替换为具体异常 # 替换为具体异常
indent = len(line) - len(line.lstrip()) indent = len(line) - len(line.lstrip())
new_line = ' ' * indent + 'except (RuntimeError, ValueError, TypeError):' new_line = " " * indent + "except (RuntimeError, ValueError, TypeError):"
new_lines.append(new_line) new_lines.append(new_line)
else: else:
new_lines.append(line) new_lines.append(line)
return '\n'.join(new_lines) return "\n".join(new_lines)
def fix_line_length(content: str) -> str: def fix_line_length(content: str) -> str:
"""修复行长度问题(简单折行)""" """修复行长度问题(简单折行)"""
lines = content.split('\n') lines = content.split("\n")
new_lines = [] new_lines = []
for line in lines: for line in lines:
if len(line) > 100: if len(line) > 100:
# 尝试在逗号或运算符处折行 # 尝试在逗号或运算符处折行
if ', ' in line[80:]: if ", " in line[80:]:
# 简单处理:截断并添加续行 # 简单处理:截断并添加续行
indent = len(line) - len(line.lstrip()) indent = len(line) - len(line.lstrip())
new_lines.append(line) new_lines.append(line)
@@ -226,12 +258,13 @@ def fix_line_length(content: str) -> str:
else: else:
new_lines.append(line) new_lines.append(line)
return '\n'.join(new_lines) return "\n".join(new_lines)
def analyze_file(file_path: Path) -> dict: def analyze_file(file_path: Path) -> dict:
"""分析单个文件""" """分析单个文件"""
try: try:
content = file_path.read_text(encoding = 'utf-8') content = file_path.read_text(encoding="utf-8")
except Exception as e: except Exception as e:
return {"error": str(e)} return {"error": str(e)}
@@ -248,10 +281,11 @@ def analyze_file(file_path: Path) -> dict:
return issues return issues
def fix_file(file_path: Path, issues: dict) -> bool: def fix_file(file_path: Path, issues: dict) -> bool:
"""自动修复文件问题""" """自动修复文件问题"""
try: try:
content = file_path.read_text(encoding = 'utf-8') content = file_path.read_text(encoding="utf-8")
original_content = content original_content = content
# 修复裸异常 # 修复裸异常
@@ -260,13 +294,14 @@ def fix_file(file_path: Path, issues: dict) -> bool:
# 如果有修改,写回文件 # 如果有修改,写回文件
if content != original_content: if content != original_content:
file_path.write_text(content, encoding = 'utf-8') file_path.write_text(content, encoding="utf-8")
return True return True
return False return False
except Exception as e: except Exception as e:
report["errors"].append(f"{file_path}: {e}") report["errors"].append(f"{file_path}: {e}")
return False return False
def generate_report(all_issues: dict) -> str: def generate_report(all_issues: dict) -> str:
"""生成修复报告""" """生成修复报告"""
lines = [] lines = []
@@ -305,7 +340,9 @@ def generate_report(all_issues: dict) -> str:
if manual_issues: if manual_issues:
lines.append(f"### {file_path}") lines.append(f"### {file_path}")
for issue in manual_issues: for issue in manual_issues:
lines.append(f"- **{issue['type']}** (第 {issue['line']} 行): {issue.get('content', '')}") lines.append(
f"- **{issue['type']}** (第 {issue['line']} 行): {issue.get('content', '')}"
)
total_manual += len(manual_issues) total_manual += len(manual_issues)
if total_manual == 0: if total_manual == 0:
@@ -331,7 +368,8 @@ def generate_report(all_issues: dict) -> str:
if len(style_issues) > 5: if len(style_issues) > 5:
lines.append(f"- ... 还有 {len(style_issues) - 5} 个类似问题") lines.append(f"- ... 还有 {len(style_issues) - 5} 个类似问题")
return '\n'.join(lines) return "\n".join(lines)
def git_commit_and_push() -> None: def git_commit_and_push() -> None:
"""提交并推送代码""" """提交并推送代码"""
@@ -340,9 +378,7 @@ def git_commit_and_push() -> None:
# 检查是否有修改 # 检查是否有修改
result = subprocess.run( result = subprocess.run(
["git", "status", "--porcelain"], ["git", "status", "--porcelain"], capture_output=True, text=True
capture_output = True,
text = True
) )
if not result.stdout.strip(): if not result.stdout.strip():
@@ -353,13 +389,18 @@ def git_commit_and_push() -> None:
# 提交 # 提交
subprocess.run( subprocess.run(
["git", "commit", "-m", """fix: auto-fix code issues (cron) [
"git",
"commit",
"-m",
"""fix: auto-fix code issues (cron)
- 修复重复导入/字段 - 修复重复导入/字段
- 修复异常处理 - 修复异常处理
- 修复PEP8格式问题 - 修复PEP8格式问题
- 添加类型注解"""], - 添加类型注解""",
check = True ],
check=True,
) )
# 推送 # 推送
@@ -371,6 +412,7 @@ def git_commit_and_push() -> None:
except Exception as e: except Exception as e:
return f"❌ 错误: {e}" return f"❌ 错误: {e}"
def main() -> None: def main() -> None:
"""主函数""" """主函数"""
print("🔍 开始代码审查...") print("🔍 开始代码审查...")
@@ -392,7 +434,7 @@ def main() -> None:
# 生成报告 # 生成报告
report_content = generate_report(all_issues) report_content = generate_report(all_issues)
report_path = PROJECT_PATH / "AUTO_CODE_REVIEW_REPORT.md" report_path = PROJECT_PATH / "AUTO_CODE_REVIEW_REPORT.md"
report_path.write_text(report_content, encoding = 'utf-8') report_path.write_text(report_content, encoding="utf-8")
print("\n📄 报告已生成:", report_path) print("\n📄 报告已生成:", report_path)
@@ -402,11 +444,12 @@ def main() -> None:
print(git_result) print(git_result)
# 追加提交结果到报告 # 追加提交结果到报告
with open(report_path, 'a', encoding = 'utf-8') as f: with open(report_path, "a", encoding="utf-8") as f:
f.write(f"\n\n## Git 提交结果\n\n{git_result}\n") f.write(f"\n\n## Git 提交结果\n\n{git_result}\n")
print("\n✅ 代码审查完成!") print("\n✅ 代码审查完成!")
return report_content return report_content
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@@ -4,7 +4,9 @@ InsightFlow 代码审查与自动修复脚本
""" """
import ast import ast
import os
import re import re
import subprocess
from pathlib import Path from pathlib import Path
@@ -24,7 +26,7 @@ class CodeIssue:
self.severity = severity # info, warning, error self.severity = severity # info, warning, error
self.fixed = False self.fixed = False
def __repr__(self) -> None: def __repr__(self) -> str:
return f"{self.severity.upper()}: {self.file_path}:{self.line_no} - {self.issue_type}: {self.message}" return f"{self.severity.upper()}: {self.file_path}:{self.line_no} - {self.issue_type}: {self.message}"
@@ -365,7 +367,9 @@ class CodeReviewer:
line = lines[idx] line = lines[idx]
# 将 except Exception: 改为 except Exception: # 将 except Exception: 改为 except Exception:
if re.search(r"except\s*:\s*$", line.strip()): if re.search(r"except\s*:\s*$", line.strip()):
lines[idx] = line.replace("except Exception:", "except Exception:") lines[idx] = line.replace(
"except Exception:", "except Exception:"
)
issue.fixed = True issue.fixed = True
elif re.search(r"except\s+Exception\s*:\s*$", line.strip()): elif re.search(r"except\s+Exception\s*:\s*$", line.strip()):
# 已经是 Exception但可能需要更具体 # 已经是 Exception但可能需要更具体