
    *`mh                       d dl Z d dlZd dlZd dlZd dlZd dlZd dlmZmZ d dl	m
Z
 d dlmZ d dl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 i Zd!d
Zd Zd Zd Zd!dZd Zd!dZd Zd Z  G d d          Z! G d d          Z" G d de"          Z# G d de"          Z$d"dZ% G d d          Z& G d d           Z'dS )#    N)defaultdict
namedtuple)deepcopy)List)g)fields)config   )	BaseModelc                    ddl mm ddl m  ddlm} 	 t          | |          r|| j        j        j        }| j	        } n|| j        j        } G fdd|j
                   ||                               |           S )Nr   )date	timedelta)datetime)Queryc                   :     e Zd Z	 	 ddZd Z fdZ xZS )%render_query.<locals>.LiteralCompilerFc                 B    |                      |j        |j                  S N)render_literal_valuevaluetype)self	bindparamwithin_columns_clauseliteral_bindskwargss        ./cmf/data_providers/base.pyvisit_bindparamz5render_query.<locals>.LiteralCompiler.visit_bindparam.   s    ,,Y_inMMM    c                      t          |t                    r%dd                     fd|D                       z  S                      |          S )Nz{%s},c                 <    g | ]}                     |          S  )render_array_value).0x	item_typer   s     r   
<listcomp>zLrender_query.<locals>.LiteralCompiler.render_array_value.<locals>.<listcomp>4   s*    )])])]TU$*A*A!Y*O*O)])])]r   )
isinstancelistjoinr   )r   valr'   s   ` `r   r$   z8render_query.<locals>.LiteralCompiler.render_array_value2   s]    #t$$ _)])])])])]Y\)])])] ^ ^^^,,S)<<<r   c                     t          |t                    rt          |          S t          |f          rd|                    d          z  S t          |          r&dt	          |                              dd          z  S t          |t                    r%dd                     fd|D                       z  S t                     	                    |          S )Nz'%s'z%Y-%m-%d %H:%M:%S'z''z'{%s}'r!   c                 F    g | ]}                     |j                  S r#   )r$   r'   )r%   r&   r   type_s     r   r(   zNrender_query.<locals>.LiteralCompiler.render_literal_value.<locals>.<listcomp>@   s,    ,h,h,h]^T-D-DQ-X-X,h,h,hr   )
r)   intreprstrftimestrreplacer*   r+   superr   )r   r   r0   LiteralCompiler	__class__r   r   r   s   ` `r   r   z:render_query.<locals>.LiteralCompiler.render_literal_value7   s    %%% kE{{"ED(#344 k/B C CCCE9-- kE

 2 23 = ===E4(( k388,h,h,h,h,hbg,h,h,h#i#ijj$//DDUERRRr   )FF)__name__
__module____qualname__r   r$   r   __classcell__)r8   r7   r   r   r   s   @r   r7   r   ,   s        CH*/	N 	N 	N 	N	= 	= 	=

	S 
	S 
	S 
	S 
	S 
	S 
	S 
	S 
	S 
	S 
	S 
	S 
	Sr   r7   )r   r   r   sqlalchemy.ormr   r)   sessionbinddialect	statementstatement_compilerprocess)rA   r@   r   r7   r   r   r   s      @@@@r   render_queryrD      s    ((((((((!!!!!!$$$$$$ )U## )?',4G'			.(S S S S S S S S S S'4 S S S. ?7I..66yAAAr   c                 6    t                               |           S )uK   Вернём драйвер по имени источника данных)ds_registryget)ds_names    r   get_ddrI   F   s    ??7###r   c                      t           rt          d          d} t          j                                        D ]F\  }}|                    d          dk    r| ddlm} |} | |d<   t          ||          t           |<   GdS )uY   Инициализация всех источников данных из конфигаuZ   Источники данных нельзя инициализировать дваждыNzsqlalchemy.poolclass	QueuePoolr   )rK   )name)	rF   	Exceptionr	   data_sourcesitemsrG   sqlalchemy.poolrK   new_dd)
queue_poolrH   	ds_configrK   s       r   init_dsrT   K   s     vtuuuJ$17799 ? ?==/00K??!555555&
0:I,-  &ig>>>G? ?r   c                      t                                           D ]K\  } }t          d|             	 |                                 -# t          $ r t          d           Y Hw xY wdS )u=   Инициализация, миграция схемы БД.zInit DB u        не реализовано.N)rF   rO   printinit_dbNotImplementedError)rH   ds_dds     r   rW   rW   [   s    %++-- 7 7"""###	7MMOOOO" 	7 	7 	7566666	7	7 7s   AA#"A#c                 &   |                      d          }|s|                      d          }|dk    rd}|st          d||           |                    dd          \  }}t          j        |          }t          ||          } || |	          S )
Nclassr   
sqlalchemyz2cmf.data_providers.sqlalchemy:SQLAlchemyDataDriverzDYou must specify valid "type" or "class" in datasource configuration:   )maxsplitrS   rL   )rG   
ValueErrorsplit	importlibimport_modulegetattr)rS   rL   dd_mod_classdd_typedd_module_namedd_class_name	dd_moduledd_classs           r   rQ   rQ   f   s    ==))L P--''l""OL s`bfhqrrr$0$6$6sQ$6$G$G!NM'77Iy-00H8id3333r   c                  f    t                                           D ]} |                                  d S r   )rF   valuesbefore_requestdds    r   rn   rn   u   s<      ""  
 r   c                     | r)t          t          d          rt          j        d           t                                          D ]-}| r|                                 |                                 .d S )NdebugROLLBACK)hasattrr   rr   rF   rm   rollbackcommit)	exceptionrp   s     r   commit_all_dsrx   {   s{      1g 	 GJ  ""   	 KKMMMM IIKKKK r   c                      t                                           D ]-} t          j        d|             |                                  .d S )Nz	ROLLBACK )rF   rm   r   rr   ru   ro   s    r   rollback_all_dsrz      sO      ""  	 B  !!!
 r   c                  t    ddl m}  t                                          D ]}|                    |            dS )zmake_models hookr   modelsN)cmf.includer}   rF   rm   make_models)r}   rp   s     r   r   r      sN    """"""  ""  
v r   c                       e Zd ZdZddddZd Zd Zd Zd Zd	 Z	d
 Z
