U
    Eh                    @   sP  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
dZdd Zdd Zdd Zd,ddZdd Zd-ddZdd Zdd Z G dd dZ!G dd dZ"G d d! d!e"Z#G d"d# d#e"Z$d.d%d&Z%G d'd( d(Z&G d)d* d*Z'dS )/    N)defaultdict
namedtuple)deepcopy)List)g)fields)config   )	BaseModelc                    s   ddl mm ddl m  ddlm} t| |rL|d krD| jjj}| j	} n|d kr\| jj}G  fddd|j
  || | S )Nr   )date	timedelta)datetime)Queryc                       s6   e Zd ZdddZdd Z fddZ  ZS )	z%render_query.<locals>.LiteralCompilerFc                 [   s   |  |j|jS N)render_literal_valuevaluetype)selfZ	bindparamZwithin_columns_clauseZliteral_bindskwargs r   ./cmf/data_providers/base.pyvisit_bindparam.   s    z5render_query.<locals>.LiteralCompiler.visit_bindparamc                    s4   t |tr(dd fdd|D  S | S )Nz{%s},c                    s   g | ]} | qS r   )render_array_value.0x	item_typer   r   r   
<listcomp>4   s     zLrender_query.<locals>.LiteralCompiler.render_array_value.<locals>.<listcomp>)
isinstancelistjoinr   )r   valr   r   r   r   r   2   s    
z8render_query.<locals>.LiteralCompiler.render_array_valuec                    s   t |trt|S t |fr.d|d S t |rLdt|dd S t |trtdd fdd|D  S t 	|S )	Nz'%s'z%Y-%m-%d %H:%M:%S'z''z'{%s}'r   c                    s   g | ]}  |jqS r   )r   r   r   r   type_r   r   r   @   s     zNrender_query.<locals>.LiteralCompiler.render_literal_value.<locals>.<listcomp>)
r    intreprstrftimestrreplacer!   r"   superr   )r   r   r&   )LiteralCompiler	__class__r   r   r   r%   r   r   7   s    


z:render_query.<locals>.LiteralCompiler.render_literal_value)FF)__name__
__module____qualname__r   r   r   __classcell__r   r-   r   r   r   r.   r   r-   ,   s
     
r-   )r   r   r   Zsqlalchemy.ormr   r    ZsessionZbinddialect	statementZstatement_compilerZprocess)r6   r5   r   r   r3   r   render_query   s    	

r7   c                 C   s
   t | S )uK   Вернём драйвер по имени источника данных)ds_registryget)ds_namer   r   r   get_ddF   s    r;   c                  C   sf   t rtdd} tj D ]F\}}|ddkrP| dkrHddlm} |} | |d< t||dt |< qdS )uY   Инициализация всех источников данных из конфигаuZ   Источники данных нельзя инициализировать дваждыNzsqlalchemy.poolclass	QueuePoolr   )r<   )name)	r8   	Exceptionr   Zdata_sourcesitemsr9   Zsqlalchemy.poolr<   new_dd)Z
queue_poolr:   	ds_configr<   r   r   r   init_dsK   s    rB   c               	   C   sN   t  D ]@\} }td|   z|  W q tk
rF   td Y qX qdS )u=   Инициализация, миграция схемы БД.zInit DB u        не реализовано.N)r8   r?   printinit_dbNotImplementedError)r:   Zds_ddr   r   r   rD   [   s    rD   c                 C   sf   |  d}|s$|  d}|dkr$d}|s4td|| |jddd\}}t|}t||}|| |d	S )
Nclassr   Z
sqlalchemyz2cmf.data_providers.sqlalchemy:SQLAlchemyDataDriverzDYou must specify valid "type" or "class" in datasource configuration:   )maxsplitrA   r=   )r9   
ValueErrorsplit	importlibimport_modulegetattr)rA   r=   Zdd_mod_classZdd_typeZdd_module_nameZdd_class_nameZ	dd_moduleZdd_classr   r   r   r@   f   s    



