
    Ni                     n    d dl Z d dlmZ d dlZd dlT d dlT d dlmZ  G d dej	        j
                  ZdS )    N)defaultdict)*)timeitc            	       R   e Zd ZdZdZdZ eedddddd          Z eedd          Z	 ee
d	
          Z eedd          Z ee
d
          Z eed
          Z ee
d
          Z ee
d
          Z ee
d
          Z ee
d
          Z ee
d
          Z ee
d
          Zed+d            Zed,d            Zed+d            Ze	 d-d            Zed             Zej         G d d                      Zi ZdZ ed             Z!ed.d            Z"ed             Z#ed             Z$ed e%d!e&fd"            Z'ed/d e%d!e&d#e(j)        j*        fd$            Z+ed%             Z,ed&             Z-e e.de/j0        d'(          d)                         Z1e2d*             Z3dS )0RelationCacheu  
    Мастер таблица всех деревянных связей объектов. В т.ч. непрямых. Т.е. дерего развёрнутое.
    Не заменяет m2m таблицы.
    Работа с данными этой таблицы только через методы этой модели. Вся магия деревьев здесь.

    TODO: Мультиколоночные индексы id+field

    TODO: какой-нить лок на изменение дерева, т.к. одновременные изменения его поломают.
        Сейчас защита на select for update, но нет уверенности что этого достаточно.
    Fu)   Идентификатор объектаu3   Автоматически генерируетсяT)captioncommentnullableprimary_keyreadonlyvisibleu   ID родителя)r   indexu$   Поле связи родителя)r   u   ID потомкаu"   Поле связи потомкаu   Глубина связиu   Модель родителяu   Имя родителяu   Код родителяu   Модель потомкаu.   Опциональное имя потомкаu   Код потомкаNc                    dg}ddl m} ddlm} |                    |          }	t          |	|          }
g }|j        r/t          |
dd          r|rt          d          t          |
t          j
        j                  st          d          |
j        r5d	 |
                                                    |d
g          D             }n4d |
                                                    |dg          D             }|sg S g }d |
j        D             D ]"\  }}|                    dd|gdd|gg           #t#          |          dk    rdg|}ddd|g|g}rfd|D             }n|}nddd|gdd|gg}rdddg|g}|r|g dz  }|                     |||          }|r|S t%          d |D                       }|D ]}|                    |           |S )u  
        full=True - возвращаем список экземпляров RelationCacheModel со всеми полями
        иначе только список child_id
        fixme: фильтр по child_field - нужен ли? Возможно
        r   r   cmfutil)confignested_fields_is_edge_parentFu]   get_children(full=True) не поддерживается для nested_fields_is_edge_parentuZ   TODO Тип поля не поддерживается для nested_fields_is_edge_parentc                     g | ]	}|j         
