U
    TFd                    @   s   d dl Z d dlZd dlZd dlZd dlmZ d dlmZmZm	Z	m
Z
mZmZ d dlmZ d dlmZ d dlT d dlmZ d dlmZ d	d
 ZG dd dejZdS )    N)Path)DictOptionalListCallableUnionType)BeautifulSoup)cmf_context)*)cmf_plugin_tracker_api)
TrackerApic                    s    fdd}|S )Nc                    s    fdd}|S )Nc                    s   zpz4| j jd d dd   | f||W W <S  tk
rl   |  jd7  _| j jd  Y nX W 5 | j j  X d S )Nz====================    u   Ошибка )
cmf_importdpcommitloggerinfo	Exception
has_errors	exception)objargskwargs)funcname 2./modules/tracker/models/cmf_plugin_tracker_api.pywrapper   s    z3catch_exception.<locals>.decorator.<locals>.wrapperr   )r   r   r   )r   r   	decorator   s    
z"catch_exception.<locals>.decoratorr   )r   r!   r   r    r   catch_exception   s    r"   c                       s  e Zd ZU ejjd Zeed< ee	e
f ed<  fddZedd Zeee	e
f dd	d
Zee
 dddZedd ZedddZee	eee
  dddZedd Zeee
 e
dddZdd Zee
 e
dddZdd Zeee	e	f  dd d!Zed"d# Zed$d% Zd&d' Zd(d) Zd*d+ Z d,d- Z!e	d.d/d0Z"e	d.d1d2Z#e	d.d3d4Z$d5d6 Z%e	d7d8d9Z&e	d7d:d;Z'e	e(d<d=d>Z)d?d@ Z*e
edAdBdCZ+dDdE Z,dFdG Z-dHdI Z.dJdK Z/dLdM Z0e
dNdOdPZ1e2dQdRdS Z3e2dTdUdV Z4e2dWdXdY Z5dZd[ Z6e2d\d]d^ Z7d_d` Z8dadb Z9e2dcddde Z:dfdg Z;e2dhdidj Z<e2dkdldm Z=edndo Z>e2dpdqdr Z?e2dsdtdu Z@ee
dvdwdxZAe
dvdydzZBee
dvd{d|ZCe2d}d~d ZDe2de	e	dddZEdd ZFe2de	dddZGedd ZHe
dvddZIe2ddd ZJdd ZKdd ZLe2ddd ZMdddZNe2ddd ZOe
e
dddZPe2ddd ZQe2ddd ZRe2ddd ZSdd ZTe2ddd ZUdd ZV  ZWS )CmfPluginTrackerApi)trackertracker_fieldsr   $_CmfPluginTrackerApi__tracker_fieldsc                    sN   t  j|| d | _d | _g | _d| _i | _i | _i | _i | _	d | _
d | _d S )Nr   )super__init__source_hashsettingsselected_queuescount_issuesissue_relationssubtaskssprint_issuesproject_list_issuesjira_urlr&   )selfr   r   	__class__r   r   r(   '   s    zCmfPluginTrackerApi.__init__c                 C   s(   |  dddg t| jjj| jjjdS )u8    Клиент для работы с API Yandex Tracker pluginzplugin.ext_tokenzplugin.ext_token_addontokenZorg_id)load_fieldsr   r5   	ext_tokenvalueext_token_addonr2   r   r   r   r$   5   s    zCmfPluginTrackerApi.tracker)returnc              	   C   s~   | j r| j S | j d}| rHt|d}t|| _ W 5 Q R X n0| j	 | _ t|d}t
| j | W 5 Q R X | j S )Nzfields.jsonr+w+)r&   r   get_download_pathjoinpathexistsopenjsonloadr$   Z
get_fieldsdump)r2   	file_pathfr   r   r   r%   ;   s    z"CmfPluginTrackerApi.tracker_fieldsc                 C   s   || _ | | j jd }ddg g gdg}| jjddD ]}| }t|tjj	 d D ]f\}}|d sjqX| 
||d	 }| |d d
 |}|d d |d d  |d d d | qXq8|S )Nimport_settingsu   Задачиzcalendar-today)titleicontitlesrows   Zmax_resultsfieldsmodel_fieldattr
field_namer   rL   captionrM   )r   _normalize_settingsjson_settingsr$   
get_issuesas_dict	enumeratemodelsCmfTaskverbose_name
_get_value_normalize_valueappend)r2   r   r*   resultissueZnumsettingr:   r   r   r   previewK   s    zCmfPluginTrackerApi.previewc               
   C   s   dt j t jjddt j t jjddt j t jjddt j t jjddt j t jjddt j t jjddt j	 t j	jdg} | S )	uW    Собственный магазин при выборе импорта из Tracker u   Поля контактов)rT   rP   rK   u   Поля организацийu   Поля задачu   Поля заметокu   Поля проектовu"   Поля списков задачu   Поля групп)
rZ   	CmfPersonimport_shop_fieldsrK   Z
CmfCompanyr[   
CmfCommentZ
CmfProduct
CmfProjectCmfPersonGroup)resr   r   r   calc_models_settings\   s*    





z(CmfPluginTrackerApi.calc_models_settingsTc                 C   s   |sdS |  |}t|tr |S |s(dS t|tr^dddg}|D ]}||kr@||   S q@dS t|trg }|D ]f}d|kr||d d  qpd|kr||d d  qpd|kr||d  qp|rp|t| qpd|S |S )	u`   
        Метод получает значение параметра объекта
        Nr   displaykey inwardIssueoutwardIssue,)get
isinstancebooldictlistr_   strjoin)r   rR   to_strr:   Z
str_fieldsZ	str_fieldr`   Zrelated_objr   r   r   r]   p   s4    





zCmfPluginTrackerApi._get_value)rS   r=   c                 C   s&   |sd S | j |gd}|r"|d S d S )N)Zfields_namer   )re   )modelrS   ri   r   r   r   _get_field_name   s    z#CmfPluginTrackerApi._get_field_namec                 C   s   dddddd}| | dS )Nr   r      )u   Незначительныйu   Низкийu   Среднийu   Критичныйu   Блокер)rq   )prioritymappingr   r   r   _get_priority   s    z!CmfPluginTrackerApi._get_priority)r*   r=   c                 C   s   dd | D S )Nc                 S   s   i | ]}|d  |qS r    r   ).0sr   r   r   
<dictcomp>   s      z;CmfPluginTrackerApi._normalize_settings.<locals>.<dictcomp>r   )r*   r   r   r   rU      s    z'CmfPluginTrackerApi._normalize_settingsc                 C   s   |dkr|  |S |S )Nr}   )r   )r2   Zlocal_field_namer:   r   r   r   r^      s    
z$CmfPluginTrackerApi._normalize_valuec                 C   sT   i }|D ]F}|d sq| j ||d dd}| |d d |}|||d d < q|S )uC    Преобразование настроек для модели rQ   rR   F)rx   rS   )r]   r^   )r2   r   r*   Znormalized_objrb   r:   r   r   r   _normalize_obj   s    z"CmfPluginTrackerApi._normalize_objc              	   C   s<   ddddddddd	}||kr&|| S | j |i d
dS )Nu   ИмяZEmailu   Активныйu   Созданоu
   Авторu
   Текстu   Ключu(   Не работает/Уволенный)rk   emailZactivecreatedauthorZbodyrl   	dismissedr   rm   )r%   rq   )r2   rR   r~   r   r   r   _get_setting_title_from_attr   s    
z0CmfPluginTrackerApi._get_setting_title_from_attrc                 C   sn   g }ddddddddd	d
ddddd}i }| j  D ]4\}}| ||d }|||d|d q4|S )uO    Сопоставление настроек для модели models.CmfTaskresponsiblecmf_created_at
cmf_authordeadlinetextcoder}   parentstatusZagile_story_pointsr   
logic_typecmf_modified_atcmf_modified_by)assignee	createdAt	createdByr   descriptionrl   r}   queuer   ZstoryPointssummarytype	updatedAt	updatedByrm   NrQ   rR   )r%   itemsrq   r_   )r2   Zissue_settingsZdefault_local_attrs_mappingZadditional_attrZcustom_field_keyZcustom_fieldrR   r   r   r   _get_issue_import_settings   s0    

z.CmfPluginTrackerApi._get_issue_import_settingsc                  C   s0   ddddddddddddd	d
dg} | S )NZ
first_nameZ	firstNamer   	last_nameZlastNamer   rk   r   does_not_workr   r   )Zuser_settingsr   r   r   _get_user_import_settings   s    z-CmfPluginTrackerApi._get_user_import_settingsc                  C   s    dddddddddg} | S )Nr   r   r   r   r   r   r   )Zcomment_settingsr   r   r   _get_comment_import_settings   s
    z0CmfPluginTrackerApi._get_comment_import_settingsc                    s  t ttj ttj f }g  |_ttg tt f |td fdd}j	dg j
 d}| r D ] }|d D ]} qq qqvdD ]} qqn8dd	 jjd
dD d }dd	 jjd
dD d }||jtj ||jtj  dg d  S )N)r   settings_funcry   r=   c                    sj   | }|D ]H} | |d |d< ||d |d< |d |d< |j|d< q
 |j|d d S )NrR   r:   rQ   rJ   rK   )r   rP   )r]   rz   r   rK   r_   r\   )r   r   ry   Zobj_settingsrb   r`   r2   r   r   _get_settings  s    z@CmfPluginTrackerApi.tmplt_import_settings.<locals>._get_settingsplugin.plugin.*queuesidusersc                 S   s   g | ]}|  qS r   rX   r   r   r   r   r   
