U
     @i                    @   s   d dl Z 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mZ d dlmZ d dlmZ d d	lmZ d d
lT G dd dejZedZee  dddZG dd deZdS )    N)DictListOptionalIterator)wrapssleep)HTTPAdapter)Retry)
HTTPStatus)Path)Jira)*c                   @   s   e Zd Zdd ZdS )SensitiveDataFilterc                 C   sb   t |dr^d}|jdd}td||}td||}td||}td||}||_d	S d S )
Nmsgz\1***\2z\""z("username":\s*")[^"]*(")z("password":\s*")[^"]*(")z ("webSudoPassword":\s*")[^"]*(")z("atl_token":\s*")[^"]*(")T)hasattrr   replaceresub)selfrecordreplZ	clean_msg r   ./modules/jira/api.pyfilter   s    
zSensitiveDataFilter.filterN)__name__
__module____qualname__r   r   r   r   r   r      s   r   zatlassian.rest_client皙?         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_timer   r   	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   retryA   s    z/backoff.<locals>.retry_exception.<locals>.retry)r   inspectZisgeneratorfunction)r-   r0   r1   r*   r+   r,   r.   r/   )r-   r   retry_exception,   s    
z backoff.<locals>.retry_exceptionr   )r+   r/   r,   r*   r.   r4   r   r3   r   backoff!   s    -r5   c                       sP  e Zd ZdZ fddZdd Z fddZ fdd	Z fd
dZdd Z	 fddZ
dddZdd ZdddZdee dddZdЇ fdd	Zeedd  Zeedeeed!d"d#Zdee dd$d%Zdee dd&d'Zd(d) Zd*d+ Zd,d- Zdd.d/Zed0d1d2Zed3d4d5Z fd6d7Z e!ed8d9d:Z"e!d;d<d=Z#de!eed?d@dAZ$de!eedBdCdDZ% fdEdFZ&dGdH Z'dIdJ Z( fdKdLZ)ddMdNZ*e!dOdPdQZ+dee ddRdSZ,ddTdUZ-ddVdWZ.dXdY Z/dZd[ Z0d\d] Z1e2e!ef dd^d_Z3d`da Z4ddbdcZ5ddddeZ6ddfdgZ7e!dhdidjZ8deddkdlZ9ee ddmdnZ:dodp Z; fdqdrZ<dsdt Z= fdudvZ> fdwdxZ? fdydzZ@ fd{d|ZA fd}d~ZBdd ZCdd ZDdd ZEdd ZFdd ZG fddZHdd ZIdd ZJdeeedddZKde!e!e!dddZLdd ZMdd ZNdd ZOdd ZPdd ZQdd ZRdddZSe!edddZTdd ZUdd ZVdd ZWe!dddZXe!eedddZYe!dddZZe!e!dddZ[e!dddZ\e!dddZ]de!e!e!e!edddZ^dedddZ_edddĄZ`ddƄ Za fddȄZb fddʄZc fdd̄Zd  ZeS )JiraApid   c                    s   | dr|nd| }|dr2|d|d< n|d|d< d|krPd|d< d|krdt |d< t j|f|| |   |d| _d	| _d
| _	d S )Nhttphttps://cloudtokenpasswordtimeout,  ZsessionFzrest/auth/1/session)

startswithgetcmfutilZrequests_sessionsuper__init___set_session_retriesr;   _session_valid_session_url)r   urlr&   r'   	__class__r   r   rC   _   s    
zJiraApi.__init__c                 C   s@   t tjtjtjdd}t|d}| jd| | jd| dS )u   
        Конфигурирует стратегию повторных попыток
        и ассоциирует ее с сессией
        r    )totalstatusZstatus_forcelistZbackoff_factor)Zmax_retrieszhttp://r9   N)r
   configZIMPORT_REQUEST_RETRY_TOTALZ!IMPORT_REQUEST_RETRY_STATUS_CODESr	   _sessionZmount)r   ZretriesZhttp_adapterr   r   r   rD   u   s    
zJiraApi._set_session_retriesc                    s   | j rt || dS )u   
        Переопределенный метод
        Базовая аутентификация устанавливается только для Jira Cloud
        N)r:   rB   _create_basic_session)r   usernamer<   rH   r   r   rN      s    zJiraApi._create_basic_sessionc                    sH   | j j  | j| jd}t jd| j|d}| j js>tdd| _	dS )u;   
        Выполняет авторизацию
        )rO   r<   ZPOST)pathdatauR   Ошибка аутентификации: файлы cookie не полученыTN)
rM   cookiesclearrO   r<   rB   requestrF   RuntimeErrorrE   )r   rQ   responserH   r   r   _authenticate   s    zJiraApi._authenticatec                    s>   z t  jd| jd}|jtjkW S  tjk
r8   Y dS X dS )u~   
        Проверяет валидность текущей сессии через тестовый запрос
        GET)rP   FN)rB   rT   rF   status_coder   ZOKrequestsRequestException)r   rV   rH   r   r   _check_session   s    zJiraApi._check_sessionc                 C   sP   | j r| jstd| jjr<| js<|  r<d| _|   dS |   |   dS )u>   
        Создает валидную сессию
        u_   Учетные данные для аутентификации не предоставленыTN)	rO   r<   
ValueErrorrM   rR   rE   r\   user_get_websudorW   r   r   r   r   _create_valid_session   s    zJiraApi._create_valid_sessionc              
      s   | j rt j||S zJ| js$|   t j||}|jtjkrZd| _|   t j||}|W S  tj	k
