o
    ^iV                  
   @   sD  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	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 ddlmZmZ dd	lmZ dd
lmZmZmZ ddl m!Z! ddl"m#Z# ddl$Z$ddl%Z%ddl&m'Z' ddl(m)Z) ddl*m+Z+m,Z,m-Z-m.Z.m/Z/ ddl0m1Z1 ddl2m3Z3m4Z4m5Z5m6Z6 G dd dej7j8Z9e:dZ;e:dpe:dpe;Z<e:dpe:dpe<pe;Z=e)e$j1Z>i Z?dZ@e<re!e<ZAeAjBCd\ZDZEZFe>e)dkrde$jGe<de$jGe=ddiZ?nde<e=diZ?e9 Z@e@HeDeF de$jId eJd!eJd"eJd#eKf
d$d%ZLG d&d' d'e4ZMdS )(OExtension manager using pip as package manager and PyPi.org as packages source.    N)datetime	timedeltatimezone)partial)groupby)environ)Path)CalledProcessErrorrun)TarFile)AnyCallableOptional)urlparse)ZipFile)
alru_cache)Version)CFloatCIntUnicodeconfigobserve)__version__)ActionResultExtensionManagerExtensionManagerMetadataExtensionPackagec                   @   s   e Zd ZdddZdd ZdS )ProxiedTransportNc                 C   s   ||f| _ || _d S N)proxyproxy_headers)selfhostportheaders r&   U/home/ubuntu/hpml_nyu/venv/lib/python3.10/site-packages/jupyterlab/extensions/pypi.py	set_proxy*   s   

zProxiedTransport.set_proxyc                 C   s,   t jj| j }|j|| jd ||f| _|S )Nr%   )httpclientHTTPConnectionr    
set_tunnelr!   _connection)r"   r#   
connectionr&   r&   r'   make_connection.   s   
z ProxiedTransport.make_connection)NN)__name__
__module____qualname__r(   r0   r&   r&   r&   r'   r   )   s    
r   	ALL_PROXY
http_proxy
HTTP_PROXYhttps_proxyHTTPS_PROXY:z0.28.0mounts)r    )zhttp://zhttps://proxiesr+   namelatest_versionbase_urlreturnc                    s^   | j |d| d| d ddidI d H }|jdk r-t|j d  fdd	d
D S i S )N//jsonContent-Typeapplication/jsonr)     infoc                    s   i | ]}|  |qS r&   )get).0kdatar&   r'   
<dictcomp>h   s    
z+_fetch_package_metadata.<locals>.<dictcomp>)	authorbugtrack_urldocs_url	home_pagelicensepackage_urlproject_urlproject_urlssummary)rF   status_codejsonloadstext)r+   r<   r=   r>   responser&   rI   r'   _fetch_package_metadataZ   s   

rZ   c                       sh  e Zd ZdZeddddZeddddZeddd	dZ	ed
dddZ
			d1dee dee deej ddf fddZedefddZdedee fddZdedefddZdededefddZedd d! Zd"ed#ed$edeeeef ee f fd%d&Zde eeef  fd'd(Z!d2d)ed*ee de"fd+d,Z#dede"fd-d.Z$d)edefd/d0Z%  Z&S )3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                    s   t  ||| tjd	i t| _tt| j| _| d| j	i t
jj| jtd| _tjtjdt| jd d | _d | _| jd| j d trV| jdtj  d S d S )
Nnew)	transporttz)\(?secondsz%Extensions list will be fetched from .z=Extensions will be fetched using proxy, proxy host and port: r&   )super__init__httpxAsyncClient_httpx_client_args_httpx_clientr   rZ   $_observe_package_metadata_cache_sizepackage_metadata_cache_sizexmlrpcr+   ServerProxyr>   xmlrpc_transport_override_rpc_clientr   nowr   utcr   cache_timeout5_PyPIExtensionManager__last_all_packages_request_time)_PyPIExtensionManager__all_packages_cachelogdebugrE   r    )r"   r]   r^   r_   	__class__r&   r'   ri      s"   

zPyPIExtensionManager.__init__c                 C   s   t ddtjS )zExtension manager metadata.PyPIT)r   sysprefixr"   r&   r&   r'   metadata   s   zPyPIExtensionManager.metadatapkgc                    s   z2| j j| jd| d ddidI dH }|jdk r&t|jdi }n| jd	| W dS W n
 t	y=   Y dS w t
|d
dpHdS )zReturn the latest available version for a given extension.

        Args:
            pkg: The extension to search for
        Returns:
            The latest available version
        r@   rA   rB   rC   r)   NrD   rE   z+Failed to get package information on PyPI; version )rm   rF   r>   rU   rV   rW   contentry   rz   	Exceptionr   get_semver_version)r"   r   rY   rJ   r&   r&   r'   get_latest_version   s   
z'PyPIExtensionManager.get_latest_version	extensionc                 C   s6   |j dur|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<   )r"   r   install_metadatar&   r&   r'   get_normalized_name   s
   