<listcomp>  s     z=CmfPluginTrackerApi.tmplt_import_settings.<locals>.<listcomp>r   rO   r   c                 S   s   g | ]}|  qS r   r   r   r   r   r   r     s     selectedObjects)r   r:   )r   r   rZ   r[   rd   r   r   r   r   r8   r@   rA   rB   _get_projects_get_project_tasks_simple_getr$   rW   	get_usersr   r   r_   )r2   r   Z	TypeModelr   Zdump_dirprojecttaskuserr   r   r   tmplt_import_settings   s&    &	z)CmfPluginTrackerApi.tmplt_import_settingsc                 C   sd   t dkrd S | j d| }tjjddd| dgd}|s`| jjd| d |  jd	7  _|S )
Nunknown::ext_idLIKE%filteru3   Не найден пользователь ext_id ""r   )	r   r)   rZ   rd   rq   r   r   errorr   )r2   uidperson_ext_idpersonr   r   r   _get_person"  s    zCmfPluginTrackerApi._get_personc              
   c   sb   | j  d}| r^t|D ]:}|dr2q"t||dd}t	|V  W 5 Q R X q"d S )Nr   .dirty	data.jsonr>   )
r   r@   rA   rB   oslistdirendswithrC   rD   rE   )r2   	queue_dirZqueue_idrH   r   r   r   r   /  s    
z!CmfPluginTrackerApi._get_projectsc              
   C   s   z:|dkr"dd | j |D }ndd | j |D }W n\ tk
r } z>t| tjj|ddgd| _dd | 	|D }|s W 5 d }~X Y nX |S )	Nboardsc                 S   s    g | ]}|j d s| qS )   Доска проекта)r   
startswithrX   r   r   r   r   r   ;  s    z?CmfPluginTrackerApi.get_from_online_or_dump.<locals>.<listcomp>c                 S   s   g | ]}|  qS r   r   r   r   r   r   r   >  s     r   r   )r   rP   c                 S   s   g | ]}|qS r   r   r   r   r   r   r   C  s     )
r$   Zget_collectionr   gdebugrZ   Z	CmfImportrq   r   r   )r2   Zcollection_namecmf_import_iddataer   r   r   get_from_online_or_dump8  s    
z+CmfPluginTrackerApi.get_from_online_or_dump)r   c                O   s   |  d|S )u   
        В Yandex Tracker 'Очереди', это 'Проекты' в EVA.
        Метод получения всех проектов в Tracker для настройки выбора импортируемых очередей.
        r   )r   )r2   r   r   r   r   r   r   get_all_queuesI  s    z"CmfPluginTrackerApi.get_all_queuesc                   s   | dg }g  |D ]$}|d|d<  t|d  q| d|}g }|D ]t}| dg }	t|	dkrt||d< n( fdd	|	D }
t|
dkrqN|
|d< t|d d
krdnd|d< || qN|S )u  
        В Yandex Tracker 'Проекты', это обычные(классические) списки в EVA !!!
        Метод получения проектов(списков), которые не удалось автоматически сопоставить с очередями,
        для дальнейшей настройки маппинга 'проект -> очередь(проект в EVA)'

        С front в kwargs ожидает:
        selected_queues = [
            {'self': 'https://api.tracker.yandex.net/v2/queues/QWE', 'id': '1', 'key': 'QWE', 'name': 'Тестовый QWE'},
            {'self': 'https://api.tracker.yandex.net/v2/queues/ASD', 'id': '2', 'key': 'ASD', 'name': 'Тестовый ASD'}
        ]

        Возвращает:
        "result": [
        {
            "self": "https://api.tracker.yandex.net/v2/projects/8",
            "id": "8",
            "key": "Проект 1",
            "name": "Проект 1",
            "queues": [
                {
                    "self": "https://api.tracker.yandex.net/v2/queues/SRM",
                    "id": "6",
                    "key": "SRM",
                    "display": "Тестовый 123"
                },
                ...
            ],
            "is_show": false  # если в queues только одно значение, нет смысла предлагать пользователю маппить
        }, ... ]

        Маппинг сохраняется при CmfImport.update в obj выбранной очереди в параметр projects
        'json_settings': {
            ...
            'import_settings': {
                ...
                {'name': 'selectedObjects', 'value': [
                    ...
                    'obj': {
                        'self': 'https://api.tracker.yandex.net/v2/queues/QWE',
                        'id': 1,
                        'key': 'QWE',
                        'name': 'Тестовый QWE',
                        'projects': [{'id': '8', 'name': 'Проект 1'}, {...}, ... ],
                        'boards': [{'id': '14', 'name': 'Доска 1'}, {...}, ... ]
                    }
                    ...
                ]}
            ...
        }
        r+   r   rk   r   projectsr   r   c                    s    g | ]}t |d   kr|qS r   rv   r   r   Zselected_queues_idsr   r   r     s      z8CmfPluginTrackerApi.get_all_projects.<locals>.<listcomp>r   TFis_show)rq   popr_   rv   r   len)r2   r   r   r   r+   r   r   r`   r   r   