S  )right_id.0is     "./cmf/fields/cmf_relation_cache.py
<listcomp>z.RelationCache.get_children.<locals>.<listcomp>P   s,      %E  %E  %EAQZ  %E  %E  %E    r   )left_idfieldsc                     g | ]	}|j         
S r   )r   r   s     r   r   z.RelationCache.get_children.<locals>.<listcomp>R   s,      %D  %D  %D1QY  %D  %D  %Dr   r   )r   r   c                 8    g | ]}|                     d           S ).splitr   s     r   r   z.RelationCache.get_children.<locals>.<listcomp>Y   s"    8j8j8j!8j8j8jr   parent_model=parent_field   ORAND	parent_idINc                 N    g | ]!}|                     d           d         v |"S ):r   r"   )r   r   child_modelss     r   r   z.RelationCache.get_children.<locals>.<listcomp>a   s4    *k*k*k177SV<<XY?^jKjKj1KjKjKjr   ==child_model)
r*   r&   r$   parent_nameparent_codechild_fieldr0   
child_name
child_codedepthr   filter
for_updatec                 &    h | ]}|j         j        S r   )child_idvaluer   rows     r   	<setcomp>z-RelationCache.get_children.<locals>.<setcomp>r   s    9993CL&999r   )cmf.utilr   cmf.includer   get_model_by_idgetattrRELATION_CACHE_EDGE_OPTIMIZE	Exception
issubclasscmfr   
CmfM2MBaseleftm2m_model_clsslistnested_fieldsappendlenlist)clsr*   parent_field_namer.   fullr9   r   r   r   r$   r&   additional_children_idsnested_ids_depth0parent_meta_filternested_model_namenested_field_namequery_filterresultresadditional_ids      `                r   get_childrenzRelationCache.get_children7   s    $$$$$$&&&&&& ..y99|->??"$. 	n7<Igin3o3o 	n B  !A  B  B  BlCJ,ABB  }~~~  D %E  %E9S9S9U9U9[9[dm  xB  wC9[  :D  :D  %E  %E  %E!! %D  %D8R8R8T8T8Z8Zdm  xA  wB8Z  9C  9C  %D  %D  %D!$ 	 "$8j8j|Oi8j8j8j @ @4!#4"))NCAR+SVdfik|U}*~%&&**&*%@-?%@"!K7H#IK]^L <*k*k*k*k6G*k*k*k''*;'' "Ky#ANTXZkClmL 	V!M4#FUL 	S S S S SF TT 	M99&999::4 	& 	&MJJ}%%%%
r   c                    t          t                    }|                     |||          D ]6}||                    d          d                                      |           7|sd |                                D             S |S )u   
        get_children с разбитием по классам, потом удобней фильтровать, подгружать.
        result = {"child_model1": ["child_id1", ...], ...}
        )r.   r-   r   c                 4    i | ]\  }}|t          |          S r   rO   )r   
model_nameids_sets      r   
<dictcomp>z3RelationCache.get_children_dict.<locals>.<dictcomp>   s%    XXX2E*gJWXXXr   )r   setr\   r#   additems)rP   r*   rQ   r.   
return_setrY   r>   s          r   get_children_dictzRelationCache.get_children_dictw   s     S!!##I/@|#\\ 	/ 	/C399S>>!$%))#.... 	YXXXXXXr   c                     dg}ddd|gdd|gg}|rddd|g|g}|                      |||          }|r|S t          d	 |D                       S )
u   
        full=True - возвращаем список экземпляров RelationCacheModel со всеми полями
        иначе только список parent_id
        r   r)   r;   r/   r3   r$   r+   r7   c                 &    h | ]}|j         j        S r   )r*   r<   r=   s     r   r?   z,RelationCache.get_parents.<locals>.<setcomp>   s    ;;;SS](;;;r   r_   )	rP   r;   child_field_nameparents_modelsrR   r9   r   rX   rY   s	            r   get_parentszRelationCache.get_parents   s     
D(;mTSc=de 	Y!ND.#I<XLTT 	M;;F;;;<<<r   c	                    |r|s,t          d| d| d| d| d ||h|h|h           
          |                     ||||dddg          }	|	rd	S |                     ||dd
          }
|                     ||dd
          } | |||                    d          d         |||||                    d          d         ||d          }d}||gz   D ]6}|
|gz   D ]+}|j        |j        z   }|j        |j        f|j        |j        fk    r|dz  }|j        |j	        f|j        |j	        fk    r|dz  }|j        |j        k    rid}|d|j
         d|j         d|j         d|j         d	z  }|dz  }|sddlm} |                    |           d}t"                              d|             | |j        |j        |j        |j
        |j        |j        |j	        |j        |j        |j        |                                           -8d	S )u   Добавим прямую связь между полями двух объектов, а также связи между родителями и детьми.z%add_relation: try add None relation, (z, z) -> r   Tr   r*   r&   r;   r3   r6   r9   r   N)rR   r9   r-   )r*   r&   r$   r1   r2   r;   r3   r0   r4   r5   r6   Fr'   ud   Объект вложен сам в себя через промежуточные сущности: z) -> ... -> z).u    Зацикливание может привести к поблемам с производительностью, устраните зацикливание.r   z"ERROR RelationCache cycle detect: )CmfOrmErrorrO   r\   rl   	partitionr6   r*   r&   r;   r3   r1   r2   r4   r5   r@   r   admin_alertgdebugr$   r0   save)rP   r*   rQ   r;   rj   r1   r2   r4   r5   direct_linkschildrenparentsdirect_linklinked_objects_cycle_alarmparentchildr6   error_messager   s                      r   add_relationzRelationCache.add_relation   sI     	W 	WVV V/V V3=V VAKV V y"3!4{mk]SSV VW W W
 xx.?+;cU   4 4  	 F ##H.>TVZ#[[//)->TVZ/[[ c.?iNaNabeNfNfghNi#+;I[I[\_I`I`abIc!j
 
 
 &+"- 	 	F![M1  u{2$f&9:{?TVaVn>oooQJENE$56;;OQ\Qh:iiiQJE #u~55 %LM!  &F);  &F  &Ff>P  &F  &F^c^n  &F  &Fqv  rB  &F  &F  &F  FM!  &J  JM5 :444444++M:::592GGPPPQQQ$.V=P_e_r & 2@R"^9J % 1$/E<L   $&&&&9	 	r   c                 &   |                      ||||dddg          }|sdS t          |          dk    r/t          dt          |           d| d	| d
| d	| 
||||          |d         }|                     ||d          }|                     ||d          }||z   D ]}	||z   D ]}
|	j        |
j        z   }|	j        |	j        f|j        |j        fk    r|dz  }|
j        |
j	        f|j        |j	        fk    r|dz  }| 
                    |	j        |	j        |
j        |
j	        |ddg          }|r|                                 t          d|	j        j         d	|	j        j         d
|
j        j         d	|
j	        j         d| 
|	|
|          dS )u3   
        TODO: пакетный режим
        r   Tr   ro   Nr'   ztoo many relation (z) z::z => )rR   zrelation absent z depth )rO   rN   LookupErrorrl   r\   r6   r*   r&   r;   r3   getdeleteFileNotFoundErrorr<   )rP   r*   rQ   r;   rj   rw   rz   ry   rx   r|   r}   r6   links                r   remove_relationzRelationCache.remove_relation   su    xx.?+;cU   4 4  	JF ""6c,&7&7 6 66 6!26 66 6#36 6 ,h8H	J J J
 #1o//)->T/JJ##H.>T#JJ, 	. 	.F!L0 . .u{2$f&9:{?TVaVn>oooQJENE$56;;OQ\Qh:iiiQJE ww$.V=P"^9JD#  @ @  .KKMMMM ,_",2_ _6<6I6O_ _$~3_ _7<7H7N_ _W\_ _ u	. . .'.	. 	.r   c                       e Zd ZU dZeed<    ej        e          Z	eed<    ej        e          Z
eed<   dZeed<   dS )	RelationCache.FieldCacheu~   Данные по полю модели Cmf, отражающие его связи и положение в иерархии.field_class)default_factoryrx   	right_forFrecursion_doneN)__name__
__module____qualname____doc__CmfTypeMeta__annotations__dataclassesfieldrO   rx   r   r   boolr   r   r   
FieldCacher   &  s|          	M  	M    **4@@@$@@@
 ,++DAAA	4AAA$$$$$$r   r   c                    t          |dg           }t          |dd          r|t          |d          gz  }t          |t                    r!|d |                                D             z  }t	          t          |                    S )u$   Список имён related_modelsmodelsmodelNc                     g | ]	}|j         
S r   )
class_name)r   	sub_models     r   r   z8RelationCache.get_field_models_names.<locals>.<listcomp>>  s    "`"`"`I9#7"`"`"`r   )rC   rF   CmfSubclassedGenericRelationrelated_modelsrO   rc   )rP   r   field_models_namess      r   get_field_models_namesz$RelationCache.get_field_models_names6  s     %UHb995'4(( 	<75'#:#:";;e9:: 	a"`"`I]I]I_I_"`"`"``C*++,,,r   c                 \   | j         |         j                            |           |rKd|vr |                    d          d          d| }| j         |         j                            ||f           | j         |         j        }t          |dd          rt          d| d|           t          |t                    rft          |dd          sW| j         |         j
        sGd| j         |         _
        |                     |          D ]!}|                     || d	           dS dS dS dS )