r@   c                  C   s   t  D ]} |   qd S r   )r8   valuesbefore_requestddr   r   r   rQ   u   s    rQ   c                 C   s@   | rt tdrtd t D ]}| r2|  q |  q d S )NdebugZROLLBACK)hasattrr   rT   r8   rP   rollbackcommit)	exceptionrS   r   r   r   commit_all_ds{   s    


rY   c                  C   s*   t  D ]} td|   |   qd S )Nz	ROLLBACK )r8   rP   r   rT   rV   rR   r   r   r   rollback_all_ds   s    rZ   c                  C   s(   ddl m}  t D ]}||  qdS )zmake_models hookr   modelsN)cmf.includer\   r8   rP   make_models)r\   rS   r   r   r   r^      s    r^   c                   @   s   e Zd ZdZdddddZdd Zdd	 Zd
d Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% ZdS )&BaseDataDriver NrJ   c                O   s   || _ || _d S r   )r   r=   )r   rA   r=   _args_kwargsr   r   r   __init__   s    zBaseDataDriver.__init__c                 O   s   d S r   r   r   modelargsr   r   r   r   r9      s    zBaseDataDriver.getc                 O   s   d S r   r   r   instancerf   r   r   r   r   create   s    zBaseDataDriver.createc                 O   s   d S r   r   rg   r   r   r   delete   s    zBaseDataDriver.deletec                 O   s   d S r   r   rg   r   r   r   update   s    zBaseDataDriver.updatec                 O   s   d S r   r   rd   r   r   r   r!      s    zBaseDataDriver.listc                 O   s   d S r   r   rd   r   r   r   count   s    zBaseDataDriver.countc                 C   s   d S r   r   r   r   r   r   rW      s    zBaseDataDriver.commitc                 C   s   d S r   r   rm   r   r   r   rV      s    zBaseDataDriver.rollbackc                 C   s   d S r   r   rm   r   r   r   rQ      s    zBaseDataDriver.before_requestc                 C   s   d S r   r   )r   	cmf_modelr   r   r   dp_model   s    zBaseDataDriver.dp_modelc                 C   s   d S r   r   )r   Zsa_modelr   r   r   rn      s    zBaseDataDriver.cmf_modelc                 C   s   d S r   r   )r   Zdp_instancer   r   r   is_instance   s    zBaseDataDriver.is_instancec                 C   s   d S r   r   )r   Zmodels_r   r   r   r^      s    zBaseDataDriver.make_modelsc                 O   s   dS )u,   Вернём кастомный запросNr   r   rf   r   r   r   r   query_deprecated   s    zBaseDataDriver.query_deprecatedc                 C   s   t dS )u2   Создание/миграция схемы БД.NrE   rm   r   r   r   rD      s    zBaseDataDriver.init_dbc                 C   s   dS )u8   Закрываем текущие подключенияNr   rm   r   r   r   close_all_sessions   s    z!BaseDataDriver.close_all_sessions)r/   r0   r1   __doc__rc   r9   ri   rj   rk   r!   rl   rW   rV   rQ   ro   rn   rp   r^   rr   rD   rt   r   r   r   r   r_      s$   r_   c                   @   sF   e Zd Zdd ZdddZdd Zdd	 Zdd
dZedddZ	dS )
BaseMapperc                 C   s   dS )u  
        Вызывать по завершению маппинга всех объектов в запросе, постобработка.
        Обычно должен вызывать тот, кто создал экземпляр маппера.
        Nr   rm   r   r   r   post_mapping_hook   s    zBaseMapper.post_mapping_hookNc                 C   s   t d S r   rs   )r   obj
cmf_entityre   
model_namefull_fields_loadr   r   r   object_to_cmf   s    zBaseMapper.object_to_cmfc                 C   s   t d S r   rs   )r   ry   rx   r   r   r   cmf_to_object   s    zBaseMapper.cmf_to_objectc                    s~   |sdS  fdd|j D }tdtf|}| |_ |j D ]>}|  dr:d|ddd }t||t|| q:|S )u  
        TODO: создание промежуточного объекта плохо для производительности, нужно маппить напрямую из ResultSet
          да и в целом можно зарефакторить
        Nc                    s6   i | ].}|   d rd|ddd dqS )_sub__rH   N)
startswithr"   rL   )r   field
field_namer   r   
<dictcomp>   s    z4BaseMapper.obj_from_result_query.<locals>.<dictcomp>ZCmfObjr~   r   rH   )	_fieldsr   objectkeysr   r"   rL   setattrrO   )r   result_queryr   Z
obj_fieldsresr   Zattnamer   r   r   obj_from_result_query   s    


z BaseMapper.obj_from_result_queryc                    s    fdd|D S )Nc                    s   g | ]}j | d qS )re   r{   )r|   )r   rx   r{   re   r   r   r   r      s     z*BaseMapper.list_to_cmf.<locals>.<listcomp>r   )r   Zlstr{   re   r   r   r   list_to_cmf   s    zBaseMapper.list_to_cmfc                 C   sB   |s
t  S |dkrt S t|tr&|S t|tr6| S tddS )u   
        :param mapper: тип маппера
        :type mapper: None, str, Mapper subclass, Mapper instance
        :return: экземпляр маппера
        :rtype:  Mapper
        ZsimplezInvalid mapperN)MapperSimpleMapperr    rv   
