o
    KDi                     @  s   d Z ddlmZ ddlZddlmZmZmZ ddl	m
Z
mZmZmZmZmZ ddlZddlmZ ddlmZ dd	lmZ e
rDdd
lmZ eeeef eeeef  f Zeeeef eeeef  f ZedeeZededZdd ZG dd dZ dS )zMixin that adds model instance loading behavior.

.. warning::

    This module is treated as private API.
    Users should not need to use this module directly.
    )annotationsN)IterableMappingSequence)TYPE_CHECKINGAnyGenericTypeVarUnioncast)DeclarativeMeta)ObjectDeletedError   )get_primary_keys)Session
_LoadDataT
_ModelType)boundc                 C  s,   t tjdd dkrtd| S td| S )Nmarshmallowr      _LoadDataV4_LoadDataV3)int	importlibmetadataversionr   data r   c/var/www/Datamplify/venv/lib/python3.10/site-packages/marshmallow_sqlalchemy/load_instance_mixin.py
_cast_data   s   

r    c                   @  s.   e Zd ZG dd dZG dd dee ZdS )LoadInstanceMixinc                      s>   e Zd ZU ded< ded< ded< ded<  fdd	Z  ZS )
LoadInstanceMixin.Optsztype[DeclarativeMeta] | NonemodelSession | Nonesqla_sessionboolload_instance	transientc                   sV   t  j|g|R i | t|dd | _t|dd | _t|dd| _t|dd| _d S )Nr#   r%   r'   Fr(   )super__init__getattrr#   r%   r'   r(   )selfmetaargskwargs	__class__r   r   r*   +   s
   zLoadInstanceMixin.Opts.__init__)__name__
__module____qualname____annotations__r*   __classcell__r   r   r0   r   Opts%   s   
 r7   c                      s   e Zd ZU ded< ded< ded< ded< d	ed
< ed+ddZejd,ddZed-ddZejd.ddZ fddZd/ddZ	e
jd0ddZddddd1 fd#d$Zdd%d2 fd'd(Zd)d* Z  ZS )3zLoadInstanceMixin.Schemar"   opts_ModelType | Noneinstancer$   _sessionzbool | None
_transientr&   _load_instancereturnc                 C  s   | j p| jjS )z+The SQLAlchemy session used to load models.)r;   r8   r%   r,   r   r   r   session9   s   z LoadInstanceMixin.Schema.sessionr@   r   Nonec                 C  
   || _ d S N)r;   )r,   r@   r   r   r   r@   >      
c                 C  s   | j dur| j S | jjS )z8Whether model instances are loaded in a transient state.N)r<   r8   r(   r?   r   r   r   r(   B   s   
z"LoadInstanceMixin.Schema.transientr(   c                 C  rB   rC   )r<   )r,   r(   r   r   r   r(   I   rD   c                   sR   | dd | _| dd | _| dd | _| d| jj| _t j|i | d S )Nr@   r:   r(   r'   )	popr;   r:   r<   r8   r'   r=   r)   r*   )r,   r.   r/   r0   r   r   r*   M   s
   z!LoadInstanceMixin.Schema.__init__c                   sn   | j rdS td| jj}t|} fdd|D }d| vr5ztd| j||W S  ty4   Y dS w dS )zRetrieve an existing record by primary key(s). If the schema instance
            is transient, return `None`.

            :param data: Serialized data to inform lookup.
            Nztype[_ModelType]c                   s   i | ]
}|j  |j qS r   )keyget).0propr   r   r   
<dictcomp>^   s    z9LoadInstanceMixin.Schema.get_instance.<locals>.<dictcomp>r   )	r(   r   r8   r#   r   valuesr@   rG   r   )r,   r   r#   propsfiltersr   r   r   get_instanceT   s   z%LoadInstanceMixin.Schema.get_instancer   c           	      K  s   | j s|S | jp| |}|dur"| D ]
\}}t||| q|S | |\}}td| jj}|di |}| D ]
\}}t||| q;|S )a  Deserialize data to an instance of the model if self.load_instance is True.

            Update an existing row if specified in `self.instance` or loaded by primary
            key(s) in the data; else create a new row.

            :param data: Data to deserialize.
            Nr   r   )	r=   r:   rN   itemssetattr_split_model_kwargs_associationr   r8   r#   )	r,   r   r/   r:   rF   valueassociation_attrs
ModelClassattrr   r   r   make_instancef   s   	z&LoadInstanceMixin.Schema.make_instanceNF)r@   r:   r(   r   r   r   c                  sn   |p| j | _ |p
| j| _| jr| js| jstd|p| j| _ztdt j	t
|fi |W d| _S d| _w )a  Deserialize data. If ``load_instance`` is set to `True`
            in the schema meta options, load the data as model instance(s).

            :param data: The data to deserialize.
            :param session: SQLAlchemy `session <sqlalchemy.orm.Session>`.
            :param instance: Existing model instance to modify.
            :param transient: If `True`, load transient model instance(s).
            :param kwargs: Same keyword arguments as `marshmallow.Schema.load`.
            z"Deserialization requires a session	ma.SchemaN)r;   r<   r=   r(   r@   
ValueErrorr:   r   r)   loadr    )r,   r   r@   r:   r(   r/   r0   r   r   rY   }   s   zLoadInstanceMixin.Schema.load)r@   dict[str, list[str]]c                  s>   |p| j | _ | js| jstdtdt jt|fi |S )zGSame as `marshmallow.Schema.validate` but allows passing a ``session``.zValidation requires a sessionrW   )r;   r(   r@   rX   r   r)   validater    )r,   r   r@   r/   r0   r   r   r[      s   z!LoadInstanceMixin.Schema.validatec                   s6   fdd|  D   fdd|  D }| fS )a$  Split serialized attrs to ensure association proxies are passed separately.

            This is necessary for Python < 3.6.0, as the order in which kwargs are passed
            is non-deterministic, and associations must be parsed by sqlalchemy after their
            intermediate relationship, unless their `creator` has been set.

            Ignore invalid keys at this point - behaviour for unknowns should be
            handled elsewhere.

            :param data: serialized dictionary of attrs to split on association_proxy.
            c                   s,   i | ]\}}t t jj|d dr||qS )Nremote_attr)hasattrr+   r8   r#   rH   rF   rR   r?   r   r   rJ      s    zLLoadInstanceMixin.Schema._split_model_kwargs_association.<locals>.<dictcomp>c                   s,   i | ]\}}t jj|r| vr||qS r   )r]   r8   r#   r^   rS   r,   r   r   rJ      s    )rO   )r,   r   r/   r   r_   r   rQ      s   
z8LoadInstanceMixin.Schema._split_model_kwargs_association)r>   r$   )r@   r   r>   rA   )r>   r&   )r(   r&   r>   rA   )r>   r9   )r>   r   )
r   r   r@   r$   r:   r9   r(   r&   r>   r   )r   r   r@   r$   r>   rZ   )r2   r3   r4   r5   propertyr@   setterr(   r*   rN   ma	post_loadrV   rY   r[   rQ   r6   r   r   r0   r   Schema2   s2   
 
 rd   N)r2   r3   r4   r7   r   r   rd   r   r   r   r   r!   $   s    r!   )!__doc__
__future__r   importlib.metadatar   collections.abcr   r   r   typingr   r   r   r	   r
   r   r   rb   sqlalchemy.ext.declarativer   sqlalchemy.orm.excr   fieldsr   sqlalchemy.ormr   strr   r   r   r   r    r!   r   r   r   r   <module>   s"       