From 41a0449f6db357d81bd655eeb5e07581dde548a5 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 7 May 2026 15:37:55 +0200 Subject: [PATCH] component: fix component init compat with py3.10 In Python 3.10, dynamically reassigning __bases__ on a class (as done in _build_component) incorrectly propagates slot descriptors from classes that become transitively reachable through the new MRO. odoo.models.BaseModel declares env as a __slots__ entry, which creates a data descriptor on the class. When _build_component rewrites ComponentClass.__bases__, Python 3.10 surfaces this slot descriptor in the component's MRO. Since the slot storage does not exist on component instances, any attempt to assign self.env = value raises AttributeError: can't set attribute. This bug was fixed in Python 3.12 (see cpython#95573), which is why the issue could not be reproduced locally. The fix defines env as a property with both getter and setter directly on AbstractComponent. Since AbstractComponent always precedes BaseModel in the built class MRO, the property descriptor takes priority, and self.env = value correctly routes through the setter regardless of Python version. --- component/core.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/component/core.py b/component/core.py index 483820037..6af800aab 100644 --- a/component/core.py +++ b/component/core.py @@ -696,11 +696,22 @@ def vocalize(action, message): #: Component purpose ('import.mapper', ...). _usage = None + _env = None + def __init__(self, work_context): super().__init__() self.work = work_context self.env = work_context.env + @property + def env(self): + """Return the current Odoo env""" + return self._env + + @env.setter + def env(self, value): + self._env = value + @classmethod def _component_match(cls, work, usage=None, model_name=None, **kw): """Evaluated on candidate components