
    ic                         d dl mZmZ d dlT d dl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 e                    d	          Z G d
 de          ZdS )    )urlparse	parse_qsl)*N)contextmanager)HTTPAdapter)Retry)
Confluence)ApiNotFoundErrorzatlassian.rest_clientc                       e Zd ZdZddej        de                                ddf fd	Zd Z	e
d9d            Zd Zd	 Zd
 Z fdZd:dZd; fd	Zd<dZd Zd Zd Z fdZ fdZ	 	 d=dededededef
dZd9d ededefd!Zd>defd"Zd9d#Zd9d$Z d9d%Z!d;d&Z"ddd' fd(
Z#d?d)ed*e$fd+Z% fd,Z&d- Z'd9ded.ededefd/Z(	 	 	 	 d@ded2ededed3ededefd4Z)d5 Z*defd6Z+d7 Z,d8 Z- xZ.S )AConfluenceApiuK    Подключение по API к учетной записи Confluence NTFc	                    |                     d          r|nd| }|                    d          s|dz  }|r|}nd } t                      j        |f|||||||d|	 |                                  t
          j        j        | _        dt          |          j	         | _
        d | _        |                                  d S )Nhttphttps:///)usernamepasswordtimeout
verify_sslsessioncloudtokenzCONFLUENCE:COOKIE:)
startswithendswithsuper__init___set_session_retriesAPPREDIS_DBredisr   netloc	redis_keycookies_dict_init_cookies)selfurlr   r   r   r   r   r   r   kwargs	__class__s             ./modules/confluence/api.pyr   zConfluenceApi.__init__   s     ^^F++Acc1AC1A1A||C   	3JC 	HHE
	
!
	
 
	
 
	
 
	
 
	
 	!!###\'
