B
    ¿Á[ìú  ã               @   s  d Z ddlZddlm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 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 ddlmZ ddlmZmZmZmZ ddlmZ ddlmZ dd	l m!Z!m"Z"m#Z# dd
l$m%Z%m&Z&m'Z'm(Z( ddl)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/ ddl0m1Z1m2Z2 e 3d¡Z4e 5e	j 6e2dd¡¡Z7dd„ Z8dd„ Z9dd„ Z:dd„ Z;dpdd„Z<dqdd„Z=drdd„Z>dsdd „Z?dtd!d"„Z@dud#d$„ZAdvd%d&„ZBdwd(d)„ZCdxd*d+„ZDdyd-d.„ZEdzd/d0„ZFd{d1d2„ZGd|d3d4„ZHd}d5d6„ZId~d7d8„ZJdd9d:„ZKd€d;d<„ZLdd=d>„ZMd‚d?d@„ZNdƒdAdB„ZOdCdD„ ZPG dEdF„ dFeQƒZRdGdH„ ZSd„dIdJ„ZTdKdL„ ZUdMdN„ ZVdOdP„ ZWdQdR„ ZXdSdT„ ZYdUdV„ ZZdWdX„ Z[dYdZ„ Z\d[d\„ Z]g fd]d^„Z^d_d`„ Z_dadb„ Z`dcdd„ Zadedf„ Zbdgdh„ Zcdidj„ Zdd…dkdl„Zedmdn„ Zfegdokre?e2ƒ dS )†zJupyterLab command handleré    N)ÚLooseVersion)ÚTemporaryDirectory)ÚEvent)ÚRequestÚurlopenÚurljoinÚquote)ÚURLError)Újupyter_config_path)ÚwhichÚProcessÚWatchHelper)ÚGREEN_ENABLEDÚGREEN_OKÚRED_DISABLEDÚRED_Xé   )ÚRangeÚgteÚltÚlteÚgtÚmake_semver)Ú	YARN_PATHÚHEREz.*/index.out.jsz..Údev_modec              G   s   t  t j| Ž ¡S )z&Join paths to create a real path.
    )ÚospÚrealpathÚjoin)Úargs© r    ú2lib/python3.7/site-packages/jupyterlab/commands.pyÚpjoin)   s    r"   c              C   s,   t j d¡} | p ttƒ d ddƒ} t | ¡S )z;Get the configured JupyterLab user settings directory.
    ZJUPYTERLAB_SETTINGS_DIRr   Úlabzuser-settings)ÚosÚenvironÚgetr"   r
   r   r   )Zsettings_dirr    r    r!   Úget_user_settings_dir/   s    r'   c              C   s,   t j d¡} | p ttƒ d ddƒ} t | ¡S )z8Get the configured JupyterLab workspaces directory.
    ZJUPYTERLAB_WORKSPACES_DIRr   r#   Z
workspaces)r$   r%   r&   r"   r
   r   r   )Zworkspaces_dirr    r    r!   Úget_workspaces_dir9   s    r(   c              C   sœ   t j d¡rt t jd ¡S ttjdddƒ} tt	dƒr>t	 
¡  tt	ddƒ}t |¡rn|  |¡snt|dddƒ} n$tj d¡r’t | ¡s’t d	¡r’d	} t | ¡S )
z1Get the configured JupyterLab app directory.
    ZJUPYTERLAB_DIRZshareZjupyterr#   ÚgetuserbaseÚ	USER_BASENz/usrz/usr/local/share/jupyter/lab)r$   r%   r&   r   r   r"   ÚsysÚprefixÚhasattrÚsiter)   Úgetattrr   Ú
startswithÚexists)Úapp_dirÚuserbaser    r    r!   Úget_app_dirC   s    


r4   c             C   s´   t tdƒ}t t |dƒ¡s4tdtg|| d}| ¡  ddg}xD|D ]<}t |d|ƒ}t t |dƒ¡sBtdtd	g|| d}| ¡  qBW t t |d
dƒ¡s°tdtdg|| d}| ¡  dS )z.Ensure that the dev assets are available.
    z..Únode_modulesÚnode)ÚcwdÚloggerztheme-light-extensionztheme-dark-extensionÚpackagesÚstaticzbuild:webpackr   ÚbuildN)r"   r   r   r1   r   r   Úwait)r8   ÚparentÚ	yarn_procZtheme_packagesZthemeÚ	base_pathr    r    r!   Ú
ensure_dev^   s    



r@   c             C   sx   t tdƒ}t t tdƒ¡rdS t t |dƒ¡sHtdtg|| d}| ¡  t t tdƒ¡sttdtdg|| d}| ¡  dS )z/Ensure that the core assets are available.
    Ústagingr:   Nr5   r6   )r7   r8   r;   )r"   r   r   r1   r   r   r<   )r8   rA   r>   r    r    r!   Úensure_coreu   s    
rB   c             C   st   t tdƒ}t t |dƒ¡s4tdtg|| d}| ¡  t| ƒ} t t 	tddd¡¡}d}t
dtdd	g|| |d
}|gS )zÔRun watch mode for the source packages.

    Parameters
    ----------
    logger: :class:`~logger.Logger`, optional
        The logger instance.

    Returns
    -------
    A list of `WatchHelper` objects.
    z..r5   r6   )r7   r8   r9   Zmetapackagez/.* Found 0 errors\. Watching for file changes\.ÚrunÚwatch)r7   r8   Ústartup_regex)r"   r   r   r1   r   r   r<   Ú_ensure_loggerr   r   r   )r8   r=   r>   Zts_dirZts_regexZts_procr    r    r!   Úwatch_packagesˆ   s    
rG   c             C   s2   t | ƒ} t| ƒ}tdtddgt| td}||g S )zÑRun watch mode in a given directory.

    Parameters
    ----------
    logger: :class:`~logger.Logger`, optional
        The logger instance.

    Returns
    -------
    A list of `WatchHelper` objects.
    r6   rC   rD   )r7   r8   rE   )rF   rG   r   r   ÚDEV_DIRÚWEBPACK_EXPECT)r8   Zpackage_procsZwp_procr    r    r!   Ú	watch_dev¥   s    rJ   c             C   s"   t |ƒ}t|ƒ t| |ƒ}| ¡ S )a  Watch the application.

    Parameters
    ----------
    app_dir: string, optional
        The application directory.
    logger: :class:`~logger.Logger`, optional
        The logger instance.

    Returns
    -------
    A list of processes to run asynchronously.
    )rF   Ú_node_checkÚ_AppHandlerrD   )r2   r8   Úhandlerr    r    r!   rD   ½   s    
rD   c             C   s$   t |ƒ}t|ƒ t||ƒ}| | ¡S )zInstall an extension package into JupyterLab.

    The extension is first validated.

    Returns `True` if a rebuild is recommended, `False` otherwise.
    )rF   rK   rL   Úinstall_extension)Ú	extensionr2   r8   rM   r    r    r!   rN   Ñ   s    
rN   c             C   s$   t |ƒ}t|ƒ t||ƒ}| | ¡S )zpUninstall an extension by name or path.

    Returns `True` if a rebuild is recommended, `False` otherwise.
    )rF   rK   rL   Úuninstall_extension)Únamer2   r8   rM   r    r    r!   rP   Þ   s    
rP   Fc             C   s4   t |ƒ}t|ƒ t||ƒ}|dkr*| ¡ S | | ¡S )zùUpdate an extension by name, or all extensions.

    Either `name` must be given as a string, or `all_` must be `True`.
    If `all_` is `True`, the value of `name` is ignored.

    Returns `True` if a rebuild is recommended, `False` otherwise.
    T)rF   rK   rL   Úupdate_all_extensionsÚupdate_extension)rQ   Zall_r2   r8   rM   r    r    r!   rS   é   s    
rS   c             C   s„   t |ƒ}| ptƒ } | d| ¡ | ttdƒkr4tdƒ‚| ttdƒkrJtdƒ‚x*dD ]"}t| |ƒ}t |¡rPt||ƒ qPW | d¡ dS )	z+Clean the JupyterLab application directory.zCleaning %s...ZdevzCannot clean the dev appZcorezCannot clean the core app)rA   zSuccess!N)	rF   r4   Úinfor"   r   Ú
ValueErrorr   r1   Ú_rmtree)r2   r8   rQ   Útargetr    r    r!   Úcleanù   s    



rX   ú
build:prodc       	      C   s2   t |ƒ}t|ƒ t| ||d}|j|||||dS )z&Build the JupyterLab application.
    )Ú
kill_event)rQ   ÚversionÚ
public_urlÚcommandÚclean_staging)rF   rK   rL   r;   )	r2   rQ   r[   r\   r8   r]   rZ   r^   rM   r    r    r!   r;   	  s
    
r;   c             C   s   t | |ƒ}|jS )z3Get a dictionary of information about the app.
    )rL   rT   )r2   r8   rM   r    r    r!   Úget_app_info  s    
r_   c             C   s   t ||ƒ}| | d¡S )zgEnable a JupyterLab extension.

    Returns `True` if a rebuild is recommended, `False` otherwise.
    F)rL   Útoggle_extension)rO   r2   r8   rM   r    r    r!   Úenable_extension  s    
ra   c             C   s   t ||ƒ}| | d¡S )zfDisable a JupyterLab package.

    Returns `True` if a rebuild is recommended, `False` otherwise.
    T)rL   r`   )rO   r2   r8   rM   r    r    r!   Údisable_extension%  s    
rb   c             C   s   t ||ƒ}| | |¡S )z<Check if a JupyterLab extension is enabled or disabled.
    )rL   Úcheck_extension)rO   r2   Z	installedr8   rM   r    r    r!   rc   .  s    
rc   c             C   s"   t |ƒ}t|ƒ t| |ƒ}| ¡ S )zSDetermine whether JupyterLab should be built.

    Returns a list of messages.
    )rF   rK   rL   Úbuild_check)r2   r8   rM   r    r    r!   rd   5  s    
rd   c             C   s   t | |ƒ}| ¡ S )zList the extensions.
    )rL   Úlist_extensions)r2   r8   rM   r    r    r!   re   @  s    
re   c             C   s   t ||ƒ}| | ¡S )zuLink a package against the JupyterLab build.

    Returns `True` if a rebuild is recommended, `False` otherwise.
    )rL   Úlink_package)Úpathr2   r8   rM   r    r    r!   rf   G  s    
rf   c             C   s   t ||ƒ}| | ¡S )zzUnlink a package from JupyterLab by path or name.

    Returns `True` if a rebuild is recommended, `False` otherwise.
    )rL   Úunlink_package)Úpackager2   r8   rM   r    r    r!   rh   P  s    
rh   c             C   s   | pt ƒ } t| ƒ}|jd S )zGet the application version.r[   )r4   rL   rT   )r2   rM   r    r    r!   Úget_app_versionY  s    
rj   c             C   s   |pt ƒ }t||ƒ}| | ¡S )z=Get the latest compatible version of a list of packages.
    )r4   rL   Ú"latest_compatible_package_versions)Únamesr2   r8   rM   r    r    r!   Ú&get_latest_compatible_package_versions`  s    

rm   c             C   sL   t  | d¡}| d¡}t | ¡  d¡¡}dd„ | ¡ D ƒ|d< | ¡  |S )z5Read the package data in a given target tarball.
    Úrzpackage/package.jsonÚutf8c             S   s   g | ]}|j td ƒd… ‘qS )zpackage/N)rg   Úlen)Ú.0Úfr    r    r!   ú
<listcomp>o  s    z read_package.<locals>.<listcomp>Újupyterlab_extracted_files)	ÚtarfileÚopenÚextractfileÚjsonÚloadsÚreadÚdecodeZ
getmembersÚclose)rW   Útarrr   Údatar    r    r!   Úread_packageh  s    
r   c               @   s\  e Zd ZdTdd„ZdUdd„ZdVdd	„Zd
d„ Zdd„ ZdWdd„Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ ZdXdd„Zd d!„ Zd"d#„ Zd$d%„ ZdYd&d'„ZdZd(d)„Zd*d+„ Zd,d-„ Zd.d/„ Zd0d1„ Zd2d3„ Zd4d5„ Zd6d7„ Zd8d9„ Zd:d;„ Zd<d=„ Zd>d?„ Z d@dA„ Z!dBdC„ Z"dDdE„ Z#dFdG„ Z$dHdI„ Z%d[dJdK„Z&dLdM„ Z'dNdO„ Z(dPdQ„ Z)dRdS„ Z*dS )\rL   Nc             C   s>   |pt ƒ | _t ƒ | _t|ƒ| _|  ¡ | _|p0tƒ | _d| _	dS )z(Create a new _AppHandler object
        zhttps://registry.npmjs.orgN)
r4   r2   Úsys_dirrF   r8   Ú_get_app_inforT   r   rZ   Úregistry)Úselfr2   r8   rZ   r    r    r!   Ú__init__|  s    

z_AppHandler.__init__c          	   C   s  t |ƒ}| jd }|| jd krp|  ¡ }| dg ¡}||krl| j d| ¡ | |¡ ||d< |  |¡ dS dS |  ¡  tƒ }|  	||¡}W dQ R X |d }|d	 rÒ|  ¡ }| 
d
tƒ ¡}	|d |	|< |  |¡ ||kr|| }
|
d |d kr|
d dkrt |
d ¡ dS )z©Install an extension package into JupyterLab.

        The extension is first validated.

        Returns `True` if a rebuild is recommended, `False` otherwise.
        Ú
extensionsÚcore_extensionsÚuninstalled_core_extensionszInstalling core extension %sTFNrQ   Úis_dirÚlocal_extensionsÚsourcerg   ÚlocationÚapp)Ú_normalize_pathrT   Ú_read_build_configr&   r8   ÚremoveÚ_write_build_configÚ_ensure_app_dirsr   Ú_install_extensionÚ
setdefaultÚdictr$   )rƒ   rO   Úexistingr…   ÚconfigÚuninstalledÚtempdirrT   rQ   ÚlocalÚotherr    r    r!   rN   ‡  s4    




 z_AppHandler.install_extensionú
build:prodFc             C   sP   | j }| j||||d t|dƒ}| jdtdg|d | jdtd|g|d dS )zBuild the application.
        )rQ   r[   r\   rX   rA   r6   Úinstall)r7   rC   N)r2   Ú_populate_stagingr"   Ú_runr   )rƒ   rQ   r[   r\   r]   r^   r2   rA   r    r    r!   r;   µ  s    
z_AppHandler.buildc             C   sP   t | jdƒ}|  ¡  | jdtdg|d tdtddgt | jdƒt| jd}|gS )zXStart the application watcher and then run the watch in
        the background.
        rA   r6   rœ   )r7   rC   rD   )r7   rE   r8   )r"   r2   r   rž   r   r   rI   r8   )rƒ   rA   Úprocr    r    r!   rD   É  s    

z_AppHandler.watchc       
         sr  | j ‰ | j}ˆ  d|d  ¡ |d rV|  ¡ |d< ˆ  d¡ |  |d¡ |  |d¡ n
ˆ  d¡ |d	 }|ržˆ  d
¡ x&t|ƒD ]}ˆ  d||| f ¡ q€W |d }|räˆ  d¡ x.t|ƒD ]"}|| d }ˆ  d||f ¡ q¾W |d }|rˆ  d¡ ‡ fdd„t|ƒD ƒ |d }|r@ˆ  d¡ ‡ fdd„t|ƒD ƒ | jdd}	|	rnˆ  d¡ ‡ fdd„|	D ƒ dS )z+Print an output of the extensions.
        zJupyterLab v%sr[   r…   Úcompat_errorszKnown labextensions:rŒ   r+   zNo installed extensionsr‰   z
   local extensions:z        %s: %sÚlinked_packagesz
   linked packages:rŠ   Úuninstalled_corez
Uninstalled core extensions:c                s   g | ]}ˆ   d | ¡‘qS )z    %s)rT   )rq   Úitem)r8   r    r!   rs   ú  s    z/_AppHandler.list_extensions.<locals>.<listcomp>Údisabled_corez
Disabled core extensions:c                s   g | ]}ˆ   d | ¡‘qS )z    %s)rT   )rq   r£   )r8   r    r!   rs   ÿ  s    T)Úfastz3
Build recommended, please run `jupyter lab build`:c                s   g | ]}ˆ   d | ¡‘qS )z    %s)rT   )rq   r£   )r8   r    r!   rs     s    N)r8   rT   Ú_get_extension_compatÚ_list_extensionsÚsortedrd   )
rƒ   rT   r™   rQ   r¡   ÚkeyrŠ   r¢   r¤   Úmessagesr    )r8   r!   re   Ú  s@    






z_AppHandler.list_extensionsc             C   s"  | j }| jd }| jd }g }t|ddƒ}t |¡s:dgS | jd }|d }| dtƒ ¡}	| d	d
¡}
|d	 }t|
ƒt|ƒkrd}||
|f gS | j|d}|d }| dtƒ ¡}xddD ]\}x*|| D ]}||| krÆ| 	d| ¡ qÆW x*|| D ]}||| krò| 	d| ¡ qòW q¸W xj| 
¡ D ]^\}}||	kr8q"||ks"||krPq"|	| |kr"d}| 	|||	| || f ¡ q"W xH| 
¡ D ]<\}}|r qŽt|dƒ}|  |||¡rŽ| 	d| ¡ qŽW xN| 
¡ D ]B\}}|rêqØt|ddƒ}|  ||d |¡rØ| 	d| ¡ qØW |S )z[Determine whether JupyterLab should be built.

        Returns a list of messages.
        r‰   r¡   r:   zpackage.jsonzNo built applicationÚstatic_dataÚ
jupyterlabÚdependenciesr[   Ú z*Version mismatch: %s (built), %s (current))Úsilent)r…   ÚmimeExtensionsz %s needs to be included in buildz!%s needs to be removed from buildz%s changed from %s to %sr…   z%s content changedrA   rŠ   )r2   rT   r"   r   r1   r&   r”   r   Ú_get_package_templateÚappendÚitemsÚ_check_local)rƒ   r¥   r2   r™   Úlinkedrª   Úpkg_pathr«   Zold_jlabZold_depsZstatic_versionZcore_versionÚmsgZnew_packageZnew_jlabZnew_depsÚext_typeÚextÚpkgZdeprQ   rŠ   Údnamer£   r    r    r!   rd     s\    





"
z_AppHandler.build_checkc       	      C   s  | j d }|| j d krh|  ¡ }| dg ¡}||krd| j  d| ¡ | |¡ ||d< |  |¡ dS dS | j d }x„| j d  ¡ D ]r\}}|d	 }||kr‚d
|t |¡f }| j  |¡ t	 
|¡ ||krð|  ¡ }| dtƒ ¡}||= |  |¡ dS q‚W | j d| ¡ dS )zpUninstall an extension by name.

        Returns `True` if a rebuild is recommended, `False` otherwise.
        Ú	core_datar†   r‡   zUninstalling core extension %sTFr‰   r…   rg   zUninstalling %s from %sz$No labextension named "%s" installed)rT   rŽ   r&   r8   r²   r   r³   r   Údirnamer$   r   r“   r”   Úwarn)	rƒ   rQ   r~   r–   r—   r™   Úextnamerg   r·   r    r    r!   rP   M  s4    





z_AppHandler.uninstall_extensionc             C   sF   d}x<| j d  ¡ D ]*\}}|| j d kr,q|  |¡}|p<|}qW |S )zqUpdate all non-local extensions.

        Returns `True` if a rebuild is recommended, `False` otherwise.
        Fr…   r‰   )rT   r³   Ú_update_extension)rƒ   Zshould_rebuildr¿   Ú_Úupdatedr    r    r!   rR   r  s    
z!_AppHandler.update_all_extensionsc             C   s,   || j d kr"| j d| ¡ dS |  |¡S )zmUpdate an extension by name.

        Returns `True` if a rebuild is recommended, `False` otherwise.
        r…   z$No labextension named "%s" installedF)rT   r8   r¾   rÀ   )rƒ   rQ   r    r    r!   rS   €  s    z_AppHandler.update_extensionc             C   s€   y|   |¡}W n tk
r"   dS X |dkr0dS || jd | d krZ| j d| ¡ dS | j d||f ¡ |  d||f ¡S )zmUpdate an extension by name.

        Returns `True` if a rebuild is recommended, `False` otherwise.
        FNr…   r[   zExtension %r already up to datezUpdating %s to version %sz%s@%s)Ú"_latest_compatible_package_versionr	   rT   r8   rN   )rƒ   rQ   Zlatestr    r    r!   rÀ   Š  s    z_AppHandler._update_extensionc          	      s¸   t |ƒ}t |¡rt |¡s,d}t|| ƒ‚tƒ }ˆ  ||¡}W dQ R X t|d ƒ}|sdˆ  |¡S ˆ j	 
