U
    `e                    @   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	 ZG d
d dejZdS )    N)Path)DictOptionalListCallableUnionType)BeautifulSoup)cmf_context)*)cmf_plugin_tracker_apic                    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                    sH   t  j|| d | _d | _g | _d| _i | _i | _i | _i | _	d | _
d S )Nr   )super__init__source_hashsettingsselected_queuescount_issuesissue_relationssubtaskssprint_issuesproject_list_issuesr%   )selfr   r   	__class__r   r   r'   &   s    zCmfPluginTrackerApi.__init__c                 C   s@   ddl m} | ddddg || jj | jjj| jjjdS )u8    Клиент для работы с API Yandex Tracker r   
TrackerApipluginzplugin.ext_tokenzplugin.ext_token_addonzplugin.cloudtokenZorg_idcloud)	modules.tracker.tracker_apir4   load_fieldsr5   	ext_tokendecryptext_token_addonvaluer8   )r0   r4   r   r   r   r#   3   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)r0   	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   rN   captionrO   )r   _normalize_settingsjson_settingsr#   
get_issuesas_dict	enumeratemodelsCmfTaskverbose_name
_get_value_normalize_valueappend)r0   r   r)   resultissueZnumsettingr>   r   r   r   previewO   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   Поля контактов)rV   rR   rM   u   Поля организацийu   Поля задачu   Поля заметокu   Поля проектовu"   Поля списков задачu   Поля групп)
r\   	CmfPersonimport_shop_fieldsrM   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listra   strjoin)r   rT   to_strr>   Z
str_fieldsZ	str_fieldrb   Zrelated_objr   r   r   r_   t   s4    





zCmfPluginTrackerApi._get_value)rU   r?   c                 C   s&   |sd S | j |gd}|r"|d S d S )N)Zfields_namer   )rg   )modelrU   rk   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   Блокер)rs   )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   rW      s    z'CmfPluginTrackerApi._normalize_settingsc                 C   s   |dkr|  |S |S )Nr   )r   )r0   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    Преобразование настроек для модели rS   rT   F)rz   rU   )r_   r`   )r0   r   r)   Znormalized_objrd   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(   Не работает/Уволенный)rm   emailZactivecreatedauthorZbodyrn   	dismissedr   ro   )r$   rs   )r0   rT   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   descriptionrn   r   queuer   ZstoryPointssummarytype	updatedAt	updatedByro   NrS   rT   )r$   itemsrs   ra   )r0   Zissue_settingsZdefault_local_attrs_mappingZadditional_attrZcustom_field_keyZcustom_fieldrT   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   rm   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_funcr{   r?   c                    sj   | }|D ]H} | |d |d< ||d |d< |d |d< |j|d< q
 |j|d d S )NrT   r>   rS   rL   rM   )r   rR   )r_   r|   r   rM   ra   r^   )r   r   r{   Zobj_settingsrd   rb   r0   r   r   _get_settings  s    z@CmfPluginTrackerApi.tmplt_import_settings.<locals>._get_settingsplugin.plugin.*queuesidusersc                 S   s   g | ]}|  qS r   rZ   r   r   r   r   r   
<listcomp>  s     z=CmfPluginTrackerApi.tmplt_import_settings.<locals>.<listcomp>r   rQ   r   c                 S   s   g | ]}|  qS r   r   r   r   r   r   r     s     selectedObjects)r   r>   )r   r   r\   r]   rf   r   r   r   r   r:   rB   rC   rD   _get_projects_get_project_tasks_simple_getr#   rY   	get_usersr   r   ra   )r0   r   Z	TypeModelr   Zdump_dirprojecttaskuserr   r   r   tmplt_import_settings   s&    &	z)CmfPluginTrackerApi.tmplt_import_settingsc                 C   sd   |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\   rf   rs   r   r   errorr   )r0   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   rB   rC   rD   oslistdirendswithrE   rF   rG   )r0   	queue_dirZqueue_idrJ   r   r   r   r   3  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   
startswithrZ   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   B  s     r   r   r   rR   c                 S   s   g | ]}|qS r   r   r   r   r   r   r   G  s     )
r#   Zget_collectionr   gdebugr\   	CmfImportrs   r   r   )r0   Zcollection_namecmf_import_iddataer   r   r   get_from_online_or_dump<  s    
z+CmfPluginTrackerApi.get_from_online_or_dump)r   c                O   s   |  d|S )u   
        В Yandex Tracker 'Очереди', это 'Проекты' в EVA.
        Метод получения всех проектов в Tracker для настройки выбора импортируемых очередей.
        r   )r   )r0   r   r   r   r   r   r   get_all_queuesM  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   rm   r   projectsr   r   c                    s    g | ]}t |d   kr|qS r   rx   r   r   Zselected_queues_idsr   r   r     s      z8CmfPluginTrackerApi.get_all_projects.<locals>.<listcomp>r   TFis_show)rs   popra   rx   r   len)r0   r   r   r   r*   r   r   rb   r   r   