r } zBt
|dr|jjtjkrd| _|   t j|| W Y S  W 5 d}~X Y nX dS )u8  
        Переопределенный метод
        Используется только для Jira Server.
        Перед запросом проверяется валидность сессии
        и при необходимости выполняется авторизация 
        FrV   N)r:   rB   rT   rE   r`   rY   r   ZUNAUTHORIZEDrZ   r[   r   rV   )r   r&   r'   rV   erH   r   r   rT      s"    zJiraApi.requestN   c              
   C   s  |p| j }|p| j}| jd||d | jj|d||| j| jd}td| d|j	 d|j
  |  |jdd	}td
|}|r|dp|d}	nd	}	t|d"}
|j|dD ]}|
| qW 5 Q R X t|}| j}|	|dW  5 Q R  S Q R X dS )u  
        Скачивает файл

        Args:
            download_url (_type_): url файла для скачивания
            save_path (_type_): путь для сохранения файла
            headers (_type_, optional): Заголовки. Defaults to None.
            timeout (_type_, optional): Таймаут. Defaults to None.
            chunk_size (_type_, optional): _description_. Defaults to 8*1024.
        rX   )methodrG   headersT)streamrd   r=   Zverifyproxiesz
HTTP: GET z ->  zContent-Disposition z!filename\*?=(?:"([^"]+)"|([^;]+))r$   r    wb)
chunk_size)	file_name	file_sizeN)no_check_headersr=   Zlog_curl_debugrM   r@   Z
verify_sslrf   loggerdebugrY   reasonZraise_for_statusrd   r   searchgroupopenZiter_contentwriter   statst_size)r   Zdownload_urlZ	save_pathrd   r=   rj   resZcontent_dispositionmatchrk   fchunkZ	file_pathrl   r   r   r   download_file   s6    

 
zJiraApi.download_filec                 C   sR   d}| j dd}d}| jjr2| jj }|d}|r>||d< | j||g | jdS )u   
        Получает веб-куки sudo
        Переопределенный метод, так как метод в родительском классе выполняется некорректно
        z%secure/admin/WebSudoAuthenticate.jspaZfalse)ZwebSudoPasswordZwebSudoIsPostNzatlassian.xsrf.token	atl_token)rP   rQ   filesrd   )r<   rM   rR   Zget_dictr@   postform_token_headers)r   rG   rQ   r|   rR   r   r   r   r^     s    
zJiraApi.user_get_websudo*allr   c                 C   s0  i }|dk	rt ||d< |dk	rBt|tttfr:d|}||d< |dk	rR||d< |dk	rb||d< |dk	rr||d< | | jrdnd	}	g }
| jr|pd
|d< nt ||d< | j|	|d}|sq,|d }|
	| |dk	rސq,| jr|d rq,|d}qt |d }|t
|| krq,|t
|7 }q|
S )u   
        Переопределение метода jql_get_list_of_tickets класса Jira
        с учетом https://developer.atlassian.com/changelog/#CHANGE-2046
        N
maxResults,fieldsjqlexpandvalidateQuery
search/jqlrq   rh   ZnextPageTokenstartAtparamsissuesisLastrJ   )int
isinstancelisttuplesetjoinresource_urlr:   r@   extendlen)r   r   r   startlimitr   validate_queryZnext_page_tokenr   rG   resultsrV   r   rJ   r   r   r   jql_get_list_of_tickets+  sD    

zJiraApi.jql_get_list_of_tickets)returnc                 c   s   |dkrd}| j rd| }d}d}|p,| j}| j|||dd}|sHdS ||7 }|E dH  |t|7 }d|  k rz|kr.n q.dS q.dS )u(    Получение всех задач Norder by created ASCzcreated > '1900-01-01' r   ZrenderedFields)r   r   r   r   )r:   MAX_RESULTSr   r   )r   r   r   start_atrJ   max_resultsr   r   r   r   
get_issuesf  s(    


zJiraApi.get_issuesc                 #   s   d}d}d}|p| j }t j||||dd}|d s8d 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   r   changelog,renderedFields)r   r   r   r   u    из rJ   )r   rB   get_issues_for_boardgro   r   )r   board_idr   r   r   rJ   r   r   rH   r   r   r     s&    
"zJiraApi.get_issues_for_boardc                 c   sH   d}d}| j |||d}|dg s&qD||7 }|d D ]
}|V  q6qd S )Nr   2   r   r   r   values)Zget_all_sprintr@   )r   r   r   r   rw   rowr   r   r   get_sprints  s    zJiraApi.get_sprints)r   r   r   c           	      c   sz   d| d}|pd|pdd}|r0d ||d< | j||d}|d	g sLqv|d
  |d 7  < |d	 D ]
}|V  qhq0dS )u  
        Возвращает все задачи в для заданного спринта.
        Включены только задачи, на просмотр которых у пользователя есть разрешение.

        Args:
            sprint_id (_type_): ID спринта
            start (int, optional): начальный индекс задач. Defaults to None.
            limit (int, optional): максимальное количество задач на странице. Defaults to None.
            fields (list, optional): необходимые поля задач. Defaults to None.

        Yields:
            dict: данные задачи
        zrest/agile/1.0/sprint/z/issuer   r   r   r   r   r   r   r   r   r   N)r   r@   )	r   Z	sprint_idr   r   r   rG   r   rw   r   r   r   r   get_sprint_issues  s    zJiraApi.get_sprint_issuesc                 c   s   d}|dkst dd|pd|d}|r0||d< | jr| 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@n|  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,operationsr   uG   Больше 50 за раз запросить не получится!r   r   r   r   ZworkflowNamezworkflow/searchr   errorMessagesr   Nr   )AssertionErrorr:   r   r@   	Exceptionr   Zget_all_workflows)r   namesr   r   r   rG   rw   r   r   r   get_workflows  s&    
zJiraApi.get_workflowsc                 c   s   | j r| d}d|p| jdd}|r.||d< | j||d}|d sHdS |d E dH  |d	  t|d 7  < |r.|d	 |kr.dS q.n$|r| |E dH  n|  E dH  dS )
u.    Получение всех statuses
        zstatuses/searchr   Zusagesr   	projectIdr   r   Nr   )r:   r   r   r@   r   get_status_for_projectget_all_statuses)r   r   
project_idrG   r   rw   r   r   r   get_statuses  s"    

zJiraApi.get_statusesc                 C   s6   d}d|i}| j ||d}d|kr.t|d |d S )Nz!rest/api/3/workflowscheme/projectr   r   r   r   r@   r   )r   r   rG   r   rw   r   r   r   get_project_scheme  s    zJiraApi.get_project_schemec                 C   s   d| d}|  |S )Nzrest/api/3/workflowscheme/z	/workflowr@   r   idurir   r   r   get_issue_type_workflow_scheme  s    z&JiraApi.get_issue_type_workflow_schemec                 C   s   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}d}| j||d}d|kr6t|d |d sBd S |d E d H  |d  t|d 7  < |r|d |krd S qd S )Nr   r   zrest/api/3/workflowschemer   r   r   r   )r   r@   r   r   )r   r   r   r   rw   r   r   r   get_all_workflow_schemes  s    z JiraApi.get_all_workflow_schemes)project_idsc                 c   sV   dd|d}d}| j ||d}|d s*d S |d E d H  |d  t|d 7  < qd S )Nr   r   )r   r   r   z"rest/api/3/issuetypescheme/projectr   r   r   )r@   r   )r   r   r   r   rw   r   r   r   get_issue_type_schemes  s    zJiraApi.get_issue_type_schemes)r   c                 C   s   d|i}d}| j ||dS )Nr   zrest/api/3/issuetype/projectr   r   )r   r   r   r   r   r   r   get_issue_for_project#  s    zJiraApi.get_issue_for_projectc                 #   s   | j rd}| |E d H  n~t  }| d}| dd t  }|rX| d| n
| d |D ]2 tt fdd|d }|r|d  d<  V  qfd S )Nzrest/api/3/issuetypejira.user.localeen_UKc                    s   | d  d kS Nr   r   )Zitu
issue_typer   r   <lambda>G      z)JiraApi.get_issue_types.<locals>.<lambda>nameuntranslatedName)	r:   r@   rB   get_issue_typesget_mypreferencesset_mypreferencesdelete_mypreferencesnextr   )r   r   issue_typescurrent_user_localeZissue_types_untranslatedZissue_type_untranslatedrH   r   r   r   (  s*    




zJiraApi.get_issue_types)	issue_keyr   c                 c   sp   |  d}| d| d}tdddd}| j||d}|d	sDd
S |d	 E d
H  |d  t|d	 7  < q(d
S )u@    Получим все комментарии по задаче issue/z/commentr   r   zrenderedBody,propertiesr   r   ZcommentsNr   )r   dictr@   r   )r   r   base_urlrG   r   rw   r   r   r   get_commentsQ  s    

zJiraApi.get_comments)issue_id_or_keyc                 c   sv   |  d}| d| d}ddd}| j||d}|ds@d	S |d E d	H  |d
 rXqr|d  t|d 7  < q$d	S )u?    Получим историю изменений задачи r   r   z
/changelogr   r7   r   r   r   Nr   r   )r   r@   r   )r   r   r   rG   r   rw   r   r   r   get_changelog]  s    

zJiraApi.get_changelogr   r   c                 C   s   d| d}|dkrdn||dkr&dn|d}g }| j ||d}| dg sNq|||d  |dk	rfq||d	  |d
 7  < q2|S )u  
        Возвращает все проекты, связанные с доской,
        для заданного идентификатора доски.
        Если у пользователя нет разрешения на просмотр доски,
        никакие проекты не будут возвращены вообще.
        Возвращаемые проекты упорядочены по названию.

        Args:
            board_id (str): id доски
            start (int, optional): начальная позиция выборки. Defaults to 0.
            limit (int, optional): максимальное количество возвращаемых элементов.
                                   Если указано None, то вернет все элементы.
                                   Defaults to 50.

        Returns:
            list: список проектов
        rest/agile/1.0/board/z/projectNr   r   r   r   r   r   r   )r@   r   )r   r   r   r   rG   r   r   resultr   r   r   get_agile_board_projectn  s    zJiraApi.get_agile_board_projectproject_keyr   r   c                 C   sB   d}i }|r||d< |r$t ||d< |r4t ||d< | j||dS )u  
        Возвращает доски находящиеся в проекте Jira Cloud

        Args:
            project_key (_type_, optional): ключ или id проекта. Defaults to None.
            start (int, optional): начальная позиция выборки. Defaults to 0.
            limit (int, optional): максимальное количество возвращаемых элементов. Defaults to 50.

        Returns:
            _type_: _description_
        zrest/agile/1.0/boardZprojectLocationr   r   r   )r   r@   )r   r   r   r   rG   r   r   r   r   get_project_boards  s    zJiraApi.get_project_boardsc                 #   sb   d}d}| j r | j|||d}nt j|||d}|dg s@q^||7 }|d D ]
}|V  qPqd S )Nr   r   r   r   )r:   r   rB   get_all_agile_boardsr@   r   r   r   r   rw   r   rH   r   r   r     s    zJiraApi.get_all_agile_boardsc                 C   s0   d}| j |d|id}| |}||d d< |S )Nz3rest/greenhopper/1.0/rapidviewconfig/editmodel.jsonZrapidViewIdr   ZcardColorConfig
strategies)r@    get_board_card_colors_strategies)r   r   r   rV   Zcard_colors_strategiesr   r   r   get_advanced_board_settings  s
    
z#JiraApi.get_advanced_board_settingsc           	   	   C   sp   d| d}ddi}i }ddddg}|D ]B}z(| d	| }| j ||d
}|||< W q( tk
rh   Y q(X q(|S )u   
        Получает стратегии присвоения цветов карточкам

        Args:
            board_id (int | str): ID доски

        Returns:
            dict: стратегии цветов карточек
        z rest/greenhopper/1.0/cardcolors/z	/strategyZpreloadValuestrueZ	issuetypepriorityZassigneeZcustomr   r   r   )	r   r   r   r   r   Zstrategy_typesZstrategy_typerG   rV   r   r   r   r     s$    
 z(JiraApi.get_board_card_colors_strategiesc                 #   sJ   d}d}t  j|||d}|dg s(qF||7 }|d D ]
}|V  q8qd S )Nr   r   )keyr   r   r   )rB   get_project_versions_paginatedr@   r   rH   r   r   r     s    z&JiraApi.get_project_versions_paginatedc                 c   sp   |  d}d}d}t }|r$||d< ||d< ||d< | ||}||d krNql||7 }|d D ]
}|V  q^q$d S )	Nzauditing/recordr   i  Z
projectIdsoffsetr   rJ   Zrecords)r   r   r@   )r   r   rG   r   r   r   rw   r   r   r   r   get_audit_records  s    
zJiraApi.get_audit_records)r   c                 C   s   |  |}|d S )u(   Наблюдатели по задачеwatchers)Zissue_get_watchers)r   r   r   r   r   r   get_watchers  s    
zJiraApi.get_watchersc                 c   s4  | j rd}dddd}|r.|d |kr.||d< | j||d}|sBq|D ]}|| |d  |V  qF|d	  t|7  < |r.|d	 |kr.qq.nd
}dddd}|r|d |kr||d< |pd|d< d|d< | j||d}|sq0|D ]}|| |d  |V  q|d	  t|7  < |r|d	 |kr̐q0qdS )u   Возвращает список всех пользователей, включая активных,
            неактивных и ранее удаленных, у которых есть учетная запись Atlassian.
            в старых версиях невозможно получить больше 1000 учеток
            https://jira.atlassian.com/browse/JRASERVER-65089
            исправлено в 8.7.0, 8.6.1 и выше
            zrest/api/3/users/searchr   r7   z"operations,groups,applicationRolesr   r   r   Z	accountIdr   zrest/api/2/user/search.rO   TZincludeInactiver   N)r:   r@   updateget_user_infor   )r   rO   Z	limit_endr   r   Zusers	user_infor   r   r   	get_users  s:    zJiraApi.get_usersc              
   C   sT   z| j ||dW S  tjk
rN } z|jjdkr:W Y d S |W 5 d }~X Y nX d S )Nr   r     userrZ   	HTTPErrorrV   rY   )r   r   r   excr   r   r   get_user_info_by_key-  s    
zJiraApi.get_user_info_by_keyc              
   C   sT   z| j ||dW S  tjk
rN } z|jjdkr:W Y d S |W 5 d }~X Y nX d S )NrO   r   r   r   )r   rO   r   r   r   r   r   get_user_info_by_username5  s    
z!JiraApi.get_user_info_by_usernamec                 C   s   d}| j r | j|| dd}n4| j||d}|s@| j||d}|sTtd| ddtj }tjj	j
t| }|d	st|d
 d |  | |d	< n(d|d	 kr|d	 d |  | |d	< |S )Nzgroups,applicationRolesz,operations)Z
account_idr   r   r   u   Пользователь u    не найден@ZemailAddressZdisplayName)r:   r   r   r   r   rL   Z
ORG_DOMAINZcmfr   ZCmfEmailZ
max_lengthr   r@   rA   Ztranslit_strip)r   r   r   r   ZpostfixZmax_lenr   r   r   r   =  s    
$zJiraApi.get_user_infoc                 C   sb   d| d}ddd}g }| j ||d}||d  t||d krHq^|d	  |d
 7  < q|S )Nrest/api/2/field//contextr   r   r   r   r   rJ   r   r   r@   r   r   )r   r   rG   r   rw   rV   r   r   r   _get_field_contextO  s    
zJiraApi._get_field_contextc                 C   sh   d| d| d}ddd}g }| j ||d}||d  t||d	 krNqd|d
  |d 7  < q |S )Nr   	/context//optionr   r   r   r   r   rJ   r   r   r   )r   ZfieldId	contextIdrG   r   rw   rV   r   r   r   _get_field_options[  s    
zJiraApi._get_field_optionsc                 C   sN   |   }t }|D ]6}d|kr,|||d < n|||d < g |d< g |d< q|S )u]    Возвращает системные и настраиваемые поля задачи r   r   contextoptions)Zget_all_fieldsr   )r   r   rw   fieldr   r   r   
get_fieldsg  s    
zJiraApi.get_fieldsc                 C   s
   |  |S N)Zissue_editmeta)r   r   r   r   r   get_issue_metau  s    zJiraApi.get_issue_metac                 c   sz   d}|r|| |kr|| }dj |d}| j|d||dd}| jrH|}n|d }|sXd S |E d H  ||7 }||krqvqd S )Nr7   z"project = "{project}" ORDER BY key)projectr   r   r   r   r   r   r   )formatr   advanced_mode)r   r   r   maxr   r   rV   rw   r   r   r   get_all_project_issuesx  s    
zJiraApi.get_all_project_issuesc           	      C   s   i }|dk	rt ||d< |dk	r,t ||d< |dk	rVt|tttfrNd|}||d< |dk	rf||d< |dk	rv||d< |dk	r||d< | | jrd	nd
}| j||dS )u   
        Переопределение метода jql класса Jira
        с учетом https://developer.atlassian.com/changelog/#CHANGE-2046
        Nr   r   r   r   r   r   r   r   rq   r   )	r   r   r   r   r   r   r   r:   r@   )	r   r   r   r   r   r   r   r   rG   r   r   r   r     s"    
zJiraApi.jqlc           
      c   s   d}d| d}|r$|d| d7 }|r8|d| d7 }|d7 }|rX|| |krX|| }| j |d||dd	}| jrx|}	n|d
 }	|	sd S |	E d H  ||7 }||kr@qq@d S )Nr7   project = "r    AND updated >= " AND updated <= " ORDER BY updatedr   r   r  r   )r   r  )
r   r  r   r  
start_dateend_dater   r   rV   rw   r   r   r   get_all_project_issues_during  s&    
z%JiraApi.get_all_project_issues_during)r   c                 C   s,   d|i}|  d}| j||d}t|d S )u   
        Возвращает количество задач, которые соответствуют JQL

        Args:
            jql (str): Выражение JQL

        Returns:
            int: количество задач
        r   zsearch/approximate-count)rQ   count)r   r~   r   )r   r   rQ   rG   rV   r   r   r   jql_get_issue_count  s    

zJiraApi.jql_get_issue_countc                 C   sl   d| d}|r |d| d7 }|r4|d| d7 }|d7 }| j rL| |S | j|ddd}t|d	 S d S )
Nr  r   r  r  r  r   r$   )r   r   rJ   )r:   r  r   r   )r   r   r  r  r   rV   r   r   r   get_project_issues_count_during  s    
z'JiraApi.get_project_issues_count_duringc                 c   s"   |   }|std|E dH  dS )u*   Возвращает все проектыuE   Не удалось получить ни одного проектаN)Zget_all_projectsr   )r   rw   r   r   r   get_projects  s    zJiraApi.get_projectsc                 c   sb   d| d}t dddd}| j||d}|ds6d S |d E d H  |d	  t|d 7  < qd S )
Nr   z/quickfilterr   r   ZrenderedBodyr   r   r   r   )r   r@   r   )r   r   r   r   rw   r   r   r   get_board_quick_filters  s    
zJiraApi.get_board_quick_filtersc                    s"   t  |}| j|d dd}|S )Nr   all)r   )rB   get_project_permission_schemeZget_permissionscheme)r   r   schemerH   r   r   r    s    z%JiraApi.get_project_permission_schemec                 C   sD   d| d}g }|  |}|d D ]}|| j |d dd q"|S )Nzrest/api/2/issue/z/propertieskeysr   T)absolute)r@   append)r   issue_idr   Z
propertiesrw   r   r   r   r   get_issue_properties  s    
zJiraApi.get_issue_propertiesc                    s   t  |}|d S )NZworklogs)rB   issue_get_worklog)r   r#  rw   rH   r   r   r%    s    zJiraApi.issue_get_worklogc                    s$   zt  |W S    i  Y S X d S r	  )rB   !get_project_issue_security_scheme)r   r   rH   r   r   r&    s    z)JiraApi.get_project_issue_security_schemec                 #   s$   t   D ]}| |d V  q
d S r   )rB   get_issue_security_schemesZget_issue_security_scheme)r   ZschrH   r   r   r'    s    z"JiraApi.get_issue_security_schemesc                    s   d}ddd}g }| j s$t  }qh| j||d}||d  t||d krRqh|d  |d	 7  < q|D ]}| |d
 |d< ql|S )Nzrest/api/2/screensr   r   r   r   r   rJ   r   r   r   Ztabs)r:   rB   get_all_screensr@   r   r   get_screen_tabs)r   r   r   rw   rV   ZscrrH   r   r   r(    s    

zJiraApi.get_all_screensc                    sH   z2t  |}|D ]}| j||d d|d< q|W S    g  Y S X d S )Nr   )	screen_idtab_idr   )rB   r)  get_tab_fields)r   r*  rV   ZtabrH   r   r   r)    s    zJiraApi.get_screen_tabsc                 C   s$   z|  ||W S    g  Y S X d S r	  )Zget_screen_tab_fields)r   r*  r+  r   r   r   r,  $  s    zJiraApi.get_tab_fieldsc                 C   sr   g }| j rnd| jd}d}| j||d}d|kr<t|d |dg sJqn||d  |d  |d 7  < q|S )	Nr   r   z rest/api/2/issuetypescreenschemer   r   r   r   r   )r:   r   r@   r   r   )r   r   r   r   rV   r   r   r   get_screen_scheme*  s    zJiraApi.get_screen_schemec                 C   sT   d}d|i}| j ||d}d|kr.t|d |d d d }| |d |d	< |S )
Nz(rest/api/3/issuetypescreenscheme/projectr   r   r   r   r   ZissueTypeScreenSchemer   r   )r@   r   get_screen_scheme_issuetypes)r   r   rG   r   rV   Zscreen_schemer   r   r   get_project_screen_scheme>  s    z!JiraApi.get_project_screen_schemec                 C   s   zd}d| j |d}g }| j||d}d|kr:t|d |dg sHql||d  |d  |d 7  < q|D ]}| |d	 |d
< qp|W S    g  Y S X d S )Nz(rest/api/3/issuetypescreenscheme/mappingr   )r   r   ZissueTypeScreenSchemeIdr   r   r   r   r   ZscreenSchemeIdactions)r   r@   r   r   get_screen_scheme_actions)r   screen_scheme_idrG   r   r   rV   r   r   r   r   r.  L  s&    z$JiraApi.get_screen_scheme_issuetypesc                 C   sV   z@d}d|i}| j ||d}d|kr0t|d |d d d W S    i  Y S X d S )Nzrest/api/3/screenschemer   r   r   r   r   Zscreensr   )r   r2  rG   r   rV   r   r   r   r1  j  s    z!JiraApi.get_screen_scheme_actionsc                    s"   zt   W S    g  Y S X d S r	  )rB   get_all_prioritiesr_   rH   r   r   r3  x  s    zJiraApi.get_all_prioritiesc                 C   s   d| d}ddd}g }| j ||d}d|kr<t|d | dg sJq||d D ]}||d	  qR|d
  |d 7  < q|S )Nrest/api/2/priorityscheme/z	/projectsr   r>   r   r   r   r   r   r   r   )r@   r   r"  )r   	scheme_idrG   r   Zproject_keysrV   r  r   r   r   get_priority_scheme_projects~  s    
z$JiraApi.get_priority_scheme_projectsc                 C   sr   d| d}ddd}g }| j ||d}d|kr<t|d | dg sJqn||d  |d	  |d
 7  < q|S )Nr4  z/prioritiesr   r>   r   r   r   r   r   r   )r@   r   r   )r   r5  rG   r   
prioritiesrV   r   r   r   get_priority_scheme_priorities  s    
z&JiraApi.get_priority_scheme_priorities)r   r   r   c                 C   s   | j rd}d }d}nd}d}d}i }|d k	r8t||d< |d k	rLt||d< |rX||d< g }| j||d	}||g sxq|| D ]d}	| j r| |	d
 |	d< | |	d
 |	d< n*g |	d< |	d D ]}
|	d | |
 q||	 q|d  |d 7  < q\|S )Nzrest/api/2/priorityschemer   zrest/api/2/priorityschemeszschemes.projectKeysschemesr   r   r   r   r   ZprojectKeysr7  Z	optionIds)r:   r   r@   r6  r8  r"  Zget_priority_by_id)r   r   r   rG   r   r   r   r9  rV   r  Zpriority_idr   r   r   get_priority_schemes  s8    zJiraApi.get_priority_schemes)r   r  
issuetypesc                 C   s~  dddddddg}dd	 | d
}d}z| j|| jd}W nl tk
r } zNd| d}t|dr|d|jj d	|jj d|jj d| 7 }t	|W 5 d }~X Y nX |d}	|	|krt
d|	 d|  d}
d|i}|r||d< |r||d< z| j|
|d}W np tk
rx } zPd| d}t|dr`|d|jj d	|jj d|jj d| 7 }t	|W 5 d }~X Y nX |S )Nz5.2.7z5.2.3z4.8.12z4.8.9z4.8.7z4.7.3z4.5.1u   Установите плагин по ссылке https://marketplace.atlassian.com/apps/1221996/smart-jira-configuration-formerly-smart-project-config-docs/version-history(поддерживаемые версии: z, )z1rest/plugins/1.0/com.eis.jira.plugins.jiradoc-key)rd   u   Для получения полной конфигурации проекта не установлен плагин "Smart Jira Configuration". z. rV   u   Код ошибки - z - u   , адрес запроса: versionup   Установлена неподдерживаемая версия плагина 'Smart Jira Configuration': uF   . При импорте могут возникнуть ошибки. z-rest/smart-configuration/1.0/getProjectConfig
projectKeyr  r;  r   uN   Не удалось получить конфигурацию проекта "u6   " через плагин "Smart Jira Configuration". )r   r@   rm   r   r   rV   rY   rp   textZCmfErrorrn   warning)r   r   r  r;  Zsupported_versionsZ
error_textZ
plugin_urlrV   r   Zplugin_versionrG   r   r   r   r   get_project_smart_config  sV    