d|¡ ‡ fdd„|D ƒ ˆ  ¡ }| dtƒ ¡}|d ||d	 < ˆ  |¡ d
S )zrLink a package at the given path.

        Returns `True` if a rebuild is recommended, `False` otherwise.
        z,Can install "%s" only link local directoriesNr~   z"Installing %s as a linked package:c                s   g | ]}ˆ j  |¡‘qS r    )r8   r¾   )rq   Úm)rƒ   r    r!   rs   ®  s    z,_AppHandler.link_package.<locals>.<listcomp>r¡   rŠ   rQ   T)r   r   r1   ÚisdirrU   r   Ú_extract_packageÚ_validate_extensionrN   r8   r¾   rŽ   r“   r”   r   )rƒ   rg   r·   r˜   rT   rª   r–   rµ   r    )rƒ   r!   rf   ›  s     

z_AppHandler.link_packagec             C   sÔ   t |ƒ}|  ¡ }| dtƒ ¡}d}x(| ¡ D ]\}}||ksD||kr,|}q,W |rX||= n^| dtƒ ¡}x(| ¡ D ]\}}||ksˆ||krp|}qpW |r¶||= | jd | d }t |¡ |sÆtd| ƒ‚|  	|¡ dS )zÉUnlink a package by name or at the given path.

        A ValueError is raised if the path is not an unlinkable package.

        Returns `True` if a rebuild is recommended, `False` otherwise.
        r¡   Nr‰   r…   rg   zNo linked package for %sT)
r   rŽ   r“   r”   r³   rT   r$   r   rU   r   )rƒ   rg   r–   rµ   ÚfoundrQ   rŠ   r™   r    r    r!   rh   ¸  s*    

z_AppHandler.unlink_packagec             C   s`   |   ¡ }| dg ¡}d}|r4||kr4| |¡ d}n|sN||krN| |¡ d}|r\|  |¡ |S )zsEnable or disable a lab extension.

        Returns `True` if a rebuild is recommended, `False` otherwise.
        ÚdisabledExtensionsFT)Ú_read_page_configr“   r²   r   Ú_write_page_config)rƒ   rO   Úvaluer–   ÚdisabledZdid_somethingr    r    r!   r`   Ú  s    


z_AppHandler.toggle_extensionc             C   sR   | j }||d kr |  |||¡S ||d krD| j  d|tf ¡ dS |  |||¡S )z8Check if a lab extension is enabled or disabled
        r†   r¡   z%s:%sT)rT   Ú_check_core_extensionr8   r   Ú_check_common_extension)rƒ   rO   Úcheck_installed_onlyrT   r    r    r!   rc   ì  s    
z_AppHandler.check_extensionc             C   s|   ||d kr$| j  d|tf ¡ dS |r@| j  d|tf ¡ dS ||d krd| j  d|tf ¡ dS | j  d|tf ¡ dS )z9Check if a core extension is enabled or disabled
        r¢   z%s:%sFz%s: %sTr¤   )r8   rT   r   r   r   r   )rƒ   rO   rT   rÐ   r    r    r!   rÎ   ü  s    z!_AppHandler._check_core_extensionc             C   s¦   ||d kr$| j  d|tf ¡ dS |  ¡ | }|rL| j  d|tf ¡ dS |rh| j  d|tf ¡ dS t||d ƒrŽ| j  d|tf ¡ dS | j  d|tf ¡ dS )zFCheck if a common (non-core) extension is enabled or disabled
        r…   z%s:%sFz%s:%s (compatibility errors)z%s: %sTrÍ   )r8   rT   r   r¦   r   Ú_is_disabledr   r   )rƒ   rO   rT   rÐ   Úerrorsr    r    r!   rÏ     s     z#_AppHandler._check_common_extensionc             C   sZ  t ƒ }tƒ  |d< }|  |¡ |d< }|  ¡ }| dg ¡|d< |  ¡ |d< |  ¡ |d< g  |d< }g  |d< }xF| ¡ D ]:\}}||d k|d	< |d
 dkr¨| |¡ qx| |¡ qxW |  	¡ |d< t
| jƒ|d< |d pÚ|}	|	d d |d< |	d  dd¡|d< | j|d< | j|d< tƒ  |d< }
g }x&|
D ]}||d kr,| |¡ q,W ||d< |S )z'Get information about the app.
        r¼   r…   rÉ   rÍ   r‰   r¡   Zapp_extensionsZsys_extensionsÚis_localr‹   rŒ   r¢   r«   r¬   r[   Ú	publicUrlr®   r€   r2   r†   r¤   )r”   Ú_get_core_dataÚ_get_extensionsrÊ   r&   Ú_get_local_extensionsÚ_get_linked_packagesr³   r²   Ú _get_uninstalled_core_extensionsÚ_get_static_datar2   r€   Ú_get_core_extensions)rƒ   rT   r¼   r…   Zpage_configrŒ   r+   rQ   r~   Zapp_datar†   r¤   r©   r    r    r!   r   #  s8    


z_AppHandler._get_app_infoc          
   C   s  | j }t|dƒ}|r8t |¡r8| j d|¡ t|| jƒ |  ¡  |sV| jd d d }t|dƒ}t |¡r²t|ƒ}t	 
|¡}	W dQ R X |	d  dd¡|kr²t|| jƒ t |¡ x*d	D ]"}
t||
ƒ}t ttd|
ƒ|¡ q¸W t t|d
ƒ¡rþt t|d
ƒ¡ t|dƒ}t |¡r t|| jƒ yt ttddƒ|¡ W nT tjk
rŒ } z2dt|ƒkofdt|ƒk}|szt |¡s|‚ W dd}~X Y nX t|dƒ}t |¡r°t|| jƒ t |¡ | jd }d}xt| jd  ¡ D ]b\}}||kr|  ¡ }| dtƒ ¡}	|	|= |  |¡ d}qØt|dƒ}|  ||||| d¡ qØW |rR|  ¡ | jd< | jd }x6| ¡ D ]*\}}t|dƒ}|  ||d ||d¡ qfW |  ¡ }	|r®||	d d< |rÀ||	d d< |rÒ||	d d< t|dƒ}t|dƒ}t	j|	|dd W dQ R X dS )z4Set up the assets in the staging directory.
        rA   zCleaning %sr¼   r¬   r[   zpackage.jsonNr®   )zindex.jszwebpack.config.jszwebpack.prod.config.jsz.yarnrczyarn.jsz	yarn.lockÚ	templatesz
[Errno 22]z	[Errno 5]r¡   r…   Fr‰   TrŠ   rQ   rÔ   Úwé   )Úindent)r2   r"   r   r1   r8   rT   rV   r‘   rv   rx   Úloadr&   r$   ÚmakedirsÚshutilÚcopyr   r   ZcopytreeÚErrorÚstrr³   rŽ   r“   r”   r   Ú_update_localr×   r±   Údump)rƒ   rQ   r[   r\   rX   r2   rA   r¶   Úfidr~   ÚfnamerW   rÜ   ÚerrorZ
real_errorZ
linked_dirr…   Zremovedr©   rŠ   r–   r»   rµ   r£   r    r    r!   r   K  s~    
















z_AppHandler._populate_stagingc                s¾  ˆ j }ˆ jd }ˆ jd }ˆ jd }ˆ jd }|d }‡ fdd„}tƒ |d< x | ¡ D ]\}	}
|
|d |	< qVW xP| ¡ D ]D\}	}tˆ jd	dƒ}t||d
 ƒ}||ƒ|d |	< |d |d |	< qxW ˆ  ¡ }x˜| ¡ D ]Œ\}	}||	 }|rþ|sÒt||	|d |ƒ qÒ||d ƒ|d |	< |d }xBdD ]:}| |d¡}|s:q |dkrHd}|||d  |	< q W qÒW xVˆ jd D ]H}||d kr”|d d  	|¡ n|d d  	|¡ |d  	|¡ qnW |S )z<Get the template the for staging package.json file.
        r¼   r‰   r¡   r…   r¬   c                s<   t  | tˆ jdƒ¡} d|  tjd¡ } tjdkr8|  ¡ } | S )NrA   zfile:ú/Únt)	r   Úrelpathr"   r2   Úreplacer$   ÚseprQ   Úlower)rg   )rƒ   r    r!   Úformat_path»  s
    
z6_AppHandler._get_package_template.<locals>.format_pathZlinkedPackagesrA   Úfilenamer­   rŠ   r[   rg   )rO   ÚmimeExtensionFTr®   Úsr¢   r°   )
r8   rT   r”   r³   r"   r2   r¦   Ú_log_single_compat_errorsr&   Úpop)rƒ   r¯   r8   r~   r™   rµ   r…   Újlabrñ   r©   rŠ   r£   rg   r    rÌ   rÒ   Z	jlab_datar¹   r    )rƒ   r!   r±   ±  sL    






z!_AppHandler._get_package_templatec          	   C   s8   t ƒ (}|  ||¡}t||d ƒ}t |¡ S Q R X dS )zwCheck if a local package has changed.

        `dname` is the directory name of existing package tar archives.
        rò   N)r   rÆ   r"   r   r1   )rƒ   rQ   rŠ   r»   r˜   rT   rW   r    r    r!   r´   ñ  s    z_AppHandler._check_localc       	   	   C   sŽ   |d }t ƒ <}|  ||¡}|d |kr,|S t |d t||d ƒ¡ W dQ R X |rdt t||ƒ¡ |d |d< t|d |d ƒ|d< |d S )z>Update a local dependency.  Return `True` if changed.
        rò   rg   NÚtar_dir)r   rÆ   râ   Úmover"   r$   r   )	rƒ   rQ   rŠ   r»   r~   Zdtyper•   r˜   rT   r    r    r!   ræ      s    $z_AppHandler._update_localc             C   sh   | j }tƒ }t| jdƒ}t| j dƒ}|  | j|¡}t|dƒ}||ksNt |¡sR|S | |  ||¡¡ |S )z0Get the extensions for the application.
        r…   )r2   r”   r"   r€   Ú_get_extensions_in_dirr   r1   Úupdate)rƒ   r¼   r2   r…   Zsys_pathZapp_pathr    r    r!   rÖ     s    
z_AppHandler._get_extensionsc             C   sØ   t ƒ }|| jkrdnd}xºt t|ddƒ¡D ]¤}t|ƒ}| dt ƒ ¡}|d }| dt ƒ ¡}	t |¡}
d|krx|d }n,d	|kr t|d	 t ƒr |d	  d
d¡}nd}t |
t 	|
¡||d |	|t 
|
¡|d||< q,W |S )z1Get the extensions in a given directory.
        rŒ   r+   r…   z*.tgzr­   rQ   r¬   ZhomepageZ
repositoryÚurlr®   r[   )rg   rò   rü   r[   r¬   r­   rø   r‹   )r”   r2   Úglobr"   r   r&   r   r   Ú
isinstanceÚbasenamer½   )rƒ   r»   r¼   r…   r‹   rW   r~   ÚdepsrQ   r÷   rg   rü   r    r    r!   rú   +  s,    

z"_AppHandler._get_extensions_in_dirc             C   sH   t ƒ }| jd }x2| jd  ¡ D ] \}}|d }t|||ƒ||< q W |S )z.Get the extension compatibility info.
        r¼   r…   r­   )r”   rT   r³   Ú_validate_compatibility)rƒ   Úcompatr¼   rQ   r~   r   r    r    r!   r¦   G  s    
z!_AppHandler._get_extension_compatc             C   s
   |   d¡S )z.Get the locally installed extensions.
        r‰   )Ú_get_local_data)rƒ   r    r    r!   r×   Q  s    z!_AppHandler._get_local_extensionsc             C   sÜ   |   d¡}t| jddƒ}x&| ¡ D ]\}}t|d|d||< q"W t |¡sN|S xˆt t|dƒ¡D ]t}t |¡}t	|ƒ}|d }||kr¢| j
 d| ¡ t |¡ q`|| }t |¡|d< ||d	< |d
 |d
< ||d< q`W |S )z!Get the linked packages.
        r¡   rA   r®   )rŠ   rò   rø   z*.tgzrQ   z#Removing orphaned linked package %srò   rg   r[   r~   )r  r"   r2   r³   r”   r   r1   rý   r   r   r8   r¾   r$   r   rÿ   )rƒ   rT   r»   rQ   rŠ   rg   r~   r£   r    r    r!   rØ   V  s(    



z _AppHandler._get_linked_packagesc             C   s   |   ¡ }| dg ¡S )z-Get the uninstalled core extensions.
        r‡   )rŽ   r&   )rƒ   r–   r    r    r!   rÙ   p  s    z,_AppHandler._get_uninstalled_core_extensionsc             C   sv   dddddg}xb|D ]Z}t | j|ƒ}t |¡syt |¡ W q tk
rl } z|jtjkr\‚ W dd}~X Y qX qW dS )z-Ensure that the application directories existr…   ÚsettingsrA   ZschemasZthemesN)	r"   r2   r   r1   r$   rá   ÚOSErrorÚerrnoZEEXIST)rƒ   Údirsr»   rg   Úer    r    r!   r‘   v  s    

z_AppHandler._ensure_app_dirsc             C   sú   | j }|d|  }|sdS |d|  }i }| d||f ¡ x®t|ƒD ]¢}|d | }|d }	|d | }
d}t||d	 ƒrŠ|d
t 7 }n|d
t 7 }|
r¨|d
t 7 }n|d
t 7 }|d rÄ|d7 }| d||	|f ¡ |
rF|	|
f||< qFW t||ƒ dS )z-List the extensions of a given type.
        z%s_extensionsNz%s_dirz   %s dir: %sr…   r[   r    r®   rÍ   z %srÓ   Ú*z        %s v%s%s)	r8   rT   r¨   rÑ   r   r   r   r   Ú_log_multiple_compat_errors)rƒ   rT   r¸   r8   rl   r»   Zerror_accumulatorrQ   r~   r[   rÒ   Zextrar    r    r!   r§   ‚  s0    z_AppHandler._list_extensionsc          	   C   s:   t | jddƒ}t |¡si S t|ƒ}t |¡S Q R X dS )z3Get the build config data for the app dir.
        r  zbuild_config.jsonN)r"   r2   r   r1   rv   rx   rà   )rƒ   rW   rè   r    r    r!   rŽ   ¥  s
    

z_AppHandler._read_build_configc          	   C   s@   |   ¡  t| jddƒ}t|dƒ}tj||dd W dQ R X dS )z/Write the build config to the app dir.
        r  zbuild_config.jsonrÝ   rÞ   )rß   N)r‘   r"   r2   rv   rx   rç   )rƒ   r–   rW   rè   r    r    r!   r   ¯  s    z_AppHandler._write_build_configc          	   C   s:   t | jddƒ}t |¡si S t|ƒ}t |¡S Q R X dS )z2Get the page config data for the app dir.
        r  zpage_config.jsonN)r"   r2   r   r1   rv   rx   rà   )rƒ   rW   rè   r    r    r!   rÊ   ·  s
    

z_AppHandler._read_page_configc          	   C   s@   |   ¡  t| jddƒ}t|dƒ}tj||dd W dQ R X dS )z/Write the build config to the app dir.
        r  zpage_config.jsonrÝ   rÞ   )rß   N)r‘   r"   r2   rv   rx   rç   )rƒ   r–   rW   rè   r    r    r!   rË   Á  s    z_AppHandler._write_page_configc             C   sŽ   |   ¡ }| |tƒ ¡}g }x(| ¡ D ]\}}t |¡s$| |¡ q$W x6|D ].}| dd¡}d||f }| j 	|¡ ||= qJW |rŠ|  
|¡ |S )z>Get the local data for extensions or linked packages.
        rÁ   ú z**Note: Removing dead %s "%s")rŽ   r“   r”   r³   r   r1   r²   rî   r8   r¾   r   )rƒ   rŠ   r–   r~   ZdeadrQ   Z	link_typer·   r    r    r!   r  É  s    



z_AppHandler._get_local_datac          	   C   s†  |   ||¡}|d }t|ƒ}|r:d}t||d |¡f ƒ‚tƒ }| dtƒ ¡}t|||ƒ}	|	rBt|d |d |	ƒ}d|dd	… kr:|d
 s:|d }
y|  	|
¡}W n t
k
rÂ   t|ƒ‚Y nX |r|
r| j d|¡ | j d|¡ tƒ }|  d|
|f |¡S Q R X d | ¡ dd	… ¡}d |  |
¡d|f¡}t|ƒ‚t| jd|d ƒ}t |¡rjt |¡ t |d |¡ ||d< |S )zKInstall an extension with validation and return the name and path.
        r~   z!"%s" is not a valid extension:
%sÚ
r­   rQ   r[   ú@r   Nrˆ   zIncompatible extension:
%szFound compatible version: %sz%s@%sé   r®   z

r…   rò   rg   )rÆ   rÇ   rU   r   rÕ   r&   r”   r  Ú_format_compatibility_errorsrÃ   r	   r8   Úwarningr   r’   Ú
splitlinesÚ%_format_no_compatible_package_versionr"   r2   r   r1   r$   r   râ   rù   )rƒ   rO   r˜   rT   r~   rª   r·   r¼   r   rÒ   rQ   r[   Ztempdir2Z	conflictsrW   r    r    r!   r’   ß  sH    
z_AppHandler._install_extensionc             C   s  t  |¡ot  |¡}|r>t  t|dƒ¡s>| jdtdg||d t||d}| jtdƒd|g||d}|dkr|d	}t|| ƒ‚t	 	t|d
ƒ¡d }t
|ƒ|d< |rÖt|ƒ |d< }	| dd|	 ¡}
t ||
¡ |
|d< n||d< t  |d ¡|d< |d d |d< |d d |d< |S )zÇCall `npm pack` for an extension.

        The pack command will download the package tar if `source` is
        a package name, or run `npm pack` locally if `source` is a
        directory.
        r5   r6   rœ   )r7   Úquiet)rŠ   rˆ   ÚnpmÚpackr   z"%s" is not a valid npm packagez*.tgzr~   Úshaz.tgzz-%s.tgzrg   rò   rQ   r[   )r   r1   rÅ   r"   rž   r   r”   r   rU   rý   r   Ú_tarsumrî   râ   rù   rÿ   )rƒ   rŠ   r˜   r  rˆ   rT   Úretr·   rg   r  rW   r    r    r!   rÆ     s(    
z_AppHandler._extract_packagec          
   C   sÆ   | j d }yt| j|| jƒ}W n tk
r2   dS X | dg ¡}dd„ }xxt| ¡ |ddD ]b\}}| di ¡}t|||ƒ}	|	s\t	ƒ }
| j
d	||f |
dd
}W dQ R X t|d ƒrºdS |S q\W dS )z.Get the latest compatible version of a packager¼   NÚversionsc             S   s   t | d ddS )Nr   T)Úprerelease_first)Ú_semver_key)Ú	key_valuer    r    r!   Úsort_keyF  s    z@_AppHandler._latest_compatible_package_version.<locals>.sort_keyT)r©   Úreverser­   z%s@%s)r  r~   )rT   Ú_fetch_package_metadatar‚   r8   r	   r&   r¨   r³   r  r   rÆ   rÇ   )rƒ   rQ   r¼   Úmetadatar  r  r[   r~   r   rÒ   r˜   rT   r    r    r!   rÃ   <  s&    

z._AppHandler._latest_compatible_package_versionc          	   C   sf  | j d }g }xœ|D ]”}yt| j|| jƒ}W n tk
rB   wY nX | dg ¡}dd„ }xNt| ¡ |ddD ]8\}}	|	 di ¡}
t||
|ƒ}|sl| 	d||f ¡ P qlW qW i }|s¸|S t
ƒ ž}| jtd	ƒd
g| |dd}|dkrôd}t|| ƒ‚xb|D ]Z}|d  dd¡|dd…  dd¡ dd¡ d }ttj ||¡ƒ}	t|	ƒsú|	d ||< qúW W dQ R X |S )zÉGet the latest compatible versions of several packages

        Like _latest_compatible_package_version, but optimized for
        retrieving the latest version for several packages in one go.
        r¼   r  c             S   s   t | d ddS )Nr   T)r  )r  )r  r    r    r!   r  k  s    z@_AppHandler.latest_compatible_package_versions.<locals>.sort_keyT)r©   r  r­   z%s@%sr  r  )r7   r  r   z"%s" is not a valid npm packager  r®   r   Nú-rë   z.tgzr[   )rT   r  r‚   r8   r	   r&   r¨   r³   r  r²   r   rž   r   rU   rî   r   r$   rg   r   rÇ   )rƒ   rl   r¼   ÚkeysrQ   r   r  r  r[   r~   r   rÒ   r˜   r  r·   r©   ré   r    r    r!   rk   Z  s>    




0z._AppHandler.latest_compatible_package_versionsc             C   s   | j d }d}d}yt| j|| jƒ}W n tk
r:   Y n˜X | dg ¡}dd„ }tt| ¡ |ddƒ}|d d	  d
i ¡}	|d
 }
|d d }xB|	 ¡ D ]6\}}||kr˜t	|
| |ƒ}|pÀ|dk }|pÌ|dk}q˜W |rÚdS dg}|rî| 
d¡ d |¡j|dS )z.Get the latest compatible version of a packager¼   Fr  c             S   s   t | d ddS )Nr   T)r  )r  )r  r    r    r!   r  ›  s    zC_AppHandler._format_no_compatible_package_version.<locals>.sort_keyT)r©   r  r   r   r­   r¬   ÚsingletonPackageszGThis extension does not yet support the current version of JupyterLab.
zcNo version of {extension} could be found that is compatible with the current version of JupyterLab.)z9However, it seems to support a new version of JupyterLab.zConsider upgrading JupyterLab.r  )rO   )rT   r  r‚   r8   r	   r&   Útupler¨   r³   Ú_compare_rangesÚextendr   Úformat)rƒ   rQ   r¼   Zlab_newer_than_latestZlatest_newer_than_labr   r  r  ZstoreZlatest_depsÚ	core_depsÚ
singletonsr©   rÌ   ÚcÚpartsr    r    r!   r  ‹  s0    

z1_AppHandler._format_no_compatible_package_versionc             K   s:   | j  ¡ rtdƒ‚| j|d< | j |d< t|f|Ž}| ¡ S )z]Run the command using our logger and abort callback.

        Returns the exit code.
        zCommand was killedr8   rZ   )rZ   Zis_setrU   r8   r   r<   )rƒ   ÚcmdÚkwargsrŸ   r    r    r!   rž   ¸  s    


z_AppHandler._run)NN)N)NNNr›   F)F)F)NNNF)F)F)+Ú__name__Ú
__module__Ú__qualname__r„   rN   r;   rD   re   rd   rP   rR   rS   rÀ   rf   rh   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Ã   rk   r  rž   r    r    r    r!   rL   z  sT   

. 
,
G%
"
( 
e
@
#

:
#1-rL   c             C   sj   t dƒ}y&tj|dgtd}|  | d¡¡ W n6 tk
rd   tƒ }|d d }d| }t|ƒ‚Y nX dS )z@Check for the existence of nodejs with the correct version.
    r6   znode-version-check.js)r7   zutf-8ZenginesztPlease install nodejs %s before continuing. nodejs may be installed using conda or directly from the nodejs website.N)	r   Ú
subprocessZcheck_outputr   rT   r{   Ú	ExceptionrÕ   rU   )r8   r6   Úoutputr~   Zverr·   r    r    r!   rK   Æ  s    rK   c             C   s   | pt  d¡S )zEnsure that we have a loggerr¬   )ÚloggingZ	getLogger)r8   r    r    r!   rF   Ô  s    rF   c             C   s"   t  | ¡} t  | ¡rt  | ¡} | S )z1Normalize a given extension if it is a path.
    )r   Ú
expanduserr1   Úabspath)rO   r    r    r!   r   Ù  s    


r   c                s   ‡ fdd„}t j| |d dS )zRemove a tree, logging errorsc                 s   ˆ j d| d d S )NzError in rmtree)Úexc_info)Údebug)r7  )r8   r    r!   Úonerrorä  s    z_rmtree.<locals>.onerror)r9  N)râ   Zrmtree)rg   r8   r9  r    )r8   r!   rV   â  s    rV   c                sŒ  |   dd¡}|dkrdgS t|tƒs*dgS |  dd¡}|  dd¡}|  dd	¡‰|  d
d	¡‰ g }|sp|sp| d¡ ||kr†d}| |¡ | d }|   dd¡}| d¡s¬|d7 }|dkrº|}n|rÐ| d¡sÐ|d7 }|dkrÞ|}n|rô| d¡sô|d7 }|r||kr| d| ¡ |r0||kr0| d| ¡ ˆr\t‡fdd„|D ƒƒs\| dˆ ¡ ˆ rˆt‡ fdd„|D ƒƒsˆ| dˆ  ¡ |S )z`Detect if a package is an extension using its metadata.

    Returns any problems it finds.
    r¬   NzNo `jupyterlab` keyz*The `jupyterlab` key must be a JSON objectrO   Fró   ÚthemeDirr®   Ú	schemaDirz-No `extension` or `mimeExtension` key presentz?`mimeExtension` and `extension` must point to different modulesrt   Úmainzindex.jsz.jsTzMissing extension module "%s"z!Missing mimeExtension module "%s"c             3   s   | ]}|  ˆ ¡V  qd S )N)r0   )rq   rr   )r:  r    r!   ú	<genexpr>  s    z&_validate_extension.<locals>.<genexpr>zthemeDir is empty: "%s"c             3   s   | ]}|  ˆ ¡V  qd S )N)r0   )rq   rr   )r;  r    r!   r=    s    zschemaDir is empty: "%s")r&   rþ   r”   r²   ÚendswithÚany)r~   r÷   rO   Zmime_extensionrª   r·   Úfilesr<  r    )r;  r:  r!   rÇ   ê  sH    



rÇ   c             C   sl   t  | d¡}d}t d¡}xH|D ]@}| ¡ s.q | |¡}| |¡}x|r^| |¡ | |¡}qDW q W | ¡ S )z6
    Compute the recursive sha sum of a tar file.
    rn   i  Zsha1)	ru   rv   ÚhashlibÚnewÚisfilerw   rz   rû   Z	hexdigest)Z
input_filer}   Z
chunk_sizeÚhÚmemberrr   r~   r    r    r!   r    s    




r  c           	   C   s&   t ttddƒƒ} t | ¡S Q R X dS )z'Get the data for the app template.
    rA   zpackage.jsonN)rv   r"   r   rx   rà   )rè   r    r    r!   rÕ   2  s    rÕ   c          	   C   s<   t | ddƒ}tj |¡r4t|ƒ}t |¡S Q R X ndS dS )z)Get the data for the app static dir.
    r:   zpackage.jsonN)r"   r$   rg   r1   rv   rx   rà   )r2   rW   rè   r    r    r!   rÚ   9  s
    
rÚ   c       	      C   sd   |d }|d d }g }xF|  ¡ D ]:\}}||kr"t|| |ƒ}|dkr"| ||| |f¡ q"W |S )z0Validate the compatibility of an extension.
    r­   r¬   r#  F)r³   Ú_test_overlapr²   )	rO   r   r¼   r(  r)  rÒ   r©   rÌ   Zoverlapr    r    r!   r  D  s    r  c             C   s   t | |ƒ}|dkrdS |dkS )zTest whether two version specs overlap.

    Returns `None` if we cannot determine compatibility,
    otherwise whether there is an overlap
    Nr   )r%  )Úspec1Úspec2Zcmpr    r    r!   rF  U  s    
rF  c             C   s¸  t | dƒ}t |dƒ}|jr |js$dS |jd d j}|jd d j}|jd d j}|jd d j}|jd d j}|jd d j}	| d¡s˜|	 d¡rœdS ||kr¨tnt}
||kr¸tnt}||krÈtnt	}||krØtnt	}dd„ }||krú| d¡rú|}
||kr|	 d¡r|}t||dƒr0|||dƒs„|||dƒrL|||dƒs„t||dƒrh|
||dƒs„|||dƒrˆ|
||dƒrˆdS t||dƒršd	S t||dƒr¬dS t
d
ƒ‚dS )zïTest whether two version specs overlap.

    Returns `None` if we cannot determine compatibility,
    otherwise return 0 if there is an overlap, 1 if
    spec1 is lower/older than spec2, and -1 if spec1
    is higher/newer than spec2.
    TNr   éÿÿÿÿú<c             S   s   dS )NTr    )ÚxÚyÚzr    r    r!   Únoop„  s    z_compare_ranges.<locals>.noopú>r   z(Unexpected case comparing version ranges)r   ÚrangeÚsetÚsemverÚoperatorr0   r   r   r   r   ÚAssertionError)rG  rH  Zr1Zr2Zx1Zx2Zy1Zy2Zo1Zo2ZlxZlyZgxZgyrN  r    r    r!   r%  a  s>    	

r%  c             C   s6   x0|D ](}| |krdS t  |¡ | ¡dk	rdS qW dS )z*Test whether the package is disabled.
    TNF)ÚreÚcompileÚmatch)rQ   rÍ   Úpatternr    r    r!   rÑ   š  s    
rÑ   c             C   sè   g }d}d}xf|D ]^}|\}}}	t t|dƒƒ}t t|	dƒƒ}	| |||	f¡ t|t|ƒd ƒ}t|t|ƒd ƒ}qW d}
|
| |f }
|
d7 }
|
d |¡7 }
|
d |¡7 }
|
d7 }
x2|D ]*\}}}	|
| |¡|	 |¡ | d	 7 }
q¶W |
S )
z/Format a message for compatibility errors.
    é
   Tr   z6
"%s@%s" is not compatible with the current JupyterLabz
Conflicting Dependencies:
Z
JupyterLabZ	ExtensionzPackage
r  )rå   r   r²   Úmaxrp   Úljust)rQ   r[   rÒ   ZmsgsZl0Úl1rê   rº   r÷   r¹   r·   r    r    r!   r  ¥  s&    

$r  c       	      C   s    g }g }x>|  ¡ D ]2\}\}}t|ƒ}|dkr:| |¡ q| |¡ qW |rh|  d dg| dg ¡¡ x2|D ]*}|| \}}t|||ƒ}|  |d ¡ qnW dS )z8Log compatability errors for multiple extensions at oncer   z	
        z)
   The following extension are outdated:zO
   Consider running "jupyter labextension update --all" to check for updates.
r  N)r³   Ú_compat_error_ager²   r¾   r   r  )	r8   Z
errors_mapZoutdatedZothersrQ   r[   rÒ   Úager·   r    r    r!   r
  À  s    
r
  c             C   s<   t |ƒ}|dkr|  d|¡ nt|||ƒ}|  |d ¡ dS )z/Log compatability errors for a single extensionr   z The extension "%s" is outdated.
r  N)r]  r¾   r  )r8   rQ   r[   rÒ   r^  r·   r    r    r!   rõ   Û  s
    rõ   c             C   sZ   d}d}x4| D ],\}}}t ||ƒ}|p,|dk }|p8|dk}qW |rJ|sJdS |rV|sVdS dS )züCompare all incompatabilites for an extension.

    Returns a number > 0 if all extensions are older than that supported by lab.
    Returns a number < 0 if all extensions are newer than that supported by lab.
    Returns 0 otherwise (i.e. a mix).
    Fr   r   rI  )r%  )rÒ   Z	any_olderZ	any_newerrÁ   r÷   r¹   r*  r    r    r!   r]  æ  s    
r]  c              C   s"   t ƒ d } t| d ƒt| d ƒ S )zGet the core extensions.
    r¬   r…   r°   )rÕ   Úlist)r~   r    r    r!   rÛ   ý  s    
rÛ   c             c   s0   x*| D ]"}t |tƒr d|fV  q|fV  qW dS )az  Sort key for prereleases.

    Precedence for two pre-release versions with the same
    major, minor, and patch version MUST be determined by
    comparing each dot separated identifier from left to
    right until a difference is found as follows:
    identifiers consisting of only digits are compare
    numerically and identifiers with letters or hyphens
    are compared lexically in ASCII sort order. Numeric
    identifiers always have lower precedence than non-
    numeric identifiers. A larger set of pre-release
    fields has a higher precedence than a smaller set,
    if all of the preceding identifiers are equal.
    r®   N)rþ   Úint)Ú
prereleaseÚentryr    r    r!   Ú_semver_prerelease_key  s    

rc  c             C   sh   t | dƒ}|r|jrdnd}nd}||j|j|jf }|sL|jrH|d nd}|jrd|tt|jƒƒ }|S )aË  A sort key-function for sorting semver version string.

    The default sorting order is ascending (0.x -> 1.x -> 2.x).

    If `prerelease_first`, pre-releases will come before
    ALL other semver keys (not just those with same version).
    I.e (1.0-pre, 2.0-pre -> 0.x -> 1.x -> 2.x).

    Otherwise it will sort in the standard way that it simply
    comes before any release with shared version string
    (0.x -> 1.0-pre -> 1.x -> 2.0-pre -> 2.x).
    T)r   )r   r    )r   ra  ÚmajorÚminorZpatchr$  rc  )r[   r  Úvr©   r    r    r!   r    s    
r  c          
   C   sÀ   t t| t|ddƒddid}y| d|j ¡ W n& tk
rX   | d| ¡  ¡ Y nX y.t t	|ƒ¡}t
 | ¡  d¡¡S Q R X W n2 tk
rº } z| d	||¡ ‚ W dd}~X Y nX dS )
z6Fetch the metadata for a package from the npm registryr  )ZsafeZAcceptzHapplication/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*)ZheaderszFetching URL: %szutf-8Nz+Failed to fetch package metadata for %r: %r)r   r   r   r8  Zfull_urlÚAttributeErrorZget_full_urlÚ
contextlibÚclosingr   rx   ry   rz   r{   r	   r  )r‚   rQ   r8   ZreqZresponseÚexcr    r    r!   r  9  s    r  Ú__main__)N)N)N)N)NN)NN)NN)NFNN)NN)NNNNNrY   NF)NN)NN)NN)NFN)NN)NN)NN)NN)N)NN)N)F)hÚ__doc__rh  Zdistutils.versionr   r  rý   rA  rx   r4  r$   Úos.pathrg   r   rU  râ   r.   r1  r+   ru   Ztempfiler   Z	threadingr   Zurllib.requestr   r   r   r   Zurllib.errorr	   Zjupyter_core.pathsr
   Zjupyterlab_server.processr   r   r   Znotebook.nbextensionsr   r   r   r   rR  r   r   r   r   r   r   Zjlpmappr   r   rV  rI   r   r   rH   r"   r'   r(   r4   r@   rB   rG   rJ   rD   rN   rP   rS   rX   r;   r_   ra   rb   rc   rd   re   rf   rh   rj   rm   r   ÚobjectrL   rK   rF   r   rV   rÇ   r  rÕ   rÚ   r  rF  r%  rÑ   r  r
  rõ   r]  rÛ   rc  r  r  r.  r    r    r    r!   Ú<module>   s¨    











  



	
	



	
	

        T
	59

