U
    PN^)                  	   @   s   d Z ddl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
mZ d	Zd
d ZG dd deZG dd de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.
    )unicode_literalsN)fields)
validators)Form   )QuerySelectFieldQuerySelectMultipleField)model_fields
model_formc                     s    fdd}|S )Nc                    s   t  | _| S N)	frozenset_converter_for)funcargs ?/tmp/pip-install-o1yuzyg2/WTForms/wtforms/ext/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dZdS )	ModelConverterBaseTc                 C   sN   || _ |si }t| D ],}t| |}t|dr|jD ]}|||< q4q|| _d S )Nr   )use_mrodirgetattrhasattrr   
converters)r   r"   r   nameobj	classnamer   r   r   r      s    


zModelConverterBase.__init__Nc                    s  t |dst |dsd S t |ds8t|jdkr8tdg g d d}d }d }d }	t |ds|jd }t|dd }
|
d k	rt|
dd }|d k	rt|r|d n|}
|
|d< |jr|d	 t	  n|d	 t
  | jrtt|j}	nt|jg}	|	D ]J}d
|j|jf }|dr*|dd  }|| jk r| j| } q q|	D ]&}|j| jkrN| j|j } qqNtd|j|	d f nf std|j |jjd}|jD ]}|d jsd}q|| fddd | j|jj }|r|| ||||||dS )Ncolumns	directionr   z?Do not know how to convert multiple-column properties currently)r   filtersdefaultr   r)   argr   z%s.%sZ
sqlalchemy   z+Could not find field converter for %s (%r).z)Cannot convert field %s, need DB session.TFc                      s      S r   )queryallr   
db_sessionZforeign_modelr   r   <lambda>y       z,ModelConverterBase.convert.<locals>.<lambda>)Zallow_blankZquery_factory)modelmapperpropcolumn
field_args)r!   lenr&   	TypeErrorr    callablenullableappendr   OptionalZRequiredr   inspectgetmrotyper   r   
startswithr"   r   keyr3   class_Zlocal_remote_pairsupdater'   r#   )r   r2   r3   r4   r6   r/   kwargs	converterr5   typesr)   Zcallable_defaultZcol_typeZtype_stringr:   pairr   r.   r   convert-   sx    





zModelConverterBase.convert)T)N)r   r   r   r   rH   r   r   r   r   r      s   
r   c                       s  e Zd Zd; fdd	Zedd Zeddd	d
 Zeddd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 d! Zed"d#d$d% Zed&d'd(d) Zed*d+d,d- Zed.d/d0 Zed1d2d3 Zed4d5d6 Zed7d8d9d: Z  ZS )<ModelConverterNTc                    s   t t| j||d d S )N)r   )superrI   r   )r   Zextra_convertersr   	__class__r   r   r      s    zModelConverter.__init__c                 K   s&   |j jr"|d tj|j jd d S )Nr   )max)r?   lengthr;   r   ZLength)clsr5   r6   extrar   r   r   _string_common   s    zModelConverter._string_commonStringZUnicodec                 K   s    | j f d|i| tjf |S Nr6   )rQ   f	TextFieldr   r6   rP   r   r   r   conv_String   s    zModelConverter.conv_Stringz