new_queuesr   r   r   get_all_projectsT  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   rm   rn   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)rs   r   ra   r   rv   r   )r0   r   r   r   r*   r   r   rb   
board_databoardr   r   r   r   r   r   get_all_boards  s6    0z"CmfPluginTrackerApi.get_all_boardsc                 C   sL   t jj| jjdddgd}|jrHt|j|j d |_|j	dd t
  d S )Nimported_object_countjson_object_countprogressr   d   TZ	only_data)r\   r   rs   r   r   r   intr   r   savecommit_with_event)r0   r   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   rB   rC   rE   rF   loads)r0   r   rI   rJ   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   
Tr   )r   rB   rC   rD   r   removerE   rZ   r   r   r   Zget_allr   writerF   dumpsshutilmover   r   )r0   Zapi_funcr   rI   Zfile_path_tmprJ   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_attachmentr\   CmfDocument_get_filenamer   rC   CmfImportDownloadrs   contentrZ   pathr  
downloadedr   r   r   r   Zrollback)r0   r   r  
issue_dictissue_ext_idr  rn   r  Zattachment_id
attachment	file_namerI   download_jobr   r   r   r   _dump_links  sZ    



 


zCmfPluginTrackerApi._dump_linksc                 C   s4  t dd |}d}	| jjd| d| d| d |j|d |d	}
t||D ]}|j|
|d
}
|
D ]}| }| j d|d  }znz:| j rW 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r8| jjdt|d  ||D ]}|d }tj|}||}|d drt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 qb|  |dd|| |d}| rlt!"| | 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r||d&<  qq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|/|	 qT|j01  W 5 Q R X d S ).NFZinit_views_and_dsr   u   Страницы задач с u    до u    по u    на страницеrn   )per_page)pager   r   r   u   Задача "" ID r   Texist_okattachmentsu%   Обработка вложений: r   r  r  r  )r   r  r  r(   u   Не ссылка zwb+descriptionHtmlro   comments.jsonu'   Дампинг комментариевr   r   textHtml	changelog	workflowsr   workflow
issue_pathr   rA   u   Скачано задач     из r+   u0   Не удалось скачать задачу )2r
   r   r   r   Zget_issues_for_queuerangeZget_issues_for_queue_by_pagerZ   r(   r   r   	is_cancelrC   rx   rD   mkdirrs   r   Zget_issue_attachmentsr\   r  r  r   r  r  r   r  r  r   r  rE   r   r%  r   r   Zget_issue_commentsrF   r   r   Zget_issue_changelogr   r   r   replacerH   r+   r   putclientclose)r0   
start_pageend_pager'  	tasks_dir
queue_datar#   tasks_that_are_doner:  errorsissuesr(  rc   r   r!  Ztask_dirZtask_dir_tmpr  r"  r#  Zattach_file_pathr$  rJ   Zcomments_filecommentr1  r2  
issuetypesZ	issuetypeZ	info_pathr   r   r   _dump_task_partN  s    "

"






$
"z#CmfPluginTrackerApi._dump_task_partr?  cntc                 C   s  ddl m} ddlm} ddlm} d}t|| }|| j }||k rft|| j }t|| }t	|d 
d}	|	jdd	 | }
d}t|| j }d
}|}g }|dkrH|| }||kr|d
 }|| jd| ||||	||| jj | jjj| jjjd|
dd}|| |  | jjd|  ||7 }||8 }q|D ]}|  qL| jjd |
 s||
 7 }qj| jjd|  |S )Nr   QueueThreadr3   r   r   tasksTr*  r   Z
dump_tasksr6   )r<  r=  r'  r>  r?  r#   r@  targetr   r   u   Форк _dump_task_part proc=uE   Конец параллельного скачивания задачu   Ошибок: )r   rI  	threadingrK  r9   r4   mathZceildownload_threading_max_forksr   rC   r7  rE  r5   r;   r<   r=   r>   r8   ra   startr   r   r   ry   emptyrs   )r0   r?  rG  rI  rK  r4   r'  Ztotal_pagesZper_threadsr>  r@  rA  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)rC   rD   r   r   rE   getattrr   rw   r   rF   r   rZ   r   r   rv   r   rH   )	r0   rT   	queue_objqueue_dir_tmpZ
items_filerJ   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 ]}zJ| j rW  d S | j jd7  _| jj	
d|d  d|d  d |t|d }|d}| j|d }| sp||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   u,   Создание дампа очереди "r   r)  r    ... r   rn   r   )rn   r   r   r   r+   u1   Создание дампа типов задачrD  u0   Создание дампа разрешенийZpermissionsu=   Создание дампа рабочих процессовr1  u(   Создание дампа версийZversionsu2   Создание дампа компонентов
componentsr   rA   ru7   Создание дампа задач очереди: rF  u<   Не удалось создать дамп очереди "r   u7   Конец создания дампа очередей)$r)   r   r*   r   rB   rC   r7  r   r   r   r   r6  r   rx   r#   Zget_queue_issues_countrD   
get_queuesrZ   r   makedirsr^  r   r   r   r   r   r   rE   rF   rH   rG   r+   r   rU  r   )r0   rootZ
queues_dirrG  stepr   r   Z	data_filer+   rZ  rY  r?  rJ   r   r   r   _dump_queues  sn    

