o
    [h,                  	   @   s   d 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 ddlm	Z	 d	Z
d
d ZG dd deZG dd dZG dd deZ							dddZdedddddddf	ddZdS )z8
Tools for generating forms based on SQLAlchemy models.
    N)fields)
validators)Form   QuerySelectFieldQuerySelectMultipleField)model_fields
model_formc                     s    fdd}|S )Nc                    s   t  | _| S N)	frozenset_converter_for)funcargs }/home/ubuntu/experiments/live_experiments/Pythonexperiments/Otree/venv/lib/python3.10/site-packages/wtforms_sqlalchemy/orm.py_inner   s   
zconverts.<locals>._innerr   )r   r   r   r   r   converts   s   r   c                   @   s   e Zd Zdd ZdS )ModelConversionErrorc                 C   s   t | | d S r   )	Exception__init__)selfmessager   r   r   r      s   zModelConversionError.__init__N)__name__
__module____qualname__r   r   r   r   r   r      s    r   c                   @   s(   e Zd Zd	ddZdd Zd
ddZdS )ModelConverterBaseTc                 C   sN   || _ |si }t| D ]}t| |}t|dr!|jD ]}|||< qq|| _d S )Nr   )use_mrodirgetattrhasattrr   
converters)r   r#   r   nameobj	classnamer   r   r   r   !   s   




zModelConverterBase.__init__c                 C   s   | j rtt|j}nt|jg}|D ]"}|j d|j }|dr*|dd }|| jv r6| j|   S q|D ]}|j| jv rI| j|j   S q9td|j	|d f )z|
        Searches `self.converters` for a converter method with an argument that
        matches the column's type.
        .zsqlalchemy.   Nz2Could not find field converter for column %s (%r).r   )
r   inspectgetmrotyper   r   
startswithr#   r   r$   )r   columntypesZcol_typeZtype_stringr   r   r   get_converter/   s&   

z ModelConverterBase.get_converterNc                    s|  t |dst |dsd S t |dst|jdkrtdg g d |jd}|r+|| |d r7t|d |d< d }d }t |ds|jd }t|dd }	|	d urct|	d	d }
|
d urct|
ra|
d n|
}	|	|d< |j	rt|d 
t  n	|d 
t  | |}n2 d u rtd
|j |jjd}|jD ]	}|d j	sd}q|| fddd | j|jj }||||||dS )Ncolumns	directionr   z?Do not know how to convert multiple-column properties currently)r   filtersdefaultdescriptionr   r   r3   argz)Cannot convert field %s, need DB session.TFc                      s      S r   )queryallr   
db_sessionZforeign_modelr   r   <lambda>   s    z,ModelConverterBase.convert.<locals>.<lambda>)allow_blankZquery_factory)modelmapperpropr-   
field_args)r"   lenr0   	TypeErrordocupdatelistr!   callablenullableappendr   OptionalRequiredr/   r   keyr=   class_Zlocal_remote_pairsr#   r1   r$   )r   r<   r=   r>   r?   r9   kwargs	converterr-   r3   Zcallable_defaultrF   pairr   r8   r   convertN   sf   






