尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

open-code-review Python 审查规则全解:内置 python.md 审查清单的逐项拆解与源码级实现原理

open-code-review Python 审查规则全解:内置 python.md 审查清单的逐项拆解与源码级实现原理 open-code-review Python 审查规则全解内置 python.md 审查清单的逐项拆解与源码级实现原理【免费下载链接】open-code-reviewFast, efficient, battle-tested at Alibabas scale. Hybrid architecture code review tool: deterministic pipelines LLM Agent, precise line-level comments, built-in multi-language ruleset (NPE, thread-safety, XSS, SQL injection), OpenAI Anthropic compatible.项目地址: https://gitcode.com/GitHub_Trending/op/open-code-reviewopen-code-reviewOCR是一款基于确定性流水线 LLM Agent混合架构的代码审查工具。当被审查文件是.py或.ipynb时OCR 会从内嵌的系统规则库中解析出internal/config/rules/rule_docs/python.md将其作为该文件的专用审查清单注入 LLM Agent 的提示词。本文以这份 Python 审查清单为绝对主体逐项拆解其全部审查要点并结合仓库源码说明规则从内嵌文档到注入提示词的完整链路以及如何通过ocr rules check验证规则命中、如何用项目级rule.json定制你的 Python 审查标准。读完本文你将掌握 OCR 针对 Python 代码的内置审查维度并能按需扩展自己的审查规则。规则从哪来python.md 在系统规则库中的位置与加载机制内嵌规则库与路径映射OCR 将一套多语言规则文档随二进制内嵌发布规则文档位于 internal/config/rules/rule_docs/其中每个文件对应一种语言或文件类型的审查清单。路径与规则文档的映射关系写在 internal/config/rules/system_rules.json{ default_rule: default.md, path_rule_map: { **/*.properties: properties.md, **/*.java: java.md, **/*.go: go.md, **/*.{py,ipynb}: python.md, **/*.{ts,js,tsx,jsx,mjs,cjs}: ts_js_tsx_jsx.md, ...: ... } }其中**/*.{py,ipynb}: python.md一行即 Python 审查规则的入口凡是路径匹配*.py或*.ipynb的文件都会命中python.md这份审查清单。注意这个 glob 使用了花括号展开语法{py,ipynb}会被展开为*.py与*.ipynb两个模式逐个匹配。加载与解析的源码实现internal/config/rules/system_rules.go 负责把上述 JSON 与 Markdown 文档加载进内存//go:embed system_rules.json rule_docs/*将system_rules.json与全部规则文档嵌入二进制见 system_rules.go。LoadDefault()读取system_rules.json按path_rule_map中的声明顺序保存每一条模式再读取每个模式对应的rule_docs/*.md内容并去除末尾换行见 system_rules.go。匹配时使用bmatcuk/doublestar/v4库支持**跨目录递归、*通配、{a,b}花括号展开、?与[abc]字符类路径统一转小写后大小写不敏感匹配见 system_rules.go。path_rule_map是有序匹配、首个命中者胜出若没有任何模式命中则回退到default_rule即default.md。UnmarshalJSON用流式 JSON Decoder 保留键的声明顺序见 system_rules.go。这意味着python.md并不依赖关键词或语法树判断而是纯粹的文件路径 → 规则文档映射命中*.py/*.ipynb的文件其审查提示词中的{{system_rule}}占位符会被填充为该文档的完整内容。该占位符出现在主任务提示词 internal/config/template/prompts/main_task_user.md、规划任务提示词 internal/config/template/prompts/plan_task_user.md 以及扫描模板 internal/config/template/scan_template.json 中是 Agent 每个文件审查时必须遵循的检查清单。四层规则优先级系统内嵌规则只是最低优先级的一层。OCR 的规则解析遵循四层优先级链实现于 system_rules.go 的NewResolver优先级来源路径1最高--rule命令行参数用户临时指定仅当次运行生效2项目级规则repoDir/.opencodereview/rule.json可提交到仓库3全局规则~/.opencodereview/rule.json影响本机所有仓库4最低系统内嵌规则二进制内置system_rules.json对每个文件路径各层按优先级依次尝试、第一个命中的模式胜出高层配置文件不存在时静默跳过不视为错误。用户规则默认整体替换系统规则但若在rule.json条目中设置merge_system_rule: true则会将命中的系统规则与用户规则合并——系统部分标注为 System-Specific Rules (Mandatory)用户部分标注为 User-Specific Rules (Mandatory)两者都必须遵守见 system_rules.go。此外项目级规则还支持include/excludeglob 过滤exclude优先级最高见 system_rules.go。用ocr rules check验证命中怀疑某个.py文件没有按预期使用python.md或被用户规则覆盖时直接运行内置调试命令ocr rules check实现见 cmd/opencodereview/rules_cmd.go# 查看默认规则下某个 Python 文件命中哪条规则 ocr rules check src/utils/cache.py # 查看指定 --rule 文件时命中哪条规则 ocr rules check --rule custom.json src/utils/cache.py输出会给出File、SourceCustom/Project/Global/System built-in、Pattern命中的 glob回退时显示default以及完整的规则正文。当.py文件被.opencodereview/rule.json覆盖时Source会显示为Project (.opencodereview/rule.json)而非System built-in可据此快速定位为什么 Python 审查清单和预期不一致。审查总原则Precision over Recallpython.md开篇即为整个 Python 审查行为定下总基调这是理解其余所有条目的前提Favor precision over recall: only raise an issue when you are confident it is a real defect, and stay silent when the surrounding context is unclear — a false alarm costs more reviewer trust than a missed minor issue. Treat security and correctness findings as blocking, and style or idiom suggestions as non-blocking.其要点可提炼为三条纪律宁可漏报不可误报只有对这是真实缺陷有充分信心时才提出意见上下文不明时保持沉默。因为误报一次损失的是开发者在后续所有审查中对机器意见的信任。分级处理安全Security与正确性Correctness类发现视为blocking阻塞性风格Style与习惯用法Idiom类建议视为non-blocking非阻塞性。先取证再报告全文反复出现confirm the data source withfile_readValidate the data source before flagging等要求——即报告前必须用file_read工具核实上下文而非仅凭片段臆断。这一原则与 Agent 工具层的设计遥相呼应OCR 提供给 Agent 的code_comment工具要求每条意见携带category与severity字段见 internal/config/toolsconfig/tools.json其中category枚举为bug、security、performance、maintainability、test、style、documentation、otherseverity枚举为critical、high、medium、low。规则文档中安全/正确性为阻塞的分类最终正是通过这两个字段落到每一条行级评论上的。显而易见的拼写与命名错误python.md对拼写错误的处理范围做了非常克制的限定避免把审查变成字典挑错只报告声明处的错误变量名、函数名、类名、模块名中的拼写错误只在声明位置报告引用位置的拼写由声明决定不要报告。只报告影响可读性的字符串错误日志消息或异常消息中、明显影响可读性的拼写错误。也就是说cache_servie这种声明处的拼写错误值得指出而某处注释或文档里无关紧要的拼写则不在优先范围内——这与Precision over Recall的总原则完全一致。死代码Dead Code规则要求报告以下几类不可能执行或无价值的代码不可达代码块条件恒为 false 的分支return、raise、break、continue之后的代码。声明但从未使用的实体从未被读取或引用的变量、导入import、函数参数。无保留意图的大段注释代码没有迹象表明要保留的大块注释掉的代码。对应到 OCR 的审查流程中Agent 在阅读 diff 时依赖file_read工具读取上下文、code_search/file_find确认某个符号是否真的未被引用工具定义见 internal/config/toolsconfig/tools.json从而避免把当前 diff 中未用误判为全局死代码。可变默认参数与共享状态Python 高发问题这是 Python 特有的经典陷阱规则列举了四类情况1. 可变默认参数。def f(x[])或def f(x{})的默认值在定义时只创建一次并在所有调用间共享。正确做法是默认设为None在函数体内构建新值# Bad: 默认列表被所有调用共享 def append_item(item, items[]): items.append(item) return items # Good: 默认 None函数体内新建 def append_item(item, itemsNone): if items is None: items [] items.append(item) return items2. 类级可变属性被无意共享本意是实例级属性却写成了类级可变属性导致所有实例共享同一份数据。3. 模块级可变全局状态模块级可变的 list、dict、缓存等在请求间或线程间被修改以令调用方意外的形式保留状态。4. 闭包按引用捕获循环变量闭包捕获循环变量时按引用捕获导致所有闭包最终都看到循环变量的最终值# Bad: 所有函数最终看到的都是 i 4 funcs [] for i in range(4): funcs.append(lambda: i) # Good: 用默认参数固化当前值 funcs [] for i in range(4): funcs.append(lambda ii: i)同时规则明确给出豁免条件当函数从不修改该参数、或共享默认值是刻意为之且有文档说明的缓存/哨兵值时不要报告。这条豁免同样服务于Precision over Recall。边界与极端情况处理规则覆盖了 Python 中常见的边界错误模式空输入被当作非空未先处理空list/str/dict/迭代器就直接xs[0]索引、调用max()/min()或直接切片。Off-by-one 与越界访问索引、range、切片上的越界尤其首/尾元素附近。None到达假定有值的代码上游调用或默认值可能合法返回None时。报告前必须用file_read确认数据来源。浮点数精确比较浮点运算结果不精确应使用math.isclose或显式容差# Bad if x 0.1 0.2: # Good import math if math.isclose(x, 0.1 0.2, rel_tol1e-9):整数/浮点与除法假设//导致的意外截断除数为 0 时的ZeroDivisionError。集合中元素类型异构代码假定集合内元素类型统一实际混入了None、数字、字符串等。字典按 key 访问未处理缺失d[k]直接访问 vsd.get(k)set/dict 操作假定 key 必然存在。同样给出豁免如果调用方或类型约定已经排除了这些边界情况、或上游已验证边界不可能出现则不要报告。错误处理与异常规则对异常处理提出了精细的层次要求裸except:一律吞掉所有异常包括KeyboardInterrupt与SystemExit至少应except Exception更理想的是捕获期望的具体异常类型。except Exception仍然过宽应收窄到被保护调用实际可能抛出的异常。静默丢弃except ...: pass捕获异常后不记录、不重新抛出。丢失原始 traceback重新抛出时应用raise NewError(...) from err保留原始异常链cause# Bad: 丢失原始异常上下文 try: do_something() except ValueError as err: raise RuntimeError(failed) # Good: 用 from err 保留 cause try: do_something() except ValueError as err: raise RuntimeError(failed) from err过宽的 try 块try包裹的范围远超真正可能失败的那一行掩盖了错误来源。用assert做外部输入的运行时校验assert在python -O下会被剥离不能作为运行时校验手段。身份is与相等比较这是 Python 语义最容易被误解的地方规则给出了精确的取舍用is/is not与字符串、数字、元组等字面量比较这依赖实现特定的驻留interning行为而非值相等是真实的正确性风险应改用。用与True/False比较truthy 但非True的值如1、非空容器会得到不相等的错误结论应使用直接的真值判断plain truthiness check。is只保留给单例singleton与哨兵sentinel的身份判断。用/!而非is/is not比较None属于风格偏好按 minor次要报告不阻塞。资源管理规则要求关注文件、套接字、锁、数据库连接等资源是否正确释放未使用with语句打开资源面临提前 return 或异常时泄漏的风险。绕过现成的上下文管理器能用with却手动open()/close()配对。try中获取的资源缺少finally清理错误路径上清理不完整。迭代器/生成器持有资源过久比必要时间更长地保持资源打开。同样强调取证短生命周期脚本不要报告句柄已被外层with或框架托管生命周期管理的不要报告——报告前用file_read确认外围作用域。性能规则要求先确认数据规模、确认代码在热路径上再报告性能问题具体包括循环内用拼接字符串应累积到 list 后用.join(...)或直接使用 f-string。对 list 反复做成员测试in list是 O(n) 查找改用set或dict可降为 O(1)。构建完整 list 而非生成器当只需迭代时生成器避免在内存中一次性持有全部数据。循环内重复计算不变量例如在循环里反复编译正则表达式、热路径中反复做属性查找应提到循环外。向logging传入预先格式化的 f-stringlogging.info(f...)会在日志级别被禁用时也付出格式化开销应改为logging.info(%s, value)以利用惰性格式化# Bad: 级别禁用时仍会执行格式化 logging.info(fuser{user.name} total{compute_total()}) # Good: 惰性格式化级别禁用时零开销 logging.info(user%s total%s, user.name, compute_total())注意这里存在一个经典误区——logging.info(%s, value)的惰性格式化收益在于不传入 f-string 表达式如果参数本身就是表达式如compute_total()%风格下它依然会被求值因此最佳实践是把开销大的计算移出日志参数。并发与异步规则强调只有存在多线程、多进程或异步调用的证据时才报告并发问题报告前确认调用上下文。这避免了把普通单线程代码误判为并发缺陷。具体关注GIL 下用threading并行化 CPU 密集任务传统 CPython 中应使用multiprocessing或进程池I/O 密集才是线程真正有用的场景free-threaded 构建除外。共享状态上的 check-then-act 竞态无Lock保护的先检查后执行把非原子复合更新当作原子操作。async def内出现阻塞调用同步 I/O、time.sleep、requests、CPU 密集工作会卡死事件循环应改用异步等价物或放入 executor 执行。创建后从未 await 的 asyncio 任务异常被吞掉任务可能在完成前被垃圾回收。跨线程/跨任务共享可变状态无同步机制或线程安全结构。并明确给出不报告的边界局部变量每个线程各自持有、对共享数据的只读访问、以及没有并发使用证据的代码。安全敏感代码安全类发现是 blocking 级别但规则首先要求先验证数据来源确认输入确实由攻击者控制attacker-controlled而非可信常量。审查点包括eval/exec/compile作用于不可信输入这是任意代码执行arbitrary code execution。subprocess使用shellTrue且由未净化输入拼命令应传参数列表argument list并避免走 shell# Bad: shellTrue 且拼接输入 subprocess.run(fgrep {user_input} file.txt, shellTrue) # Good: 参数列表不经 shell subprocess.run([grep, user_input, file.txt])pickle、marshal、或未用SafeLoader的yaml.load处理不可信数据反序列化可执行任意代码# Bad import yaml data yaml.load(untrusted_content) # 默认 loader 不安全 # Good data yaml.safe_load(untrusted_content)SQL 用字符串拼接或 f-string 构建而非参数化查询# Bad: 拼接 SQL存在注入风险 cursor.execute(fSELECT * FROM users WHERE name {name}) # Good: 参数化查询 cursor.execute(SELECT * FROM users WHERE name %s, (name,))密钥、令牌、密码或 PII 写入日志或提交进源码。弱或误用的密码学用hashlib.md5/sha1存密码、用random生成安全令牌应使用secrets和经过验证的库。不可信文件路径未经校验直接拼接可能导致路径穿越path traversal。如何把 python.md 的能力延伸到你的团队python.md覆盖的是通用 Python 缺陷但 OCR 的四层规则体系允许你在其上叠加团队专属要求且项目级规则永远高于系统规则场景一项目级追加 Python 专属规范在仓库根目录创建.opencodereview/rule.json并提交{ rules: [ { path: **/*.py, rule: 所有对外接口必须使用类型注解禁止在业务代码中直接 print 调试一律使用 logging。, merge_system_rule: true } ] }merge_system_rule: true会让 Agent 同时遵守系统内嵌的python.md与你的团队规范若省略该字段则系统规则被整体替换为你自定义的文本。场景二单次 PR 安全专项审查不想动仓库配置时用--rule临时覆盖ocr review --rule ./security-only-python.json该文件在本次运行中优先级最高会绕过项目级与全局层。场景三全局个人偏好在~/.opencodereview/rule.json放置跨仓库偏好例如对所有 Python 文件强制检查异常链与类型标注。验证与排障任何一次规则调整后都建议用ocr rules check确认命中的层与模式是否符合预期再提交正式审查避免把配置问题带入真正的评审流程。此外OCR 会将规则文本的规范化配置计算进运行清单的rule_config_sha256见 system_rules.go 的CanonicalConfig规则内容的变更会反映到审查运行的可追溯元数据中方便复盘某次审查实际遵循了哪一版规则。小结internal/config/rules/rule_docs/python.md是一份以精确优先、宁缺毋滥为总纲的 Python 审查清单覆盖拼写、死代码、可变默认参数、边界处理、异常、身份比较、资源、性能、并发与安全十大维度每个维度都给出了明确的报告什么与豁免什么的边界。它通过 system_rules.json 中的**/*.{py,ipynb}映射被按需加载经 system_rules.go 的四层优先级解析后注入 Agent 提示词最终以code_comment的行级评论携带 category/severity 分级呈现。理解这份清单的每一条细则并用ocr rules check 项目级rule.json组合定制你就能让 OCR 的 Python 审查同时具备通用缺陷识别与团队规范执行两种能力。【免费下载链接】open-code-reviewFast, efficient, battle-tested at Alibabas scale. Hybrid architecture code review tool: deterministic pipelines LLM Agent, precise line-level comments, built-in multi-language ruleset (NPE, thread-safety, XSS, SQL injection), OpenAI Anthropic compatible.项目地址: https://gitcode.com/GitHub_Trending/op/open-code-review创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表