
    yfd                         d dl Z d dlZd dlZd dlZd dlZddlmZ ddlm	Z	m
Z
 ddlmZmZmZmZmZmZmZmZ  G d de      Z G d	 d
e      Z G d de      Z G d de      Zy)    N   )InfoExtractor   )compat_urllib_parse_urlparsecompat_urlparse)bug_reports_messageExtractorError	get_firstint_or_noneOnDemandPagedListparse_qssrt_subtitles_timecodetraverse_objc                       e Zd ZdZi dddddddd	d
dddddddddddddddddddddd d!d"d#d$d%d&d'd(d)Zd-d+Zed,        Zy*).PanoptoBaseIEz:(?P<base_url>https?://[\w.-]+\.panopto.(?:com|eu)/Panopto)r   en-USr   zen-GBr   zes-MX   es-ES   zde-DE   zfr-FR   znl-NL   zth-TH   zzh-CN	   zzh-TW
   zko-KR   zja-JP   zru-RU   zpt-PT   zpl-PL   zen-AU   zda-DKzfi-FIzhu-HUznb-NOzsv-SEzit-IT)               Nc                 P    | j                   ||z   |f|r$t        j                  |      j                  d      nd |dddd|}|sy t	        |d      }|dk(  r| j                  d       |S |7d	|j                  d
       }	|rt        |	|d      | j                  |	|       |S )Nutf8application/json)acceptcontent-type)datafatalheaders	ErrorCoder   cookies)methodzPanopto said: ErrorMessageT)video_idexpected)r3   )	_download_jsonjsondumpsencoder   raise_login_requiredgetr	   report_warning)