$


"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   Создание дампа всех рабочих процессовr1  u5   Создание дампа всех очередейr   u/   Создание дампа всех досокr   u5   Создание дампа всех спринтовr   uE   Создание дампа всех проектов(списков)r      u?   Создание дампа выбранных очередейN)r   rB   r   
disk_usager   r   r   r#   r   Z	get_rolesZ
get_groupsZget_issue_typesZget_prioritiesZget_statusesZget_linktypesZget_screensZget_workflowsre  Z
get_boardsZget_sprintsZget_projectsr   r   r   ri  )r0   Zdownload_pathtotalusedfreeZfree_percentr   r   r   download_dataO  sH    

z!CmfPluginTrackerApi.download_datac              
   C   s0  t dd | }|dkr"q"| j r0q"tj|d }| jjd| d z| j	
|d |d  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
r   | jjd|  Y qX qW 5 Q R X d S )NFr&  DONEr  u   Попытка скачать rb  r  r  sizeu   Возможно файл u.    не был скачан корректно: r4  u	    байтr   r   Tu   Сохранен в u,   Не удалось скачать файл )r
   rs   r   r6  r  r  r  r   r   r#   Zdownloadr   statst_sizer  r\   r  r  r   r   r   )r0   download_queuer$  r  	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 rld S | jjd d S )Nr   rH  rJ  u5   Старт скачивания вложений ... zplugin.plugin.source_hashr(   ==r  Fr   u   Вложений нетu   Файлов: Z_download_file_worker_rw  rM  u/   Запуск задачи скачивания rb  r  r  r  r   rR   )r   r  r  r  rs  u   Конец скачивания)r   rI  rO  rK  r   r   r   r:   r(   r\   r  countr5  rQ  ry  ra   rR  Zslistr6  r9  r   r  r  r  rS  ry   )r0   rI  rK  rw  _filterZcount_download_filesZprocsirT  r$  rW  r   r   r   download_files  sL    


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| |_	|j
dd |S )Nu   Импорт группы rm   r   r   r   r   r   r   r{  r   rz  T)r   r   import_originalr  r   Zsave_import)r   r   r   r(   r\   rj   rs   r  r   r   r   )r0   r  Zgroup_ext_idgroupr   r   r   _process_group  s       

z"CmfPluginTrackerApi._process_groupu;   Обработка пользователей и группc              	   C   s  t  }| dD ]}| j r& dS zV| 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}|s$t	j
jddd| dgdgd}|s$t	j
jdd
|d gd}t|dkr|  jd7  _| jjd|d  dt|  |r$|d }|sJd}t	j
||d  | jdd}|jrn|D ]}t||||  qV|jr|jr|jdd |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   Nu&   Импорт пользователя rm   r   r   rR   Floginrz  r   r   r{  r   r   r   r   r   r   u+   Пользователей с именем z > r   T)r   r  r   r  r  rg_member_ofrj  r   z.evateam.ruzrobot@yandex.ruu@   Не удалось загрузить пользователя )r   )(setr   r   r6  r   r   r(   r   r)   r\   rf   r^   rs   rw   r   r   r   lowerr  setattr
is_changedr   r:   r   rj   tracker_group
user_groupr  ra   Z
user_localr  r   r   r   r   addr>   r   Zschedule_deferred_jobZregister_persons)r0   Znew_user_emailsr   r   Z	user_dictZ
is_createdr   Zpersonsrn   r  r  r  r  r   r   r   _process_users  sz    
 "
 




 z"CmfPluginTrackerApi._process_usersu#   Обработка статусовc                 C   s   |  dD ]}| j r dS | j d|d  }tjj|d}|sjd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dd | jj  | j jd7  _q
