o
    KDi(                     @  s.  d dl mZ d dlZd dlmZmZmZ d dlZd dl	m
Z
 d dlmZmZmZmZ ddlmZ ddlmZ dd	lmZmZ erFd d
lmZ G dd de
ZG dd dejeZG dd deZG dd deZG dd deZG dd deje eedZG dd dee edZ 	d$dddd%d"d#Z!dS )&    )annotationsN)TYPE_CHECKINGAnycast)Field)Schema
SchemaMeta
SchemaOpts_get_fields   )ModelConverterIncorrectSchemaTypeError)LoadInstanceMixin
_ModelType)DeclarativeMetac                      s<   e Zd Zddddd fddZdddZdddZ  ZS )SQLAlchemyAutoFieldN)column_namemodeltabler   
str | Noner   type[DeclarativeMeta] | Noner   sa.Table | Nonefield_kwargsdict[str, Any]c                  s6   t    |r|rtd|| _|| _|| _|| _d S )Nz-Cannot pass both `model` and `table` options.)super__init__
ValueErrorr   r   r   r   )selfr   r   r   r   	__class__ V/var/www/Datamplify/venv/lib/python3.10/site-packages/marshmallow_sqlalchemy/schema.pyr      s   

zSQLAlchemyAutoField.__init__schema_optsSQLAlchemySchemaOptsstr	converterr   c                 C  sb   | j p|j }|r|j||fi | jS | jd ur| jn|j}ttd|j|}|j|fi | jS )Nzsa.Table)r   	field_forr   r   getattrr   columnscolumn2field)r   r#   r   r&   r   r   columnr!   r!   r"   create_field'   s   z SQLAlchemyAutoField.create_field
field_nameparentSchema | FieldreturnNonec                 C  s   t d| d)Nz0Cannot bind SQLAlchemyAutoField. Make sure that z/ is a SQLAlchemySchema or SQLAlchemyAutoSchema.r   )r   r-   r.   r!   r!   r"   _bind_to_schema6   s   
z#SQLAlchemyAutoField._bind_to_schema)r   r   r   r   r   r   r   r   )r#   r$   r   r%   r&   r   )r-   r%   r.   r/   r0   r1   )__name__
__module____qualname__r   r,   r2   __classcell__r!   r!   r   r"   r      s    
r   c                      s2   e Zd ZU dZded< ded<  fddZ  ZS )r$   a5  Options class for `SQLAlchemySchema`.
    Adds the following options:

    - ``model``: The SQLAlchemy model to generate the `Schema` from (mutually exclusive with ``table``).
    - ``table``: The SQLAlchemy table to generate the `Schema` from (mutually exclusive with ``model``).
    - ``load_instance``: Whether to load model instances.
    - ``sqla_session``: SQLAlchemy session to be used for deserialization.
        This is only needed when ``load_instance`` is `True`. You can also pass a session to the Schema's `load` method.
    - ``transient``: Whether to load model instances in a transient state (effectively ignoring the session).
        Only relevant when ``load_instance`` is `True`.
    - ``model_converter``: `ModelConverter` class to use for converting the SQLAlchemy model to marshmallow fields.
    r   r   ztype[ModelConverter]model_converterc                   sV   t  j|g|R i | t|dd | _| jd ur"| jd ur"tdt|dt| _d S )Nr   z,Cannot set both `model` and `table` options.r7   )r   r   r(   r   r   r   r   r7   r   metaargskwargsr   r!   r"   r   M   s
   zSQLAlchemySchemaOpts.__init__r3   r4   r5   __doc____annotations__r   r6   r!   r!   r   r"   r$   <   s
   
 r$   c                      s2   e Zd ZU dZded< ded<  fddZ  ZS )SQLAlchemyAutoSchemaOptsa  Options class for `SQLAlchemyAutoSchema`.
    Has the same options as `SQLAlchemySchemaOpts`, with the addition of:

    - ``include_fk``: Whether to include foreign fields; defaults to `False`.
    - ``include_relationships``: Whether to include relationships; defaults to `False`.
    bool
include_fkinclude_relationshipsc                   sV   t  j|g|R i | t|dd| _t|dd| _| jd ur'| jr)tdd S d S )NrA   FrB   z6Cannot set `table` and `include_relationships = True`.)r   r   r(   rA   rB   r   r   r8   r   r!   r"   r   a   s   z!SQLAlchemyAutoSchemaOpts.__init__r<   r!   r!   r   r"   r?   V   s
   
 r?   c                      sP   e Zd Zeefd fdd	ZedddZedddZedddZ	  Z