z(PyPIExtensionManager.get_normalized_name	recursivefnc           	   
      s.  t jj }z|jd|g|R  I dH }W |S  tjjy } zq|jdkr}|j	
drd}td|j	}|durBt|dp@d}| jd| d	 t|| j d
 I dH  |ri| jd|g|R  I dH }n"|jd|g|R  I dH }W Y d}~|S W Y d}~|S W Y d}~|S W Y d}~|S d}~ww )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:rd   z!Limit may reset in (\d+) seconds.   1z>HTTPTooManyRequests - Perform next call to PyPI XMLRPC API in zs.g{Gz?F)tornadoioloopIOLoopcurrentrun_in_executorrp   r+   Fault	faultCodefaultString
startswithresearchintgroupry   rE   asynciosleeprpc_request_throttling&_PyPIExtensionManager__throttleRequest)	r"   r   r   argscurrent_looprJ   errdelaymatchr&   r&   r'   __throttleRequest   s:   
$


z&PyPIExtensionManager.__throttleRequestro   c                 C   s    t |d dtt| j| _d S )Nr`   )maxsize)r   r   rZ   rm   )r"   changer&   r&   r'   rn      s   

z9PyPIExtensionManager._observe_package_metadata_cache_sizequerypageper_pagec                    s  |   I dH }i }g }tt fdd|dd D ]\}}t|d \}	}
| ||
| jI dH }| |}|dp<i }|d}|dpK|d	}|d
pU|d}|dp_|d}|pq|dpq|dpq|pq|pq|}t||d||d|dt	
|
d|||d|d}d}dd |||fD }ddg}|D ]!|v rd} ntfdddD rd} n	dv rd } nq|||f qt|d!d d"}|d | }|| }||| }|D ]	\}	}|||j< qtt|| }||fS )#a  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 and sorts by organization priority:
            1. Project Jupyter (@jupyter)
            2. JupyterLab Community (@jupyterlab-contrib)
            3. Others

        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
        Nc                    s    | d v S Nr   r&   )m)r   r&   r'   <lambda>  s    z4PyPIExtensionManager.list_packages.<locals>.<lambda>c                 S   s   | d S r   r&   )er&   r&   r'   r         rS   zSource CoderO   HomepagerN   DocumentationrM   zBug TrackerrR   rQ   rT   rL   rP   prebuilt)r<   descriptionhomepage_urlrL   rP   r=   pkg_typebug_tracker_urldocumentation_urlpackage_manager_urlrepository_url   c                 S   s   g | ]
}|rt | qS r&   )strlower)rG   urlr&   r&   r'   
<listcomp>>  s
    
z6PyPIExtensionManager.list_packages.<locals>.<listcomp>z-https://github.com/jupyterlab/jupyterlab_apodz0https://github.com/jupyterlab/extension-examples   c                 3   s    | ]}| v V  qd S r   r&   )rG   org)r   r&   r'   	<genexpr>J  s
    
z5PyPIExtensionManager.list_packages.<locals>.<genexpr>)zgithub.com/jupyter/zjupyter.orgzgithub.com/jupyterlab/r   zgithub.com/jupyterlab-contrib/   c                 S   s   | d | d j fS )Nr   r   r<   )xr&   r&   r'   r   V  s    )key))_PyPIExtensionManager__get_all_extensionsr   filterlistrZ   r>   r   rF   r   r   r   anyappendsortedr<   mathceillen)r"   r   r   r   matches
extensionsall_matchesr<   r   _r=   rJ   normalized_namepackage_urls
source_urlr   r   r   best_guess_home_urlr   priorityurls_to_checkexcludesorted_matches	start_idxend_idxpage_matchestotal_pagesr&   )r   r   r'   list_packages   s   $

	z"PyPIExtensionManager.list_packagesc                    sj   | j d u stjtjd| jt| jd kr2| j	d | 
d| jjdgI d H | _ tjtjd| _| j S )Nrb   re   z?Requesting PyPI.org RPC API for prebuilt JupyterLab extensions.Tz<Framework :: Jupyter :: JupyterLab :: Extensions :: Prebuilt)rx   r   rt   r   ru   rw   r   rv   ry   rz   r   rs   browser   r&   r&   r'   __get_all_extensionsd  s   z)PyPIExtensionManager.__get_all_extensionsr<   r   c                    s  t jj }t ?}tjd|dd$}|dt  |	  t
jddddd	d
dd|jg
}|dur@|  d|  n|  i }z?| }|dd |dd |dd |dtt|dddI dH }	t|	jd}
tt fdd|
dg }W n7 ty } z| jjd|j |d W Y d}~n+d}~w ty } z| jjd|d W Y d}~nd}~ww | jdt|
 d | jdd | d |dtt|dd I dH }	| jd!|	j!  | jd"|	jd  |	jd}|	j!d#kr| jd$|  d}z|d%i d&}|dur| j"|I dH }|j#d'k r|$d(rst%t&'|j()}td)d |) D ]}t|*|}|d*}|dur` nqJW d   n	1 smw   Y  nP|$d+rt+t&'|j(,}td,d |, D ]}t-|.|/|}|d*}|dur nqW d   n	1 sw   Y  n| jd-| d.| W n ty } z| jjd/|d W Y d}~nd}~ww d0g}|dur|d1i }d2|v r|d2 d3|v r|d3 t0d4|d5W  d   W  d   S | j1d6  d7|	j! d8|  t0d9|d:W  d   W  d   S 1 s>w   Y  W d   dS 1 sOw   Y  dS );a  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
        zw+F)modedirdeletezjupyterlab==-mpipr   
