
    @eC                     >   d Z ddlZddlZ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	m
Z
mZ ddlmZ ddlmZ ddlmZ ddlmZmZ ddlmZ dd	lmZmZmZmZmZmZ dd
lmZ ddl Z ddl!m"Z" ddl#m$Z$m%Z%m&Z&m'Z'm(Z( ddl)m*Z*m+Z+m,Z,m-Z- de.de.de.de/fdZ0 G d de+          Z1dS )OExtension manager using pip as package manager and PyPi.org as packages source.    N)datetime	timedeltatimezone)partial)groupby)Path)CalledProcessErrorrun)TarFile)AnyCallableDictListOptionalTuple)ZipFile)
alru_cache)CFloatCIntUnicodeconfigobserve)ActionResultExtensionManagerExtensionManagerMetadataExtensionPackagenamelatest_versionbase_urlreturnc                 
  K   t           j                                        }|                    |d|  d| dz   ddi           d {V }t	          j        |j                                      d          fddD             S )	N//jsonContent-Typeapplication/jsonheadersinfoc                 <    i | ]}|                     |          S  )get).0kdatas     :lib/python3.11/site-packages/jupyterlab/extensions/pypi.py
<dictcomp>z+_fetch_package_metadata.<locals>.<dictcomp>+   s5        	
488A;;      )	authorbugtrack_urldocs_url	home_pagelicensepackage_urlproject_urlproject_urlssummary)tornado
httpclientAsyncHTTPClientfetchjsonloadsbodyr,   )r   r   r    http_clientresponser/   s        @r0   _fetch_package_metadatarE   "   s      $4466K &&3t33n3333!34 '        H :hm$$((00D   

   r2   c                       e Zd ZdZ eddd          Z eddd          Z eddd	          Z	 ed
dd          Z
	 	 	 d&dee         dee         deej                 ddf fdZedefd            Zdedee         fdZdedefdZdededefdZ ed          d             Zdedededeeeef         ee         f         fdZ de!eeef                  fd Z"d'd!ed"ee         de#fd#Z$dede#fd$Z%d!edefd%Z& xZ'S )(PyPIExtensionManagerr   zhttps://pypi.org/pypiTzThe base URL of PyPI index.)r   helpg     r@z.PyPI extensions list cache timeout in seconds.i  z$The cache size for package metadata.g      ?zGThrottling time in seconds between PyPI requests using the XML-RPC API.Napp_optionsext_optionsparentr!   c                    t                                          |||           t          | _        |                     d| j        i           t
          j                                        | _        t          j
                            | j                  | _        t          j        t           j                  t%          | j        dz            z
  | _        d | _        | j                            d| j         d           d S )Nnewtz)\(?secondsz%Extensions list will be fetched from .)super__init__rE   $_observe_package_metadata_cache_sizepackage_metadata_cache_sizer<   r=   r>   _http_clientxmlrpcclientServerProxyr    _rpc_clientr   nowr   utcr   cache_timeout5_PyPIExtensionManager__last_all_packages_request_time)_PyPIExtensionManager__all_packages_cachelogdebug)selfrI   rJ   rK   	__class__s       r0   rU   zPyPIExtensionManager.__init__N   s     	k6:::'>$115$:Z2[\\\#.>>@@!=44T]CC080M0M0MPY&-Q
 Q
 Q
 1