issubclassrK   )clsmapperr   r   r   
get_mapper   s    

zBaseMapper.get_mapper)NNNN)N)N)
r/   r0   r1   rw   r|   r}   r   r   classmethodr   r   r   r   r   rv      s   

rv   c                       sX   e Zd ZdZe G dd dZeddddgZ fdd	Z	d
d Z
dddZ  ZS )r   u   
    Dataclass as model, для лёгкой сериализации в json
    fill class_name
    TODO fill meta для api, но вероятно это драйвер будет делать, там дешевле
    c                   @   s"   e Zd ZU dZeed< dd ZdS )zSimpleMapper.SimpleModelNidc                 C   s@   t | dr&| j d| j d| j dS | j dt| dd  dS )Nr=   (z: )r   )rU   
class_namecoder=   rO   rm   r   r   r   __repr__  s    
z!SimpleMapper.SimpleModel.__repr__)r/   r0   r1   r   r*   __annotations__r   r   r   r   r   SimpleModel  s   
r   VirtualInitDatar   re   
field_listc                    s   t    g | _d S r   )r,   rc   _virtual_init_listrm   r4   r   r   rc     s    
zSimpleMapper.__init__c                 C   s   i }t | jD ]j}||jj}|r.|j|_n|j|jd}|||jj< |jD ](}t||j}d|_	t
|j|j|j qNqg | _dS )uN   Вычислим все запрошенные виртуальные поля)simple_objectN)reversedr   r9   re   r   r   r   r   rO   _valuer   r   )r   Zcmf_instancesZ	init_dataZcmf_wrapper	field_clsZvirtual_fieldr   r   r   rw   #  s    

zSimpleMapper.post_mapping_hookNc              	   C   s  ddl m} |s.|s$|jdd }t||}|sDt }|j|_ntd||g }|p\|j	D ]}d|krt
||t||d q^|j	|}	|	sq^|	jr|s|	jdkr||	 q^t|	t	jt	jfr8t||	 d}
|
dkrq^|
dkrd}nF|o||}|r^t|| d	ddk	r^| j| |||d
}nq^nq^n(t|	t	jt	jt	jfrTq^nt||d}|dkrlq^t|	t	jr| ||o||t||	jd }nLt|	t	jr|r|js|jtjjd}nt|	t	j r|rt!"|}t
||| q^|r| j#tj$|||d |S )u  
        отображение obj -> simple_model
        если cmf_entity не указан, то создадим новый на основе модели cmf_model или её имени model_name
        возвращаем simple_model
        r   r[   rG   uI   Передан cmf_entity в SimpleMapper, вероятно это багr   .)defaultalwaysN_sub__id)r{   tzinfo)r   re   r   )%r]   r\   r   rL   rO   r   r   r   rK   r   r   r9   virtual	load_modeappendr   CmfRelationCmfGenericRelationid_fieldnamer|   r   
