odoo/odoo#70183
Created by Merel Geens
- label
- odoo-dev:14.0-hw_drivers-fix-interface-super-deprecation-warning-and-runtime-error-raf
- head
- 536f9b38df21d543d6921648f29ee35b9456bb23
odoo/odoo | |
---|---|
14.0 | #70183 |
[FIX] hw_drivers: InterfaceMetaClass violates CPython constraints and breaks imports
Currently, none of the classes derived from Interface
use super
. If
it's added, for example by adding this to SocketInterface
:
def __init__(self):
super().__init__()
, a deprecation warning will appear in Python 3.6 and 3.7:
2021-04-30 13:14:25,000 24736 WARNING ? py.warnings: /home/pi/odoo/addons/hw_drivers/iot_handlers/interfaces/SocketInterface.py:11: DeprecationWarning: class not set defining 'SocketInterface' as <class 'SocketInterface.py.SocketInterface'>. Was classcell propagated to type.new?
class SocketInterface(Interface):
In Python 3.8 this is no longer a warning and becomes a RuntimeError
.
The reason this happens is that InterfaceMetaClass
caches the results
of the __new__
calls it does in interfaces
. CPython's data model
specifies that when calling __new__
, the cell for __class__
needs to
be passed along to the parent class: https://docs.python.org/3/reference/datamodel.html#creating-the-class-object .
See https://docs.python.org/3/c-api/cell.html for a definition of what
a cell is.
Because of the caching, this doesn't happen when __new__
is called
multiple times for the same class. In the case of the SocketInterface
example, __new__
is called twice: first when it's imported directly by load_iot_handlers
and second when IngenicoDriver
imports it. The __class__
cell is
different each time in that case. With the caching present, this means
the second cell isn't propagated correctly, resulting in the warning /
error.
After load_iot_handlers
has finished, the Manager
's run
method
iterates over interfaces
, instantiating and starting the loaded
classes. Because of this, simply removing the caching appears to be
sufficient to avoid the issue while keeping the end result the same.