uA   Используется при создании cls.fields_cacher!   r   r   Nu   Нельзя ссылаться с помощью nested_fields на поле, помеченное как nested_fields_is_edge_parent: z -> rL   Tz.id)_fields_cacherx   rM   rr   r   r   rC   rE   rF   CmfRelationBaser   r   
_add_child)rP   r|   r}   backrefr3   field_model_names         r   r   zRelationCache._add_childA  s    	&!*11%888 	I'!!"__S11!4@@w@@g&077HHH '.:; >EE 	C  B  io  B  B  u@  B  B  C  C  Ck?33 	@_dCC	@)%0?	@ 7;Ce$3$'$>$>{$K$K @ @ u)9&>&>&>????	@ 	@ 	@ 	@ 	@ 	@@ @r   c                 t   t           }t          t                              |                    | _        | j        D ]}}|j                                        D ]a}t          |t          j	        j
        j                  s|j        dk    s2|j         d|j         }|                     |          | j        |<   b~t          | j                  }|D ]}| j        |         }|j        }t          |t                    r|j        r|                     |          }t          |t&          t(          f          rt|D ]p}	d}
|j        D ]9}|                    |	dz             r|                     |||j                   d}
:|
s)|                     ||	 d|j        pd |j                   qt1          d|          d	S )
ud   
        Вызывается после загрузки моделей при создании app)model_filteridr!   )r   F)r   Tz#Unsupported nested_fields for fieldN)r   rO   r   iter_models_models_listr   valuesrF   rG   r   
