B
    f                 @   sP  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 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$d0d'd(Z%G d)d* d*Z&G d+d, d,Z'dS )1    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>3   s    zLrender_query.<locals>.LiteralCompiler.render_array_value.<locals>.<listcomp>)
isinstancelistjoinr   )r   valr   r   )r   r   r   r   1   s    
z8render_query.<locals>.LiteralCompiler.render_array_valuec                sj   t |trt|S t |fr0d|d S t |trXdd fdd|D  S t |S )Nz'%s'z%Y-%m-%d %H:%M:%Sz'{%s}'r   c                s   g | ]}  |jqS r   )r   r   )r   r   )r   type_r   r   r   =   s    zNrender_query.<locals>.LiteralCompiler.render_literal_value.<locals>.<listcomp>)r   intreprZstrftimer   r   superr   )r   r   r!   )LiteralCompiler	__class__r   r   r   )r   r!   r   r   6   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)r,   r+   r   r   )r%   r   r   r   r   render_query   s    	

r-   c             C   s
   t | S )uK   Вернём драйвер по имени источника данных)ds_registryget)ds_namer   r   r   get_ddC   s    r1   c              C   sj   t rtdd} xTtj D ]F\}}|ddkrR| dkrJddlm} |} | |d< t||dt |< qW dS )uY   Инициализация всех источников данных из конфигаuZ   Источники данных нельзя инициализировать дваждыNzsqlalchemy.poolclass	QueuePoolr   )r2   )name)	r.   	Exceptionr   Zdata_sourcesitemsr/   Zsqlalchemy.poolr2   new_dd)Z
queue_poolr0   	ds_configr2   r   r   r   init_dsH   s    r8   c           	   C   sR   xLt  D ]@\} }td|   y|  W q
 tk
rH   td Y q
X q
W dS )u=   Инициализация, миграция схемы БД.zInit DB u        не реализовано.N)r.   r5   printinit_dbNotImplementedError)r0   Zds_ddr   r   r   r:   X   s    r:   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)r7   r3   )r/   
ValueErrorsplit	importlibimport_modulegetattr)r7   r3   Zdd_mod_classZdd_typeZdd_module_nameZdd_class_nameZ	dd_moduleZdd_classr   r   r   r6   c   s    



r6   c              C   s   xt  D ]} |   q
W d S )N)r.   valuesbefore_request)ddr   r   r   rF   r   s    rF   c              C   s   xt  D ]} |   q
W d S )N)r.   rE   before_first_request)rG   r   r   r   rH   x   s    rH   c             C   sD   | rt tdrtd x&t D ]}| r4|  q"|  q"W d S )NdebugZROLLBACK)hasattrr   rI   r.   rE   rollbackcommit)Z	exceptionrG   r   r   r   commit_all_ds~   s    