CmfM2MBaseCmfBackrefBaseCmfDateRangeCmfObjectListr   CmfDateTimer   r+   r   timezoneutcCmfJsonujsonloadsr   r   )r   rx   ry   re   rz   r{   r\   Zvirtual_fieldsr   r   obj_related_idfield_valuesub_fflr   r   r   r|   6  sr    




 
zSimpleMapper.object_to_cmf)NNNN)r/   r0   r1   ru   dataclassesZ	dataclassr   r   r   rc   rw   r|   r2   r   r   r4   r   r     s   r   c                   @   s   e Zd ZdddZdd ZdS )r   Nc              	   C   s  ddl m} |sB|s2|s(|jdd }t||}|dd}d}nd}|sRt|}|}|r`|}	n
|j }	|	D ]6}
|j|
 }sqn|j	r|s|j
dkrt||
}d|_d|_qnt|tjtjtjfrqnt||
d	}t|tjr|d	krqn| ||o||
t||jd }t|tjtjfrt|| d	}|d	krDqn|dkrTd}n|ob||
}|rnt||
 d
ddkrnt||
 d
rnt|tjr|dd n|j}t||d}|r| j| ||
||d}nd}nqnnqn|d	krqnt|tjr |r |js |jtjjd}t|tjr:| |}nt|tj!rX|rXt"#|}t||
}|rt|jd	krt$|t%t&t'tdt(fr||_n
t)||_||_qnd|_*|+  |S )u  
        отображение obj -> cmf_entity
        если cmf_entity не указан, то создадим новый на основе модели cmf_model или её имени model_name
        возвращаем ссылку на cmf_entity
        r   r[   rG   T)emptyFr   N.r   r   r   ),r]   r\   r   rL   rO   r   r   r   r9   r   r   r   Z_oldr   r   r   r   r   r   r   r   r   re   r|   r   r   r   r+   r   r   r   ZCmfIPv4NetworkListZdb_castr   jsonr   r    r*   r'   floatboolr   is_newZmark_exists_in_db)r   rx   ry   re   rz   r{   r\   Zcmf_is_existsr   r   kr   r   r   r   r   Z	model_subZ	field_objr   r   r   r|     s    




  

&
 



zMapper.object_to_cmfc                 C   s   t |}|j D ]\}}t|tjr(qt|tjr6qt|tjrDqt|tjrRqt|tjr`qt|tj	rnqt|tj
r|qt||}t|tjr|jdks|jrq|js|jsq| }|dkrtd| d| d| t||| q|S )N.u%   Попытка update field=Ellipsis  )r   r   r?   r   r   r   ZCmfM2MZCmfGenericM2MZ
CmfBackrefr   ZCmfGenericBackrefrO   r    CmfTyper   r   
is_changedZ	orm_dirtyZ	db_formatr>   r   )r   ry   rx   re   r   vZvvr   r   r   r}     s6    
zMapper.cmf_to_object)NNNN)r/   r0   r1   r|   r}   r   r   r   r   r     s   
lr   selectc              
   C   s   zdt krttt _W n( tk
r> } z
W Y dS d}~X Y nX t jdtt t jd | d t jd |   d7  < t jd dd t jd d  d7  < dS )uK   
    Глобальный счетчик запросов
    :return:
    profiler_dataNZselect_countr   rH   total)r   r   dictr   r>   
setdefault)actioner   r   r   inc_select_count  s    r   c                   @   s   e Zd ZdZedZd,ddZedd Z	ddddd	d
dZ
ddddZdd Zdd ZddddZdd Zdd Zdd Zdd Zd-d d!Zd"d# Zddddd	d$d%Zdddd&d'd(Zdd)d*d+ZdS ).DataProvideruV   Объект, связывающий модель с источником данныхz"\b(?P<table>\w+)\.(?P<field>\w+)\bNc                 C   s   || _ || _d | _t| _d S r   )re   data_source_ddr   Z
mapper_cls)r   r   re   r   r   r   rc   1  s    zDataProvider.__init__c                 C   s   | j st| j| _ | j S r   )r   r;   r   rm   r   r   r   data_driver7  s    zDataProvider.data_driverF)no_cacheTECHCOM_nocache
for_updatecache_inmemoryc                   s  |rt d| jjp2|p2tjp2|p2tjj| jj	}| 
| j||d<  fdd tjr| jj	dkr| jj	tjjjkri 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f|d	|i|}|rd}	ntjjj||d
}	t  |	dkr2tjtjjjd|  dS |	dk	rZtjtjjjd|  |	S tjtjjjd|  | jj| jf|d|i|}
| jjdkr|
S |r|
rd|
_|r|
S tjjj||
| jj	 | | j|d |d|d|d |
S dS )zF
        :param args:
        :param kwargs:
        :return:
        8   no_cache запрещен и будет удален osvfilterc                    sF   |  D ]8\}}|| kr&|| | |< q| | |kr | | | qd S r   )r?   )Z_fields_grow_cacheZ_full_fields_loadr   r   _grow_merger   r   r   Q  s
    z%DataProvider.get.<locals>._grow_merge)Z
CmfProjectZCmfWorkflowZCmfLogicTypeZCmfSchemeWfZCmfSchemeWfRuleZCmfActivityr{   Nz.getr   r   EmptyzDP: get() cache Empty zDP: get() cache zDP: get() NOcache r   rdiskTorder_bygroup_byquery_paramsr   )r>   re   TEXKOM_no_cacher   import_modecmfapp	CMF_CACHEcache_is_lockedr/   _get_filterZTEXCOM_ENABLE_GROWCACHE_HACKZtexcom_growcache_hack_cacher9   hashr   print_debugDEBUGr   r=   readonlyadd_query_params)r   r   r   r   r   rf   r   Zfields_grow_cachekeycachedb_resr   r   r   r9   =  sV    	
(

   zDataProvider.getT)