--no-inputz--quietz--progress-baroffz--constraintNz==r   z	--dry-runz--report-T)capture_outputcheckutf-8c                    s   |  di  d ddkS )Nr   r<   r   r   )rF   replace)pr   r&   r'   r     s    z.PyPIExtensionManager.install.<locals>.<lambda>z!Fail to get installation report: exc_infoz Fail to get installation report.zActions to be executed by pip rg   Executing ' 'r   return code: stdout: r   stderr: download_infor   rD   z.whlc                 S      t | jdkS Nzpackage.jsonr	   r<   fr&   r&   r'   r         
jupyterlabztar.gzc                 S   r   r  r  r  r&   r&   r'   r     r  zFailed to get 'z'; zFail to get package.json.frontend	discoverykernelserverokstatusneeds_restartzFailed to install : code 
errorr  message)2r   r   r   r   tempfileTemporaryDirectoryNamedTemporaryFilewriter   flushr~   
executabler<   r   copyinsertr   r   r   rV   rW   stdoutdecodenextr   rF   r
   ry   rz   stderrr   dumpsjoin
returncoderm   rU   endswithr   ioBytesIOr   namelistreadr   getnamesloadextractfile	getmemberr   r  )r"   r<   r   r   ve_dirfconstraintcmdline
pkg_actiontmp_cmdresultaction_infor   r   r  jlab_metadatadownload_urlrY   wheelfilenamerJ   sdist
follow_upsr  r&   r   r'   r   r  s   



$



	







 i
VzPyPIExtensionManager.installc              
      s  t jj }tjddddd|g}d}zJ| }|d |dt	t
|ddI dH }td	d
 tdd
 |jd }tdd
 tt|D ]}t| }	|	d}|dur[ nqGW n tyw }
 z| jjd|
d W Y d}
~
nd}
~
ww | jdd| d |dt	t
|ddI dH }| jd|j  | jd|jd  |jd}|jdkr| jd|  dg}|dur|di }d|v r|d d|v r|d td|dS | jd| d|j d |  td!|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                 S   s
   |  dS r  )r#  liner&   r&   r'   r        
 z0PyPIExtensionManager.uninstall.<locals>.<lambda>c                 S   s   |   S r   )stripr:  r&   r&   r'   r     r   r   c                 S   s
   | j dkS r  r   r  r&   r&   r'   r     r<  r  z%Fail to list files to be uninstalled.r   r   r   r   r   r   r   r   r  r  r	  r
  r  r  zFailed to installed r  r  r  r  )r   r   r   r   r~   r  r  remover   r   r   r   mapr  r  
splitlinesr	   rV   rW   
read_bytesrF   r   ry   rz   r!  r"  r  r   r   r  )r"   r   r   r.  r3  r0  r1  linesfilepathrJ   r   r  r8  r  r&   r&   r'   r9    sn   






 zPyPIExtensionManager.uninstallc                 C   s   | 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   )r   )r"   r<   r&   r&   r'   r   6  s   
z$PyPIExtensionManager._normalize_name)NNNr   )'r1   r2   r3   __doc__r   r>   r   rv   r   ro   r   r   dictr   Configurableri   propertyr   r   r   r   r   r   boolr   r   r   r   rn   r   tupler   r   r   r   r   r9  r   __classcell__r&   r&   r{   r'   r[   z   s\    "

f{Ir[   )NrE  r   http.clientr*   r$  rV   r   r   r~   r  xmlrpc.clientrp   r   r   r   	functoolsr   	itertoolsr   osr   pathlibr	   
subprocessr
   r   tarfiler   typingr   r   r   urllib.parser   zipfiler   rj   r   	async_lrur   packaging.versionr   	traitletsr   r   r   r   r   jupyterlab._versionr   jupyterlab.extensions.managerr   r   r   r   r+   	Transportr   rF   all_proxy_urlhttp_proxy_urlhttps_proxy_url_httpx_versionrl   rr   r5   netloc	partition
proxy_hostr   
proxy_portAsyncHTTPTransportr(   rk   r   rF  rZ   r[   r&   r&   r&   r'   <module>   s~   




 