rM   c              C   s.   x(t  D ]} td|   |   q
W d S )Nz	ROLLBACK )r.   rE   r   rI   rK   )rG   r   r   r   rollback_all_ds   s    rN   c              C   s,   ddl m}  xt D ]}||  qW dS )zmake_models hookr   )modelsN)cmf.includerO   r.   rE   make_models)rO   rG   r   r   r   rQ      s    rQ   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&d' ZdS )(BaseDataDriver N)r7   r3   c            O   s   || _ || _d S )N)r   r3   )r   r7   r3   Z_argsZ_kwargsr   r   r   __init__   s    zBaseDataDriver.__init__c             O   s   d S )Nr   )r   modelargsr   r   r   r   r/      s    zBaseDataDriver.getc             O   s   d S )Nr   )r   instancerV   r   r   r   r   create   s    zBaseDataDriver.createc             O   s   d S )Nr   )r   rW   rV   r   r   r   r   delete   s    zBaseDataDriver.deletec             O   s   d S )Nr   )r   rW   rV   r   r   r   r   update   s    zBaseDataDriver.updatec             O   s   d S )Nr   )r   rU   rV   r   r   r   r   r      s    zBaseDataDriver.listc             O   s   d S )Nr   )r   rU   rV   r   r   r   r   count   s    zBaseDataDriver.countc             C   s   d S )Nr   )r   r   r   r   rL      s    zBaseDataDriver.commitc             C   s   d S )Nr   )r   r   r   r   rK      s    zBaseDataDriver.rollbackc             C   s   d S )Nr   )r   r   r   r   rF      s    zBaseDataDriver.before_requestc             C   s   d S )Nr   )r   r   r   r   rH      s    z#BaseDataDriver.before_first_requestc             C   s   d S )Nr   )r   	cmf_modelr   r   r   dp_model   s    zBaseDataDriver.dp_modelc             C   s   d S )Nr   )r   Zsa_modelr   r   r   r\      s    zBaseDataDriver.cmf_modelc             C   s   d S )Nr   )r   Zdp_instancer   r   r   is_instance   s    zBaseDataDriver.is_instancec             C   s   d S )Nr   )r   Zmodels_r   r   r   rQ      s    zBaseDataDriver.make_modelsc             O   s   dS )u,   Вернём кастомный запросNr   )r   rV   r   r   r   r   query_deprecated   s    zBaseDataDriver.query_deprecatedc             C   s   t dS )u2   Создание/миграция схемы БД.N)r;   )r   r   r   r   r:      s    zBaseDataDriver.init_dbc             C   s   dS )u8   Закрываем текущие подключенияNr   )r   r   r   r   close_all_sessions   s    z!BaseDataDriver.close_all_sessions)r'   r(   r)   __doc__rT   r/   rX   rY   rZ   r   r[   rL   rK   rF   rH   r]   r\   r^   rQ   r_   r:   r`   r   r   r   r   rR      s&   rR   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   )r   r   r   r   post_mapping_hook   s    zBaseMapper.post_mapping_hookNc             C   s   t d S )N)r;   )r   obj
cmf_entityrU   
model_namefull_fields_loadr   r   r   object_to_cmf   s    zBaseMapper.object_to_cmfc             C   s   t d S )N)r;   )r   re   rd   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|}| |_ xH|j D ]>}|  dr<d|ddd }t||t|| q<W |S )u  
        TODO: создание промежуточного объекта плохо для производительности, нужно маппить напрямую из ResultSet
          да и в целом можно зарефакторить
        Nc                s6   i | ].}|   d rdd|ddd qS )_subN__r>   )
startswithr   rA   )r   field)
field_namer   r   
<dictcomp>   s   z4BaseMapper.obj_from_result_query.<locals>.<dictcomp>ZCmfObjrj   rk   r>   )	_fieldsr   objectkeysrl   r   rA   setattrrD   )r   result_queryrn   Z
obj_fieldsresrm   Zattnamer   )rn   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 ))rU   rg   )rh   )r   rd   )rg   rU   r   r   r   r      s    z*BaseMapper.list_to_cmf.<locals>.<listcomp>r   )r   Zlstrg   rU   r   )rg   rU   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   rb   
issubclassr@   )clsmapperr   r   r   
get_mapper   s    

zBaseMapper.get_mapper)NNNN)N)N)
r'   r(   r)   rc   rh   ri   rv   rw   classmethodr}   r   r   r   r   rb      s   

rb   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 )ry   u   
    Dataclass as model, для лёгкой сериализации в json
    fill class_name
    TODO fill meta для api, но вероятно это драйвер будет делать, там дешевле
    c               @   s   e Zd Zdd ZdS )zSimpleMapper.SimpleModelc             C   s@   t | dr&| j d| j d| j dS | j dt| dd  dS )Nr3   (z: )id)rJ   
class_namecoder3   rD   )r   r   r   r   __repr__  s    
z!SimpleMapper.SimpleModel.__repr__N)r'   r(   r)   r   r   r   r   r   SimpleModel  s   r   VirtualInitDatarq   rU   
field_listc                s   t    g | _d S )N)r$   rT   _virtual_init_list)r   )r&   r   r   rT     s    
zSimpleMapper.__init__c             C   s   i }x|t | jD ]n}||jj}|r0|j|_n|j|jd}|||jj< x2|jD ](}t||j}d|_	t
|j|j|j qRW qW g | _dS )uN   Вычислим все запрошенные виртуальные поля)simple_objectN)reversedr   r/   rU   r   rq   r   r   rD   _valuers   r   )r   Zcmf_instancesZ	init_dataZcmf_wrapper	field_clsZvirtual_fieldr   r   r   rc   #  s    
zSimpleMapper.post_mapping_hookNc          	   C   s&  ddl m} |s.|s$|jdd }t||}|sDt }|j|_ntd||g }x|p`|j	D ]}d|krt
||t||d qb|j	|}	|	sqb|	jr|s|	jdkr||	 qbt|	t	jt	jfr>t||	 d}
|
dkrqb|
dkrd}nH|o||}|rbt|| d	ddk	rb| j| |||d
}nqbnqbn(t|	t	jt	jt	jfrZqbnt||d}|dkrrqbt|	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
||| qbW |r"| j#tj$|||d |S )u  
        отображение obj -> simple_model
        если cmf_entity не указан, то создадим новый на основе модели cmf_model или её имени model_name
        возвращаем simple_model
        r   )rO   r=   uI   Передан cmf_entity в SimpleMapper, вероятно это багrk   .)defaultalwaysN_sub__id)rg   )tzinfo)rq   rU   r   )%rP   rO   r   rA   rD   ry   r   r   r@   r   rs   r/   virtual	load_modeappendrz   CmfRelationCmfGenericRelationid_fieldnamerh   rv   