dS )uJ    Импорт и сопоставление статусов из Tracker rl  Nr   r   r   r   rz  r   r   r   r   r   rE   u
   РевьюZreviewTr  r   )r   r   r6  r(   r\   CmfStatusCoders   r   Zcalc_status_typestatus_typer   r   r   r   r   )r0   r   status_code_ext_idstatus_coder}  r   r   r   _process_statuses4  s$    

z%CmfPluginTrackerApi._process_statusesu2   Обработка логических типовc                 C   s0  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 rn 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	rx|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  rk  Nu#   Импорт типа задачи r   r   r   r   r   r   r   r   rz  r{  Tr   u   Поиск по имени "z" ... ILIKEu   Тип "u7   " не найден. Создание нового ... r  r   ro   r]   r   )r   r   r6  r   r   r(   r\   CmfLogicTypers   r   r   stripr   r   templatecmf_model_nameis_newr   r   )r0   Z	name2codeZ
issue_typeZissue_type_ext_idr   Zlogic_type_dictZtemplate_coder  r   r   r   _process_issue_typesO  s`    
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   r2  =r  r   rm   )r2  r  r   Fr   )r(   r\   r  rs   r   	CmfStatusr   r   r  r  Zallow_empty_transitionr   r  )r0   Zstatus_datar2  r  r  status_ext_idr   r   r   r   _create_status  s0    
z"CmfPluginTrackerApi._create_statusu4   Обработка рабочих процессовc              	   C   s  |  dD ]}| j r  dS | jjd|d   | j d|d  }tjj|d}|s~tjjdd	}tj||| jd
}|d |_	|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 r6  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|_||_|j
dd qhq| j jd7  _q
dS )u    Импорт workflow r1  Nu/   Импорт рабочего процесса r   r   r   r  r  r   r   r  r   Tr  Zstepsr   r2  rz  r   r  r{  !=r   )forceactionsrN  -)r   r2  r   )r   r   r6  r   r   r(   r\   CmfWorkflowrs   r   r   r  r  rw   r  deleter   ZCmfTransstatus_from	status_tor   )r0   Zworkflow_infoworkflow_ext_idr2  Ztemplate_workflowrh  Zworkflow_statusesr   Zstatus_from_ext_idr  actionZstatus_to_ext_idr  Ztransition_ext_idZ
transitionr   r   r   _process_workflow  sT    

 
&
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  |_||_	||_
||_|jdd tjj|dD ]}|  q0| D ]b\}	}| j rb qtjjdd	d
|	 d
gd}
|
|d|| jd}tjf |}|jdd qH|S )NZissueTypesConfigr   r2  r   r  Z	issueTypeZdefaultTyper   r   r   r   zsoftdev:defaultr  r  u!   Simple-схема проекта r   Tr  )	scheme_wfr]   )r   Ztarget_workflowr  r  r   )rv   r(   r\   r  rs   r  ZCmfSchemeWfr   r   default_task_logic_typeZdefault_task_workflowZdefault_subtask_workflowr   ZCmfSchemeWfRulerw   r  r   r6  )r0   r   Z	issue_mapr  Zdefault_task_wfZdefault_subtask_wfZtype_configr  r2  logic_type_ext_idr   Zscheme_ext_idschemer  ZruleZ	rule_dictr   r   r   #_create_schemewf_for_simple_project  sR    
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   r0   
project_idZproject_dirrJ   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 ]0}z| j r`W  d S | j d	|d  }t jj|d
}|st j|| jdd}t j	jdd|_
||_|d |_|dd|_|jj|_|d r|n||_|jr|d s|d r|d n
|d |jr2|jr2|j|j d | 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   rR   release)sys_typetree_parentarchiver   r  
::version:r  Tr   r   r  zlist.release:defaultr  r   r   ro   archivedZreleasedCLOSEDZOPENr   r   u)   Ошибка импорта версии )r\   ri   rs   	CmfFolderr  r   r6  r(   CmfListr  r   r   r   r   r  Zdefault_release_workflowr2  r  Zset_default_statusr  r  r   r  r   r   r   r   )r0   project_dataproject_objZrelease_folderZarchive_folderversionversion_ext_idZversion_listr   r   r   _process_versions'  s@    



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_componentsN  s    z+CmfPluginTrackerApi._get_project_componentsu)   Обработка компонентовc              	   C   s  t jj|d d}t jj|dddgd}| j|d dD ]n}z4|jsVd|_|  | j rhW  d S | j	 d	|d  }t j
j|d
dddddgd}|st j
|| jdd}||_|d |_||_|dr| |d d |_|ddr|j|_|jr|jr|jdd |ddrb|js8|  d|j_|jjrb|dd|j_|jjjdd | j jd7  _W q8   |  jd7  _| jjd|d   Y q8X q8d S )Nr   r  rc  Ttree_node_is_branch)r  r  Zinclude_systemrR   r   r  ::component:descr_documentdefault_ownerdefault_responsibler  r  r   r  r  r   leadZ
assignAutoFr  r   ro   r   u1   Ошибка импорта компонента )r\   ri   rs   r  r  r  r   r   r6  r(   CmfComponentr   r   r  r   r  r  r  r  r  Zcreate_descr_document
text_draftr>   r   r   r   r   )r0   r  r  Zcomponents_folder	componentcomponent_ext_idZcomponent_listr   r   r   _process_componentsT  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 ]Z | j rn 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gd}|st j|d ||| jdd}|dd|_|d|_|d|_||_t jjdd|_|jrR|jrR|j|j d | j|j }rnd|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   r   c                    s   t | d t  d kS Nr   r   rW  project_listr   r   r	    r
  z<CmfPluginTrackerApi._process_project_lists.<locals>.<lambda>   Проект "r   u"   " не найден в дампе!::project_list:r  T)r   r   r   r   r  r   ro   	startDateendDatezlist.base:defaultr  r   r   r   u+   Ошибка импорта проекта )r\   ri   rs   r(   r  r   r   r6  nextr   r   r   r   r  r   plan_start_dateplan_end_dater  r  r   r  r  r  r/   r   r   r   r   )r0   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  sL    