- %)!Ot}OOOPPPPPr2   c                 8    t          ddt          j                  S )zExtension manager metadata.PyPIT)r   sysprefixrd   s    r0   metadatazPyPIExtensionManager.metadatab   s     (cjAAAr2   pkgc                 b  K   	 t           j                                        }|                    | j        d| dz   ddi           d{V }t          j        |j                                      d          }t          j
        |                    d                    S # t          $ r Y dS w xY w)	zReturn the latest available version for a given extension.

        Args:
            pkg: The extension to search for
        Returns:
            The latest available version
        r#   r$   r%   r&   r'   Nr)   version)r<   r=   r>   r?   r    r@   rA   rB   r,   r   get_semver_version	Exception)rd   rl   rC   rD   r/   s        r0   get_latest_versionz'PyPIExtensionManager.get_latest_versiong   s      
	L!,<<>>K(..C.');< /        H :hm,,0088D $6txx	7J7JKKK  	 	 	44	s   A5B   
B.-B.	extensionc                     |j         .|j         }|d         dk    r|                     |d                   S |                     |j                  S )a  Normalize extension name.

        Extension have multiple parts, npm package, Python package,...
        Sub-classes may override this method to ensure the name of
        an extension from the service provider and the local installed
        listing is matching.

        Args:
            extension: The extension metadata
        Returns:
            The normalized name
        NpackageManagerpythonpackageName)install_normalize_namer   )rd   rr   install_metadatas      r0   get_normalized_namez(PyPIExtensionManager.get_normalized_name{   sW     ((0 01X==++,<],KLLL##IN333r2   	recursivefnc                 n  K   t           j        j                                        }	  |j        d|g|R   d{V }n# t
          j        j        $ r}|j        dk    r|j	        
                    d          rd}t          j        d|j	                  }|$t          |                    d          pd          }| j                            d| d	           t#          j        || j        z  d
z              d{V  |r | j        d|g|R   d{V }n |j        d|g|R   d{V }Y d}~nd}~ww xY w|S )a/  Throttle XMLRPC API request

        Args:
            recursive: Whether to call the throttling recursively once or not.
            fn: API method to call
            *args: API method arguments
        Returns:
            Result of the method
        Raises:
            xmlrpc.client.Fault
        NizHTTPTooManyRequests:rP   z!Limit may reset in (\d+) seconds.   1z>HTTPTooManyRequests - Perform next call to PyPI XMLRPC API in zs.g{Gz?F)r<   ioloopIOLoopcurrentrun_in_executorrY   rZ   Fault	faultCodefaultString
startswithresearchintgrouprb   r)   asynciosleeprpc_request_throttling&_PyPIExtensionManager__throttleRequest)	rd   r{   r|   argscurrent_loopr/   errdelaymatchs	            r0   __throttleRequestz&PyPIExtensionManager.__throttleRequest   s      ~,4466	O55dBFFFFFFFFFFDD}" 	O 	O 	O}&&3?+E+E&, ,& 	"FXX$A 5#66E^UZ^^^   mED,G$G$$NOOOOOOOOO O!7!7r!ID!I!I!IIIIIIIDD!=!=dB!N!N!N!NNNNNNND	O" s   = D2CD--D2rW   c                 X     t          |d                   t                    | _        d S )NrM   )maxsize)r   rE   )rd   changes     r0   rV   z9PyPIExtensionManager._observe_package_metadata_cache_size   s*    'Hz&-'H'H'HI`'a'a$$$r2   querypageper_pagec                 Z  K   |                                   d{V }i }d}|dz
  |z  }||z  }t          t          fd|          d           D ]\  }	}
