Skip to content

OD211 orphan-super

super() calls a method no parent class defines.

Category Severity Series Needs the index
Correctness Error all yes

What it reports

A super().name() call in a model class whose model, and the models it inherits, define no method name in any other class, and which is not a method of BaseModel such as create, write or search. A call in the body of a class defined inside a method is not the model's, while one in a nested function counts. A call inside a hasattr test on the same super() and name cannot fail and is not reported: write that test around a call whose parent may be missing. Nor is super().__getattr__() inside __getattr__, where the AttributeError it raises is the answer that method owes for a missing name. A BaseModel method counts in every series, whichever series has it, and so does a dunder of BaseModel or object, such as __init__: super() reaches both at the end of the model's classes. A method BaseModel lost before saas~11.5, such as create_workflow, counts only in the series that have it, and in none for a module of unknown series. Classes from modules outside depends count as parents here, because an override of a method such a module adds is only called by that module. A method of a model reached through _inherits or delegate=True does not count: the model gets the delegated model's fields, not its methods, and super() never reaches it. OD312 says what defines a method.

Why it matters

Python looks the method up along the model's classes when the call runs and raises AttributeError when no class after this one has it. The usual cause is a method renamed or removed upstream between versions: the override is then never called by Odoo, and calling it directly fails.

The rule stays silent when it cannot see every parent: a class with a plain Python class among its bases, a class of the model or of a model it inherits with an _inherit element that is not a literal, or in a file that does not parse in the module or its dependencies, which counts as one the scan cannot read, a module whose dependencies include one that is not indexed (such as an Enterprise module), a model no indexed module defines, and an abstract model, whose method may come from the models that inherit it. A plain base of another class of the model, which its file defines above that class with nothing but methods and literals in its body, is read, and the names it binds count as parent methods.

Example

models/sale_order.py
class SaleOrder(models.Model):
    _inherit = "sale.order"

    def _prepare_invoice_vals(self):
        vals = super()._prepare_invoice_vals()
        vals["narration"] = self.note
        return vals

sale names this method _prepare_invoice, so no parent has _prepare_invoice_vals.

models/sale_order.py
class SaleOrder(models.Model):
    _inherit = "sale.order"

    def _prepare_invoice(self):
        vals = super()._prepare_invoice()
        vals["narration"] = self.note
        return vals

Suppressing

vals = super()._prepare_invoice_vals()  # odooscan: ignore[OD211]

See suppressing a finding.