a
    m b8l                     @   sj  d 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 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 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 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	 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# ddl$m%Z% e&dZ'G dd deZ(G dd  d e(Z)dS )!z#A base class for contents managers.    Nfnmatch)import_item)sign)validate)ValidationError)new_notebook)	HTTPError)RequestHandler)Any)Bool)default)Dict)Instance)List)
TraitError)Type)Unicode)LoggingConfigurable   )FilesHandler   )AsyncCheckpoints)Checkpoints)_i18n)ensure_asyncz\-Copy\d*\.c                   @   s  e Zd ZdZedddZeddddZee	j
Zdd	 Zee g d
dddZeeddddZeddddZeddddZedddddZeddd Zdd ZeeddZeeddZeddZeddd Zeddd Z ee!e"ddd d!Z#edd"dZ$d#d$ Z%d%d& Z&d'd( Z'd\d*d+Z(d,d- Z)d]d.d/Z*d0d1 Z+d2d3 Z,d4d5 Z-d6d7 Z.d8d9 Z/d:d; Z0d<d= Z1d^d>d?Z2d_d@dAZ3dBdC Z4d`dDdEZ5dadFdGZ6dbdHdIZ7dJdK Z8dLdM Z9dcdNdOZ:dddPdQZ;dRdS Z<dTdU Z=dVdW Z>dXdY Z?dZd[ Z@dS )eContentsManagera  Base class for serving files and directories.

    This serves any text or binary file,
    as well as directories,
    with special handling for JSON notebook documents.

    Most APIs take a path argument,
    which is always an API-style unicode path,
    and always refers to a directory.

    - unicode, not url-escaped
    - '/'-separated
    - leading and trailing '/' will be stripped
    - if unspecified, path defaults to '',
      indicating the root path.

    /TconfigFzAllow access to hidden files)r   helpc                 C   s   t j| dS )N)parent)r   NotebookNotaryself r%   Glib/python3.9/site-packages/jupyter_server/services/contents/manager.py_notary_default?   s    zContentsManager._notary_default)__pycache__z*.pycz*.pyoz	.DS_Storez*.soz*.dylibz*~zC
        Glob patterns to hide in file and directory listings.
    ZUntitledz4The base name used when creating untitled notebooks.untitledz0The base name used when creating untitled files.zUntitled Folderz6The base name used when creating untitled directories.Nau  Python callable or importstring thereof

        To be called on a contents model prior to save.

        This can be used to process the structure,
        such as removing notebook outputs or other side effects that
        should not be saved.

        It will be called as (all arguments passed by keyword)::

            hook(path=path, model=model, contents_manager=self)

        - model: the model to be saved. Includes file contents.
          Modifying this dict will affect the file that is stored.
        - path: the API path of the save destination
        - contents_manager: this ContentsManager instance
        )r   
allow_noner    pre_save_hookc                 C   s0   |d }t |trt| j}t|s,td|S )Nvaluezpre_save_hook must be callable)
isinstancestrr   r+   callabler   )r$   Zproposalr,   r%   r%   r&   _validate_pre_save_hookx   s    

z'ContentsManager._validate_pre_save_hookc                 K   sl   | j rhz*| jd| | j f ||| d| W n6 tyD    Y n$ tyf   | jjd|dd Y n0 dS )z0Run the pre-save hook if defined, and log errorszRunning pre-save hook on %s)modelpathZcontents_managerzPre-save hook failed on %sT)exc_infoN)r+   logdebugr	   	Exceptionerror)r$   r1   r2   kwargsr%   r%   r&   run_pre_save_hook   s    z!ContentsManager.run_pre_save_hookcheckpointsc                 C   s   | j f i | jS Ncheckpoints_classcheckpoints_kwargsr#   r%   r%   r&   _default_checkpoints   s    z$ContentsManager._default_checkpointsr>   c                 C   s   t | | jdS N)r!   r4   dictr4   r#   r%   r%   r&   _default_checkpoints_kwargs   s    z+ContentsManager._default_checkpoints_kwargsav  handler class to use when serving raw file requests.

        Default is a fallback that talks to the ContentsManager API,
        which may be inefficient, especially for large files.

        Local files-based ContentsManagers can use a StaticFileHandler subclass,
        which will be much more efficient.

        Access to these files should be Authenticated.
        )klassr*   r   r    zExtra parameters to pass to files_handler_class.

        For example, StaticFileHandlers generally expect a `path` argument
        specifying the root directory from which to serve files.
        c                 C   s"   g }| j r|d| j | jf |S )z[Return additional handlers

        Default: self.files_handler_class on /files/.*
        z/files/(.*))files_handler_classappendfiles_handler_params)r$   handlersr%   r%   r&   get_extra_handlers   s    z"ContentsManager.get_extra_handlersc                 C   s   t dS a=  Does a directory exist at the given path?

        Like os.path.isdir

        Override this method in subclasses.

        Parameters
        ----------
        path : string
            The path to check

        Returns
        -------
        exists : bool
            Whether the path does indeed exist.
        NNotImplementedErrorr$   r2   r%   r%   r&   