z*CmfPluginTrackerApi._process_project_listsc              
   C   s   ddl m} | dddd} || ddd	}z^d
ddd|  dgdd| gddd| dgg}tjj|d}|stj| d}|jdd |W S  tk
r } zt	d|  d|  W 5 d }~X Y nX d S )Nr   )translitr   rW  #ro   ruT)Zlanguage_codereversedORaliasr  r   "%r   r   r   r  u+   Не удалось создать тег "z": )
Ztransliterater  r8  r\   ZCmfTagrs   r   r   Zloggingr  )r  r  r  r}  tag_objr   r   r   r   _create_tag  s     zCmfPluginTrackerApi._create_tagu   Обработка теговc                 C   sZ   t  }| |d D ],}| j r( d S |dr||d }q|D ]}| | qFd S )Nr   tags)r  r   r   r6  rs   unionr  )r0   r  r  rc   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: Не найден наблюдатель задачи rm   N)r   CmfErrorr   r   	cmf_ownerZ
spectatorsra   r   )r0   	issue_objrc   Zwatcherr   r   r   r   _process_watchers  s    z%CmfPluginTrackerApi._process_watchers)rc   c              	   c   sB   t | d d}t|d}|D ]}t|V  q"W 5 Q R X d S )Nr3  r.  r@   )r   rC   rE   rF   r   )rc   Zcomments_file_pathrJ   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|||_||_|jdd q
d S )Nr   ZlongIdr  Tr   r  r   r   r   r   r   r   r/  r   ro   r  )r  r(   r\   rh   rs   r  r   r   r  r   r   r   _process_mentionsr   _process_linksr>   r  r   )r0   r   rc   Zcomment_datar   rC  r   r   r   _process_issue_comments  s     


z+CmfPluginTrackerApi._process_issue_commentsc                 c   s8   t | d d}t|D ]}|||dV  qd S )Nr3  r,  )r#  rI   )r   rC   r   r   )rc   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r^|jdd |	  t
|d |j |j}|rtjjj }||j}	|	  || t  qd S )	Nr   )RDiskr#  )r   r   )r   r   r   Tr  rI   )Zrdisk.rdiskr  r  r\   CmfAttachmentrs   r   r  r   Z
upload_dirr   copyZfull_path_filer  ZCmfRFiler   Zdata_driverZget_rdZ	get_rfileZ
_file_nameZmake_previewra   r   )
r0   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  r\   rf   rs   r   r  r   r>   r  r   r   r   r   rx   )	r0   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   ro   Ni)ZfileNameZ	fileName2ZurlPreviewImgZ
urlPreviewr  r  z/static/file-outline.png)r  r|  r   findurl_previewr	   r8  formaturl_preview_imgr  replace_withZ
currentTag)r0   r  ZattachZTAG_TMPLr   r   r   r   _create_preview?  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	  t  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   rV  Zfile_idr   r   	<genexpr>  s      z5CmfPluginTrackerApi._process_links.<locals>.<genexpr>r,  rm   r  r  r  )r   r   rR   Zsrc_origTZvideoZcontrolsz100%widthZheightZimageZ	href_origsourcer   u   Заменили на )r	   r  r  rs   r   r   r   r  r   r  r  r  r  r  r\   r  r  r  sgetr  	mimetypesZ
guess_typer   r  Znew_tagra   rx   )r0   r   r   r   Z	text_soupr  r  Zattachment_datar#  Z
attach_objZ	mime_typeencoder  r  r   r  r   r  n  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   Не указаноrm   z, c              	   S   s2   g | ]*}t |tk	r*t|d |dn|qS )rm   r   )r   rx   rs   rV  r   r   r   r     s     zLCmfPluginTrackerApi._simple_html_diff.<locals>.get_value.<locals>.<listcomp>)r   rv   rs   rw   ry   rx   )r]  r   r   r   	get_value  s    
z8CmfPluginTrackerApi._simple_html_diff.<locals>.get_valuer  u    ➔ r   )rV   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|_|jdd qd S )Nr0  z	::change:r   r  rR   fieldr   fromtorm   z<br>Tr  r   r   r~   r  )r(   r\   rh   rs   r  r  r   r   r   r  r   	log_levelr   )
r0   r   rc   Zchanger   rC  Zcomment_textrR   r  Zdiffr   r   r   _process_issue_changelog  s,    