S )SQLAlchemySchemaMeta
cls_fieldslist[tuple[str, Field]]inherited_fieldsdict_cls
type[dict]r0   dict[str, Field]c           	   	     sd   |j }|j}||d}t ||| j|||d|}|| |||| || |||| |S )N)
schema_cls)optsklass)rK   r7   r   get_declared_fields_maybe_filter_foreign_keysupdateget_declared_sqla_fieldsget_auto_fields)	mcsrL   rD   rF   rG   rK   	Converterr&   fieldsr   r!   r"   rM   j   s   
z(SQLAlchemySchemaMeta.get_declared_fieldsbase_fieldsr&   r   rK   r   c                 C  s   i S Nr!   )rR   rU   r&   rK   rG   r!   r!   r"   rP      s   z-SQLAlchemySchemaMeta.get_declared_sqla_fieldsrT   c                   s   | fdd|  D S )Nc                   s:   i | ]\}}t |tr|jvr|||jp| qS r!   )
isinstancer   excluder,   r   ).0r-   fieldr&   rK   r!   r"   
<dictcomp>   s    
z8SQLAlchemySchemaMeta.get_auto_fields.<locals>.<dictcomp>)items)rR   rT   r&   rK   rG   r!   r[   r"   rQ      s
   z$SQLAlchemySchemaMeta.get_auto_fieldsr$   rL   r   c                  s   |j d us
|jd urTt|dr|jdu r| S dd t|j p |jjD dd t|D }t  |D ]}t	|d|j
} dd	 t|D  q4 fd
d| D S | S )NrA   Tc                 S  s   h | ]}|j r|jqS r!   )foreign_keyskey)rY   r+   r!   r!   r"   	<setcomp>   s    zBSQLAlchemySchemaMeta._maybe_filter_foreign_keys.<locals>.<setcomp>c                 S  s$   g | ]}t |trt |ts|qS r!   )
issubclassr   SQLAlchemyAutoSchema)rY   baser!   r!   r"   
<listcomp>   s    zCSQLAlchemySchemaMeta._maybe_filter_foreign_keys.<locals>.<listcomp>_declared_fieldsc                 s  s    | ]\}}|V  qd S rV   r!   )rY   name_r!   r!   r"   	<genexpr>   s    zBSQLAlchemySchemaMeta._maybe_filter_foreign_keys.<locals>.<genexpr>c                   s(   g | ]\}}|vs| v r||fqS r!   r!   )rY   rf   rZ   declared_fieldsr^   r!   r"   rd      s
    )r   r   hasattrrA   sainspectr)   getmrosetr(   __dict__rO   r
   )rT   rK   rL   non_auto_schema_basesrc   rU   r!   ri   r"   rN      s"   z/SQLAlchemySchemaMeta._maybe_filter_foreign_keys)rD   rE   rF   rE   rG   rH   r0   rI   )
rU   rI   r&   r   rK   r   rG   rH   r0   rI   )
rT   rI   r&   r   rK   r   rG   rH   r0   rI   )rT   rE   rK   r$   rL   r   r0   rE   )r3   r4   r5   classmethoddictrM   rP   rQ   staticmethodrN   r6   r!   r!   r   r"   rC   i   s    	rC   c                   @  s   e Zd ZedddZdS )SQLAlchemyAutoSchemaMetar&   r   c                 C  sn   | }|j d ur||j|j |j|j|j||d |S |jd ur5||j|j|j|j|j|j||d |S )N)rT   rX   rA   rU   rG   )rT   rX   rA   rB   rU   rG   )	r   rO   fields_for_tablerT   rX   rA   r   fields_for_modelrB   )clsrU   r&   rK   rG   rT   r!   r!   r"   rP      s4   

z1SQLAlchemyAutoSchemaMeta.get_declared_sqla_fieldsN)r&   r   )r3   r4   r5   rr   rP   r!   r!   r!   r"   ru      s    ru   c                   @     e Zd ZdZeZdS )SQLAlchemySchemaa  Schema for a SQLAlchemy model or table.
    Use together with `auto_field` to generate fields from columns.

    Example: ::

        from marshmallow_sqlalchemy import SQLAlchemySchema, auto_field

        from mymodels import User


        class UserSchema(SQLAlchemySchema):
            class Meta:
                model = User

            id = auto_field()
            created_at = auto_field(dump_only=True)
            name = auto_field()
    N)r3   r4   r5   r=   r$   OPTIONS_CLASSr!   r!   r!   r"   rz          rz   )	metaclassc                   @  ry   )rb   a  Schema that automatically generates fields from the columns of
     a SQLAlchemy model or table.

    Example: ::

        from marshmallow_sqlalchemy import SQLAlchemyAutoSchema, auto_field

        from mymodels import User


        class UserSchema(SQLAlchemyAutoSchema):
            class Meta:
                model = User
                # OR
                # table = User.__table__

            created_at = auto_field(dump_only=True)
    N)r3   r4   r5   r=   r?   r{   r!   r!   r!   r"   rb      r|   rb   )r   r   r   r   r   r   r   r   r0   c                K  s$   | dur
| d|  t| |||dS )a-  Mark a field to autogenerate from a model or table.

    :param column_name: Name of the column to generate the field from.
        If ``None``, matches the field name. If ``attribute`` is unspecified,
        ``attribute`` will be set to the same value as ``column_name``.
    :param model: Model to generate the field from.
        If ``None``, uses ``model`` specified on ``class Meta``.
    :param table: Table to generate the field from.
        If ``None``, uses ``table`` specified on ``class Meta``.
    :param kwargs: Field argument overrides.
    N	attribute)r   r   r   r   )
setdefaultr   )r   r   r   r;   r!   r!   r"   
auto_field  s
   r   rV   )r   r   r   r   r   r   r0   r   )"
__future__r   rm   typingr   r   r   
sqlalchemyrl   marshmallow.fieldsr   marshmallow.schemar   r   r	   r
   convertr   
exceptionsr   load_instance_mixinr   r   sqlalchemy.ext.declarativer   r   Optsr$   r?   rC   ru   rz   rb   r   r!   r!   r!   r"   <module>   s6    (Z
 