Dhsmm.BDD     c                     t          t          j        t          j        t          j        d          }t	          |          }| j                            d|           | j                            d|           dS )u   
        Конфигурирует стратегию повторных попыток
        и ассоциирует ее с сессией
           )totalstatusstatus_forcelistbackoff_factormax_retrieshttp://r   N)r   configIMPORT_REQUEST_RETRY_TOTAL!IMPORT_REQUEST_RETRY_STATUS_CODESr   _sessionmount)r$   retrieshttp_adapters      r(   r   z"ConfluenceApi._set_session_retries:   su    
 34#E	
 
 
 #w777I|444J55555r)   c              #   n  K   i }t          d          }dD ]?}| j        j                            |          ||<   | j                            ||           @| j        }|r|| _        	 | V  |                                D ]C\  }}|r| j                            ||           #| j        j                            |d           D|r	|| _        dS dS # |                                D ]C\  }}|r| j                            ||           #| j        j                            |d           D|r|| _        w xY w)u<   
        Временно отключает Retry.
        r   r0   )r2   r   N)r   r6   adaptersgetr7   r   itemspop)r$   r   old_adaptersno_retry_adapterprefixold_timeoutadapters          r(   without_retryzConfluenceApi.without_retryI   s     
 &1555 . 	: 	:F#'=#9#=#=f#E#EL M(89999l 	#"DL	+JJJ $0#5#5#7#7 = = =M''8888M*..vt<<<<  +*+ + $0#5#5#7#7 = = =M''8888M*..vt<<<<  +*****s   (C A#D4c                 &   | j                             | j                  }|ro	 t          j        |          }| j        j                            |           | j        j                                        | _	        dS # t          j
        $ r Y dS w xY wdS )u  
        Добавляет cookie в сессию при инициализации,
        что бы не выполнять повторную авторизацию, если cookie еще действуют.
        При недействительных cookie, выполнится авторизация,
        а cookie обновятся в сессии и кеше
        N)r   r<   r!   pickleloadsr6   cookiesupdateget_dictr"   PickleError)r$   cookies_picklerH   s      r(   r#   zConfluenceApi._init_cookiesi   s     77 	 ,~66%,,W555$(M$9$B$B$D$D!!!%   	 	s   AA; ;BBc                     t          j        | j        j                  }| j                            | j        |d           dS )u   
        Сохраняет cookie в кеш (Redis) для последующего использования
        без выполнения повторной авторизации
        i`T  )exN)rF   dumpsr6   rH   r   setr!   )r$   rL   s     r(   _save_cookieszConfluenceApi._save_cookiesy   s:    
  dm&;<<
t~~+FFFFFr)   c                     | j         j                                        }| j        |k    r|| _        |                                  dS dS )u   
        Проверяет изменение cookie и обновляет их в кеше при необходимости
        N)r6   rH   rJ   r"   rQ   )r$   current_cookies_dicts     r(   _check_cookieszConfluenceApi._check_cookies   sR      $}4==?? 444 4D      54r)   c                 b     t                      j        |i |}|                                  |S N)r   requestrT   )r$   argsr&   responser'   s       r(   rW   zConfluenceApi.request   s4    "577?D3F33r)      c           	         | j         }|p| j        }|                     d||           | j                            |d||| j        | j                  5 }t                              d| d|j	         d|j
                    |                                 t          |d          5 }|                    |	          D ]}|                    |           	 d
d
d
           n# 1 swxY w Y   d
d
d
           d
S # 1 swxY w Y   d
S )us  
        Скачивает файл

        Args:
            download_url (_type_): url файла для скачивания
            save_path (_type_): путь для сохранения файла
            timeout (_type_, optional): Таймаут. Defaults to None.
            chunk_size (_type_, optional): _description_. Defaults to 64*1024.
        GET)methodr%   headersT)streamr^   r   verifyproxiesz
HTTP: GET z ->  zwb+)
chunk_sizeN)no_check_headersr   log_curl_debugr6   r<   r   ra   loggerdebugstatus_codereasonraise_for_statusopeniter_contentwrite)	r$   download_url	save_pathr   rc   r^   resfchunks	            r(   download_filezConfluenceApi.download_file   s    ')T\5lGLLL]?L  
 
 	# LLVlVVVV#*VVWWW  """i'' #1 ---DD # #EGGENNNN## # # # # # # # # # # # # # #	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	#s7   AC9%/C!C9!C%	%C9(C%	)C99C= C=c              #      K   |r|d         }|d         |d         z
  }nd}d}	 t                                          |||          }|r|                    d          sdS |d         D ]}|V  |rdS ||z  }V)u   
        Получим все пространства из Confluence

        :return: Список всех пространств
        r   r+   d   T)
space_typestartlimitresultsN)r   get_all_spacesr<   )r$   rv   slicerw   rx   rp   rowr'   s          r(   rz   zConfluenceApi.get_all_spaces   s        	!HE!HuQx'EEEE
	''((JeSX(YYC cggi00 9~  				 UNE
	r)   r   ru   archivedpagec              #   `   K   	 |                      |||||          }|sdS |E d{V  ||z  },)ud   
        Получает архивные документы из пространства
        T)content_typeN)get_all_pages_from_space)r$   spacerw   rx   r-   r   rp   s          r(    get_all_pages_from_space_archivez.ConfluenceApi.get_all_pages_from_space_archive   sV      	//ueVZf/ggC NNNNNNNUNE	r)   c              #   \  K   t          dd          }|||<   d}	 	 |                     ||          }|                    d          sd S |d         E d {V  |dxx         |d	         z  cc<   n=# t          j        $ r+}t                              d
| d|            Y d }~d S d }~ww xY w)Nr      rw   rx   zrest/api/user/memberofTparamsry   rw   rx   uL   Не удалось получить группы пользователя "". )dictr<   requests	HTTPErrorrf   warning)r$   keyvaluer   r%   rp   http_errs          r(   user_member_ofzConfluenceApi.user_member_of   s     AR(((s&		hhs6h22wwy)) Fy>)))))))w6'?2%      Cns   C   C  yA   C   C  D  D  D		s   ,A0 $A0 0B*? B%%B*c                     	 |                      |          }nE# t          $ r8}t                              d| d|            t	                      }Y d }~nd }~ww xY w|S )NuL   Не удалось получить данные пользователя "r   )get_mobile_parameters	Exceptionrf   r   r   )r$   r   infoerrors       r(   get_user_detailzConfluenceApi.get_user_detail   sz    	--h77DD 	 	 	NN~jr~~w|~~66DDDDDD	 s    
A.AAc              #     K   | j         rt          dddd          }	 |                     d|          }|d	         sd S |d	         D ]}|d
         |                     d                   }                    fd|                                D                        d |                     dd                   D             d<   V  |dxx         |d         z  cc<   t          dddd          }	  | j        di |}|d	         sd S |d	         D ]}|d
         d         dk    rt          	                    d           /|d
         |                     |d
         d                   }                    fd|                                D                        d |                     dd                   D             d<   V  |dxx         |d         z  cc<   )Nr   r   zuser=""zoperations,personalSpace)rw   rx   cqlexpandTzrest/api/search/userr   ry   user	accountIdr   c              3   :   K   | ]\  }}|vs|d k    ||fV  dS  N .0kvr   s      r(   	<genexpr>z.ConfluenceApi.get_all_users.<locals>.<genexpr>   D        =  =41a#$D==AGG "#A4;GGG =  =r)   c                     g | ]}|S r   r   r   gs     r(   
<listcomp>z/ConfluenceApi.get_all_users.<locals>.<listcomp>   s    %e%e%eAa%e%e%er)   groupsrw   rx   z	type=userz&user.operations,user.status,user.emailr   recovery_adminu   В вашем Confluence включен режим восстановления! Не оставляйте Confluence в режиме восстановления и не используйте учетную запись recovery_admin!c              3   :   K   | ]\  }}|vs|d k    ||fV  dS r   r   r   s      r(   r   z.ConfluenceApi.get_all_users.<locals>.<genexpr>  r   r)   c                     g | ]}|S r   r   r   s     r(   r   z/ConfluenceApi.get_all_users.<locals>.<listcomp>  s    %c%c%cAa%c%c%cr)   r   )
r   r   r<   r   rI   r=   r   r   rf   r   )r$   r   rp   r|   	user_infor   s        @r(   get_all_userszConfluenceApi.get_all_users   s     :  	3C]^^^F3hh5fhEE9~ Fy>  Cv;D $ 4 4d;>O 4 P PIKK  =  =  =  =9??3D3D  =  =  = = = =%e%e1D1D[RVWbRc1d1d%e%e%eDNJJJJw6'?23 EmnnnF3dh((((9~ Fy>  C6{:.2BBB (t u u u !v;D $ 4 4c&k*>U 4 V VIKK  =  =  =  =9??3D3D  =  =  = = = =%c%c1D1DZQUV`Qa1b1b%c%c%cDNJJJJw6'?2!3r)   c              #      K   t          dd          }	  t                      j        di |}|sd S |E d {V  |dxx         |d         z  cc<   <)Nr   r   r   Trw   rx   r   )r   r   get_all_groups)r$   r   rp   r'   s      r(   r   zConfluenceApi.get_all_groups  sw      AR(((	/(%''(22622C NNNNNNN7OOOvg.OOO	/r)   c              #      K   t          dd|d          }	  t                      j        di |}|sd S |D ]}|V  |dxx         |d         z  cc<   =)	Nr   r   zoperations,status)rw   rx   
group_namer   Trw   rx   r   )r   r   get_group_members)r$   r   r   rp   r|   r'   s        r(   r   zConfluenceApi.get_group_members  s      ARJGZ[[[	/+%''+55f55C   				7OOOvg.OOO	/r)   r   
content_idrw   rx   r   returnc              #     K   d| d}i }|t          |          |d<   |t          |          |d<   |||d<   |sd|d<   	 |                     ||
          }|d         D ]?}	|r7|	d         dk    r+d |                     |	d         ||          D             |	d<   |	V  @|d         }
