Search code examples
pythonpython-typing

Type annotations for dynamically created subclasses


I want to dynamically create child classes at startup with the type() function. Everything works as expected. I know this isn't great, but I am bound to a framework and have to do it this way. The other option is to generate source code...

Functional equivalent to my code:

class BaseEntity:
    id: str


def make_new_entity(name: str, attrs: dict) -> type:
    return type('RuntimeEntity', (BaseEntity,), attrs)


RuntimeEntity: ??? = make_new_entity('RuntimeEntity', {'id': 'entity.RuntimeEntity'})

Is there a way to provide a bound to the returned type? Basically the equivalent of

E = TypeVar('E', bound='BaseEntity')

I have also looked at the types module.

Thanks for any help!


Solution

  • typing.Type lets you specify that the value should be an actual type, rather than an instance of that type.

    from typing import Type
    
    class BaseEntity:
        id: str
    
    
    def make_new_entity(name: str, attrs: dict) -> Type[BaseEntity]:
        return type('RuntimeEntity', (BaseEntity,), attrs)
    
    
    RuntimeEntity: Type[BaseEntity] = make_new_entity('RuntimeEntity', {'id':     'entity.RuntimeEntity'})
    

    A value of type Type[BaseEntity] can be BaseEntity itself, or any class that inherits from BaseEntity. (The term to describe this is covariance. If Type were invariant, Type[BaseEntity] would accept BaseEntity itself only.)