zModelConverterBase.convert)Tr   )r   r   r   r   r/   rO   r   r   r   r   r       s    
r   c                       s  e Zd Zd6 fdd	Zedd Zeddd	 Zed
dddd Zedddd Z	eddd Z
eddd Zeddd Zeddd Zedd d! Zed"d#d$d% Zed&d'd( Zed)d*d+ Zed,d-d. Zed/d0d1 Zed2d3d4d5 Z  ZS )7ModelConverterNTc                    s   t  j||d d S )N)r   )superr   )r   Zextra_convertersr   	__class__r   r   r      s   zModelConverter.__init__c                 K   s<   t |jjtr|jjr|d tj|jjd d S d S d S )Nr   )max)
isinstancer+   lengthintrG   r   ZLength)clsr-   r?   extrar   r   r   _string_common   s   zModelConverter._string_commonStringc                 K   $   | j dd|i| tjdi |S Nr?   r   )rZ   wtforms_fieldsStringFieldr   r?   rY   r   r   r   conv_String      zModelConverter.conv_StringTextZLargeBinaryBinaryc                 K   r\   r]   )rZ   r^   ZTextAreaFieldr`   r   r   r   	conv_Text   rb   zModelConverter.conv_TextBooleanzdialects.mssql.base.BITc                 K      t jdi |S Nr   )r^   ZBooleanFieldr`   r   r   r   conv_Boolean      zModelConverter.conv_BooleanDatec                 K   rg   rh   )r^   Z	DateFieldr`   r   r   r   	conv_Date   rj   zModelConverter.conv_DateDateTimec                 K   rg   rh   )r^   ZDateTimeFieldr`   r   r   r   conv_DateTime   rj   zModelConverter.conv_DateTimeEnumc                 K   s&   dd |j jD |d< tjdi |S )Nc                 S   s   g | ]}||fqS r   r   ).0er   r   r   
<listcomp>   s    z,ModelConverter.conv_Enum.<locals>.<listcomp>choicesr   )r+   enumsr^   ZSelectFieldr   r-   r?   rY   r   r   r   	conv_Enum   s   zModelConverter.conv_EnumIntegerc                 K   s8   t |jdd}|r|d tjdd tjdi |S )NunsignedFr   r   )minr   )r!   r+   rG   r   NumberRanger^   ZIntegerField)r   r-   r?   rY   rx   r   r   r   handle_integer_types   s   z#ModelConverter.handle_integer_typesZNumericc                 K   s   | dd  tjdi |S )NZplacesr   )
setdefaultr^   ZDecimalFieldru   r   r   r   handle_decimal_types   s   z#ModelConverter.handle_decimal_typeszdialects.mysql.types.YEARzdialects.mysql.base.YEARc                 K   s(   |d  tjddd tjdi |S )Nr   im  ik  )ry   rT   r   )rG   r   rz   r^   r_   r`   r   r   r   conv_MSYear   s   zModelConverter.conv_MSYearzdialects.postgresql.base.INETc                 K   .   | dd |d t  tjdi |S )Nlabelz
IP Addressr   r   )r|   rG   r   Z	IPAddressr^   r_   r`   r   r   r   conv_PGInet      zModelConverter.conv_PGInetz dialects.postgresql.base.MACADDRc                 K   r   )Nr   zMAC Addressr   r   )r|   rG   r   Z
MacAddressr^   r_   r`   r   r   r   conv_PGMacaddr   r   zModelConverter.conv_PGMacaddrzdialects.postgresql.base.UUIDc                 K   r   )Nr   UUIDr   r   )r|   rG   r   r   r^   r_   r`   r   r   r   conv_PGUuid   r   zModelConverter.conv_PGUuidZ	MANYTOONEc                 K      t di |S rh   r   r`   r   r   r   conv_ManyToOne      zModelConverter.conv_ManyToOneZ
MANYTOMANYZ	ONETOMANYc                 K   r   rh   r   r`   r   r   r   conv_ManyToMany   r   zModelConverter.conv_ManyToMany)NT)r   r   r   r   classmethodrZ   r   ra   re   ri   rl   rn   rv   r{   r}   r~   r   r   r   r   r   __classcell__r   r   rR   r   rP      s@    














rP   Fc              	      s   | j j}|pt }|pi }g }	|jD ]"}
t|
ddr,|r#|
jd jr#q|r,|
jd jr,q|	|
j	|
f qrAfdd|	D }	n rL fdd|	D }	i }|	D ]\}}
|
| ||
|||}|durh|||< qP|S )z
    Generate a dictionary of fields for a given SQLAlchemy model.

    See `model_form` docstring for description of parameters.
    r0   Nr   c                 3   s     | ]}|d   v r|V  qdS r   Nr   rp   x)onlyr   r   	<genexpr>      zmodel_fields.<locals>.<genexpr>c                 3   s     | ]}|d   vr|V  qdS r   r   r   )excluder   r   r     r   )_sa_class_managerr=   rP   Ziterate_propertiesr!   r0   Zforeign_keysZprimary_keyrG   rJ   rO   get)r<   r9   r   r   r?   rM   
exclude_pk
exclude_fkr=   
propertiesr>   
field_dictr$   fieldr   )r   r   r   r
      s,   

r
   Tc
              
   C   sJ   t | ds	td|	pt| jd }	t| |||||||d}
t|	|f|
S )a  
    Create a wtforms Form for a given SQLAlchemy model class::

        from wtalchemy.orm import model_form
        from myapp.models import User
        UserForm = model_form(User)

    :param model:
        A SQLAlchemy mapped model class.
    :param db_session:
        An optional SQLAlchemy Session.
    :param base_class:
        Base form class to extend from. Must be a ``wtforms.Form`` subclass.
    :param only:
        An optional iterable with the property names that should be included in
        the form. Only these properties will have fields.
    :param exclude:
        An optional iterable with the property names that should be excluded
        from the form. All other properties will have fields.
    :param field_args:
        An optional dictionary of field names mapping to keyword arguments used
        to construct each field object.
    :param converter:
        A converter to generate the fields based on the model properties. If
        not set, ``ModelConverter`` is used.
    :param exclude_pk:
        An optional boolean to force primary key exclusion.
    :param exclude_fk:
        An optional boolean to force foreign keys exclusion.
    :param type_name:
        An optional string to set returned type name.
    r   z'model must be a sqlalchemy mapped modelr   )r   r   )r"   rA   strr   r
   r+   )r<   r9   Z
base_classr   r   r?   rM   r   r   	type_namer   r   r   r   r     s   
,
r   )NNNNNFF)__doc__r)   Zwtformsr   r^   r   Zwtforms.formr   r   r	   __all__r   r   r   r   rP   r
   r   r   r   r   r   <module>   s>     S
.