U
    hem                     @   sp   d dl mZmZmZmZ d dlZd dlmZ d dlm	Z	 d dl
Z
d dlmZ d dlT dddZG dd dZdS )    )DictListOptionalIteratorN)wrapssleep)HTTPBasicAuth)*皙?         c                    s    fdd}|S )u-  
    Декоратор для повторного выполнения функции через некоторое время, при возникновении ошибки.
    Использует экспоненциальный рост времени повтора(factor) до граничного времени ожидания(border_sleep_time)

    :param exception: исключения, которые отлавливаются
    :param start_sleep_time: начальное время повтора
    :param factor: во сколько раз нужно увеличить время ожидания
    :param border_sleep_time: граничное время ожидания
    :param max_attempts: максимальное количество попыток выполнения
    c                    sN   t   fdd}t   fdd}t rJ|S |S )Nc               
   ?   s~   d}}|d7 }z| |E d H W S  k
rv } z6|kr@|| krN }n|d  7 }t | W 5 d }~X Y qX qd S Nr      r   r   argskwargsZattemptZtime_outerrorborder_sleep_time	exceptionfactorfuncmax_attemptsstart_sleep_time ./modules/jira/api.py	gen_retry   s    z3backoff.<locals>.retry_exception.<locals>.gen_retryc               
      sx   d}}|d7 }z| |W S  k
rp } z6|kr:|| krH }n|d  7 }t | W 5 d }~X Y qX qd S r   r   r   r   r   r   retry+   s    z/backoff.<locals>.retry_exception.<locals>.retry)r   inspectZisgeneratorfunction)r   r   r   r   r   r   r   r   )r   r   retry_exception   s    
z backoff.<locals>.retry_exceptionr   )r   r   r   r   r   r"   r   r!   r   backoff   s    -r#   c                   @   s  e Zd ZU dZdZdZe dZe dZe dZe dZ	e dZ
e dZe d	Ze d	Ze d
Ze dZe dZe dZe dZe dZe dZdZeed< eed< dyddZdddejdddZdzeee edddZd{e e dd d!Z!d|d"d#Z"e#e$d$d% Z%e#e$d&d' Z&d}e e dd(d)Z'd~e e dd*d+Z(d,d- Z)d.d/ Z*d0d1 Z+dd2d3Z,e-d4d5d6Z.e/d7d8d9Z0d:d; Z1ee-d<d=d>Z2d?d@ Z3dAdB Z4dCdD Z5ddEdFZ6edGdHdIZ7de e ddJdKZ8dLdM Z9dNdO Z:dPdQ Z;e<eef ddRdSZ=dTdU Z>ddVdWZ?e/ddXdYZ@e e ddZd[ZAe<ee<f e e d\d]d^ZBeeCe d<d_d`ZDdadb ZEdcdd ZFdedf ZGdgdh ZHdidj ZIdkdl ZJdmdn ZKdodp ZLdqdr ZMdsdt ZNdudv ZOdwdx ZPdS )JiraApid   z
rest/api/3z
rest/api/2z/searchz/workflow/searchz/statuses/searchz/issue/{issue_key}z/issue/{issue_key}/commentz/issue/{issue_key}/watchersz/users/searchz/fieldz/projectz/project/{project_key}z$/project/{project_id}/role/{role_id}z/auditing/recordz"/rest/api/3/workflowscheme/projectcloudurlNc	           
   
   C   s   ddl m}	 |r|}n|}|	||||||dt d| _dd| i| _|dsZ|d }|drh|nd	| | _|| _	|| _
