[IMP] fields: New x2many command namespace

Documentation (scroll a bit)
https://www.odoo.com/documentation/master/reference/orm.html#relational-fields

Namespace source code
https://github.com/odoo-dev/odoo/blob/5d522e9bab3f44b1155cc0bfcd1214b3d920315f/odoo/fields.py#L2805

Github PR
https://github.com/odoo/odoo/pull/60965

TL;DR

You were writing 3-elements tuples with an obscure literal integer, you now use the new fields.Command namespace instead.

You may import the new namespace Command from odoo or odoo.fields. It contains helper fonctions and low level named constants for every x2many command. Functions are create(values), update(id, values), delete(id), unlink(id), link(id), clear() and set(ids). Named constants are CREATE (0), UPDATE (1), DELETE (2), UNLINK (3), LINK (4), CLEAR (5) and SET (6).

The 3-elements-tuple literal usage is deprecated in favor of the Command namespace. We plan to enforce its usage using a pylint extension in the runbot in some years.

x2many commands

Because One2many and Many2many are complex values they get updated procedurally via commands. Internally these commands are triplets of a command identifier and up to 2 parameters.

As the command identifier is an integer (usually literal) its meaning is not self-explanatory, and while old hands are used to them they often cause newcomers to stumble.

The reason the various commands are obscure triplets is because they have to be compatible with the xmlrpc layer. Alternatives like using string constants instead of integers have been considered but showed limitations.

Command namespace

Because we still believe we can do better than (0, 0 {...}), we created a namespace that maps every command identifier to a name and provided fully documented helper functions to create the tuples. The source code is linked above. The implementation was kept simple on purpose.

Using the namespace, you can replace record.parter_ids = [(5,), (0, 0, {...})] by record.parter_ids = [Command.clear(), Command.create({...})]. More keystrokes but nicer to read.

What should I do with this namespace ?

For now the namespace is opt-in. We let you decide whether to use it or not, to use it only for new code, only when you have a diff or to change everything in one bulk commit. If you wish to change the source code of your module in bulk, you might be interested by the following tool: https://gist.github.com/Julien00859/757c21df92c43c241fd703d05e9156f7.

In the long term (in a few years), we plan to enforce you use the Command namespace, using the above tool as a pylint extension to detect code that needs to be migrated. In other terms, we are deprecating the usage of the command literal triplet in favor the namespace and plan to enforce the namespace in some years.

--

If you have any question, remark, I'm hiding in the #rd-framework-py in discord. Feel free to reach me or my team.

Cheers,
Julien