types.TextZUnicodeTextztypes.LargeBinaryztypes.Binaryzsql.sqltypes.Textc                 K   s    | j f d|i| tjf |S rS   )rQ   rT   ZTextAreaFieldrV   r   r   r   	conv_Text   s    zModelConverter.conv_TextBooleanc                 K   s   t jf |S r   )rT   ZBooleanFieldrV   r   r   r   conv_Boolean   s    zModelConverter.conv_BooleanDatec                 K   s   t jf |S r   )rT   Z	DateFieldrV   r   r   r   	conv_Date   s    zModelConverter.conv_DateDateTimec                 K   s   t jf |S r   )rT   ZDateTimeFieldrV   r   r   r   conv_DateTime   s    zModelConverter.conv_DateTimeEnumc                 K   s*   d|krdd |j jD |d< tjf |S )Nchoicesc                 S   s   g | ]}||fqS r   r   ).0er   r   r   
<listcomp>   s     z,ModelConverter.conv_Enum.<locals>.<listcomp>)r?   enumsrT   ZSelectField)r   r5   r6   rP   r   r   r   	conv_Enum   s    zModelConverter.conv_EnumZIntegerZSmallIntegerc                 K   s4   t |jdd}|r(|d tjdd tjf |S )NunsignedFr   r   )min)r    r?   r;   r   NumberRangerT   ZIntegerField)r   r5   r6   rP   rf   r   r   r   handle_integer_types   s    z#ModelConverter.handle_integer_typesZNumericZFloatc                 K   s*   t |jdd}|d k	r||d< tjf |S )NZscale   places)r    r?   rT   ZDecimalField)r   r5   r6   rP   rk   r   r   r   handle_decimal_types   s    z#ModelConverter.handle_decimal_typeszdatabases.mysql.MSYearzdialects.mysql.base.YEARc                 K   s$   |d  tjddd tjf |S )Nr   im  ik  )rg   rM   )r;   r   rh   rT   rU   rV   r   r   r   conv_MSYear   s    zModelConverter.conv_MSYearzdatabases.postgres.PGInetzdialects.postgresql.base.INETc                 K   s*   | dd |d t  tjf |S )Nlabelz
IP Addressr   )
setdefaultr;   r   Z	IPAddressrT   rU   rV   r   r   r   conv_PGInet   s    zModelConverter.conv_PGInetz dialects.postgresql.base.MACADDRc                 K   s*   | dd |d t  tjf |S )Nrn   zMAC Addressr   )ro   r;   r   Z
MacAddressrT   rU   rV   r   r   r   conv_PGMacaddr   s    zModelConverter.conv_PGMacaddrzdialects.postgresql.base.UUIDc                 K   s*   | dd |d t  tjf |S )Nrn   UUIDr   )ro   r;   r   rr   rT   rU   rV   r   r   r   conv_PGUuid   s    zModelConverter.conv_PGUuidZ	MANYTOONEc                 K   s
   t f |S r   )r   rV   r   r   r   conv_ManyToOne   s    zModelConverter.conv_ManyToOneZ
MANYTOMANYZ	ONETOMANYc                 K   s
   t f |S r   )r   rV   r   r   r   conv_ManyToMany   s    zModelConverter.conv_ManyToMany)NT)r   r   r   r   classmethodrQ   r   rW   rX   rZ   r\   r^   re   ri   rl   rm   rp   rq   rs   rt   ru   __classcell__r   r   rK   r   rI      s>   













rI   Fc              	      s   | j j}|pt }|pi }g }	|jD ]F}
t|
ddrZ|rH|
jd jrHq$n|rZ|
jd jrZq$|	|
j	|
f q$rfdd|	D }	n r fdd|	D }	i }|	D ]0\}}
|
| ||
|||}|dk	r|||< q|S )z
    Generate a dictionary of fields for a given SQLAlchemy model.

    See `model_form` docstring for description of parameters.
    r&   Nr   c                 3   s   | ]}|d   kr|V  qdS r   Nr   ra   x)onlyr   r   	<genexpr>   s      zmodel_fields.<locals>.<genexpr>c                 3   s   | ]}|d   kr|V  qdS rx   r   ry   )excluder   r   r|      s      )_sa_class_managerr3   rI   Ziterate_propertiesr    r&   Zforeign_keysZprimary_keyr;   rA   rH   get)r2   r/   r{   r}   r6   rE   
exclude_pk
exclude_fkr3   Z
propertiesr4   
field_dictr#   fieldr   )r}   r{   r   r	      s6    

   
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 wtforms.ext.sqlalchemy.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!   r8   strr   r	   r?   )r2   r/   Z
base_classr{   r}   r6   rE   r   r   	type_namer   r   r   r   r
     s    #
      r
   )NNNNNFF)__doc__
__future__r   r=   Zwtformsr   rT   r   Zwtforms.formr   r   r   __all__r   r   r   objectr   rI   r	   r
   r   r   r   r   <module>   s2   lS       
(    