Skip to content

invalid-odoo-method-call (ODE9502)

Preview (since 0.16.3.34) · Related issues · View source

Derived from the odoo linter.

This rule is unstable and in preview. The --preview flag is required for use.

What it does

Checks calls to Odoo ORM model methods against the parameter list the method actually has in the configured odoo-version.

Why is this bad?

Odoo reshapes ORM signatures between releases, and the call sites do not fail until the line runs. read_group is the extreme case: 20.0 reused the freed name for a different method, so self.read_group(domain, fields, groupby, lazy=False) raises TypeError: got an unexpected keyword argument 'lazy' there while reading as valid code. The same happens more quietly elsewhere — _search dropped access_rights_uid in 18.0, name_search renamed args to domain in 19.0 — and a migration has no way to find them short of running every branch.

The check needs signatures to compare against, so it reports nothing unless odoo-version is set to a version this linter ships a stub for. Since that silence is indistinguishable from a clean run, it warns once on stderr when the setting is missing or names a version with no signatures; the run still succeeds, and the warning only appears when this rule is enabled.

Only receivers that are certainly recordsets are checked: self and super() inside a model class, env[...] subscripts anywhere, and chains of recordset-returning ORM calls over either, so self.env["res.partner"].sudo().search(...) is covered. A local is not, because nothing distinguishes one holding a recordset from one holding a worksheet. A method the file defines itself is left alone too, since the call may well mean that override rather than Odoo's -- except through env["other.model"], which reaches a model the override says nothing about.

Known limitation

The check binds arguments; it does not know that a name changed meaning. Where Odoo reused a freed name for a method of the same arity, a fully positional call still binds and is not reported, even though every argument now lands on a different parameter:

# Silent on 20.0: seven positionals against a signature that takes seven.
super().read_group(domain, fields, groupby, offset, limit, orderby, lazy)

Nothing in that call distinguishes it from correct 20.0 code, so reporting it would land on code that is right. Naming a repurposed method is deprecated-odoo-method-call's job, not this one's.

Example

groups = self.read_group(domain, ["amount:sum"], ["partner_id"], lazy=False)

Use instead:

groups = self._read_group(domain, ["partner_id"], ["amount:sum"])