d Zd Zd Zd Zd Zd Zd Zd Zd Zd ZdS )BaseDataDriver Nr`   c                "    || _         || _        d S r   )r	   rL   )r   rS   rL   _args_kwargss        r   __init__zBaseDataDriver.__init__   s    			r   c                     d S r   r#   r   modelargsr   s       r   rG   zBaseDataDriver.get       r   c                     d S r   r#   r   instancer   r   s       r   createzBaseDataDriver.create   r   r   c                     d S r   r#   r   s       r   deletezBaseDataDriver.delete   r   r   c                     d S r   r#   r   s       r   updatezBaseDataDriver.update   r   r   c                     d S r   r#   r   s       r   r*   zBaseDataDriver.list   r   r   c                     d S r   r#   r   s       r   countzBaseDataDriver.count   r   r   c                     d S r   r#   r   s    r   rv   zBaseDataDriver.commit   r   r   c                     d S r   r#   r   s    r   ru   zBaseDataDriver.rollback   r   r   c                     d S r   r#   r   s    r   rn   zBaseDataDriver.before_request   r   r   c                     d S r   r#   )r   	cmf_models     r   dp_modelzBaseDataDriver.dp_model   r   r   c                     d S r   r#   )r   sa_models     r   r   zBaseDataDriver.cmf_model   r   r   c                     d S r   r#   )r   dp_instances     r   is_instancezBaseDataDriver.is_instance   r   r   c                     d S r   r#   )r   models_s     r   r   zBaseDataDriver.make_models   r   r   c                     dS )u,   Вернём кастомный запросNr#   r   r   r   s      r   query_deprecatedzBaseDataDriver.query_deprecated         r   c                     t           )u2   Создание/миграция схемы БД.rX   r   s    r   rW   zBaseDataDriver.init_db   s    !!r   c                     dS )u8   Закрываем текущие подключенияNr#   r   s    r   close_all_sessionsz!BaseDataDriver.close_all_sessions   s    r   )r9   r:   r;   __doc__r   rG   r   r   r   r*   r   rv   ru   rn   r   r   r   r   r   rW   r   r#   r   r   r   r      s'       
F)-D                               ; ; ;" " "    r   r   c                   H    e Zd Zd ZddZd Zd Zd	dZed	d            Z	dS )

BaseMapperc                     dS )u  
        Вызывать по завершению маппинга всех объектов в запросе, постобработка.
        Обычно должен вызывать тот, кто создал экземпляр маппера.
        Nr#   r   s    r   post_mapping_hookzBaseMapper.post_mapping_hook   r   r   Nc                     t           r   r   )r   obj
cmf_entityr   
model_namefull_fields_loads         r   object_to_cmfzBaseMapper.object_to_cmf       !!r   c                     t           r   r   )r   r   r   s      r   cmf_to_objectzBaseMapper.cmf_to_object   r   r   c           	      x   |sdS fd|j         D             }t          dt          f|          }|                                |_         |j         D ]i}|                     d          rOd                    |                    d          dd                   }t          ||t          ||                     j|S )u  
        TODO: создание промежуточного объекта плохо для производительности, нужно маппить напрямую из ResultSet
          да и в целом можно зарефакторить
        Nc                     i | ]K}|                      d           d                    |                    d          dd                   dLS )_sub__r^   N)
startswithr+   rb   )r%   field
field_names     r   
<dictcomp>z4BaseMapper.obj_from_result_query.<locals>.<dictcomp>   si     6 6 6: 3 3 3446IIekk$''+,,d6 6 6r   CmfObjr   r   r^   )	_fieldsr   objectkeysr   r+   rb   setattrre   )r   result_queryr   
obj_fieldsresr   attnames     `    r   obj_from_result_queryz BaseMapper.obj_from_result_query   s    
  	46 6 6 6%-6 6 6
 8fZ44 oo''!) 	D 	DE: 3 3 344 D))EKK$5$5abb$9::WglE&B&BCCC
r   c                 (      fd|D             S )Nc                 @    g | ]}                     |           S )r   r   )r   )r%   r   r   r   r   s     r   r(   z*BaseMapper.list_to_cmf.<locals>.<listcomp>   s0    ggg\_""3eFV"WWgggr   r#   )r   lstr   r   s   ` ``r   list_to_cmfzBaseMapper.list_to_cmf   s&    ggggggcfggggr   c                     |st                      S |dk    rt                      S t          |t                    r|S t	          |t                    r
 |            S t          d          )u   
        :param mapper: тип маппера
        :type mapper: None, str, Mapper subclass, Mapper instance
        :return: экземпляр маппера
        :rtype:  Mapper
        simplezInvalid mapper)MapperSimpleMapperr)   r   
issubclassra   )clsmappers     r   
get_mapperzBaseMapper.get_mapper   sm      	88OX>>!fj)) 	Mfj)) 	688O)***r   NNNNr   )
r9   r:   r;   r   r   r   r   r   classmethodr   r#   r   r   r   r      s          " " " "" " "  (h h h h + + + [+ + +r   r   c                        e Zd ZdZ ej                     G d d                      Z edg d          Z fdZ	d Z
d
d	Z xZS )r   u   
    Dataclass as model, для лёгкой сериализации в json
    fill class_name
    TODO fill meta для api, но вероятно это драйвер будет делать, там дешевле
    c                   $    e Zd ZU dZeed<   d ZdS )SimpleMapper.SimpleModelNidc                     t          | d          r| j         d| j         d| j         dS | j         dt	          | dd            dS )NrL   (z: )r   )rt   
class_namecoderL   re   r   s    r   __repr__z!SimpleMapper.SimpleModel.__repr__  s_    tV$$ F/EEDIEEEEEEoDDdD(A(ADDDDr   )r9   r:   r;   r   r4   __annotations__r   r#   r   r   SimpleModelr     s9          C	E 	E 	E 	E 	Er   r   VirtualInitDatar   r   
field_listc                 V    t                                                       g | _        d S r   )r6   r   _virtual_init_list)r   r8   s    r   r   zSimpleMapper.__init__  s'    "$r   c                    i }t          | j                  D ]}|                    |j        j                  }|r|j        |_        n*|                    |j                  }|||j        j        <   |j        D ]>}t          ||j                  }d|_	        t          |j        |j        |j                   ?g | _        dS )uN   Вычислим все запрошенные виртуальные поля)simple_objectN)reversedr   rG   r   r   r   r   r   re   _valuer   r   )r   cmf_instances	init_datacmf_wrapper	field_clsvirtual_fields         r   r   zSimpleMapper.post_mapping_hook#  s     "$"9:: 	U 	UI'++IO,FGGK H,5,<))'ooI<LoMM<Gio89&1 U U	 'Y5I J J'+$	()*>@STTTTU #%r   Nc           
         ddl m} |s2|s |j                            d          d         }t	          ||          }|s&t
                                          }|j        |_        nt          d||          g }|p|j	        D ]Q}d|v r!t          ||t	          ||d                     (|j	                            |          }	|	sE|	j        r!|s	|	j        dv r|                    |	           mt          |	t          j        t          j        f          rt	          ||	                                d          }
