Creating a newly created class in a metaclass results in a RuntimeError ("super (): empty __class__ cell")

So, I have this metaclass that I want to use to automatically register new components, i.e. subclasses of some base component. When registering a new component, it is expected that its instance will be passed to the register_component () function, which handles this.

Metaclass Code (stripped down version):

class AutoRegisteredMeta(type): def __new__(metacls, name, bases, attrs): # ... (omitted) check if "name" has already been registered ... new_class = super().__new__(metacls, name, bases, attrs) register_component(name, new_class()) # RuntimeError(super(): empty __class__ cell) return new_class 

The problem is that calling new_class() results in an error, but not for all classes. After some experimentation, I realized that this only happens if the subclass calls super().__init__() in its own __init__() method.

An example of a component and a base class:

 class BaseComponent(metaclass=AutoRegisteredMeta): def __init__(self): # do some work here ... class ComponentFoo(BaseComponent): def __init__(self): super().__init__() # <--- RuntimeError occurs here self.foo = 'bar' 

What am I doing wrong here? Reading this I found out that I probably shouldn't create an instance in the metaclasses __new__() or __init__() , right? Could this somehow get around?

Also, some explanation in layman terms would be nice, I don’t know many internal functions of CPython implementation.

Thanks in advance!

(FWIW, I am using Python 3.3.6, Ubuntu)


EDIT: I am adding the minimal example that was requested, you can run it directly and see the error in action yourself.

 #!/usr/bin/env python3 class AutoRegisteredMeta(type): def __new__(metacls, name, bases, attrs): new_class = super().__new__(metacls, name, bases, attrs) new_class() # <--- RuntimeError can occur here return new_class class BaseComponent(metaclass=AutoRegisteredMeta): def __init__(self): print("BaseComponent __init__()") class GoodComponent(BaseComponent): def __init__(self): print("GoodComponent __init__()") class BadComponent(BaseComponent): def __init__(self): print("BadComponent __init__()") super().__init__() # <--- RuntimeError occurs because of this 
+6
source share
1 answer

maybe this works:

 #!/usr/bin/env python3 class AutoRegisteredMeta(type): def __new__(metacls, name, bases, attrs): new_class = super().__new__(metacls, name, bases, attrs) new_class() return new_class class BaseComponent(metaclass=AutoRegisteredMeta): def __init__(self): print("BaseComponent __init__()") class GoodComponent(BaseComponent): def __init__(self): print("GoodComponent __init__()") class BadComponent(BaseComponent): def __init__(self): print("BadComponent __init__()") super(self.__class__, self).__init__() 
+3
source

Source: https://habr.com/ru/post/989610/


All Articles