Type gets erased in generic loader classmethod #1433
-
|
Hello all, trying to figure out I can make a generic loader function for some Pydantic models. For some reason this code: from pydantic import BaseModel
from pydantic.generics import GenericModel
from typing import TypeVar, Generic, get_args, get_origin
TIM = TypeVar("TIM", bound=BaseModel)
class TemplateTestCase(GenericModel, Generic[TIM]):
input: TIM
class SomeModel(BaseModel):
age: int
class GenericTestCaseLoader(Generic[TIM]):
@classmethod
def load_test_case(cls: type["GenericTestCaseLoader[TIM]"], data: dict) -> TemplateTestCase[TIM]:
print(get_args(cls))
print(get_origin(cls))
print(get_origin(cls))
print(cls.__orig_bases__)
return TemplateTestCase[TIM].parse_obj(data)
def test_generic_model() -> None:
test_case = TemplateTestCase(
input=SomeModel(age=33),
)
root_data = test_case.dict()
template_test_case_2 = GenericTestCaseLoader[SomeModel].load_test_case(root_data)
print(template_test_case_2)
if __name__ == "__main__":
test_generic_model()Prints: As if that SomeModel gets completely erased and it falls back to the BaseModel that the TypeVar is bound to. What am I doing wrong? I'm just trying to build something that can serialize a model, and then deserialize into the specified model. Thanks for the help! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
|
IIRC the type you get within an instance is not quite the same as the one you get from specifying the type parameters on a generic, since calling Why not just pass in the type as an additional parameter? It seems more readable to me anyways i.e.: class GenericTestCaseLoader:
@classmethod
def load_test_case(cls, model: type[TIM], data: dict) -> TemplateTestCase[TIM]:
return TemplateTestCase[TIM].parse_obj(data)
GenericTestCaseLoader.load_test_case(SomeModel, root_data)If you absolutely must have it work the way you wrote it, you could accomplish it by overwriting |
Beta Was this translation helpful? Give feedback.
IIRC the type you get within an instance is not quite the same as the one you get from specifying the type parameters on a generic, since calling
__getitem__on a generic gives you a_GenericAliasback, which behaves like the original type for many use cases, since the original class gets inserted into its mro, but is not the actual type.get_originandget_argsonly return something on a_GenericAliasand not the unbound generic type.__orig_bases__looks correct to me. So I don't thinkSomeModelgets erased.Why not just pass in the type as an additional parameter? It seems more readable to me anyways i.e.: