o
    KDi]F                     @  s  U d dl mZ d dlZd dlZd dlZd dlmZmZmZm	Z	m
Z
mZmZ z
d dlmZmZ W n ey@   d dlmZmZ Y nw d dlZd dlZd dlmZmZ d dlmZmZmZ d dlmZ dd	lmZ dd
lmZm Z  erd dl!m"Z" d dl#m$Z$ d dlm%Z% d dl&m'Z' e%ej(B Z)de*d< eg ej+f Z,de*d< edege
e-ej+ e,f f Z.de*d< d,ddZ/dd Z0d-ddZ1d-dd Z2d.d%d&Z3d/d)d*Z4G d+d dZ5e5 Z6e6j7Z7e6j8Z8e6j9Z9e6j:Z:dS )0    )annotationsN)TYPE_CHECKINGAnyCallableLiteralUnioncastoverload)	TypeAlias	TypeGuard)fieldsvalidate)mssqlmysql
postgresql)SynonymProperty   )ModelConversionError)RelatedRelatedList)Iterable)DeclarativeMeta)MapperProperty)
TypeEnginer
   PropertyOrColumn_FieldPartialModelConverter_FieldClassFactoryvaluer   returnTypeGuard[type[fields.Field]]c                 C  s   t | to
t| tjS N)
isinstancetype
issubclassr   Field)r    r&   W/var/www/Datamplify/venv/lib/python3.10/site-packages/marshmallow_sqlalchemy/convert.py	_is_field/      r(   c                 C  s(   | | j vrt| j dkr| j \}|S | S )zUnwrap proxied columnsr   )base_columnslen)columnbaser&   r&   r'   _base_column3   s   r.   boolc                 C  s   | j d up| jd upt| S r!   )defaultserver_default_is_auto_incrementr,   r&   r&   r'   _has_default;   s
   
r4   c                 C  s   | j d uo
| | j ju S r!   )table_autoincrement_columnr3   r&   r&   r'   r2   C   r)   r2   	converter	data_typepostgresql.ARRAYCallable[[], fields.List]c                 C  s`   |  |j}| }|jr|jdkrttj|S |j}t|d D ]}t|}q!ttj|S )Nr   )_get_field_class_for_data_type	item_type
dimensions	functoolspartialr   Listrange)r7   r8   
FieldClassinnerr=   _r&   r&   r'   _list_field_factoryG   s   rE   sa.EnumCallable[[], fields.Field]c                 C  s   |j rtjtj|j dS tjS )N)enum)
enum_classr>   r?   r   EnumRaw)r7   r8   r&   r&   r'   _enum_field_factoryW   s
   rL   c                   @  sp  e Zd ZU dZi ejeejej	ej
eejej	ejejejejejejejejejejejejejej	ejej	ejej	ej
eejejejejejejejejejejej ej!ej"ej#ej$ejej%ej&e'jeje'j(ejiZ)de*d< ddddZ+d[d\d
dZ,e-d]ddZ.ddddde/dd^ddZ0dddde/d d_d#d$Z1e2d%d%d&d`d.d/Z3e2d%d%d&dad2d/Z3ddd&dbd4d/Z3e2d%d5dcd6d7Z4e2d%d5ddd8d7Z4dd5ded9d7Z4e2d%d%d&dfd<d=Z5e2d%dd&dgd>d=Z5ddd&dhd?d=Z5didBdCZ6djdFdGZ7dkdJdKZ8dldLdMZ9dmdOdPZ:dndSdTZ;dodUdVZ<		dpdqdWdXZ=dYdZ Z>dS )rr   zxConverts a SQLAlchemy model into a dictionary of corresponding
    marshmallow `Fields <marshmallow.fields.Field>`.
    z?dict[type[TypeEngine], type[fields.Field] | _FieldClassFactory]SQLA_TYPE_MAPPINGFT)	MANYTOONE
MANYTOMANY	ONETOMANYN
schema_clstype[ma.Schema] | Nonec                 C  s
   || _ d S r!   )rQ   )selfrQ   r&   r&   r'   __init__      
zModelConverter.__init__r   dict[type, type[fields.Field]]c                 C  s   | j r| j jS tjjS r!   )rQ   TYPE_MAPPINGmaSchemarS   r&   r&   r'   type_mapping   s   zModelConverter.type_mapping)
include_fkinclude_relationshipsr   excludebase_fieldsdict_clsmodeltype[DeclarativeMeta]r\   r/   r]   r   Iterable[str] | Noner^   r_   dict | Noner`   
type[dict]dict[str, fields.Field]c                C  s   | }|pi }t |jD ]E}	| |	}
| j|	||dr!d||
< qt|	tr'qt|	dr:|s:|	jD ]}|j	s8 nq1q|sBt|	drBq|
|
pK| |	}|rR|||
< q|S )a  Generate a dict of field_name: `marshmallow.fields.Field` pairs for the given model.
        Note: SynonymProperties are ignored. Use an explicit field if you want to include a synonym.

        :param model: The SQLAlchemy model
        :param bool include_fk: Whether to include foreign key fields in the output.
        :param bool include_relationships: Whether to include relationships fields in the output.
        :return: dict of field_name: Field instance pairs
        r   r^   Ncolumns	direction)sainspectattrs_get_field_name_should_exclude_fieldr"   r   hasattrrh   foreign_keysgetproperty2field)rS   ra   r\   r]   r   r^   r_   r`   resultpropkeyr,   fieldr&   r&   r'   fields_for_model   s.   