CmfM2MBaseCmfBackrefBaseCmfDateRangeCmfObjectListrw   CmfDateTimer   replacer   timezoneutcCmfJsonujsonloadsr   r   )r   rd   re   rU   rf   rg   rO   Zvirtual_fieldsrn   r   obj_related_idfield_valuesub_fflr   r   r   rh   6  sj    






zSimpleMapper.object_to_cmf)NNNN)r'   r(   r)   ra   dataclassesZ	dataclassr   r   r   rT   rc   rh   r*   r   r   )r&   r   ry     s   ry   c               @   s   e Zd ZdddZdd ZdS )rx   Nc          	   C   s  ddl m} |sB|s2|s(|jdd }t||}|dd}d}nd}|sRt|}|}|r`|}	n
|j }	x@|	D ]6}
|j|
}|sqr|j	r|s|j
dkrt||
}d|_d|_qrt|tjtjtjfrqrt||
d	}t|tjr|d	krqr| ||o||
t||jd }t|tjtjfrt|| d	}|d	krHqr|dkrXd}n|of||
}|rrt||
 d
ddkrrt||
 d
rrt|tjr|dd n|j}t||d}|r| j| ||
||d}nd}nqrnqr|d	krqrt|tjr$|r$|js$|jtjjd}t|tjr>| |}nt|tj!r\|r\t"#|}t||
}|rx|jd	krt$|t%t&t'tdt(fr||_n
t)||_||_qrW d|_*|+  |S )u  
        отображение obj -> cmf_entity
        если cmf_entity не указан, то создадим новый на основе модели cmf_model или её имени model_name
        возвращаем ссылку на cmf_entity
        r   )rO   r=   T)emptyFr   N.r   )rU   rg   )r   ),rP   rO   r   rA   rD   r   r   rr   r/   r   r   r   Z_oldrz   r   r   r   r   rw   r   r   r   rU   rh   rv   r   r   r   r   r   r   ZCmfIPv4NetworkListZdb_castr   jsonr   r   strr"   floatboolr   is_newZmark_exists_in_db)r   rd   re   rU   rf   rg   rO   Zcmf_is_existsrt   rr   kr   rm   r   r   r   Z	model_subZ	field_objr   r   r   rh     s    



"

&





zMapper.object_to_cmfc             C   s   t |}x|j D ]\}}t|tjr*qt|tjr8qt|tjrFqt|tjrTqt|tjrbqt|tj	rpqt|tj
r~qt||}t|tjr|jdks|jrq| }|dkrtd| d| d| t||| qW |S )N.u%   Попытка update field=Ellipsis  )r   r   r5   rz   r   r   ZCmfM2MZCmfGenericM2MZ
CmfBackrefr   ZCmfGenericBackrefrD   r   CmfTyper   r   Z	db_formatr4   rs   )r   re   rd   rU   r   vZvvr   r   r   ri     s2    
zMapper.cmf_to_object)NNNN)r'   r(   r)   rh   ri   r   r   r   r   rx     s   
mrx   selectc          
   C   s   ydt krttt _W n" tk
