55from typing import Any , Callable , Type
66
77import typing_inspect
8- from typing_extensions import Self , get_args , get_origin
8+ from typing_extensions import Annotated , Self , get_args , get_origin , get_type_hints
99
1010from dataclass_settings .loaders import Loader
1111
@@ -25,6 +25,7 @@ def detect(cls: type) -> bool:
2525class ClassTypes (Enum ):
2626 dataclass = "dataclass"
2727 pydantic = "pydantic"
28+ pydantic_v1 = "pydantic_v1"
2829 pydantic_dataclass = "pydantic_dataclass"
2930 attrs = "attrs"
3031
@@ -37,16 +38,20 @@ def from_cls(cls, obj: type) -> ClassTypes:
3738 return cls .dataclass
3839
3940 try :
40- from pydantic import BaseModel
41+ import pydantic
4142 except ImportError : # pragma: no cover
4243 pass
4344 else :
4445 try :
45- is_base_model = issubclass (obj , BaseModel )
46+ is_base_model = isinstance (obj , type ) and issubclass (
47+ obj , pydantic .BaseModel
48+ )
4649 except TypeError :
4750 is_base_model = False
4851
4952 if is_base_model :
53+ if pydantic .__version__ .startswith ("1." ):
54+ return cls .pydantic_v1
5055 return cls .pydantic
5156
5257 if hasattr (obj , "__attrs_attrs__" ):
@@ -69,11 +74,17 @@ class Field:
6974 def from_dataclass (cls , typ : Type ) -> list [Self ]:
7075 fields = []
7176 for f in typ .__dataclass_fields__ .values ():
77+ type_ = get_origin (f .type ) or f .type
78+ args = get_args (f .type ) or ()
79+ if type_ is Annotated :
80+ type_ , * _args = args
81+ args = tuple (_args )
82+
7283 field = cls (
7384 name = f .name ,
74- type = get_origin ( f . type ) or f . type ,
75- annotations = get_args ( f . type ) or () ,
76- mapper = f . type ,
85+ type = type_ ,
86+ annotations = args ,
87+ mapper = type_ ,
7788 )
7889 fields .append (field )
7990 return fields
@@ -94,6 +105,23 @@ def from_pydantic(cls, typ: Type) -> list[Self]:
94105 fields .append (field )
95106 return fields
96107
108+ @classmethod
109+ def from_pydantic_v1 (cls , typ : Type ) -> list [Self ]:
110+ fields = []
111+ type_hints = get_type_hints (typ , include_extras = True )
112+ for name , f in typ .__fields__ .items ():
113+ annotation = get_type (type_hints [name ])
114+ mapper = annotation if detect (annotation ) else None
115+
116+ field = cls (
117+ name = name ,
118+ type = f .annotation ,
119+ annotations = get_args (annotation ) or (),
120+ mapper = mapper ,
121+ )
122+ fields .append (field )
123+ return fields
124+
97125 @classmethod
98126 def from_pydantic_dataclass (cls , typ : Type ) -> list [Self ]:
99127 fields = []
@@ -167,6 +195,9 @@ def fields(cls: type):
167195 if class_type == ClassTypes .pydantic :
168196 return Field .from_pydantic (cls )
169197
198+ if class_type == ClassTypes .pydantic_v1 :
199+ return Field .from_pydantic_v1 (cls )
200+
170201 if class_type == ClassTypes .pydantic_dataclass :
171202 return Field .from_pydantic_dataclass (cls )
172203
0 commit comments