zModelConverter.fields_for_model)r\   r   r^   r_   r`   r5   sa.Tablec                C  sn   | }|pi }|j D ]*}| |}	| j|||drd ||	< q
|s$|jr$q
||	p-| |}
|
r4|
||	< q
|S )Nrg   )rh   rm   rn   rp   rq   column2field)rS   r5   r\   r   r^   r_   r`   rs   r,   ru   rv   r&   r&   r'   fields_for_table   s   



zModelConverter.fields_for_table.instancefield_classrt   r   r|   Literal[True]r}   type[fields.Field] | Nonefields.Fieldc                K     d S r!   r&   rS   rt   r|   r}   kwargsr&   r&   r'   rr         zModelConverter.property2fieldLiteral[False]type[fields.Field]c                K  r   r!   r&   r   r&   r&   r'   rr      r   !fields.Field | type[fields.Field]c          	      K  s   dD ]}t ||d}|dur|}q|p| |}|s|S | |}|| |di |}t|drL| j|jj rL|jdu rLt	|fi i | 
 |}|S )a  Convert a SQLAlchemy `Property` to a field instance or class.

        :param Property prop: SQLAlchemy Property.
        :param bool instance: If `True`, return  `Field` instance, computing relevant kwargs
            from the given property. If `False`, return the `Field` class.
        :param kwargs: Additional keyword arguments to pass to the field constructor.
        :return: A `marshmallow.fields.Field` class or instance.
        )_proxied_property_proxied_objectNri   Tr&   )getattr_get_field_class_for_property_get_field_kwargs_for_propertyupdatero   DIRECTION_MAPPINGri   nameuselistr   get_base_kwargs)	rS   rt   r|   r}   r   attrproxied_objfield_kwargsretr&   r&   r'   rr      s$   


)r|   c                K  r   r!   r&   rS   r,   r|   r   r&   r&   r'   ry        zModelConverter.column2fieldc                K  r   r!   r&   r   r&   r&   r'   ry     r   c                K  s<   |  |}|s	|S |  }| || |di i ||S )a  Convert a SQLAlchemy `Column <sqlalchemy.schema.Column>` to a field instance or class.

        :param sqlalchemy.schema.Column column: SQLAlchemy Column.
        :param bool instance: If `True`, return  `Field` instance, computing relevant kwargs
            from the given property. If `False`, return the `Field` class.
        :return: A `marshmallow.fields.Field` class or instance.
        Nr&   )_get_field_class_for_columnr   _add_column_kwargs)rS   r,   r|   r   r}   r   r&   r&   r'   ry     s   

property_namestrc                K  r   r!   r&   rS   ra   r   r|   r}   r   r&   r&   r'   	field_for*     	zModelConverter.field_forc                K  r   r!   r&   r   r&   r&   r'   r   5  r   c                K  s   |}|}t ||}d}	t|dr|j}|j}|jjj}	t|j	
|}
| j|
f|r,dnd|d|}|	rDt|fi i |  |S |S )a  Convert a property for a mapped SQLAlchemy class to a marshmallow `Field`.
        Example: ::

            date_created = field_for(Author, "date_created", dump_only=True)
            author = field_for(Book, "author")

        :param type model: A SQLAlchemy mapped class.
        :param str property_name: The name of the property to convert.
        :param kwargs: Extra keyword arguments to pass to `property2field`
        :return: A `marshmallow.fields.Field` class or instance.
        Fremote_attrTr{   )r   ro   target_class
value_attr
local_attrrt   r   rj   rk   rl   rq   rr   r   r   )rS   ra   r   r|   r}   r   target_model	prop_namer   remote_with_local_multiplicityrt   converted_propr&   r&   r'   r   @  s(   



prop_or_columnr   c                 C  s   |j S r!   )ru   )rS   r   r&   r&   r'   rm   h  s   zModelConverter._get_field_namer,   	sa.Columnc                 C  s   |  |jS r!   )r;   r#   )rS   r,   r&   r&   r'   r   k  s   z*ModelConverter._get_field_class_for_columnr8   r   c                 C  s   d }t t|}|D ]}|| jv r(| j| }t|r|}ntd|| |} n2qz|j}W n ty9   d }Y nw || jv rE| j| }nt	|drP| 
|jS td|d  dtd|S )Nr   implz$Could not find field column of type r   .r   )rk   getmror#   rM   r(   r   python_typeNotImplementedErrorr[   ro   r;   r   r   )rS   r8   	field_clstypescol_typefield_or_factoryr   r&   r&   r'   r;   n  s2   





