
    D6iN                     P   d dl Z d dlmZ d dlm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mZmZmZmZ d dlmZmZ d d	lmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$ d d
l%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z- ddl.m/Z/m0Z0m1Z1 ddl2m3Z3m4Z4m5Z5 ddl6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@  G d d      ZAy)    N)OrderedDict)Decimal)Enum)ColumnProperty)types)BooleanFieldField
FloatFieldPasswordFieldTextAreaField)CheckboxInputTextArea)
ColorField	DateFieldDateIntervalFieldDateTimeFieldDateTimeIntervalFieldDateTimeLocalFieldDecimalFieldDecimalIntervalField
EmailFieldIntegerFieldIntIntervalFieldSelectFieldStringField	TimeField)
ColorInput	DateInputDateTimeInputDateTimeLocalInput
EmailInputNumberInput	TextInput	TimeInput   )AttributeTypeExceptionInvalidAttributeExceptionUnknownTypeException)CountryFieldPhoneNumberFieldWeekDaysField)
choice_type_coerce_factoryClassMapflattenis_date_column	is_numberis_number_range	is_scalarnull_or_unicodestrip_stringtranslated_attributesc            !       L   e Zd ZdZ eej                  j                  efej                  j                  e
fej                  j                  e
fej                  j                  efej                  j                  efej                  j                  efej                  j"                  efej                  j&                  efej                  j*                  efej                  j.                  e
fej                  j0                  efej                  j4                  efej                  j8                  efej                  j:                  efej                  j>                  efej@                  efejB                  efejD                  e#fejH                  e%fejL                  e'fejP                  e)fejT                  e+fejX                  e-fej\                  e/fej`                  e1fejd                  e3fejh                  efejj                  efejl                  efejn                  e8ff      Z9 e:ee;fe#e<fee=fee>fe?e@feeAfe+eBfeeAfe
eAfeeCfeeDfeeEff      ZFd ZGd ZHd ZId ZJd ZKd ZLd ZMd	 ZNd
 ZOd ZPd ZQd ZRd ZSd ZTd ZUd ZVd ZWd ZXd ZYd ZZd Z[d Z\d Z]d Z^d Z_d Z`y)FormGeneratorzb
    Base form generator, you can make your own form generators by inheriting
    this class.
    c                    || _         | j                   j                  j                  | _        | j                   j                  | _        | j
                  j                  | j                   j                  j                         y)z
        Initializes the form generator

        :param form_class: ModelForm class to be used as the base of generation
                           process
        N)
form_classMetamodelmodel_classmetaTYPE_MAPupdatetype_map)selfr9   s     \/home/azureuser/techstart-app/venv/lib/python3.12/site-packages/wtforms_alchemy/generator.py__init__zFormGenerator.__init__}   sV     %??//55OO((	T__11::;    c                    t               }t        j                  | j                        j                  j                         D ]-  \  }}t        |t              s| j                  |      r)|||<   / t        | j                        D ]  }|j                  ||j                  <    | j                  || j                  |            S )zL
        Creates the form.

        :param form: ModelForm instance
        )r   sainspectr<   attrsitems
isinstancer   skip_column_propertyr5   propertykeycreate_fieldsfilter_attributes)rA   formrH   rM   	property_attrs         rB   create_formzFormGenerator.create_form   s      jj)9)9:@@FFH 	#NCi8((3"E#J	# *$*:*:; 	,D"mmE$((O	, !!$(>(>u(EFFrD   c                 x   | j                   j                  rLt        t        | j                  | j                   j                        D cg c]  \  }}|r||f c}}      }|S | j                   j
                  rP|j                  t        | j                  | j                   j
                        D cg c]  \  }}|r||f c}}       | j                   j                  r| j                   j                  D ]  }	 ||=  |S c c}}w c c}}w # t        $ r$ | j                   j                  rt        |      Y Cw xY w)z
        Filter set of model attributes based on only, exclude and include
        meta parameters.

        :param attrs: Set of attributes
        )r=   onlyr   mapvalidate_attributeincluder?   excludeKeyErrorattr_errorsr'   )rA   rH   rM   props       rB   rO   zFormGenerator.filter_attributes   s%    99>> &))@)@$))..%Q!T $KE0 ! yy   *-T-D-DdiiFWFW)X%C d yy  99,, ACA!#JA / $ A9900";C"@@ 1As   	D 
1D
9D*D98D9c                    	 t        | j                  |      }	 t        |j                  t              s"| j                  j
                  rt        |      y	 ||j                  fS # t        $ r[ 	 | j                  j                  d   }t        ||      }n1# t        $ r% | j                  j
                  rt        |      Y Y yw xY wY w xY w# t        $ r t        |      w xY w)z
        Finds out whether or not given sqlalchemy model attribute name is
        valid. Returns attribute property if valid.

        :param attr_name: Attribute name
        class)NN)getattrr<   AttributeError__translatable__r=   r[   r'   rJ   rL   r   r&   )rA   	attr_namerR   translation_classs       rB   rW   z FormGenerator.validate_attribute   s    
	&4++Y7D	4dmm^<99((3I>>%	 = $--''#  	&&$($4$4$E$Eg$N!0)<! &99((3I>>%	& 	&  	4(33	4s@   A$ ;C $	C.%BC*C>CCCCC c                     |j                         D ]A  \  }}|j                  d   }	 | j                  ||      }t        ||      r5t        |||       C y# t        $ r | j                  j
                  s Y gw xY w)z
        Creates fields for given form based on given model attributes.

        :param form: form to attach the generated fields into
        :param attributes: model attributes to generate the form fields from
        r   N)rI   columnscreate_fieldr(   r=   skip_unknown_typeshasattrsetattr)rA   rP   
propertiesrM   r\   columnfields          rB   rN   zFormGenerator.create_fields   s     $))+ 	*IC\\!_F))$7 4%c5)	* ( yy33	s   A A98A9c                 X    |j                   ry| j                  |j                  d         S )z
        Whether or not to skip column property in the generation process.

        :param column_property: SQLAlchemy ColumnProperty object
        Tr   )_is_polymorphic_discriminatorskip_columnre   )rA   column_propertys     rB   rK   z"FormGenerator.skip_column_property   s,     88 7 7 :;;rD   c                    | j                   j                  s|j                  ry| j                   j                  s|j                  ry| j                   j
                  s;t        |j                  t        j                  j                        r|j                  ryt        |j                  t        j                        ry| j                   j                  r| j                  |      syt        |t        j                        syy)z
        Whether or not to skip column in the generation process.

        :param column_property: SQLAlchemy Column object
        TF)r=   include_foreign_keysforeign_keysinclude_primary_keysprimary_keyinclude_datetimes_with_defaultrJ   typerF   r   DateTimedefaultTSVectorTypeonly_indexed_fields	has_indexColumnrA   rk   s     rB   ro   zFormGenerator.skip_column   s     yy--&2E2Eyy--&2D2D 		886;;(9(9:fkk5#5#5699((1G &")),rD   c                     |j                   s|j                  ry|j                  }|j                  D ]5  }t	        |j
                        dk(  s|j                  |j
                  v s5 y y)z}
        Whether or not given column has an index.

        :param column: Column object to inspect the indexes from
        Tr%   F)ru   rs   tableindexeslenre   name)rA   rk   r   indexs       rB   r|   zFormGenerator.has_index  s\     !4!4]] 	E5==!Q&6;;%--+G	 rD   c                 r   i }| j                  |      }| j                  |      |d<   | j                  ||      |d<   | j                  |      |d<   |j	                  | j                  |j                  |             |j	                  | j                  |             |j                  | j                  j                  v r2|j	                  | j                  j                  |j                            t        |t              r/t        |j                  d      r|j                  j                  |d<    |di |}|S )z
        Create form field for given column.

        :param prop: SQLAlchemy ColumnProperty object.
        :param column: SQLAlchemy Column object.
        ry   
validatorsfiltersscaleplaces )get_field_classry   create_validatorsr   r?   type_agnostic_parametersrM   type_specific_parametersr=   
field_args
issubclassr   rh   rw   r   )rA   r\   rk   kwargsfield_classrl   s         rB   rf   zFormGenerator.create_field'  s     **62 LL0y#55dFC| LL0yd33DHHfEFd33F;<88tyy+++MM$))..txx89k<0v{{G,#);;#4#4x %f%rD   c                     |j                   r5t        |j                   j                        r|j                   j                  S |j                  s| j                  j                   S y)zi
        Return field default for given column.

        :param column: SQLAlchemy Column object
        N)ry   r2   argnullabler=   r~   s     rB   ry   zFormGenerator.default>  sH     >>i(:(:;>>%%%??yy((( #rD   c                 4   |j                   j                  dd      }|j                   j                  dg       }t        |j                  t        j
                  j                        r| j                  j                  r||du r|j                  t               |S )zc
        Return filters for given column.

        :param column: SQLAlchemy Column object
        trimNr   T)infogetrJ   rw   rF   r   Stringr=   strip_string_fieldsappendr4   )rA   rk   should_trimr   s       rB   r   zFormGenerator.filtersJ  sn     kkoofd3++//)R0v{{BHHOO4		--#D NN<(rD   c                 \   t        |j                  t        j                  j                        s$t        |j                  t        j
                        r| j                  j                  S t        |j                  t        j                  j                        r| j                  j                  S y)zh
        Returns date format for given column.

        :param column: SQLAlchemy Column object
        N)
rJ   rw   rF   r   rx   	ArrowTyper=   datetime_formatDatedate_formatr~   s     rB   r   zFormGenerator.date_formatZ  sm     fkk288#4#45KK:
 99,,,fkk288==199((( 2rD   c                    i }t        |j                  d      s?|j                  j                  d      s$t	        |j                  t
        j                        r |j                  | j                  |             | j                  |      }|r||d<   t        |j                  d      r|j                  j                  |d<   | j                  |      |d<   |S )zu
        Returns type specific parameters for given column.

        :param column: SQLAlchemy Column object
        enumschoicesformatregionwidget)rh   rw   r   r   rJ   r   
ChoiceTyper?   select_field_kwargsr   r   r   )rA   rk   r   r   s       rB   r   z&FormGenerator.type_specific_parametersh  s     FKK){{y)&++u'7'78MM$226:;&&v.*F86;;)%{{11F8;;v.xrD   c                    |j                   j                  dd      }||S i }|j                   j                  dd      }|||d<   nt        |j                  t        j
                  j                        rY|j                  j                  C|j                   j                  d      s(| j                  |j                  j                        |d<   |r&| j                  | j                  |         } |di |S y)zk
        Returns WTForms widget for given column.

        :param column: SQLAlchemy Column object
        r   Nstepr   r   )r   r   rJ   rw   rF   r   Numericr   scale_to_step
WIDGET_MAPr   )rA   rk   r   r   r   widget_classs         rB   r   zFormGenerator.widget  s     40M{{vt,!F6N&++rxx'7'78;;$$09S%)%7%78I8I%JF6N??4+?+?+GHL)&)) rD   c                 >    t        t        t        d      |            S )z
        Returns HTML5 compatible step attribute for given decimal scale.

        :param scale: an integer that defines a Numeric column's scale
        z0.1)strpowr   )rA   r   s     rB   r   zFormGenerator.scale_to_step  s     3wu~u-..rD   c                     i }|j                   j                  dd      |d<   |j                   j                  d|      |d<   |S )z
        Returns all type agnostic form field parameters for given column.

        :param column: SQLAlchemy Column object
        description label)r   r   )rA   rM   rk   r   s       rB   r   z&FormGenerator.type_agnostic_parameters  s?      &r B} ++//'37wrD   c                    i }| j                  |      |d<   t        |j                  t        j                        rm|j                  j
                  }t        Jt        |t              r:t        |t              r*|D cg c]  }|j                  t        |      f c}|d<   |S ||d<   |S d|j                  v r#|j                  d   r|j                  d   |d<   |S |j                  j                  D cg c]  }||f c}|d<   |S c c}w c c}w )z
        Returns key value args for SelectField based on SQLAlchemy column
        definitions.

        :param column: SQLAlchemy Column object
        coercer   )r   rJ   rw   r   r   r   r   r   valuer   r   r   )rA   rk   r   r   choiceenums         rB   r   z!FormGenerator.select_field_kwargs  s     ;;v.xfkk5#3#34kk))G w-w-OV$WVfllCK%@$Wy!  %,y!
 	 &++%&++i*@ &I 6F9  ;A++:K:K L$$ LF9 %X !Ms   ;D1D	c                 N   d|j                   v r|j                   d   S t        |j                  t        j                        rt        |j                        S 	 |j                  j                  }|j                  rt        |t              rt        S |S # t        $ r	 t        cY S w xY w)zk
        Returns coerce callable for given column

        :param column: SQLAlchemy Column object
        r   )r   rJ   rw   r   r   r,   python_typeNotImplementedErrorr3   r   r   r   )rA   rk   r   s      rB   r   zFormGenerator.coerce  s     v{{";;x((fkk5#3#34-fkk::	# ++11K ??z+s;"" # 	#""	#s   B B$#B$c                 H   | j                  |      | j                  |      | j                  |j                  |      | j	                  |      g}t        |j                  t        j                        r |j                  | j                  d             t        |j                  t        j                        r |j                  | j                  d             t        |D cg c]  }||	 c}      }|j                  | j                  |j                  |             |S c c}w )zf
        Returns validators for given column

        :param column: SQLAlchemy Column object
        emailurl)required_validatorlength_validatorunique_validatorrM   range_validatorrJ   rw   r   	EmailTyper   get_validatorURLTyper.   extendadditional_validators)rA   r\   rk   r   vs        rB   r   zFormGenerator.create_validators  s     ##F+!!&)!!$((F3  (	

 fkk5??3d009:fkk5==1d0078EAq}aEF
$44TXXvFG Fs   D'Dc                    | j                   j                  s>|j                  s2|j                  s&| j                   j                  }	 ||j
                     S | j                  d      S # t        $ r t        |j
                  t        j                  j                        r-|j
                  j                  }	 ||   cY S # t        $ r Y nw xY w| j                   j                  | j                   j                  cY S Y w xY w)z
        Returns required / optional validator for given column based on column
        nullability and form configuration.

        :param column: SQLAlchemy Column object
        optional)r=   all_fields_optionalry   r   not_null_validator_type_maprw   rZ   rJ   rF   r   TypeDecoratorimplnot_null_validatorr   )rA   rk   r@   type_s       rB   r   z FormGenerator.required_validator  s     		--NNOOyy<<H8,, !!*--  	8fkk288+A+AB"KK,,E'.# 99//;99777 <	8s7   A& &AC;4B;8C;;	CC;C/C;:C;c                 P    | d}t        | j                  |      }||S  |di |S )N
_validatorr   )r_   r=   )rA   r   r   rb   rR   s        rB   r   zFormGenerator.get_validator  s4    fJ'	tyy),<K~f~rD   c                    g }|| j                   j                  v r)	 |j                  | j                   j                  |          d|j
                  v r0|j
                  d   r!	 |j                  |j
                  d          |S |S # t        $ r+ |j	                  | j                   j                  |          Y sw xY w# t        $ r" |j	                  |j
                  d          Y |S w xY w)z
        Returns additional validators for given column

        :param key: String key of the column property
        :param column: SQLAlchemy Column object
        r   )r=   r   r   	TypeErrorr   r   )rA   rM   rk   r   s       rB   r   z#FormGenerator.additional_validators  s     
$))&&&=!!$))"6"6s";< 6;;&6;;|+D=!!&++l";< z  =!!$))"6"6s";<=  =!!&++l";<=s#   (B "B; 1B87B8;'C&%C&c                     |j                   r<| j                  dt        | j                  |      | j                  j
                        S y)z
        Returns unique validator for given column if column has a unique index

        :param key: String key of the column property
        :param column: SQLAlchemy Column object
        unique)rk   get_sessionN)r   r   r_   r<   r9   r   )rA   rM   rk   s      rB   r   zFormGenerator.unique_validator$  sH     ==%%t//5 OO77 &   rD   c                    |j                   j                  d      }|j                   j                  d      }||t        |j                        st	        |j                        r| j                  d||      S t        |      r| j                  d||      S t        |j                  t        j                  j                        r| j                  d||      S yy)z
        Returns range validator based on column type and column info min and
        max arguments

        :param column: SQLAlchemy Column object
        minmaxNnumber_range)r   r   
date_range
time_range)r   r   r0   rw   r1   r   r/   rJ   rF   r   Time)rA   rk   min_max_s       rB   r   zFormGenerator.range_validator2  s     {{u%{{u%t/%)E)).d)MM')),Dd)KKFKK7)),Dd)KK 8  0rD   c                 
   t        |j                  t        j                  j                        rUt        |j                  d      r>|j                  j                  r'| j                  d|j                  j                        S yyy)zl
        Returns length validator for given column

        :param column: SQLAlchemy Column object
        length)r   N)rJ   rw   rF   r   r   rh   r   r   r~   s     rB   r   zFormGenerator.length_validatorD  sd     v{{BHHOO4X.""%%hFKK4F4F%GG # / 5rD   c                     d|j                   v r|j                   d   r|j                   d   S d|j                   v r|j                   d   rt        S |j                  | j                  vrEt	        |j                  t
        j                  j                        r|j                  j                  }n|j                  }	 | j                  |   }t        j                  |      rt        |t              r|S  ||      S # t        $ r t        |      w xY w)z
        Returns WTForms field class. Class is based on a custom field class
        attribute or SQLAlchemy column type.

        :param column: SQLAlchemy Column object
        form_field_classr   )r   r   rw   r>   rJ   rF   r   r   r   rG   isclassr   r	   rZ   r(   )rA   rk   
check_typecolumn_types       rB   r   zFormGenerator.get_field_classQ  s     ,=O1P;;122#I(>;;dmm+
KK//1
  ))JJ	/--
3K{+
;0N"""6** 	/&v..	/s   :5C8 0C8 8DN)a__name__
__module____qualname____doc__r-   rF   r   UnicodeTextr   
BigIntegerr   SmallIntegerTextBooleanr   r   r   rx   r   r   r   Floatr
   Integerr   r   Unicoder   r   r   r   JSONr   r   	ColorTyper   CountryTyper)   DateRangeTyper   DateTimeRangeTyper   r   r   IntRangeTyper   NumericRangeTyper   PasswordTyper   PhoneNumberTyper*   ScalarListTyper   UUIDTypeWeekDaysTyper+   r>   r   r   r   r   r   r   r    r"   r!   r   r$   r#   r   rC   rS   rO   rW   rN   rK   ro   r|   rf   ry   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rD   rB   r7   r7   @   s    XX!!=1XX  ,/XX""L1XX]]M*XX|,XX]]I&XX.XX]]K(XX^^Z(XX|,XX|,XX{+XX__k*XX]]I&XX]]M*__m,{+__j)-  "34$$&;<__j)!12##%9:/""$45!!;/]]K(^^[)/=	
!HF =)$	"M*!34;'$%;'H%	")$	
J"
<G& D(8*(	<@.
) )0*0/	2&*.6*L$H/rD   r7   )BrG   collectionsr   decimalr   r   r   
sqlalchemyrF   sqlalchemy.orm.propertiesr   sqlalchemy_utilsr   wtformsr   r	   r
   r   r   wtforms.widgetsr   r   wtforms_componentsr   r   r   r   r   r   r   r   r   r   r   r   r   r   wtforms_components.widgetsr   r   r   r    r!   r"   r#   r$   excr&   r'   r(   fieldsr)   r*   r+   utilsr,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r7   r   rD   rB   <module>r     sz     #    4 "  4    	 	 	 
 B A  k/ k/rD   