特战匕首¶
You can translate it into your own country's language.
#!/bin/bash
# ==============================================================================
# 🗡️ 特战匕首 V1.1
# 定位:对单一文件进行审计
# 用法: ./qaf.sh <path/to/file.py>
# 场景:新建或重构后立即进行单文件审计,将问题扼杀在摇篮中
# 要求:必须确保该文件所有报错清零,尽管当前任务中不包含修复这些报错。
# 说明:此脚适用于大多数常见场景,可根据实际需要自由搭配、修改和扩展。
# 更新:新增 AI 模式,排除干扰,降低 token 成本 命令:./qaf.sh <path/to/file.py> -a
# ==============================================================================
# =======================================================================
# 准备开始:环境配置
# =======================================================================
# ---------------------------------------------------
# --- 1. 通用输出函数 ---
# ---------------------------------------------------
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
print_chapter_header() {
# 人类模式下输出章节标题;AI 模式下默认关闭以减少噪音
if [[ "${PYCOURT_UI_MODE:-human}" != "ai" ]]; then
echo -e "\n${BLUE}================== $1 ==================${NC}"
fi
}
print_sub_header() {
# 人类模式下输出小节标题;AI 模式下默认关闭以减少噪音
if [[ "${PYCOURT_UI_MODE:-human}" != "ai" ]]; then
echo -e "\n${YELLOW}--- $1 ---${NC}"
fi
}
print_success() {
echo -e "${GREEN}✅ $1${NC}"
}
print_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
print_error() {
echo -e "${RED}❌ $1${NC}"
}
# ---------------------------------------------------
# --- 2. 审判语言默认为中文,可选 -en ---
# ---------------------------------------------------
export PYCOURT_LANG="${PYCOURT_LANG:-zh}"
# ---------------------------------------------------
# --- 3. 零容忍,发现问题立即终止 ---
# ---------------------------------------------------
set -euo pipefail
# ---------------------------------------------------
# --- 4. 以当前位置为中心(放在根目录) ---
# ---------------------------------------------------
export PYTHONPATH=$(pwd)
# ---------------------------------------------------
# --- 5. pycourt file 命令封装与参数检查 ---
# ---------------------------------------------------
validate_target() {
# 提供的文件路径数量限定为一个
if [ "$#" -lt 1 ]; then
echo "❌ 错误:必须提供一个文件为审判目标 (文件路径)" >&2
echo "用法: ./qaf.sh [-a|--ai] <path/to/file.py>" >&2
exit 1
fi
local target="$1"
# 目标文件必须存在
if [ ! -f "$target" ]; then
echo "❌ 错误:特战匕首的审判目标必须是一个存在的文件。" >&2
echo "用法: ./qaf.sh [-a|--ai] <path/to/file.py>" >&2
exit 1
fi
# 目标必须为 Python 源文件
if [[ "$target" != *.py ]]; then
echo "❌ 错误:特战匕首仅支持审计单个 Python 源文件 (*.py)。" >&2
echo "用法: ./qaf.sh [-a|--ai] <path/to/file.py>" >&2
exit 1
fi
}
# 解析参数:可选 -a/--ai + 必填目标文件
AUDIT_TARGET=""
while [[ $# -gt 0 ]]; do
case "$1" in
-a|--ai)
# AI 模式:切换为 AI 友好输出(由后端根据 PYCOURT_AUDIENCE/PYCOURT_UI_MODE 控制)
export PYCOURT_AUDIENCE=${PYCOURT_AUDIENCE:-ai}
export PYCOURT_UI_MODE=${PYCOURT_UI_MODE:-ai}
# 若当前语言为中文系 (zh*),在 AI 模式下自动切换到英文文案,
# 若用户已显式设为 en/其他语言,则尊重用户选择。
if [[ "${PYCOURT_LANG:-}" == zh* ]]; then
export PYCOURT_LANG=en
fi
shift
;;
-*)
echo "❌ 未知参数: $1" >&2
echo "用法: ./qaf.sh [-a|--ai] <path/to/file.py>" >&2
exit 1
;;
*)
if [[ -z "$AUDIT_TARGET" ]]; then
AUDIT_TARGET="$1"
shift
else
echo "❌ 多余参数: $1" >&2
echo "用法: ./qaf.sh [-a|--ai] <path/to/file.py>" >&2
exit 1
fi
;;
esac
done
if [[ -z "$AUDIT_TARGET" ]]; then
echo "❌ 错误:必须提供一个文件为审判目标 (文件路径)" >&2
echo "用法: ./qaf.sh [-a|--ai] <path/to/file.py>" >&2
exit 1
fi
# 调用校验函数,确保 AUDIT_TARGET 合法
validate_target "$AUDIT_TARGET"
# pycourt统一审计入口,根据法庭代码执行对应审计
run_judges() {
local codes="$1"
poetry run pycourt file "$AUDIT_TARGET" --select "$codes"
}
# ---------------------------------------------------
# --- 6. 外部工具封装与可用性检查---
# 预留参数统一配置,只封装,具体参数通过 pyproject.toml 决定
# ---------------------------------------------------
run_mypy() {
poetry run mypy "$@"
}
run_pyright() {
poetry run pyright "$@"
}
run_bandit() {
poetry run bandit "$@"
}
run_ruff_check() {
poetry run ruff check "$@"
}
run_ruff_format() {
poetry run ruff format "$@"
}
# 报告缺少的外部工具
check_tool() {
local cmd="$1"
local desc="$2"
if ! command -v "$cmd" >/dev/null 2>&1; then
print_warning "缺少外部工具: $cmd ($desc),将跳过对应审计步骤。"
return 1
fi
return 0
}
# ---------------------------------------------------
# --- 准备就绪 ---
# ---------------------------------------------------
print_chapter_header "🗡️ 特战匕首 - 准备就绪"
print_sub_header "审计目标: $AUDIT_TARGET"
# =======================================================================
# 第一章:架构生死线
# 审判最根本的、动摇项目根基的“叛国罪”。
# =======================================================================
print_chapter_header "第一章:架构生死线"
# ---------------------------------------------------
# 1.1 架构位置:循环依赖 / 门面规范 / 依赖倒置
# 先确保文件站在正确的架构世界,否则后续所有结果都失去意义。
# ---------------------------------------------------
# 禁止使用TYPE_CHECKING等手段引入循环依赖
print_sub_header "1.1.1 循环依赖法庭 (TC001)"
run_judges "TC001"
# 禁止在门面层使用领域逻辑并聚合导出
print_sub_header "1.1.2 门面纪律法庭 (RE001)"
run_judges "RE001,RE002,RE003"
# 禁止违反依赖倒置原则直接依赖具体实现
print_sub_header "1.1.3 依赖倒置法庭 (DI001)"
run_judges "DI001"
# ---------------------------------------------------
# 1.2 事务与边界:UoW / 边界 DTO / 向量触发协议
# 在架构位置正确的前提下,优先保证事务语义与边界契约的正确。
# ---------------------------------------------------
# 禁止违反 unit of work 原则的事务处理
print_sub_header "1.2.1 仓库事务法庭 (UW001)"
run_judges "UW001,UW002,UW003,UW004"
# 禁止违反边界 DTO 规范的跨层数据传递
print_sub_header "1.2.2 疆域边界法庭 (BC001)"
run_judges "BC001"
# 禁止违反向量触发协议的事件处理
print_sub_header "1.2.3 向量触发法庭 (VT001)"
run_judges "VT001"
# ---------------------------------------------------
# 1.3 类型与领域纪律:Any/dict/cast/object 滥用
# 在“做对事、站对层”的前提下,收紧类型与领域使用习惯,防止灰色地带。
# ---------------------------------------------------
# 禁止滥用鸭子类型、Any、cast 等破坏类型纯净度的行为
print_sub_header "1.3.1 鸭子类型法庭 (AC001)"
run_judges "AC001,AC002,AC003"
# 禁止滥用通用对象类型(object)破坏领域纯净度的行为
print_sub_header "1.3.2 鸭子类型法庭 (OU001)"
run_judges "OU001"
# 禁止滥用时间相关操作破坏领域纯净度的行为
print_sub_header "1.3.3 时间漂移法庭 (DT001)"
run_judges "DT001"
# 禁止违反技能配置规范的行为
print_sub_header "1.3.4 技能配置法庭 (SK001)"
run_judges "SK001"
# =======================================================================
# 第二章:类型联邦调查局
# 审判所有违反“类型法”的行为,确保逻辑的严谨。
# =======================================================================
print_chapter_header "第二章:类型联邦调查局"
# ---------------------------------------------------
# --- 2.1 Pyright 终审:最严格的深度逻辑推断 ---
# 先用 Pyright 做一轮更“挑剔”的静态分析,尽早暴露语法/推断问题。
# ---------------------------------------------------
print_sub_header "2.1 Pyright 审查"
if check_tool "pyright" "Python 静态类型检查器"; then
run_pyright "$AUDIT_TARGET"
else
print_warning "跳过 Pyright 审查"
fi
# ---------------------------------------------------
# --- 2.2 Mypy 复核:对照canonical类型配置做二次确认 ---
# 再用 Mypy 做一轮“官方”类型复核,确保符合帝国标准。
# ---------------------------------------------------
print_sub_header "2.2 Mypy 复核"
if check_tool "mypy" "Python 静态类型检查器"; then
run_mypy "$AUDIT_TARGET"
else
print_warning "跳过 Mypy 审查。"
fi
# =======================================================================
# 第三章:安全署
# 审判危害帝国安全与内部秩序的“中级罪行”。
# =======================================================================
print_chapter_header "第三章:安全署"
# ---------------------------------------------------
# --- 3. Bandit 安全稽查 ---
# 在进入风格/可维护性审查前,优先排除明显的安全隐患.
# 对测试文件,只关心 B101(assert) 这一条罪行,避免噪音过大。
# ---------------------------------------------------
print_sub_header "3. 安全稽查 (Bandit)"
if check_tool "bandit" "安全审计工具 (Bandit)"; then
if [[ "$AUDIT_TARGET" == tests* ]]; then
run_bandit -q "$AUDIT_TARGET" -s B101
else
run_bandit -q "$AUDIT_TARGET"
fi
else
print_warning "跳过 Bandit 安全稽查。"
fi
# =======================================================================
# 第四章:内政署(仪容仪表)
# 检查代码的仪容仪表和风格。
# 在类型与安全通过后,可按需选择检查“渎职”和“懒政”类问题。
# =======================================================================
print_chapter_header "第四章:内政署"
# 确保所有公共接口均有完整文档
print_sub_header "4.1 文档字符串法庭 (DS001)"
run_judges "DS001,DS002"
# 检查代码复杂度,防止过度复杂化
print_sub_header "4.2 代码复杂度法庭 (LL001)"
run_judges "LL001,LL002"
# 禁止字符串/数字等硬编码常量
print_sub_header "4.3 硬编码法庭 (HC001)"
run_judges "HC001,HC004,HC005"
# 检查是否绕过RuleProvider机制的常量使用
print_sub_header "4.4 可调参数法庭 (PC001)"
run_judges "PC001,PC002"
# 采用命名空间类型定义常量风格
print_sub_header "4.5 常量风格法庭 (HC002)"
run_judges "HC002,HC003"
# =======================================================================
# 第五章:环境署(清理战场)
# 清理所有轻微的“市容”问题,并进行最终的格式化。
# 所有语义/安全/风格审查通过后,最后一步统一自动修复 + 格式化输出。
# =======================================================================
print_chapter_header "第五章:环境署"
print_sub_header "5. 清理战场 (Ruff)"
if check_tool "ruff" "Python Lint & Format 工具 (Ruff)"; then
run_ruff_check "$AUDIT_TARGET" --fix
run_ruff_format "$AUDIT_TARGET"
else
print_warning "跳过 Ruff 审查与格式化。"
fi
# =======================================================================
# --- 结案判决 ---
# =======================================================================
print_success "结案判决:目标已达纯净!"