new_queuesr   r   r   get_all_projectsP  s$    3
z$CmfPluginTrackerApi.get_all_projectsc                   sL  | dg }g i  |D ],}|d|d< |d  | |d < q| d|}g }|D ]}t|d |d d}	| d }
r|
d kr|d g|	d	< d
|	d< ||	 qZ| di  d }r fdd|D }t|dkrqZ||	d	< t|dkrdnd
|	d< ||	 qZ||	d	< t|	d	 dkr4dnd
|	d< ||	 qZ|S )u  
        Метод получения досок, которые не удалось автоматически сопоставить с очередями,
        для дальнейшей настройки маппинга 'доска -> очередь(проект в EVA)'

        С front в kwargs ожидает:
        selected_queues = [
            {'self': 'https://api.tracker.yandex.net/v2/queues/QWE', 'id': '1', 'key': 'QWE', 'name': 'Тестовый QWE'},
            {'self': 'https://api.tracker.yandex.net/v2/queues/ASD', 'id': '2', 'key': 'ASD', 'name': 'Тестовый ASD'}
        ]

        Возвращает:
        "result": [
        {
            "id": 14,
            "name": "Доска 1",
            "queues": [
                {
                    "self": "https://api.tracker.yandex.net/v2/queues/QWE",
                    "id": "6",
                    "key": "SRM",
                    "display": "Тестовый QWE"
                },
                ...
            ],
            "is_show": true  # если в queues только одно значение, нет смысла предлагать пользователю маппить
        }, ... ]

        Маппинг сохраняется при CmfImport.update в obj выбранной очереди в параметр boards
        'json_settings': {
            ...
            'import_settings': {
                ...
                {'name': 'selectedObjects', 'value': [
                    ...
                    'obj': {
                        'self': 'https://api.tracker.yandex.net/v2/queues/QWE',
                        'id': 1,
                        'key': 'QWE',
                        'name': 'Тестовый QWE',
                        'projects': [{'id': '8', 'name': 'Проект 1'}, {...}, ... ],
                        'boards': [{'id': '14', 'name': 'Доска 1'}, {...}, ... ]
                    }
                    ...
                ]}
            ...
        }
        r+   r   rk   rl   r   r   )r   r   defaultQueuer   Fr   r   r   c                    s   g | ]}|kr | qS r   r   r   Zselected_queues_dictZselected_queues_keysr   r   r     s      z6CmfPluginTrackerApi.get_all_boards.<locals>.<listcomp>r   r   T)rq   r   r_   r   rt   r   )r2   r   r   r   r+   r   r   r`   
board_databoardr   r   r   r   r   r   get_all_boards  s6    0z"CmfPluginTrackerApi.get_all_boardsc                 C   s0   t | jj| jj d | j_| j  t  d S )Nd   )intr   imported_object_countjson_object_countprogresssavecommit_with_eventr<   r   r   r   _calc_progress  s    
z"CmfPluginTrackerApi._calc_progressr    c              	   c   sF   | j  | d}t|d}|D ]}t|V  q&W 5 Q R X d S )N.jsonr>   r   r@   rA   rC   rD   loads)r2   r   rG   rH   rowr   r   r   r     s    zCmfPluginTrackerApi._simple_getc              	   C   s   | j  | d}| j  | d}| rL|dkrHt| nd S t|dp}| D ]b}| }|dkr|j	drq^dd |j
jd	d
D |d< | j  jd7  _|t|d  q^W 5 Q R X t|| | j jdd t  d S )Nr   z.json.dirty)r   r   sprintsa+r   r   c                 S   s   g | ]}|  qS r   r   )r   columnr   r   r   r   	  s     z4CmfPluginTrackerApi._simple_dump.<locals>.<listcomp>all)expandcolumnsr   
TZ	only_data)r   r@   rA   rB   r   removerC   rX   r   r   r   Zget_allr   writerD   dumpsshutilmover   r   )r2   Zapi_funcr   rG   Zfile_path_tmprH   r   Zrow_dictr   r   r   _simple_dump  s$    
 z CmfPluginTrackerApi._simple_dump)r   attachments_dirc                 C   s  |sd S | j jd | j d|d  }t|ddd D ]}d}|drVd}|j| }zP|d	r| j j	d
|  W q>|ds| j
j | }|| j
js| j j	dtj|  W q>|| j
j ds| j j	dtj|  W q>tj|dd dd }| j
|}	tj|	j}
||
}tjj|	j|| jd}|stj| j |	j|| j|	 d}||_|
|_|	 |_d|_|  |j  W q> t k
r } z2| j j!  | j j	dtj| d|  W 5 d }~X Y q>X q>d S )Nu/   Обработка ссылок в текстеr   r   Zlxmlc                 S   s   |  dp|  dS Nhrefsrchas_attrtagr   r   r   <lambda>      z1CmfPluginTrackerApi._dump_links.<locals>.<lambda>r   r   zmailto:u   Почта: httpuA   Внешняя ссылка, оставляем как есть: z/ajax/v2/attachments/u   Не файл: /r{   ?r   r   
obj_ext_idr)   )r   r   r  r)   import_raw_jsonFu>   Не удалось скачать файл по ссылке : )"r   r   r   r)   r	   find_allr  attrsr   warningr$   urlurllibparseunquotesplitZget_attachmentrZ   CmfDocument_get_filenamer   rA   CmfImportDownloadrq   contentrX   pathr  
downloadedr   r   r   r   Zrollback)r2   r   r   
issue_dictissue_ext_idr  rl   r  Zattachment_id
attachment	file_namerG   download_jobr   r   r   r   _dump_links  sZ    



 


zCmfPluginTrackerApi._dump_linksc                 C   sF  t dd0 |}d}	| jjd| d| d| d |j|d |d	}
t||D ]}|j|
|d
}
|
D ]}| }| j d|d  }zzL| j rd| j_| j  W W X  W 5 Q R  dS | jjd|d  d|d   |t|d }| rW W  ql|t|d d }|jdd |d}|drJ| jjdt|d  ||D ]}|d }tj|}||}|d dr
tjj|d || jd}|stj| j|d || jd}||_||_||_d|_|  |j	
  n<| jjd|d   t|d}| |d  W 5 Q R X qt| !|dd|| |d}| r~t"#| | jjd  t|d!R}|$|D ]@}| t%&|d"  | j j'd7  _'| !|d#d|| qW 5 Q R X |(||d$< t)*|| |jdd |d% }|+ D ]:\}}|D ]*}|d |d& d kr0||d'<  q$q0q$t|,dd|d(< |d)}t|d*P}t%-|| | j j'd7  _'|  j.d7  _.| jjd+| j. d,|d-   W 5 Q R X W n,   |	d7 }	| jj/d.|d   Y nX W 5 | jj	
  X ql|0|	 qT|j12  W 5 Q R X d S )/NFZinit_views_and_dsr   u   Страницы задач с u    до u    по u    на страницеrl   )per_page)pager   r   import-cancelingr   u   Задача "" ID r   Texist_okattachmentsu%   Обработка вложений: r   r  r  r
  )r   r   r  r)   u   Не ссылка wb+descriptionHtmlrm   comments.jsonu'   Дампинг комментариевr   r   textHtml	changelog	workflowsr   workflow
issue_pathr   r?   u   Скачано задач     из r,   u0   Не удалось скачать задачу )3r
   r   r   r   Zget_issues_for_queuerangeZget_issues_for_queue_by_pagerX   r)   r   r   	is_cancelr   r   rA   rv   rB   mkdirrq   r   Zget_issue_attachmentsrZ   r  r  r   r  r  r   r  r  r  rC   r   r!  r   r   Zget_issue_commentsrD   r   r   Zget_issue_changelogr   r   r   replacerF   r,   r   putclientclose)r2   
start_pageend_pager#  	tasks_dir
queue_datar$   tasks_that_are_doner8  errorsissuesr$  ra   r  r  Ztask_dirZtask_dir_tmpr   r  r  Zattach_file_pathr   rH   Zcomments_filecommentr/  r0  
issuetypesZ	issuetypeZ	info_pathr   r   r   _dump_task_partF  s    "


"






$
"z#CmfPluginTrackerApi._dump_task_partr=  cntc                 C   s  ddl m} ddlm} d}t|| }|| j }||k rZt|| j }t|| }t|d d}|j	dd | }	d}
t|| j }d	}|}g }|dkr2|| }||kr|d	 }|| j
d
| |||||t| jjj| jjjd|	dd}|| |  | jjd|  ||7 }||8 }q|D ]}|  q6| jjd |	 sn|
|	 7 }
qT| jjd|
  |
S )Nr   QueueThreadr   r   tasksTr'  r   Z
dump_tasksr6   )r:  r;  r#  r<  r=  r$   r>  targetr   r   u   Форк _dump_task_part proc=uE   Конец параллельного скачивания задачu   Ошибок: )r   rG  	threadingrI  mathZceilthreading_max_forksr   rA   r5  rC  r   r5   r9   r:   r;   r_   startr   r   r   rw   emptyrq   )r2   r=  rE  rG  rI  r#  Ztotal_pagesZper_threadsr<  r>  r?  Z	step_pager:  Z	last_pageZprocessr;  procr   r   r   _dump_tasks  s\    





zCmfPluginTrackerApi._dump_tasksc           	   	   C   s   | | d}| r"t| t|d}t||}t|tkrx|D ],}|t	
| d  | j jd7  _qHnnt|tkr| D ]\}}dd |D ||< qt	|| | j jd7  _n t	| | | j jd7  _W 5 Q R X dS )u(  
        Метод создает дамп элемента очереди.
        :param attr: элемент очереди
        :param queue_obj: объект очереди
        :param queue_dir_tmp: директория для сохранения JSON файла дампа
        r   r   r   r   c                 S   s   g | ]}|  qS r   r   r   _r   r   r   r     s     z9CmfPluginTrackerApi._dump_queue_items.<locals>.<listcomp>N)rA   rB   r   r   rC   getattrr   ru   r   rD   r   rX   r   r   rt   r   rF   )	r2   rR   	queue_objqueue_dir_tmpZ
items_filerH   itemkvr   r   r   _dump_queue_items  s     

z%CmfPluginTrackerApi._dump_queue_itemsc              
   C   s*  | j d d d }|d s"tddd |d D | _| j d	}|jd
d t| j}td| }| jj	
d | jD ]}z\| j rd| j_| j  W  d S | j jd7  _| jj	
d|d  d|d  d |t|d }|d}| j|d }| s||d  d}	| jj|d d}
|
 }|d |d< |d |d< t|	|d< ||d< tj|d d
d | jj	
d | d|
|	 | jj	
d | d |
|	 | jj	
d! | d"|
|	 | jj	
d# | d$|
|	 | jj	
d% | d&|
|	 | j j|7  _| jjd
d' t  t|d | t||d< t|d d}t|d(}t|| W 5 Q R X n t|d)}t |}W 5 Q R X | jj	
d*|  |dkrd| _!|  j"| j#||d+7  _"W q|   |  j"d7  _"| jj	$d,|d  d- Y q|X q|| jj	
d. d S )/Nr   r:   r   	isCheckedu7   Не выбрано ни одной очереди ... c                 S   s$   g | ]}|d  r|d r|d  qS )r   r]  r   )r   valr   r   r   r      s       z4CmfPluginTrackerApi._dump_queues.<locals>.<listcomp>Zchildrenr   Tr'  P   u<   Старт создания дампа очередей ... r%  r   u,   Создание дампа очереди "r   r&  r    ... r   rl   r   )rl   r   r   r   r,   u1   Создание дампа типов задачrB  u0   Создание дампа разрешенийZpermissionsu=   Создание дампа рабочих процессовr/  u(   Создание дампа версийZversionsu2   Создание дампа компонентов
componentsr   r?   ru7   Создание дампа задач очереди: rD  u<   Не удалось создать дамп очереди "r   u7   Конец создания дампа очередей)%r*   r   r+   r   r@   rA   r5  r   r   r   r   r4  r   r   r   rv   r$   Zget_queue_issues_countrB   
get_queuesrX   r   makedirsr\  r   r   r   r   r   rC   rD   rF   rE   r,   r   rS  r   )r2   rootZ
queues_dirrE  stepr   r   Z	data_filer,   rX  rW  r=  rH   r   r   r   _dump_queues  sr    


$


"z CmfPluginTrackerApi._dump_queuesc                 C   s  | j  }t|\}}}|| d }| j jd| d | j jd | j jd | | jjd | j jd | | jj	d | j jd	 | | jj
d
 | j jd | | jjd | j jd | | jjd | j jd | | jjd | j jd | | jjd | j jd | | jjd | j jd | | jjd | j jd | | jjd | j jd | | jjd | j jd | | jjd | j jd | | jjd d| j _| j   t  | j jd  |   d!S )"u^   
        Загружает все данные из API, кроме вложений
        r   u   Свободно места: r   u5   Скачивание данных через API ... u?   Создание дампа всех пользователейr   u/   Создание дампа всех ролейZrolesu/   Создание дампа всех группgroupsu:   Создание дампа всех типов задачissue_typesu;   Создание дампа всех приоритетовZ
prioritiesu5   Создание дампа всех статусовstatusesu<   Создание дампа всех типов ссылокZ	linktypesu3   Создание дампа всех экрановZscreensuF   Создание дампа всех рабочих процессовr/  u5   Создание дампа всех очередейr   u/   Создание дампа всех досокr   u5   Создание дампа всех спринтовr   uE   Создание дампа всех проектов(списков)r      u?   Создание дампа выбранных очередейN)r   r@   r   
disk_usager   r   r   r$   r   Z	get_rolesZ
get_groupsZget_issue_typesZget_prioritiesZget_statusesZget_linktypesZget_screensZget_workflowsrc  Z
get_boardsZget_sprintsZget_projectsr   r   r   rg  )r2   Zdownload_pathtotalusedfreeZfree_percentr   r   r   download_dataI  sH    

z!CmfPluginTrackerApi.download_datac              
   C   sZ  t ddD | }|dkr"qL| j r0qLtj|d }| jjd| d zt	|d d,}| j
jjj|d d	D ]}|| q~W 5 Q R X t|d  j}||d
 d kr| jjd| d| d|d
 d  d tjj|d d}d|_|  | jjd|d   W q tk
rH   | jjd|  Y qX qW 5 Q R X d S )NFr"  DONEr   u   Попытка скачать r`  r  r*  )r  r  sizeu   Возможно файл u.    не был скачан корректно: r2  u	    байтr   r   Tu   Сохранен в u,   Не удалось скачать файл )r
   rq   r   r4  r  r  r  r   r   rC   r$   r8  Z_connectionstreamr   r   statst_sizer  rZ   r  r  r   r   r   )r2   download_queuer   r   rH   chunk	file_sizeZdownload_filer   r   r   _download_file_worker  s.    