&

&z JiraApi.get_project_smart_configc                 C   s   d| d}ddd}i }| j ||d}d|kr<t|d | dg sJq|d D ]&}|t|d	 g }||d
  qR|d  |d 7  < q|S )Nz rest/api/2/issuesecurityschemes/z/membersr   r   r   r   r   r   ZissueSecurityLevelIdZholderr   r   )r@   r   
setdefaultstrr"  )r   Zsecurity_scheme_idrG   r   Zsecurity_level_membersrV   membermembersr   r   r    get_issue_security_level_members  s    z(JiraApi.get_issue_security_level_membersc                 C   sD   d| d}|d| j d}| j||d}|dg s8dS |d d S )uR    Возвращает контекст пользовательского поляrest/api/3/field/r   r   r  r   r   r   r   Nr   r@   )r   field_id
context_idrG   r   rV   r   r   r   get_field_context)  s    zJiraApi.get_field_contextc           
   
   C   s   d| d| d}d| j d}i }z| j||d}W n< tjk
rp } z|jjdkr^W Y 
dS  W 5 d}~X Y nX |d	g }|sq|D ]}	|	||	d
 < q|d  |d 7  < q"|S )u`    Возвращает опции контекста пользовательского поля rG  r  r  r   r   r   i  Nr   r   r   r   )r   r@   rZ   r   rV   rY   )
