1212_T = TypeVar ("_T" )
1313_ModelT = TypeVar ("_ModelT" , bound = pydantic .BaseModel )
1414
15- # --------------- Pydantic v2 compatibility ---------------
15+ # --------------- Pydantic v2, v3 compatibility ---------------
1616
1717# Pyright incorrectly reports some of our functions as overriding a method when they don't
1818# pyright: reportIncompatibleMethodOverride=false
1919
20- PYDANTIC_V2 = pydantic .VERSION .startswith ("2 ." )
20+ PYDANTIC_V1 = pydantic .VERSION .startswith ("1 ." )
2121
22- # v1 re-exports
2322if TYPE_CHECKING :
2423
2524 def parse_date (value : date | StrBytesIntFloat ) -> date : # noqa: ARG001
@@ -44,90 +43,92 @@ def is_typeddict(type_: type[Any]) -> bool: # noqa: ARG001
4443 ...
4544
4645else :
47- if PYDANTIC_V2 :
48- from pydantic .v1 .typing import (
46+ # v1 re-exports
47+ if PYDANTIC_V1 :
48+ from pydantic .typing import (
4949 get_args as get_args ,
5050 is_union as is_union ,
5151 get_origin as get_origin ,
5252 is_typeddict as is_typeddict ,
5353 is_literal_type as is_literal_type ,
5454 )
55- from pydantic .v1 . datetime_parse import parse_date as parse_date , parse_datetime as parse_datetime
55+ from pydantic .datetime_parse import parse_date as parse_date , parse_datetime as parse_datetime
5656 else :
57- from pydantic . typing import (
57+ from . _utils import (
5858 get_args as get_args ,
5959 is_union as is_union ,
6060 get_origin as get_origin ,
61+ parse_date as parse_date ,
6162 is_typeddict as is_typeddict ,
63+ parse_datetime as parse_datetime ,
6264 is_literal_type as is_literal_type ,
6365 )
64- from pydantic .datetime_parse import parse_date as parse_date , parse_datetime as parse_datetime
6566
6667
6768# refactored config
6869if TYPE_CHECKING :
6970 from pydantic import ConfigDict as ConfigDict
7071else :
71- if PYDANTIC_V2 :
72- from pydantic import ConfigDict
73- else :
72+ if PYDANTIC_V1 :
7473 # TODO: provide an error message here?
7574 ConfigDict = None
75+ else :
76+ from pydantic import ConfigDict as ConfigDict
7677
7778
7879# renamed methods / properties
7980def parse_obj (model : type [_ModelT ], value : object ) -> _ModelT :
80- if PYDANTIC_V2 :
81- return model .model_validate (value )
82- else :
81+ if PYDANTIC_V1 :
8382 return cast (_ModelT , model .parse_obj (value )) # pyright: ignore[reportDeprecated, reportUnnecessaryCast]
83+ else :
84+ return model .model_validate (value )
8485
8586
8687def field_is_required (field : FieldInfo ) -> bool :
87- if PYDANTIC_V2 :
88- return field .is_required ()
89- return field .required # type: ignore
88+ if PYDANTIC_V1 :
89+ return field .required # type: ignore
90+ return field .is_required ()
9091
9192
9293def field_get_default (field : FieldInfo ) -> Any :
9394 value = field .get_default ()
94- if PYDANTIC_V2 :
95- from pydantic_core import PydanticUndefined
96-
97- if value == PydanticUndefined :
98- return None
95+ if PYDANTIC_V1 :
9996 return value
97+ from pydantic_core import PydanticUndefined
98+
99+ if value == PydanticUndefined :
100+ return None
100101 return value
101102
102103
103104def field_outer_type (field : FieldInfo ) -> Any :
104- if PYDANTIC_V2 :
105- return field .annotation
106- return field .outer_type_ # type: ignore
105+ if PYDANTIC_V1 :
106+ return field .outer_type_ # type: ignore
107+ return field .annotation
107108
108109
109110def get_model_config (model : type [pydantic .BaseModel ]) -> Any :
110- if PYDANTIC_V2 :
111- return model .model_config
112- return model .__config__ # type: ignore
111+ if PYDANTIC_V1 :
112+ return model .__config__ # type: ignore
113+ return model .model_config
113114
114115
115116def get_model_fields (model : type [pydantic .BaseModel ]) -> dict [str , FieldInfo ]:
116- if PYDANTIC_V2 :
117- return model .model_fields
118- return model .__fields__ # type: ignore
117+ if PYDANTIC_V1 :
118+ return model .__fields__ # type: ignore
119+ return model .model_fields
119120
120121
121122def model_copy (model : _ModelT , * , deep : bool = False ) -> _ModelT :
122- if PYDANTIC_V2 :
123- return model .model_copy (deep = deep )
124- return model .copy (deep = deep ) # type: ignore
123+ if PYDANTIC_V1 :
124+ return model .copy (deep = deep ) # type: ignore
125+ return model .model_copy (deep = deep )
125126
126127
127128def model_json (model : pydantic .BaseModel , * , indent : int | None = None ) -> str :
128- if PYDANTIC_V2 :
129- return model .model_dump_json (indent = indent )
130- return model .json (indent = indent ) # type: ignore
129+ if PYDANTIC_V1 :
130+ return model .json (indent = indent ) # type: ignore
131+ return model .model_dump_json (indent = indent )
131132
132133
133134def model_dump (
@@ -139,14 +140,14 @@ def model_dump(
139140 warnings : bool = True ,
140141 mode : Literal ["json" , "python" ] = "python" ,
141142) -> dict [str , Any ]:
142- if PYDANTIC_V2 or hasattr (model , "model_dump" ):
143+ if ( not PYDANTIC_V1 ) or hasattr (model , "model_dump" ):
143144 return model .model_dump (
144145 mode = mode ,
145146 exclude = exclude ,
146147 exclude_unset = exclude_unset ,
147148 exclude_defaults = exclude_defaults ,
148149 # warnings are not supported in Pydantic v1
149- warnings = warnings if PYDANTIC_V2 else True ,
150+ warnings = True if PYDANTIC_V1 else warnings ,
150151 )
151152 return cast (
152153 "dict[str, Any]" ,
@@ -159,9 +160,9 @@ def model_dump(
159160
160161
161162def model_parse (model : type [_ModelT ], data : Any ) -> _ModelT :
162- if PYDANTIC_V2 :
163- return model .model_validate (data )
164- return model .parse_obj (data ) # pyright: ignore[reportDeprecated]
163+ if PYDANTIC_V1 :
164+ return model .parse_obj (data ) # pyright: ignore[reportDeprecated]
165+ return model .model_validate (data )
165166
166167
167168# generic models
@@ -170,17 +171,16 @@ def model_parse(model: type[_ModelT], data: Any) -> _ModelT:
170171 class GenericModel (pydantic .BaseModel ): ...
171172
172173else :
173- if PYDANTIC_V2 :
174+ if PYDANTIC_V1 :
175+ import pydantic .generics
176+
177+ class GenericModel (pydantic .generics .GenericModel , pydantic .BaseModel ): ...
178+ else :
174179 # there no longer needs to be a distinction in v2 but
175180 # we still have to create our own subclass to avoid
176181 # inconsistent MRO ordering errors
177182 class GenericModel (pydantic .BaseModel ): ...
178183
179- else :
180- import pydantic .generics
181-
182- class GenericModel (pydantic .generics .GenericModel , pydantic .BaseModel ): ...
183-
184184
185185# cached properties
186186if TYPE_CHECKING :
0 commit comments