odoo/odoo#70183

Created by Merel Geens
Closed
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.