Python (pydantic) сравнение аннотаций

Возможно ли сравнить аннотации на вхождение между собой? В примере используется pydantic, однако его использование, в целом, не обязательно

from pydantic import BaseModel
from typing import Union

class Test1(BaseModel):
    simple: list[str]
    hard: Union[list[str], list[int], None] = None     

class Test2(BaseModel):
    simple: list[str]
    hard: list[int]

m_f_1 = Test1.model_fields
m_f_2 = Test2.model_fields

print(m_f_1['simple'].annotation == m_f_2['simple'].annotation)
print(m_f_1['hard'].annotation == m_f_2['hard'].annotation)

dct = {'simple':['stroka'], 'hard':[1]}

t1 = Test1(**dct)
t2 = Test2(**dct)

Поле hard в объекте Test1 принимает более широкий спектр объектов, но при этом всё что подходит для поля в объекте Test2 будет подходить и для поля в объекте Test1. Нужно сравнить эти поля на то, входит ли аннотация одного поля в аннотацию другого. Сравнение напрямую == работает корректно для абсолютно одинаковых аннотаций (что логично).

Думал про вариант сгенерировать левый объект, но вероятно, есть чуть более простой и корректный вариант сравнить аннотации.


Ответы (1 шт):

Автор решения: iglebov

Если преобразовать аннотацию с Union в строку:

str(m_f_1['hard'].annotation)

То получится следующее:

'typing.Union[list[str], list[int], NoneType]'

А если преобразовать аннотацию GenericAlias

m_f_2['hard'].annotation

То получается следующий вывод:

'list[int]'

Таким образом, можно проверить вхождение типа данных в аннотацию при помощи in.

У меня получился такой код:

from types import GenericAlias

a = m_f_1['hard'].annotation
b = m_f_2['hard'].annotation

if isinstance(a, GenericAlias) and isinstance(b, GenericAlias):
    print(a == b)
elif isinstance(a, GenericAlias):
    print(str(a) in str(b))
elif isinstance(b, GenericAlias):
    print(str(b) in str(a))

Вывод:

True
→ Ссылка