|dz  }||k     s||k    rt          |
          d         \  }}|                     |	|| j                   d{V }|                     |	          }|                    d          pi }|                    d          }|                    d          p|                    d	          }|                    d
          p|                    d          }|                    d          p|                    d          }|p/|                    d          p|                    d          p|p|p|}t          ||                    d          ||                    d          |                    d          t          j
        |          d|||                    d          |          ||<   |t          j        |dz   |z            fS )aw  List the available extensions.

        Note:
            This will list the packages based on the classifier
                Framework :: Jupyter :: JupyterLab :: Extensions :: Prebuilt

            Then it filters it with the query

            We do not try to check if they are compatible (version wise)

        Args:
            query: The search extension query
            page: The result page
            per_page: The number of results per page
        Returns:
            The available extensions in a mapping {name: metadata}
            The results last page; None if the manager does not support pagination
        Nr~   c                     | d         v S Nr   r+   )mr   s    r0   <lambda>z4PyPIExtensionManager.list_packages.<locals>.<lambda>   s    EQqTM r2   c                     | d         S r   r+   )es    r0   r   z4PyPIExtensionManager.list_packages.<locals>.<lambda>   s    WXYZW[ r2   r:   zSource Coder6   Homepager5   Documentationr4   zBug Trackerr9   r8   r;   r3   r7   prebuilt)r   descriptionhomepage_urlr3   r7   r   pkg_typebug_tracker_urldocumentation_urlpackage_manager_urlrepository_url))_PyPIExtensionManager__get_all_extensionsr   filterlistrE   r    rx   r,   r   r   ro   mathceil)rd   r   r   r   matches
extensionscounter	min_index	max_indexr   r   _r   r/   normalized_namepackage_urls
source_urlr   r   r   best_guess_home_urls    `                   r0   list_packagesz"PyPIExtensionManager.list_packages   ss     * 1133333333
AX)	8O	"6*A*A*A*A7#K#K^^\\ &	 &	KD%qLG""g&:&: $UBA~55dNDMZZZZZZZZD"22488O88N339rL%))-88J88K00PL4D4DZ4P4PL $ 4 4 Y8H8H8Y8Y"hh~66Y,:J:J=:Y:YO  #88M**#88M**# %# 	#
 #   +;$ HHY//0xx))++/B>RR# /"3$(HH]$;$;)+ + +J'' 49gkX%=>>>>r2   c                 t  K   | j         >t          j        t          j                  | j        t          | j                  z   k    rk| j        	                    d           | 
                    d| j        j        dg           d {V | _         t          j        t          j                  | _        | j         S )NrN   rQ   z?Requesting PyPI.org RPC API for prebuilt JupyterLab extensions.Tz<Framework :: Jupyter :: JupyterLab :: Extensions :: Prebuilt)ra   r   r]   r   r^   r`   r   r_   rb   rc   r   r\   browserj   s    r0   __get_all_extensionsz)PyPIExtensionManager.__get_all_extensions   s      $,|1
 1
 1
1IdFX4Y4Y4YY1Z 1Z HNN\]]].2.D.D 'OP/ / ) ) ) ) ) )D%
 5=LHL4Q4Q4QD1((r2   r   rn   c                 6  K   t           j        j                                        }t          j        dddddddg}||                     d	|            n|                               i }	 |                                }|                    d
d           |                    d
d           |                    d
d           |	                    dt          t          |dd                     d{V }t          j        |j                            d                    }t!          t#          t%          fd|                    dg                                         }| j                            dt          j        |           d           ni# t.          $ r.}	| j                            d|	j         |	           Y d}	~	n6d}	~	wt2          $ r&}
| j                            d|
           Y d}
~
nd}
~
ww xY w| j                            dd                    |           d           |	                    dt          t          |d                     d{V }| j                            d|j                    | j                            d|j                            d                      |j                            d          }|j        dk    r| j                            d|            d}	 |                    di                               d           }|| j                            |           d{V }|                    d!          rt?          tA          j!        |j"                            5 }t%          d" |#                                          D ]Bt          j        |$                                        }|                    d#          }| nCddd           n# 1 swxY w Y   n|                    d$          rtK          tA          j!        |j"                            5 }t%          d% |&                                          D ]Ut          j'        |(                    |)                                                  }|                    d#          }| nVddd           n# 1 swxY w Y   n3# t2          $ r&}	| j                            d&|	           Y d}	~	nd}	~	ww xY wd'g}|H|                    d(i           }d)|v r|                    d)           d*|v r|                    d*           tU          d+|,          S | j        +                    d- d.|j         d/|            tU          d0|1          S )2a  Install the required extension.

        Note:
            If the user must be notified with a message (like asking to restart the
            server), the result should be
            {"status": "warning", "message": "<explanation for the user>"}

        Args:
            name: The extension name
            version: The version to install; default None (i.e. the latest possible)
        Returns:
            The action result
        -mpiprw   