base_model
CmfRelBaser   r   r   sortedr   rL   r   CmfBackrefBaserH   
startswithr   r   	TypeError)rP   r   r   r   field_full_namesorted_fields
field_namefield_cachefield_modelsfield_modelfoundrW   s               r   build_fields_cachez RelationCache.build_fields_cacheW  s!       3 3 3 N NOO
 % 	W 	WE,,.. W W"5#**?*JKK uO_cgOgOg%*%5"J"J8H"J"J58^^PU^5V5V!/22	W s011' 	W 	WJ+J7K+E %,, W1D W"99%@@enj%ABB W'3 	m 	m %161D - --0;;KOLL - #z;LV[Vc d d d(,$ mNN *{,T,TU]=Rd,T,T^c^k + m m m	m $$I:VVV'	W 	Wr   c                     | j                             |          }|r3|j        rdS |j        r%t	          |j        t          t          f          rdS d S d S d S )NT)r   r   r   rx   rF   r   r   rH   )rP   r   fcs      r   _is_tree_fieldzRelationCache._is_tree_field  st    ""?33 	| t{ z".?J:WXX t	 	
   r   
inst_field	target_idc                    |j         j        }|j        }| d| }| j        |         }|j        }|                    d          d         }t
          j        r|j        r	 |j        D ]\  }	}
|
                    d          \  }}}|	                    d          \  }}}t          |t          t          f          r.||k    r'|                     |||j         j        j        |           t          d|          |j        D ]t}|                    d          \  }}}t          |t          t          f          r.||k    r'|                     |j         j        j        |||           et          d|          dS )uk  
        Рвём связь между field.instance и target_id, если она существует
        По field и fields_cache мы должны понять:
          - есть ли такая связь в кеше
          - поля, между которыми связь
          - кто родитель и кто потомок
        r!   r-   r   Unsupported right_for for fieldUnsupported children for fieldN)instancer   r   r   rr   r   rD   r   r   rF   r   rH   r   r   r<   r   rx   )rP   r   r   r   r   r   r   r   target_model_nameparent_field_full_namechild_field_full_namechild_model_name_rj   parent_model_namerQ   child_full_field_names                    r   remove_field_referencez$RelationCache.remove_field_reference  s    &.9*
