Upgrade utils

Upgrade utils is a library that contains helper functions to facilitate the writing of upgrade scripts. This library, used by Odoo for the upgrade scripts of standard modules, provides reliability and helps speed up the upgrade process:

  • The helper functions help make sure the data is consistent in the database.

  • It takes care of indirect references of the updated records.

  • Allows calling functions and avoid writing code, saving time and reducing development risks.

  • Helpers allow to focus on what is important for the upgrade and not think of details.

Installation

Clone the Upgrade utils repository locally and start odoo with the src directory prepended to the --upgrade-path option.

$ ./odoo-bin --upgrade-path=/path/to/upgrade-util/src,/path/to/other/upgrade/script/directory [...]

On platforms where you do not manage Odoo yourself, you can install this library via pip:

$ python3 -m pip install git+https://github.com/odoo/upgrade-util@master

On Odoo.sh it is recommended to add it to the requirements.txt of the custom repository. For this, add the following line inside the file:

odoo_upgrade @ git+https://github.com/odoo/upgrade-util@master

Using Upgrade utils

Once installed, the following packages are available for the upgrade scripts:

  • odoo.upgrade.util: the helper itself.

  • odoo.upgrade.testing: base TestCase classes.

To use it in upgrade scripts, simply import it:

from odoo.upgrade import util


def migrate(cr, version):
   # Rest of the script

Now, the helper functions are available to be called through util.

Util functions

Upgrade utils provides many useful functions to ease the upgrade process. Here, we describe some of the most useful ones. Refer to the util folder for the comprehensive declaration of helper functions.

Note

All util functions receive cr as a parameter. This refers to the database cursor. Pass the one received as a parameter in migrate().

Fields

remove_field(cr, model, fieldname, cascade=False, drop_column=True, skip_inherit=())

Remove a field and its references from the database.

Parameters
  • model (str) – model name of the field to remove

  • fieldname (str) – name of the field to remove

  • cascade (bool) – whether the field’s column and inheritance are removed in CASCADE

  • drop_column (bool) – whether the field’s column is dropped

  • skip_inherit (list(str) or str) – list of models whose field’s inheritance is skipped. Use "*" to skip all inheritances

rename_field(cr, model, old, new, update_references=True, domain_adapter=None, skip_inherit=())

Rename a field and its references from old to new.

Parameters
  • model (str) – model name of the field to rename

  • old (str) – current name od the field to rename

  • new (str) – new name od the field to rename

  • update_references (bool) – whether all references of field old to new are replaced in: ir_filters, ir_exports_line, ir_act_server, mail_alias, ir_ui_view_custom (dashboard), domains (using "domain_adapter"), related fields

  • domain_adapter (function) – function that takes three arguments and returns a domain that substitutes the original leaf: (leaf: Tuple[str,str,Any], in_or: bool, negated: bool) -> List[Union[str,Tuple[str,str,Any]]]

  • skip_inherit (list(str) or str) – list of models whose field’s inheritance is skipped. Use "*" to skip all inheritances

move_field_to_module(cr, model, fieldname, old_module, new_module, skip_inherit=())

Move a field’s reference in ir_model_data table from old_module to new_module.

Parameters
  • model (str) – model name of the field to move

  • fieldname (str) – name of the field to move

  • old_module (str) – current module name of the field to move

  • new_module (str) – new module name of the field to move

  • skip_inherit (list(str) or str) – list of models whose field’s inheritance is skipped. Use "*" to skip all inheritances

Models

remove_model(cr, model, drop_table=True, ignore_m2m=())

Remove a model and its references from the database.

Parameters
  • model (str) – name of the model to remove

  • drop_table (bool) – whether the model’s table is dropped

  • ignore_m2m (list(str) or str) – list of m2m tables ignored to remove. Use "*" to ignore all m2m tables

rename_model(cr, old, new, rename_table=True)

Rename a model and its references from old to new.

Parameters
  • old (str) – current name of the model to rename

  • new (str) – new name of the model to rename

  • rename_table (bool) – whether the model’s table is renamed

merge_model(cr, source, target, drop_table=True, fields_mapping=None, ignore_m2m=())