|
du r|
d}n|o|                    |          }|rBt	          || d	d          ,|                     |                     ||          |
          }nHt          |	t          j        t          j        t          j        f          rPt	          ||d          }|du rgt          |	t          j                  rF|                     ||o|                    |          t	          ||	j        d                             }nyt          |	t          j                  r/|r-|j        s%|                    t:          j        j                  }n0t          |	t          j                   r|rtC          j"        |          }t          |||           S|r5| j#                            t
          $                    |||                     |S )u  
        отображение obj -> simple_model
        если cmf_entity не указан, то создадим новый на основе модели cmf_model или её имени model_name
        возвращаем simple_model
        r   r|   r]   uI   Передан cmf_entity в SimpleMapper, вероятно это багr   .)defaultalwaysN_sub__id)r   tzinfor   )%r~   r}   r   rb   re   r   r   r   ra   r   r   rG   virtual	load_modeappendr   CmfRelationCmfGenericRelationid_fieldnamer   r   
CmfM2MBaseCmfBackrefBaseCmfDateRangeCmfObjectListr   CmfDateTimer   r5   r   timezoneutcCmfJsonujsonloadsr   r   )r   r   r   r   r   r   r}   virtual_fieldsr   r   obj_related_idfield_valuesub_ffls                r   r   zSimpleMapper.object_to_cmf6  sd    	'&&&&&  	0 2 V\\#..q1
FJ//E 	{%1133J$)$4J!!hjtvyzzz*:el 6	9 6	9Jz!!
JZ0M0MNNN((44I   &6 ):MQf:f:f%%i000)f&8&:S%TUU <!(i.D.D.F.F!L!L!S((!)"&KK.S3C3G3G
3S3SG ! #3:(?(?(?FFR*.*<*< $ : :3
 K K18 += +: +:KK % I(96;PRXRe'fgg <%c:s;;c!!)V%9:: 	7"..!1!V6F6J6J:6V6VFI$4Q$788: : Iv'9:: 7{ 7") T"-"5"5X=N=R"5"S"SKIv~66 7; 7#k+66J
K8888 	i#**,,JeXf,ggi i ir   r   )r9   r:   r;   r   dataclasses	dataclassr   r   r   r   r   r   r<   )r8   s   @r   r   r     s         
 [
E 
E 
E 
E 
E 
E 
E 
E !j!24U4U4UVVO% % % % %
% % %&P P P P P P P Pr   r   c                       e Zd ZddZd ZdS )r   Nc           
         ddl m} |sC|s2|s |j                            d          d         }t	          ||          } |d          }d}nd}|st          |          }|}|r|}	n|j                                        }	|	D ]7}
|j                            |
          x}s |j	        r,|s|j
        dk    rt	          ||
          }d|_        d|_        St          |t          j        t          j        t          j        f          rt	          ||
d	          }t          |t          j                  rJ|d	u r|                     ||o|                    |
          t	          ||j        d                             }t          |t          j        t          j        f          rt	          ||                                d	          }|d	u rI|d}n|o|                    |
          }|rt	          ||
 d
d          dk    rt	          ||
 d
          rt          |t          j                  r|                    d          d         n|j        }t	          ||d          }|r-|                     |                     ||
          ||          }nd}n|d	u rt          |t          j                  r.|r,|j        s%|                    t8          j        j                  }t          |t          j                  r|                     |          }n0t          |t          j!                  r|rtE          j#        |          }t	          ||
          }|r	|j        d	u rRtI          |tJ          tL          tN          t          d          tP          f          r||_        ntS          |          |_        ||_        9d|_*        |+                                 |S )u  
        отображение obj -> cmf_entity
        если cmf_entity не указан, то создадим новый на основе модели cmf_model или её имени model_name
        возвращаем ссылку на cmf_entity
        r   r|   r]   T)emptyFr   N.r   r   r   ),r~   r}   r   rb   re   r   r   r   rG   r   r   r   _oldr   r  r  r  r  r   r   r   r  r   r   r   r  r   r5   r   r  r  CmfIPv4NetworkListdb_castr	  jsonr  r)   r4   r1   floatboolr   is_newmark_exists_in_db)r   r   r   r   r   r   r}   cmf_is_existsr   r   kr   r   r  r  r  	model_sub	field_objs                     r   r   zMapper.object_to_cmf  sF    	'&&&&& 	! 4! 6!$c!2!21!5J
33T***J!MM M 	%$$E 	'#DD<$$&&D M	+ M	+A!&!1!1!!4!44I   &6 ):MQY:Y:Y
A..#!
 )f&79NPVPc%dee !#q#..K)V%9:: u#%%"..!1!M6F6J6J16M6MwW]_h_opq_rOsOsu u )f&8&:S%TUU !!(i.D.D.F.F!L!L!S((!)"&KK.J3C3G3G3J3JG !"<ADDJJwWchiesesesOtOtJIST]_e_xIyIy *5)=)=c)B)B1)E)E%._ '(/
D(I(II  ) 3.2.@.@$($>$>|Q$O$O*3g /A /O /O /3$  c!!)V%788 T[ T") T"-"5"5X=N=R"5"S"SK)V%>?? 6'//<<Iv~66 6; 6"j55  
A..I ! ;INc$9$9kCeT$ZZ+NOO ;%0INN%-k%:%:IN*I!
$$&&&r   c           	         t          |          }|j                                        D ]O\  }}t          |t          j                  r!t          |t          j                  r<t          |t          j                  rWt          |t          j                  rrt          |t          j                  rt          |t          j	                  rt          |t          j
                  rt          ||          }t          |t          j                  r5|j        du s|j        r|j        s	|j        s|                                }|du rt'          d| d| d|           t)          |||           Q|S )N.u%   Попытка update field=Ellipsis  )r   r   rO   r   r   r   CmfM2MCmfGenericM2M
CmfBackrefr  CmfGenericBackrefre   r)   CmfTyper   r   
is_changed	orm_dirty	db_formatrM   r   )r   r   r   r   r  vvvs          r   r   zMapper.cmf_to_object  s   Z  L&&(( 	  	 DAq!V/00 !V677 !V]++ !V122 !V.// !V011 !V566 Q''B"fn-- 	$9##rz#
 } R\ \\^^Syy ]
 ] ]UV ] ]Y[ ] ]^^^CB