invalidatec                O   sd   t d | jj|f||}| jjdkr,|S |s4|S |d krPtjj|d d S tjj|d |S )Ninsertr   ri   )r   r   ri   r=   r   r   r   r   )r   rh   r   rf   r   r   r   r   r   ri     s    zDataProvider.createc                 O   s   t d | jj||}|S )Nrj   )r   r   bulk_deleter   rf   r   r   r   r   r   r     s    zDataProvider.bulk_deletec           
   	   O   s   dd l }ddlm} dd l}td td| d| d|  | jj|f||}td |j	s|  }t
|dkrtjj|jd  n|rtjj|j| |  | d }	|d	t
| d
| d|	dd |	dkr|d|	dd |S )Nr   	cmf_alertrk   zbulk_update start model=z args=z kwargs=zbulk_update endi  u)   Инвалидировали кеш по u$    обьектам у таблицы u    за z.2fu    мс   u2   DEV: Инвалидация кэша заняла )timer]   r   loggingr   r   rT   r   bulk_updater   lenr   r   r   Zinvalidate_idsr   Zwarning)
r   re   rf   r   r   r   r   r   Z
start_timeZelapsed_timer   r   r   r     s$    
$zDataProvider.bulk_update)r   c                O   s   t d | jjs"td|j  | jj|f||}| jjsPtd|j  |r\td| jj}| jj	dkrt|S |s|
ddrd}d|jkr|jjr|jrd	nd
}|jrd
}tjj|| td|j  |S )Nrk   z+Run self.data_driver.update(), instance_id=z+End self.data_driver.update(), instance_id=r   r   r   Tcmf_deletedrj   ri   z0End cmf.app.CMF_CACHE.invalidate(), instance_id=)r   re   r   r   rT   r   r   rk   r>   r=   r9   r   r   r   r   r   r   r   r   )r   rh   r   rf   r   r   r   r   r   r   rk     s(    zDataProvider.updatec                 O   s   | j j||}|S r   )r   rW   )r   rf   r   retr   r   r   rW     s    zDataProvider.commitc                 O   s   | j j||S r   )r   rV   rq   r   r   r   rV     s    zDataProvider.rollbackc                 O   s2   | j j||}| j jdkr|S tjj|d |S )u   
        Logical delete. Реализация в провайдере или в модели?
        self.deleted = 1
        self.update()
        r   rj   )r   rj   r=   r   r   r   r   r   r   r   r   rj     s
    zDataProvider.deletec                    s   | dg }|dkrg }| ds*i t|tr>t|}|rH|g}|  D ]:\}}||jkrT||= t|tjr~|j	}|
|d|g qTdfdd	fdd  fd	d
|}|S )u   
        Преобразуем обычные kwargs в продвинутый фильтр для однообразной логики фильтрования
        :param model:
        :param kwargs:
        :return:
        r   Nfilter_context==c              
      sn   |s
| j }z| j|||d}W nJ tk
rh } z,t|dkrR | |||d d}nt|W 5 d }~X Y nX |S )N)yearmonthdayzday is out of range for monthrH   )cur_datetimer  r  r  )r  r+   rK   r*   )r  r  r  r  Znew_dater   _replace_month_yearr   r   r    s    z5DataProvider._get_filter.<locals>._replace_month_yearc                    s   d}t || }ddddddh}d } } } } }}	d }
|D ]}|\}}}t|}d }|rx|d	krld
}n|dkrxd}|s|
pd
}|}
||kr@|dkr||| 7 }q@q@|dkr||| 7 }q@q@|dkr||| 7 }q@q@|dkr||| 7 }q@q@|dkr
||| 7 }q@q@|dkr@|	|| 7 }	q@q@t  }}|j}|j}|sF|r|dk rTdnd
}|t|d | 7 }t|d | }|| dkr|| d
 }d| | }n8|| dkr|| d
 }|| d }n|| }|| } |||d}|tj	||||	d S )Nz([+-]?)\s*(\d+)\s*(min|[ymwdh])ymwdhminr   +rH   -r      )r  r  r  )weeksdayshoursminutes)
refindallr'   r   nowr  r  absr   r   )Ztime_strpatternmatchesZallowed_unitsZyearsZmonthsr  r  r  r  Z	prev_signmatchZ	time_signr   Zunitsignr  Z	init_dateZcur_yearZ	cur_monthZ	init_yearZ
init_monthr  r   r   _parse_time_string  sj    