--no-inputz--quietz--progress-baroffNz==r   z	--dry-runz--report-T)capture_outputcheckutf-8c                     |                      di                                d                              dd          k    S )Nrk   r   r   r   )r,   replace)pr   s    r0   r   z.PyPIExtensionManager.install.<locals>.<lambda>5  s8    !%%
B"7"7";";F"C"Ct||TWY\G]G]"] r2   zActions to be executed by pip rS   z!Fail to get installation report: exc_infoz Fail to get installation report.Executing ' 'r   return code: stdout: r   stderr: download_infourlz.whlc                 2    t          |           j        dk    S Nzpackage.jsonr	   r   fs    r0   r   z.PyPIExtensionManager.install.<locals>.<lambda>U      $q'',.*H r2   
jupyterlabztar.gzc                 2    t          |           j        dk    S r   r   r   s    r0   r   z.PyPIExtensionManager.install.<locals>.<lambda>_  r   r2   zFail to get package.json.frontend	discoverykernelserverokstatusneeds_restartFailed to installed : code 
errorr   message),r<   r   r   r   rh   
executableappendcopyinsertr   r   r   r@   rA   stdoutdecodenextiterr   r,   rb   rc   dumpsr
   stderrrp   join
returncoderX   r?   endswithr   ioBytesIOrB   namelistreadr   getnamesloadextractfile	getmemberr   r   )rd   r   rn   r   cmdline
pkg_actiontmp_cmdresultaction_infor   r   r   jlab_metadatadownload_urlrD   wheelr/   sdist
follow_upsr   s    `                  r0   rw   zPyPIExtensionManager.install  s      ~,4466 N	
 NNd//g//0000NN4   
	XllnnGNN2{+++NN2z***NN2s###'77gc74tLLL       F *V]%9%9'%B%BCCK]]]]#	266   J HNNVDJ{<S<SVVVWWWW " 	W 	W 	WHNNIqxIITUNVVVVVVVV 	M 	M 	MHNN=NLLLLLLLL	M
 	9SXXg%6%6999:::#33'#wt<<<
 
 
 
 
 
 
 
 	:v'8::;;;A&-"6"6w"?"?AABBB$$W--!!HNN-e--... MH$.NN?B$G$G$K$KE$R$R+%)%6%<%<\%J%JJJJJJJH#,,V44 *$RZ%>%>?? *5(. H H % 0 0) ) * * (,z%**T2B2B'C'C040F0F#0#<$)E $=* * * * * * * * * * * * * * * &..x88 	*$RZ%>%>?? *5(. H H % 0 0) ) * * (,y1B1B5??SWCXCX1Y1Y'Z'Z040F0F#0#<$)E $=* * * * * * * * * * * * * * *  H H H:QGGGGGGGGH J ()--k2>>	y((%%h///y((%%h///t:FFFFHNN[$[[v?P[[TY[[\\\w>>>>s   0C5F 
G< $G		G<G77G<>BS A'O8,S 8O<<S ?O< ?S ?A:S9S S		S S	S 
TS<<Tc           	        K   t           j        j                                        }t          j        ddddd|g}d}	 |                                }|                    d           |                    dt          t          |d                     d{V }t          d	 t          d
 |j                            d                                                              }t          d t          t           |                    D ]A}t#          j        |                                          }	|	                    d          }| nBn3# t*          $ r&}
| j                            d|
           Y d}
~
nd}
~
ww xY w| j                            dd                    |           d           |                    dt          t          |d                     d{V }| j                            d|j                    | j                            d|j                            d                      |j                            d          }|j        dk    r{| j                            d|            dg}|H|                    di           }d|v r|                    d           d|v r|                    d           t9          d|          S | j                            d| d|j         d|            t9          d |!          S )"aj  Uninstall the required extension.

        Note:
            If the user must be notified with a message (like asking to restart the
            server), the result should be
            {"status": "warning", "message": "<explanation for the user>"}

        Args:
            extension: The extension name
        Returns:
            The action result
        r   r   	uninstallz--yesr   NTr   c                 ,    |                      d          S r   )r   lines    r0   r   z0PyPIExtensionManager.uninstall.<locals>.<lambda>  s    T]]>:: r2   c                 *    |                                  S N)stripr  s    r0   r   z0PyPIExtensionManager.uninstall.<locals>.<lambda>  s     r2   r   c                     | j         dk    S r   )r   r   s    r0   r   z0PyPIExtensionManager.uninstall.<locals>.<lambda>  s    !&N2 r2   r   z%Fail to list files to be uninstalled.r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r<   r   r   r   rh   r   r   remover   r   r   r   mapr   r   
splitlinesr	   r@   rA   
read_bytesr,   rp   rb   rc   r   r   r   r   r   r   )rd   rr   r   r  r  r  r  linesfilepathr/   r   r   r  r   s                 r0   r  zPyPIExtensionManager.uninstallx  sk      ~,4466N
 	PllnnGNN7###'77gc74@@@       F ::--v}/C/CG/L/L/W/W/Y/YZZ E #22D%      z("5"5"7"788 $ 6 6 ,E - 	P 	P 	PHNNBQNOOOOOOOO	P 	9SXXg%6%6999:::#33'#wt<<<
 
 
 
 
 
 
 
 	:v'8::;;;A&-"6"6w"?"?AABBB$$W--!!HNN-e--...J ()--k2>>	y((%%h///y((%%h///t:FFFFHNN`)``FDU``Y^``aaaw>>>>s   D