z)CmfPluginTrackerApi._download_file_workerc                 C   s  ddl m} ddlm} | jjd | }| jdg dd| jgddd	gg}t	j
j|d
}|st| jjd d S | jjd|  g }t| jD ]F}|| jd| d|id}|| |  | jjd| d qt	j
j|dddgdD ]2}	| j r
 q(||	j|	j|	j|	jd q|D ]}
|d q,| s\|D ]}|  qL| j r~d| j_| j  d S | jjd d S )Nr   rF  rH  u5   Старт скачивания вложений ... zplugin.plugin.source_hashr)   ==r  Fr   u   Вложений нетu   Файлов: Z_download_file_worker_rv  rK  u/   Запуск задачи скачивания r`  r   r  r  r   rP   )r   r   r  r  rq  r%  u   Конец скачивания)r   rG  rM  rI  r   r   r   r8   r)   rZ   r  countr3  rO  ry  r_   rP  Zslistr4  r7  r   r   r  r  rQ  rw   r   r   )r2   rG  rI  rv  _filterZcount_download_filesZprocsirR  r   rU  r   r   r   download_files  sP    



z"CmfPluginTrackerApi.download_files)
group_infoc                 C   s   | j jd|d   | j d|d  }tjjddd| dgdgd	}|sltjjd
d|d gdgd	}|stj|d |d|| j d}|jr|d |_||j	kr|j	 d| |_	|
  |S )Nu   Импорт группы rk   r   r   r   r   r   r   r{  r   rz  T)r   r   import_originalr  r   )r   r   r   r)   rZ   rh   rq   r  r   r   save_import)r2   r  Zgroup_ext_idgroupr   r   r   _process_group  s       

z"CmfPluginTrackerApi._process_groupu;   Обработка пользователей и группc              	   C   s  t  }| dD ]}| j r8d| j_| j   dS zN| jjd|d   d| j d|d  d}| 	|| j
tjj d }d	}tjjd
d|d gdgd}|s6tjjddd| dgdgd}|s6tjjdd|d gd}t|dkr(|  jd7  _| jjd|d  dt|  |r6|d }|sXd}tj||d | jdd}|jr||D ]}t||||  qd|jr|jr|  |ddg |jr||jkr|j | |_n||_tj }	tj }
|j|	 |j|
 d|_|dg D ]}| |}|j| q|jdd | j j d7  _ |j!r|j"s|j!#ds|j!#ds|r|$|j!j% W q   |  jd7  _| jj&d|d   Y qX q|rt'tjj(|gd  dS )!u7    Импорт пользователей и групп r   r%  Nu&   Импорт пользователя rk   r   r   rP   Floginrz  r   r   r{  r   r   r   r   r   r   u+   Пользователей с именем z > r   T)r   r  r   r  rg_member_ofrh  r   z.evateam.ruzrobot@yandex.ruu@   Не удалось загрузить пользователя )r   ))setr   r   r4  r   r   r   r   r)   r   r*   rZ   rd   r\   rq   ru   r   r   r   r  setattr
is_changedr  r8   r   rh   tracker_group
user_groupr  r_   Z
user_localr  r   r   r   r   addr:   r   Zcmf_deferred_taskZregister_persons)r2   Znew_user_emailsr   r   Z	user_dictZ
is_createdr   Zpersonsrl   r  r  r  r  r   r   r   _process_users  s~    

 " 




 z"CmfPluginTrackerApi._process_usersu#   Обработка статусовc                 C   s   |  dD ]}| j r0d| j_| j   dS | j d|d  }tjj|d}|s|dd|d gd	ddgg}tjj|d
}|stj|d | jd}|d |_	| 
|dd|_|d dkr| 
d|_||_|  | jj  | j jd7  _q
dS )uJ    Импорт и сопоставление статусов из Tracker rj  r%  Nr   r   r   r   rz  r   r   r   r   r   rC   u
   РевьюZreviewr   )r   r   r4  r   r   r)   rZ   CmfStatusCoderq   r   Zcalc_status_typestatus_typer   r  r   r   r   )r2   r   status_code_ext_idstatus_coder}  r   r   r   _process_statuses4  s(    


z%CmfPluginTrackerApi._process_statusesu2   Обработка логических типовc                 C   sB  ddddddddddd	dd
ddddddddddddddd	}|  dD ]}| j rd| j_| j   dS | jjd|d   | j d|d  }tj	j
ddd| dgd}|rqX|
|d }|r.tj	j
d d!|d  gdgd"}|jr|j d| |_n||_|jd#d$ qX| jjd%|d  d& tj	j
dd'|d  gdgd"}|r|jr|j d| |_n||_|jd#d$ qX| jjd(|d  d) d}tj	j
d d!|gd}tj	|d  | jd*}|d  |_|
d+d,|_||_d-|_||_|j|j d$ t  | j jd.7  _qXdS )/u9    Маппинг issuetypes в logic_type и импорт ZBugztask.bug:default)r   r   z
Task Agiletask.agile:defaultZFeatureztask.feature:defaultZImproveztask.improve:defaultEpicztask.epic:defaultZ	UserStoryztask.userstory:defaultu$   Запрос на измененияztask.sd_change_request:default   Инцидентztask.sd_incident:default*   Запрос на обслуживаниеztask.sd_service_request:default)	u   Ошибкаu   Задачаu!   Новая возможностьu   Улучшениеr  ZStoryzChange requestr  r  ri  r%  Nu#   Импорт типа задачи r   r   r   r   r   r   r   r   rz  r{  Tr   u   Поиск по имени "z" ... ILIKEu   Тип "u7   " не найден. Создание нового ... r  r   rm   r[   r   )r   r   r4  r   r   r   r   r)   rZ   CmfLogicTyperq   r   stripr   r   templatecmf_model_nameis_newr   r   )r2   Z	name2codeZ
issue_typeZissue_type_ext_idr   Zlogic_type_dictZtemplate_coder  r   r   r   _process_issue_typesQ  sd    

z(CmfPluginTrackerApi._process_issue_typesc                 C   s   | j  d|d  }tjj|d}|j d|d  }tjjdd|gd}|sttjjddd gdd|gd	d|ggd}|stjjddd gd
d|d gdd|ggd}|stj||| jd}|d |_||_|j	|_	d|_
||_|j|j d d S )Nr   r   r  r   rz  r   r0  =r  r   rk   )r0  r  r   Fr   )r)   rZ   r  rq   r   	CmfStatusr   r   r  r  Zallow_empty_transitionr   r  )r2   Zstatus_datar0  r  r  status_ext_idr   r   r   r   _create_status  s0    
z"CmfPluginTrackerApi._create_statusu4   Обработка рабочих процессовc              	   C   s:  |  dD ](}| j r2d| j_| j   dS | jjd|d   | j d|d  }tj	j
|d}|stj	j
d	d
}tj	||| jd}|d |_|  |d D ]}| |d | qtjjdd|gdddggdgd}|D ]<}tjj
dd|jgdd|gdddggdsq|jdd q|d D ]}| j rVd| j_| j    dS |j d|d d  }tjj
|d}	|
dg D ]}
|j d|
d d  }tjj
|d}|j d|d d  d|
d d  }tjj
||d}|stj||d}|
d |_|	g|_||_|  qq,| j jd7  _q
dS )u    Импорт workflow r/  r%  Nu/   Импорт рабочего процесса r   r   r   r  r  r   r   r  r   Zstepsr   r0  rz  r   r  r{  !=r   T)forceactionsrL  -)r   r0  r   )r   r   r4  r   r   r   r   r)   rZ   CmfWorkflowrq   r   r  r  r  ru   r  deleter   ZCmfTransstatus_from	status_tor   )r2   Zworkflow_infoworkflow_ext_idr0  Ztemplate_workflowrf  Zworkflow_statusesr   Zstatus_from_ext_idr  actionZstatus_to_ext_idr  Ztransition_ext_idZ
transitionr   r   r   _process_workflow  s\    


 

&
z%CmfPluginTrackerApi._process_workflowc                 C   s  t  }d }d }d }|d D ]}| j d|d d  }tjj|d}| j d|d d  }	|d d |d d krtjjdd	d
|	 d
gd}
|
}|s|}|s|}|||	< q| j d|d  }tjj|d}|stjjdd}tj||| jd}d|d  |_||_	||_
||_|  tjj|dD ]}|  q,| D ]p\}	}| j rpd| j_| j   qtjjdd	d
|	 d
gd}
|
|d|| jd}tjf |}|  qD|S )NZissueTypesConfigr   r0  r   r  Z	issueTypeZdefaultTyper   r   r   r   zsoftdev:defaultr  r  u!   Simple-схема проекта r   )	scheme_wfr%  r[   )r   Ztarget_workflowr  r  r   )rt   r)   rZ   r  rq   r  ZCmfSchemeWfr   r   default_task_logic_typeZdefault_task_workflowZdefault_subtask_workflowr  ZCmfSchemeWfRuleru   r  r   r4  r   r   )r2   r   Z	issue_mapr  Zdefault_task_wfZdefault_subtask_wfZtype_configr  r0  logic_type_ext_idr   Zscheme_ext_idschemer  ZruleZ	rule_dictr   r   r   #_create_schemewf_for_simple_project  sV    

z7CmfPluginTrackerApi._create_schemewf_for_simple_projectc              	   c   sH   | j  d|}t|dd}|D ]}t|V  q(W 5 Q R X d S )Nr   zversions.jsonr>   r   r2   
project_idZproject_dirrH   r   r   r   r   _get_project_versions+  s    z)CmfPluginTrackerApi._get_project_versionsu   Обработка версийc              	   C   s  t jj|d dgd}t jjd|d}t jjd|d}| j|d dD ]4}z| j rrd	| j_| j  W  d S | j	 d
|d  }t j
j|d}|st j
|d ||| jdd}|dd|_|jj|_|d r|n||_t jjdd|_|jr|d s|d r|d n
|d |jr6|jr6|  | j jd7  _W qF   |  jd7  _| jjd|d   Y qFX qFd S )Nr   z"scheme_wf.default_release_workflowr   rP   release)sys_typetree_parentarchiver   r  r%  
::version:r  r   Tr   r   r   r   r  r   rm   archivedzlist.release:defaultr  ZreleasedCLOSEDZOPENr   u)   Ошибка импорта версии )rZ   rg   rq   	CmfFolderr  r   r4  r   r   r)   CmfListr   r  Zdefault_release_workflowr0  r  r  r   Zset_default_statusr  r  r  r   r   r   r   )r2   project_dataproject_objZrelease_folderZarchive_folderversionversion_ext_idZversion_listr   r   r   _process_versions1  sD    




z%CmfPluginTrackerApi._process_versionsc              	   c   sH   | j  d|}t|dd}|D ]}t|V  q(W 5 Q R X d S )Nr   zcomponents.jsonr>   r   r  r   r   r   _get_project_components\  s    z+CmfPluginTrackerApi._get_project_componentsu)   Обработка компонентовc              	   C   sZ  t jj|d d}| j d|d  }t jj|d}|sPt j|d|d}|  | j|d dD ]}z| j rd| j_	| j  W  d S | j d	|d  }t j
j|d}|st j
|d
 ||| jdd}|dd|_||_t jjdd|_|jr|jr|j|j d | j jd7  _W q`   |  jd7  _| jjd|d
   Y q`X q`d S )Nr   r  z::components:r   u   Компонентыr  r   r   r  r%  ::component:r   Tr  r   rm   list.base:defaultr  r   r   u1   Ошибка импорта компонента )rZ   rg   rq   r)   r  r   r  r   r4  r   r  r   r  r  r   r  r  r  r   r   r   r   )r2   r  r  Zcomponents_folder_ext_idZcomponents_folder	componentcomponent_ext_idZcomponent_listr   r   r   _process_componentsb  s@    


