1import json
2import sys
3import warnings
4from abc import ABCMeta
5from copy import deepcopy
6from enum import Enum
7from functools import partial
8from pathlib import Path
9from types import FunctionType
10from typing import (
11    TYPE_CHECKING,
12    AbstractSet,
13    Any,
14    Callable,
15    Dict,
16    List,
17    Mapping,
18    Optional,
19    Tuple,
20    Type,
21    TypeVar,
22    Union,
23    cast,
24    no_type_check,
25    overload,
26)
27
28from .class_validators import ValidatorGroup, extract_root_validators, extract_validators, inherit_validators
29from .error_wrappers import ErrorWrapper, ValidationError
30from .errors import ConfigError, DictError, ExtraError, MissingError
31from .fields import MAPPING_LIKE_SHAPES, ModelField, ModelPrivateAttr, PrivateAttr, Undefined
32from .json import custom_pydantic_encoder, pydantic_encoder
33from .parse import Protocol, load_file, load_str_bytes
34from .schema import default_ref_template, model_schema
35from .types import PyObject, StrBytes
36from .typing import (
37    AnyCallable,
38    get_args,
39    get_origin,
40    is_classvar,
41    is_namedtuple,
42    resolve_annotations,
43    update_field_forward_refs,
44)
45from .utils import (
46    ROOT_KEY,
47    ClassAttribute,
48    GetterDict,
49    Representation,
50    ValueItems,
51    generate_model_signature,
52    is_valid_field,
53    is_valid_private_name,
54    lenient_issubclass,
55    sequence_like,
56    smart_deepcopy,
57    unique_list,
58    validate_field_name,
59)
60
61if TYPE_CHECKING:
62    from inspect import Signature
63
64    import typing_extensions
65
66    from .class_validators import ValidatorListDict
67    from .types import ModelOrDc
68    from .typing import (  # noqa: F401
69        AbstractSetIntStr,
70        CallableGenerator,
71        DictAny,
72        DictStrAny,
73        MappingIntStrAny,
74        ReprArgs,
75        SetStr,
76        TupleGenerator,
77    )
78
79    ConfigType = Type['BaseConfig']
80    Model = TypeVar('Model', bound='BaseModel')
81
82    class SchemaExtraCallable(typing_extensions.Protocol):
83        @overload
84        def __call__(self, schema: Dict[str, Any]) -> None:
85            pass
86
87        @overload  # noqa: F811
88        def __call__(self, schema: Dict[str, Any], model_class: Type['Model']) -> None:  # noqa: F811
89            pass
90
91
92else:
93    SchemaExtraCallable = Callable[..., None]
94
95try:
96    import cython  # type: ignore
97except ImportError:
98    compiled: bool = False
99else:  # pragma: no cover
100    try:
101        compiled = cython.compiled
102    except AttributeError:
103        compiled = False
104
105__all__ = 'BaseConfig', 'BaseModel', 'Extra', 'compiled', 'create_model', 'validate_model'
106
107
108class Extra(str, Enum):
109    allow = 'allow'
110    ignore = 'ignore'
111    forbid = 'forbid'
112
113
114class BaseConfig:
115    title = None
116    anystr_lower = False
117    anystr_strip_whitespace = False
118    min_anystr_length = None
119    max_anystr_length = None
120    validate_all = False
121    extra = Extra.ignore
122    allow_mutation = True
123    frozen = False
124    allow_population_by_field_name = False
125    use_enum_values = False
126    fields: Dict[str, Union[str, Dict[str, str]]] = {}
127    validate_assignment = False
128    error_msg_templates: Dict[str, str] = {}
129    arbitrary_types_allowed = False
130    orm_mode: bool = False
131    getter_dict: Type[GetterDict] = GetterDict
132    alias_generator: Optional[Callable[[str], str]] = None
133    keep_untouched: Tuple[type, ...] = ()
134    schema_extra: Union[Dict[str, Any], 'SchemaExtraCallable'] = {}
135    json_loads: Callable[[str], Any] = json.loads
136    json_dumps: Callable[..., str] = json.dumps
137    json_encoders: Dict[Type[Any], AnyCallable] = {}
138    underscore_attrs_are_private: bool = False
139
140    # Whether or not inherited models as fields should be reconstructed as base model
141    copy_on_model_validation: bool = True
142
143    @classmethod
144    def get_field_info(cls, name: str) -> Dict[str, Any]:
145        """
146        Get properties of FieldInfo from the `fields` property of the config class.
147        """
148
149        fields_value = cls.fields.get(name)
150
151        if isinstance(fields_value, str):
152            field_info: Dict[str, Any] = {'alias': fields_value}
153        elif isinstance(fields_value, dict):
154            field_info = fields_value
155        else:
156            field_info = {}
157
158        if 'alias' in field_info:
159            field_info.setdefault('alias_priority', 2)
160
161        if field_info.get('alias_priority', 0) <= 1 and cls.alias_generator:
162            alias = cls.alias_generator(name)
163            if not isinstance(alias, str):
164                raise TypeError(f'Config.alias_generator must return str, not {alias.__class__}')
165            field_info.update(alias=alias, alias_priority=1)
166        return field_info
167
168    @classmethod
169    def prepare_field(cls, field: 'ModelField') -> None:
170        """
171        Optional hook to check or modify fields during model creation.
172        """
173        pass
174
175
176def inherit_config(self_config: 'ConfigType', parent_config: 'ConfigType', **namespace: Any) -> 'ConfigType':
177    if not self_config:
178        base_classes: Tuple['ConfigType', ...] = (parent_config,)
179    elif self_config == parent_config:
180        base_classes = (self_config,)
181    else:
182        base_classes = self_config, parent_config
183
184    namespace['json_encoders'] = {
185        **getattr(parent_config, 'json_encoders', {}),
186        **getattr(self_config, 'json_encoders', {}),
187        **namespace.get('json_encoders', {}),
188    }
189
190    return type('Config', base_classes, namespace)
191
192
193EXTRA_LINK = 'https://pydantic-docs.helpmanual.io/usage/model_config/'
194
195
196def prepare_config(config: Type[BaseConfig], cls_name: str) -> None:
197    if not isinstance(config.extra, Extra):
198        try:
199            config.extra = Extra(config.extra)
200        except ValueError:
201            raise ValueError(f'"{cls_name}": {config.extra} is not a valid value for "extra"')
202
203
204def validate_custom_root_type(fields: Dict[str, ModelField]) -> None:
205    if len(fields) > 1:
206        raise ValueError(f'{ROOT_KEY} cannot be mixed with other fields')
207
208
209def generate_hash_function(frozen: bool) -> Optional[Callable[[Any], int]]:
210    def hash_function(self_: Any) -> int:
211        return hash(self_.__class__) + hash(tuple(self_.__dict__.values()))
212
213    return hash_function if frozen else None
214
215
216# If a field is of type `Callable`, its default value should be a function and cannot to ignored.
217ANNOTATED_FIELD_UNTOUCHED_TYPES: Tuple[Any, ...] = (property, type, classmethod, staticmethod)
218# When creating a `BaseModel` instance, we bypass all the methods, properties... added to the model
219UNTOUCHED_TYPES: Tuple[Any, ...] = (FunctionType,) + ANNOTATED_FIELD_UNTOUCHED_TYPES
220# Note `ModelMetaclass` refers to `BaseModel`, but is also used to *create* `BaseModel`, so we need to add this extra
221# (somewhat hacky) boolean to keep track of whether we've created the `BaseModel` class yet, and therefore whether it's
222# safe to refer to it. If it *hasn't* been created, we assume that the `__new__` call we're in the middle of is for
223# the `BaseModel` class, since that's defined immediately after the metaclass.
224_is_base_model_class_defined = False
225
226
227class ModelMetaclass(ABCMeta):
228    @no_type_check  # noqa C901
229    def __new__(mcs, name, bases, namespace, **kwargs):  # noqa C901
230        fields: Dict[str, ModelField] = {}
231        config = BaseConfig
232        validators: 'ValidatorListDict' = {}
233
234        pre_root_validators, post_root_validators = [], []
235        private_attributes: Dict[str, ModelPrivateAttr] = {}
236        slots: SetStr = namespace.get('__slots__', ())
237        slots = {slots} if isinstance(slots, str) else set(slots)
238        class_vars: SetStr = set()
239        hash_func: Optional[Callable[[Any], int]] = None
240
241        for base in reversed(bases):
242            if _is_base_model_class_defined and issubclass(base, BaseModel) and base != BaseModel:
243                fields.update(smart_deepcopy(base.__fields__))
244                config = inherit_config(base.__config__, config)
245                validators = inherit_validators(base.__validators__, validators)
246                pre_root_validators += base.__pre_root_validators__
247                post_root_validators += base.__post_root_validators__
248                private_attributes.update(base.__private_attributes__)
249                class_vars.update(base.__class_vars__)
250                hash_func = base.__hash__
251
252        allowed_config_kwargs: SetStr = {
253            key
254            for key in dir(config)
255            if not (key.startswith('__') and key.endswith('__'))  # skip dunder methods and attributes
256        }
257        config_kwargs = {key: kwargs.pop(key) for key in kwargs.keys() & allowed_config_kwargs}
258        config_from_namespace = namespace.get('Config')
259        if config_kwargs and config_from_namespace:
260            raise TypeError('Specifying config in two places is ambiguous, use either Config attribute or class kwargs')
261        config = inherit_config(config_from_namespace, config, **config_kwargs)
262
263        validators = inherit_validators(extract_validators(namespace), validators)
264        vg = ValidatorGroup(validators)
265
266        for f in fields.values():
267            f.set_config(config)
268            extra_validators = vg.get_validators(f.name)
269            if extra_validators:
270                f.class_validators.update(extra_validators)
271                # re-run prepare to add extra validators
272                f.populate_validators()
273
274        prepare_config(config, name)
275
276        untouched_types = ANNOTATED_FIELD_UNTOUCHED_TYPES
277
278        def is_untouched(v: Any) -> bool:
279            return isinstance(v, untouched_types) or v.__class__.__name__ == 'cython_function_or_method'
280
281        if (namespace.get('__module__'), namespace.get('__qualname__')) != ('pydantic.main', 'BaseModel'):
282            annotations = resolve_annotations(namespace.get('__annotations__', {}), namespace.get('__module__', None))
283            # annotation only fields need to come first in fields
284            for ann_name, ann_type in annotations.items():
285                if is_classvar(ann_type):
286                    class_vars.add(ann_name)
287                elif is_valid_field(ann_name):
288                    validate_field_name(bases, ann_name)
289                    value = namespace.get(ann_name, Undefined)
290                    allowed_types = get_args(ann_type) if get_origin(ann_type) is Union else (ann_type,)
291                    if (
292                        is_untouched(value)
293                        and ann_type != PyObject
294                        and not any(
295                            lenient_issubclass(get_origin(allowed_type), Type) for allowed_type in allowed_types
296                        )
297                    ):
298                        continue
299                    fields[ann_name] = ModelField.infer(
300                        name=ann_name,
301                        value=value,
302                        annotation=ann_type,
303                        class_validators=vg.get_validators(ann_name),
304                        config=config,
305                    )
306                elif ann_name not in namespace and config.underscore_attrs_are_private:
307                    private_attributes[ann_name] = PrivateAttr()
308
309            untouched_types = UNTOUCHED_TYPES + config.keep_untouched
310            for var_name, value in namespace.items():
311                can_be_changed = var_name not in class_vars and not is_untouched(value)
312                if isinstance(value, ModelPrivateAttr):
313                    if not is_valid_private_name(var_name):
314                        raise NameError(
315                            f'Private attributes "{var_name}" must not be a valid field name; '
316                            f'Use sunder or dunder names, e. g. "_{var_name}" or "__{var_name}__"'
317                        )
318                    private_attributes[var_name] = value
319                elif config.underscore_attrs_are_private and is_valid_private_name(var_name) and can_be_changed:
320                    private_attributes[var_name] = PrivateAttr(default=value)
321                elif is_valid_field(var_name) and var_name not in annotations and can_be_changed:
322                    validate_field_name(bases, var_name)
323                    inferred = ModelField.infer(
324                        name=var_name,
325                        value=value,
326                        annotation=annotations.get(var_name, Undefined),
327                        class_validators=vg.get_validators(var_name),
328                        config=config,
329                    )
330                    if var_name in fields and inferred.type_ != fields[var_name].type_:
331                        raise TypeError(
332                            f'The type of {name}.{var_name} differs from the new default value; '
333                            f'if you wish to change the type of this field, please use a type annotation'
334                        )
335                    fields[var_name] = inferred
336
337        _custom_root_type = ROOT_KEY in fields
338        if _custom_root_type:
339            validate_custom_root_type(fields)
340        vg.check_for_unused()
341        if config.json_encoders:
342            json_encoder = partial(custom_pydantic_encoder, config.json_encoders)
343        else:
344            json_encoder = pydantic_encoder
345        pre_rv_new, post_rv_new = extract_root_validators(namespace)
346
347        if hash_func is None:
348            hash_func = generate_hash_function(config.frozen)
349
350        exclude_from_namespace = fields | private_attributes.keys() | {'__slots__'}
351        new_namespace = {
352            '__config__': config,
353            '__fields__': fields,
354            '__validators__': vg.validators,
355            '__pre_root_validators__': unique_list(pre_root_validators + pre_rv_new),
356            '__post_root_validators__': unique_list(post_root_validators + post_rv_new),
357            '__schema_cache__': {},
358            '__json_encoder__': staticmethod(json_encoder),
359            '__custom_root_type__': _custom_root_type,
360            '__private_attributes__': private_attributes,
361            '__slots__': slots | private_attributes.keys(),
362            '__hash__': hash_func,
363            '__class_vars__': class_vars,
364            **{n: v for n, v in namespace.items() if n not in exclude_from_namespace},
365        }
366
367        cls = super().__new__(mcs, name, bases, new_namespace, **kwargs)
368        # set __signature__ attr only for model class, but not for its instances
369        cls.__signature__ = ClassAttribute('__signature__', generate_model_signature(cls.__init__, fields, config))
370        return cls
371
372
373object_setattr = object.__setattr__
374
375
376class BaseModel(Representation, metaclass=ModelMetaclass):
377    if TYPE_CHECKING:
378        # populated by the metaclass, defined here to help IDEs only
379        __fields__: Dict[str, ModelField] = {}
380        __validators__: Dict[str, AnyCallable] = {}
381        __pre_root_validators__: List[AnyCallable]
382        __post_root_validators__: List[Tuple[bool, AnyCallable]]
383        __config__: Type[BaseConfig] = BaseConfig
384        __root__: Any = None
385        __json_encoder__: Callable[[Any], Any] = lambda x: x
386        __schema_cache__: 'DictAny' = {}
387        __custom_root_type__: bool = False
388        __signature__: 'Signature'
389        __private_attributes__: Dict[str, Any]
390        __class_vars__: SetStr
391        __fields_set__: SetStr = set()
392
393    Config = BaseConfig
394    __slots__ = ('__dict__', '__fields_set__')
395    __doc__ = ''  # Null out the Representation docstring
396
397    def __init__(__pydantic_self__, **data: Any) -> None:
398        """
399        Create a new model by parsing and validating input data from keyword arguments.
400
401        Raises ValidationError if the input data cannot be parsed to form a valid model.
402        """
403        # Uses something other than `self` the first arg to allow "self" as a settable attribute
404        values, fields_set, validation_error = validate_model(__pydantic_self__.__class__, data)
405        if validation_error:
406            raise validation_error
407        try:
408            object_setattr(__pydantic_self__, '__dict__', values)
409        except TypeError as e:
410            raise TypeError(
411                'Model values must be a dict; you may not have returned a dictionary from a root validator'
412            ) from e
413        object_setattr(__pydantic_self__, '__fields_set__', fields_set)
414        __pydantic_self__._init_private_attributes()
415
416    @no_type_check
417    def __setattr__(self, name, value):  # noqa: C901 (ignore complexity)
418        if name in self.__private_attributes__:
419            return object_setattr(self, name, value)
420
421        if self.__config__.extra is not Extra.allow and name not in self.__fields__:
422            raise ValueError(f'"{self.__class__.__name__}" object has no field "{name}"')
423        elif not self.__config__.allow_mutation or self.__config__.frozen:
424            raise TypeError(f'"{self.__class__.__name__}" is immutable and does not support item assignment')
425        elif self.__config__.validate_assignment:
426            new_values = {**self.__dict__, name: value}
427
428            for validator in self.__pre_root_validators__:
429                try:
430                    new_values = validator(self.__class__, new_values)
431                except (ValueError, TypeError, AssertionError) as exc:
432                    raise ValidationError([ErrorWrapper(exc, loc=ROOT_KEY)], self.__class__)
433
434            known_field = self.__fields__.get(name, None)
435            if known_field:
436                # We want to
437                # - make sure validators are called without the current value for this field inside `values`
438                # - keep other values (e.g. submodels) untouched (using `BaseModel.dict()` will change them into dicts)
439                # - keep the order of the fields
440                if not known_field.field_info.allow_mutation:
441                    raise TypeError(f'"{known_field.name}" has allow_mutation set to False and cannot be assigned')
442                dict_without_original_value = {k: v for k, v in self.__dict__.items() if k != name}
443                value, error_ = known_field.validate(value, dict_without_original_value, loc=name, cls=self.__class__)
444                if error_:
445                    raise ValidationError([error_], self.__class__)
446                else:
447                    new_values[name] = value
448
449            errors = []
450            for skip_on_failure, validator in self.__post_root_validators__:
451                if skip_on_failure and errors:
452                    continue
453                try:
454                    new_values = validator(self.__class__, new_values)
455                except (ValueError, TypeError, AssertionError) as exc:
456                    errors.append(ErrorWrapper(exc, loc=ROOT_KEY))
457            if errors:
458                raise ValidationError(errors, self.__class__)
459
460            # update the whole __dict__ as other values than just `value`
461            # may be changed (e.g. with `root_validator`)
462            object_setattr(self, '__dict__', new_values)
463        else:
464            self.__dict__[name] = value
465
466        self.__fields_set__.add(name)
467
468    def __getstate__(self) -> 'DictAny':
469        private_attrs = ((k, getattr(self, k, Undefined)) for k in self.__private_attributes__)
470        return {
471            '__dict__': self.__dict__,
472            '__fields_set__': self.__fields_set__,
473            '__private_attribute_values__': {k: v for k, v in private_attrs if v is not Undefined},
474        }
475
476    def __setstate__(self, state: 'DictAny') -> None:
477        object_setattr(self, '__dict__', state['__dict__'])
478        object_setattr(self, '__fields_set__', state['__fields_set__'])
479        for name, value in state.get('__private_attribute_values__', {}).items():
480            object_setattr(self, name, value)
481
482    def _init_private_attributes(self) -> None:
483        for name, private_attr in self.__private_attributes__.items():
484            default = private_attr.get_default()
485            if default is not Undefined:
486                object_setattr(self, name, default)
487
488    def dict(
489        self,
490        *,
491        include: Union['AbstractSetIntStr', 'MappingIntStrAny'] = None,
492        exclude: Union['AbstractSetIntStr', 'MappingIntStrAny'] = None,
493        by_alias: bool = False,
494        skip_defaults: bool = None,
495        exclude_unset: bool = False,
496        exclude_defaults: bool = False,
497        exclude_none: bool = False,
498    ) -> 'DictStrAny':
499        """
500        Generate a dictionary representation of the model, optionally specifying which fields to include or exclude.
501
502        """
503        if skip_defaults is not None:
504            warnings.warn(
505                f'{self.__class__.__name__}.dict(): "skip_defaults" is deprecated and replaced by "exclude_unset"',
506                DeprecationWarning,
507            )
508            exclude_unset = skip_defaults
509
510        return dict(
511            self._iter(
512                to_dict=True,
513                by_alias=by_alias,
514                include=include,
515                exclude=exclude,
516                exclude_unset=exclude_unset,
517                exclude_defaults=exclude_defaults,
518                exclude_none=exclude_none,
519            )
520        )
521
522    def json(
523        self,
524        *,
525        include: Union['AbstractSetIntStr', 'MappingIntStrAny'] = None,
526        exclude: Union['AbstractSetIntStr', 'MappingIntStrAny'] = None,
527        by_alias: bool = False,
528        skip_defaults: bool = None,
529        exclude_unset: bool = False,
530        exclude_defaults: bool = False,
531        exclude_none: bool = False,
532        encoder: Optional[Callable[[Any], Any]] = None,
533        **dumps_kwargs: Any,
534    ) -> str:
535        """
536        Generate a JSON representation of the model, `include` and `exclude` arguments as per `dict()`.
537
538        `encoder` is an optional function to supply as `default` to json.dumps(), other arguments as per `json.dumps()`.
539        """
540        if skip_defaults is not None:
541            warnings.warn(
542                f'{self.__class__.__name__}.json(): "skip_defaults" is deprecated and replaced by "exclude_unset"',
543                DeprecationWarning,
544            )
545            exclude_unset = skip_defaults
546        encoder = cast(Callable[[Any], Any], encoder or self.__json_encoder__)
547        data = self.dict(
548            include=include,
549            exclude=exclude,
550            by_alias=by_alias,
551            exclude_unset=exclude_unset,
552            exclude_defaults=exclude_defaults,
553            exclude_none=exclude_none,
554        )
555        if self.__custom_root_type__:
556            data = data[ROOT_KEY]
557        return self.__config__.json_dumps(data, default=encoder, **dumps_kwargs)
558
559    @classmethod
560    def _enforce_dict_if_root(cls, obj: Any) -> Any:
561        if cls.__custom_root_type__ and (
562            not (isinstance(obj, dict) and obj.keys() == {ROOT_KEY})
563            or cls.__fields__[ROOT_KEY].shape in MAPPING_LIKE_SHAPES
564        ):
565            return {ROOT_KEY: obj}
566        else:
567            return obj
568
569    @classmethod
570    def parse_obj(cls: Type['Model'], obj: Any) -> 'Model':
571        obj = cls._enforce_dict_if_root(obj)
572        if not isinstance(obj, dict):
573            try:
574                obj = dict(obj)
575            except (TypeError, ValueError) as e:
576                exc = TypeError(f'{cls.__name__} expected dict not {obj.__class__.__name__}')
577                raise ValidationError([ErrorWrapper(exc, loc=ROOT_KEY)], cls) from e
578        return cls(**obj)
579
580    @classmethod
581    def parse_raw(
582        cls: Type['Model'],
583        b: StrBytes,
584        *,
585        content_type: str = None,
586        encoding: str = 'utf8',
587        proto: Protocol = None,
588        allow_pickle: bool = False,
589    ) -> 'Model':
590        try:
591            obj = load_str_bytes(
592                b,
593                proto=proto,
594                content_type=content_type,
595                encoding=encoding,
596                allow_pickle=allow_pickle,
597                json_loads=cls.__config__.json_loads,
598            )
599        except (ValueError, TypeError, UnicodeDecodeError) as e:
600            raise ValidationError([ErrorWrapper(e, loc=ROOT_KEY)], cls)
601        return cls.parse_obj(obj)
602
603    @classmethod
604    def parse_file(
605        cls: Type['Model'],
606        path: Union[str, Path],
607        *,
608        content_type: str = None,
609        encoding: str = 'utf8',
610        proto: Protocol = None,
611        allow_pickle: bool = False,
612    ) -> 'Model':
613        obj = load_file(
614            path,
615            proto=proto,
616            content_type=content_type,
617            encoding=encoding,
618            allow_pickle=allow_pickle,
619            json_loads=cls.__config__.json_loads,
620        )
621        return cls.parse_obj(obj)
622
623    @classmethod
624    def from_orm(cls: Type['Model'], obj: Any) -> 'Model':
625        if not cls.__config__.orm_mode:
626            raise ConfigError('You must have the config attribute orm_mode=True to use from_orm')
627        obj = {ROOT_KEY: obj} if cls.__custom_root_type__ else cls._decompose_class(obj)
628        m = cls.__new__(cls)
629        values, fields_set, validation_error = validate_model(cls, obj)
630        if validation_error:
631            raise validation_error
632        object_setattr(m, '__dict__', values)
633        object_setattr(m, '__fields_set__', fields_set)
634        m._init_private_attributes()
635        return m
636
637    @classmethod
638    def construct(cls: Type['Model'], _fields_set: Optional['SetStr'] = None, **values: Any) -> 'Model':
639        """
640        Creates a new model setting __dict__ and __fields_set__ from trusted or pre-validated data.
641        Default values are respected, but no other validation is performed.
642        Behaves as if `Config.extra = 'allow'` was set since it adds all passed values
643        """
644        m = cls.__new__(cls)
645        fields_values: Dict[str, Any] = {}
646        for name, field in cls.__fields__.items():
647            if name in values:
648                fields_values[name] = values[name]
649            elif not field.required:
650                fields_values[name] = field.get_default()
651        fields_values.update(values)
652        object_setattr(m, '__dict__', fields_values)
653        if _fields_set is None:
654            _fields_set = set(values.keys())
655        object_setattr(m, '__fields_set__', _fields_set)
656        m._init_private_attributes()
657        return m
658
659    def copy(
660        self: 'Model',
661        *,
662        include: Union['AbstractSetIntStr', 'MappingIntStrAny'] = None,
663        exclude: Union['AbstractSetIntStr', 'MappingIntStrAny'] = None,
664        update: 'DictStrAny' = None,
665        deep: bool = False,
666    ) -> 'Model':
667        """
668        Duplicate a model, optionally choose which fields to include, exclude and change.
669
670        :param include: fields to include in new model
671        :param exclude: fields to exclude from new model, as with values this takes precedence over include
672        :param update: values to change/add in the new model. Note: the data is not validated before creating
673            the new model: you should trust this data
674        :param deep: set to `True` to make a deep copy of the model
675        :return: new model instance
676        """
677
678        v = dict(
679            self._iter(to_dict=False, by_alias=False, include=include, exclude=exclude, exclude_unset=False),
680            **(update or {}),
681        )
682
683        if deep:
684            # chances of having empty dict here are quite low for using smart_deepcopy
685            v = deepcopy(v)
686
687        cls = self.__class__
688        m = cls.__new__(cls)
689        object_setattr(m, '__dict__', v)
690        # new `__fields_set__` can have unset optional fields with a set value in `update` kwarg
691        if update:
692            fields_set = self.__fields_set__ | update.keys()
693        else:
694            fields_set = set(self.__fields_set__)
695        object_setattr(m, '__fields_set__', fields_set)
696        for name in self.__private_attributes__:
697            value = getattr(self, name, Undefined)
698            if value is not Undefined:
699                if deep:
700                    value = deepcopy(value)
701                object_setattr(m, name, value)
702
703        return m
704
705    @classmethod
706    def schema(cls, by_alias: bool = True, ref_template: str = default_ref_template) -> 'DictStrAny':
707        cached = cls.__schema_cache__.get((by_alias, ref_template))
708        if cached is not None:
709            return cached
710        s = model_schema(cls, by_alias=by_alias, ref_template=ref_template)
711        cls.__schema_cache__[(by_alias, ref_template)] = s
712        return s
713
714    @classmethod
715    def schema_json(
716        cls, *, by_alias: bool = True, ref_template: str = default_ref_template, **dumps_kwargs: Any
717    ) -> str:
718        from .json import pydantic_encoder
719
720        return cls.__config__.json_dumps(
721            cls.schema(by_alias=by_alias, ref_template=ref_template), default=pydantic_encoder, **dumps_kwargs
722        )
723
724    @classmethod
725    def __get_validators__(cls) -> 'CallableGenerator':
726        yield cls.validate
727
728    @classmethod
729    def validate(cls: Type['Model'], value: Any) -> 'Model':
730        if isinstance(value, cls):
731            return value.copy() if cls.__config__.copy_on_model_validation else value
732
733        value = cls._enforce_dict_if_root(value)
734        if isinstance(value, dict):
735            return cls(**value)
736        elif cls.__config__.orm_mode:
737            return cls.from_orm(value)
738        else:
739            try:
740                value_as_dict = dict(value)
741            except (TypeError, ValueError) as e:
742                raise DictError() from e
743            return cls(**value_as_dict)
744
745    @classmethod
746    def _decompose_class(cls: Type['Model'], obj: Any) -> GetterDict:
747        return cls.__config__.getter_dict(obj)
748
749    @classmethod
750    @no_type_check
751    def _get_value(
752        cls,
753        v: Any,
754        to_dict: bool,
755        by_alias: bool,
756        include: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']],
757        exclude: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']],
758        exclude_unset: bool,
759        exclude_defaults: bool,
760        exclude_none: bool,
761    ) -> Any:
762
763        if isinstance(v, BaseModel):
764            if to_dict:
765                v_dict = v.dict(
766                    by_alias=by_alias,
767                    exclude_unset=exclude_unset,
768                    exclude_defaults=exclude_defaults,
769                    include=include,
770                    exclude=exclude,
771                    exclude_none=exclude_none,
772                )
773                if ROOT_KEY in v_dict:
774                    return v_dict[ROOT_KEY]
775                return v_dict
776            else:
777                return v.copy(include=include, exclude=exclude)
778
779        value_exclude = ValueItems(v, exclude) if exclude else None
780        value_include = ValueItems(v, include) if include else None
781
782        if isinstance(v, dict):
783            return {
784                k_: cls._get_value(
785                    v_,
786                    to_dict=to_dict,
787                    by_alias=by_alias,
788                    exclude_unset=exclude_unset,
789                    exclude_defaults=exclude_defaults,
790                    include=value_include and value_include.for_element(k_),
791                    exclude=value_exclude and value_exclude.for_element(k_),
792                    exclude_none=exclude_none,
793                )
794                for k_, v_ in v.items()
795                if (not value_exclude or not value_exclude.is_excluded(k_))
796                and (not value_include or value_include.is_included(k_))
797            }
798
799        elif sequence_like(v):
800            seq_args = (
801                cls._get_value(
802                    v_,
803                    to_dict=to_dict,
804                    by_alias=by_alias,
805                    exclude_unset=exclude_unset,
806                    exclude_defaults=exclude_defaults,
807                    include=value_include and value_include.for_element(i),
808                    exclude=value_exclude and value_exclude.for_element(i),
809                    exclude_none=exclude_none,
810                )
811                for i, v_ in enumerate(v)
812                if (not value_exclude or not value_exclude.is_excluded(i))
813                and (not value_include or value_include.is_included(i))
814            )
815
816            return v.__class__(*seq_args) if is_namedtuple(v.__class__) else v.__class__(seq_args)
817
818        elif isinstance(v, Enum) and getattr(cls.Config, 'use_enum_values', False):
819            return v.value
820
821        else:
822            return v
823
824    @classmethod
825    def update_forward_refs(cls, **localns: Any) -> None:
826        """
827        Try to update ForwardRefs on fields based on this Model, globalns and localns.
828        """
829        globalns = sys.modules[cls.__module__].__dict__.copy()
830        globalns.setdefault(cls.__name__, cls)
831        for f in cls.__fields__.values():
832            update_field_forward_refs(f, globalns=globalns, localns=localns)
833
834    def __iter__(self) -> 'TupleGenerator':
835        """
836        so `dict(model)` works
837        """
838        yield from self.__dict__.items()
839
840    def _iter(
841        self,
842        to_dict: bool = False,
843        by_alias: bool = False,
844        include: Union['AbstractSetIntStr', 'MappingIntStrAny'] = None,
845        exclude: Union['AbstractSetIntStr', 'MappingIntStrAny'] = None,
846        exclude_unset: bool = False,
847        exclude_defaults: bool = False,
848        exclude_none: bool = False,
849    ) -> 'TupleGenerator':
850
851        allowed_keys = self._calculate_keys(include=include, exclude=exclude, exclude_unset=exclude_unset)
852        if allowed_keys is None and not (to_dict or by_alias or exclude_unset or exclude_defaults or exclude_none):
853            # huge boost for plain _iter()
854            yield from self.__dict__.items()
855            return
856
857        value_exclude = ValueItems(self, exclude) if exclude else None
858        value_include = ValueItems(self, include) if include else None
859
860        for field_key, v in self.__dict__.items():
861            if (allowed_keys is not None and field_key not in allowed_keys) or (exclude_none and v is None):
862                continue
863
864            if exclude_defaults:
865                model_field = self.__fields__.get(field_key)
866                if not getattr(model_field, 'required', True) and getattr(model_field, 'default', _missing) == v:
867                    continue
868
869            if by_alias and field_key in self.__fields__:
870                dict_key = self.__fields__[field_key].alias
871            else:
872                dict_key = field_key
873
874            if to_dict or value_include or value_exclude:
875                v = self._get_value(
876                    v,
877                    to_dict=to_dict,
878                    by_alias=by_alias,
879                    include=value_include and value_include.for_element(field_key),
880                    exclude=value_exclude and value_exclude.for_element(field_key),
881                    exclude_unset=exclude_unset,
882                    exclude_defaults=exclude_defaults,
883                    exclude_none=exclude_none,
884                )
885            yield dict_key, v
886
887    def _calculate_keys(
888        self,
889        include: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']],
890        exclude: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']],
891        exclude_unset: bool,
892        update: Optional['DictStrAny'] = None,
893    ) -> Optional[AbstractSet[str]]:
894        if include is None and exclude is None and exclude_unset is False:
895            return None
896
897        keys: AbstractSet[str]
898        if exclude_unset:
899            keys = self.__fields_set__.copy()
900        else:
901            keys = self.__dict__.keys()
902
903        if include is not None:
904            if isinstance(include, Mapping):
905                keys &= include.keys()
906            else:
907                keys &= include
908
909        if update:
910            keys -= update.keys()
911
912        if exclude:
913            if isinstance(exclude, Mapping):
914                keys -= {k for k, v in exclude.items() if v is ...}
915            else:
916                keys -= exclude
917
918        return keys
919
920    def __eq__(self, other: Any) -> bool:
921        if isinstance(other, BaseModel):
922            return self.dict() == other.dict()
923        else:
924            return self.dict() == other
925
926    def __repr_args__(self) -> 'ReprArgs':
927        return self.__dict__.items()  # type: ignore
928
929
930_is_base_model_class_defined = True
931
932
933def create_model(
934    __model_name: str,
935    *,
936    __config__: Type[BaseConfig] = None,
937    __base__: Type['Model'] = None,
938    __module__: str = __name__,
939    __validators__: Dict[str, classmethod] = None,
940    **field_definitions: Any,
941) -> Type['Model']:
942    """
943    Dynamically create a model.
944    :param __model_name: name of the created model
945    :param __config__: config class to use for the new model
946    :param __base__: base class for the new model to inherit from
947    :param __module__: module of the created model
948    :param __validators__: a dict of method names and @validator class methods
949    :param field_definitions: fields of the model (or extra fields if a base is supplied)
950        in the format `<name>=(<type>, <default default>)` or `<name>=<default value>, e.g.
951        `foobar=(str, ...)` or `foobar=123`, or, for complex use-cases, in the format
952        `<name>=<FieldInfo>`, e.g. `foo=Field(default_factory=datetime.utcnow, alias='bar')`
953    """
954
955    if __base__ is not None:
956        if __config__ is not None:
957            raise ConfigError('to avoid confusion __config__ and __base__ cannot be used together')
958    else:
959        __base__ = cast(Type['Model'], BaseModel)
960
961    fields = {}
962    annotations = {}
963
964    for f_name, f_def in field_definitions.items():
965        if not is_valid_field(f_name):
966            warnings.warn(f'fields may not start with an underscore, ignoring "{f_name}"', RuntimeWarning)
967        if isinstance(f_def, tuple):
968            try:
969                f_annotation, f_value = f_def
970            except ValueError as e:
971                raise ConfigError(
972                    'field definitions should either be a tuple of (<type>, <default>) or just a '
973                    'default value, unfortunately this means tuples as '
974                    'default values are not allowed'
975                ) from e
976        else:
977            f_annotation, f_value = None, f_def
978
979        if f_annotation:
980            annotations[f_name] = f_annotation
981        fields[f_name] = f_value
982
983    namespace: 'DictStrAny' = {'__annotations__': annotations, '__module__': __module__}
984    if __validators__:
985        namespace.update(__validators__)
986    namespace.update(fields)
987    if __config__:
988        namespace['Config'] = inherit_config(__config__, BaseConfig)
989
990    return type(__model_name, (__base__,), namespace)
991
992
993_missing = object()
994
995
996def validate_model(  # noqa: C901 (ignore complexity)
997    model: Type[BaseModel], input_data: 'DictStrAny', cls: 'ModelOrDc' = None
998) -> Tuple['DictStrAny', 'SetStr', Optional[ValidationError]]:
999    """
1000    validate data against a model.
1001    """
1002    values = {}
1003    errors = []
1004    # input_data names, possibly alias
1005    names_used = set()
1006    # field names, never aliases
1007    fields_set = set()
1008    config = model.__config__
1009    check_extra = config.extra is not Extra.ignore
1010    cls_ = cls or model
1011
1012    for validator in model.__pre_root_validators__:
1013        try:
1014            input_data = validator(cls_, input_data)
1015        except (ValueError, TypeError, AssertionError) as exc:
1016            return {}, set(), ValidationError([ErrorWrapper(exc, loc=ROOT_KEY)], cls_)
1017
1018    for name, field in model.__fields__.items():
1019        value = input_data.get(field.alias, _missing)
1020        using_name = False
1021        if value is _missing and config.allow_population_by_field_name and field.alt_alias:
1022            value = input_data.get(field.name, _missing)
1023            using_name = True
1024
1025        if value is _missing:
1026            if field.required:
1027                errors.append(ErrorWrapper(MissingError(), loc=field.alias))
1028                continue
1029
1030            value = field.get_default()
1031
1032            if not config.validate_all and not field.validate_always:
1033                values[name] = value
1034                continue
1035        else:
1036            fields_set.add(name)
1037            if check_extra:
1038                names_used.add(field.name if using_name else field.alias)
1039
1040        v_, errors_ = field.validate(value, values, loc=field.alias, cls=cls_)
1041        if isinstance(errors_, ErrorWrapper):
1042            errors.append(errors_)
1043        elif isinstance(errors_, list):
1044            errors.extend(errors_)
1045        else:
1046            values[name] = v_
1047
1048    if check_extra:
1049        if isinstance(input_data, GetterDict):
1050            extra = input_data.extra_keys() - names_used
1051        else:
1052            extra = input_data.keys() - names_used
1053        if extra:
1054            fields_set |= extra
1055            if config.extra is Extra.allow:
1056                for f in extra:
1057                    values[f] = input_data[f]
1058            else:
1059                for f in sorted(extra):
1060                    errors.append(ErrorWrapper(ExtraError(), loc=f))
1061
1062    for skip_on_failure, validator in model.__post_root_validators__:
1063        if skip_on_failure and errors:
1064            continue
1065        try:
1066            values = validator(cls_, values)
1067        except (ValueError, TypeError, AssertionError) as exc:
1068            errors.append(ErrorWrapper(exc, loc=ROOT_KEY))
1069
1070    if errors:
1071        return values, fields_set, ValidationError(errors, cls_)
1072    else:
1073        return values, fields_set, None
1074