-<<
<</%//44Q7 . 	:3Z 	  >@\ 	T 	T9"$94I4S4STW4X4X1a!16L6V6VWZ6[6[3q"3%/:!>?? T$(999''	3DjFYF\Fbdtuuu A?SSS &([ 	S 	S!4I4S4STW4X4X1a!1%/:!>?? S$(888''
(;(>(DjR[]mnnn @/RRR	S 	Sr   targetc                 8   |j         j        }|j        }| d| }| j        |         }|j        s	|j        sdS d}d}	|rK|j        j        }t          |t          j	        j
                  r|j        j        }|j        j        }	|j        }
n|                    d          d         \  }
}}|j        }|j         }d}d}t          |t          j	        j
                  r|j        j        }|j        j        }t          j        r	|j        rdS |j        D ]\  }}|                    d          \  }}}|                    d          \  }}}t%          |t&          t(          f          r.|
|k    r'|                     |||j        j        |||	||           t-          d|          |j        D ]t}|                    d          \  }}}t%          |t&          t(          f          r.|
|k    r'|                     |j        j        |||||||	           et-          d|          dS )u`  
        Создаём связь между field.instance и target_id, если нужно
        По field и fields_cache мы должны понять:
          - есть ли такая связь в кеше
          - поля, между которыми связь
          - кто родитель и кто потомок
        r!   Nr-   r   r1   r2   r4   r5   r   r   )r   r   r   rx   r   r   r<   
isinstancerG   r   	CmfEntitynamecoderr   r   r   rD   r   rF   r   rH   r   r   )rP   r   r   r   r   r   r   r   target_nametarget_coder   r   r   r   instance_nameinstance_coder   r   r   rj   r   rQ   r   s                          r   add_field_referencez!RelationCache.add_field_reference  s    &.9*
-<<
<</{ 	2< 	F 	B	I&#*"677 0$k/$k/ & 1&/&9&9#&>&>q&A#q!&h
 455 	0$M/M$M/M. 	:3Z 	F >@\ 	T 	T9"$94I4S4STW4X4X1a!16L6V6VWZ6[6[3q"3%/:!>?? T$(999$$!#4hk6GIY$/[#0] % L L L
   A?SSS &([ 
	S 
	S!4I4S4STW4X4X1a!1%/:!>?? S$(888$$ ):yBR$1}#.; % H H H
   @/RRR
	S 
	Sr   c                    d }d }t          |t          j        j                  r|j        j        }|j        j        }|                    d          \  }}}| j        |         }|j	        }	t          ||	j                  }
