OD229 override-signature-mismatch¶
An override refuses a call that the method it overrides takes.
| Category | Severity | Series | Needs the index |
|---|---|---|---|
| Correctness | Error | saas~12.5 and later | yes |
What it reports¶
A method of a class that extends its model in place, with _inherit and no other _name, whose
parameters refuse a call that passes every parameter each definition it overrides requires:
- a positional parameter the parent requires, past those the override takes by position, when the
override has no
*args; - a parameter the override requires that no call made for the parent passes: a positional one past
the parent's, when the parent has no
*args, or a keyword-only one the parent cannot take by name, when the parent has no**kwargs; - a keyword-only parameter of the parent that the override cannot take by name, when the override
has no
**kwargs, and the parent requires it or the override adds a keyword-only parameter in its place.
The definitions it overrides are those of the other classes the registry merges into the model:
in the modules it depends on and those Odoo installs with base, short of one that depends on this
module, and above the class in its own file. The module's other files are left out, as their order
is that of the imports. Every one of them must refuse the call. The message names the one that
loads first, its module and its parameters, and the parameter the call fails on.
An override that drops an optional parameter, makes a default required or renames a positional parameter is not reported, as core overrides do all three where no caller passes that parameter. Nor is an override in a class that defines a model, whose callers may be its own.
Why it matters¶
Odoo calls a method on the model's records, so a caller written for the parent reaches the
override. When the override's parameters do not fit that call, Python raises TypeError and the
action fails. The usual cause is a parameter added upstream between versions that the override
does not take. Up to saas~12.4, Odoo wraps every method in api.guess, which adapts old-style
calls, so the rule starts at saas~12.5.
The rule stays silent when a definition has a decorator that may change the arguments it takes:
any but those of api, staticmethod, classmethod, override, ormcache and
ormcache_context. It is also silent when a class binds the method's name other than with a
def in its body, such as under an if. Python renames a __name method per class name, so it
is compared only with classes of the same name, leading underscores aside. The rule stays silent
where OD211 does, and when a class of the model 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: an
override of a name it binds and that class does not define is not compared, as the scan keeps no
signature of the base's, and every other override is.
Example¶
class StockRule(models.Model):
_inherit = "stock.rule"
def _get_matching_bom(self, product_id, company_id):
return super()._get_matching_bom(product_id, company_id, {})
mrp defines _get_matching_bom with a last parameter, values, which _run_manufacture passes.
class StockRule(models.Model):
_inherit = "stock.rule"
def _get_matching_bom(self, product_id, company_id, values):
return super()._get_matching_bom(product_id, company_id, values)