z-ModelConverter._get_field_class_for_data_typec                 C  s.   t |dr	t}|S t|jd }| |}|S )Nri   r   )ro   r   r.   rh   r   )rS   rt   r   r,   r&   r&   r'   r     s   

z,ModelConverter._get_field_class_for_propertydict[str, Any]c                 C  sd   |   }t|drt|jd }| || |}t|dr#| || t|dd r0|j|d d< |S )Nrh   r   ri   docmetadatadescription)r   ro   r.   rh   r   _add_relationship_kwargsr   r   )rS   rt   r   r,   r&   r&   r'   r     s   

z-ModelConverter._get_field_kwargs_for_propertyr   Nonec              	   C  s*  t |dr|jrd|d< |j ot| |d< nd|d< t |jdr/|jjdur/|jj|d< nt |jd	rG|dsG|d
 tj|jj	d t |jdr|ds|jj
}|durz|jj}W n ttfym   d}Y nw |rvt|tjs|d
 tj|d t|jddrt|jdd|d< dS dS )zwAdd keyword arguments to kwargs (in-place) based on the passed in
        `Column <sqlalchemy.schema.Column>`.
        nullableT
allow_nonerequired	dump_onlyrI   NrH   enumsr   )choiceslength)max	asdecimalFscaleplaces)ro   r   r4   r#   rI   rq   appendr   OneOfr   r   r   AttributeErrorr   r$   uuidUUIDLengthr   )rS   r   r,   column_lengthr   r&   r&   r'   r     s,   
z!ModelConverter._add_column_kwargsc                 C  sT   d}|j D ]}|d js|jdu s| j|jj du rd} nq||| d dS )zkAdd keyword arguments to kwargs (in-place) based on the passed in
        relationship `Property`.
        Tr   F)r   r   N)local_remote_pairsr   r   r   ri   r   r   )rS   r   rt   r   pairr&   r&   r'   r     s   


z'ModelConverter._add_relationship_kwargsc                 C  s*   |  |}|r||vrdS t|o||v S )NT)rm   r/   )rS   r,   r   r^   ru   r&   r&   r'   rn     s   
z$ModelConverter._should_exclude_fieldc                 C  s
   g i dS )N)r   r   r&   rZ   r&   r&   r'   r     rU   zModelConverter.get_base_kwargsr!   )rQ   rR   )r   rV   )ra   rb   r\   r/   r]   r/   r   rc   r^   rc   r_   rd   r`   re   r   rf   )r5   rx   r\   r/   r   rc   r^   rc   r_   rd   r`   re   r   rf   )rt   r   r|   r~   r}   r   r   r   )rt   r   r|   r   r}   r   r   r   )rt   r   r|   r/   r}   r   r   r   )r|   r~   r   r   )r|   r   r   r   )r|   r/   r   r   )
ra   rb   r   r   r|   r~   r}   r   r   r   )
ra   rb   r   r   r|   r   r}   r   r   r   )
ra   rb   r   r   r|   r/   r}   r   r   r   )r   r   r   r   )r,   r   r   r   )r8   r   r   r   )r   r   )rt   r   r   r   )r   r   r,   r   r   r   )r   r   rt   r   r   r   )NN)r,   r   r   rc   r^   rc   r   r/   )?__name__
__module____qualname____doc__rj   rJ   rL   JSONr   rK   ARRAYrE   
PickleTyper   BITIntegerOIDr   MACADDRStringINETCIDRJSONBHSTOREMONEYDecimalDATEDateTIMETimer   YEARSETr@   ENUMr%   INTEGERDATETIMEDateTimer   UNIQUEIDENTIFIERrM   __annotations__r   rT   propertyr[   dictrw   rz   r	   rr   ry   r   rm   r   r;   r   r   r   r   rn   r   r&   r&   r&   r'   r   a   s   
 	

	2	$

(


!
	

")r   r   r   r    )r   r/   )r7   r   r8   r9   r   r:   )r7   r   r8   rF   r   rG   );
__future__r   r>   rk   r   typingr   r   r   r   r   r   r	   r
   r   ImportErrortyping_extensionsmarshmallowrX   
sqlalchemyrj   r   r   sqlalchemy.dialectsr   r   r   sqlalchemy.ormr   
exceptionsr   r   r   collections.abcr   sqlalchemy.ext.declarativer   r   sqlalchemy.typesr   Columnr   r   r%   r   r#   r   r(   r.   r4   r2   rE   rL   r   default_converterrw   rr   ry   r   r&   r&   r&   r'   <module>   sT    $





   