|
sd S d }d }t          |
t                    rFt          |
j        t          j        j                  r"|
j        j        j        }|
j        j        j        }|j        D ]\  }}|                    d          \  }}}|                    d          \  }}}t          |	t                    rG|
j        j        |k    r6|                     |
j        j        j        ||j        j        |||||           t          |	t"                    rt%          d|          |j        D ]}|                    d          \  }}}t          |	t                    rG|
j        j        |k    r6|                     |j        j        ||
j        j        j        |||||           xt          |	t"                    r|
j        D ]y}|j        |k    rld }d }t          |t          j        j                  r|j        j        }|j        j        }|                     |j        j        ||j        j        |||||           zt%          d|          d S )Nr!   r   r   r   )r   rG   r   r   r   r<   r   rr   r   r   rC   r   r   r   rF   r   r   rH   r   rx   )rP   r   inst	inst_name	inst_coder   r   r   r   fr   inst_field_nameinst_field_coder   r   r   rj   r   rQ   r   rel_instrel_inst_namerel_inst_codes                          r   _make_field_relationsz#RelationCache._make_field_relations  s1   
 		dCJ011 	(	I	I*9*C*CC*H*H'!Z/NT1<00
 	Fj/22 	:z*BRTWT^Th7i7i 	:(.39O(.39O >@\ 	T 	T9"$94I4S4STW4X4X1a!16L6V6VWZ6[6[3q"3!_-- T#.2CCC $$"(+13D'7$3#,	 % D D D Az** T A?SSS%'[ 	S 	S!4I4S4STW4X4X1a!1!_-- S#.2BBB $$z"(+13C$-9#2	 % P P P Az** S * 0 P PH*.>>>(,(,%h
0DEE @,4M,?M,4M,?M (( GM:$K-/?(1y'4	 ) P P PP   @/RRR;	S 	Sr   c           	      H   d}d}d}| j         D ]}t          |t          j        j                  s#t          d|j                    |dz  }|j        }|j        	                    |          
                    |j        j                            d                                                     }||j        	                    |          
                    |j        j                            d                                                     z  }t                      }g }|j        	                    |j        |j        |j                  D ]C\  }	}
}|
|f|v r |dz  }|dz  }|                    |	           ,|                    |
|f           D|j        	                    |          
                    |j                            |                                        d           |r"|dz  }t          |j         d| d| d           t          | d	| d
           d S )Nr   zClear r'   F)synchronize_sessionrp   z
 deleted, z duplicate refs/z m2m tables cleared)r   rF   rG   r   BaseM2MModelprintr   dp_modeldpquery_deprecatedr8   r*   isnotr   root_idrc   r   r   r   rM   rd   in_)rP   models_count	dup_countclearedr   r   deleteduniq_reldup_idsrel_idr   r   s               r   clear_old_m2m_treez RelationCache.clear_old_m2m_treeR  s2    	% !	[ !	[EeSZ%<== -5+--...AL~Hh//99@@AYA_A_`dAeAeffmmooGux00::AA%.BXB^B^_cBdBdeellnnnG uuHG-2X-F-Fx{T\Tdfnfw-x-x 6 6)X&(22qLGNINN6****LL'8!45555H%%h//66x{w7O7OPPWWlqWrrr [1)YYGYYyYYYZZZ<<<<<<=====r   <   	log_startalarm_levelalarm_thresholdc                     t                                            t          j                            d          }dt          j        d<   t          d            j                             j                  	                                }t          d| d            
                                 t          dt          j        d           fd	            } j        D ] |j                                                     |t          j        d= n|t          j        d<   t                                            d
S )u  
        Актуализация данных в таблице. Требуется монопольный режим для обеспечения целостности.
            TODO: Лок на таблицу
        Пока лучше выключать срм на время ребилда:
            systemctl stop eva-app
            cd /opt/eva-app
            python3 ./manage.py shell <<<"models.RelationCache.recalculate()"
        Есть смысл делать при обновлении, после наката миграций.

        TODO: clear=True - предварительно очистить таблицу.
        TODO: выборочный пересчёт
        NO_CACHE1zClear relation_cachez  z ClearedFr'   r   c                    d}g }g }	j                                         D ]u}t          j        rt	          |dd          r 	j         d|j         }                    |          r/|                    |           |                    |j                   v|sd S 	                    dddg|          D ]"}|d	z  }|D ]}	                    ||           #t          d
	j         d| d           d S )Nr   r   Fr!   r   r   r   r   r'   zBuild relations from z done, z objects)r   r   r   rD   rC   r   r   rM   rO   r   r   )
_model_namecount_tree_fields_full_namestree_fields_namesr   r   r   r   rP   r   s
           r   create_model_relationsz9RelationCache.recalculate.<locals>.create_model_relations  sN    F%'" ",,.. ? ?6 75Jhjo;p;p %*%5"J"J8H"J"J%%o66 ?*11/BBB%,,U-=>>>) !JJtVV.XFW.XJYY D D!"8 D DJ--j(CCCCDS%*:SS6SSSTTTTTr   N)	CMF_CACHEflushdbosenvironr   r   r   r   r   r   r   r   loggingWARNINGr   r   fix_relation_locations)rP   	cache_oldcountr  r   s   `   @r   recalculatezRelationCache.recalculate|  sT     	 JNN:..	!$