dir_exists   s    zContentsManager.dir_existsc                 C   s   t dS a/  Is path a hidden directory or file?

        Parameters
        ----------
        path : string
            The path to check. This is an API path (`/` separated,
            relative to root dir).

        Returns
        -------
        hidden : bool
            Whether the path is hidden.

        NrK   rM   r%   r%   r&   	is_hidden   s    zContentsManager.is_hidden c                 C   s   t ddS aA  Does a file exist at the given path?

        Like os.path.isfile

        Override this method in subclasses.

        Parameters
        ----------
        path : string
            The API path of a file to check for.

        Returns
        -------
        exists : bool
            Whether the file exists.
        !must be implemented in a subclassNrK   rM   r%   r%   r&   file_exists   s    zContentsManager.file_existsc                 C   s   |  |p| |S )0  Does a file or directory exist at the given path?

        Like os.path.exists

        Parameters
        ----------
        path : string
            The API path of a file or directory to check for.

        Returns
        -------
        exists : bool
            Whether the target exists.
        )rT   rN   rM   r%   r%   r&   exists   s    zContentsManager.existsc                 C   s   t ddS zGet a file or directory model.rS   NrK   r$   r2   contenttypeformatr%   r%   r&   get  s    zContentsManager.getc                 C   s   t ddS z
        Save a file or directory model to path.

        Should return the saved model with no content.  Save implementations
        should call self.run_pre_save_hook(model=model, path=path) prior to
        writing any data.
        rS   NrK   r$   r1   r2   r%   r%   r&   save  s    zContentsManager.savec                 C   s   t ddS z%Delete the file or directory at path.rS   NrK   rM   r%   r%   r&   delete_file  s    zContentsManager.delete_filec                 C   s   t ddS zRename a file or directory.rS   NrK   r$   Zold_pathnew_pathr%   r%   r&   rename_file   s    zContentsManager.rename_filec                 C   s2   | d}|stdd| | | j| dS z7Delete a file/directory and any associated checkpoints.r     zCan't delete rootNstripr	   ra   r:   Zdelete_all_checkpointsrM   r%   r%   r&   delete'  s
    


zContentsManager.deletec                 C   s   |  || | j|| dS z<Rename a file and any checkpoints associated with that file.Nre   r:   Zrename_all_checkpointsrc   r%   r%   r&   rename/  s    zContentsManager.renamec                 C   sB   | d}|d| d}||kr0| || | j|dd}|S )Update the file's path

        For use in PATCH requests, to enable renaming a file without
        re-uploading its contents. Only used for renaming at the moment.
        r   r2   FrY   ri   r\   rm   r$   r1   r2   rd   r%   r%   r&   update4  s    
zContentsManager.updatec                 C   s   dS )NzServing contentsr%   r#   r%   r%   r&   info_stringA  s    zContentsManager.info_stringc                 C   s   dS )aM  Return the API path for the kernel

        KernelManagers can turn this value into a filesystem path,
        or ignore it altogether.

        The default value here will start kernels in the directory of the
        notebook server. FileContentsManager overrides this to use the
        directory containing the notebook.
        rQ   r%   )r$   r2   r1   r%   r%   r&   get_kernel_pathD  s    