|
                    d          }|sdS t          |          }t	          t          |j                            }|d         |d<   |                    d          r|                    d          |d<   |                    d          r|                    d          |d<   )u  
        Получает все комментарии к документу

        Args:
            content_id (str): ID страницы(документа) в Confluence
            expand (str): Cвойства элемента, которые нужно расширить, например, expand='body,version,history'
            children (bool): Создать иерархическую структуру с дочерними элементами

        Yields:
            Iterator[list]: элемент
        rest/api/content/z/child/commentNrw   rx   r   alldepthTr   ry   r-   currentc                     g | ]}|S r   r   )r   objs     r(   r   z3ConfluenceApi.get_page_comments.<locals>.<listcomp>;  s*     *d *d *d## *d *d *dr)   id)r   childrenr   _linksnextcursor)intr<   get_page_commentsr   r   r   query)r$   r   rw   rx   r   r   r%   r   rp   resultlinksnext_
next_parser   s                 r(   r   zConfluenceApi.get_page_comments  s      =*<<<!%jjF7O!%jjF7O%F8 	$#F7O	3((3v(..Ci.   dx 0I = =*d *d9O9OPVW[P\W]Ya :P :c :c *d *d *dF:& MEIIf%%E !%J:#34455E#GnF7Oyy"" 7#(99X#6#6x yy   3!&6!2!2v-	3r)   	key_spacec              #     K   d}d}	 |                      |d|||d          }|d         D ]}|d         |d	         |d
         dg ddid}|                    d          rmd |                     |d         d          D             }|                    d            ||d         d         d<   t	          |          |d         d         d<   |V  |d         sdS ||z  })ui  
        Получим все документы из корня пространства.

        :param key_space: Идентификатор пространства.
        :param expand: Дополнительные данные по документам.

        :return: Соответствие id документа и его данных.
        r   2   Trootr~   )r   r   rw   rx   r   ry   r   titletypery   size)r   r   r   r   r   c                     g | ]}|S r   r   r   childs     r(   r   z;ConfluenceApi.get_root_pages_from_space.<locals>.<listcomp>j  s    ```%```r)   Fdetailedc                     | d         S Npositionr   ps    r(   <lambda>z9ConfluenceApi.get_root_pages_from_space.<locals>.<lambda>k  s
    * r)   r   r   N)get_space_contentr<   get_childrensortlen)	r$   r   r   rw   rx   rp   r|   datar   s	            r(   get_root_pages_from_spacez'ConfluenceApi.get_root_pages_from_spaceO  s@      	((&W\di;A ) C CC9~  d) \K')$%! !!	
 
 77:&& E``43D3DSYY^3D3_3_```HMM&=&=M>>>:BD$V,Y77:8}}D$V,V4



y> UNE/	r)   c              #      K   t          |||          }	  | j        |fi |}|r|                    d          sd S |d         D ]}|V  |dxx         |d         z  cc<   M)N)rw   rx   r   Try   rw   rx   )r   get_attachments_from_contentr<   )r$   page_idrw   rx   r   r   rp   r|   s           r(   get_all_attachmentz ConfluenceApi.get_all_attachments  s      Ev>>>	/3$3GFFvFFC cggi00 9~  				7OOOvg.OOO	/r)   c                 T    	 |                      ||          S # t          $ r Y d S w xY w)N)userkeyr   )get_user_details_by_userkeyr
   )r$   r   r   s      r(   get_user_info_by_keyz"ConfluenceApi.get_user_info_by_key~  sB    	33GF3SSS 	 	 	44	s    
''c                 B    | j         r|                     ||          S d S )N)r   )r   get_user_details_by_accountid)r$   r   r   s      r(   get_user_infozConfluenceApi.get_user_info  s2    : 	P55i5OOO	P 	Pr)   c                     	 | j         r3|                     |          }|                     |d         |          S |                     ||          S # t          $ r Y d S w xY w)Nr   r   )	accountidr   )r   r   )r   get_account_idr   get_user_details_by_usernamer
   )r$   r   r   r   s       r(   get_user_info_by_usernamez'ConfluenceApi.get_user_info_by_username  s    	z f**H*==99DDU^d9eee44hv4VVV 	 	 	44	s   9A A 
A! A!c                 f    d}|rd|i}nd|i}|                      ||          }|d         d         S )Nzrest/api/user/bulk/migrationr   r   r   ry   r   r<   )r$   r   r   r%   r   rp   s         r(   r   zConfluenceApi.get_account_id  sI    , 	* (+FF)Fhhs6h**9~a  r)   )r   with_childrenc                2    t                      j        |g|R i |}|s%|d         |d         |d         |d         d         d}|rOd |                     ||          D             }|                    d	 
           d|t	          |          di|d<   |S )u  
        Возвращает данные контента

        Николай1: expand='children.page' имеет лимит 25 элементов, запрашиваем детей вручную
        https://jira.atlassian.com/browse/CONFSERVER-52558?src=confmacro
        get_page_child_by_type - без лимита падает, т.к. в коде думает что урлы не относительные
        поэтому лимиты считаем руками
        Bспользуется в двух местах, поэтому вынес в глобальный API

        Args:
            page_id (str, int): ID контента
            detailed (bool, optional): Вернуть подробные данные. Defaults to True.
            with_children (bool, optional): Запросить дочерние объекты. Defaults to False.

        Returns:
            page (dict): данные контента
        r   r   r   
extensionsr   r   r   r   r   c                     g | ]}|S r   r   r   s     r(   r   z0ConfluenceApi.get_page_by_id.<locals>.<listcomp>  s    YYY%YYYr)   r   c                     | d         S r   r   r   s    r(   r   z.ConfluenceApi.get_page_by_id.<locals>.<lambda>  s
    * r)   r   r~   r   r   )r   get_page_by_idr   r   r   )	r$   r   r   r   rX   r&   r~   r   r'   s	           r(   r   zConfluenceApi.get_page_by_id  s    $ &uww%g?????? 	4jgV .z:	 D  	YY4+<+<Wx+<+X+XYYYHMM55M666'MM  D r)   typesr   c              #      K   || j         sdgnddg}|D ]b}d}d}	 |                     ||||          }|sn?|r	|E d{V  n.|D ]+}|d         |d	         |d
         |d         d         d}	|	V  ,||z  }[cdS )u  
        Возвращает дочерние объекты(контент)

        Args:
            parent_id (_type_): ID родительского контента
            types (list, optional): Список типов дочерних объектов. Defaults to None.
            detailed (bool, optional): Вернуть подробные данные. Defaults to True.

        Yields:
            dict: данные дочернего объекта(контента)
        Nr~   folderr   r   T)r   rw   rx   r   r   r   r   r   r   )r   get_page_child_by_type)
r$   	parent_idr   r   type_rw   rx   ry   r   r   s
             r(   r   zConfluenceApi.get_children  s       =$(JFVHHVX4FE 	 	EEE55	 6     
#&&&&&&&&&") # #"(,%+G_$*6N(.|(<Z(H	    #



) 	 	r)   c              #      K   t          t                                          |                                                    d d         E d {V  d S )N)listr    get_all_restrictions_for_contentvalues)r$   r   r'   s     r(   r  z.ConfluenceApi.get_all_restrictions_for_content  sW      @@IIPPRRSSTWUWTWXXXXXXXXXXr)   c              #      K   t          dd|          }	  | j        d	i |}|d         E d {V  |dxx         |d         z  cc<   |d         |d         k     rd S F)
Nr   ru   )rw   rx   r   Try   rw   rx   r   r   )r   get_page_labels)r$   r   r   rp   s       r(   get_all_page_labelsz!ConfluenceApi.get_all_page_labels  s      AS':::	&$&0000C9~%%%%%%%7OOOvg.OOO6{VG_,,	r)   version_numberc                 r    | j         r	d| d| }nd| d| }i }|||d<   |                     ||          S )u  
        Получает определенную версию документа

        Args:
            content_id (str): ID страницы(документа) в Confluence
            version_number (int): номер версии страницы(документа)
            expand (str): Cвойства элемента, которые нужно расширить, например, expand='body,version,history'

        Return:
            dict: данные версии документа
        r   z	/version/rest/experimental/content/Nr   r   )r   r<   )r$   r   r  r   r%   r   s         r(   get_page_versionzConfluenceApi.get_page_version  sf     : 	UKjKK>KKCCTzTTNTTC%F8xxFx+++r)      r  current_versionlast_versionsc           	   #     K   |sdS | j         rd| d}nd| d}i }|t          |          |d<   |t          |          |d<   |||d<   d}		 	 |                     ||
          }
|
d         }|                    d          }|
d         D ]*}|	dz  }	d|cxk    r|	k     rn nd} n|d         dz
  }|V  +n|#  t          |dd          D ]a}|	dz  }	d|cxk    r|	k     rn n nI	 |                     |||          V  4# t
          $ r!}t          d| d|           V  Y d}~Zd}~ww xY wd}Y nxY w|sdS t          |          }t          t          |j	                            }|d         |d<   |                    d          r|                    d          |d<   |                    d          r|                    d          |d<   )u  
        Получает версии страницы (историю документа)
        При большом количестве данных в версиях, limit > 5 может не работать,
        зависает, либо падает с ошибкой по таймауту.
        Получение версий списком может упасть с ошибкой 500 "Internal Server Error", если в ответе будет кривая версия.
        При получении ошибки при запросе списков, пытаемся получить версии по одной.

        Args:
            content_id (str): ID страницы(документа) в Confluence
            current_version (int): номер текущй версии страницы(документа)
            last_versions (int): колчество послених версий для получения, при "-1" - получение всех версий
            expand (str): Cвойства элемента, которые нужно расширить, например, expand='body,version,history'

        Yields:
            Iterator[list]: элемент
        Nr   z/versionr  rw   rx   r   r   Tr   r   r   ry   r+   Fnumberr  u   версия z. r   )
r   r   r<   ranger  r   r   r   r   r   )r$   r   r  rw   rx   r  r   r%   r   version_countrp   r   r   versionr  excr   r   s                     r(   get_page_versionszConfluenceApi.get_page_versions  s     2  	4: 	D:j:::CCCzCCCC!%jjF7O!%jjF7O%F8'	3hhs6h22H		&))"9~ " "G!Q&MM9999M99999 %&-h&7!&;O!MMMM&+OQ&C&C Q QN!Q&MM9999M99999Q"33JPVWWWWWW$ Q Q Q'(O(O(O#(O(OPPPPPPPPPPQ  !%J:#34455E#GnF7Oyy"" 7#(99X#6#6x yy   3!&6!2!2vO'	3s7   A'B8 8,D1%C?>D1?
D*	D% D1%D**D1c                    | j         r-|                     |d          }|                    dg           S |dk    rd| d}|                     |          S d}ddd	|gd
}|                     ||                              dg           S )Npermissions)	space_keyr   
   zrest/api/space/z/permissionsz!rpc/json-rpc/confluenceservice-v2z2.0getSpacePermissionSets   )jsonrpcr]   r   r   )r   r   )r   	get_spacer<   post)r$   r  r  
space_datar%   r   s         r(   get_space_permissionsz#ConfluenceApi.get_space_permissionsb  s    : 	?)MRRJ>>-444]];I;;;C88C==  6C 2$+	 D 99St9,,002>>>r)   c                 0    d}|                      |          S )u   
        Получает связи с другими системами

        Return:
            applinks (dict): данные связей с другими системами
        zrest/applinks/3.0/applinksr   r$   r%   s     r(   get_applinkszConfluenceApi.get_applinkst  s     ,xx}}r)   c                 0    d}|                      |          S )u7   Получить информацию о системеzrest/applinks/1.0/manifestr   r'  s     r(   get_system_infozConfluenceApi.get_system_info  s    *xx}}r)   c                 0    d}|                      |          S )u^   
        Возвращает данные о текущем пользователе
        zrest/api/user/currentr   r'  s     r(   get_current_userzConfluenceApi.get_current_user  s     &xx}}r)   rV   )NrZ   )NN)r   ru   r}   r~   )r   r   NT)r   r   N)NT)r   r  r  N)/__name__
__module____qualname____doc__r3   !IMPORT_CONFLUENCE_REQUEST_TIMEOUTcmfutilrequests_sessionr   r   r   rD   r#   rQ   rT   rW   rs   rz   r   r   r   r   r   r   strr   r  r   r   r   r   r   r   r   r   r   boolr   r  r  r  r  r%  r(  r*  r,  __classcell__)r'   s   @r(   r   r      s       UU 8((**' ' ' ' ' 'R6 6 6 + + + ^+>   G G G! ! !    
# # # #:     0	 	 	 	     !3 !3 !3F/ / / / // / / / / 8:7;/3 /3C /3!$/314/3"%/3@D/3 /3 /3 /3b" "3 " "t " " " "H	/ 	/S 	/ 	/ 	/ 	/   P P P P   ! ! ! ! 7;% % % % % % % %N' 'T 'D ' ' ' 'RY Y Y Y Y  , ,3 , ,S ,\` , , , ,6 Q3 Q3Q3 Q3 	Q3
 Q3 Q3 Q3 
Q3 Q3 Q3 Q3f? ? ?$	d 	 	 	 	  
      r)   r   )urllib.parser   r   cmf.includerF   r   
contextlibr   requests.adaptersr   urllib3.util.retryr   	atlassianr	   atlassian.errorsr
   logging	getLoggerrf   r   r   r)   r(   <module>r@     s    , , , , , , , ,       % % % % % % ) ) ) ) ) ) $ $ $ $ $ $             - - - - - -			2	3	3z	 z	 z	 z	 z	J z	 z	 z	 z	 z	r)   