r8 } z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   r>   Ztotal)r   r   dictr   r4   
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 )N)rU   data_source_ddrx   Z
mapper_cls)r   r   rU   r   r   r   rT   ,  s    zDataProvider.__init__c             C   s   | j st| j| _ | j S )N)r   r1   r   )r   r   r   r   data_driver2  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:
        u8   no_cache запрещен и будет удален osvfilterc                sJ   xD|  D ]8\}}|| kr(|| | |< q
| | |kr
 | | | q
W d S )N)r5   )Z_fields_grow_cacheZ_full_fields_loadr   r   )_grow_merger   r   r   L  s
    z%DataProvider.get.<locals>._grow_merge)Z
CmfProjectZCmfWorkflowZCmfLogicTypeZCmfSchemeWfZCmfSchemeWfRuleZCmfActivityrg   Nz.getr   )r   EmptyzDP: get() cache Empty zDP: get() cache zDP: get() NOcache r   rdiskTorder_bygroup_by)query_paramsr   )r4   rU   TEXKOM_no_cacher   import_modecmfapp	CMF_CACHEcache_is_lockedr'   _get_filterZTEXCOM_ENABLE_GROWCACHE_HACKZtexcom_growcache_hack_cacher/   hashr   print_debugDEBUGr   r3   readonlyadd_query_params)r   r   r   r   r   rV   r   Zfields_grow_cachekeycachedb_resr   )r   r   r/   8  sL    	(

 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   rX   )r   r   rX   r3   r   r   r   r   )r   rW   r   rV   r   ru   r   r   r   rX     s    zDataProvider.createc             O   s   t d | jj||}|S )NrY   )r   r   bulk_delete)r   rV   r   ru   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_alertrZ   zbulk_update start model=z args=z kwargs=zbulk_update endi  u)   Инвалидировали кеш по u$    обьектам у таблицы u    за z.2fu    мс   u2   DEV: Инвалидация кэша заняла )timerP   r   loggingr   r   rI   r   bulk_updater   lenr   r   r   Zinvalidate_idsr   Zwarning)
r   rU   rV   r   r   r   r   ru   Z
start_timeZelapsed_timer   r   r   r     s$    
$zDataProvider.bulk_update)r   c            O   s   t d | jj|f||}|r(td| jj}| jjdkr@|S |s|ddrd}d|jkrt|j	j
rt|j	rpdnd}|jr~d}tjj|| |S )	NrZ   u8   no_cache запрещен и будет удален osvr   r   Tcmf_deletedrY   rX   )r   r   rZ   r4   rU   r   r3   r/   r   r   Z
is_changedr   r   r   r   r   )r   rW   r   rV   r   ru   r   r   r   r   rZ     s    zDataProvider.updatec             O   s   | j j||}|S )N)r   rL   )r   rV   r   retr   r   r   rL     s    zDataProvider.commitc             O   s   | j j||S )N)r   rK   )r   rV   r   r   r   r   rK     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   rY   )r   rY   r3   r   r   r   r   )r   rV   r   ru   r   r   r   rY     s
    zDataProvider.deletec                s   | dg }|dkrg }t|tr,t|}|r6|g}xJ|  D ]:\}}||jkrD||= t|tjrn|j	}|
|d|g qDW d
fdd	fdd  fdd	|}|S )u   
        Преобразуем обычные kwargs в продвинутый фильтр для однообразной логики фильтрования
        :param model:
        :param kwargs:
        :return:
        r   Nz==c          
      sn   |s
| j }y| j|||d}W nJ tk
rh } z,t|dkrR | |||d d}nt|W d d }~X Y nX |S )N)yearmonthdayzday is out of range for monthr>   )cur_datetimer   r   r   )r   r   r@   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 }
x|D ]}|\}}}t|}d }|rz|d	krnd
}n|dkrzd}|s|
pd
}|}
||krB|dkr||| 7 }qBqB|dkr||| 7 }qBqB|dkr||| 7 }qBqB|dkr||| 7 }qBqB|dkr||| 7 }qBqB|dkrB|	|| 7 }	qBqBW t  }}|j}|j}|sJ|r|dk rXd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   +r>   -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_month)r   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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   H  s    zODataProvider._get_filter.<locals>._recursive_params_replace.<locals>.<listcomp>Z__G_CURRENT_USERZ__G_NOWi,  Z__G_DATEip  znow())r   r   r   r   Zcurrent_userr   r   Zjscache_timelifer   r   r   rl   )r   )r   r   r   r   r   F  s*    