selfbase_urlpathr3   r,   r-   kwargsresponse
error_codemsgs
             :/usr/lib/python3/dist-packages/yt_dlp/extractor/panopto.py	_call_apizPanoptoBaseIE._call_api6   s    &4&&tOXoOSDJJt,<,C,CF,KY],>Pb!cogmo !(K8
?%%Y%7  #"8<<#?"@AC$S8dKK##C(#;    c           	          t        j                  t        |       j                        j	                         D ci c]  \  }}|t        j                  |d           c}}S c c}}w )Nr   )r   r   r   fragmentitemsr6   loads)urlkvs      rC   _parse_fragmentzPanoptoBaseIE._parse_fragmentG   sM    0?0H0HIefiIjIsIs0t0z0z0|}14::ad##}}}s   #A!)NT)__name__
__module____qualname__BASE_URL_RE_SUB_LANG_MAPPINGrD   staticmethodrM    rE   rC   r   r      s   OK	7	7 	
7 	
7	
 	
7 	
7 	
7 	
7 	
7 	
7 	G 	G 	G 	G 	G  	G!" 	G#$ -2" ~ ~rE   r   c                   Z    e Zd Zej                  dz   Zdej                   dgZdddddd	d
g g deddddddddddddd
ddgdedddddddi dd d!d
d"d#d$d%gd&d'd(d)d*d+d,gd-g d.d/d0d1d2d3d4d5d6ed7d%d8d9d:d;dd<d=d
d>gg d?d@dAedBd>dCdDdEdFdGdHddIdJdKdLdMdNdddOdPdddQdRdgdSddTdKdUdVdWdXdYd
g dZdPd[d\d]gd^d_d`dadbdagdcdddegdcdfdegdgdhdUdUdidWdjdkd
dldmdgg dnd_dodpddPdqdrdsdtdUdUdidWdudUdvdwdUdvg	Ze	 fdx       Z
dy Zedz        Zed{        Zed|        Zd} Zd~ Zd Z xZS )	PanoptoIEz:/Pages/(Viewer|Embed)\.aspx.*(?:\?|&)id=(?P<id>[a-f0-9-]+)z<iframe[^>]+src=["\'](?P<url>z1/Pages/(Viewer|Embed|Sessions/List)\.aspx[^"\']+)zahttps://demo.hosted.panopto.com/Panopto/Pages/Viewer.aspx?id=26b3ae9e-4a48-4dcc-96ba-0befba08a0fbz$26b3ae9e-4a48-4dcc-96ba-0befba08a0fbz Panopto for Business - Use CasesiHbVz(re:https://demo\.hosted\.panopto\.com/.+20160328mp4gl
V@z$2db6b718-47a0-4b0b-9e17-ab0b00f42b1e$e4c6a2fc-1214-4ca0-8fb7-aef2e29ff63aShowcase Videos)idtitle	timestamp	thumbnailupload_dateextcastchaptersdurationaverage_ratinguploader_id
channel_idchannel)rJ   	info_dictzahttps://demo.hosted.panopto.com/Panopto/Pages/Viewer.aspx?id=ed01b077-c9e5-4c7b-b8ff-15fa306d7a59z$ed01b077-c9e5-4c7b-b8ff-15fa306d7a59z/Overcoming Top 4 Challenges of Enterprise VideozPanopto Supporti:dV20151206zcount:12z$a96d1a31-b4de-489b-9eee-b4a5b414372cz$md5:4391837802b3fc856dadf630c4b375d1gMb@z$9f3c1921-43bb-4bda-8b3a-b8d2f05a8546Webcasts)r[   r\   uploaderr]   r^   r_   r`   rb   ra   re   rd   descriptionrc   rf   rg   zhttps://howtovideos.hosted.panopto.com/Panopto/Pages/Viewer.aspx?randomparam=thisisnotreal&id=5fa74e93-3d87-4694-b60e-aaa4012214ed&advance=truer[   z$5fa74e93-3d87-4694-b60e-aaa4012214edr`   rc   g#~j0`@ra   zKathryn Kellyre   z$316a0a58-7fa2-4cd9-be1c-64270d284a56r]   i]tagsViewer
Enterpriserb   r_   20190930r^   z/re:https://howtovideos\.hosted\.panopto\.com/.+rl   z$md5:2d844aaa1b1a14ad0e2601a0993b431fr\   zGetting Started: View a Videord   rk   rf   z$fb93bc3c-6750-4b80-a05b-a921013735d3rg   zGetting Startedz]https://unisa.au.panopto.com/Panopto/Pages/Embed.aspx?id=9d9a0fa3-e99a-4ebd-a281-aac2017f4da4z$9d9a0fa3-e99a-4ebd-a281-aac2017f4da4zLTS CLI Scriptgffff@z$md5:ee5cf653919f55b72bce2dbcf829c9faz$b23e673f-c287-4cb1-8344-aae9005a69f8z$38377323-6a23-41e2-9ff6-a8e8004bf6f7iι]z*WW2 Vets Interview 3 Ronald Stanley Georgez%re:https://unisa\.au\.panopto\.com/.+zWorld War II Veteran Interviews20191030)r[   r`   ra   rb   rc   rl   rf   rd   re   rk   r]   r\   r^   rg   r_   zahttps://demo.hosted.panopto.com/Panopto/Pages/Viewer.aspx?id=a7f12f1d-3872-4310-84b0-f8d8ab15326bz$a7f12f1d-3872-4310-84b0-f8d8ab15326bmhtmliZVgVh@z)Cache Memory - CompSci 15-213, Lecture 1220151129r   z$md5:55e51d54233ddb0e6c2ed388ca73822czISR Videographerzcount:28)r[   r`   r]   rc   r\   rf   re   r_   rd   rk   rg   rl   ra   rb   r^   T)formatskip_download)rJ   rh   paramszjhttps://na-training-1.hosted.panopto.com/Panopto/Pages/Viewer.aspx?id=8285224a-9a2b-4957-84f2-acb0000c4ea9z$8285224a-9a2b-4957-84f2-acb0000c4ea9zCompany PolicyiC`zHuman ResourcesHumanResourcesg@z1re:https://na-training-1\.hosted\.panopto\.com/.+z$8e8ba0a3-424f-40df-a4f1-ab3a01375103zCait M.20210306srtz$md5:a3f4d25963fdeace838f327097c13265r`   r,   z$md5:57e9dad365fd0fbaf0468eac4949f189)r   r   )r[   r`   rb   r\   rd   r]   rg   rm   rc   r^   re   rk   r_   ra   	subtitles)writesubtitlesru   zjhttps://na-training-1.hosted.panopto.com/Panopto/Pages/Viewer.aspx?id=940cbd41-f616-4a45-b13e-aaf1000c915bz$940cbd41-f616-4a45-b13e-aaf1000c915bzcount:1zHR Benefits Review Meeting*i{]Zoomz$md5:04f90a9c2c68b7828144abfb170f0106gQy@z$b6ac04ad-38b8-4724-a004-a851004ea3df20191129)r[   r`   r{   r\   ra   rb   r]   r^   rg   rl   rk   rd   rc   re   r_   z^https://ucc.cloud.panopto.eu/Panopto/Pages/Viewer.aspx?id=0e8484a4-4ceb-4d98-a63f-ac0200b455cb)rJ   only_matchingzahttps://brown.hosted.panopto.com/Panopto/Pages/Embed.aspx?id=0b3ff73b-36a0-46c5-8455-aadf010a3638c                 P    t         j                  |      rdS t        |   |      S )NF)PanoptoPlaylistIEsuitablesuper)clsrJ   	__class__s     rC   r   zPanoptoIE.suitable   s%    )2237uRUW=Mc=RRrE   c                    t        |dt              }|j                  d      }t        |ddt              }|r|r|rdt	        j
                  t        j                  j                  t        j                  j                        j                                d}d	|d