z4DataProvider._get_filter.<locals>._parse_time_stringc                    s   t | trfdd| D S t | tr| dkr8tjjjS | dkrdtjsNdt_nttjdt_t	 S | dkrtjszdt_nttjdt_t
 S | drd fd	d
	  | dd  S | drtjsdt_nttjdt_| S | S )Nc                    s   g | ]} |qS r   r   )r   i)_recursive_params_replacer   r   r   V  s     zODataProvider._get_filter.<locals>._recursive_params_replace.<locals>.<listcomp>Z__G_CURRENT_USERZ__G_NOWi,  Z__G_DATEip  z__SELF.c                    sH   |  d}|d }|r$t||d }n | }|d rD|d |d}|S )N.r   rH   r	   )r   )	partitionrO   )Z
value_pathr   partsattr)r  get_ctx_attrr   r   r%  k  s    
zQDataProvider._get_filter.<locals>._recursive_params_replace.<locals>.get_ctx_attrr	   znow())N)r    r!   r*   r   Zcurrent_userr   r   Zjscache_timelifer  r  r   r   )r   )r  r   r  )r%  r   r   T  s0    




z;DataProvider._get_filter.<locals>._recursive_params_replace)N)r9   r    r*   r   r   copyr?   r   r   r   r   )r   re   r   Zsmart_filterr   r   r   )r  r   r  r  r   r     s*    



F-zDataProvider._get_filterANDc                 C   s<  ddl m} ddl m} tg g i d}|r|D ]f}	|	dkr<q.|	drd|	d d |jkrd|	d d }	|	drz|	d	d  }	|d
 |j d|	  q.|r|D ]F}
|
dr|
d d |jkr|
d d }
|d
 |j d|
  q|s|S t	|d t
rV|D ]N}| j|||d D ]2\}}|dkr<|| | n|| | qqn|d dkr| j||d	d  |d d D ]2\}}|dkr|| | n|| | qn||d dkrVt|dks|d	 dkrtd|d D ]Z}	|	dkrq|	dr4|	d d |jkr4|	d d }	|d
 |j d|	  qnt|dkr$d }|d d}|d	 d}d }d }|d dkr|S |d dkrd|d< |d |jkr|d	 }|j|d  }|d }t|d	kr>|d	 }nD|d |jkr>|d }|j|d  }|d }t|d	kr>|d	 }d}|drr|d d |jkrr|d d }d}|r|dr| }|r|d d |d jkr|d d }d}|r8|s|dkr|dkr|d }t	|trt
|}t	|t
s|g}g }|D ]@}tt|tjr,|j}tt|trD|jj}|| q|dkrr|d |g | ||jkr|d |g | |dkrt|tjrd}|D ]B}t	|tr|dd	krt|dd t|ksd}q|rd}t|tj r8|jdkr8|j!|jd d p6|}t|tjr|dkr| D ]>}|st|d |j  |rX|d
 |j d|  qXt|tjr|dkr| D ]N}| ||d  D ]2\}}|dkr|| | n|| | qАq|d
 |j d|  n|d| d dd! |S )"Nr   r   r[   )r\   r   cache_clustersr   Z_idr  rH   r   r!  )parent_operr(  )r'  ORr      )=r  ut   Операция order_by в фильтре должна быть в формате: ["order_by", "=", [поля..]]r	   r   ANYtextFT)r-  r  INr+  parentrG   r\   EXISTSuP   Ошибка  при выполнении UBQL - неверный запрос. uM    Проверьте правильность введенных данных.)abort)"r]   r   r\   r   endswithr   r   r   r   r    r!   r   r?   rk   extendr   r>   rL   Zrelated_modelssetr   r   r   r   r
   r   r   Zcache_cluster_fieldsZ
CmfRelBaser*   rl   varsZCmfTUUIDr9   )r   re   Z
obj_filterZobj_order_byZobj_group_byr*  r   r\   r   r   r   Zfilt_lsr   r#   r   Zobj_filter0Zobj_filter1Zfield__field_namer   ZoperZfield_is_tuuidZ
_relmodelsZrule_values_dirtyZrule_valuesrvZmaybe_field_is_tuuidZ_vZrmodelr   r   r   r     s    

