升级工具¶
升级工具 是一个包含辅助函数的库,用于简化升级脚本的编写。该库被 Odoo 用于标准模块的升级脚本,提供了可靠性并有助于加快升级过程:
辅助函数帮助确保数据库中的数据一致性。
它处理更新记录的间接引用。
允许调用函数以避免编写代码,节省时间并降低开发风险。
辅助工具使您可以专注于升级的重要部分,而无需考虑细节。
安装¶
克隆 升级工具仓库 到本地,并在启动 odoo
时将 src
目录添加到 --upgrade-path
选项之前。
$ ./odoo-bin --upgrade-path=/path/to/upgrade-util/src,/path/to/other/upgrade/script/directory [...]
在您不自行管理 Odoo 的平台上,可以通过 pip
安装此库:
$ python3 -m pip install git+https://github.com/odoo/upgrade-util@master
在 Odoo.sh 上,建议将其添加到自定义仓库的 requirements.txt
文件中。为此,请在文件中添加以下行:
odoo_upgrade @ git+https://github.com/odoo/upgrade-util@master
使用升级工具¶
安装完成后,以下包可供升级脚本使用:
odoo.upgrade.util
: 辅助工具本身。odoo.upgrade.testing
: 基础 TestCase 类。
要在升级脚本中使用它,只需导入即可:
from odoo.upgrade import util
def migrate(cr, version):
# Rest of the script
现在,可以通过 util
调用辅助函数。
工具函数¶
升级工具提供了许多有用的函数来简化升级过程。在此,我们将描述一些最有用的函数。有关辅助函数的完整声明,请参阅 util 文件夹。
注解
工具函数中的 cr
参数始终指代数据库游标。传递在 migrate()
中接收到的游标。并非所有函数都需要此参数。
模块¶
用于模块级操作的实用函数。
在大多数情况下,模块操作(重命名、合并、删除等)应在 base
脚本中执行。原因是一旦 base
模块升级完成,所有与模块相关的信息应该已经设置在数据库中,以确保升级过程正常运行。命令行选项 --pre-upgrade-scripts`(从 Odoo 16 开始可用)允许在加载 `base
模块之前运行升级脚本。这是在主要升级后执行模块操作的推荐方式。
- odoo.upgrade.util.modules.modules_installed(cr, *modules)[源代码]¶
返回是否安装了 所有 给定模块。
注解
在升级的上下文中,如果模块被标记为升级或安装,则即使尚未完全安装,也会被视为已安装。
- odoo.upgrade.util.modules.uninstall_module(cr, module)[源代码]¶
卸载并删除模块拥有的所有记录。
- 参数
module (str) – 要卸载的模块名称
- odoo.upgrade.util.modules.uninstall_theme(cr, theme, base_theme=None)[源代码]¶
卸载主题模块并将其从网站中移除。
警告
此函数只能在
website
模块的post-
脚本中使用,因为它依赖于 ORM。
- odoo.upgrade.util.modules.remove_module(cr, module)[源代码]¶
完全删除模块。
此操作等同于卸载并移除模块的所有引用——数据库中不会留下任何痕迹。
- 参数
module (str) – 要移除的模块名称
警告
由于此函数会移除与模块关联的所有数据,请在调用此函数之前确保重新分配记录。
- odoo.upgrade.util.modules.remove_theme(cr, theme, base_theme=None)[源代码]¶
卸载主题模块。
警告
此函数只能在
post-
脚本中使用。
- odoo.upgrade.util.modules.merge_module(cr, old, into, update_dependers=True)[源代码]¶
将一个模块合并到另一个模块中。
此函数将源模块中的所有引用和记录移动到目标模块中。
警告
此函数不会删除任何记录,但会从源模块中移除与目标模块中名称冲突的 xml_ids。
- odoo.upgrade.util.modules.force_install_module(cr, module, if_installed=None, reason='it has been explicitly asked for')[源代码]¶
强制 ORM 安装模块。
- odoo.upgrade.util.modules.force_upgrade_of_fresh_module(cr, module, init=True)[源代码]¶
强制执行正在安装的模块的升级脚本。
标准 Odoo 在安装模块时不运行升级脚本。这在技术上是有意义的,因为模块并未真正升级。然而,有时(新)模块需要执行一些操作才能正确安装,例如从其他模块获取数据。这种情况在模块功能被 拆分 为多个模块时很常见。
处于 init 模式的一个副作用是不遵守 XML 文件或
ir_model_data
中的 noupdate 标志。
模型¶
用于修改模型的实用函数。
模型操作最好在相关模块的 pre-
脚本中完成。
- odoo.upgrade.util.models.remove_model(cr, model, drop_table=True, ignore_m2m=())[源代码]¶
从数据库中删除模型及其引用。
某些对模型的必要间接引用会被替换为 未知模型 —— 一个作为空占位符的空模型,用于替代已移除的模型。
- odoo.upgrade.util.models.delete_model(cr, model, drop_table=True, ignore_m2m=())[源代码]¶
从数据库中删除模型及其引用。
某些对模型的必要间接引用会被替换为 未知模型 —— 一个作为空占位符的空模型,用于替代已移除的模型。
- odoo.upgrade.util.models.merge_model(cr, source, target, drop_table=True, fields_mapping=None, ignore_m2m=())[源代码]¶
将一个模型合并到另一个模型中。
此函数将所有引用从
source
模型移动到target
模型,并 删除source
模型及其引用。默认情况下,仅移动两个模型中同名的字段;可选地,可以提供不同字段名称的映射。警告
此函数不会将记录从
source
模型移动到target
模型。
- odoo.upgrade.util.models.remove_inherit_from_model(cr, model, inherit, keep=(), skip_inherit=(), with_inherit_parents=True)[源代码]¶
从
model
中移除inherit
。此函数会从
model
及其所有子模型中移除通过inherit
继承的所有字段。包括继承模型及其父模型中的所有字段也将被移除,除非未设置with_inherit_parents
模式。在这种情况下,仅移除inherit
中的字段,而保留其父模型中的字段。在keep
中列出的字段永远不会被移除。如果model
的某些子模型列在skip_inherit
中,它们将保留来自inherit
的字段。
字段¶
用于修改模型字段的实用函数。
字段操作最好在相关模块的 pre-
脚本中完成。在某些情况下,初步操作可以在 pre
中完成,然后在 post
中完成。一个常见的例子是在 pre-
中移除字段但保留其列,稍后在 post
中当列最终被删除时使用。
- odoo.upgrade.util.fields.remove_field(cr, model, fieldname, cascade=False, drop_column=True, skip_inherit=(), keep_as_attachments=False)[源代码]¶
从数据库中移除字段及其引用。
此函数还会从继承模型中移除字段,除非在
skip_inherit
中指定了例外情况。当字段已存储时,我们可以选择不删除该列。
- odoo.upgrade.util.fields.make_field_non_stored(cr, model, field, selectable=False)[源代码]¶
将字段转换为非存储字段。
- odoo.upgrade.util.fields.move_field_to_module(cr, model, fieldname, old_module, new_module, skip_inherit=())[源代码]¶
将字段从一个模块移动到另一个模块。
此函数更新对特定字段的所有引用,从源模块切换到目标模块。它避免了在注册表完全加载后数据丢失。继承模型中的字段也会被移动,除非跳过。
- odoo.upgrade.util.fields.rename_field(cr, model, old, new, update_references=True, domain_adapter=None, skip_inherit=())[源代码]¶
在给定的
model
上将字段及其引用从old
重命名为new
。该字段会在所有继承模型中更新,但
skip_inherit
中指定的模型除外。此函数还会更新直接或间接的引用,包括过滤器、服务器操作、相关字段、电子邮件、仪表板、域等更多内容。参见
update_field_usage()
可以使用特殊的适配器函数来更新域。默认适配器仅在每个域叶中将
old
替换为new
。有关域适配器的信息,请参阅adapt_domains()
。
- odoo.upgrade.util.fields.invert_boolean_field(cr, model, old, new, skip_inherit=())[源代码]¶
重命名布尔字段并反转其值。
- odoo.upgrade.util.fields.change_field_selection_values(cr, model, field, mapping, skip_inherit=())[源代码]¶
替换选择字段值的引用。
此函数根据映射替换对选择值的所有引用。域也会被更新。
- odoo.upgrade.util.fields.update_field_usage(cr, model, old, new, domain_adapter=None, skip_inherit=())[源代码]¶
在不同位置将字段
old
的所有引用替换为new
。- 搜索范围:
ir_filters
ir_exports_line
ir_act_server
mail_alias
ir_ui_view_custom(仪表板)
域(使用
domain_adapter
)相关字段
此函数可用于替换字段的使用。域会使用
domain_adapter
进行更新。默认情况下,域适配器仅在域叶中将old
替换为new
。有关域适配器的更多信息,请参阅adapt_domains()
。
记录¶
用于记录级操作的实用函数。
- odoo.upgrade.util.records.remove_view(cr, xml_id=None, view_id=None, silent=False, key=None)[源代码]¶
删除视图及其所有子视图。
此函数递归删除给定视图及其继承的视图,只要它们是模块的一部分。如果层次结构中存在任何自定义视图,该函数将失败。它还会删除多网站的 COW 视图。
- 参数
警告
必须设置
xml_id
或view_id
。同时指定两者将引发错误。
- odoo.upgrade.util.records.edit_view(cr, xmlid=None, view_id=None, skip_if_not_noupdate=True, active='auto')[源代码]¶
用于编辑视图架构的上下文管理器。
此函数返回一个上下文管理器,可能会生成视图的解析架构,作为 etree 元素。返回对象中的任何更改将在退出上下文管理器时写回数据库,并更新架构的翻译版本。由于函数可能不会生成内容,可以使用
skippable_cm()
来避免错误。with util.skippable_cm(), util.edit_view(cr, "xml.id") as arch: arch.attrib["string"] = "My Form"
要选择要编辑的目标视图,请使用
xmlid
或view_id
,但不要同时使用两者。当通过
view_id
确定视图时,如果视图存在,则始终生成其架构,而不考虑其可能关联的noupdate
标志。当设置了xmlid
时,如果视图的noupdate
标志为False
,则不会生成架构,除非将skip_if_not_noupdate
设置为False
。如果noupdate
为True
,则生成视图以供编辑。如果
active
参数为True
或False
,则视图的active
标志将相应设置。注解
如果
active
为 “auto”(默认值),则通过xmlid
选择时视图将被激活,而通过view_id
选择时保持不变。
- odoo.upgrade.util.records.remove_record(cr, name)[源代码]¶
删除与给定 xml_id 对应的记录及其引用。
- 参数
name (str) – 记录的 xml_id,格式为
module.name
- odoo.upgrade.util.records.is_changed(cr, xmlid, interval='1 minute')[源代码]¶
返回记录是否已更改。
此函数检查记录是否在当前升级开始时间之前已更改。参见
upgrade-util/src/base/0.0.0/pre-00-upgrade-start.py
对于符合以下条件的记录的 xmlid,此工具将返回假阳性:
已在当前升级之前的升级中更新过
尚未在当前升级中更新
如果
xmlid
不存在于数据库中,此函数返回None
。
- odoo.upgrade.util.records.if_unchanged(cr, xmlid, callback, interval='1 minute', **kwargs)[源代码]¶
如果记录未更改,则运行
callback
。当引用的记录未更改时,此函数将运行
callback
。xmlid
和任何其他参数(但不包括interval
)将传递给callback
。如果记录已更改,则会将其标记为noupdate=True
。另请参见is_changed()
和force_noupdate()
。此函数在记录未更新时执行操作非常有用,一个常见示例是即使记录为
noupdate=True
,也强制从 XML 更新。util.if_unchanged(cr, "mymodule.myrecord", util.update_record_from_xml)
- odoo.upgrade.util.records.rename_xmlid(cr, old, new, noupdate=None, on_collision='fail')[源代码]¶
重命名记录的 external identifier (
xml_id
)。如果目标名称已存在于数据库中,则无法进行重命名。在这种情况下,有两种选项可以控制此函数的行为:
fail
:引发异常并阻止重命名merge
:重命名外部标识符,删除旧标识符,并替换引用。参见replace_record_references_batch()
注解
此函数不会删除记录,仅更新 xml_ids。
- odoo.upgrade.util.records.force_noupdate(cr, xmlid, noupdate=True, warn=False)[源代码]¶
更新记录的
noupdate
标志。
- odoo.upgrade.util.records.ensure_xmlid_match_record(cr, xmlid, model, values)[源代码]¶
确保 xml_id 引用具有特定值的记录。
此函数确保 xml_id 指向的记录与
values
参数中指定字段的值匹配。如果 xmlid 存在,但它指向的记录与值不匹配,则会将 xmlid 更新为指向一个匹配的记录(如果找到)。如果 xmlid 不存在,则使用找到的记录创建它。如果未找到匹配的记录,则不会执行任何操作。在所有情况下,都会返回 xml_id 引用的记录(可能已更新)。- 参数
- 返回
匹配记录的 ID,如果未找到记录则为
None
- 返回类型
小技巧
在将数据库中的记录迁移到自定义模块时,此函数非常有用,可以在模块更新之前创建 xml_ids 并避免重复。
- odoo.upgrade.util.records.update_record_from_xml(cr, xmlid, reset_write_metadata=True, force_create=AUTOMATIC, from_module=None, reset_translations=(), ensure_references=False, fields=None)[源代码]¶
根据其在 数据文件(Data Files) 中的定义更新记录。
此函数忽略记录的
noupdate
标志。它会在 xmlid 或from_module
参数(如果设置)所指定的模块清单中的所有 XML 文件中搜索匹配的定义。找到后,它会强制 ORM 按照数据文件中的规范更新记录。可选地,此函数可以重置某些字段的翻译。
- 参数
xmlid (str) – 记录的 xml_id,格式为
module.name
reset_write_metadata (bool) – 是否更新记录的
write_date
force_create (bool) – 如果记录不存在是否创建记录。默认为
True
,除非fields
不为 None。from_module (str) – 从中更新记录的模块名称,仅当规范位于不同于 xml_id 所在模块的其他模块中时才需要。
ensure_references (bool) – 通过
ref
XML 属性引用的记录是否也应更新。fields (set(str) or None) – 要在 XML 声明中包含的字段的可选列表。如果设置,所有其他字段将被忽略。如果设置且记录缺失,则不会创建记录。
警告
此函数使用 ORM,因此只能在记录的数据规范中引用的所有模型均已加载之后使用。实际上,这意味着此函数应在
post-
或end-
脚本中使用。注解
ORM 的标准行为是如果记录不存在则创建记录,包括其 xml_id。此函数也会发生这种情况,除非将
force_create
设置为False
。
- odoo.upgrade.util.records.delete_unused(cr, *xmlids, **kwargs)[源代码]¶
删除未使用的记录。
此函数仅在
xmlids
指向的记录未被任何表引用时才会删除这些记录。对于具有层级结构的记录(例如产品分类),它会检查标记为级联删除的子记录是否也未被引用。在这种情况下,记录及其子记录将全部删除。注解
无法删除的记录将被设置为
noupdate=True
。
- odoo.upgrade.util.records.replace_record_references_batch(cr, id_mapping, model_src, model_dst=None, replace_xmlid=True, ignores=())[源代码]¶
替换对记录的所有引用。
此函数将对
model_src
记录的所有引用(直接或间接)替换为映射中的对应记录。如果映射的目标模型与源模型不同,则必须设置model_dst
参数。
ORM¶
通过 ORM 执行操作的实用函数。
此模块中的函数允许在升级期间安全地使用 ORM。它们增强或修补了 ORM,使其能够高效处理大量数据。在某些情况下,提供了完全不同于 ORM 自身功能的替代方案。此模块中的函数适用于 所有 支持版本的 ORM。
- odoo.upgrade.util.orm.env(cr)[源代码]¶
创建一个新环境。
警告
此函数不会清空为超级用户维护的缓存(在空环境中)。每次直接在数据库中修改数据时,可能需要调用
invalidate_cache
。- 返回
新环境
- 返回类型
- odoo.upgrade.util.orm.recompute_fields(cr, model, fields, ids=None, logger=<Logger odoo.upgrade.util.orm (WARNING)>, chunk_size=256, strategy='auto')[源代码]¶
重新计算字段值。
此函数将重新计算模型的字段值,限制为一组记录或所有记录。重新计算不会一次性处理所有记录,而是分成多个批次(块)。这样可以避免性能问题,并在最坏情况下避免因
MemoryError
导致失败。每个块处理完成后,数据会根据以下策略之一返回数据库:flush:使用 ORM 的
flush
方法commit:提交游标(同时也会刷新)
auto:根据要计算的记录数量和是否存在跟踪字段,从上述两种策略中选择最佳选项。
commit 策略在处理大量数据时更不容易导致
MemoryError
。
- class odoo.upgrade.util.orm.iter_browse(model, *args, **kw)[源代码]¶
遍历记录集。
此类返回的
callable
对象可以用作迭代器,按块加载记录(到recordset
中)。每个块耗尽后,其数据会被发送回数据库(刷新或提交),然后加载下一个块。此类允许运行如下代码:
for record in env['my.model'].browse(ids): record.field1 = val env['my.model'].browse(ids)._compute_field2() env['my.model'].create(values)
以高效的方式运行,同时避免
MemoryError
,即使ids
或values
包含数百万条目。使用此类的替代方法是:Example
MyModel = util.env(cr)['my.model'] for record in util.iter_browse(MyModel, ids): record.field1 = val util.iter_browse(MyModel, ids)._compute_field2() util.iter_browse(MyModel, ids).create(values)
- 参数
model (
odoo.model.Model
) – 要迭代的模型chunk_size (int) – 每次迭代块中加载的记录数量,默认为
200
logger (
logging.Logger
) – 用于报告进度的日志记录器,默认为_logger
strategy (str) – 是否在每个块上执行
flush
或commit
,默认为flush
- 返回
此类返回的对象可用于安全地迭代或调用任何模型方法,即使是数百万条记录。
另请参见
env()
- odoo.upgrade.util.domains.adapt_domains(cr, model, old, new, adapter=None, skip_inherit=(), force_adapt=False)[源代码]¶
在域中使用
model
和继承模型将old
替换为new
。adapter
是一个用于调整叶子节点的回调函数。适配器函数必须接受三个参数,并返回一个替换原始叶子节点的 域。参数如下:leaf
:一个域叶子节点,形式为(left, op, right)
的元组in_or
:布尔值,当为True
时表示该叶子节点是 OR ("|"
) 域的一部分,否则是 AND ("&"
) 域的一部分negated
:布尔值,当为True
时表示该叶子节点被取反 ("!"
)
Example
def adapter(leaf, in_or, negated): left, op, right = leaf ok, ko = (1, 2) if not negated else (2, 1) if op == "=" return [(left, "=", ok)] elif op == "!=": return [(left, "=", ko)] return [leaf]
除非
force_adapt
为True
,否则adapter
仅对那些将model
的old
字段作为叶子节点left
部分的 最后一部分 使用的叶子节点调用。在后一种情况下,如果字段出现在路径中的任何位置,则会调用适配器,这仅对关系字段有用。适配器返回的域不需要在输入叶子节点的
left
部分将old
字段替换为new
。无论如何,替换都会应用于适配器返回的整个域。适配器的通常用途是修改操作符和输入叶子节点的right
部分。如果未设置adapter
,则仅执行替换操作。Example
当将
"field1"
替换为"field2"
时,会发生以下情况:("foo.bar.baz.field1", "=", 1)
仅在foo.bar.baz
指向的记录属于请求的model
时才会被调整。("foo.field1.baz", "=", 1)
即使foo
指向model
,也不会被调整,除非force_adapt
为True
,因为field1
不是此叶子节点中left
的最后一部分。
注解
此函数将替换所有 标准 域字段中的域,包括过滤器、仪表板和已知表示域的标准字段。
SQL¶
用于与 PostgreSQL 交互的实用函数。
- odoo.upgrade.util.pg.parallel_execute(cr, queries, logger=<Logger odoo.upgrade.util.pg (WARNING)>)[源代码]¶
并行执行查询。
Example
util.parallel_execute(cr, [util.format_query(cr, "REINDEX TABLE {}", t) for t in tables])
小技巧
如果希望加速单个查询,请参见
explode_execute()
。- 参数
- 返回
每个查询运行后的
cr.rowcount
总和- 返回类型
警告
由于
cr.rowcount
的特性,此函数的返回值可能低估了实际受影响记录的数量。例如,当某些记录因ondelete
子句而被删除或更新时,它们不会被计入。作为副作用,游标将被提交。
注解
如果发生并发问题,失败的查询将按顺序重试。
- odoo.upgrade.util.pg.format_query(cr, query, *args, **kwargs)[源代码]¶
安全格式化查询。
传递给此函数的
str
参数假定为 SQL 标识符。在使用str.format()
展开之前,它们会被包裹在双引号中。任何其他 psycopg2.sql.Composable 也是允许的。这包括ColumnList
,另请参见get_columns()
。Example
>>> util.format_query(cr, "SELECT {0} FROM {table}", "id", table="res_users") SELECT "id" FROM "res_users"
- 参数
query (str) – 要格式化的查询,可以像
str.format()
一样使用大括号{}
- odoo.upgrade.util.pg.explode_execute(cr, query, table, alias=None, bucket_size=10000, logger=<Logger odoo.upgrade.util.pg (WARNING)>)[源代码]¶
并行执行查询。
查询按 ID 分桶拆分,然后由工作线程并行处理。如果查询未包含特殊的
{parallel_filter}
值,则会将其添加到最后一个WHERE
子句中(如果未找到WHERE
子句,也可能新增)。如果查询已经包含过滤器,则不执行任何操作。过滤器始终扩展为拆分策略。拆分时,每个单独查询更新的 ID 数量不超过bucket_size
。Example
util.explode_execute( cr, ''' UPDATE res_users u SET active = False WHERE (u.login LIKE 'dummy' OR u.login = 'bob') AND {parallel_filter} ''', table="res_users" alias="u", )
- 参数
query (str) – 要执行的查询。
table (str) – 查询的主表名称,用于拆分处理
alias (str) – 查询中为主表使用的别名
bucket_size (int) – 用于拆分处理的 ID 桶大小
logger (
logging.Logger
) – 用于报告进度的日志记录器
- 返回
每个查询运行后的
cr.rowcount
总和- 返回类型
警告
调用者需要确保查询不会在不同的桶中更新相同的记录。建议不要对具有自引用的表使用此函数执行
DELETE
查询,因为可能存在ON DELETE
影响。更多详细信息,请参见parallel_execute()
。
- odoo.upgrade.util.pg.create_column(cr, table, column, definition, **kwargs)[源代码]¶
创建列。
此函数仅在列不存在时创建该列。如果现有列的类型不同,它会记录错误。如果设置了
fk_table
,它将确保外键已设置,并在必要时进行更新,同时应用正确的 `on_delete_action`(如果有)。
- odoo.upgrade.util.pg.alter_column_type(cr, table, column, type, using=None, where=None, logger=<Logger odoo.upgrade.util.pg (WARNING)>)[源代码]¶
更改列的类型。
通过使用临时列和并行 UPDATE 查询高效完成。
- odoo.upgrade.util.pg.remove_constraint(cr, table, name, cascade=False, warn=True)[源代码]¶
删除表约束。
此函数从
table
中删除名为name
的约束。它还会从ir_model_constraint
及其 xml_ids 中删除记录,并记录未找到的约束。注解
如果没有名为
name
的约束,此函数将尝试删除{table}_{name}
,后者是 ORM 为从_sql_constraints
创建的约束使用的默认名称。
- class odoo.upgrade.util.pg.ColumnList(list_=(), quoted=())[源代码]¶
封装表示列名称的元素列表。
生成的对象可以渲染为带有前导/尾随逗号或别名的字符串。
Example
>>> columns = ColumnList(["id", "field_Yx"], ["id", '"field_Yx"'])
>>> list(columns) ['id', '"field_Yx"']
>>> columns.using(alias="t").as_string(cr._cnx) '"t"."id", "t"."field_Yx"'
>>> columns.using(leading_comma=True).as_string(cr._cnx) ', "id", "field_Yx"'
>>> util.format_query(cr, "SELECT {} t.name FROM table t", columns.using(alias="t", trailing_comma=True)) 'SELECT "t"."id", "t"."field_Yx", t.name FROM table t'
>>> columns = ColumnList.from_unquoted(cr, ["foo", "BAR"])
>>> list(columns) ['"foo"', '"BAR"']
>>> list(columns.iter_unquoted()) ['foo', 'BAR']
注解
此类最好通过
get_columns()
使用
杂项¶
各种独立函数。
- odoo.upgrade.util.misc.version_gte(version)[源代码]¶
返回当前运行的 Odoo 版本是否大于或等于
version
。此函数对于适用于多个版本的升级脚本中的条件执行非常有用,例如
0.0.0
脚本。
- odoo.upgrade.util.misc.version_between(a, b)[源代码]¶
返回当前运行的 Odoo 版本是否在范围
[a,b]
内。另请参见
version_gte()
注解
边界值包含在内。
- odoo.upgrade.util.misc.expand_braces(s)[源代码]¶
展开输入中的大括号。
Example
>>> util.expand_braces("a_{this,that}_b") ['a_this_b', 'a_that_b']
- 参数
s (str) – 要展开的字符串,必须包含且仅包含一对大括号。
- 返回
展开后的输入
- odoo.upgrade.util.misc.import_script(path, name=None)[源代码]¶
导入升级脚本。
此函数允许从其他升级脚本中导入函数到当前脚本中。
Example
在
mymodule/15.0.1.0/pre-migrate.py
中def my_util(cr): # do stuff
在
myothermodule/16.0.1.0/post-migrate.py
中from odoo.upgrade import util script = util.import_script("mymodule/15.0.1.0/pre-migrate.py") def migrate(cr, version): script.my_util(cr) # reuse the function
此函数返回一个 Python
module
。>>> util.import_script("base/0.0.0/end-moved0.py", name="my-moved0") <module 'my-moved0' from '/home/odoo/src/upgrade-util/src/base/0.0.0/end-moved0.py'>
- odoo.upgrade.util.misc.skippable_cm()[源代码]¶
返回一个上下文管理器,允许另一个上下文管理器不产生值。
参见
edit_view()
获取示例用法。
- odoo.upgrade.util.misc.chunks(iterable, size, fmt=None)[源代码]¶
将
iterable
拆分为大小为size
的块,并使用fmt
函数包装每个块。此函数对于将大量输入数据拆分为可独立处理的小块非常有用。
Example
>>> list(chunks(range(10), 4, fmt=tuple)) [(0, 1, 2, 3), (4, 5, 6, 7), (8, 9)] >>> ' '.join(chunks('abcdefghijklm', 3)) 'abc def ghi jkl m'
- 参数
iterable (iterable) – 要拆分的可迭代对象
size (int) – 块大小
fmt (function) – 应用于每个块的函数,当传入
None
时,fmt
在iterable
为字符串时变为"".join
,否则为iter
。
- 返回
一个生成器,迭代
fmt
应用于每个块的结果