r   rJ  rK  rG   r   r  rV   r   r   valuer   r   r   get_field_context_option9  s$    
z JiraApi.get_field_context_optionc                 C   s~   d| d}|d| j d}g }| j||d}|dg s:qz|d D ] }|drB|t|d  qB|d  |d	 7  < q|S )
u    Возвращает сопоставленный список типов задач и контекста пользователького поля rG  z/context/issuetypemappingr   rH  r   r   issueTypeIdr   r   )r   r@   r"  rC  )r   rJ  rK  rG   r   r;  rV   rM  r   r   r   #get_field_context_issuetype_mappingU  s    
z+JiraApi.get_field_context_issuetype_mappingc           
   
   C   s   d| d}d| j d}g }z| j||d}W nN tjk
r| } z.|jjdkrhtd| d W Y 
q|W 5 d	}~X Y nX |d
g sq||d
  |d  |d 7  < qd	}|D ]0}	|	d|kr|	d   S |	dr|	d }q|S )uz    Возвращает список контекстов пользовательского поля для проекта rG  z/context/projectmappingr   r   r   r   uA   Не удалось получить контексты поля u@   . Пользовательское поле не найдено.Nr   r   r   r   r  ZisGlobalContext)	r   r@   rZ   r   rV   rY   rn   r@  r   )