r   r   )r9   r:   r;   r   r   r#   r   r   r   r     s<        j j j jX! ! ! ! !r   r   selectc                    	 dt           vrt          t                    t           _        n# t          $ r}Y d}~dS d}~ww xY wt           j                            dt          t                               t           j        d                             | d           t           j        d         | xx         dz  cc<   t           j        d                             dd           t           j        d         dxx         dz  cc<   dS )uK   
    Глобальный счетчик запросов
    :return:
    profiler_dataNselect_countr   r^   total)r   r   dictr0  rM   
setdefault)actiones     r   inc_select_countr7    s    !##)$//AO    O~{4/@/@AAAON#..vq999ON#F+++q0+++ON#..w:::ON#G,,,1,,,,,s   '* 
??c                       e Zd ZdZ ej        d          ZddZed             Z	ddddddZ
d	d
dZd Zd ZdddZd Zd Zd Zd ZddZd ZddddddZdddddZdddZdS )DataProvideruV   Объект, связывающий модель с источником данныхz"\b(?P<table>\w+)\.(?P<field>\w+)\bNc                 H    || _         || _        d | _        t          | _        d S r   )r   data_source_ddr   
mapper_cls)r   r;  r   s      r   r   zDataProvider.__init__1  s#    
& r   c                 P    | j         st          | j                  | _         | j         S r   )r<  rI   r;  r   s    r   data_driverzDataProvider.data_driver7  s%    x 	0d.//DHxr   F)no_cacheTECHCOM_nocache
for_updatecache_inmemoryc                &   |rt          d          | j        j        p=|p;t          j        p/|p-t
          j        j                            | j        j	                  }| 
                    | j        |          |d<   fdt          j        r| j        j	        dv r| j        j	        t
          j        j        j        vr#i t
          j        j        j        | j        j	        <   t
          j        j        j        | j        j	                 }|                    dd          r% ||                    dd                     ||d<   t          j        j        j        | j        j	         dg|R d|i|}|rd}	n&t
          j        j                            ||	          }	t                       |	d
k    r9t
          j                            t
          j        j        j        d|            dS |	9t
          j                            t
          j        j        j        d|            |	S t
          j                            t
          j        j        j        d|             | j        j        | j        g|R d|i|}
| j        j        dk    r|
S |r	|
rd|
_        |r|
S t
          j        j                            ||
| j        j	         |                     | j        |d         |                    d          |                    d                    |           |
S )zF
        :param args:
        :param kwargs:
        :return:
        8   no_cache запрещен и будет удален osvfilterc                     |                                 D ]3\  }}|| vr||         | |<   | |         |k    r | |         |           4d S r   )rO   )_fields_grow_cache_full_fields_loadr  r,  _grow_merges       r   rJ  z%DataProvider.get.<locals>._grow_mergeQ  st    )//11 > >1...,=a,@&q)))!,11#$6q$91===> >r   )
CmfProjectCmfWorkflowCmfLogicTypeCmfSchemeWfCmfSchemeWfRuleCmfActivityr   Nz.getrC  rC  EmptyzDP: get() cache Empty zDP: get() cache zDP: get() NOcache rB  rdiskTorder_bygroup_byquery_paramsrC  )rM   r   TEXKOM_no_cacher   import_modecmfapp	CMF_CACHEcache_is_lockedr9   _get_filterTEXCOM_ENABLE_GROWCACHE_HACKtexcom_growcache_hack_cacherG   hashr7  print_debugDEBUGr?  rL   readonlyadd_query_params)r   r@  rA  rB  rC  r   r   fields_grow_cachekeycachedb_resrJ  s              @r   rG   zDataProvider.get=  s9     	XVWWW:- M MAM MU_ Mg'77
8KLL 	  ++DJ??x	> 	> 	> 	> 	> ) 	?J' ,] ] ]z"#'*;*WWWUW!=dj>QR # 1 MdjNa bzz,d33 ?-vzz:Ld/S/STTT->)*g$
(;%A%A%ArDrrrYgrkqrr 	NEEG%))#n)MMEGG 1 79WRU9W9WXXX4G 1 79QC9Q9QRRRLG 1 79Sc9S9STTT)T%)$*]t]]]
]V\]]F $// '& '"&  G!!V
 35!//
F8<LfjjYcNdNdflfpfpq{f|f|}}- "   
 Mr   T)