zContentsManager.get_kernel_pathc                 C   s   | d}|d\}}}|dkr2|d\}}}|| }t D ]@}|rXd||}	nd}	dj||	|d}
| d||
sB qqB|
S )	  Increment a filename until it is unique.

        Parameters
        ----------
        filename : unicode
            The name of a file, including extension
        path : unicode
            The API path of the target's directory
        insert : unicode
            The characters to insert after the base filename

        Returns
        -------
        name : unicode
            A filename that is unique, based on the input filename.
        r   .ipynb{}{}rQ   {basename}{insert}{suffix}basenameinsertsuffix{}/{})ri   
rpartition	partition	itertoolscountr[   rV   )r$   filenamer2   r|   r{   dotextr}   iinsert_inamer%   r%   r&   increment_filenameP  s    
z"ContentsManager.increment_filenamec                 C   s^   zt |d  W nH tyX } z0d|jtj|jddd d|d< W Y d}~n
d}~0 0 |S )	z&Add failed-validation message to modelrY   z"Notebook validation failed: {}:
{}r   c                 S   s   dS )Nz	<UNKNOWN>r%   )objr%   r%   r&   <lambda>|      z9ContentsManager.validate_notebook_model.<locals>.<lambda>)indentr   messageN)validate_nbr   r[   r   jsondumpsinstance)r$   r1   er%   r%   r&   validate_notebook_modelu  s    z'ContentsManager.validate_notebook_modelc                 C   s   | d}| |s"tdd| i }|r2||d< |dkrH|dd n|dd d}|d d	krp| j}d
}n>|d dkr| j}d}n&|d dkr| j}ntdd|d  | j|| ||d}d||}| 	||S )Create a new untitled file or directory in path

        path must be a directory

        File extension can be specified.

        Use `new` to create files with a fully specified path (including filename).
        r     No such directory: %srZ   .ipynbnotebookfilerQ   	directory rg   Unexpected model type: %rr|   {0}/{1})
ri   rN   r	   
setdefaultuntitled_directoryuntitled_notebookuntitled_filer   r[   new)r$   r2   rZ   r   r1   r|   r)   r   r%   r%   r&   new_untitled  s,    	

zContentsManager.new_untitledc                 C   s   | d}|du ri }|dr.|dd n|dd d|vr|d dkr|d dkrnt |d< d	|d
< nd|d< d|d< d|d
< | ||}|S zCreate a new file or directory and return its model with no content.

        To create a new untitled entity in a directory, use `new_untitled`.
        r   Nr   rZ   r   r   rY   r   r   r[   rQ   textri   endswithr   r   r_   r^   r%   r%   r&   r     s    



zContentsManager.newc           	      C   s   | d}|dur| d}d|v r6|dd\}}nd}|}| |}|dd |dd |d dkrvtd	d
|du r|}| |rtd|}| j||dd}d	||}| 
||}|S a  Copy an existing file and return its new model.

        If to_path not specified, it will be the parent directory of from_path.
        If to_path is a directory, filename will increment `from_path-Copy#.ext`.
        Considering multi-part extensions, the Copy# part will be placed before the first dot for all the extensions except `ipynb`.
        For easier manual searching in case of notebooks, the Copy# part will be placed before the last dot.

        from_path must be a full path to a file.
        r   Nr   rQ   r2   r   rZ   r   rg   zCan't copy directoriesrv   z-Copyr   r   )ri   rsplitr\   popr	   rN   copy_patsubr   r[   r_   	r$   Z	from_pathZto_pathr2   Zfrom_dir	from_namer1   r   Zto_namer%   r%   r&   copy  s(    





zContentsManager.copyc                 C   s   | j |   d S r;   )r4   infors   r#   r%   r%   r&   log_info  s    zContentsManager.log_infoc                 C   s>   |  |}|d }| jd| | j|d | || dS )Explicitly trust a notebook

        Parameters
        ----------
        path : string
            The path of a notebook
        rY   Trusting notebook %sTNr\   r4   warningnotary
mark_cellscheck_and_signr$   r2   r1   nbr%   r%   r&   trust_notebook  s
    
