Let’s start from an example (simple and academic):
from typing import ClassVar, TypeVar, Generic, Any, Type class Options: pass class Foo: Opts: ClassVar[Options] FooType = TypeVar('FooType', bound=Foo) class GenericModel(Generic[FooType]): opts: FooType.Opts # <-- not working def configure(self, foo: Type[FooType]): self.opts = foo.Opts def another_use_case(self, opts: FooType.Opts): # <-- not working # an argument is something from FooType pass # usage class FooBar(Foo): class Opts(Options): optA: Any wrap = Wrapper[FooBar]() wrap.configure(FooBar)
Is it possible to annotate the type of
Python complains that TypeVar has not attribute Opts. I found that when TypeVar is bounded, the bound is stored in
__bound__ but it looks like there is no overloaded getattr on
TypeVar class to access attributes from the bound type.
Do I made a mistake somewhere or such cases are not supported by Python typing at all? Is there any workaround for this? I can imagine more cases when access to
TypeVar bounded type attributes types might be useful in generic class typing.
Real use case for this is much more complex and depends on Pydantic.
GenericModel is a Pydantic model which I’m trying to make generic as I have a set of very similar models which differs mostly on types, so instead of having
BarModel and so on, I want to make one
GenericModel class and concretize them by writing
foo_model = GenericModel[Foo](),
bar_model = GenericModel[Bar]().
In Pydantic to validate
opts automatically, it must be correctly type annotated. Also with such type hinting, someone else exactly knows what
opts should be.
The only workaround I found as far is typing
Any and making a validation in custom validator, however it kind a magic and makes code very error prone as it’s not clear that
opts is not in fact an
Any. The next disadvantage is that this model is used as payload in
FastAPI so I’ve lost all type schema in generated OpenAPI spec.
Source: Python-3x Questions