z'CmfPluginTrackerApi._process_componentsu3   Обработка проектов(списков)c              	      s  t jj|d d}| j d|d  }t jj|d}|sPt j|d|d}|  |d D ]j | j rd| j_| j   d S t	t
 fd	d
| dd }|d kr| jjd d  d qXz| j d|d  }t jj|d}|st j|d ||| jdd}|dd|_|d|_|d|_||_t jjdd|_|jrb|jrb|j|j d | j|j }r~d|d< | j jd7  _W qX   |  jd7  _| jjd|d   Y qXX qXd S )Nr   r  z::projects:r   u   Проектыr  r   r%  c                    s   t | d t  d kS Nr   r   rU  project_listr   r   r    r  z<CmfPluginTrackerApi._process_project_lists.<locals>.<lambda>   Проект "r   u"   " не найден в дампе!::project_list:Tr  r   rm   	startDateendDater  r  r   r   r   u+   Ошибка импорта проекта )rZ   rg   rq   r)   r  r   r   r4  r   nextr   r   r   r   r  r   plan_start_dateplan_end_dater  r  r   r  r  r  r0   r   r   r   r   )r2   r  r  Zproject_lists_folder_ext_idZproject_lists_folderproject_list_ext_idproject_list_objproject_list_datar   r  r   _process_project_lists  sP    


z*CmfPluginTrackerApi._process_project_listsc              
   C   s   ddl m} | dddd} || ddd	}zZd
ddd|  dgdd| gddd| dgg}tjj|d}|stj| d}|  |W S  tk
r } zt	d|  d|  W 5 d }~X Y nX d S )Nr   )translitr   rU  #rm   ruT)Zlanguage_codereversedORaliasr  r   "%r   r   r    u+   Не удалось создать тег "z": )
Ztransliterater  r6  rZ   ZCmfTagrq   r  r   Zloggingr  )r  r  r  r}  tag_objr   r   r   r   _create_tag  s     zCmfPluginTrackerApi._create_tagu   Обработка теговc                 C   sl   t  }| |d D ]>}| j r:d| j_| j   d S |dr||d  q|D ]}| | qXd S )Nr   r%  tags)	r  r   r   r4  r   r   rq   unionr  )r2   r  r  ra   r  r   r   r   _process_tags  s    


z!CmfPluginTrackerApi._process_tagsu8   Обработка наблюдателей задачиc                 C   sh   |d D ]T}|  |d }|s0td|d  ||jks||jks||jkrPq|j| qt  dS )u;   Добавляем наблюдателей в задачу	followersr   uI   _process_watchers: Не найден наблюдатель задачи rk   N)r   CmfErrorr   r   	cmf_ownerZ
spectatorsr_   r   )r2   	issue_objra   Zwatcherr   r   r   r   _process_watchers  s    z%CmfPluginTrackerApi._process_watchers)ra   c              	   c   sB   t | d d}t|d}|D ]}t|V  q"W 5 Q R X d S )Nr1  r,  r>   )r   rA   rC   rD   r   )ra   Zcomments_file_pathrH   r   r   r   r   _get_issue_comments  s    z'CmfPluginTrackerApi._get_issue_commentsc              
   C   s   |  |D ]}| j d|d  }tjj|d}|r<|js<q
