Skip to content

Code inspection ​

Get inline warnings in Python, XML and CSV files when your code departs from Odoo conventions. Each warning shows the exact location and the value the plugin expects, and some offer a quick fix. Inspections run as you edit.

What you can do ​

File typeWhat is checked
PythonFile structure, manifest keys and hooks, model and class names, field names and attributes, function names and decorators.
XMLRecord and field order, view, menu, action, group and rule names and IDs, and the links between menus and actions.
CSVStructure and naming of ir.model.access.csv.

Python ​

File structure

  • The file starts with the UTF-8 declaration # -*- coding: utf-8 -*-.
  • Imports in __init__.py are in alphabetical order, and so are the items in from odoo import ....
python
# -*- coding: utf-8 -*-
from . import models
from . import wizards

from odoo import api, fields, models

Manifest (__manifest__.py)

  • Required keys are present: name, summary, description, version, license, category and images.
  • summary and description are different, and images is not empty.
  • version uses five numbers, such as 16.0.1.0.0.
  • If you declare a hook (pre_init_hook, post_init_hook, uninstall_hook or post_load), the matching function exists in hooks.py.

Models and classes

  • The file name matches the model: sale.order is in sale_order.py.
  • The class name is PascalCase: SaleOrder.
  • _name uses only lowercase letters, dots and underscores.
  • _description is set when _name is set.

Fields

RuleExample
Many2one names end with _id.partner_id = fields.Many2one('res.partner')
One2many and Many2many names end with _ids.line_ids = fields.One2many('sale.order.line', 'order_id')
Do not set default values explicitly.Use fields.Char(), not fields.Char(required=False). The same applies to readonly=False and store=True on stored fields.
No conflicting attributes.fields.Char(required=True, readonly=True) is flagged.
string starts with a capital letter.string='Customer Name'
string is not redundant.name = fields.Char(string='Name') is flagged because Odoo derives it.
string and help differ.string='Description', help='Description' is flagged.

The redundant-attribute warnings have a quick fix that removes the attribute.

Function names

KindPatternExample
@api.onchange_onchange_<field_name>_onchange_partner_id
@api.constrains_check_<field_name>_check_amount_total
Compute method_compute_<field_name>_compute_amount_total
Default method_default_<field_name>, with @api.model_default_currency_id

Call a default method from the field with a lambda:

python
currency_id = fields.Many2one(
    'res.currency',
    default=lambda self: self._default_currency_id()
)

@api.model
def _default_currency_id(self):
    return self.env.company.currency_id

XML ​

Records and fields

  • A <record> has id and model attributes, with id first.
  • A <field> has name as its first attribute.
  • Non-updatable data sits in <data noupdate="1">.

Names and IDs

The plugin derives the model name from the file name and the view type from the arch, then checks the pattern.

ElementPatternExample
View name<model.name>.view.<type>sale.order.view.form
View ID<model_name>_view_<type>sale_order_view_form
Menu ID<model_name>_menu_<description>sale_order_menu_main
Action ID<model_name>_actionsale_order_action
Record rule ID<model_name>_rule_<group_type>sale_order_rule_company
Group ID<module_name>_group_<group_name>sale_management_group_manager
  • A rule counts as a company rule when its domain contains company_id, and as a user rule when it uses base.group_user.
  • The module name comes from the file path.
  • Menu IDs must match ^[a-z0-9]+(_[a-z0-9]+)*_menu(_[a-z0-9]+)*$.

Cross-checks

The plugin tracks the links between menu items and their actions, and checks them for consistency.

xml
<record id="sale_order_view_form" model="ir.ui.view">
    <field name="name">sale.order.view.form</field>
    <field name="model">sale.order</field>
    <field name="arch" type="xml">
        <form>
            <field name="name"/>
        </form>
    </field>
</record>

<menuitem id="sale_order_menu_main"
          name="Sales Orders"
          action="sale_order_action"
          parent="sale.sale_menu_root"/>

CSV ​

For ir.model.access.csv:

  • The file has a header and at least one data line.
  • The columns id, name and model_id are present.
  • Access IDs follow access_<model_name> and names follow access.<model.name>, derived from the model_id value.
  • Quoted fields with commas and escaped quotes are read correctly, and a warning points at the exact field.
model_idExpected idExpected name
model_sale_orderaccess_sale_orderaccess.sale.order
model_account_moveaccess_account_moveaccess.account.move
model_res_partneraccess_res_partneraccess.res.partner
csv
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_sale_order,access.sale.order,model_sale_order,base.group_user,1,1,1,1
access_account_move,access.account.move,model_account_move,base.group_user,1,0,0,0

Get started ​

Inspections run automatically as you edit. To turn them on or off:

  1. Open Settings > Editor > Inspections > Cybrosys Assista.
  2. Select or clear the inspections you want:
InspectionControls
Assista Py-InspectionPython standard inspections
Assista XML-InspectionXML standard inspections
Assista CSV-InspectionCSV standard inspections

Tips and limits ​

  • Enable all three inspections from the start, and fix warnings as they appear rather than at review time.
  • Share your inspection settings with your team so everyone sees the same warnings.
  • Guidelines change between Odoo releases. Check the current Odoo coding guidelines if a warning looks wrong for your version.

Next steps ​

Built by Cybrosys Technologies.