r   rJ  r   rG   r   ZcontextsrV   r   Zglobal_contextr  r   r   r   !get_field_context_project_mappingm  s.    

z)JiraApi.get_field_context_project_mappingc                 c   sb   d| d}d| j d}| j||d}|dg }|s8q^|D ]
}|V  q<|d  |d 7  < qd	S )
u8    Возвращает поля конфигурации zrest/api/3/fieldconfiguration/z/fieldsr   r   r   r   r   r   NrI  )r   Zfield_configuration_idrG   r   rV   r   r  r   r   r   get_field_config_fields  s    zJiraApi.get_field_config_fieldsFc                 C   sn   d}d| j |d}g }| j||d}|dg s2qV||d  |d  |d 7  < q|rf|rf|d S |S dS )	u    Возвращает список конфигураций или конфигурацию по умолчанию при is_default=Truezrest/api/3/fieldconfigurationr   )r   r   Z	isDefaultr   r   r   r   N)r   r@   r   )r   Z
is_defaultrG   r   Zfield_configurationsrV   r   r   r   get_field_config  s    zJiraApi.get_field_config)field_configuration_scheme_idr   c                 C   s"   d}d|i}| j ||d}|d S )u  
        Возвращает список сопоставления типа задачи и конфигурации поля

        Args:
            field_configuration_scheme_id (str): ID схемы конфигурации полей

        Returns:
            list: список сопоставления типа задачи и конфигурации поля
        z+rest/api/3/fieldconfigurationscheme/mappingZfieldConfigurationSchemeIdr   r   r   )r   rT  rG   r   rV   r   r   r   "get_field_configuration_issue_type  s    