|sPtj|d|d}| |d d |_|j|_| |d d |_	|d	 |_
|d
 |_| |d|dd|_| |jj|||_||_|  q
d S )Nr   ZlongIdr  Tr   r  r   r   r   r   r   r   r-  r   rm   )r  r)   rZ   rf   rq   r  r   r   r  r   r   r   _process_mentionsr   _process_linksr:   r  r  )r2   r   ra   Zcomment_datar   rA  r   r   r   _process_issue_comments  s     


z+CmfPluginTrackerApi._process_issue_commentsc                 c   s8   t | d d}t|D ]}|||dV  qd S )Nr1  r)  )r  rG   )r   rA   r   r   )ra   Zattachments_pathr  r   r   r   _get_issue_attachments	  s    z*CmfPluginTrackerApi._get_issue_attachmentsu#   Обработка вложенийc           
      C   s   ddl m} g }| |D ]}tjj|d |d}|sLtj| j||d d}|jrZ|  |	  t
|d |j |j}|rtjjj }||j}	|	  || t  qd S )Nr   )RDiskr  )r   r   )r   r   r   rG   )Zrdisk.rdiskr  r  rZ   CmfAttachmentrq   r   r  r  Z
upload_dirr   copyZfull_path_filer  ZCmfRFiler   Zdata_driverZget_rdZ	get_rfileZ
_file_nameZmake_previewr_   r   )
r2   r  
issue_datar  r)  Zattachment_infor  r  ZrdiskZrfiler   r   r   _process_attachments  s(    
z(CmfPluginTrackerApi._process_attachmentsuB   Обработка упоминаний пользователейr   r=   c           	      C   s  ddl m} |sd S t|d}|jtddD ]}z~||jd }|jd}t	j
jdd	d
| d
gd}|s~td| |j|jd< d|jd< |jj|jd< |jj|jd< W q0 tk
r } z,|  jd7  _| jjd| d|  W 5 d }~X Y q0X q0t|S )Nr   )urlparsehtml.parserzstaff.yandex.ru)r   r   r  r  r  r   r   u+   Не найден пользователь Tcmf_convertedzdata-linked-resource-idzdata-usernamer   uZ   Не удалось преобразовать ссылку на пользователя r  )Zurllib.parser  r	   r  recompiler  r  r  rZ   rd   rq   r   r   r   r:   r  r   r   r   r   rv   )	r2   r   r  soupr  Zuser_urlZ	user_namer   r   r   r   r   r  +  s&    

.z%CmfPluginTrackerApi._process_mentionsc              	   C   s   d}| dr|d ds0|jdks0|dr|jr|t|ddjf |j|jdd |j|j|j	d	d
}|
|j n@t|ddjf |j|jdd dd|j	d	d
}|
|j |S )uS   
        Из документов MS создаем наши превью
        au  
        <div contenteditable="false" class="app-tinymce-card-preview app-tinymce-is-preview">
              <a class="app-tinymce-href-preview app-tinymce-is-preview" title="{fileName}"
                rel="{urlPreview}"
                download="{url}" cmf_converted=True>
                <span class="app-tinymce-img-preview-block app-tinymce-is-preview">
                <span class="app-tinymce-img-preview-size app-tinymce-is-preview">
                  <img class="app-tinymce-img-preview app-tinymce-is-preview"
                  src="{urlPreviewImg}" alt="attachment" cmf_converted=True>
                </span>
                </span>
                <span class="app-tinymce-file-preview-block app-tinymce-is-preview">
                      <span class="app-tinymce-file-name-block app-tinymce-is-preview">
                        <span class="app-tinymce-file-name-view app-tinymce-is-preview">{fileName}</span>
                        <span class="app-tinymce-file-name-view app-tinymce-is-preview">{fileName2}</span>
                      </span>
                      <span class="app-tinymce-file-create-view app-tinymce-is-preview display-contents"></span>
                      <svg class="remove-file-icon" style="width:24px;height:24px" viewBox="0 0 24 24">
                          <path style="pointer-events: none;" fill="#e8e8e8" d="M19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5A2,2 0 0,0 19,3M19,19H5V5H19V19M17,8.4L13.4,12L17,15.6L15.6,17L12,13.4L8.4,17L7,15.6L10.6,12L7,8.4L8.4,7L12,10.6L15.6,7L17,8.4Z" />
                      </svg>
                </span>
              </a>
            </div>
            classzyfm-fileZimgr   rm   Ni)ZfileNameZ	fileName2ZurlPreviewImgZ
urlPreviewr  r  z/static/file-outline.png)r  r|  r   findurl_previewr	   r6  formaturl_preview_imgr  replace_withZ
currentTag)r2   r  ZattachZTAG_TMPLr   r   r   r   _create_previewE  s,    ,z#CmfPluginTrackerApi._create_previewu#   Конвертация ссылок)r   c                    s  |s|S t |}|dd D ]}|jdrF| jjd|  q|drv|jd drv| jjd|  q| jjd|  |dr|jd }n
|jd	 }t	j
|d
d dd  t fdd|dg D d }|d krqtj|d }tjj||dddgd}	|	r|d	r|jd	 |jd< |	j|jd	< d|jd< t|	j}
|
r|
d r|
d drd|_d|jd< d|jd< d|jd< n,|
r|
d r|
d ds| ||	 |dr|jd |jd< |	j|jd< d|jd< t|	j\}
}|
rx|
drxd|_d|jd< d|jd< d|jd< |d}|jd |jd	< |
|jd < || n| ||	 t	j
|	j}| jjd!|  qt|S )"Nc                 S   s   |  dp|  dS r   r  r  r   r   r   r  z  r  z4CmfPluginTrackerApi._process_links.<locals>.<lambda>r  u   Уже обработали r   r  u   Это якорь u&   Обрабатываем ссылку r   r  r{   r	  r   c                 3   s   | ]}|d   kr|V  qdS )r   Nr   rT  Zfile_idr   r   	<genexpr>  s      z5CmfPluginTrackerApi._process_links.<locals>.<genexpr>r)  rk   r  r  r  )r   r   rP   Zsrc_origTZvideoZcontrolsz100%widthZheightZimageZ	href_origsourcer   u   Заменили на )r	   r  r  rq   r   r   r   r  r   r  r  r  r  r  rZ   r  r  r  sgetr  	mimetypesZ
guess_typer   r	  new_tagr_   rv   )r2   r   r   r  Z	text_soupr  r  Zattachment_datar  Z
attach_objZ	mime_typeencoder  r   r   r
  r   r  t  sj    

  

 

 