E 
E7E22E7c                 ~    |                     dd                               dd                               dd          S )zNormalize extension name.

        Remove `@` from npm scope and replace `/` and `_` by `-`.

        Args:
            name: Extension name
        Returns:
            Normalized name
        @ r#   r   r   )r   )rd   r   s     r0   rx   z$PyPIExtensionManager._normalize_name  s8     ||C$$,,S#66>>sCHHHr2   )NNNr  )(__name__
__module____qualname____doc__r   r    r   r_   r   rW   r   r   dictr   ConfigurablerU   propertyr   rk   strrq   r   rz   boolr   r   r   r   rV   r   r   r   r   r   r   r   rw   r  rx   __classcell__)re   s   @r0   rG   rG   ;   s       YYw.tB_```HF$T  M #'$T F# # # $VV   '+&*04	Q Qd^Q d^Q ,-	Q
 
Q Q Q Q Q Q( B2 B B B XBLC LHSM L L L L(4-= 4# 4 4 4 4&   8  s        D W*++b b ,+bD?D? #D?/2D?	tC))*HSM9	:D? D? D? D?L)DsCx,A ) ) ) )n? n?# n? n? n? n? n? n?`G? G? G? G? G? G?R
IC 
IC 
I 
I 
I 
I 
I 
I 
I 
Ir2   rG   )2r"  r   r   r@   r   r   rh   xmlrpc.clientrY   r   r   r   	functoolsr   	itertoolsr   pathlibr	   
subprocessr
   r   tarfiler   typingr   r   r   r   r   r   zipfiler   r<   	async_lrur   	traitletsr   r   r   r   r   jupyterlab.extensions.managerr   r   r   r   r&  r#  rE   rG   r+   r2   r0   <module>r4     s   V U  				   				 



     2 2 2 2 2 2 2 2 2 2                   . . . . . . . .       = = = = = = = = = = = = = = = =                    < < < < < < < < < < < < < <            S C TX    2PI PI PI PI PI+ PI PI PI PI PIr2   