z*JiraApi.get_field_configuration_issue_typec                 C   sD   d}d|i}| j ||d}|d d }d}| dr@|d d }|S )	uR    Возвращает схему конфигурации полей прокта z+rest/api/3/fieldconfigurationscheme/projectr   r   r   r   NZfieldConfigurationSchemer   r   )r   r   rG   r   rV   r   rT  r   r   r   &get_project_field_configuration_scheme  s    
z.JiraApi.get_project_field_configuration_schemec                 C   s"   d| }| j |dddid}|S )u   
        Получает бизнес-процесс как XML

        Args:
            name (str): название бизнес-процесса

        Returns:
            str: содержимое в формате XML
        zKsecure/admin/workflows/ViewWorkflowXml.jspa?workflowMode=live&workflowName=TZAcceptzapplication/xml)not_json_responserd   r   )r   r   rG   rV   r   r   r   get_workflow_as_xml  s    

zJiraApi.get_workflow_as_xmlc                 C   s   d}|  |S )u   
        Получает cloudId для Jira
        https://developer.atlassian.com/cloud/jira/software/rest/intro/#base-url-differences

        Returns:
            dict: результат ответа
        z_edge/tenant_infor   )r   rG   r   r   r   get_cloud_id  s    zJiraApi.get_cloud_id)r   c                 C   s    d| }ddi}| j ||dS )u   
        Получает информацию о схеме бизнес-процессов проекта

        Args:
            project_key (str): Ключ проекта

        Returns:
            dict: результат ответа
        z$rest/projectconfig/1/workflowscheme/ZoriginalTr   r   )r   r   rG   r   r   r   r   get_project_workflow_scheme  s    