z"CmfPluginTrackerApi._process_linksc                 C   s,   dd }||}||}|  d| d| S )Nc                 S   sN   | d krdS t | tkr"| dS t | tkrBddd | D S t| S d S )Nu   Не указаноrk   z, c              	   S   s2   g | ]*}t |tk	r*t|d |dn|qS )rk   r   )r   rv   rq   rT  r   r   r   r     s     zLCmfPluginTrackerApi._simple_html_diff.<locals>.get_value.<locals>.<listcomp>)r   rt   rq   ru   rw   rv   )r[  r   r   r   	get_value  s    
z8CmfPluginTrackerApi._simple_html_diff.<locals>.get_valuer  u    ➔ r   )rT   Z_fromZ_tor  Z
from_valueZto_valuer   r   r   _simple_html_diff  s    
z%CmfPluginTrackerApi._simple_html_diffc           
      C   s  |d D ]}| j  d|d  }tjj|d}|r:|js:qd }|d }r|D ]`}|d d dkrfqP|d sx|d	 sxqP| |d d
 |d |d	 }	|d kr|	n| d|	 }qP|stj|d|d}||_| |d d |_|j|_	|d |_
d|_|  qd S )Nr.  z	::change:r   r  rP   fieldr   fromtork   z<br>Tr  r   r   r|   )r)   rZ   rf   rq   r  r  r   r   r   r  r   	log_levelr  )
r2   r   ra   Zchanger   rA  Zcomment_textrP   r  Zdiffr   r   r   _process_issue_changelog  s,    

z,CmfPluginTrackerApi._process_issue_changelogu   Обработка задачиc           )   	   C   sP  | j  d|d d  }tjj|d}|sBtd|d d  d| j  d|d  }| || jtjj d }| j  d|d	  d|d
 d  }tj	jddd| dgdgd}| j  d|d d  }tj
jddd|gddd| dggd}	|drX| |dd}
|
|d< |
|d< |
sX|  jd7  _| jjd|dd  |dr~| |dd|d< |dr| |dd|d< ||d
< |j|d< |	|d< | j|d< d |d!< ||d"< |d#|d$d%|d&< ||d< |d'g }|D ]}| j  d|d  }|d(d)krpt|d d|d*< t| j  d|d+ d  d|d,< || j|< nN|d(d-krt|d d|d,< t| j  d|d+ d  d|d*< || j|< q|d. }r| j  d|d  }| j|g }|| j  d|d   || j|< |d" }rn| j  d|d  }| j|g }|| j  d|d   || j|< | jjd/|  tjj|d&dddgd0}|stj|d1 | jd |d2}t|d3r|js|jr| D ]\}}t||| q|jr|  |d d4 d.kr |d5 |_||_|  || | !|j"j#|_"| $|j"j#|||_"| %|| | &|| |d6g D ]b}| j  d7|d  }tj'j|d}|s| jjd8|d   |  jd7  _n|j(| qz|d9g D ]b}| j  d:|d  }tj'j|d}|s>| jjd;|d   |  jd7  _n|j(| q|d< }r| j  d=|d  }| j)|td>g d?}|d@ | || j)|< |dA }r |D ]J} | j  dB| d  }!| j*|!td>d>g dC}"|"d@ | |"| j*|!< q|dDr| +|| |jr(|  t,  |dEg }#|#rzP|-dEg |#D ]}$| .|$}%|j/|% qR|jr|j0d dF |j12  W n   | jj3dG Y nX | j  d|d  }&tj4j|&d}'|'stj4|&| jdH}'||'_5|dI  }(dJ|( dK|( dL|'_"dM|'_6|'  |'j12  |  j7d7  _7| jjdN| j7 dO| j8  dPS )Qu   
        Общая логика обработки которая потом разделяется на задачи и эпики
        r   r   r   r  u   Нет проекта "rk   r   rP   r0  r   r   r   r   r  r{  r   r  r  r   r   r   r  r   u*   Не найден автор задачи r   r   r   r   cache_status_typer   activityTZapprovedr   r+  r   rm   r   Zlinks	directioninwardro   objectrn   outwardZepicu0   Попытка создать задачу из r  r   r   r   r  r   r  rl   r   ZfixVersionsr  u!   Не найдена версия ra  r  u%   Не найден компонент r   r  F)r   r@  r@  sprint	::sprint:)r   r  r@  r  r  r   u/   Не удалось привязать тегиr   r   r2   u?   Задача импортирована из Tracker: <a href="" target="_blank"></a>r|   u&   Импортировано задач r2  N)9r)   rZ   rg   rq   r  r   r*   r[   r\   r  r  r   r   r   r   r   r  Zdefault_activityrt   r-   r.   r_   r   hasattrr  r  r   r  r  r  r   r  r  r  r   r:   r  r  r  r  listsr0   r/   r  r   r8   r  r  r   r   r   Zexcepionrf   r   r  r,   count_project_issues))r2   ra   project_ext_idr   r  Znormalized_issuer  r   r  r   r   Zissue_linksZ
issue_linkZlink_ext_idZ
issue_epicZepic_ext_idZ	sub_tasksZissue_parentparent_ext_idr  rS   r:   r  r  Zversion_objr  r  Zcomponent_objr  r  r  r   r   sprint_ext_idsprint_datar  r  r  comment_ext_idrA  r   r   r   r   _process_issue  s    "  

""







z"CmfPluginTrackerApi._process_issuec              	   C   sD   t dd0 | j rq6| }|dkr*q6| | qW 5 Q R X d S )NFr"  rq  )r
   r   r4  rq   r-  )r2   issue_queuera   r   r   r   _process_issue_fork  s    
z'CmfPluginTrackerApi._process_issue_forkc              
   c   sb   | j  dt|d}t|D ]:}|dr2q"t||dd}t	|V  W 5 Q R X q"d S )Nr   rJ  r   r   r>   )
r   r@   rA   rv   r   r   r   rC   rD   rE   )r2   r  r<  Ztask_idrH   r   r   r   r     s    
z&CmfPluginTrackerApi._get_project_tasksu   Обработка досокc           
         s  t jj|d d}|d D ] | j rBd| j_| j   d S tt fdd| 	dd }|d kr| jj
d d  d	 q| j d
|d  |d< t jj|d ddddgd}|st j|d | jd}|d |_||_||_||_|  |jr|jD ]}|  q|d D ]v}t j|d || jdd}|  |d D ]>}| j d
|d  }t jj|d}	|	svt|j|	 qF|  q| j jd7  _t  qd S )Nr   r  r   r%  c                    s   t | d t  d kS r  r   r  r   r   r   r    r  z5CmfPluginTrackerApi._process_boards.<locals>.<lambda>u   Доска "r   u$   " не найдена в дампе!r   r   kanban_board_columnsr  r   r  r  r"  r   T)r   r   r   r  rj  r   )rZ   rg   rq   r   r4  r   r   r  r   r   r   r   r)   ZCmfKanbanBoardr   r   r  r  r  r  r1  r  ZCmfKanbanBoardColumnr  AssertionErrorZmapped_status_codesr_   r   r   )
r2   r  r   r   Z	board_objr   Zboard_columnr   r  Zstatus_globalr   r0  r   _process_boards  sR    





z#CmfPluginTrackerApi._process_boardsr   kanbanc           	      C   s   dd|j gg}|dr*|dddg n|dd|g tjj|d}| j d|d  }tjj|d	gd
}|stj|| jdd}|d |_|d|_	|d|_
||_||_||_tjjdd|_|jr|jr|jr|d |_|  |S )NZtree_parent_idrz  r  r  r  r   r!  r   r   r  T)r   r   r  r   r  r  zlist.agile_sprint:defaultr  )r   rq   r_   rZ   r  r)   r  r   r   r  r  r  r   	list_typer  r   r  r  r  r  )	r2   r   r   Zparent_sys_typer5  r}  r  r*  Zsprint_listr   r   r   _process_list  s.    



z!CmfPluginTrackerApi._process_listu#   Обработка спринтовc                    s   t jj|d d}|d D ] tt fdd| d}|D ]r}| j rfd| j_| j	    d S | 
||}| j|j }rd|d	< |d
|d
< t  | j jd7  _q>qd S )Nr   r  r   c                    s   | d d  d kS )Nr   r   r   r  r0  r   r   r     r  z6CmfPluginTrackerApi._process_sprints.<locals>.<lambda>r   r%  Tr   r  r   )rZ   rg   rq   ru   r   r   r   r4  r   r   r6  r/   r   r   r   )r2   r  r   r   r   
sprint_objr+  r   r0  r   _process_sprints  s    

z$CmfPluginTrackerApi._process_sprints)project_structr  c                 C   s  ddl m} ddlm} d}tjjdd|d gddgd	}|r|jj|d ksb|j	r|j	|d kr|d  d
|d  d|d< | j
jd|j d|d  d n|j	s|d |_	|  tjj|d | d}|sd}tj|d | j
d|d d}tdd|jj|_|D ]}t||||  q|  |r`tjj||j dd}|  |j  |   | | |   | | |   | j|d | j
jd g }	| }
t| j D ]F}|| j!d| d|
id}|	"| |#  | j
jd|  q| $|d D ]"}| j
% r& q4|
&| q|	D ]}|
&d q8| j
jd |	D ]}|'  q\| j
jd tj|d d!}|(  d|_)|jdd" | j
% rd#| j
_*| j
  d S t+  | ,| |   | -| |   | .| | j
 j/d$7  _/|   |S )%Nr   rF  rH  Fr   rz  r   r   r{  z ()r  uo   " уже существует! Импортируемый проект будет переименован в "r   r  Tr  z[^A-Za-z0-9-]rm   z-1)r   r   )r  u<   Импорт задач в несколько потоковr/  r.  rK  u.   Параллельный обработчик r   rq  u3   Ожидание обработки задач ... u(   Конец обработки задачdelmer   r   r   r%  r   )0r   rG  rM  rI  rZ   rg   rq   r   r   r   r   r   r  r   r   keysr   subr   r:   r  r[   task_code_prefixr  r   r   r   r  r  r  r   r3  rO  r/  r_   rP  r   r4  r7  rw   r  cmf_deletedr   r   r  r3  r8  r   )r2   r9  r  rG  rI  Zproject_is_newr  rl   Z	epic_taskZissue_processr.  r~  rR  ra   r   r   r   r   _process_project  s    $









z$CmfPluginTrackerApi._process_projectu#   Обработка проектовc                 C   s  t jjddjj}|  D ]}d }t|d |d< z| j rd| j_	| j
  |rt j|dd}|  d|_|j
