1"""Private logic for creating models.""" 
    2 
    3from __future__ import annotations as _annotations 
    4 
    5import operator 
    6import sys 
    7import typing 
    8import warnings 
    9import weakref 
    10from abc import ABCMeta 
    11from functools import cache, partial, wraps 
    12from types import FunctionType 
    13from typing import TYPE_CHECKING, Any, Callable, Generic, Literal, NoReturn, TypeVar, cast 
    14 
    15from pydantic_core import PydanticUndefined, SchemaSerializer 
    16from typing_extensions import TypeAliasType, dataclass_transform, deprecated, get_args, get_origin 
    17from typing_inspection import typing_objects 
    18 
    19from ..errors import PydanticUndefinedAnnotation, PydanticUserError 
    20from ..plugin._schema_validator import create_schema_validator 
    21from ..warnings import GenericBeforeBaseModelWarning, PydanticDeprecatedSince20 
    22from ._config import ConfigWrapper 
    23from ._decorators import DecoratorInfos, PydanticDescriptorProxy, get_attribute_from_bases, unwrap_wrapped_function 
    24from ._fields import collect_model_fields, is_valid_field_name, is_valid_privateattr_name, rebuild_model_fields 
    25from ._generate_schema import GenerateSchema, InvalidSchemaError 
    26from ._generics import PydanticGenericMetadata, get_model_typevars_map 
    27from ._import_utils import import_cached_base_model, import_cached_field_info 
    28from ._mock_val_ser import set_model_mocks 
    29from ._namespace_utils import NsResolver 
    30from ._signature import generate_pydantic_signature 
    31from ._typing_extra import ( 
    32    _make_forward_ref, 
    33    eval_type_backport, 
    34    is_classvar_annotation, 
    35    parent_frame_namespace, 
    36) 
    37from ._utils import LazyClassAttribute, SafeGetItemProxy 
    38 
    39if TYPE_CHECKING: 
    40    from ..fields import Field as PydanticModelField 
    41    from ..fields import FieldInfo, ModelPrivateAttr 
    42    from ..fields import PrivateAttr as PydanticModelPrivateAttr 
    43    from ..main import BaseModel 
    44else: 
    45    PydanticModelField = object() 
    46    PydanticModelPrivateAttr = object() 
    47 
    48object_setattr = object.__setattr__ 
    49 
    50 
    51class _ModelNamespaceDict(dict): 
    52    """A dictionary subclass that intercepts attribute setting on model classes and 
    53    warns about overriding of decorators. 
    54    """ 
    55 
    56    def __setitem__(self, k: str, v: object) -> None: 
    57        existing: Any = self.get(k, None) 
    58        if existing and v is not existing and isinstance(existing, PydanticDescriptorProxy): 
    59            warnings.warn( 
    60                f'`{k}` overrides an existing Pydantic `{existing.decorator_info.decorator_repr}` decorator', 
    61                stacklevel=2, 
    62            ) 
    63 
    64        return super().__setitem__(k, v) 
    65 
    66 
    67def NoInitField( 
    68    *, 
    69    init: Literal[False] = False, 
    70) -> Any: 
    71    """Only for typing purposes. Used as default value of `__pydantic_fields_set__`, 
    72    `__pydantic_extra__`, `__pydantic_private__`, so they could be ignored when 
    73    synthesizing the `__init__` signature. 
    74    """ 
    75 
    76 
    77# For ModelMetaclass.register(): 
    78_T = TypeVar('_T') 
    79 
    80 
    81@dataclass_transform(kw_only_default=True, field_specifiers=(PydanticModelField, PydanticModelPrivateAttr, NoInitField)) 
    82class ModelMetaclass(ABCMeta): 
    83    def __new__( 
    84        mcs, 
    85        cls_name: str, 
    86        bases: tuple[type[Any], ...], 
    87        namespace: dict[str, Any], 
    88        __pydantic_generic_metadata__: PydanticGenericMetadata | None = None, 
    89        __pydantic_reset_parent_namespace__: bool = True, 
    90        _create_model_module: str | None = None, 
    91        **kwargs: Any, 
    92    ) -> type: 
    93        """Metaclass for creating Pydantic models. 
    94 
    95        Args: 
    96            cls_name: The name of the class to be created. 
    97            bases: The base classes of the class to be created. 
    98            namespace: The attribute dictionary of the class to be created. 
    99            __pydantic_generic_metadata__: Metadata for generic models. 
    100            __pydantic_reset_parent_namespace__: Reset parent namespace. 
    101            _create_model_module: The module of the class to be created, if created by `create_model`. 
    102            **kwargs: Catch-all for any other keyword arguments. 
    103 
    104        Returns: 
    105            The new class created by the metaclass. 
    106        """ 
    107        # Note `ModelMetaclass` refers to `BaseModel`, but is also used to *create* `BaseModel`, so we rely on the fact 
    108        # that `BaseModel` itself won't have any bases, but any subclass of it will, to determine whether the `__new__` 
    109        # call we're in the middle of is for the `BaseModel` class. 
    110        if bases: 
    111            raw_annotations: dict[str, Any] 
    112            if sys.version_info >= (3, 14): 
    113                if ( 
    114                    '__annotations__' in namespace 
    115                ):  # `from __future__ import annotations` was used in the model's module 
    116                    raw_annotations = namespace['__annotations__'] 
    117                else: 
    118                    # See https://docs.python.org/3.14/library/annotationlib.html#using-annotations-in-a-metaclass: 
    119                    from annotationlib import Format, call_annotate_function, get_annotate_from_class_namespace 
    120 
    121                    if annotate := get_annotate_from_class_namespace(namespace): 
    122                        raw_annotations = call_annotate_function(annotate, format=Format.FORWARDREF) 
    123                    else: 
    124                        raw_annotations = {} 
    125            else: 
    126                raw_annotations = namespace.get('__annotations__', {}) 
    127 
    128            base_field_names, class_vars, base_private_attributes = mcs._collect_bases_data(bases) 
    129 
    130            config_wrapper = ConfigWrapper.for_model(bases, namespace, raw_annotations, kwargs) 
    131            namespace['model_config'] = config_wrapper.config_dict 
    132            private_attributes = inspect_namespace( 
    133                namespace, raw_annotations, config_wrapper.ignored_types, class_vars, base_field_names 
    134            ) 
    135            if private_attributes or base_private_attributes: 
    136                original_model_post_init = get_model_post_init(namespace, bases) 
    137                if original_model_post_init is not None: 
    138                    # if there are private_attributes and a model_post_init function, we handle both 
    139 
    140                    @wraps(original_model_post_init) 
    141                    def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None: 
    142                        """We need to both initialize private attributes and call the user-defined model_post_init 
    143                        method. 
    144                        """ 
    145                        init_private_attributes(self, context) 
    146                        original_model_post_init(self, context) 
    147 
    148                    namespace['model_post_init'] = wrapped_model_post_init 
    149                else: 
    150                    namespace['model_post_init'] = init_private_attributes 
    151 
    152            namespace['__class_vars__'] = class_vars 
    153            namespace['__private_attributes__'] = {**base_private_attributes, **private_attributes} 
    154 
    155            cls = cast('type[BaseModel]', super().__new__(mcs, cls_name, bases, namespace, **kwargs)) 
    156            BaseModel_ = import_cached_base_model() 
    157 
    158            mro = cls.__mro__ 
    159            if Generic in mro and mro.index(Generic) < mro.index(BaseModel_): 
    160                warnings.warn( 
    161                    GenericBeforeBaseModelWarning( 
    162                        'Classes should inherit from `BaseModel` before generic classes (e.g. `typing.Generic[T]`) ' 
    163                        'for pydantic generics to work properly.' 
    164                    ), 
    165                    stacklevel=2, 
    166                ) 
    167 
    168            cls.__pydantic_custom_init__ = not getattr(cls.__init__, '__pydantic_base_init__', False) 
    169            cls.__pydantic_post_init__ = ( 
    170                None if cls.model_post_init is BaseModel_.model_post_init else 'model_post_init' 
    171            ) 
    172 
    173            cls.__pydantic_setattr_handlers__ = {} 
    174 
    175            cls.__pydantic_decorators__ = DecoratorInfos.build(cls) 
    176            cls.__pydantic_decorators__.update_from_config(config_wrapper) 
    177 
    178            # Use the getattr below to grab the __parameters__ from the `typing.Generic` parent class 
    179            if __pydantic_generic_metadata__: 
    180                cls.__pydantic_generic_metadata__ = __pydantic_generic_metadata__ 
    181            else: 
    182                parent_parameters = getattr(cls, '__pydantic_generic_metadata__', {}).get('parameters', ()) 
    183                parameters = getattr(cls, '__parameters__', None) or parent_parameters 
    184                if parameters and parent_parameters and not all(x in parameters for x in parent_parameters): 
    185                    from ..root_model import RootModelRootType 
    186 
    187                    missing_parameters = tuple(x for x in parameters if x not in parent_parameters) 
    188                    if RootModelRootType in parent_parameters and RootModelRootType not in parameters: 
    189                        # This is a special case where the user has subclassed `RootModel`, but has not parametrized 
    190                        # RootModel with the generic type identifiers being used. Ex: 
    191                        # class MyModel(RootModel, Generic[T]): 
    192                        #    root: T 
    193                        # Should instead just be: 
    194                        # class MyModel(RootModel[T]): 
    195                        #   root: T 
    196                        parameters_str = ', '.join([x.__name__ for x in missing_parameters]) 
    197                        error_message = ( 
    198                            f'{cls.__name__} is a subclass of `RootModel`, but does not include the generic type identifier(s) ' 
    199                            f'{parameters_str} in its parameters. ' 
    200                            f'You should parametrize RootModel directly, e.g., `class {cls.__name__}(RootModel[{parameters_str}]): ...`.' 
    201                        ) 
    202                    else: 
    203                        combined_parameters = parent_parameters + missing_parameters 
    204                        parameters_str = ', '.join([str(x) for x in combined_parameters]) 
    205                        generic_type_label = f'typing.Generic[{parameters_str}]' 
    206                        error_message = ( 
    207                            f'All parameters must be present on typing.Generic;' 
    208                            f' you should inherit from {generic_type_label}.' 
    209                        ) 
    210                        if Generic not in bases:  # pragma: no cover 
    211                            # We raise an error here not because it is desirable, but because some cases are mishandled. 
    212                            # It would be nice to remove this error and still have things behave as expected, it's just 
    213                            # challenging because we are using a custom `__class_getitem__` to parametrize generic models, 
    214                            # and not returning a typing._GenericAlias from it. 
    215                            bases_str = ', '.join([x.__name__ for x in bases] + [generic_type_label]) 
    216                            error_message += ( 
    217                                f' Note: `typing.Generic` must go last: `class {cls.__name__}({bases_str}): ...`)' 
    218                            ) 
    219                    raise TypeError(error_message) 
    220 
    221                cls.__pydantic_generic_metadata__ = { 
    222                    'origin': None, 
    223                    'args': (), 
    224                    'parameters': parameters, 
    225                } 
    226 
    227            cls.__pydantic_complete__ = False  # Ensure this specific class gets completed 
    228 
    229            # preserve `__set_name__` protocol defined in https://peps.python.org/pep-0487 
    230            # for attributes not in `new_namespace` (e.g. private attributes) 
    231            for name, obj in private_attributes.items(): 
    232                obj.__set_name__(cls, name) 
    233 
    234            if __pydantic_reset_parent_namespace__: 
    235                cls.__pydantic_parent_namespace__ = build_lenient_weakvaluedict(parent_frame_namespace()) 
    236            parent_namespace: dict[str, Any] | None = getattr(cls, '__pydantic_parent_namespace__', None) 
    237            if isinstance(parent_namespace, dict): 
    238                parent_namespace = unpack_lenient_weakvaluedict(parent_namespace) 
    239 
    240            ns_resolver = NsResolver(parent_namespace=parent_namespace) 
    241 
    242            set_model_fields(cls, config_wrapper=config_wrapper, ns_resolver=ns_resolver) 
    243 
    244            # This is also set in `complete_model_class()`, after schema gen because they are recreated. 
    245            # We set them here as well for backwards compatibility: 
    246            cls.__pydantic_computed_fields__ = { 
    247                k: v.info for k, v in cls.__pydantic_decorators__.computed_fields.items() 
    248            } 
    249 
    250            if config_wrapper.defer_build: 
    251                set_model_mocks(cls) 
    252            else: 
    253                # Any operation that requires accessing the field infos instances should be put inside 
    254                # `complete_model_class()`: 
    255                complete_model_class( 
    256                    cls, 
    257                    config_wrapper, 
    258                    ns_resolver, 
    259                    raise_errors=False, 
    260                    create_model_module=_create_model_module, 
    261                ) 
    262 
    263            if config_wrapper.frozen and '__hash__' not in namespace: 
    264                set_default_hash_func(cls, bases) 
    265 
    266            # using super(cls, cls) on the next line ensures we only call the parent class's __pydantic_init_subclass__ 
    267            # I believe the `type: ignore` is only necessary because mypy doesn't realize that this code branch is 
    268            # only hit for _proper_ subclasses of BaseModel 
    269            super(cls, cls).__pydantic_init_subclass__(**kwargs)  # type: ignore[misc] 
    270            return cls 
    271        else: 
    272            # These are instance variables, but have been assigned to `NoInitField` to trick the type checker. 
    273            for instance_slot in '__pydantic_fields_set__', '__pydantic_extra__', '__pydantic_private__': 
    274                namespace.pop( 
    275                    instance_slot, 
    276                    None,  # In case the metaclass is used with a class other than `BaseModel`. 
    277                ) 
    278            namespace.get('__annotations__', {}).clear() 
    279            return super().__new__(mcs, cls_name, bases, namespace, **kwargs) 
    280 
    281    if not TYPE_CHECKING:  # pragma: no branch 
    282        # We put `__getattr__` in a non-TYPE_CHECKING block because otherwise, mypy allows arbitrary attribute access 
    283 
    284        def __getattr__(self, item: str) -> Any: 
    285            """This is necessary to keep attribute access working for class attribute access.""" 
    286            private_attributes = self.__dict__.get('__private_attributes__') 
    287            if private_attributes and item in private_attributes: 
    288                return private_attributes[item] 
    289            raise AttributeError(item) 
    290 
    291    @classmethod 
    292    def __prepare__(cls, *args: Any, **kwargs: Any) -> dict[str, object]: 
    293        return _ModelNamespaceDict() 
    294 
    295    # Due to performance and memory issues, in the ABCMeta.__subclasscheck__ implementation, we don't support 
    296    # registered virtual subclasses. See https://github.com/python/cpython/issues/92810#issuecomment-2762454345. 
    297    # This may change once the CPython gets fixed (possibly in 3.15), in which case we should conditionally 
    298    # define `register()`. 
    299    def register(self, subclass: type[_T]) -> type[_T]: 
    300        warnings.warn( 
    301            f"For performance reasons, virtual subclasses registered using '{self.__qualname__}.register()' " 
    302            "are not supported in 'isinstance()' and 'issubclass()' checks.", 
    303            stacklevel=2, 
    304        ) 
    305        return super().register(subclass) 
    306 
    307    __instancecheck__ = type.__instancecheck__  # pyright: ignore[reportAssignmentType] 
    308    __subclasscheck__ = type.__subclasscheck__  # pyright: ignore[reportAssignmentType] 
    309 
    310    @staticmethod 
    311    def _collect_bases_data(bases: tuple[type[Any], ...]) -> tuple[set[str], set[str], dict[str, ModelPrivateAttr]]: 
    312        BaseModel = import_cached_base_model() 
    313 
    314        field_names: set[str] = set() 
    315        class_vars: set[str] = set() 
    316        private_attributes: dict[str, ModelPrivateAttr] = {} 
    317        for base in bases: 
    318            if issubclass(base, BaseModel) and base is not BaseModel: 
    319                # model_fields might not be defined yet in the case of generics, so we use getattr here: 
    320                field_names.update(getattr(base, '__pydantic_fields__', {}).keys()) 
    321                class_vars.update(base.__class_vars__) 
    322                private_attributes.update(base.__private_attributes__) 
    323        return field_names, class_vars, private_attributes 
    324 
    325    @property 
    326    @deprecated( 
    327        'The `__fields__` attribute is deprecated, use the `model_fields` class property instead.', category=None 
    328    ) 
    329    def __fields__(self) -> dict[str, FieldInfo]: 
    330        warnings.warn( 
    331            'The `__fields__` attribute is deprecated, use the `model_fields` class property instead.', 
    332            PydanticDeprecatedSince20, 
    333            stacklevel=2, 
    334        ) 
    335        return getattr(self, '__pydantic_fields__', {}) 
    336 
    337    @property 
    338    def __pydantic_fields_complete__(self) -> bool: 
    339        """Whether the fields where successfully collected (i.e. type hints were successfully resolves). 
    340 
    341        This is a private attribute, not meant to be used outside Pydantic. 
    342        """ 
    343        if '__pydantic_fields__' not in self.__dict__: 
    344            return False 
    345 
    346        field_infos = cast('dict[str, FieldInfo]', self.__pydantic_fields__)  # pyright: ignore[reportAttributeAccessIssue] 
    347 
    348        return all(field_info._complete for field_info in field_infos.values()) 
    349 
    350    def __dir__(self) -> list[str]: 
    351        attributes = list(super().__dir__()) 
    352        if '__fields__' in attributes: 
    353            attributes.remove('__fields__') 
    354        return attributes 
    355 
    356 
    357def init_private_attributes(self: BaseModel, context: Any, /) -> None: 
    358    """This function is meant to behave like a BaseModel method to initialise private attributes. 
    359 
    360    It takes context as an argument since that's what pydantic-core passes when calling it. 
    361 
    362    Args: 
    363        self: The BaseModel instance. 
    364        context: The context. 
    365    """ 
    366    if getattr(self, '__pydantic_private__', None) is None: 
    367        pydantic_private = {} 
    368        for name, private_attr in self.__private_attributes__.items(): 
    369            default = private_attr.get_default() 
    370            if default is not PydanticUndefined: 
    371                pydantic_private[name] = default 
    372        object_setattr(self, '__pydantic_private__', pydantic_private) 
    373 
    374 
    375def get_model_post_init(namespace: dict[str, Any], bases: tuple[type[Any], ...]) -> Callable[..., Any] | None: 
    376    """Get the `model_post_init` method from the namespace or the class bases, or `None` if not defined.""" 
    377    if 'model_post_init' in namespace: 
    378        return namespace['model_post_init'] 
    379 
    380    BaseModel = import_cached_base_model() 
    381 
    382    model_post_init = get_attribute_from_bases(bases, 'model_post_init') 
    383    if model_post_init is not BaseModel.model_post_init: 
    384        return model_post_init 
    385 
    386 
    387def inspect_namespace(  # noqa C901 
    388    namespace: dict[str, Any], 
    389    raw_annotations: dict[str, Any], 
    390    ignored_types: tuple[type[Any], ...], 
    391    base_class_vars: set[str], 
    392    base_class_fields: set[str], 
    393) -> dict[str, ModelPrivateAttr]: 
    394    """Iterate over the namespace and: 
    395    * gather private attributes 
    396    * check for items which look like fields but are not (e.g. have no annotation) and warn. 
    397 
    398    Args: 
    399        namespace: The attribute dictionary of the class to be created. 
    400        raw_annotations: The (non-evaluated) annotations of the model. 
    401        ignored_types: A tuple of ignore types. 
    402        base_class_vars: A set of base class class variables. 
    403        base_class_fields: A set of base class fields. 
    404 
    405    Returns: 
    406        A dict contains private attributes info. 
    407 
    408    Raises: 
    409        TypeError: If there is a `__root__` field in model. 
    410        NameError: If private attribute name is invalid. 
    411        PydanticUserError: 
    412            - If a field does not have a type annotation. 
    413            - If a field on base class was overridden by a non-annotated attribute. 
    414    """ 
    415    from ..fields import ModelPrivateAttr, PrivateAttr 
    416 
    417    FieldInfo = import_cached_field_info() 
    418 
    419    all_ignored_types = ignored_types + default_ignored_types() 
    420 
    421    private_attributes: dict[str, ModelPrivateAttr] = {} 
    422 
    423    if '__root__' in raw_annotations or '__root__' in namespace: 
    424        raise TypeError("To define root models, use `pydantic.RootModel` rather than a field called '__root__'") 
    425 
    426    ignored_names: set[str] = set() 
    427    for var_name, value in list(namespace.items()): 
    428        if var_name == 'model_config' or var_name == '__pydantic_extra__': 
    429            continue 
    430        elif ( 
    431            isinstance(value, type) 
    432            and value.__module__ == namespace['__module__'] 
    433            and '__qualname__' in namespace 
    434            and value.__qualname__.startswith(f'{namespace["__qualname__"]}.') 
    435        ): 
    436            # `value` is a nested type defined in this namespace; don't error 
    437            continue 
    438        elif isinstance(value, all_ignored_types) or value.__class__.__module__ == 'functools': 
    439            ignored_names.add(var_name) 
    440            continue 
    441        elif isinstance(value, ModelPrivateAttr): 
    442            if var_name.startswith('__'): 
    443                raise NameError( 
    444                    'Private attributes must not use dunder names;' 
    445                    f' use a single underscore prefix instead of {var_name!r}.' 
    446                ) 
    447            elif is_valid_field_name(var_name): 
    448                raise NameError( 
    449                    'Private attributes must not use valid field names;' 
    450                    f' use sunder names, e.g. {"_" + var_name!r} instead of {var_name!r}.' 
    451                ) 
    452            private_attributes[var_name] = value 
    453            del namespace[var_name] 
    454        elif isinstance(value, FieldInfo) and not is_valid_field_name(var_name): 
    455            suggested_name = var_name.lstrip('_') or 'my_field'  # don't suggest '' for all-underscore name 
    456            raise NameError( 
    457                f'Fields must not use names with leading underscores;' 
    458                f' e.g., use {suggested_name!r} instead of {var_name!r}.' 
    459            ) 
    460 
    461        elif var_name.startswith('__'): 
    462            continue 
    463        elif is_valid_privateattr_name(var_name): 
    464            if var_name not in raw_annotations or not is_classvar_annotation(raw_annotations[var_name]): 
    465                private_attributes[var_name] = cast(ModelPrivateAttr, PrivateAttr(default=value)) 
    466                del namespace[var_name] 
    467        elif var_name in base_class_vars: 
    468            continue 
    469        elif var_name not in raw_annotations: 
    470            if var_name in base_class_fields: 
    471                raise PydanticUserError( 
    472                    f'Field {var_name!r} defined on a base class was overridden by a non-annotated attribute. ' 
    473                    f'All field definitions, including overrides, require a type annotation.', 
    474                    code='model-field-overridden', 
    475                ) 
    476            elif isinstance(value, FieldInfo): 
    477                raise PydanticUserError( 
    478                    f'Field {var_name!r} requires a type annotation', code='model-field-missing-annotation' 
    479                ) 
    480            else: 
    481                raise PydanticUserError( 
    482                    f'A non-annotated attribute was detected: `{var_name} = {value!r}`. All model fields require a ' 
    483                    f'type annotation; if `{var_name}` is not meant to be a field, you may be able to resolve this ' 
    484                    f"error by annotating it as a `ClassVar` or updating `model_config['ignored_types']`.", 
    485                    code='model-field-missing-annotation', 
    486                ) 
    487 
    488    for ann_name, ann_type in raw_annotations.items(): 
    489        if ( 
    490            is_valid_privateattr_name(ann_name) 
    491            and ann_name not in private_attributes 
    492            and ann_name not in ignored_names 
    493            # This condition can be a false negative when `ann_type` is stringified, 
    494            # but it is handled in most cases in `set_model_fields`: 
    495            and not is_classvar_annotation(ann_type) 
    496            and ann_type not in all_ignored_types 
    497            and getattr(ann_type, '__module__', None) != 'functools' 
    498        ): 
    499            if isinstance(ann_type, str): 
    500                # Walking up the frames to get the module namespace where the model is defined 
    501                # (as the model class wasn't created yet, we unfortunately can't use `cls.__module__`): 
    502                frame = sys._getframe(2) 
    503                if frame is not None: 
    504                    try: 
    505                        ann_type = eval_type_backport( 
    506                            _make_forward_ref(ann_type, is_argument=False, is_class=True), 
    507                            globalns=frame.f_globals, 
    508                            localns=frame.f_locals, 
    509                        ) 
    510                    except (NameError, TypeError): 
    511                        pass 
    512 
    513            if typing_objects.is_annotated(get_origin(ann_type)): 
    514                _, *metadata = get_args(ann_type) 
    515                private_attr = next((v for v in metadata if isinstance(v, ModelPrivateAttr)), None) 
    516                if private_attr is not None: 
    517                    private_attributes[ann_name] = private_attr 
    518                    continue 
    519            private_attributes[ann_name] = PrivateAttr() 
    520 
    521    return private_attributes 
    522 
    523 
    524def set_default_hash_func(cls: type[BaseModel], bases: tuple[type[Any], ...]) -> None: 
    525    base_hash_func = get_attribute_from_bases(bases, '__hash__') 
    526    new_hash_func = make_hash_func(cls) 
    527    if base_hash_func in {None, object.__hash__} or getattr(base_hash_func, '__code__', None) == new_hash_func.__code__: 
    528        # If `__hash__` is some default, we generate a hash function. 
    529        # It will be `None` if not overridden from BaseModel. 
    530        # It may be `object.__hash__` if there is another 
    531        # parent class earlier in the bases which doesn't override `__hash__` (e.g. `typing.Generic`). 
    532        # It may be a value set by `set_default_hash_func` if `cls` is a subclass of another frozen model. 
    533        # In the last case we still need a new hash function to account for new `model_fields`. 
    534        cls.__hash__ = new_hash_func 
    535 
    536 
    537def make_hash_func(cls: type[BaseModel]) -> Any: 
    538    getter = operator.itemgetter(*cls.__pydantic_fields__.keys()) if cls.__pydantic_fields__ else lambda _: 0 
    539 
    540    def hash_func(self: Any) -> int: 
    541        try: 
    542            return hash(getter(self.__dict__)) 
    543        except KeyError: 
    544            # In rare cases (such as when using the deprecated copy method), the __dict__ may not contain 
    545            # all model fields, which is how we can get here. 
    546            # getter(self.__dict__) is much faster than any 'safe' method that accounts for missing keys, 
    547            # and wrapping it in a `try` doesn't slow things down much in the common case. 
    548            return hash(getter(SafeGetItemProxy(self.__dict__))) 
    549 
    550    return hash_func 
    551 
    552 
    553def set_model_fields( 
    554    cls: type[BaseModel], 
    555    config_wrapper: ConfigWrapper, 
    556    ns_resolver: NsResolver | None, 
    557) -> None: 
    558    """Collect and set `cls.__pydantic_fields__` and `cls.__class_vars__`. 
    559 
    560    Args: 
    561        cls: BaseModel or dataclass. 
    562        config_wrapper: The config wrapper instance. 
    563        ns_resolver: Namespace resolver to use when getting model annotations. 
    564    """ 
    565    typevars_map = get_model_typevars_map(cls) 
    566    fields, class_vars = collect_model_fields(cls, config_wrapper, ns_resolver, typevars_map=typevars_map) 
    567 
    568    cls.__pydantic_fields__ = fields 
    569    cls.__class_vars__.update(class_vars) 
    570 
    571    for k in class_vars: 
    572        # Class vars should not be private attributes 
    573        #     We remove them _here_ and not earlier because we rely on inspecting the class to determine its classvars, 
    574        #     but private attributes are determined by inspecting the namespace _prior_ to class creation. 
    575        #     In the case that a classvar with a leading-'_' is defined via a ForwardRef (e.g., when using 
    576        #     `__future__.annotations`), we want to remove the private attribute which was detected _before_ we knew it 
    577        #     evaluated to a classvar 
    578 
    579        value = cls.__private_attributes__.pop(k, None) 
    580        if value is not None and value.default is not PydanticUndefined: 
    581            setattr(cls, k, value.default) 
    582 
    583 
    584def complete_model_class( 
    585    cls: type[BaseModel], 
    586    config_wrapper: ConfigWrapper, 
    587    ns_resolver: NsResolver, 
    588    *, 
    589    raise_errors: bool = True, 
    590    call_on_complete_hook: bool = True, 
    591    create_model_module: str | None = None, 
    592) -> bool: 
    593    """Finish building a model class. 
    594 
    595    This logic must be called after class has been created since validation functions must be bound 
    596    and `get_type_hints` requires a class object. 
    597 
    598    Args: 
    599        cls: BaseModel or dataclass. 
    600        config_wrapper: The config wrapper instance. 
    601        ns_resolver: The namespace resolver instance to use during schema building. 
    602        raise_errors: Whether to raise errors. 
    603        call_on_complete_hook: Whether to call the `__pydantic_on_complete__` hook. 
    604        create_model_module: The module of the class to be created, if created by `create_model`. 
    605 
    606    Returns: 
    607        `True` if the model is successfully completed, else `False`. 
    608 
    609    Raises: 
    610        PydanticUndefinedAnnotation: If `PydanticUndefinedAnnotation` occurs in`__get_pydantic_core_schema__` 
    611            and `raise_errors=True`. 
    612    """ 
    613    typevars_map = get_model_typevars_map(cls) 
    614 
    615    if not cls.__pydantic_fields_complete__: 
    616        # Note: when coming from `ModelMetaclass.__new__()`, this results in fields being built twice. 
    617        # We do so a second time here so that we can get the `NameError` for the specific undefined annotation. 
    618        # Alternatively, we could let `GenerateSchema()` raise the error, but there are cases where incomplete 
    619        # fields are inherited in `collect_model_fields()` and can actually have their annotation resolved in the 
    620        # generate schema process. As we want to avoid having `__pydantic_fields_complete__` set to `False` 
    621        # when `__pydantic_complete__` is `True`, we rebuild here: 
    622        try: 
    623            cls.__pydantic_fields__ = rebuild_model_fields( 
    624                cls, 
    625                config_wrapper=config_wrapper, 
    626                ns_resolver=ns_resolver, 
    627                typevars_map=typevars_map, 
    628            ) 
    629        except NameError as e: 
    630            exc = PydanticUndefinedAnnotation.from_name_error(e) 
    631            set_model_mocks(cls, f'`{exc.name}`') 
    632            if raise_errors: 
    633                raise exc from e 
    634 
    635        if not raise_errors and not cls.__pydantic_fields_complete__: 
    636            # No need to continue with schema gen, it is guaranteed to fail 
    637            return False 
    638 
    639        assert cls.__pydantic_fields_complete__ 
    640 
    641    gen_schema = GenerateSchema( 
    642        config_wrapper, 
    643        ns_resolver, 
    644        typevars_map, 
    645    ) 
    646 
    647    try: 
    648        schema = gen_schema.generate_schema(cls) 
    649    except PydanticUndefinedAnnotation as e: 
    650        if raise_errors: 
    651            raise 
    652        set_model_mocks(cls, f'`{e.name}`') 
    653        return False 
    654 
    655    core_config = config_wrapper.core_config(title=cls.__name__) 
    656 
    657    try: 
    658        schema = gen_schema.clean_schema(schema) 
    659    except InvalidSchemaError: 
    660        set_model_mocks(cls) 
    661        return False 
    662 
    663    # This needs to happen *after* model schema generation, as the return type 
    664    # of the properties are evaluated and the `ComputedFieldInfo` are recreated: 
    665    cls.__pydantic_computed_fields__ = {k: v.info for k, v in cls.__pydantic_decorators__.computed_fields.items()} 
    666 
    667    set_deprecated_descriptors(cls) 
    668 
    669    cls.__pydantic_core_schema__ = schema 
    670 
    671    cls.__pydantic_validator__ = create_schema_validator( 
    672        schema, 
    673        cls, 
    674        create_model_module or cls.__module__, 
    675        cls.__qualname__, 
    676        'create_model' if create_model_module else 'BaseModel', 
    677        core_config, 
    678        config_wrapper.plugin_settings, 
    679    ) 
    680    cls.__pydantic_serializer__ = SchemaSerializer(schema, core_config) 
    681 
    682    # set __signature__ attr only for model class, but not for its instances 
    683    # (because instances can define `__call__`, and `inspect.signature` shouldn't 
    684    # use the `__signature__` attribute and instead generate from `__call__`). 
    685    cls.__signature__ = LazyClassAttribute( 
    686        '__signature__', 
    687        partial( 
    688            generate_pydantic_signature, 
    689            init=cls.__init__, 
    690            fields=cls.__pydantic_fields__, 
    691            validate_by_name=config_wrapper.validate_by_name, 
    692            extra=config_wrapper.extra, 
    693        ), 
    694    ) 
    695 
    696    cls.__pydantic_complete__ = True 
    697 
    698    if call_on_complete_hook: 
    699        cls.__pydantic_on_complete__() 
    700 
    701    return True 
    702 
    703 
    704def set_deprecated_descriptors(cls: type[BaseModel]) -> None: 
    705    """Set data descriptors on the class for deprecated fields.""" 
    706    for field, field_info in cls.__pydantic_fields__.items(): 
    707        if (msg := field_info.deprecation_message) is not None: 
    708            desc = _DeprecatedFieldDescriptor(msg) 
    709            desc.__set_name__(cls, field) 
    710            setattr(cls, field, desc) 
    711 
    712    for field, computed_field_info in cls.__pydantic_computed_fields__.items(): 
    713        if ( 
    714            (msg := computed_field_info.deprecation_message) is not None 
    715            # Avoid having two warnings emitted: 
    716            and not hasattr(unwrap_wrapped_function(computed_field_info.wrapped_property), '__deprecated__') 
    717        ): 
    718            desc = _DeprecatedFieldDescriptor(msg, computed_field_info.wrapped_property) 
    719            desc.__set_name__(cls, field) 
    720            setattr(cls, field, desc) 
    721 
    722 
    723class _DeprecatedFieldDescriptor: 
    724    """Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field. 
    725 
    726    Attributes: 
    727        msg: The deprecation message to be emitted. 
    728        wrapped_property: The property instance if the deprecated field is a computed field, or `None`. 
    729        field_name: The name of the field being deprecated. 
    730    """ 
    731 
    732    field_name: str 
    733 
    734    def __init__(self, msg: str, wrapped_property: property | None = None) -> None: 
    735        self.msg = msg 
    736        self.wrapped_property = wrapped_property 
    737 
    738    def __set_name__(self, cls: type[BaseModel], name: str) -> None: 
    739        self.field_name = name 
    740 
    741    def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any: 
    742        if obj is None: 
    743            if self.wrapped_property is not None: 
    744                return self.wrapped_property.__get__(None, obj_type) 
    745            raise AttributeError(self.field_name) 
    746 
    747        warnings.warn(self.msg, DeprecationWarning, stacklevel=2) 
    748 
    749        if self.wrapped_property is not None: 
    750            return self.wrapped_property.__get__(obj, obj_type) 
    751        return obj.__dict__[self.field_name] 
    752 
    753    # Defined to make it a data descriptor and take precedence over the instance's dictionary. 
    754    # Note that it will not be called when setting a value on a model instance 
    755    # as `BaseModel.__setattr__` is defined and takes priority. 
    756    def __set__(self, obj: Any, value: Any) -> NoReturn: 
    757        raise AttributeError(self.field_name) 
    758 
    759 
    760class _PydanticWeakRef: 
    761    """Wrapper for `weakref.ref` that enables `pickle` serialization. 
    762 
    763    Cloudpickle fails to serialize `weakref.ref` objects due to an arcane error related 
    764    to abstract base classes (`abc.ABC`). This class works around the issue by wrapping 
    765    `weakref.ref` instead of subclassing it. 
    766 
    767    See https://github.com/pydantic/pydantic/issues/6763 for context. 
    768 
    769    Semantics: 
    770        - If not pickled, behaves the same as a `weakref.ref`. 
    771        - If pickled along with the referenced object, the same `weakref.ref` behavior 
    772          will be maintained between them after unpickling. 
    773        - If pickled without the referenced object, after unpickling the underlying 
    774          reference will be cleared (`__call__` will always return `None`). 
    775    """ 
    776 
    777    def __init__(self, obj: Any): 
    778        if obj is None: 
    779            # The object will be `None` upon deserialization if the serialized weakref 
    780            # had lost its underlying object. 
    781            self._wr = None 
    782        else: 
    783            self._wr = weakref.ref(obj) 
    784 
    785    def __call__(self) -> Any: 
    786        if self._wr is None: 
    787            return None 
    788        else: 
    789            return self._wr() 
    790 
    791    def __reduce__(self) -> tuple[Callable, tuple[weakref.ReferenceType | None]]: 
    792        return _PydanticWeakRef, (self(),) 
    793 
    794 
    795def build_lenient_weakvaluedict(d: dict[str, Any] | None) -> dict[str, Any] | None: 
    796    """Takes an input dictionary, and produces a new value that (invertibly) replaces the values with weakrefs. 
    797 
    798    We can't just use a WeakValueDictionary because many types (including int, str, etc.) can't be stored as values 
    799    in a WeakValueDictionary. 
    800 
    801    The `unpack_lenient_weakvaluedict` function can be used to reverse this operation. 
    802    """ 
    803    if d is None: 
    804        return None 
    805    result = {} 
    806    for k, v in d.items(): 
    807        try: 
    808            proxy = _PydanticWeakRef(v) 
    809        except TypeError: 
    810            proxy = v 
    811        result[k] = proxy 
    812    return result 
    813 
    814 
    815def unpack_lenient_weakvaluedict(d: dict[str, Any] | None) -> dict[str, Any] | None: 
    816    """Inverts the transform performed by `build_lenient_weakvaluedict`.""" 
    817    if d is None: 
    818        return None 
    819 
    820    result = {} 
    821    for k, v in d.items(): 
    822        if isinstance(v, _PydanticWeakRef): 
    823            v = v() 
    824            if v is not None: 
    825                result[k] = v 
    826        else: 
    827            result[k] = v 
    828    return result 
    829 
    830 
    831@cache 
    832def default_ignored_types() -> tuple[type[Any], ...]: 
    833    from ..fields import ComputedFieldInfo 
    834 
    835    ignored_types = [ 
    836        FunctionType, 
    837        property, 
    838        classmethod, 
    839        staticmethod, 
    840        PydanticDescriptorProxy, 
    841        ComputedFieldInfo, 
    842        TypeAliasType,  # from `typing_extensions` 
    843    ] 
    844 
    845    if sys.version_info >= (3, 12): 
    846        ignored_types.append(typing.TypeAliasType) 
    847 
    848    return tuple(ignored_types)