z#JiraApi.get_project_workflow_scheme)cloud_idr   issue_type_idsc                    s   d| d}ddi}g }|D ]}| ||d qd|i}| j|||d}	|	d }
|	d	 }|D ]8}|d D ]* tt fd
d|
d}|rj | qjq^|S )u  
        Получает информацию бизнес-процессов
        для проектов с упрощенной конфигурацией (simplified) 

        Args:
            cloud_id (str): ID облака
            project_id (int): ID проекта
            issue_type_ids (list): список ID типов задачи

        Returns:
            list: данные бизнес-процессов
        z-gateway/api/jira/project-configuration/query/z/2/workflowZuseTransitionLinksFormatT)rO  r   ZprojectAndIssueTypes)r   rQ   statuses	workflowsc                    s   | d  d kS )NZstatusReferencer   )sZworkflow_statusr   r   r   0  r   z:JiraApi.get_simplified_project_workflows.<locals>.<lambda>N)r"  r~   r   r   r   )r   r[  r   r\  rG   r   Zproject_and_issue_typesZissue_type_idrQ   rV   r]  r^  ZworkflowrK   r   r`  r    get_simplified_project_workflows  s2    
z(JiraApi.get_simplified_project_workflows)r   c              
   C   sf   d}d|i}z| j ||dd}W n> tjk
r^ } z|jjdkrJW Y dS |W 5 d}~X Y nX |jS )u   
        Возвращает значение настройки текущего пользователя

        Args:
            key (str): ключ настройки

        Returns:
            _type_: значение
        rest/api/2/mypreferencesr   T)r   r  r   N)r@   rZ   r   rV   rY   r?  )r   r   rG   r   rV   r   r   r   r   r   :  s    


zJiraApi.get_mypreferences)r   rQ   c                 C   s"   d}d|i}| j ||i |d dS )u   
        Устанавливает значение настройки текущего пользователя

        Args:
            key (str): ключ настройки
            data (str): значение настройки
        rb  r   )rQ   r}   r   N)Zput)r   r   rQ   rG   r   r   r   r   r   T  s    zJiraApi.set_mypreferencesc                 C   s:   d}d|i}z| j ||d W n tjk
r4   Y nX dS )u   
        Удаляет значение настройки текущего пользователя

        Args:
            key (str): ключ настройки
        rb  r   r   N)deleterZ   r   )r   r   rG   r   r   r   r   r   f  s    zJiraApi.delete_mypreferences)workflow_scheme_idc                 C   s   d| }|  |S )u   
        Получает информацию о схеме бизнес-процессов

        Args:
            workflow_scheme_id (str): id схемы бизнес-процесса
        zrest/api/2/workflowscheme/r   )r   rd  rG   r   r   r   get_workflow_schemeu  s    
zJiraApi.get_workflow_scheme)r   r   r#  r   r   c           	      C   sx   |  d}i }|r||d< |r&||d< |r2||d< |r>||d< | jrb|  }d|d  |d< | j||d}|d S )	u,  
        Возвращает список разрешений, указывающий, какие разрешения есть у пользователя.
        Подробную информацию о разрешениях пользователя можно получить
        в глобальном контексте, контексте проекта или задачи

        Args:
            project_id (str, optional): ID проекта. Defaults to None.
            project_key (str, optional): Ключ проекта. Defaults to None.
            issue_id (str, optional): ID задачи. Defaults to None.
            issue_key (str, optional): Ключ задачи. Defaults to None.

        Returns:
            dict: Информация о разрешениях
        Zmypermissionsr   r>  ZissueIdZissueKeyr   permissionsr   )r   r:   Zget_all_permissionsr   r   r@   )	r   r   r   r#  r   rG   r   Zall_permissionsrf  r   r   r   get_permissions  s    