dd t  W  d S | j d	|d  }t jjd
d}| |}|di }|r| |d }	n
ddd}	||d< d|d |d|dd|jj|||d |	|t|d
}
d| _|d | _| |
|}W q tk
r   |rt j|dd}|  d|_|j
dd t  |  jd7  _| jjd|d   Y qX qd S )NZsoftdevr  r   r%  r;  r<  Tr   r   zproject.agile:defaultZleadz"default_import_tracker@evateam.comZdefault_import_tracker)r   r   r   r   r   r+  r   rm   rl   )
Zproject_typer   r   r   r  r  r?  r  r   r  r   r,   r   u<   Не удалось импортировать проект )rZ   ZCmfActivityrq   r   r:   r   rv   r   r4  r   r   r[   r  r@  r   r)   r  r  r   rD   r   r,   r'  rA  r   r   r   r   )r2   r  r  r   r   r(  r   r  Zproject_leadr  r9  r   r   r   _process_projects}  s`    



z%CmfPluginTrackerApi._process_projectsuN   Обработка связей задач и проектов(списков)c              	   C   s   | j  D ]\}}| j r4d| j_| j   dS |d s>q
tjj|d}|j	
  | jjd|j dt|d   |d D ]V}tjj|dd	d
gd}|r|j	| q|  jd7  _| jjd| d|j  q|  t  q
dS )ul   
        Постобработка добавления задач в проекты(списки)
        r%  Nr   r  u@   Добавляем задачи в проекты(списки) r  r@  r&  r   r  r  r   -   Неизвестная задача issue_id=u!    в проекте(списке) )r0   r   r   r4  r   r   rZ   r  rq   membersrE   r   r   r   r   r[   r_   r   r   r  r   )r2   r  r  r  issue_idr   r   r   r   _process_project_list_tasks  s,    


z/CmfPluginTrackerApi._process_project_list_tasksu>   Обработка связей задач и спринтовc              	   C   s  | j  D ]\}}| j r6d| j_| j   dS |d s@q
tjj|d}|j	
  | jjd|j dt|d   |d D ]}tjj|dd	d
gd}|rb|drT| j d|j }tjj|dddgd}|stj|| jd}d|_d|j d|j d|_||_|jr*|j|j d |jdkr`t|jdkr`|j	| n|j	| q|  jd7  _| jjd| d|j  q|  t  q
dS )u^   
        Постобработка добавления задач в спринты
        r%  Nr   r  u0   Добавляем задачи в спринт r  r@  r&  r   r  r  r  z::comment-sprint:r  r   r   r"  r|   uB   Задача была в архивном спринте <a href="r#  r$  r   r  r   rC  u    в спринте ) r/   r   r   r4  r   r   rZ   r  rq   rD  rE   r   r   r   r   r[   r)   r   rf   r  r   r   r   r  r  r  r&  r_   r   r   r  r   )r2   r*  r+  r7  rE  r   r,  rA  r   r   r   _process_sprint_tasks  s@    


$z)CmfPluginTrackerApi._process_sprint_tasksc              	      s  t t d fdd}dddgddd	gg}d
D ]R}tt| }|j|d} jjd|j d|  d}d}|dkr,|j|ddddg|| || | gd}|d7 }||8 }|D ]}	zt	|	dr||	j
j|	_|	jr|	  |	  n"||	j
j|	_
|	jr
|	jd	d |	jD ]8}
|
jdkr$q||
j
j|
_
|
jr|
jd	d qW q    jjd|	    jd7  _Y qX qqnq,dS )uS   
        Замена ссылок на задачи и документы
        r  c           
         s   | s| S t | d}|dD ]}|jdr0qd }|jdd jjr*td|jd  }rt	j
jddd	|d
 dgdgd}|D ] }|jd |d
kr|} qq|s҈ jjd|d
 d qnRtd|jd  }rt	jj|d
d}|s& jjd|d
 d qnqn jd k	r|jdd jrd|jd krtd|jd }|s jjd|jd   q j d|d
dd   }t	jj|dgd}|s jjd| d qnd|jd krtd|jd }|s$ jjd|jd   qt	j
jddd	|d
dd   dgdgd}|D ].}|jd |d
dd  krV|} qqV|s jjd|d
dd   d qnq|d k	r|d}	|j|	jd< |	|jj  d|	d< ||	 qt|S )Nr  ar  r   rm   z
[A-Z]+-\d+r  r  z%"key":"r   r  r{  rl   u;   Не удалось найти задачу по коду "r   z[A-Z]+$)r?  u;   Не удалось найти проект по коду "z/wiki/z\/\d+u8   Не удалось найти ID документа в r   r   r  u9   Не удалось найти документ по ID "z/browse/z	\/\w+-\d+u2   Не удалось найти ID задачи в T)r	   r  r  rq   r   r$   r  r   searchrZ   r[   ru   r  r  r   r   r  rg   r1   r)   r  r  r   r_   r   r:   r  rv   )
r   r  r  r   r   objsr   r   Zext_coder  r<   r   r   check_links	  sz    
$
$
z=CmfPluginTrackerApi._process_cross_links.<locals>.check_linksr   r  Nr  rz  T)r  r[   rg   r  r   u)   Конвертируем ссылки в u=    на локальные задачи и документы: i  r   r   zcomments.log_levelzcomments.text
text_draft)r   rP   slicer   r   r|   uZ   Не удалось конвертировать перекрестные ссылки в )rv   varsrZ   r|  r   r   r   r\   ru   r%  r   r:   rL  r  r   Z
do_approveZcommentsr  r   r   )r2   rK  r}  Z	mode_namery   rE  rf  r~  rJ  r   rA  r   r<   r   _process_cross_links		  sF    B



z(CmfPluginTrackerApi._process_cross_linksu3   Обработка связей всех задачc                 C   s  | j jdt| j  | jD ]~}| j  rFd| j _| j    dS tj	j
|d}| j| D ]>}tj	j
|dgd}|s| j jd|  q^||_|  q^q | j j  dd	d
d}| j jdt| j   | j D ]\}}| j  rd| j _| j    dS z~| j d|d d  }|
|d d }	|	rRtjj
|	d}
ntjj
|d}
|
stjj
dd|d d gd}
|
stj|| j |d d d}
|d d |
_|d d |
_|
  tj	j
|d d d}tj	j
|d d d}|rR|rR| j d|d  }tjj
|d}|s6tj|| j d}||_||_|
|_|  n:|rf|d d }n|rx|d d }| j jd|  W q   |  jd7  _| j jd|d  d|d  d|d   Y qX q| j j  dS )uD   
        Постобработка связей задач
        u   Подзадачи: r%  Nr  parent_taskr  uq   Не удалось связать задачи, возможно задача не попала в импорт zsystem.finish:finishzsystem.duplicatezsystem.link)Zdepends
duplicatesZrelatesu   Связи: r   r   r   r  r   rz  r   )r   r   r   r  r  rn   r   ro   r"  r   u.   Не удалось создать связь z out=z in=)r   r   r   r   r.   r4  r   r   rZ   r[   rq   r  rP  r  r   r   r-   r=  r   r)   ZCmfRelationTypeZin_type_nameZout_type_nameZCmfRelationOptionZin_linkZout_linkrelation_typer   r   )r2   r)  rP  Zchild_ext_idZ
child_taskZ	map_namesZrelation_ext_idZissue_relationr   Zrelation_coderR  Zin_link_taskZout_link_taskZ
rel_ext_idZrelation_optionZ	link_taskr   r   r   _process_relationss	  s    






 z&CmfPluginTrackerApi._process_relationsc                 C   sx  d| _ || _d| j_d| j_d| j_| j  | jjjj| _| | jj	d | _
| jjj| _t  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   d| j_| j  t  |  D ]>}|d dd | jD kr$q| jjd|d	  d
 q| jjd| j   | jjd| jj  | j  S )Nr   u&   Импорт данных из TrackerrI   r   r   c                 S   s   g | ]}|d  qS r   r   r   r   r   r   r   	  s     z6CmfPluginTrackerApi.process_import.<locals>.<listcomp>u'   Импортирован проект 'r   'u#   Ошибок обнаружено: u-   Импортировано объектов: )r   r   r   r   r   r   r5   r)   rU   rV   r*   Zext_urlr:   r1   r   rp  r  r   r  r  r  r  rB  rO  rS  rF  rG  r   r+   r   r   )r2   r   r   r   r   r   process_import	  sH    

z"CmfPluginTrackerApi.process_import)T)r   r4  )X__name__
__module____qualname__r   r#   Zui_meta_skipr   __annotations__r   rv   rt   r(   propertyr$   r%   r   rc   staticmethodrj   r]   r   rz   r   rU   r^   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r!  rC  rS  r\  rg  rp  ry  r  r  r"   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r	  r  r  r  r-  r/  r   r3  r6  r8  rA  rB  rF  rG  rO  rS  rU  __classcell__r   r   r3   r   r#   !   s   


%




&	MR4f5N:3
K

F 
:8
*
&
0



/B

 ,	
5

l
>

,j
Qr#   )rN  r  r   r  pathlibr   typingr   r   r   r   r   r   Zbs4r	   Zcmf.appr
   Zcmf.includeZmodules.tracker.fieldsr   Zmodules.tracker.tracker_apir   r"   r#   r   r   r   r   <module>   s    