1import sys
2from typing import Any, Callable
3
4from pydantic.warnings import PydanticDeprecatedSince20
5
6from .version import version_short
7
8MOVED_IN_V2 = {
9 'pydantic.utils:version_info': 'pydantic.version:version_info',
10 'pydantic.error_wrappers:ValidationError': 'pydantic:ValidationError',
11 'pydantic.utils:to_camel': 'pydantic.alias_generators:to_pascal',
12 'pydantic.utils:to_lower_camel': 'pydantic.alias_generators:to_camel',
13 'pydantic:PyObject': 'pydantic.types:ImportString',
14 'pydantic.types:PyObject': 'pydantic.types:ImportString',
15 'pydantic.generics:GenericModel': 'pydantic.BaseModel',
16}
17
18DEPRECATED_MOVED_IN_V2 = {
19 'pydantic.tools:schema_of': 'pydantic.deprecated.tools:schema_of',
20 'pydantic.tools:parse_obj_as': 'pydantic.deprecated.tools:parse_obj_as',
21 'pydantic.tools:schema_json_of': 'pydantic.deprecated.tools:schema_json_of',
22 'pydantic.json:pydantic_encoder': 'pydantic.deprecated.json:pydantic_encoder',
23 'pydantic:validate_arguments': 'pydantic.deprecated.decorator:validate_arguments',
24 'pydantic.json:custom_pydantic_encoder': 'pydantic.deprecated.json:custom_pydantic_encoder',
25 'pydantic.json:timedelta_isoformat': 'pydantic.deprecated.json:timedelta_isoformat',
26 'pydantic.decorator:validate_arguments': 'pydantic.deprecated.decorator:validate_arguments',
27 'pydantic.class_validators:validator': 'pydantic.deprecated.class_validators:validator',
28 'pydantic.class_validators:root_validator': 'pydantic.deprecated.class_validators:root_validator',
29 'pydantic.config:BaseConfig': 'pydantic.deprecated.config:BaseConfig',
30 'pydantic.config:Extra': 'pydantic.deprecated.config:Extra',
31}
32
33REDIRECT_TO_V1 = {
34 f'pydantic.utils:{obj}': f'pydantic.v1.utils:{obj}'
35 for obj in (
36 'deep_update',
37 'GetterDict',
38 'lenient_issubclass',
39 'lenient_isinstance',
40 'is_valid_field',
41 'update_not_none',
42 'import_string',
43 'Representation',
44 'ROOT_KEY',
45 'smart_deepcopy',
46 'sequence_like',
47 )
48}
49
50
51REMOVED_IN_V2 = {
52 'pydantic:ConstrainedBytes',
53 'pydantic:ConstrainedDate',
54 'pydantic:ConstrainedDecimal',
55 'pydantic:ConstrainedFloat',
56 'pydantic:ConstrainedFrozenSet',
57 'pydantic:ConstrainedInt',
58 'pydantic:ConstrainedList',
59 'pydantic:ConstrainedSet',
60 'pydantic:ConstrainedStr',
61 'pydantic:JsonWrapper',
62 'pydantic:NoneBytes',
63 'pydantic:NoneStr',
64 'pydantic:NoneStrBytes',
65 'pydantic:Protocol',
66 'pydantic:Required',
67 'pydantic:StrBytes',
68 'pydantic:compiled',
69 'pydantic.config:get_config',
70 'pydantic.config:inherit_config',
71 'pydantic.config:prepare_config',
72 'pydantic:create_model_from_namedtuple',
73 'pydantic:create_model_from_typeddict',
74 'pydantic.dataclasses:create_pydantic_model_from_dataclass',
75 'pydantic.dataclasses:make_dataclass_validator',
76 'pydantic.dataclasses:set_validation',
77 'pydantic.datetime_parse:parse_date',
78 'pydantic.datetime_parse:parse_time',
79 'pydantic.datetime_parse:parse_datetime',
80 'pydantic.datetime_parse:parse_duration',
81 'pydantic.error_wrappers:ErrorWrapper',
82 'pydantic.errors:AnyStrMaxLengthError',
83 'pydantic.errors:AnyStrMinLengthError',
84 'pydantic.errors:ArbitraryTypeError',
85 'pydantic.errors:BoolError',
86 'pydantic.errors:BytesError',
87 'pydantic.errors:CallableError',
88 'pydantic.errors:ClassError',
89 'pydantic.errors:ColorError',
90 'pydantic.errors:ConfigError',
91 'pydantic.errors:DataclassTypeError',
92 'pydantic.errors:DateError',
93 'pydantic.errors:DateNotInTheFutureError',
94 'pydantic.errors:DateNotInThePastError',
95 'pydantic.errors:DateTimeError',
96 'pydantic.errors:DecimalError',
97 'pydantic.errors:DecimalIsNotFiniteError',
98 'pydantic.errors:DecimalMaxDigitsError',
99 'pydantic.errors:DecimalMaxPlacesError',
100 'pydantic.errors:DecimalWholeDigitsError',
101 'pydantic.errors:DictError',
102 'pydantic.errors:DurationError',
103 'pydantic.errors:EmailError',
104 'pydantic.errors:EnumError',
105 'pydantic.errors:EnumMemberError',
106 'pydantic.errors:ExtraError',
107 'pydantic.errors:FloatError',
108 'pydantic.errors:FrozenSetError',
109 'pydantic.errors:FrozenSetMaxLengthError',
110 'pydantic.errors:FrozenSetMinLengthError',
111 'pydantic.errors:HashableError',
112 'pydantic.errors:IPv4AddressError',
113 'pydantic.errors:IPv4InterfaceError',
114 'pydantic.errors:IPv4NetworkError',
115 'pydantic.errors:IPv6AddressError',
116 'pydantic.errors:IPv6InterfaceError',
117 'pydantic.errors:IPv6NetworkError',
118 'pydantic.errors:IPvAnyAddressError',
119 'pydantic.errors:IPvAnyInterfaceError',
120 'pydantic.errors:IPvAnyNetworkError',
121 'pydantic.errors:IntEnumError',
122 'pydantic.errors:IntegerError',
123 'pydantic.errors:InvalidByteSize',
124 'pydantic.errors:InvalidByteSizeUnit',
125 'pydantic.errors:InvalidDiscriminator',
126 'pydantic.errors:InvalidLengthForBrand',
127 'pydantic.errors:JsonError',
128 'pydantic.errors:JsonTypeError',
129 'pydantic.errors:ListError',
130 'pydantic.errors:ListMaxLengthError',
131 'pydantic.errors:ListMinLengthError',
132 'pydantic.errors:ListUniqueItemsError',
133 'pydantic.errors:LuhnValidationError',
134 'pydantic.errors:MissingDiscriminator',
135 'pydantic.errors:MissingError',
136 'pydantic.errors:NoneIsAllowedError',
137 'pydantic.errors:NoneIsNotAllowedError',
138 'pydantic.errors:NotDigitError',
139 'pydantic.errors:NotNoneError',
140 'pydantic.errors:NumberNotGeError',
141 'pydantic.errors:NumberNotGtError',
142 'pydantic.errors:NumberNotLeError',
143 'pydantic.errors:NumberNotLtError',
144 'pydantic.errors:NumberNotMultipleError',
145 'pydantic.errors:PathError',
146 'pydantic.errors:PathNotADirectoryError',
147 'pydantic.errors:PathNotAFileError',
148 'pydantic.errors:PathNotExistsError',
149 'pydantic.errors:PatternError',
150 'pydantic.errors:PyObjectError',
151 'pydantic.errors:PydanticTypeError',
152 'pydantic.errors:PydanticValueError',
153 'pydantic.errors:SequenceError',
154 'pydantic.errors:SetError',
155 'pydantic.errors:SetMaxLengthError',
156 'pydantic.errors:SetMinLengthError',
157 'pydantic.errors:StrError',
158 'pydantic.errors:StrRegexError',
159 'pydantic.errors:StrictBoolError',
160 'pydantic.errors:SubclassError',
161 'pydantic.errors:TimeError',
162 'pydantic.errors:TupleError',
163 'pydantic.errors:TupleLengthError',
164 'pydantic.errors:UUIDError',
165 'pydantic.errors:UUIDVersionError',
166 'pydantic.errors:UrlError',
167 'pydantic.errors:UrlExtraError',
168 'pydantic.errors:UrlHostError',
169 'pydantic.errors:UrlHostTldError',
170 'pydantic.errors:UrlPortError',
171 'pydantic.errors:UrlSchemeError',
172 'pydantic.errors:UrlSchemePermittedError',
173 'pydantic.errors:UrlUserInfoError',
174 'pydantic.errors:WrongConstantError',
175 'pydantic.main:validate_model',
176 'pydantic.networks:stricturl',
177 'pydantic:parse_file_as',
178 'pydantic:parse_raw_as',
179 'pydantic:stricturl',
180 'pydantic.tools:parse_file_as',
181 'pydantic.tools:parse_raw_as',
182 'pydantic.types:ConstrainedBytes',
183 'pydantic.types:ConstrainedDate',
184 'pydantic.types:ConstrainedDecimal',
185 'pydantic.types:ConstrainedFloat',
186 'pydantic.types:ConstrainedFrozenSet',
187 'pydantic.types:ConstrainedInt',
188 'pydantic.types:ConstrainedList',
189 'pydantic.types:ConstrainedSet',
190 'pydantic.types:ConstrainedStr',
191 'pydantic.types:JsonWrapper',
192 'pydantic.types:NoneBytes',
193 'pydantic.types:NoneStr',
194 'pydantic.types:NoneStrBytes',
195 'pydantic.types:StrBytes',
196 'pydantic.typing:evaluate_forwardref',
197 'pydantic.typing:AbstractSetIntStr',
198 'pydantic.typing:AnyCallable',
199 'pydantic.typing:AnyClassMethod',
200 'pydantic.typing:CallableGenerator',
201 'pydantic.typing:DictAny',
202 'pydantic.typing:DictIntStrAny',
203 'pydantic.typing:DictStrAny',
204 'pydantic.typing:IntStr',
205 'pydantic.typing:ListStr',
206 'pydantic.typing:MappingIntStrAny',
207 'pydantic.typing:NoArgAnyCallable',
208 'pydantic.typing:NoneType',
209 'pydantic.typing:ReprArgs',
210 'pydantic.typing:SetStr',
211 'pydantic.typing:StrPath',
212 'pydantic.typing:TupleGenerator',
213 'pydantic.typing:WithArgsTypes',
214 'pydantic.typing:all_literal_values',
215 'pydantic.typing:display_as_type',
216 'pydantic.typing:get_all_type_hints',
217 'pydantic.typing:get_args',
218 'pydantic.typing:get_origin',
219 'pydantic.typing:get_sub_types',
220 'pydantic.typing:is_callable_type',
221 'pydantic.typing:is_classvar',
222 'pydantic.typing:is_finalvar',
223 'pydantic.typing:is_literal_type',
224 'pydantic.typing:is_namedtuple',
225 'pydantic.typing:is_new_type',
226 'pydantic.typing:is_none_type',
227 'pydantic.typing:is_typeddict',
228 'pydantic.typing:is_typeddict_special',
229 'pydantic.typing:is_union',
230 'pydantic.typing:new_type_supertype',
231 'pydantic.typing:resolve_annotations',
232 'pydantic.typing:typing_base',
233 'pydantic.typing:update_field_forward_refs',
234 'pydantic.typing:update_model_forward_refs',
235 'pydantic.utils:ClassAttribute',
236 'pydantic.utils:DUNDER_ATTRIBUTES',
237 'pydantic.utils:PyObjectStr',
238 'pydantic.utils:ValueItems',
239 'pydantic.utils:almost_equal_floats',
240 'pydantic.utils:get_discriminator_alias_and_values',
241 'pydantic.utils:get_model',
242 'pydantic.utils:get_unique_discriminator_alias',
243 'pydantic.utils:in_ipython',
244 'pydantic.utils:is_valid_identifier',
245 'pydantic.utils:path_type',
246 'pydantic.utils:validate_field_name',
247 'pydantic:validate_model',
248}
249
250
251def getattr_migration(module: str) -> Callable[[str], Any]:
252 """Implement PEP 562 for objects that were either moved or removed on the migration
253 to V2.
254
255 Args:
256 module: The module name.
257
258 Returns:
259 A callable that will raise an error if the object is not found.
260 """
261 # This avoids circular import with errors.py.
262 from .errors import PydanticImportError
263
264 def wrapper(name: str) -> object:
265 """Raise an error if the object is not found, or warn if it was moved.
266
267 In case it was moved, it still returns the object.
268
269 Args:
270 name: The object name.
271
272 Returns:
273 The object.
274 """
275 if name == '__path__':
276 raise AttributeError(f'module {module!r} has no attribute {name!r}')
277
278 import warnings
279
280 from ._internal._validators import import_string
281
282 import_path = f'{module}:{name}'
283 if import_path in MOVED_IN_V2.keys():
284 new_location = MOVED_IN_V2[import_path]
285 warnings.warn(
286 f'`{import_path}` has been moved to `{new_location}`.',
287 category=PydanticDeprecatedSince20,
288 stacklevel=2,
289 )
290 return import_string(MOVED_IN_V2[import_path])
291 if import_path in DEPRECATED_MOVED_IN_V2:
292 # skip the warning here because a deprecation warning will be raised elsewhere
293 return import_string(DEPRECATED_MOVED_IN_V2[import_path])
294 if import_path in REDIRECT_TO_V1:
295 new_location = REDIRECT_TO_V1[import_path]
296 warnings.warn(
297 f'`{import_path}` has been removed. We are importing from `{new_location}` instead.'
298 'See the migration guide for more details: https://docs.pydantic.dev/latest/migration/',
299 category=PydanticDeprecatedSince20,
300 stacklevel=2,
301 )
302 return import_string(REDIRECT_TO_V1[import_path])
303 if import_path == 'pydantic:BaseSettings':
304 raise PydanticImportError(
305 '`BaseSettings` has been moved to the `pydantic-settings` package. '
306 f'See https://docs.pydantic.dev/{version_short()}/migration/#basesettings-has-moved-to-pydantic-settings '
307 'for more details.'
308 )
309 if import_path in REMOVED_IN_V2:
310 raise PydanticImportError(f'`{import_path}` has been removed in V2.')
311 globals: dict[str, Any] = sys.modules[module].__dict__
312 if name in globals:
313 return globals[name]
314 raise AttributeError(f'module {module!r} has no attribute {name!r}')
315
316 return wrapper