|| _|| _d
| _|| _|rd| d| j | _i | _d S )Nr   )Jirai,  )r'   usernamepasswordtokenr&   
verify_ssltimeoutZsessionZAuthorizationzBearer /Zhttpzhttps://zorder by created ASCzproject = 'z' )Z	atlassianr(   cmfutilrequests_sessionconnheadersendswith
startswithr'   loginr+   r*   r,   jql
cmf_importsaved_files)
selfr'   r5   r+   r*   r&   r,   projectr7   r(   r   r   r   __init__`   s6    	
zJiraApi.__init__F<   )attachr-   )returnc                O   s   ddl m} | jrH| jrHt j|f|t| j| j| j|d|}n&t j|f|| j	| j|d|}|dr| d||d  }| j
jd||di tjd	 |sd
|j	ddkrd| krt| d |S )Nr   )	urlencode)Zauthverifyr-   )r2   r@   r-   params?ZGETdata)rC   levelzapplication/jsonzContent-type errorMessages)Zsix.moves.urllib.parser?   r5   r*   r/   r0   getr	   r,   r2   r1   Zlog_curl_debugZloggingINFOjson	Exception)r9   r'   r=   r-   r   r   r?   resr   r   r   jira_request~   s    0&
"zJiraApi.jira_request)urirA   r>   c           	      C   s  |r| d| dn| d}| | jd}tdd|}| jr| jjr| jjD ]\}|jj|rPt	|j
jd6}t| }t|tr|nd|iW  5 Q R    S Q R X qP|| jkrt	| j| d2}t| }t|tr|nd|iW  5 Q R  S Q R X t| j|  | j| j| |dd}| jrz|jd	krzd
|j d|j d|j d| j|  }| jj| t|| }| jrtj| j| j|d}||j  |  |j
| j|< t|tr|S d|iS )u    Запрос по API _z.jsonrE   z[/ '"{}]rrC   
   )rA   r-      u   Код ошибки - z, z - u   , адрес запроса: )r7   parentname) replaceAPI_VERSIONresubr7   attachmentsrS   valuer3   openZfull_path_filerI   loadsread
isinstancedictr8   gdebugr'   rL   Zstatus_codereasontextloggerr   CmfErrorZmodelsZCmfAttachmentZupload_fileencodeZsave)	r9   rM   rA   rS   
attachmentfresultresponseZ
error_textr   r   r   call   s4    .((zJiraApi.callr   c                 c   sp   d}d}|p| j }| jj| j||dd}|s0dS ||7 }|E dH  |t|7 }d|  k rb|krn qdS qdS )u(    Получение всех задач r   ZrenderedFields)r6   startlimitexpandN)MAX_ISSUES_RESULT_PER_REQUESTr1   Zjql_get_list_of_ticketsr6   len)r9   rl   start_attotalmax_resultsissuesr   r   r   
get_issues   s    