zContentsManager.trust_notebookc                 C   s,   | j |r| j | n| jd| dS )a  Check for trusted cells, and sign the notebook.

        Called as a part of saving notebooks.

        Parameters
        ----------
        nb : dict
            The notebook dict
        path : string
            The notebook's path (for logging)
        Notebook %s is not trustedN)r   Zcheck_cellsr   r4   r   )r$   r   r2   r%   r%   r&   r     s    zContentsManager.check_and_signc                 C   s0   | j |}|s| jd| | j || dS )a$  Mark cells as trusted if the notebook signature matches.

        Called as a part of loading notebooks.

        Parameters
        ----------
        nb : dict
            The notebook object (in current nbformat)
        path : string
            The notebook's path (for logging)
        r   N)r   Zcheck_signaturer4   r   r   )r$   r   r2   Ztrustedr%   r%   r&   mark_trusted_cells  s    z"ContentsManager.mark_trusted_cellsc                    s   t  fdd| jD  S )z:Should this file/directory name be displayed in a listing?c                 3   s   | ]}t  |V  qd S r;   r   ).0globr   r%   r&   	<genexpr>  r   z.ContentsManager.should_list.<locals>.<genexpr>)any
hide_globs)r$   r   r%   r   r&   should_list  s    zContentsManager.should_listc                 C   s   | j | |S )Create a checkpoint.r:   create_checkpointrM   r%   r%   r&   r     s    z!ContentsManager.create_checkpointc                 C   s   | j | || dS z'
        Restore a checkpoint.
        Nr:   restore_checkpointr$   Zcheckpoint_idr2   r%   r%   r&   r   !  s    z"ContentsManager.restore_checkpointc                 C   s   | j |S r;   r:   list_checkpointsrM   r%   r%   r&   r   '  s    z ContentsManager.list_checkpointsc                 C   s   | j ||S r;   r:   delete_checkpointr   r%   r%   r&   r   *  s    z!ContentsManager.delete_checkpoint)rQ   )TNN)N)rQ   rQ   )rQ   rQ   rQ   )NrQ   )N)rQ   )rQ   )A__name__
__module____qualname____doc__r   root_dirr   Zallow_hiddenr   r   r"   r   r'   r   r   r   r   r   r   r   r+   r   r0   r9   r   r   r=   r:   r   r>   r   r?   rC   r   r
   rE   rG   rI   rN   rP   rT   rV   r\   r_   ra   re   rj   rm   rr   rs   rt   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r%   r%   r%   r&   r   &   s   
	




	




%
&

$

r   c                   @   s   e Zd ZdZeeddZeeddZe	ddZ
eddd Zeddd	 Zd
d Zdd Zd4ddZdd Zd5ddZdd Zdd Zdd Zdd Zdd Zd d! Zd6d"d#Zd7d$d%Zd8d&d'Zd9d(d)Zd*d+ Zd,d- Zd.d/ Zd0d1 Z d2d3 Z!dS ):AsyncContentsManagerz<Base class for serving files and directories asynchronously.Tr   r:   c                 C   s   | j f i | jS r;   r<   r#   r%   r%   r&   r?   5  s    z)AsyncContentsManager._default_checkpointsr>   c                 C   s   t | | jdS r@   rA   r#   r%   r%   r&   rC   9  s    z0AsyncContentsManager._default_checkpoints_kwargsc                    s   t dS rJ   rK   rM   r%   r%   r&   rN   C  s    zAsyncContentsManager.dir_existsc                    s   t dS rO   rK   rM   r%   r%   r&   rP   V  s    zAsyncContentsManager.is_hiddenrQ   c                    s   t ddS rR   rK   rM   r%   r%   r&   rT   g  s    z AsyncContentsManager.file_existsc                    s(   t | |I dH p&t | |I dH S )rU   N)r   rT   rN   rM   r%   r%   r&   rV   z  s    zAsyncContentsManager.existsNc                    s   t ddS rW   rK   rX   r%   r%   r&   r\     s    zAsyncContentsManager.getc                    s   t ddS r]   rK   r^   r%   r%   r&   r_     s    zAsyncContentsManager.savec                    s   t ddS r`   rK   rM   r%   r%   r&   ra     s    z AsyncContentsManager.delete_filec                    s   t ddS rb   rK   rc   r%   r%   r&   re     s    z AsyncContentsManager.rename_filec                    s>   | d}|stdd| |I dH  | j|I dH  dS rf   rh   rM   r%   r%   r&   rj     s
    