z,CmfPluginTrackerApi._process_issue_changelogu   Обработка задачиc           )   	   C   s\  | 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|jd d4 |d d5 d.kr$|d6 |_||_|  || | !|j"j#|_"| $|j"j#|||_"| %|| | &|| |d7g D ]b}| j  d8|d  }tj'j|d}|s| jjd9|d   |  jd7  _n|j(| q~|d:g D ]b}| j  d;|d  }tj)j|d}|sB| jjd<|d   |  jd7  _n|j*| q|d= }r| j  d>|d  }| j+|td?g d@}|dA | || j+|< |dB }r|D ]J} | j  dC| d  }!| j,|!td?d?g dD}"|"dA | |"| j,|!< q|dEr| -|| |jr0|jd d4 t.  |dFg }#|#rzP|/dFg |#D ]}$| 0|$}%|j1|% qZ|jr|jd dG |j23  W n   | jj4dH Y nX | j  d|d  }&tj5j|&d}'|'stj5|&| jdI}'||'_6|dJ  }(dK|( dL|( dM|'_"dN|'_7|'jd d4 |'j23  |  j8d7  _8| jjdO| j8 dP| j9  dQS )Ru   
        Общая логика обработки которая потом разделяется на задачи и эпики
        r   r   r   r  u   Нет проекта "rm   r   rR   r2  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   ro   r   Zlinks	directioninwardrq   objectrp   outwardZepicu0   Попытка создать задачу из r  r   r   r   r  r   r  r  rn   r   ZfixVersionsr  u!   Не найдена версия rc  r  u%   Не найден компонент r   r  F)r   rB  rB  sprint	::sprint:)r   r  rB  r  r  r   u/   Не удалось привязать тегиr   r   r0   u?   Задача импортирована из Tracker: <a href="" target="_blank"></a>r~   u&   Импортировано задач r4  N):r(   r\   ri   rs   r  r   r)   r]   r^   r  r  r   r   r   r   r   r  Zdefault_activityrv   r,   r-   ra   r   hasattrr  r  r   r  r  r   r   r  r  r  r   r>   r  r  r  r  listsr  rc  r/   r.   r  r   r:   r  r  r   r   Zexcepionrh   r   r  r+   count_project_issues))r0   rc   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  rU   r>   r  r  Zversion_objr  r  Zcomponent_objr  r  r  r   r%  sprint_ext_idsprint_datar  r  r  comment_ext_idrC  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&  rs  )r
   r   r6  rs   r2  )r0   issue_queuerc   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   rL  r   r   r@   )
r   rB   rC   rx   r   r   r   rE   rF   rG   )r0   r  r>  Ztask_idrJ   r   r   r   r     s    
z&CmfPluginTrackerApi._get_project_tasksu   Обработка досокc           
         s  t jj|d d}|d D ] | j r0 d S tt fdd| dd }|d krr| 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dd |jr|jD ]}|  q|d D ]~}t j|d || jdd}|jdd |d D ]>}| j
 d	|d
  }t jj|d}	|	sjt|j|	 q:|jdd q
| j jd7  _t  qd S )Nr   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'  Tr  r   )r   r   r   r  rl  r   )r\   ri   rs   r   r6  r  r   r   r   r   r(   ZCmfKanbanBoardr   r   r  r  r   r  r6  r  ZCmfKanbanBoardColumnr  AssertionErrorZmapped_status_codesra   r   r   )
r0   r  r   r   Z	board_objr   Zboard_columnr   r  Zstatus_globalr   r5  r   _process_boards  sN    





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|j d |d |_|jr|jr|j|j d |S )NZtree_parent_idrz  r  r  r  r   r&  r   r   r  Tr  r   r  r  zlist.agile_sprint:defaultr  r   )r   rs   ra   r\   r  r(   r  r   r   r  r  r  r   	list_typer  r   r  r  r   r  )	r0   r   r%  Zparent_sys_typer:  r}  r  r/  Zsprint_listr   r   r   _process_list  s0    