z;DataProvider._get_filter.<locals>._recursive_params_replace)N)r/   r   r   r   r   copyr5   r   r   r   r   )r   rU   r   Zsmart_filterr   r   r   )r   r   r   r   r     s$    


FzDataProvider._get_filterANDc             C   s  ddl m} tg g i d}|rxn|D ]f}|dkr2q$|drZ|d d |jkrZ|d d }|drp|dd  }|d	 |j d
|  q$W |rxN|D ]F}	|	dr|	d d |jkr|	d d }	|d	 |j d
|	  qW |s|S t|d t	rZxZ|D ]R}
xJ| j
||
|d D ]2\}}|dkr<|| | n|| | qW q W n|d dkrxV| j
||dd  |d d D ]2\}}|dkr|| | n|| | qW n"|d dkrbt|dks|d dkrtdxf|d D ]Z}|dkrq |dr>|d d |jkr>|d d }|d	 |j d
|  q W nt|dkrd }|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rJ|d }nD|d |jkrJ|d }|j|d  }|d }t|dkrJ|d }d}|dr~|d d |jkr~|d d }d}|r|dr| }|r|d d |d jkr|d d }d}|r|s|dkr|dkr|d }t|trt	|}t|t	s|g}g }xH|D ]@}tt|tjr:|j}tt|trR|jj}|| qW |dkr|d |g | ||jkr|d |g | t|tjr|jdkr|j|jd d p|}t|tjr>|dkr>xJ| D ]>}|s|d |j  |r|d	 |j d
|  qW t|tjr|dkrx^| D ]R}xJ| 
||d  D ]2\}}|dkr|| | n|| | qzW q`W |d	 |j d
|  n|d| ddd |S ) Nr   )r   )rO   r   cache_clustersr   Z_idr   r>   r   .)parent_operr  )r   ORr      )=z==ut   Операция order_by в фильтре должна быть в формате: ["order_by", "=", [поля..]]r	   r   ANYtextFT)r  z==INr  parentrO   EXISTSuP   Ошибка  при выполнении UBQL - неверный запрос. uM    Проверьте правильность введенных данных.)abort)rP   r   r   endswithr   rl   r   r   r   r   r   r5   rZ   extendr   r4   rA   Zrelated_modelssetrz   r   r   r   r
   r   r   Zcache_cluster_fieldsZCmfTUUIDr/   Z
CmfRelBase)r   rU   Z
obj_filterZobj_order_byZobj_group_byr  r   ru   r   r   Zfilt_lsr   r    rm   Zobj_filter0Zobj_filter1Zfield__field_namern   ZoperZfield_is_tuuidZ
_relmodelsZrule_values_dirtyZrule_valuesrvZrmodelr   r   r   r   h  s    




*

 $
 


 
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} xZ|D ]R\}}|jj|j|}||krtd/| d0 td1|  td2|  qW d3S )4ug   
        Тестирование
        Запуск: models.CmfTask.dp._test_query_params()
        listsr  Zcache_status_typer  ZIN_PROGRESSZlogic_prefixzlist.agile_sprintZCmfListzCmfList.cache_status_typezCmfList.logic_prefixzCmfTask.lists)rO   r   parentsr  r  z=={   r3   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   )rO   uC   Ошибка в результате _query_params(models.CmfTask, r   u   Факт:        u   Должно быть: N)rP   rO   ZCmfTaskZdpr   r9   )r   Zf_listrO   fZres_origru   r   r   r   _test_query_params  sH    








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}ntjjj||d}|dkrt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
|  | jj| jf|d|i|}	| jjdkr&|	S |rBx|	D ]}
d|
_q2W |s| | j|d |d|d}tjjj||	| jj	 ||d |	S dS )u   
        Пробросили сюда relation_load и relation_load_only для реализации join и подселектов в будущем
        :param args:
        :param kwargs:
        :return:
        u8   no_cache запрещен и будет удален osvr   z.listr   N)r   r   zlist() From cache  Empty zlist() From cache zDP: list() From NOcache r   r   Tr   r   )r   r   )r4   rU   r   r   r   r   r   r   r   r'   r   r   r   r/   r   r   r   r   r3   r   r   r   )r   r   r   r   r   rV   r   r   r   r   r   r   r   r   r   r   W  s6    (
"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 )Nu8   no_cache запрещен и будет удален osvr   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   )r4   rU   r   r   r   r   r   r   r   r'   r   r   r   r/   r   r   r@   r   r[   r   r   )
r   r   r   r   rV   r   r   r   r   r   r   r   r   r[     s,    (
"zDataProvider.count)r|   c            O   s   t | jj||| j| j|dS )N)rG   rU   r|   )
QueryProxyr   queryrU   )r   r|   rV   r   r   r   r   r_     s    zDataProvider.query_deprecated)NN)NNr   )r'   r(   r)   ra   r   compileZTABLE_FIELD_RErT   propertyr   r/   rX   r   r   rZ   rL   rK   rY   r   r   r  r   r[   r_   r   r   r   r   r   (  s(   

I 
 !O+r   c               @   sf   e Zd ZdZ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edd Zdd ZdS )r  u   
    Оборачиваем кастомный запрос и добавляем возможность извлекать данные с автомаппингом.
    TODO: Проверить слайсы query[a:b]
    Nc             C   s0   || _ || _|| _t|t | _t|| _d S )N)_queryr   rU   r   rb   _mapper_is_myr}   _mapper)r   r  rG   rU   r|   r   r   r   rT     s
    zQueryProxy.__init__c                s    fdd}|S )u   Обёртка для методов, которые возвращают новый запрос на основании текущего.c                 s(   t j | |}t|jjjdS )N)rG   rU   r|   )rD   r  r  r   rU   r  )rV   r   Z	new_query)itemr   r   r   method_proxy  s    z,QueryProxy.__getattr__.<locals>.method_proxyr   )r   r  r   r   )r  r   r   __getattr__  s    zQueryProxy.__getattr__c             C   s2   | j r.| j |r.| jj|| j t|d}|S )u6   Автоконвертация объектов в CMF)rU   )r   r^   r  rh   r\   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 )N)r"  )r   col)r   r   r   	<genexpr>  s    z&QueryProxy._map_row.<locals>.<genexpr>)r   tupler"  )r   rowr   )r   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   )r'  )r   r&  )r   r   r   r     s    z"QueryProxy.all.<locals>.<listcomp>)r-   r  r   r   r   r   r   rU   r'   r/   r   r   r   r   r  r  rc   )r   sql_kr   r   r   r   )r   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 )r-   r  r   r   r   r   r   rU   r'   r/   r   r   r   firstr'  r   r  r  rc   )r   r(  r)  r   r   r&  r   r   r   r   r+    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   r-   r  r   r   r   r   r   rU   r'   r/   r   r   r[   r   )r   r(  r)  r   r   r   r   r   r   r[     s$    

zQueryProxy.countc             O   s   | j j||}|S )N)r  rY   )r   rV   r   r   r   r   r   rY     s    zQueryProxy.deletec             C   s   | j S )N)r  )r   r   r   r   dd_query  s    zQueryProxy.dd_queryc             C   s   t |  S )u+   Чтение строк из запроса)iterr*  )r   r   r   r   __iter__  s    zQueryProxy.__iter__)NNN)r'   r(   r)   ra   rT   r!  r"  r'  r*  r+  r[   rY   r  r,  r.  r   r   r   r   r    s   
r  )N)N)N)r   )(r   rB   r   r   r   collectionsr   r   r   r   typingr   r   Zflaskr   Zcmf.appr   r   rP   r   Zmodels.base_modelr
   r.   r-   r1   r8   r:   r6   rF   rH   rM   rN   rQ   rR   rb   ry   rx   r   r   r  r   r   r   r   <module>   sH   
+

<7{ 
    }