
    D6i                       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 ddlZddlmZ ddlmZ ddlmZ d	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      Zd Z G d d      Zy)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)AnyGenericTypeVarUnioncast)DeclarativeMeta)Session)ObjectDeletedError   )get_primary_keys
_LoadDataT
_ModelType)boundc                    t        t        j                  j                  d      d         dk\  rt	        t
        |       S t	        t        |       S )Nmarshmallowr      )int	importlibmetadataversionr   _LoadDataV4_LoadDataV3)datas    m/home/azureuser/techstart-app/venv/lib/python3.12/site-packages/marshmallow_sqlalchemy/load_instance_mixin.py
_cast_datar      s?    
9%%m4Q78A=K&&T""    c                  <    e Zd Z G d d      Z G d dee         Zy)LoadInstanceMixinc                  H     e Zd ZU ded<   ded<   ded<   ded<    fdZ xZS )	LoadInstanceMixin.Optsztype[DeclarativeMeta] | NonemodelSession | Nonesqla_sessionboolload_instance	transientc                    t        |   |g|i | t        |dd       | _        t        |dd       | _        t        |dd      | _        t        |dd      | _        y )Nr%   r'   r)   Fr*   )super__init__getattrr%   r'   r)   r*   )selfmetaargskwargs	__class__s       r   r-   zLoadInstanceMixin.Opts.__init__)   s\    GT3D3F3 w5DJ 'nd CD!(!FD$T;>DNr    )__name__
__module____qualname____annotations__r-   __classcell__r3   s   @r   Optsr$   #   s$    ++$$	? 	?r    r:   c                  :    e Zd ZU ded<   ded<   ded<   ded<   d	ed
<   edd       Zej                  dd       Zedd       Zej                  dd       Z fdZddZ	e
j                  dd       Zdddd	 	 	 	 	 	 	 	 	 d fdZdd	 	 	 	 	 d  fdZd Z xZS )!LoadInstanceMixin.Schemar$   opts_ModelType | Noneinstancer&   _sessionzbool | None
_transientr(   _load_instancec                J    | j                   xs | j                  j                  S )z+The SQLAlchemy session used to load models.)r@   r=   r'   r/   s    r   sessionz LoadInstanceMixin.Schema.session7   s     ==:DII$:$::r    c                    || _         y N)r@   )r/   rE   s     r   rE   z LoadInstanceMixin.Schema.session<   s	    #DMr    c                ^    | j                   | j                   S | j                  j                  S )z8Whether model instances are loaded in a transient state.)rA   r=   r*   rD   s    r   r*   z"LoadInstanceMixin.Schema.transient@   s(     *&99&&&r    c                    || _         y rG   )rA   )r/   r*   s     r   r*   z"LoadInstanceMixin.Schema.transientG   s	    'DOr    c                   |j                  dd       | _        |j                  dd       | _        |j                  dd       | _        |j                  d| j                  j
                        | _        t        |    |i | y )NrE   r?   r*   r)   )	popr@   r?   rA   r=   r)   rB   r,   r-   )r/   r1   r2   r3   s      r   r-   z!LoadInstanceMixin.Schema.__init__K   sh    "JJy$7DM"JJz48DM$jjd;DO"(**_dii>U>U"VDGd-f-r    c                   | j                   ryt        t        t           | j                  j
                        }t        |      }|D ci c](  }|j                  |j                  |j                        * }}d|j                         vr+	 t        t        | j                        j                  ||      S yc c}w # t        $ r Y yw xY w)zRetrieve an existing record by primary key(s). If the schema instance
            is transient, return `None`.

            :param data: Serialized data to inform lookup.
            N)r*   r   typer   r=   r%   r   keygetvaluesr   rE   r   )r/   r   r%   propspropfilterss         r   get_instancez%LoadInstanceMixin.Schema.get_instanceR   s     ~~j)499??;E$U+E@EFtxx$((!33FGF7>>++ 6::5'JJ  G *   s   -B5
)B: :	CCc                |   | j                   s|S | j                  xs | j                  |      }|'|j                         D ]  \  }}t	        |||        |S | j                  |      \  }}t        t        | j                  j                        } |di |}|j                         D ]  \  }}t	        |||        |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.
             )
rB   r?   rT   itemssetattr_split_model_kwargs_associationr   r   r=   r%   )	r/   r   r2   r?   rN   valueassociation_attrs
ModelClassattrs	            r   make_instancez&LoadInstanceMixin.Schema.make_instanced   s     &&}}?(9(9$(?H#"&**, 2JCHc512(,(L(LT(R%F%otyy?J!+F+H0668 /e$./Or    NF)rE   r?   r*   c                  |xs | j                   | _         |xs | j                  | _        | j                  r#| j                  s| j                  st        d      |xs | j                  | _        	  t        t        j                  t                     j                  t        |      fi |d| _        S # d| _        w xY 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 sessionN)r@   rA   rB   r*   rE   
ValueErrorr?   r   maSchemar,   loadr   )r/   r   rE   r?   r*   r2   r3   s         r   rc   zLoadInstanceMixin.Schema.load{   s    $ $4t}}DM':4??DO""DNNdll !EFF$5DM%4tBIIuw/44Z5EPP $s   1;B4 4	B=)rE   c                   |xs | j                   | _         | j                  s| j                  st        d       t	        t
        j                  t                     j                  t        |      fi |S )zGSame as `marshmallow.Schema.validate` but allows passing a ``session``.zValidation requires a session)
r@   r*   rE   r`   r   ra   rb   r,   validater   )r/   r   rE   r2   r3   s       r   re   z!LoadInstanceMixin.Schema.validate   sX     $4t}}DMNNdll !@AA44		57+44Z5EPPPr    c                L   |j                         D ci c]3  \  }}t        t        | j                  j                  |d      d      r||5 }}}|j                         D ci c],  \  }}t        | j                  j                  |      r||vr||. }}}||fS c c}}w c c}}w )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.
            Nremote_attr)rW   hasattrr.   r=   r%   )r/   r   rN   rZ   r[   r2   s         r   rY   z8LoadInstanceMixin.Schema._split_model_kwargs_association   s     #'**,!C7499??C>N U
! ! #'**,CDIIOOS1cAR6R U
F 
 ,,,!s   8B"1B )returnr&   )rE   r   ri   None)ri   r(   )r*   r(   ri   rj   )ri   r>   )ri   r   )
r   r   rE   r&   r?   r>   r*   r(   ri   r   )r   r   rE   r&   ri   zdict[str, list[str]])r4   r5   r6   r7   propertyrE   setterr*   r-   rT   ra   	post_loadr^   rc   re   rY   r8   r9   s   @r   rb   r<   0   s   $$##  		; 
	; 
	$ 
	$ 
	' 
	' 
			( 
	(	.	$ 
	 
	4 '+*.#	%	% $		%
 (	% 	% 	%@ '+		Q	Q $		Q "	Q	-r    rb   N)r4   r5   r6   r:   r   r   rb   rV   r    r   r"   r"   "   s    ? ?K-$ K-r    r"   ) __doc__
__future__r   importlib.metadatar   collections.abcr   r   r   typingr   r   r	   r
   r   r   ra   sqlalchemy.ext.declarativer   sqlalchemy.ormr   sqlalchemy.orm.excr   fieldsr   strr   r   r   r   r   r"   rV   r    r   <module>rx      s    #  7 7 5 5  6 " 1 $GCH%xS0A'BBCGCH%xS0A'BBC\;<
\9
#Y- Y-r    