|d|dz
  d
d
dd ||d
dgi}| j                  |dz   |dt        j                  |      j                  d      ddidd       y y y y )N)DeliveryDurationexpected_typeInvocationId)r   Streams.PublicIDF)get_allr   z/Date(z000)/streamRequestsr   r   r   )ClientTimeStampIDInvocationIDPlaybackSpeedSecondsListenedSecondsRejectedStartPositionStartReason
StopReasonStreamID	TimeStampUpdatesRejectedz)/Services/Analytics.svc/AddStreamRequestsr(   r+   r)   zMarking watchedzUnable to mark watched)r-   r,   r.   noteerrnote)r   floatr:   strcalendartimegmdtdatetimenowtimezoneutc	timetuple_download_webpager6   r7   r8   )	r<   r=   r3   delivery_inforc   invocation_id	stream_idtimestamp_strr,   s	            rC   _mark_watchedzPanoptoIE._mark_watched   s    /GW\]%)).9 0Xbgwz{	Y8$X__R[[__R[[__5U5_5_5a%b$cchiM +8(5)*+3a<+,)*'(&*$-%2+,#D$ ""FF$**T"2"9"9&"AN\nKo&0H # J) ,4Y=rE   c                     g }| xs g D ]f  }|j                  d      }t        |j                  d            t        |j                  d            }}|r||O|j                  |||z   |d       h |S )NCaptionTimer   )
start_timeend_timer\   )r:   r   append)
timestampsrb   r]   captionstartrc   s         rC   _extract_chapterszPanoptoIE._extract_chapters  s    #)r 		ImmI.G))--*?@+imm\fNgBh8Eemx/?OO#!H,  		 rE   c              #   :  K   i }|xs g D ]  }|j                  d      }|j                  d      |j                  d      }}|j                  d      dk(  r1|/|-|j                  dg       j                  | d| d| z   |d	       |j                  d
      |j                  d      |j                  d      }	}}d |||	fvs|j                  dg       j                  | d| d| d| d|	 z   |d	        |j                         D ]  \  }
}|
ddddd|d  y w)Nr   ObjectIdentifierObjectSequenceNumberEventTargetType
PowerPointslidesz/Pages/Viewer/Image.aspx?id=z&number=)rJ   rc   ObjectPublicIdentifier	SessionIDAbsoluteTimechapterz(/Pages/Viewer/Thumb.aspx?eventTargetPID=z&sessionPID=z&isPrimary=false&absoluteTime=rr   nonezabout:invalid)	format_idr`   protocolacodecvcodecrJ   	fragments)r:   
setdefaultr   rH   )r=   r   image_fragsr]   rc   obj_idobj_snobj_pid
session_idabs_timenamer   s               rC   _extract_mhtml_formatsz PanoptoIE._extract_mhtml_formats  s    #)r 	I }}Z0H&]]+=>	Nd@eFF}}./<?FDV[a[m&&x4;;#(DVHHU[T\&]] (= 
 -6MM:R,SU^UbUbcnUoqzq~q~  @N  rOZGGZ::&&y"5<<#(PQXPYYefpeqqy  {A  zB  B`  ai  `j  'k  k (> 	  +002 		OD)!#  && 		s   B>DADc                 >      fd}dj                   |             S )Nc            	   3      K   t              D ]b  \  } }|d   }|j                  d      }|r||z   }nt        | dz   df      xs d   }| dz    dt        |       dt        |       d|d     d y w)Nr   r   r   
z --> r   )	enumerater:   r   r   )iliner   rc   r   r,   deliverys        rC   
_gen_linesz'PanoptoIE._json2srt.<locals>._gen_lines<  s     $T? A4!&\
88J/)H4H+D1q5&/BZhzFZHQr"8"D!EUKabjKkJllnost}o~n  A  AAs   A2A5z

)join)r,   r   r   s   `` rC   	_json2srtzPanoptoIE._json2srt:  s    	A {{:<((rE   c                 L   i }|j                  d      xs g D ]  }| j                  |d|dd|dt        |      dd      }t        |t              s9|j                  | j                  j                  |      xs d	g       j                  d
| j                  ||      d        |S )NAvailableLanguages/Pages/Viewer/DeliveryInfo.aspxFz"Downloading captions JSON metadataTr6   )
deliveryIdgetCaptionslanguageresponseType)r-   r   querydefaultry   rz   )	r:   rD   r   
isinstancelistr   rR   r   r   )r<   r=   r3   r   r{   langr@   s          rC   _get_subtitleszPanoptoIE._get_subtitlesG  s    	LL!56<" 	D~~;XU9"*#' #D	$*	B & H h-  !7!7!;!;D!A!NYPRSZZx:\ 	  rE   c                    g }i }|xs g D ]  }g }|j                  d      }|j                  d      }	|r|j                  d|i       |	ra|j                  d      }
|
dv r9| j                  |	|      \  }}|j                  |       | j	                  ||      }n|j                  d|	i       |D ]&  }|j                  d|j                  d      i|       ( |j                  |        ||fS )NStreamHttpUrl	StreamUrlrJ   ViewerMediaFileTypeName)hlsformat_noteTag)r:   r   #_extract_m3u8_formats_and_subtitlesextend_merge_subtitlesupdate)r<   r3   streams
fmt_kwargsformatsr{   streamstream_formatshttp_stream_url
stream_url
media_typem3u8_formatsstream_subtitlesfmts                 rC   &_extract_streams_formats_and_subtitlesz0PanoptoIE._extract_streams_formats_and_subtitles[  s   	m 	+FN$jj9OK0J%%uo&>?#ZZ(AB
*595]5]^hjr5s2L"2")),7 $ 5 5iAQ RI"))z+  & 

!6::e#4  
 NN>*/	+2 	!!rE   c                 "   | j                  |      j                  dd      \  }}| j                  |d||ddddddddd		      }|d
   }t        |j	                  d            }|j	                  d      }| j                  ||j	                  d      d      \  }}	| j                  ||j	                  d      d      \  }
}||
z   }|j                  | j                  ||             | j                  |	|| j                  |||            }| j                  |||       i d|d|j	                  d      dt        |dd       d|r|dz
  nd d|j	                  d      d|d| dt        j                          z   d |j	                  d!      d"| j                  |      d#|j	                  d$      xs d d%|j	                  d&      d'|j	                  d(      d)t        |d*      d+|j	                  d,      d-t        |d.d/d01      d2|d3|S )4Nr=   r[   r    falsetruer6   )	r   invocationIdisLiveNotesrefreshAuthCookieisActiveBroadcast	isEditingisKollectiveAgentInstalledisEmbedr   )r   r   SessionStartTime
TimestampsPodcastStreamsPODCAST)r   r   i)
preferencer\   SessionNamera   )Contributors.DisplayNamec                     | xs d S )NrT   )xs    rC   <lambda>z)PanoptoIE._real_extract.<locals>.<lambda>  s    ijirnr rE   r   r]   l    Nk
 rc   r   r^   z2/Services/FrameGrabber.svc/FrameRedirect?objectId=z&mode=Delivery&random=rd   AverageRatingrb   rk   OwnerDisplayNamere   OwnerIdrl   SessionAbstractrm   )Tags.Contentrf   SessionGroupPublicIDrg   SessionGroupLongNameSessionGroupShortNameFr   r   r{   )_match_valid_urlgrouprD   r   r:   r   r   r   r   extract_subtitlesmark_watchedr   randomr   )r<   rJ   r=   r3   r   r   session_start_timer   podcast_formatspodcast_subtitlesstreams_formatsstreams_subtitlesr   r{   s                 rC   _real_extractzPanoptoIE._real_extracty  s   !2237==j$O(7& "&%+%,$.5" &
 ' 
 !,(6H)IJ\\,/
 .2-X-Xhll#34) .Y .M** .2-X-Xhll9-# .Y .?** "O3t228ZHI))0$2H2HS[]e2fh	 	(Hm<
(
X\\-0
 L+O_rs
 =O+k9UY	

 Z0
 &XYaXbbxy  zG  zG  zI  yJ  %K  K
 hll?;
 ..z:
 %78@D
 8<<	2
 8<<(9:
 L+CD
 (,,'=>
 |H.DF]glm
 w
  !
 	
rE   )rN   rO   rP   r   rQ   
_VALID_URL_EMBED_REGEXint_TESTSclassmethodr   r   rS   r   r   r   r   r   r)  __classcell__)r   s   @rC   rV   rV   L   sT   **-jjJ4]5N5N4O  PA  B  CL w<;'H)-"%ED,	
& w<J-'H)&*+E"%E.D%	
, e<u G )	
 E Z <0 B z O E 8 !# O D  ,!	
0 s<)*#ED"%E,'EE<)	
. w<'$DDE)"#-,E+->?&H" ")4@)	
. @<)"#',)*$QE%)"05?e(f'g05?e(f'gi$ *.E)	
. @<&6*+'Q!E-"#.E)$ *.E+
0 t!	

 w!	
q\F| S SJ:    8 
) 
)("<4
rE   rV   c                   ^    e Zd Zej                  dz   Zdddddddd	d
dddddgZd Zd Zy)r   z;/Pages/(Viewer|Embed)\.aspx.*(?:\?|&)pid=(?P<id>[a-f0-9-]+)zhttps://howtovideos.hosted.panopto.com/Panopto/Pages/Viewer.aspx?pid=f3b39fcf-882f-4849-93d6-a9f401236d36&id=5fa74e93-3d87-4694-b60e-aaa4012214ed&advance=truezFeatured Video Tutorialsz$f3b39fcf-882f-4849-93d6-a9f401236d36r   )r\   r[   rl   $   rJ   rh   playlist_mincountzbhttps://utsa.hosted.panopto.com/Panopto/Pages/Viewer.aspx?pid=e2900555-3ad4-4bdb-854d-ad2401686190z%Library Website Introduction Playlistz$e2900555-3ad4-4bdb-854d-ad2401686190z$md5:f958bca50a1cbda15fdc1e20d32b3ecbr   c              #     K   | j                  |d| d|      }|d   }|D ]  }|j                  d      dk7  r| j                  dt               z   d       6d	|j                  d
      |j                  d      |j                  d      |j                  d      |j                  d      t	        |d      t	        |d      d  y w)Nz/Api/SessionLists/z6?collections[0].maxCount=500&collections[0].name=itemsItemsTypeNameSessionz1Got an item in the playlist that is not a SessionT)	only_oncerJ   Id	ViewerUriNameDescriptionr   )Parentr;  )r=  r9  )_typer[   rJ   r\   rl   rc   rg   rf   )rD   r:   r;   r   r   )r<   r=   playlist_idsession_list_idsession_list_inforH   items          rC   _entrieszPanoptoPlaylistIE._entries  s      NN*?*;;qrtA "'* 	Dxx
#y0##$WZmZo$o{#  Ahhtnxx,&)#xx6 HHZ0'.@A*41AB	 			s   CCc                    | j                  |      j                  dd      \  }}t        t        |      d      }|rh| j	                  d      r@| j                  d|z         | j                  |d| z   t        j                         |      S | j                  d| d|        | j                  |d	| |      }| j                  | j                  |||d
         ||j                  d      |j                  d            S )Nr=   r[   
noplaylistz2Downloading just video %s because of --no-playlist/Pages/Viewer.aspx?id=)ie_keyr3   zDownloading playlist z+; add --no-playlist to just download video z/Api/Playlists/SessionListIdr;  r<  )r?  playlist_titleplaylist_description)r  r   r
   r   	get_param	to_screen
url_resultrV   rG  rD   playlist_resultrC  r:   )r<   rJ   r=   r?  r3   playlist_infos         rC   r)  zPanoptoPlaylistIE._real_extract  s    $ 5 5c : @ @T R+Xc]D1~~l+SV^^_x4J8*2U'U^g^n^n^p  |D  E  E!6{mCnownxyzx?;-1PR]^##MM(K1OP#M4E4Ef4M!.!2!2=!A $ C 	CrE   N)	rN   rO   rP   r   rQ   r*  r-  rC  r)  rT   rE   rC   r   r     sa    **-kkJ t3<!
 "$	
 x@<E
 "#	
F,(CrE   r   c                   t    e Zd Zej                  dz   ZdZddddddd	d
d
dddddddddgZd Zd Z	d Z
y)PanoptoListIEz/Pages/Sessions/List\.aspx   zthttps://demo.hosted.panopto.com/Panopto/Pages/Sessions/List.aspx#folderID=%22e4c6a2fc-1214-4ca0-8fb7-aef2e29ff63a%22rY   rZ   )r[   r\      r2  zVhttps://demo.hosted.panopto.com/Panopto/Pages/Sessions/List.aspx#view=2&maxResults=250panopto_listi,  zhttps://howtovideos.hosted.panopto.com/Panopto/Pages/Sessions/List.aspx?noredirect=true#folderID=%224b9de7ae-0080-4158-8496-a9ba01692c2e%22z$4b9de7ae-0080-4158-8496-a9ba01692c2ezVideo Tutorialsr   c           
   #   F  K   dddd||| j                   d}| j                  |d| d|dz    d|id	      }t        |d
g       D ]r  }|j                  d      }d||j                  d      t	        |ddd      xs |d| z   |j                  d      |j                  d      |j                  d      d t t        |dg       D ]R  }	|	j                  d      }
| j                  |d|
 dz   t        j                         |
|	j                  d             T y w)Nr   T)
sortColumngetFolderDataincludePlaylists)page
maxResultsz/Services/Data.svc/GetSessionsz page queryParametersFr,   r-   Results)r   
DeliveryIDrJ   r  	ViewerUrlEmbedUrlr  rF  r   
FolderNameFolderID)r>  r[   r\   rJ   rc   rg   rf   
Subfoldersr   z$/Pages/Sessions/List.aspx#folderID=""r;  )rG  r3   r\   )
_PAGE_SIZErD   r
   r:   r   rM  rQ  rG  )r<   r=   query_params
display_idrY  rv   r@   resultitem_idfolder	folder_ids              rC   _fetch_pagezPanoptoListIE._fetch_page  sv     ! $
 	

 //
 >>6:,fTTUXJ8W#V,E " ;  )R@ 	Fjj.GM2#FKUS  GX`e{  }D  |E  dF  YF"JJz2!::l3$jj4 	  ,C 	]F

