Как использовать атрибуты ограниченного типа TypeVar в намеках на тип универсального класса

#python-3.x #python-typing #pydantic

Вопрос:

Давайте начнем с примера (простого и академичного).:

 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)

 

Можно ли аннотировать тип opts ?

Python жалуется, что TypeVar у него нет атрибута Opts . Я обнаружил, что при TypeVar ограничении привязка сохраняется, __bound__ но похоже, что getattr класс не перегружен TypeVar для доступа к атрибутам из связанного типа.

Я где-то ошибся или такие случаи вообще не поддерживаются набором текста на Python? Есть ли какое-либо обходное решение для этого? Я могу представить себе больше случаев, когда доступ к TypeVar типам атрибутов ограниченного типа может быть полезен при типизации общих классов.

Реальный вариант использования для этого гораздо сложнее и зависит от Pydantic . GenericModel это Pydantic модель, которую я пытаюсь сделать универсальной , поскольку у меня есть набор очень похожих моделей, которые отличаются в основном по типам, поэтому вместо того, чтобы иметь FooModel BarModel и так далее, Я хочу создать один GenericModel класс и конкретизировать их, написав foo_model = GenericModel[Foo]() , bar_model = GenericModel[Bar]() . Для Pydantic opts автоматической проверки он должен быть правильно набран с аннотациями. Также с таким типом намеков, кто-то другой точно знает, что opts должно быть.

Единственный обходной путь, который я нашел, — это ввести opts as Any и выполнить проверку в пользовательском валидаторе, однако это своего рода волшебство и делает код очень подверженным ошибкам, поскольку неясно, что opts на самом деле это не так Any . Следующий недостаток заключается в том, что эта модель используется в качестве полезной нагрузки, FastAPI поэтому я потерял всю схему типов в сгенерированной OpenAPI спецификации.