Merge the references from source model into target model and removes source model and its references. By default, only the fields with the same name in both models are mapped.

Warning

This function does not move the records from source model to target model.

Parameters
  • source (str) – name of the source model of the merge

  • target (str) – name of the destination model of the merge

  • drop_table (bool) – whether the source model’s table is dropped

  • fields_mapping (dict) – Dictionary {"source_model_field_1": "target_model_field_1", ...} mapping fields with different names on both models

  • ignore_m2m (list(str) or str) – list of m2m tables ignored to remove from source model.

Modules

remove_module(cr, module)

Uninstall and remove a module and its references from the database.

Parameters

module (str) – name of the module to remove

rename_module(cr, old, new)

Rename a module and its references from old to new.

Parameters
  • old (str) – current name of the module to rename

  • new (str) – new name of the module to rename

merge_module(cr, old, into, update_dependers=True)

Move all references of module old into module into.

Parameters
  • old (str) – name of the source module of the merge

  • into (str) – ame of the destination module of the merge

  • update_dependers (bool) – whether the dependencies of modules that depends on old are updated

ORM

env(cr)

Create a new environment from the cursor.

Warning

This function does NOT empty the cache maintained on the cursor for superuser with an empty environment. A call to invalidate_cache will most probably be necessary every time you directly modify something in database.

Returns

The new environment

Return type

Environment

recompute_fields(cr, model, fields, ids=None, logger=_logger, chunk_size=256, strategy='auto')

Recompute field values. Possible strategies to process the recomputation:

  • flush: Flush the recomputation when it’s finished

  • commit: Commit the recomputation when it’s finished

  • auto: The function chooses the best alternative based on the number of records to recompute and the fields traceability

Parameters
  • model (str) – model name of the field(s) to recompute

  • fields (list(str)) – list of field names to recompute

  • ids (list(int)) – list of record IDs to recompute

  • logger (logging.Logger) – Logger used to print the progress of the function

  • chunk_size (int) – size of the chunk used to split the records for better processing

  • strategy (str) – strategy used to process the recomputation

Records

ref(cr, xmlid)

Return the id corresponding to the given xml_id.

Parameters

xml_id (str) – Record xml_id, under the format <module.id>

Returns

Found record id, if any

Return type

int or None

remove_record(cr, name)

Remove a record and its references corresponding to the given xml_id.

Parameters

name (str) – record xml_id, under the format <module.id>

rename_xmlid(cr, old, new, noupdate=None, on_collision='fail')

Rename the external Identifier of a record. Possible actions to take if the external Identifier already exists on the database:

  • fail: raise MigrationError and prevent renaming

  • merge: renames the external Identifier and removes the old one

Parameters
  • old (str) – current xml_id of the record, under the format <module.id>

  • new (str) – new xml_id of the record, under the format <module.id>

  • noupdate (bool) – value to set on the ir_model_data record noupdate field

  • on_collision (str) – action to take if the xml_id already exists

ensure_xmlid_match_record(cr, xmlid, model, values)

Match a record with an xmlid by creating or updating the external identifier.

This function is useful when migrating in-database records into a custom module, to create the record’s xmlid before the module is updated and avoid duplication.

Parameters
  • xmlid (str) – record xml_id, under the format <module.id>

  • model (str) – model name of the record

  • values (dict) –

    Dictionary {"fieldname_1": "value_1", ...} mapping fields and values to search for the record to update. For example:

    values = {"id": 123}
    values = {"name": "INV/2024/0001", company_id: 1}
    

Returns

the xml_id of the record.

Return type

str

update_record_from_xml(cr, xmlid, reset_write_metadata=True, force_create=True, from_module=None, reset_translations=())

Update a record based on its definition in the Data Files.

Useful to update noupdate records, in order to reset them for the upgraded version.

Parameters
  • xmlid (str) – record xml_id, under the format <module.id>

  • reset_write_metadata (bool) – whether the metadata before the record update is kept

  • force_create (bool) – whether the record is created if it does not exist

  • from_module (str) – name of the module from which to update the record. Useful when the record is rewritten in another module.

  • reset_translations (set of str) – set of field names whose translations get reset