z!CmfPluginTrackerApi._process_listu#   Обработка спринтовc                    s   t jj|d d}|d D ] tt fdd| d}|D ]`}| j rT  d S | ||}| j	|j
 }rd|d< |d	|d	< t  | j jd
7  _q>qd S )Nr   r  r   c                    s   t | d d t  d kS )Nr   r   r   r  r5  r   r   r	    r
  z6CmfPluginTrackerApi._process_sprints.<locals>.<lambda>r   Tr   r  r   )r\   ri   rs   rw   r   r   r   r6  r;  r.   r   r   r   )r0   r  r   r   r%  
sprint_objr0  r   r5  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|j}|  |r^tjj|dD ]}	|	jdd qJ|   | | |   | | |   | j|d | j
jd g }
| }t| jD ]F}|| j d| d|id}|
!| |"  | j
jd|  q| #|d D ]"}| j
$ r$ q2|%| q|
D ]}|%d q6| j
jd |
D ]}|&  qZ| j
jd | j
$ rd S t'  | (| |   | )| |   | *| | j
 j+d 7  _+|   |S )!Nr   rH  rJ  Fr   rz  r   r   r{  z ()r  uo   " уже существует! Импортируемый проект будет переименован в "r   r  Tr$  z[^A-Za-z0-9-]ro   )r   )ZTEXKOM_db_delete)r  u<   Импорт задач в несколько потоковr4  r3  rM  u.   Параллельный обработчик r   rs  u3   Ожидание обработки задач ... u(   Конец обработки задачr   ),r   rI  rO  rK  r\   ri   rs   r   r   r   r   r   r  r   r   keysr  subr   r>   r  r  r]   rw   r  r   r  r  r  r   r5  Zthreading_max_forksr4  ra   rR  r   r6  r9  ry   r   r  r8  r=  r   )r0   r>  r  rI  rK  Zproject_is_newr  rn   r  r   Zissue_processr3  r~  rT  rc   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 rNt	  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
rz   |rJt j|dd}
|
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   zproject.agile:defaultr  z"default_import_tracker@evateam.comZdefault_import_tracker)r   r   r   r   r   r-  r   ro   rn   )
Zproject_typer   r   r   r  r  task_code_prefixr  r   r  r   r+   Zdelme)r   r   Tr  r   r   u<   Не удалось импортировать проект )r\   ZCmfActivityrs   r   r>   r   rx   r   r6  r   r(   r  r  r   rF   r   r+   r,  rB  r   r]   r   Zcmf_deletedr   r   r   )r0   r  r  r   r-  r   r  Zproject_leadr  r>  r   r   r   r   _process_projectsn  sR    


z%CmfPluginTrackerApi._process_projectsuN   Обработка связей задач и проектов(списков)c              	   C   s   | j  D ]\}}| j r" 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| qp|  jd7  _| jj	d| d|j  qp|jdd t  q
dS )ul   
        Постобработка добавления задач в проекты(списки)
        Nr   r  u@   Добавляем задачи в проекты(списки) r  rB  r+  r   r  r  r   -   Неизвестная задача issue_id=u!    в проекте(списке) Tr  )r/   r   r   r6  r\   r  rs   membersrG   r   r   r   r   r]   ra   r   r   r   r   )r0   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 r$ 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
}|rP|drB| 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rNt|jdkrN|j| n|j| qr|  jd7  _| jj	d| d|j  qr|jdd t  q
dS )u^   
        Постобработка добавления задач в спринты
        Nr   r  u0   Добавляем задачи в спринт r  rB  r+  r   r  r  r  z::comment-sprint:r  r   r   r'  r~   uB   Задача была в архивном спринте <a href="r(  r)  r   r  r   rE  u    в спринте Tr  )r.   r   r   r6  r\   r  rs   rF  rG   r   r   r   r   r]   r(   r   rh   r  r  r   r   r  r   r  r  r+  ra   r   r   r   )r0   r/  r0  r<  rG  r   r1  rC  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npd|jddkrtd|jd }|sr 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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r:|} qjq:|s jjd|d
dd   d qnq|d k	r|t	j| qt|S )Nr  ar  r  ro   z
[A-Z]+-\d+r  r  z%"key":"r   r  r{  rn   u;   Не удалось найти задачу по коду "r   z[A-Z]+$)rC  u;   Не удалось найти проект по коду "z/wiki/z\/\d+u8   Не удалось найти ID документа в r   r   r  u9   Не удалось найти документ по ID "z/browse/z	\/\w+-\d+u2   Не удалось найти ID задачи в )r	   r  r  rs   r   r#   r  r  searchr\   r]   rw   r  r  r   r   r  ri   r(   r  r  ZCmfPluginCsvZcreate_tag_linkrx   )	r   r  r  r   r   objsr   r   Zext_coder0   r   r   check_links  sp    