4(I//A)ANN$++-	TZI[ " ] ]	]s   DD!c                 N    | j                  |d|d|id      }dt        |d      iS )Nz /Services/Data.svc/GetFolderInfofolderIDFr\  r\   r;  )rD   r
   )r<   r=   rk  r@   s       rC   _extract_folder_metadataz&PanoptoListIE._extract_folder_metadata1  s?    >>8)i( " 7 Yx0
 	
rE   c                    | j                  |      }|j                  d      }| j                  |      }|j                  d      d}}|j                  d      rd}|j                  d      s g d|d<   n|j                  d      rd	}n|r|}|j                  d
      }|r	|d| dz  }d||d}|r!|j	                  | j                  ||             t        t        j                  | j                  |||      | j                        |d<   |S )Nr=   rn  rT  isSubscriptionsPagesubscriptionssubscribableTypes)r   r   r   isSharedWithMesharedwithmer   z	: query "rd  playlist)r>  r[   r\   entries)r  r   rM   r:   r   ro  r   	functoolspartialrl  re  )	r<   rJ   mobjr=   rf  rk  rg  r   infos	            rC   r)  zPanoptoListIE._real_extract9  s   $$S)::j)++C0 , 0 0 <n:	12(J##$784=01./'J"J  )IeWA..J  

 KK55h	JK+d..,
SUYUdUdfY rE   N)rN   rO   rP   r   rQ   r*  re  r-  rl  ro  r)  rT   rE   rC   rQ  rQ    s    **-JJJJ J<* "%	
 l$' "%	
 a<* "#	
%F< ]D
rE   rQ  )r   r   r   rx  r6   r#  commonr   compatr   r   utilsr   r	   r
   r   r   r   r   r   r   rV   r   rQ  rT   rE   rC   <module>r     sf         !
	 	 	0~M 0~fa
 a
H;C ;C|jM jrE   