Odoo 版本升级时如何用 upgrade_code 脚本批量重写自定义模块的源码
【免费下载链接】odooOdoo. Open Source Apps To Grow Your Business.项目地址: https://gitcode.com/GitHub_Trending/od/odoo
跨大版本升级 Odoo 时(比如从 17 升到 19),自定义模块里大量源码需要同步做机械性改写:视图里的tree要改成list、_sql_constraints要换成models.Constraint、过期的 API 调用要替换。这类改动可以靠 odoo-bin 内置的upgrade_code子命令批量完成。它会自动执行 odoo/upgrade_code/ 目录下存放的迁移脚本,把--addons-path指向的模块目录里符合条件的文件逐个改写。当前仓库的 odoo/release.py 声明版本为 19.0,自带的迁移脚本覆盖了 17.5 到 18.5 区间的变更。
upgrade_code 的工作方式
先弄清它如何挑选文件和脚本,后面配置参数才有依据。这些规则来自 odoo/cli/upgrade_code.py 的模块 docstring 和实现:
- 脚本命名约定:每个迁移脚本放在
odoo/upgrade_code/下,命名为{version}-{name}.py,并暴露一个upgrade(file_manager)函数。文件名中第一个-之前的部分被parse_version解析成版本号,用于按版本区间筛选。 - 脚本选择:
--script NAME只跑单个脚本(按名称子串匹配,可省略.py);--from VERSION则跑该版本(含)之后、直到--to(含)之前的所有脚本。--from与--script互斥,且二选一必填。--to不指定时默认取当前release.version(本仓库即 19.0)。 - 文件范围:脚本以 glob 遍历 addons 路径下的文件(
--glob,默认**/*),但实际只处理后缀为.py、.js、.css、.scss、.xml、.csv、.po、.pot的文件,且跳过__pycache__目录。 - file_manager 接口:它表现得像一个文件列表,每个文件有三个属性——
path(文件在文件系统中的pathlib.Path)、addon(文件所在的 Odoo 模块)、content(可重写的文件内容,惰性加载)。此外还有print_progress(current, total)用于显示进度。 - 写入规则:只有
content真正发生变化的文件才会被写回磁盘,未变化的文件不动。
当前仓库自带 9 个迁移脚本,可按 odoo/upgrade_code/ 目录查看,例如 17.5-01-tree-to-list.py(把 XML、JS、Python 中的tree视图写法批量替换为list)和 18.1-00-sql-constraint.py(把_sql_constraints列表重写为models.Constraint)。
确认命令可用
在改动任何文件前,先确认当前环境里upgrade_code命令存在。有两种调用方式,官方测试 odoo/addons/base/tests/test_cli.py 里对两者都做了验证:
# 通过 odoo-bin 调用 odoo-bin upgrade_code --help# 独立调用(不启动完整 Odoo 环境,直接运行 CLI 脚本文件) python3 odoo/cli/upgrade_code.py --help两者的输出都应包含usage:和Rewrite the entire source code字样,帮助文本同时列出了--script、--from、--to、--glob、--dry-run、--addons-path各选项的含义。
第一步:用 --dry-run 预演改写
真实改写前先跑--dry-run。该参数会列出将会被重写的文件路径,但不写回任何文件(帮助文本原文:"list the files that would be re-written, but rewrite none")。
独立调用方式下,--addons-path必填,且路径必须是已经解析好的绝对路径(代码注释明确说明 "the paths must be resolved already")。假设自定义模块位于/data/web/your/addons,从 17.5 开始升级到当前版本的预演命令是:
python3 odoo/cli/upgrade_code.py \ --addons-path /data/web/your/addons \ --from 17.5 \ --dry-run- 把
--addons-path中的路径替换为你自定义模块的实际所在目录;有多个目录时用逗号分隔(PATH,...)。 --from 17.5会选中 17.5、18.1、18.2、18.3、18.5 各版本的全部脚本;若只关心某一版,可把--from换成对应版本。- 交互式终端下 stderr 会滚动显示每个脚本的处理进度;非 TTY(如管道、CI)下进度输出被静默,但不影响改写。
通过odoo-bin调用时,默认 addons 路径来自服务器配置,同样可用--addons-path指定自定义模块目录:
odoo-bin upgrade_code --addons-path /data/web/your/addons --from 17.5 --dry-run只跑某一个脚本时用--script代替--from(两者互斥):
odoo-bin upgrade_code --script 17.5-01-tree-to-list --dry-run官方测试test_upgrade_code_example提供了一个可对照的基准:odoo-bin upgrade_code --script 17.5-00-example --dry-run的 stdout 应为空——因为 17.5-00-example.py 的写回行被注释掉了,不会让任何文件变脏。如果你的 dry-run 连这个基准都输出异常,说明环境或参数配置有问题,应先停下来排查。
执行改写并核对结果
确认 dry-run 列出的文件都在预期内后,去掉--dry-run正式执行:
python3 odoo/cli/upgrade_code.py \ --addons-path /data/web/your/addons \ --from 17.5结果核对有两个来自代码实现的判断点:
- 被改写的文件清单:正式运行时,每个内容变化的文件路径会打印到 stdout。这份清单就是本次批量改写的完整结果集。
- 退出码:
run()末尾是sys.exit(int(is_dirty))——只要有文件被修改,退出码为 1;没有任何文件变化则退出码为 0。在脚本化流程中可以用$?判断"是否有模块被改写"。
清单里的每一个文件都建议逐个查看改动内容再进入升级的后续步骤。docstring 对这一点了明确要求:这些脚本做的是 best-effort 的迁移,"they only help do the heavy-lifting, they are not silver bullets"——即脚本只承担批量改写的重活,不保证每处替换都语义正确。
现有脚本没覆盖的重写:编写自己的 upgrade 脚本
如果版本变更涉及官方脚本没有处理的自有写法,可以按同样的机制补一个脚本。依据 odoo/cli/upgrade_code.py 的 docstring,脚本需放在odoo/upgrade_code/下、命名为{version}-{name}.py,并实现upgrade(file_manager)函数。docstring 给出的最小示例:
def upgrade(file_manager): files = [f for f in file_manager if f.path.suffix == '.py'] for fileno, file in enumerate(files, start=1): file.content = file.content.replace(..., ...) file_manager.print_progress(fileno, len(files))要点与 docstring、示例脚本一致:
- 在
file_manager上按path(后缀、路径片段)筛选目标文件,只有把新内容赋回file.content且内容确实变化时文件才会落盘; print_progress(fileno, len(files))提供进度反馈;- 文件名前缀决定该脚本被哪个
--from/--to区间选中,--script按名称子串匹配,例如脚本文件18.5-00-mychange.py可用--script 18.5-00-mychange单独预演。
写完先--dry-run,确认文件清单符合预期后再正式运行。
已知限制
- 文件类型白名单:只有
.py、.js、.css、.scss、.xml、.csv、.po、.pot后缀的文件会被扫描,其他文件(如.json、.sql)不在处理范围内。 - 示例脚本不是生产工具:17.5-00-example.py 源码里明确写着 "Don't use this script in production, it is broken and only serve as an example",它只用于演示
upgrade()的写法。 - 独立运行必须给已解析的绝对路径:
python3 odoo/cli/upgrade_code.py不带--addons-path会直接报错退出("--addons-path is required when used standalone");路径相对化解析不受支持。 - best-effort 语义:脚本按正则或 AST 规则做批量替换,无法覆盖规则外的边界情况,改写结果必须人工复核。
【免费下载链接】odooOdoo. Open Source Apps To Grow Your Business.项目地址: https://gitcode.com/GitHub_Trending/od/odoo
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考