OD230 orphan-hook-method¶
A compute, inverse, search or onchange method of a model extension is named nowhere, so Odoo never runs it.
| Category | Severity | Series | Needs the index |
|---|---|---|---|
| Correctness | Info | all | yes |
What it reports¶
A method of a class that extends its model in place, with _inherit and no other _name, whose
name starts with _compute_, _inverse_, _search_, _onchange_ or onchange_, when:
- no other class of the model or of a model it inherits defines it, nor
BaseModel; - no file of any indexed module names it outside the
defitself, comments included: a Python, XML or CSV file anywhere in a module, or a script or template under itsstatic/src; - its decorators, if any, are among
api.depends,api.depends_context,api.model,api.multi,api.oneandapi.returns; - Odoo could call it with what it passes: the operator and the value for a
_search_method, by position or through*args, nothing for a_compute_,_inverse_or_onchange_one, and anything for anonchange_one; - the class binds its name once.
A name built at runtime counts by its literal part: "_compute_%s" % name,
f"_compute_{name}", `_compute_${name}` and "_compute_" + name name every method that
starts with _compute_.
Why it matters¶
Odoo runs such a method only by the name a field option gives it (compute, inverse or
search), through the @api.onchange decorator on the method itself, or, through 11.0, by the
on_change attribute of a view field, which spells the call with its arguments. An override that
upstream renamed, or whose field upstream dropped, becomes dead code: the change it was written
for no longer happens, and nothing fails to say so.
A method called by a name the text of the scan never spells, such as one read from the database,
is reported. A super() call of the method spells its name, so OD211 reports that
override instead. The rule leaves out:
- the methods of a new model, whose hooks are its own to leave unused;
- a method with another decorator, which may register it elsewhere;
- a method that requires arguments Odoo does not pass, a helper that only shares the prefix;
- every method where OD211 is silent;
- every method of a model when a class of it, or of a model it inherits, has a plain Python class among its bases, whose methods the scan cannot read; a base its file defines above that class with nothing but methods and literals in its body is read, and defines the names it binds;
- every method of a module when it, a module it depends on or one that depends on it has a file the scan cannot read or decode, which may name the method.
A script under static/tests does not count as naming a method, since Odoo loads it only to run
the tests.
Example¶
class AccountMove(models.Model):
_inherit = "account.move"
@api.depends("journal_id", "sequence_number")
def _compute_made_sequence_hole(self):
for move in self:
move.made_sequence_hole = move.journal_id.code != "IMP" and move.sequence_number > 1
account 17.0 computes made_sequence_hole with _compute_made_sequence_hole. 18.0 replaces
the field with made_sequence_gap, computed by _compute_made_sequence_gap, so the override no
longer runs.
class AccountMove(models.Model):
_inherit = "account.move"
@api.depends("journal_id", "sequence_number")
def _compute_made_sequence_gap(self):
for move in self:
move.made_sequence_gap = move.journal_id.code != "IMP" and move.sequence_number > 1