zJiraApi.get_permissionsc                 C   s   d}ddd}|r||d< ndddd	d
g}d ||d< g }| j||d}|dsVq||d  |d rnq|d  |d 7  < q<|S )u2  
        Получает список всех фильтров из Jira Cloud

        Args:
            expand (str, optional): параметры для получения расширенных данных. Defaults to None.

        Returns:
            list: список фильтров
        zrest/api/2/filter/searchr   r   r   r   r   ownerdescriptionZsharePermissionsZeditPermissionsr   r   r   r   r   r   )r   r@   r   )r   r   rG   r   Zexpand_listfiltersrV   r   r   r   get_all_filters_cloud  s,    


zJiraApi.get_all_filters_cloudc                 C   s   ddl m} d}dddddd}g }| j||| jdd}||d	}|jd
dd}|sVq|jdddidD ]"}|d}	| |	}
||
 qh|jdddsq|d  d7  < q$|S )u  
        Получает список всех фильтров из Jira Server / Data Center

        В Jira Server / Data Center нет метода API для получения списка фильтров.
        Но можно получить ID фильтров через парсинг HTML-разметки страницы фильтров
        из раздела Администрирование > Система > Фильтры,
        и затем по ID фильтре получить информацию о нем через API.

        При указании параметров "decorator" и "contentOnly" в запросе, можно получить
        только необходимую часть HTML с таблицей списка фильтров и указателем пагинации.
        В таблице выводится по 20 фильтров на странице.

        Returns:
            list: список фильтров
        r   )BeautifulSoupz+secure/admin/filters/ViewSharedFilters.jspaZnoneTr   )Z	decoratorZcontentOnlyZ
sortColumnZsortAscendingpagingOffset)r   rd   rW  ZlxmltableZ	mf_browse)r   trzdata-filter-id)Zattrsaz	icon-next)class_rm  r$   )Zbs4rl  r@   r   findZfind_allZ
get_filterr"  )r   rl  rG   r   rj  rV   ZsoupZtable_resultsZfilter_dataZ	filter_idZfilter_r   r   r   get_all_filters_server  s6    


zJiraApi.get_all_filters_serverc                 C   s   | j r|  S |  S dS )u8   
        Получает все фильтры
        N)r:   rk  rs  r_   r   r   r   get_all_filters  s    zJiraApi.get_all_filtersc                 #   s   t   }| d}| dd t   }|r<| d| n
| d |D ]2 tt fdd|d}|rv|d  d<  V  qJdS )uw   
        Получает все решения

        Yields:
            dict: данные решения
        r   r   c                    s   | d  d kS r   r   )ruZ
resolutionr   r   r   +  r   z-JiraApi.get_all_resolutions.<locals>.<lambda>Nr   r   )rB   get_all_resolutionsr   r   r   r   r   )r   Zresolutionsr   Zresolutions_untranslatedZresolution_untranslatedrH   rv  r   rw    s$    




zJiraApi.get_all_resolutionsc                 #   s   t   }| d}| dd t   }|r<| d| n
| d |D ]2 t fdd|D d}|rv|d  d<  V  qJdS )uw   
        Получает все статусы

        Yields:
            dict: данные статуса
        r   r   c                 3   s"   | ]}|d   d  kr|V  qdS r   Nr   .0ZuntranslatedrK   r   r   	<genexpr>O  s   z+JiraApi.get_all_statuses.<locals>.<genexpr>Nr   r   )rB   r   r   r   r   r   )r   r]  r   untranslated_statusesuntranslated_statusrH   r{  r   r   5  s"    




zJiraApi.get_all_statusesc                 #   s   t  |}| d}| dd t  |}|r@| d| n
| d |D ]d t fdd|D d}|r d D ]4|d }tfdd|D d}|rv|d d	< qv V  qNdS )
u   
        Получает все статусы проекта по типам задач

        Yields:
            dict: данные статуса
        r   r   c                 3   s"   | ]}|d   d  kr|V  qdS rx  r   ry  r   r   r   r|  s  s   z1JiraApi.get_status_for_project.<locals>.<genexpr>Nr]  c                 3   s"   | ]}|d   d  kr|V  qdS rx  r   ry  r{  r   r   r|  ~  s   r   r   )rB   r   r   r   r   r   )r   r   r   r   Zuntranslated_issue_typesZuntranslated_issue_typer}  r~  rH   )r   rK   r   r   Z  s4    



zJiraApi.get_status_for_project)NNrb   )r   r   NNNN)Nr   )r   )NNN)Nr   )r   N)r   )r   r   )Nr   r   )N)NN)N)N)r   N)r   r   NNN)r   NNN)NN)r   r7   )NN)F)NNNN)N)fr   r   r   r   rC   rD   rN   rW   r\   r`   rT   r{   r^   r   r   r   r   r   r5   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rC  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.  r1  r3  r6  r8  r:  rA  rF  rL  rN  rP  rQ  rR  rS  rU  rV  rX  rY  rZ  ra  r   r   r   re  rg  rk  rs  rt  rw  r   r   __classcell__r   r   rH   r   r6   \   s   #   
6      
;
   %

)$
!
*



      

	(A"
2    ()7	%%r6   )r   r    r!   r"   )r   typingr   r   r   r   r2   	functoolsr   timer   rZ   Zrequests.adaptersr	   Zurllib3.util.retryr
   r8   r   pathlibr   Z	atlassianr   Zcmf.includeZloggingZFilterr   Z	getLoggerrn   Z	addFilterr5   r6   r   r   r   r   <module>   s    

;