zAsyncContentsManager.deletec                    s*   |  ||I dH  | j||I dH  dS rk   rl   rc   r%   r%   r&   rm     s    zAsyncContentsManager.renamec                    sN   | d}|d| d}||kr6| ||I dH  | j|ddI dH }|S )rn   r   r2   NFro   rp   rq   r%   r%   r&   rr     s    
zAsyncContentsManager.updatec                    s   | d}|d\}}}|dkr2|d\}}}|| }t D ]N}|rXd||}	nd}	dj||	|d}
t| d||
I d	H }|sB qqB|
S )
ru   r   rv   rw   rx   rQ   ry   rz   r~   N)ri   r   r   r   r   r[   r   rV   )r$   r   r2   r|   r{   r   r   r}   r   r   r   rT   r%   r%   r&   r     s     
z'AsyncContentsManager.increment_filenamec           	         s   | d}t| |I dH }|s0tdd| i }|r@||d< |dkrV|dd n|dd d	}|d d
kr~| j}d}n>|d dkr| j}d}n&|d dkr| j}ntdd|d  | j|| ||dI dH }d	||}| 
||I dH S )r   r   Nr   r   rZ   r   r   r   rQ   r   r   rg   r   r   r   )ri   r   rN   r	   r   r   r   r   r   r[   r   )	r$   r2   rZ   r   rN   r1   r|   r)   r   r%   r%   r&   r     s.    	
z!AsyncContentsManager.new_untitledc                    s   | d}|du ri }|dr.|dd n|dd d|vr|d dkr|d dkrnt |d< d	|d
< nd|d< d|d< d|d
< | ||I dH }|S r   r   r^   r%   r%   r&   r     s    



zAsyncContentsManager.newc           	         s   | d}|dur| d}d|v r6|dd\}}nd}|}| |I dH }|dd |dd |d dkr|td	d
|du r|}t| |I dH rtd|}| j	||ddI dH }d
||}| ||I dH }|S r   )ri   r   r\   r   r	   r   rN   r   r   r   r[   r_   r   r%   r%   r&   r   )  s(    



zAsyncContentsManager.copyc                    sD   |  |I dH }|d }| jd| | j|d | || dS )r   NrY   r   Tr   r   r%   r%   r&   r   L  s
    z#AsyncContentsManager.trust_notebookc                    s   | j | |I dH S )r   Nr   rM   r%   r%   r&   r   [  s    z&AsyncContentsManager.create_checkpointc                    s   | j | ||I dH  dS r   r   r   r%   r%   r&   r   _  s    z'AsyncContentsManager.restore_checkpointc                    s   | j |I d H S r;   r   rM   r%   r%   r&   r   e  s    z%AsyncContentsManager.list_checkpointsc                    s   | j ||I d H S r;   r   r   r%   r%   r&   r   h  s    z&AsyncContentsManager.delete_checkpoint)rQ   )TNN)rQ   rQ   )rQ   rQ   rQ   )NrQ   )N)"r   r   r   r   r   r   r=   r   r:   r   r>   r   r?   rC   rN   rP   rT   rV   r\   r_   ra   re   rj   rm   rr   r   r   r   r   r   r   r   r   r   r%   r%   r%   r&   r   .  s8   


	


	
&
'

#r   )*r   r   r   rer   Zipython_genutils.importstringr   Znbformatr   r   r   r   Znbformat.v4r   Ztornado.webr	   r
   Z	traitletsr   r   r   r   r   r   r   r   r   Ztraitlets.config.configurabler   Zfiles.handlersr   r:   r   r   Zjupyter_server.transutilsr   Zjupyter_server.utilsr   compiler   r   r   r%   r%   r%   r&   <module>   sD   
    