invalidatec                   t          d            | j        j        |g|R i |}| j        j        dk    r|S |s|S |'t          j        j                            |d           d S t          j        j                            |d           |S )NinsertrS  r   )r7  r?  r   rL   rZ  r[  r\  rk  )r   r   rk  r   r   r   s         r   r   zDataProvider.create  s    """%d%h@@@@@@  G++J 	J;G((8<<<4$$S(333
r   c                 H    t          d            | j        j        |i |}|S )Nr   )r7  r?  bulk_deleter   r   r   r   s       r   ro  zDataProvider.bulk_delete  s/    """*d*D;F;;
r   c           	      ~   dd l }ddlm} dd l}t	          d           t          j        d| d| d|             | j        j        |g|R i |}t          j        d           |j	        s |j                     }t          |          dk    r+t          j        j                            |j        d            n,|r*t          j        j                            |j        |            |j                     |z
  dz  }	|                    d	t          |           d
| d|	dd           |	dk    r |d|	dd           |S )Nr   	cmf_alertr   zbulk_update start model=z args=z kwargs=zbulk_update endi  u)   Инвалидировали кеш по u$    обьектам у таблицы u    за z.2fu    мс   u2   DEV: Инвалидация кэша заняла )timer~   rs  loggingr7  r   rr   r?  bulk_updaterX  lenrZ  r[  r\  invalidate_idsr   warning)
r   r   r   r   ru  rs  rv  r   
start_timeelapsed_times
             r   rw  zDataProvider.bulk_update  s   ))))))"""	N5NNNNfNNOOO*d*5B4BBB6BB	"###$ 	h"J3xx$!001A4HHHH H!001A3GGG%DIKK*4<LOO  [C  [  [v{  [  [  DP  [  [  [  [  \  \  \c!!	f|ffffggg
r   )r@  c                V   t          d           | j        j        st          j        d|j                     | j        j        |g|R i |}| j        j        st          j        d|j                    |rt          d          | j        j        }| j        j	        dk    r|S |s|
                    dd          rld}d|j        v r|j        j        r|j        rd	nd
}|j        rd
}t          j        j                            ||           t          j        d|j                    |S )Nr   z+Run self.data_driver.update(), instance_id=z+End self.data_driver.update(), instance_id=rE  rS  rk  Tcmf_deletedr   r   z0End cmf.app.CMF_CACHE.invalidate(), instance_id=)r7  r   rX  r   rr   r   r?  r   rM   rL   rG   r   r~  r)  r  rZ  r[  r\  rk  )r   r   r@  r   r   r   r5  s          r   r   zDataProvider.update  sX   """z) 	QGO(+OOPPP%d%h@@@@@@z) 	QGO(+OOPPP 	XVWWW:-  G++J 	VFJJ|T:: 	VF//H4H4S/%-%9Gx "!G((f555GTx{TTUUU
r   c                 *     | j         j        |i |}|S r   )r?  rv   )r   r   r   rets       r   rv   zDataProvider.commit  s!    %d%t6v66
r   c                 &     | j         j        |i |S r   )r?  ru   r   s      r   ru   zDataProvider.rollback  s    (t($9&999r   c                      | j         j        |i |}| j         j        dk    r|S t          j        j                            |d           |S )u   
        Logical delete. Реализация в провайдере или в модели?
        self.deleted = 1
        self.update()
        rS  r   )r?  r   rL   rZ  r[  r\  rk  rp  s       r   r   zDataProvider.delete  sV     &d%t6v66  G++J$$S(333
r   c                   	 |                     dg           }|g }|                     d          		si 	t          |t                    rt          j        |          }|r|g}|                                                                D ]J\  }}||j        v r<||= t          |t          j                  r|j	        }|
                    |d|g           Kdfd	fd	fd |          }|S )	u   
        Преобразуем обычные kwargs в продвинутый фильтр для однообразной логики фильтрования
        :param model:
        :param kwargs:
        :return:
        rF  Nfilter_context==c                     |s| j         }	 |                     |||          }nE# t          $ r8}t          |          dk    r | |||dz
            }nt          |Y d }~nd }~ww xY w|S )N)yearmonthdayzday is out of range for monthr^   )cur_datetimer  r  r  )r  r5   ra   r4   )r  r  r  r  new_dater6  _replace_month_years         r   r  z5DataProvider._get_filter.<locals>._replace_month_year  s     '"&,'//TC/PP , , ,q66<<<22SW_djmpqjqrrrHH$!+ HHHH,
 Os   % 
A'.A""A'c                 
   d}t          j        ||           }h d}dx}x}x}x}x}}	d }
|D ]}|\  }}}t          |          }d }|r|dk    rd}n|dk    rd}|s|
pd}|}
||v rZ|dk    r	|||z  z  }G|d	k    r	|||z  z  }V|d
k    r	|||z  z  }e|dk    r	|||z  z  }t|dk    r	|||z  z  }|dk    r	|	||z  z  }	t          j                    x}}|j        }|j        }|s|r|dk     rdnd}|t          |          dz  |z  z  }t          |          dz  |z  }||z   dk    r||z   dz
  }d|z   |z   }n$||z   dk    r||z   dz   }||z   dz
  }n
||z   }||z   } |||          }|t          j	        ||||	          z   S )Nz([+-]?)\s*(\d+)\s*(min|[ymwdh])>   dhmwyminr   +r^   -r  r  r  r  r  r  r     )r  r  r  )weeksdayshoursminutes)
refindallr1   r   nowr  r  absr   r   )time_strpatternmatchesallowed_unitsyearsmonthsr  r  r  r  	prev_signmatch	time_signr   unitsignr  	init_datecur_year	cur_month	init_year
init_monthr  s                         r   _parse_time_stringz4DataProvider._get_filter.<locals>._parse_time_string  sz    9Gj(33G<<<M>??E?F?U?T?EGI  "! "!).&	5$E

 " C'' "c))! *$>D 	=((s{{- %$,. - , - 54</ '(uww.L9#(H$*I m m#aZZrrQV*T11Vr)D0v%** (5 01 4I!#i&!8JJ'",, (5 01 4I!*V!3b!8JJ (5 0I!*V!3J//\PYaklll	x1DPU_fgggggr   c                 $   t          | t                    rfd| D             S t          | t                    rT| dk    rt          j        j        j        S | dk    rPt          j        sdt          _        n$t          t          j        d          t          _        t          j	                    S | dk    rPt          j        sdt          _        n$t          t          j        d          t          _        t          j
                    S |                     d          rdfd	 | d	d                    S |                     d
          rHt          j        sdt          _        n$t          t          j        d          t          _         |           S | S )Nc                 &    g | ]} |          S r#   r#   )r%   i_recursive_params_replaces     r   r(   zODataProvider._get_filter.<locals>._recursive_params_replace.<locals>.<listcomp>V  s%    EEE11!44EEEr   __G_CURRENT_USER__G_NOWi,  __G_DATEip  z__SELF.c                     |                      d          }|d         }|rt          ||d           }n|         }|d         r |d         |          }|S )N.r   r^   r
   )r   )	partitionre   )
value_pathr   partsattrr  get_ctx_attrs       r   r  zQDataProvider._get_filter.<locals>._recursive_params_replace.<locals>.get_ctx_attrk  sn     * 4 4S 9 9$Qx  9$+E4$>$>EE$24$8E 8 H$0Lq$G$G$GE$r   r
   znow()r   )r)   r*   r4   r   current_userr   r   jscache_timelifer  r  r   r   )rF  r  r  r  r  s    @r   r  z;DataProvider._get_filter.<locals>._recursive_params_replaceT  s   &$'' FEEEEfEEEE&#&& &6///>,22y((- M-3**-01CV-L-L*577Nz))- R-8**-01C[-Q-Q*688O&&y11 6
% 
% 
% 
% 
% 
% 
% (<qrr
333&&w// 6- M-3**-01CV-L-L*--f555Mr   r   )rG   r)   r4   r  r  copyrO   r   r(  r   r   )
r   r   r   smart_filterr  r,  r  r  r  r  s
         @@@@r   r^  zDataProvider._get_filter  se    zz(B//L$455 	 NlC(( 	4:l33L 	,(+LKKMM'')) 	2 	2DAqEL  1Ia00  A##QaL111
	 
	 
	 
	 
	 
	C	h C	h C	h C	h C	hL+	 +	 +	 +	 +	 +	 +	Z 10>>r   ANDc                    ddl m} ddl m} t          g g i           }|r|D ]}}	|	dk    r	|	                    d          r|	d d         |j        v r
|	d d         }	|	                    d          r
|	d	d          }	|d
                             |j         d|	            ~|rZ|D ]W}
|
                    d          r|
d d         |j        v r
|
d d         }
|d
                             |j         d|
            X|s|S t          |d         t                    rt|D ]o}|                     |||                                          D ]B\  }}|dk    r||                             |           '||                             |           Cpn1|d         dv r}|                     ||d	d          |d                                                   D ]B\  }}|dk    r||                             |           '||                             |           Cn|d         dk    rt          |          dk    s
|d	         dvrt!          d          |d         D ]^}	|	dk    r	|	                    d          r|	d d         |j        v r
|	d d         }	|d
                             |j         d|	            _n	t          |          dk    rd }|d                             d          }|d	                             d          }d }d }|d         dk    r|S |d         dk    rd|d<   |d         |j        v r?|d	         }|j        |d                  }|d         }t          |          d	k    r|d	         }nM|d         |j        v r>|d         }|j        |d                  }|d         }t          |          d	k    r|d	         }d}|                    d          r|d d         |j        v r|d d         }d}|rN|                    d          r9|                                }|r|d d         |d         j        v r|d d         }d}|rf|s|dv r|dk    r|d         }t          |t&                    rt          |          }t          |t                    s|g}g }|D ]s}t)          t+          |          t
          j                  r|j        }t)          t+          |          t0                    r|j        j        }|                    |           t|dk    r/|d                             |g                               |           ||j        v r/|d                             |g                               |           |dk    rt)          |t
          j                  rrd}|D ]i}t          |t:                    rP|                    d          d	k    r7t;          |                              d          d         t?          |          v sd}j|rd}t)          |t
          j                   r4|j        dk    r)|j        !                    |j        d d                   p|}t)          |t
          j                  rg|dk    ra|                                D ]L}|s!|d                             |j                    |r%|d
                             |j         d|            Mt)          |t
          j                  r|dk    r|                                D ]s}|                     ||d                                                   D ]B\  }}|dk    r||                             |           '||                             |           Ct|d
                             |j         d|            n |d| d d!           |S )"Nr   rr  r|   )r}   r   cache_clustersr   _idr  r^   r   r  )parent_operr  )r  ORrT     )=r  ut   Операция order_by в фильтре должна быть в формате: ["order_by", "=", [поля..]]r
   r~  ANYtextFT)r  r  INr  parentr]   r}   EXISTSuP   Ошибка  при выполнении UBQL - неверный запрос. uM    Проверьте правильность введенных данных.)abort)"r~   rs  r}   r3  endswithr   r   r   r   r)   r*   rf  rO   r   extendrx  rM   rb   related_modelssetr   r   r(  r   r   r   r4  cache_cluster_fields
CmfRelBaser4   r   varsCmfTUUIDrG   )r   r   
obj_filterobj_order_byobj_group_byr  rs  r}   r   rT  rU  filt_lsrh  r,   r   obj_filter0obj_filter1field__field_namer   operfield_is_tuuid
_relmodelsrule_values_dirtyrule_valuesrvmaybe_field_is_tuuid_vrmodels                               r   rf  zDataProvider._query_params  sD	   
 	*)))))&&&&&&"R;;; 		G( G Gt##$$U++ -"0M0M'}H&&s++ ,'|HH$$(8%E%E8%E%EFFFF 	G( G G$$U++ -"0M0M'}HH$$(8%E%E8%E%EFFFF 	JjmT** Q	P% - - $ 2 25'{ 2 [ [ a a c c - -HC...C,,,,C,,,,-- ]m++ ..ujnR\]^R_.``ffhh ) )S***HOOC((((HOOC(((() ]j((:!##z!}K'G'G  !W  X  X  X 'qM G Gt##$$U++ -"0M0M'}HH$$(8%E%E8%E%EFFFFG __!!E$Q---c22K$Q---c22K $J 1~..
1~&& "(A1~--!!}[^4(^
{##A%%(3A%Q5<//!!}[^4(^
{##A%%(3A%"N""5)) &j"o.M.M'_
!%  *%6%?%?%F%F *"1133
! *%6ss%;z!}?S%S%S(9#2#(>%%)N HI( /2T5F-F-F;Z^K^K^(21%!"3S99 D,01B,C,C)%&7>> @->,?)"$K/ / /%d2hh?? *!#B%d2hh	:: -!#B#**2....!X--,-88RHHOOP[\\\!U%???,-88RHHOOP[\\\* "X--*UFDU2V2V-/3,"- = =B$.r3$7$7 =BHHSMMQ<N<NSVWYSZSZS`S`adSeSefgShlpqwlxlxSxSx7< 4/ 2-1NeV_55 M%:Jd:R:R!L,,U-=crc-BCCLuEeV%677 	a "X--&+&:&:&<&< a aF#1 M #H 4 48I5K L L L0 a #H 4 48I5_5_L]5_5_ ` ` `eV%677 5DH<L<L"'"6"6"8"8 5 5(,(:(:6:a=(Q(Q(W(W(Y(Y 5 5HC"&666 #C 4 4 4 4 #C 4 4 4 45 H$$(8%G%G:%G%GHHH I  Cis  C  C  C  KO  P  P  P  P
r   c                    ddg dg dggdgg dg g g dgg ddgd	gg g d
gdgg dg dgg g g dgg ddgddgg g g dgg dg dgg ddgg g g dgg dgg dgg g g dgg dgg dgg g g dgg dgg dgg g g dgg dgdgddgg g g dgg dgg ddgg g g dgg dgdgddgg g g dgg dg d gg dd!gg g g dgg d"gg dgg g g dgg d#gdgdgg g g dgg}d$d%l m} |D ]g\  }}|j        j                            |j        |          }||k    r7t          d&| d'           t          d(|            t          d)|            hd*S )+ug   
        Тестирование
        Запуск: models.CmfTask.dp._test_query_params()
        listsr  )cache_status_typer  IN_PROGRESS)logic_prefixr  zlist.agile_sprintCmfList)zCmfList.cache_status_typezCmfList.logic_prefixCmfTask.lists)r}   r   parentsr  r  )r  r  {   r  r  )rL   r  qwezCmfTask.name)zcmf_owner.idr  zCmfPerson:12312321	CmfPersonzCmfPerson.idzCmfTask.cmf_ownerzCmfTask.cache_status_typezCmfTask.logic_prefix)ext_idLIKEz
%::qwe::%%zCmfTask.ext_id)r  r  ::qwe::)zparent.ext_idr  r  zCmfTask.parent)zstatus.ext_idr  r  	CmfStatuszCmfStatus.ext_idzCmfTask.status)zstatus.status_code_idr  12345zCmfStatus.status_code)zstatus.status_coder  r  )rL   r  r  )r   r  	qweqweqwez
CmfTask.id)zparent.project.namer  r  )statusr  r  r   r|   uC   Ошибка в результате _query_params(models.CmfTask, r   u   Факт:        u   Должно быть: N)r~   r}   CmfTaskdprf  rV   )r   f_listr}   fres_origr   s         r   _test_query_paramszDataProvider._test_query_params5  s    h!J!J!JLvLvLv wx!{.t.t.t  BD  XZ  eg  h  h	

 !  !{.?Bbdpsotuu
 "!!n%5"XZeghh
 988#}AT0Ubdxz  FH  I  I
 7668b8b8bc&ACY%Zgi}  KM  N  N
 .--. &6%7BZ\gijj
 (''( &6%7BZ\gijj
 /../&6%7BZ\gijj
 /../ $}1CEU0Vcey{  GI  J  J
 5445&=?O%P]_su  AC  D  D
 2112#}1HJZ0[hj  A  LN  O  O
 "!!#;#;#;<nl%CPRfhsuvv
 1001&6%7BZ\gijj	
 $##$#}1A0Bregrtuu
s=
@ 	'&&&&&! 	< 	<KAx.#11&.!DDCh`\]```aaa/#//000:::;;;r   c                   |rt          d          | j        j        p=|p;t          j        p/|p-t
          j        j                            | j        j	                  }t                       |                     | j        |          |d<   t          j        j        j        | j        j	         dg|R d|i|}|rd}n~t          j                    }	t
          j        j                            ||          }t          j                    |	z
  dk    r+t          j        dt          j                    |	z
              |d	k    r9t
          j                            t
          j        j        j        d
|            g S |9t
          j                            t
          j        j        j        d|            |S t
          j                            t
          j        j        j        d|            t          j                    }	 | j        j        | j        g|R d|i|}
t          j                    |	z
  dk    r+t          j        dt          j                    |	z
              | j        j        dk    r|
S |r|
D ]	}d|_        
|st          j                    }	|                     | j        |d         |                    d          |                    d                    }t
          j        j                            ||
| j        j	         ||           t          j                    |	z
  dk    r+t          j        dt          j                    |	z
              |
S )u   
        Пробросили сюда relation_load и relation_load_only для реализации join и подселектов в будущем
        :param args:
        :param kwargs:
        :return:
        rE  rF  z.listrC  NrQ  g333333?z%PROF DataProvider.list cache.get got rR  zlist() From cache  Empty zlist() From cache zDP: list() From NOcache rB  g      ?z1PROF DataProvider.list self.data_driver.list got rS  TrT  rU  rV  z%PROF DataProvider.list cache.add got )rM   r   rX  r   rY  rZ  r[  r\  r]  r9   r7  r^  ra  ru  rG   rr   rb  rc  r?  r*   rL   rd  rf  re  )r   r@  rA  rB  rC  r   r   rh  ri  prof_strj  r  rW  s                r   r*   zDataProvider.list  sM     	XVWWW:- M MAM MV` Mg'77
8KLL 	++DJ??xg$
(;%B%B%BsTsssZhslrss 	YEEikkGG%))#n)MMEy{{W$s**W	g@UWWXXXGG 1 79ZUX9Z9Z[[[IG 1 79Sc9S9STTTLG 1 79YTW9Y9YZZZikkG*T%*4:^^^^^W]^^Fy{{W$s**cDIKKZaLaccddd $// & & &A!%AJJ  ])++#11$*fX>NPVPZPZ[ePfPfhnhrhrs}h~h~!%%c6dj6I3KZf  xF%  G  G  G9;;(3..G[DIKKRYDY[[\\\Mr   )r@  rA  rC  c                    |rt          d          | j        j        p;|p9t          j        p-t
          j        j                            | j        j	                  }t                       |                     | j        |          |d<   t          j        j        j        | j        j	         dg|R d|i|}|rd }n&t
          j        j                            ||          }|dk    rFt
          j                            t
          j        j        j        d|            t!          d          |9t
          j                            t
          j        j        j        d	|            |S t                        | j        j        | j        g|R i |}|s}|                     | j        |d         |                    d
          |                    d                    }	t
          j        j                            ||| j        j	         |	|           |S )NrE  rF  z.countrC  rQ  rR  zcount() From cache Empty z$BUG: count() cache can not be empty!zcount() From cache rT  rU  rV  )rM   r   rX  r   rY  rZ  r[  r\  r]  r9   r7  r^  ra  rG   rb  rc  ra   r?  r   rf  re  )
r   r@  rA  rC  r   r   rh  ri  rj  rW  s
             r   r   zDataProvider.count  s    	XVWWW:- M MAM Mg'77
8KLL 	++DJ??xg$
(;%C%C%Ctdttt[itmstt 	NEEG%))#n)MMEGG 1 79ZUX9Z9Z[[[CDDDG 1 79Ts9T9TUUUL+T%+DJHHHHHHF G#11$*fX>NPVPZPZ[ePfPfhnhrhrs}h~h~!%%c6dj6I3KZf  xF%  G  G  Gr   )r   c                \    t           | j        j        |i || j        | j        |          S Nrp   r   r   )
QueryProxyr?  queryr   )r   r   r   r   s       r   r   zDataProvider.query_deprecated  sC    "D"D3F338HPTPZcik k k 	kr   )NN)NNr  )r9   r:   r;   r   r  compileTABLE_FIELD_REr   propertyr?  rG   r   ro  rw  r   rv   ru   r   r^  rf  r   r*   r   r   r#   r   r   r9  r9  -  s       ``RZ EFFN! ! ! !   X
 #(%`e H H H H HT 26     &    . 05     2  
: : :  \ \ \~n n n n`L L L^ $)$5af 4 4 4 4 4l %*4PU     4 .2 k k k k k k kr   r9  c                   h    e Zd ZdZddZd ZddZd Zd Zd Z	d	 Z
d
 Zd Zed             Zd ZdS )r  u   
    Оборачиваем кастомный запрос и добавляем возможность извлекать данные с автомаппингом.
    TODO: Проверить слайсы query[a:b]
    Nc                     || _         || _        || _        t          |t                     | _        t                              |          | _        d S r   )_queryr<  r   r)   r   _mapper_is_myr   _mapper)r   r  rp   r   r   s        r   r   zQueryProxy.__init__  sE    
!+FJ!?!??!,,V44r   c                       fd}|S )u   Обёртка для методов, которые возвращают новый запрос на основании текущего.c                  ~     t          j                  | i |}t          |j        j        j                  S r  )re   r  r  r<  r   r  )r   r   	new_queryitemr   s      r   method_proxyz,QueryProxy.__getattr__.<locals>.method_proxy  s@    2T22DCFCCIiDHDJt|\\\\r   r#   )r   r  r  s   `` r   __getattr__zQueryProxy.__getattr__  s0    	] 	] 	] 	] 	] 	] r   c                     | j                             | j        | j        |||          }t	          || j         | j        | j                  S )uR   
        Логика сортировки на основе модели
        )r   rT  sliceaggregate_selectr  )r<  order_queryr  r   r  r  )r   rT  r  r  r  s        r   r  zQueryProxy.order_query  sO     H((KtzHE\l ) n n	)
4<XXXXr   c                     | j         r[| j                             |          rA| j                            || j                             t          |                              }|S )u6   Автоконвертация объектов в CMF)r   )r<  r   r  r   r   r   )r   r   s     r   
_map_valuezQueryProxy._map_value  s[    8 	],,U33 	]L..uDH<N<NtTY{{<[<[.\\Er   c                      t          |t                    rt           fd|D                       S                      |          S )Nc              3   B   K   | ]}                     |          V  d S r   )r  )r%   colr   s     r   	<genexpr>z&QueryProxy._map_row.<locals>.<genexpr>  s/      ==#--======r   )r)   tupler  )r   rows   ` r   _map_rowzQueryProxy._map_row  sJ    c5!! 	(==========??3'''r   c                 n    t           j                  }d}t          j        j                            ||          }t          j        j                             j        j                  rd}n$t          j        j        	                    |          }t                       |dk    r9t          j                            t          j        j        j        d|            g S |9t          j                            t          j        j        j        d|            |S t          j                            t          j        j        j        d|             fd j        D             }t          j        j                            || j        j                     j        r j                                         |S )uo   Метод извлечения всех данных из текущего запрос с маппингом.
custom_allNrR  zall() From cache Empty zall() From cache zDP: all() From NOcache c                 :    g | ]}                     |          S r#   )r#  )r%   r"  r   s     r   r(   z"QueryProxy.all.<locals>.<listcomp>  s%    @@@SdmmC((@@@r   )rD   r  rZ  r[  r\  ra  r]  r   r9   rG   r7  rb  rc  re  r  r  r   r   sql_krh  ri  rj  s   `     r   allzQueryProxy.all  sz   4;''g$$R-- 7,,TZ-@AA 	/EEG%))#..EGG 1 79XSV9X9XYYYIG 1 79RS9R9RSSSLG 1 79XSV9X9XYYY@@@@DK@@@FG!!#v$*2E/GHHH! 1..000Mr   c                    t          | j                  }d}t          j        j                            ||          }t          j        j                            | j        j                  rd}n$t          j        j        	                    |          }t                       |dk    r9t          j                            t          j        j        j        d|            dS |9t          j                            t          j        j        j        d|            |S t          j                            t          j        j        j        d|            | j                                        }|                     |          }t          j        j                            ||| j        j                    | j        r| j                                         |S )uP   Метод извлечения первой строки с маппингом.custom_firstNrR  zDP: first() From cache Empty zDP: first() From cache zDP: first() From NOcache )rD   r  rZ  r[  r\  ra  r]  r   r9   rG   r7  rb  rc  firstr#  re  r  r  r   )r   r(  r)  rh  ri  r"  rj  s          r   r-  zQueryProxy.first  s   4;''g$$R-- 7,,TZ-@AA 	/EEG%))#..EGG 1 79^Y\9^9^___4G 1 79XSV9X9XYYYLG 1 79ZUX9Z9Z[[[+##%%C]]3''FG!!#v$*2E/GHHH! 1..000Mr   c                 N   t                       t          | j                  }d}t          j        j                            ||          }t          j        j                            | j        j	                  rd }n$t          j        j        
                    |          }t                       |dk    r9t          j                            t          j        j        j        d|            d S |9t          j                            t          j        j        j        d|            |S t          j                            t          j        j        j        d           | j                                        }t          j        j                            ||| j        j	                    |S )Ncustom_countrR  zDP: count() From cache Empty zDP: count() From cache zDP: count() From NOcache TODO)r7  rD   r  rZ  r[  r\  ra  r]  r   r9   rG   rb  rc  r   re  r'  s         r   r   zQueryProxy.count9  sV   4;''g$$R-- 7,,TZ-@AA 	/EEG%))#..EGW  !2!8:_Z]:_:_```DW  !2!8:YTW:Y:YZZZ\G 1 79YZZZ[&&((FG!!#v$*2E/GHHHr   c                 *     | j         j        |i |}|S r   )r  r   )r   r   r   rj  s       r   r   zQueryProxy.deleteS  s     ##T4V44r   c                     | j         S r   )r  r   s    r   dd_queryzQueryProxy.dd_queryX  s
    {r   c                 D    t          |                                           S )u+   Чтение строк из запроса)iterr*  r   s    r   __iter__zQueryProxy.__iter__\  s    DHHJJr   )NNN)r9   r:   r;   r   r   r  r  r  r#  r*  r-  r   r   r  r2  r5  r#   r   r   r  r    s         5 5 5 5  Y Y Y Y  ( ( (  6  8  4  
   X         r   r  r   )r.  )(r   rc   r  r  r  ru  collectionsr   r   r  r   typingr   r
  flaskr   cmf.apprZ  r   r~   r	   models.base_modelr   rF   rD   rI   rT   rW   rQ   rn   rx   rz   r   r   r   r   r   r7  r9  r  r#   r   r   <module>r;     s             				  / / / / / / / /                                 ) ) ) ) ) ) *B *B *B *BZ$ $ $
? ? ? 7 7 74 4 4 4         6 6 6 6 6 6 6 6r4+ 4+ 4+ 4+ 4+ 4+ 4+ 4+n~ ~ ~ ~ ~: ~ ~ ~BN N N N NZ N N Nb2 2 2 2&i
k i
k i
k i
k i
k i
k i
k i
kZD  D  D  D  D  D  D  D  D  D r   