zJiraApi.get_issuesc                 c   s   d}d}|p| j }| jj|| j||dd}|d s6d S ||7 }t| d|d   |d E d H  |t|d 7 }d|  k r|ksn ||d krd S qd S )Nr   changelog,renderedFields)rk   rl   rm   rs   u    из rq   )rn   r1   get_issues_for_boardr6   r_   r`   ro   )r9   board_idrl   rp   rq   rr   rs   r   r   r   rv      s    
"zJiraApi.get_issues_for_boardc                 c   sJ   d}d}| j j|||d}|dg s(qF||7 }|d D ]
}|V  q8qd S )Nr   2   )rw   rk   rl   values)r1   Zget_all_sprintrG   )r9   rw   rk   rl   rK   rowr   r   r   get_sprints   s    zJiraApi.get_sprintsc                 c   sJ   d}d}| j j|||d}|dg s(qF||7 }|d D ]
}|V  q8qd S )Nr   rx   )	sprint_idrk   rl   rs   )r1   get_sprint_issuesrG   )r9   r|   rk   rl   rK   rz   r   r   r   r}      s    zJiraApi.get_sprint_issuesc                 c   s   d}|dkst dd|pd|d}|r0||d< | jjr| j| j | j |d }d|krjt|d |d	 svd
S |d	 E d
H  |d  t|d	 7  < |r8|d |kr8d
S q8n| j	 E d
H  d
S )u    Получение всех workflow
        https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-workflows/#api-rest-api-3-workflow-search-get
        ztransitions,transitions.rules,transitions.properties,statuses,statuses.properties,default,schemes,projects,hasDraftWorkflow,operationsrx   uG   Больше 50 за раз запросить не получится!r   startAt
maxResultsrm   ZworkflowNamerA   rF   ry   Nr   )
AssertionErrorr1   r&   rL   r'   WORKFLOW_SEARCH_URIrI   rJ   ro   Zget_all_workflows)r9   namesrl   rm   rA   rK   r   r   r   get_workflows   s$    zJiraApi.get_workflowsc                 c   s   | j jrd|p| jdd}|r&||d< | j| j | j |d }|d sPdS |d E dH  |d  t|d 7  < |r&|d |kr&dS q&n&|r| j |E dH  | j 	 E dH  dS )	u.    Получение всех statuses
        r   Zusagesr~   	projectIdr   ry   Nr   )
r1   r&   rn   rL   r'   STATUS_SEARCH_URIrI   ro   Zget_status_for_projectZget_all_statuses)r9   rl   
project_idrA   rK   r   r   r   get_statuses   s     
zJiraApi.get_statusesc                 C   sB   d|i}| j | j | j |d }d|kr:t|d |d S )Nr   r   rF   ry   )rL   r'   WORKFLOW_PROJECT_URIrI   rJ   )r9   project_idsrA   rK   r   r   r   get_project_scheme  s
    zJiraApi.get_project_schemec                 C   s    | j  d| d}| | S )Nz/rest/api/3/workflowscheme/z	/workflowr'   rL   rI   r9   idrM   r   r   r   get_issue_type_workflow_scheme  s    z&JiraApi.get_issue_type_workflow_schemec                 C   s   | j  d| }| | S )Nz/rest/api/3/issuetype/r   r   r   r   r   get_issue_type!  s    zJiraApi.get_issue_typec                 c   s   d|p
| j d}| j d}| j||d }d|krBt|d |d sNd S |d E d H  |d  t|d 7  < |r|d |krd S qd S )Nr   r   r   z/rest/api/3/workflowschemer   rF   ry   r   )rn   r'   rL   rI   rJ   ro   )r9   rl   rA   rM   rK   r   r   r   get_workflow_scheme%  s    zJiraApi.get_workflow_scheme)r   c                 c   sb   dd|d}| j  d}| j||d }|d s6d S |d E d H  |d  t|d 7  < qd S )Nr   rx   )r   r   r   z#/rest/api/3/issuetypescheme/projectr   ry   r   )r'   rL   rI   ro   )r9   r   rA   rM   rK   r   r   r   get_issue_type_schemes3  s    zJiraApi.get_issue_type_schemes)r   c                 C   s&   d|i}| j  d}| j||d S )Nr   z/rest/api/3/issuetype/projectr   r   )r9   r   rA   rM   r   r   r   get_issue_for_project=  s    zJiraApi.get_issue_for_projectc                 c   s>   | j jr*| j d}| | E d H  n| j  E d H  d S )Nz/rest/api/3/issuetype)r1   r&   r'   rL   rI   get_issue_typesr9   rM   r   r   r   r   B  s    zJiraApi.get_issue_types)	issue_keyr>   c                 c   s   t dddd}| jjrB| jtj| j| j j	|d|d
 }n*| jtj| j| j j	|d|d
 }|dszdS |d E dH  |d	  t|d 7  < qdS )
u@    Получим все комментарии по задаче r   rx   renderedBodyr~   r   r   ZcommentsNr   )r^   r1   r&   rL   ospathjoinr'   COMMENTS_URI_FORMATformatrI   COMMENTS_URI_FORMAT_BOXrG   ro   )r9   r   rA   rK   r   r   r   get_commentsI  s    ,*
zJiraApi.get_commentsc                 c   sJ   d}d}| j j|||d}|dg s(qF||7 }|d D ]
}|V  q8qd S )Nr   rx   )project_keyrk   rl   ry   )r1   get_all_agile_boardsrG   r9   r   rk   rl   rK   rz   r   r   r   r   V  s    zJiraApi.get_all_agile_boardsc                 c   sJ   d}d}| j j|||d}|dg s(qF||7 }|d D ]
}|V  q8qd S )Nr   rx   )keyrk   rl   ry   )r1   get_project_versions_paginatedrG   r   r   r   r   r   a  s    z&JiraApi.get_project_versions_paginatedc                 C   s   | j |S N)r1   get_project_components)r9   r   r   r   r   r   l  s    zJiraApi.get_project_componentsc                 c   sv   d}d}t  }|r||d< ||d< ||d< | | j | j | }||d krTqr||7 }|d D ]
}|V  qdqd S )Nr   i  Z
projectIdsoffsetrl   rq   Zrecords)r^   rL   r'   	AUDIT_URIrI   )r9   r   rk   rl   rA   rK   rz   r   r   r   get_audit_recordso  s    zJiraApi.get_audit_recordsr   c                 C   sP   | j jr| | jj|d}n"| | j | jj|d  }|sHg S |d S )u(   Наблюдатели по задачеr   watchers)	r1   r&   rj   WATCHERS_URI_FORMATr   rL   r'   WATCHERS_URI_FORMAT_BOXrI   )r9   r   r   r   r   r   get_watchers  s    "zJiraApi.get_watchersc                 c   sP  | j jr| j d}dddd}|r8|d |kr8||d< | j||d }|sPq|D ]}|| |d  |V  qT|d	  t|7  < |r8|d	 |kr8qq8ntj	
| jd
}dddd}|r|d |kr||d< d|d< d|d< | j||d }|sqL|D ] }|| |d  |V  q |d	  t|7  < |r|d	 |krqLqdS )u   Возвращает список всех пользователей, включая активных,
            неактивных и ранее удаленных, у которых есть учетная запись Atlassian.
            в старых версиях невозможно получить больше 1000 учеток
            https://jira.atlassian.com/browse/JRASERVER-65089
            исправлено в 8.7.0, 8.6.1 и выше
            z/rest/api/3/users/searchr   r%   "operations,groups,applicationRolesr~   r   r   r   r   zrest/api/2/user/search.r)   TZincludeInactiveN)r1   r&   r'   rL   rI   updateget_user_inforo   r   r   r   )r9   Z	limit_endrM   rA   Zusers	user_infor   r   r   	get_users  s:    
zJiraApi.get_usersc                 C   s   | j jr| j j|dd}n| j j|dd}dtj }tjjjt	| }|
dsvt|d d |  | |d< n(d|d kr|d d |  | |d< |S )Nr   )Z
account_idrm   zgroups,applicationRoles)r   rm   @emailAddressZdisplayName)r1   r&   userZconfigZ
ORG_DOMAINZcmffieldsZCmfEmailZ
max_lengthro   rG   r/   Ztranslit_strip)r9   r   r   ZpostfixZmax_lenr   r   r   r     s    
$zJiraApi.get_user_infoc                 C   sn   ddd}g }| j tj| jd| d|d }||d  t||d krTqj|d	  |d
 7  < q|S )Nr   rx   r   rest/api/2/field/z/contextr   ry   rq   r   r   )rL   r   r   r   r'   rI   extendro   )r9   r   rA   rK   ri   r   r   r   _get_field_context  s    
&zJiraApi._get_field_contextc                 C   sx   t j| jd| d| d}ddd}g }| j||d }||d  t||d	 kr^qt|d
  |d 7  < q,|S )Nr   z	/context/z/optionr   rx   r   r   ry   rq   r   r   )r   r   r   r'   rL   rI   r   ro   )r9   ZfieldIdZ	contextIdr'   rA   rK   ri   r   r   r   _get_field_options  s    
zJiraApi._get_field_optionsc              	   C   s   | j  }t }|D ]}d|kr.|||d < n|||d < | j jr|d rg |d< zT| |d |d< |d D ]4}z"|d | |d |d  W qn   Y qnX qnW q   Y qX qg |d< q|S )u]    Возвращает системные и настраиваемые поля задачи r   r   Zcustomoptionscontext)r1   Zget_all_fieldsr^   r&   r   r   r   )r9   r   rK   Zfieldr   r   r   r   
get_fields  s&    
"
zJiraApi.get_fieldsc                 C   s   | j |S r   )r1   Zissue_editmeta)r9   r   r   r   r   get_issue_meta  s    zJiraApi.get_issue_metac                 c   s~   d}|r|| |kr|| }dj |d}| jj|d||dd}| jjrL|}n|d }|s\d S |E d H  ||7 }||krqzqd S )Nr%   "project = "{project}" ORDER BY keyr:   z*allru   )r   rk   rl   rm   rs   )r   r1   r6   Zadvanced_mode)r9   r   rk   maxrl   r6   ri   rK   r   r   r   get_all_project_issues  s    
zJiraApi.get_all_project_issuesc                 C   s*   dj |d}| jj|ddd}t|d S )Nr   r   r   r   )rk   rl   rq   )r   r1   r6   int)r9   r   r6   ri   r   r   r   get_project_issues_count  s    z JiraApi.get_project_issues_countc                 c   s$   | j  }|std|E dH  dS )u*   Возвращает все проектыuE   Не удалось получить ни одного проектаN)r1   Zget_all_projectsrJ   )r9   rK   r   r   r   get_projects  s    
zJiraApi.get_projects)settings_usersr>   c                 c   s   |  | jdg D ]}t }|d }|  | jj|d d}|di  D ]}td|}|sdqN|	 }|  | j
j|d |d}|d	g D ]R}	|	d
 d |krtd|	 d| ||	d
 d  d }
||
 ||
dV  qqNqdS )u8   Возвращает участников проектаrC   rS   r   )r   Zrolesz\d+$r   )r   role_idZactorsZ	actorUserZ	accountIdu+   Не найден пользователь u*    участвующий в проекте r   )project_nameproject_member_emailN)rj   PROJECTS_URIrG   setPROJECT_URI_FORMATr   ry   rV   searchgroupPROJECT_ROLES_URI_FORMATrd   add)r9   r   r:   Zadded_users_to_projectr   Zproject_infoZroler   Z	role_infoZactorr   r   r   r   get_project_members  s$    
zJiraApi.get_project_membersc                 C   s0   | j | jj|dddid}|s$g S |d d S )u2   Возвращает вложения задачиr   r   rf   r   )rj   ISSUE_URI_FORMATr   )r9   r   rX   r   r   r   get_attachments(  s    zJiraApi.get_attachmentsc                 C   s.   |j dddd }| | j d| }|jS )uJ   
        Скачиваем содержимое вложения
        r.   r   )maxsplit)splitrL   r'   Zcontent)r9   r'   rM   ri   r   r   r   get_attachment_content/  s
    zJiraApi.get_attachment_contentc                 c   sl   | j  d| d}tdddd}| j||d }|ds@d S |d E d H  |d	  t|d 7  < q d S )
Nzrest/agile/1.0/board/z/quickfilterr   rx   r   r~   r   ry   r   )r'   r^   rL   rI   rG   ro   )r9   rw   rM   rA   rK   r   r   r   get_board_quick_filters8  s    
zJiraApi.get_board_quick_filtersc                 C   s$   | j |}| j j|d dd}|S )Nr   all)rm   )r1   get_project_permission_schemeZget_permissionscheme)r9   r   Zschemer   r   r   r   B  s    z%JiraApi.get_project_permission_schemec                 C   sP   t j| jd|d}g }| | }|d D ]}|| |d   q.|S )Nzrest/api/2/issue
propertieskeysr9   )r   r   r   r'   rL   rI   append)r9   issue_idrM   r   rK   rz   r   r   r   get_issue_propertiesG  s    zJiraApi.get_issue_propertiesc                 C   s   | j |}|d S )NZworklogs)r1   issue_get_worklog)r9   r   rK   r   r   r   r   O  s    zJiraApi.issue_get_worklogc                 C   s   t j| jd}| | S )Nzrest/api/2/configurationr   r   r   r'   rL   rI   r   r   r   r   get_jira_global_settingsS  s    z JiraApi.get_jira_global_settingsc                 C   s"   z| j |W S    Y dS X d S )NrE   )r1   !get_project_issue_security_scheme)r9   r   r   r   r   r   W  s    z)JiraApi.get_project_issue_security_schemec                 c   s&   | j  D ]}| j |d V  q
d S )Nr   )r1   get_issue_security_schemesZget_issue_security_scheme)r9   Zschr   r   r   r   ]  s    z"JiraApi.get_issue_security_schemesc                 C   s   t j| jd}ddd}g }| j||d }| jjs>|}qt||d  t	||d kr^qt|d  |d	 7  < q|D ]}| 
|d
 |d< qx|S )Nzrest/api/2/screensr   rx   r   r   ry   rq   r   r   r   Ztabs)r   r   r   r'   rL   rI   r1   r&   r   ro   get_screen_tabs)r9   rM   rA   rK   ri   Zscrr   r   r   get_all_screensa  s    
zJiraApi.get_all_screensc                 C   sb   zLt j| jd| d}| | }|D ]}| j||d d|d< q,|W S    g  Y S X d S )Nrest/api/2/screens/z/tabsr   )	screen_idtab_idr   )r   r   r   r'   rL   rI   get_tab_fields)r9   r   rM   ri   Ztabr   r   r   r   r  s    zJiraApi.get_screen_tabsc                 C   sH   z2t j| jd| d| d}| | }|W S    g  Y S X d S )Nr   z/tabs/z/fieldsr   )r9   r   r   rM   ri   r   r   r   r   |  s    zJiraApi.get_tab_fieldsc                 C   s.   | j js*tj| jd}| | }|S g S )Nzrest/api/2/screenscheme)r1   r&   r   r   r   r'   rL   rI   )r9   rM   ri   r   r   r   get_screen_scheme  s
    zJiraApi.get_screen_scheme)NN)N)r   )r   )Nr   )r   N)r   )N)N)r   N)Q__name__
__module____qualname__rn   rU   ZAPI_BOX_VERSIONZISSUES_SEARCH_URIr   r   r   r   r   r   r   Z	USERS_URIZ
FIELDS_URIZFIELDS_BOX_URIr   r   r   r   r   bool__annotations__strr;   requestsZResponserL   r   r^   rj   r   rt   rv   r#   rJ   r{   r}   r   r   r   r   r   r   listr   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   r   r   r   r   r   r   r   r   r   r$   F   s   
















#






*
	

r$   )r   r   r   r   )typingr   r   r   r   r    	functoolsr   timer   r   Zrequests.authr	   Zcmf.includer#   r$   r   r   r   r   <module>   s   
;