(

 "
 
8

zDataProvider._query_paramsc                 C   s*  dddddgdddgggdgd	d
dgg g g dgdddgdgdgg g dgdgdddgg dgg g g dgdddgdgddgg g g dgdddgdddggg ddgg g g dgdddggg dgg g g dgdddggg dgg g g dgdddggg dgg g g dgd ddggd!gd"d#gg g g dgd$dd%ggg d&d#gg g g dgd'dd%ggd!gd&d#gg g g dgdddgd(dd)ggg dd*gg g g dgd+ddggg dgg g g dgd,ddggd!gd#gg g g dgg}d-d.l m} |D ]R\}}|jj|j|}||krtd/| d0 td1|  td2|  qd3S )4ug   
        Тестирование
        Запуск: models.CmfTask.dp._test_query_params()
        listsr2  Zcache_status_typer-  ZIN_PROGRESSZlogic_prefixzlist.agile_sprintZCmfListzCmfList.cache_status_typezCmfList.logic_prefixzCmfTask.lists)r\   r   parentsr(  r9  r  {   r=   ZqwezCmfTask.namezcmf_owner.idzCmfPerson:12312321Z	CmfPersonzCmfPerson.idzCmfTask.cmf_ownerzCmfTask.cache_status_typezCmfTask.logic_prefixZext_idZLIKEz
%::qwe::%%zCmfTask.ext_idz::qwe::zparent.ext_idzCmfTask.parentzstatus.ext_idZ	CmfStatuszCmfStatus.ext_idzCmfTask.statuszstatus.status_code_idZ12345zCmfStatus.status_codezstatus.status_coder   Z	qweqweqwez
CmfTask.idzparent.project.namestatusr   r[   uC   Ошибка в результате _query_params(models.CmfTask, r   u   Факт:        u   Должно быть: N)r]   r\   ZCmfTaskZdpr   rC   )r   Zf_listr\   fZres_origr   r   r   r   _test_query_params5  sf    








@
zDataProvider._test_query_paramsc                O   s"  |rt d| jjp2|p2tjp2|p2tjj| jj	}t
  | | j||d< tjjj| jj	 df|d|i|}|r~d}nBt }	tjjj||d}t |	 dkrtdt |	   |d	krtjtjjjd
|  g S |dk	rtjtjjjd|  |S tjtjjjd|  t }	| jj| jf|d|i|}
t |	 dkrxtdt |	   | jjdkr|
S |r|
D ]}d|_q|st }	| | j|d |d|d}tjjj||
| jj	 ||d t |	 dkrtdt |	   |
S dS )u   
        Пробросили сюда relation_load и relation_load_only для реализации join и подселектов в будущем
        :param args:
        :param kwargs:
        :return:
        r   r   z.listr   Nr   g333333?z%PROF DataProvider.list cache.get got r   zlist() From cache  Empty zlist() From cache zDP: list() From NOcache r   g      ?z1PROF DataProvider.list self.data_driver.list got r   Tr   r   r   z%PROF DataProvider.list cache.add got )r>   re   r   r   r   r   r   r   r   r/   r   r   r   r   r9   rT   r   r   r   r!   r=   r   r   r   )r   r   r   r   r   rf   r   r   r   Zprof_str   r  r   r   r   r   r!     sJ    (

"zDataProvider.list)r   r   r   c          
      O   sD  |rt d| jjp.|p.tjp.tjj| jj	}t
  | | j||d< tjjj| jj	 df|d|i|}|rzd }ntjjj||d}|dkrtjtjjjd|  tdn|d k	rtjtjjjd	|  |S t
  | jj| jf||}|s@| | j|d |d
|d}	tjjj||| jj	 |	|d |S )Nr   r   z.countr   r   r   zcount() From cache Empty z$BUG: count() cache can not be empty!zcount() From cache r   r   r   )r>   re   r   r   r   r   r   r   r   r/   r   r   r   r9   r   r   rK   r   rl   r   r   )
r   r   r   r   rf   r   r   r   r   r   r   r   r   rl     s.    (
"zDataProvider.count)r   c                O   s   t | jj||| j| j|dS NrS   re   r   )
QueryProxyr   queryre   )r   r   rf   r   r   r   r   rr     s       zDataProvider.query_deprecated)NN)NNr'  )r/   r0   r1   ru   r  compileZTABLE_FIELD_RErc   propertyr   r9   ri   r   r   rk   rW   rV   rj   r   r   r>  r!   rl   rr   r   r   r   r   r   -  s*   


J  
 1O6r   c                   @   sp   e Zd ZdZdddZdd ZdddZd	d
 Zdd Zdd Z	dd Z