:
 	$%%%''55<<>>"5"""### 	   	%W_a	P	P	P	U 	U 	U 	U 	U 
Q	P	U2 % 	5 	5E""5#34444 	""$$$
:&&%.BJz" 	r   c            
         ddl m} m} ddlm} t          |                                          D ]}t          |t                    st          ||           r-t          d|j                    d}d}d}|                    dg          D ]}|dz  }|j        r|j        sP|dz  }t          d|j         d	|j        j         d
|j        j                    |                                 |dz  }e|j        j                            d          d         }|j        j                            d          d         }	|j        | |	 k    r"|dz  }t          d|j         d	| d
|	            t          | d| d| d           t          ||          rKt          d|j                    d}d}d}|                    dg          D ]}|dz  }|j        j                            d          d         }
|j        j                            d          d         }|j        j                            d          d         }	|j                            |          sn|dz  }t          d|j         d	| d
|	            t)          ||
d          r"t)          ||d          rt)          ||d          s|                                 |dz  }t          | d| d| d           dS )u6  
        TODO: временно, после патчинга баз - убрать.
        Из-за бага, м2м связи могут быть в 'чужой' таблице. Найдём их и исправим.
        python3 ./manage.py shell "models.RelationCache.fix_relation_locations()"
        r   )CmfM2MModelCmfGM2MModel)r   zCheck Model r   r   r'   zInvalid z: z - r-   r   z rows invalid, z fixedN)
cmf.modelsr  r  rA   r   varsr   r   typerF   r   r   rO   r   r   r   r<   r   rr   r   rC   )r  r  r   r   	all_countinvalid_countfixed_countr   left_model_nameright_model_nameid_model_names              r   r  z$RelationCache.fix_relation_locations  s    	98888888&&&&&&&\\((** *	X *	XEeT** %-- X7U%577888	 ! %

3%
 8 8 ` `HNI#+ !83D !%*lll8H8NllS[SdSjllmmm )))#q( &.&6&<&F&Fs&K&KA&NO'/'8'>'H'H'M'Ma'P$'o+Q?O+Q+QQQ%*^^^^^L\^^___VVVV;VVVWWW%.. X7U%577888	 ! %

3%
 8 8 - -HNI$,K$5$?$?$D$DQ$GM&.&6&<&F&Fs&K&KA&NO'/'8'>'H'H'M'Ma'P$ +66GG -%*^^^^^L\^^___&v}dCC -'.v'M'M-'.v'M'M- %OO---'1,KVVVV;VVVWWWU*	X *	Xr   )NNN)NF)NNNN)N)NN)4r   r   r   r   abstract	api_allowFieldCmfTUUIDr   r*   CmfTextr&   r;   r3   CmfIntr6   r$   r1   r2   r0   r4   r5   classmethodr\   rg   rl   r   r   r   	dataclassr   r   r   r   r   r   r   r   strr   rG   r   CmfModelr   r   r   r   r	  r
  r  staticmethodr  r   r   r   r   r      s       	 	 HI	E  PED4
H 
H 
HB h(=TJJJI5*PQQQLuX':$GGGH%)MNNNKE&"=>>>E 5*IJJJL%)BCCCK%)BCCCK%)FGGGKw(XYYYJw(?@@@J = = = [=~ 
 
 
 [
 = = = [=,  MQJ J J [JX 7. 7. [7.x 	% 	% 	% 	% 	% 	% 	% 	% ML- - [- @ @ @ [@* (W (W [(W^   [ +S
 +Ss +S +S +S [+SZ BS BSZ BSC BSX[XbXk BS BS BS [BSH JS JS [JSX '> '> ['>R Ve"MMME E NM [EP 3X 3X \3X 3X 3Xr   r   )r   collectionsr   cmf.models.base_modelrG   cmf.fields.base_fieldsrA   cmf.cmf_profiler   r   	BaseModelr   r   r   r   <module>r+     s        # # # # # #     $ $ $ $     " " " " " "iX iX iX iX iXCJ( iX iX iX iX iXr   