$z=CmfPluginTrackerApi._process_cross_links.<locals>.check_linksr   r  Nr  rz  T)r  r]   ri   r  r   u)   Конвертируем ссылки в u=    на локальные задачи и документы: i  r   r   zcomments.log_levelzcomments.textr  )r   rR   slicer   r   r~   uZ   Не удалось конвертировать перекрестные ссылки в )rx   varsr\   r|  r   r   r   r^   rw   r*  r   r>   r  r  r   Z
do_approveZcommentsr  r   r   )r0   rN  r}  Z	mode_namer{   rG  rh  r~  rL  r   rC  r   rM  r   _process_cross_links  sF    =



z(CmfPluginTrackerApi._process_cross_linksu3   Обработка связей всех задачc                 C   s  | j jdt| j  | jD ]p}| j  r4 dS tjj|d}| j| D ]B}tjj|dgd}|s|| j j	d|  qL||_
|jdd qLq | j j  d	d
dd}| j jdt| j   | j D ]\}}| j  r dS z| j d|d d  }||d d }	|	r0tjj|	d}
ntjj|d}
|
s`tjjdd|d d gd}
|
stj|| j |d d d}
|d d |
_|d d |
_|
jdd tjj|d d d}tjj|d d d}|r8|r8| j d|d  }tjj|d}|stj|| j d}||_||_|
|_|jdd n:|rL|d d }n|r^|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   Подзадачи: Nr  parent_taskr  uq   Не удалось связать задачи, возможно задача не попала в импорт Tr  zsystem.finish:finishzsystem.duplicatezsystem.link)Zdepends
duplicatesZrelatesu   Связи: r   r   r   r  r   rz  r   )r   r   r   r#  r!  rp   r   rq   r'  r   u.   Не удалось создать связь z out=z in=)r   r   r   r   r-   r6  r\   r]   rs   r  rR  r   r   r   r,   r@  r   r(   ZCmfRelationTypeZin_type_nameZout_type_nameZCmfRelationOptionZin_linkZout_linkrelation_typer   r   )r0   r.  rR  Zchild_ext_idZ
child_taskZ	map_namesZrelation_ext_idZissue_relationr   Zrelation_coderT  Zin_link_taskZout_link_taskZ
rel_ext_idZrelation_optionZ	link_taskr   r   r   _process_relationsR	  s|    




 z&CmfPluginTrackerApi._process_relationsc                    s  d| _ || _d| j_d| j_d| j_| j  | jjjj| _| | jj	d | _
t  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   d| j_| j  t  |  D ]  d dd | jD krq| jjd d	  d
 tt fdd| jd }|r|d D ] }| jjd|d	  d
 qV|d D ] }| jjd|d	  d
 qq| jjd| j   | jjd| jj  | j  S )Nr   u&   Импорт данных из TrackerrK   r   r   c                 S   s   g | ]}|d  qS r   r   r   r   r   r   r   	  s     z6CmfPluginTrackerApi.process_import.<locals>.<listcomp>u+   Импортирована очередь 'r   'c                    s   t | d t  d kS r  r   r  r   r   r   r	  	  r
  z4CmfPluginTrackerApi.process_import.<locals>.<lambda>r   u,    --- импортирован проект 'r   u,    --- импортирована доска 'u#   Ошибок обнаружено: u-   Импортировано объектов: )r   r   r   r   r   r   r5   r(   rW   rX   r)   r   rr  r  r   r  r  r  r  rD  rQ  rU  rH  rI  r   r*   r   r   r  r   )r0   r   r?  r   r   r   rW  r   process_import	  sR    

 z"CmfPluginTrackerApi.process_import)T)r%  r9  )X__name__
__module____qualname__r   r"   Zui_meta_skipr   __annotations__r   rx   rv   r'   propertyr#   r$   r   re   staticmethodrl   r_   r   r|   r   rW   r`   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r%  rE  rU  r^  ri  rr  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  r2  r4  r   r8  r;  r=  rB  rD  rH  rI  rQ  rU  rX  __classcell__r   r   r1   r   r"       s   


%

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


&	MR	4d7L:1
I

D 
66
&
2
.



/B

 ,	
3
#
c
6

)e
Mr"   )rP  r  r   r  pathlibr   typingr   r   r   r   r   r   Zbs4r	   Zcmf.appr
   Zcmf.includeZmodules.tracker.fieldsr   r!   r"   r   r   r   r   <module>   s    