dd Zdd Zedd Zdd ZdS )rA  u   
    Оборачиваем кастомный запрос и добавляем возможность извлекать данные с автомаппингом.
    TODO: Проверить слайсы query[a:b]
    Nc                 C   s0   || _ || _|| _t|t | _t|| _d S r   )_queryr   re   r    rv   _mapper_is_myr   _mapper)r   rB  rS   re   r   r   r   r   rc     s
    zQueryProxy.__init__c                    s    fdd}|S )u   Обёртка для методов, которые возвращают новый запрос на основании текущего.c                     s(   t j | |}t|jjjdS r?  )rO   rE  rA  r   re   rG  )rf   r   	new_queryitemr   r   r   method_proxy  s    z,QueryProxy.__getattr__.<locals>.method_proxyr   )r   rJ  rK  r   rI  r   __getattr__  s    zQueryProxy.__getattr__c                 C   s0   | j j| j| j|||d}t|| j | j| jdS )uR   
        Логика сортировки на основе модели
        )re   r   sliceaggregate_selectr@  )r   order_queryrE  re   rA  rG  )r   r   rM  rN  rH  r   r   r   rO    s        zQueryProxy.order_queryc                 C   s2   | j r.| j |r.| jj|| j t|d}|S )u6   Автоконвертация объектов в CMF)re   )r   rp   rG  r|   rn   r   )r   r   r   r   r   
_map_value  s    zQueryProxy._map_valuec                    s.   t |tr t fdd|D S  |S d S )Nc                 3   s   | ]}  |V  qd S r   )rP  )r   colrm   r   r   	<genexpr>  s     z&QueryProxy._map_row.<locals>.<genexpr>)r    tuplerP  )r   rowr   rm   r   _map_row  s    
zQueryProxy._map_rowc                    s   t  j}d}tjj||}tjj jjr6d}ntjj	|}t
  |dkrptjtjjjd|  g S |dk	rtjtjjjd|  |S tjtjjjd|   fdd jD }tjj|| jj   jr j  |S dS )	uo   Метод извлечения всех данных из текущего запрос с маппингом.Z
custom_allNr   zall() From cache Empty zall() From cache zDP: all() From NOcache c                    s   g | ]}  |qS r   )rU  )r   rT  rm   r   r   r     s     z"QueryProxy.all.<locals>.<listcomp>)r7   rE  r   r   r   r   r   re   r/   r9   r   r   r   r   rF  rG  rw   r   sql_kr   r   r   r   rm   r   all  s&    

zQueryProxy.allc                 C   s   t | j}d}tjj||}tjj| jjr6d}ntjj	|}t
  |dkrptjtjjjd|  dS |dk	rtjtjjjd|  |S tjtjjjd|  | j }| |}tjj||| jj  | jr| j  |S dS )uP   Метод извлечения первой строки с маппингом.Zcustom_firstNr   zDP: first() From cache Empty zDP: first() From cache zDP: first() From NOcache )r7   rE  r   r   r   r   r   re   r/   r9   r   r   r   firstrU  r   rF  rG  rw   )r   rW  rX  r   r   rT  r   r   r   r   rZ    s(    



zQueryProxy.firstc                 C   s   t   t| j}d}tjj||}tjj| jj	r<d }ntjj
|}t   |dkrvtjtjjjd|  d S |d k	rtjtjjjd|  |S tjtjjjd | j }tjj||| jj	  |S )NZcustom_countr   zDP: count() From cache Empty zDP: count() From cache zDP: count() From NOcache TODO)r   r7   rE  r   r   r   r   r   re   r/   r9   r   r   rl   r   rV  r   r   r   rl   9  s$    

zQueryProxy.countc                 O   s   | j j||}|S r   )rE  rj   )r   rf   r   r   r   r   r   rj   S  s    zQueryProxy.deletec                 C   s   | j S r   )rE  rm   r   r   r   dd_queryX  s    zQueryProxy.dd_queryc                 C   s   t |  S )u+   Чтение строк из запроса)iterrY  rm   r   r   r   __iter__\  s    zQueryProxy.__iter__)NNN)NNN)r/   r0   r1   ru   rc   rL  rO  rP  rU  rY  rZ  rl   rj   rD  r[  r]  r   r   r   r   rA    s   


rA  )N)N)N)r   )(r   rM   r   r   r  r   collectionsr   r   r&  r   typingr   r   Zflaskr   Zcmf.appr   r   r]   r   Zmodels.base_modelr
   r8   r7   r;   rB   rD   r@   rQ   rY   rZ   r^   r_   rv   r   r   r   r   rA  r   r   r   r   <module>   sL   
-

97  
     2