B
    3¢\WR  ã               @   sn  d 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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mZmZmZmZmZ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- yddl.m/Z/ W n" e0k
rJ   ddl&m1Z/ Y nX da2dd„ Z3G dd„ deeƒZ4dS )z?A contents manager that uses the local file system for storage.é    )ÚdatetimeN)Ú
send2trash)Úwebé   )ÚFileCheckpoints)ÚFileManagerMixin)ÚContentsManageré   )Úexists)Úimport_item)ÚAnyÚUnicodeÚBoolÚ
TraitErrorÚobserveÚdefaultÚvalidate)ÚgetcwdÚstring_types)Ú_tz)Ú	is_hiddenÚis_file_hiddenÚto_api_path)ÚAuthenticatedFileHandler)Ú_)Úsamefile)Úsamefile_simplec          	   K   s¬   ddl m} t dt¡ | d dkr(dS tdkr:||da|j}tj 	|¡\}}t 
|¡\}}	||	 dd	¡ }
| d
t|
|jƒ¡ tj|
ddd}| |¡ W dQ R X dS )zkconvert notebooks to Python script after save with nbconvert

    replaces `jupyter notebook --script`
    r   )ÚScriptExporterzE`_post_save_script` is deprecated and will be removed in Notebook 5.0ÚtypeÚnotebookN)ÚparentZoutput_extensionz.txtzSaving script /%sÚwzutf-8)Úencoding)Znbconvert.exporters.scriptr   ÚwarningsÚwarnÚDeprecationWarningÚ_script_exporterÚlogÚosÚpathÚsplitextZfrom_filenameÚgetÚinfor   Úroot_dirÚioÚopenÚwrite)ÚmodelÚos_pathÚcontents_managerÚkwargsr   r'   ÚbaseZextZscriptZ	resourcesZscript_fnameÚf© r7   úElib/python3.7/site-packages/notebook/services/contents/filemanager.pyÚ_post_save_script.   s    
r9   c               @   s@  e Zd ZeddZedƒdd„ ƒZeddddZe	d	ƒd
d„ ƒZ
edddddZedƒdd„ ƒZdd„ Zedƒdd„ ƒZedƒdd„ ƒZeddddZedƒdd„ ƒZedƒdd„ ƒZd d!„ Zd"d#„ Zd$d%„ Zd&d'„ Zd(d)„ Zd?d*d+„Zd@d,d-„ZdAd.d/„ZdBd0d1„ZdCd3d4„ZdDd5d6„Zd7d8„ Z d9d:„ Z!d;d<„ Z"dEd=d>„Z#dS )FÚFileContentsManagerT)Úconfigr-   c             C   s$   y| j jS  tk
r   tƒ S X d S )N)r    Znotebook_dirÚAttributeErrorr   )Úselfr7   r7   r8   Ú_default_root_dirJ   s    z%FileContentsManager._default_root_dirFz?DEPRECATED, use post_save_hook. Will be removed in Notebook 5.0)r;   ÚhelpÚsave_scriptc             C   s"   |d sd S | j  d¡ t| _d S )NÚnewa‰  
        `--script` is deprecated and will be removed in notebook 5.0.

        You can trigger nbconvert via pre- or post-save hooks:

            ContentsManager.pre_save_hook
            FileContentsManager.post_save_hook

        A post-save hook has been registered that calls:

            jupyter nbconvert --to script [notebook]

        which behaves similarly to `--script`.
        )r'   Úwarningr9   Úpost_save_hook)r=   Zchanger7   r7   r8   Ú_update_save_scriptR   s
    z'FileContentsManager._update_save_scriptNa   Python callable or importstring thereof

        to be called on the path of a file just saved.

        This can be used to process the file on disk,
        such as converting the notebook to a script or HTML via nbconvert.

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

            hook(os_path=os_path, model=model, contents_manager=instance)

        - path: the filesystem path to the file just written
        - model: the model representing the file
        - contents_manager: this ContentsManager instance
        )r;   Z
allow_noner?   rC   c             C   s.   |d }t |tƒrt|ƒ}t|ƒs*tdƒ‚|S )NÚvaluezpost_save_hook must be callable)Ú
isinstancer   r   Úcallabler   )r=   ÚproposalrE   r7   r7   r8   Ú_validate_post_save_hooky   s    
z,FileContentsManager._validate_post_save_hookc          
   C   sr   | j rny"| j d|¡ | j ||| d W nD tk
rl } z&| jjd|dd t dd| ¡‚W dd}~X Y nX dS )	z1Run the post-save hook if defined, and log errorszRunning post-save hook on %s)r2   r1   r3   zPost-save hook failed o-n %sT)Úexc_infoiô  z1Unexpected error while running post hook save: %sN)rC   r'   ÚdebugÚ	ExceptionÚerrorr   Ú	HTTPError)r=   r1   r2   Úer7   r7   r8   Úrun_post_save_hook‚   s    z&FileContentsManager.run_post_save_hookc             C   s<   |d }t j |¡s t j |¡}t j |¡s8td| ƒ‚|S )z'Do a bit of validation of the root_dir.rE   z%r is not a directory)r(   r)   ÚisabsÚabspathÚisdirr   )r=   rH   rE   r7   r7   r8   Ú_validate_root_dirŒ   s    z&FileContentsManager._validate_root_dirZcheckpoints_classc             C   s   t S )N)r   )r=   r7   r7   r8   Ú_checkpoints_class_default—   s    z.FileContentsManager._checkpoints_class_defaultz°If True (default), deleting files will send them to the
        platform's trash/recycle bin, where they can be recovered. If False,
        deleting files really deletes them.Zfiles_handler_classc             C   s   t S )N)r   )r=   r7   r7   r8   Ú_files_handler_class_default    s    z0FileContentsManager._files_handler_class_defaultZfiles_handler_paramsc             C   s
   d| j iS )Nr)   )r-   )r=   r7   r7   r8   Ú_files_handler_params_default¤   s    z1FileContentsManager._files_handler_params_defaultc             C   s"   |  d¡}| j|d}t|| jƒS )aW  Does the API style path correspond to 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 exists and is hidden.
        ú/)r)   )ÚstripÚ_get_os_pathr   r-   )r=   r)   r2   r7   r7   r8   r   ¨   s    
zFileContentsManager.is_hiddenc             C   s    |  d¡}|  |¡}tj |¡S )aF  Returns True if the file exists, else returns False.

        API-style wrapper for os.path.isfile

        Parameters
        ----------
        path : string
            The relative path to the file (with '/' as separator)

        Returns
        -------
        exists : bool
            Whether the file exists.
        rX   )rY   rZ   r(   r)   Úisfile)r=   r)   r2   r7   r7   r8   Úfile_existsº   s    

zFileContentsManager.file_existsc             C   s"   |  d¡}| j|d}tj |¡S )ay  Does the API-style path refer to an extant directory?

        API-style wrapper for os.path.isdir

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

        Returns
        -------
        exists : bool
            Whether the path is indeed a directory.
        rX   )r)   )rY   rZ   r(   r)   rS   )r=   r)   r2   r7   r7   r8   Ú
dir_existsÍ   s    
zFileContentsManager.dir_existsc             C   s   |  d¡}| j|d}t|ƒS )aC  Returns True if the path exists, else returns False.

        API-style wrapper for os.path.exists

        Parameters
        ----------
        path : string
            The API path to the file (with '/' as separator)

        Returns
        -------
        exists : bool
            Whether the target exists.
        rX   )r)   )rY   rZ   r
   )r=   r)   r2   r7   r7   r8   r
   á   s    
zFileContentsManager.existsc             C   s„  |   |¡}t |¡}y
|j}W n( ttfk
rF   | j d¡ d}Y nX yt 	|j
¡}W n@ ttfk
r˜   | j d|j
|¡ tdddddtjd}Y nX yt 	|j¡}W n@ ttfk
rê   | j d|j|¡ tdddddtjd}Y nX i }| d	d¡d
 |d< ||d< ||d< ||d< d|d< d|d< d|d< ||d< yt |tj¡|d< W n, tk
r~   | j d|¡ d|d< Y nX |S )z)Build the common base of a contents modelzUnable to get size.NzInvalid mtime %s for %si²  r   r   )ZtzinfozInvalid ctime %s for %srX   éÿÿÿÿÚnamer)   Úlast_modifiedÚcreatedÚcontentÚformatÚmimetypeÚsizeÚwritablez'Failed to check write permissions on %sF)rZ   r(   ÚlstatÚst_sizeÚ
ValueErrorÚOSErrorr'   rB   ÚtzZutcfromtimestampÚst_mtimer   ZUTCÚst_ctimeÚrsplitÚaccessÚW_OKrM   )r=   r)   r2   r,   re   r`   ra   r1   r7   r7   r8   Ú_base_modelô   s@    



zFileContentsManager._base_modelc             C   sÊ  |   |¡}d| }tj |¡s,t d|¡‚n,t|| jƒrX| jsX| j	 
d|¡ t d|¡‚|  |¡}d|d< d|d< |rÆg  |d< }|   |¡}x,t |¡D ]}ytj ||¡}W n4 tk
rè }	 z| j	 d	||	¡ wœW dd}	~	X Y nX yt |¡}
W nT tk
rL }	 z4|	jtjkr*| j	 d
|¡ n| j	 d||	¡ wœW dd}	~	X Y nX t |
j¡sˆt |
j¡sˆt |
j¡sˆ| j	 d|¡ qœ|  |¡rœt||
dsœ| | jd||f dd¡ qœW d|d< |S )zpBuild a model for a directory

        if content is requested, will include a listing of the directory
        zdirectory does not exist: %ri”  z4Refusing to serve hidden directory %r, via 404 ErrorÚ	directoryr   Nre   rb   z"failed to decode filename '%s': %sz%s doesn't existzError stat-ing %s: %sz%s not a regular file)Zstat_resz%s/%sF)r)   rb   Újsonrc   )rZ   r(   r)   rS   r   rN   r   r-   Úallow_hiddenr'   r,   rq   ÚlistdirÚjoinÚUnicodeDecodeErrorrB   rg   rj   ÚerrnoZENOENTÚstatÚS_ISLNKÚst_modeÚS_ISREGÚS_ISDIRrK   Zshould_listr   Úappendr+   )r=   r)   rb   r2   Zfour_o_fourr1   ÚcontentsZos_dirr_   rO   Ústr7   r7   r8   Ú
_dir_model"  sN    




zFileContentsManager._dir_modelc             C   sv   |   |¡}d|d< |  |¡}t |¡d |d< |rr|  ||¡\}}|d dkrddddœ| }||d< |j||d	 |S )
a@  Build a model for a file

        if content is requested, include the file contents.

        format:
          If 'text', the contents will be decoded as UTF-8.
          If 'base64', the raw bytes contents will be encoded as base64.
          If not specified, try to decode as UTF-8, and fall back to base64
        Úfiler   r   rd   Nz
text/plainzapplication/octet-stream)ÚtextÚbase64)rb   rc   )rq   rZ   Ú	mimetypesZ
guess_typeZ
_read_fileÚupdate)r=   r)   rb   rc   r1   r2   Zdefault_mimer7   r7   r8   Ú_file_model\  s    


zFileContentsManager._file_modelc             C   sX   |   |¡}d|d< |  |¡}|rT| j|dd}|  ||¡ ||d< d|d< |  |¡ |S )zœBuild a notebook model

        if content is requested, the notebook content will be populated
        as a JSON structure (not double-serialized)
        r   r   é   )Z
as_versionrb   rs   rc   )rq   rZ   Z_read_notebookZmark_trusted_cellsÚvalidate_notebook_model)r=   r)   rb   r1   r2   Únbr7   r7   r8   Ú_notebook_model|  s    


z#FileContentsManager._notebook_modelc             C   sÄ   |  d¡}|  |¡s$t dd| ¡‚|  |¡}tj |¡rj|dkrZtjdd||f dd‚| j||d	}nV|d
ks„|dkr”| 	d¡r”| j
||d	}n,|dkr°tjdd| dd‚| j|||d}|S )a   Takes a path for an entity and returns its model

        Parameters
        ----------
        path : str
            the API path that describes the relative path for the target
        content : bool
            Whether to include the contents in the reply
        type : str, optional
            The requested type - 'file', 'notebook', or 'directory'.
            Will raise HTTPError 400 if the content doesn't match.
        format : str, optional
            The requested format for file contents. 'text' or 'base64'.
            Ignored if this returns a notebook or directory model.

        Returns
        -------
        model : dict
            the contents model. If content=True, returns the contents
            of the file or directory as well.
        rX   i”  zNo such file or directory: %s)Nrr   i  z%s is a directory, not a %szbad type)Úreason)rb   r   Nz.ipynbrr   z%s is not a directory)rb   rc   )rY   r
   r   rN   rZ   r(   r)   rS   r   Úendswithr‹   r‡   )r=   r)   rb   r   rc   r2   r1   r7   r7   r8   r+     s     


zFileContentsManager.getÚ c          	   C   s~   t || jƒr"| js"t dd| ¡‚tj |¡sN|  ¡  t 	|¡ W dQ R X n,tj 
|¡slt dd| ¡‚n| j d|¡ dS )zcreate a directoryi  z!Cannot create hidden directory %rNzNot a directory: %szDirectory %r already exists)r   r-   rt   r   rN   r(   r)   r
   Úperm_to_403ÚmkdirrS   r'   rK   )r=   r2   r1   r)   r7   r7   r8   Ú_save_directory¹  s    
z#FileContentsManager._save_directoryc          
   C   sÄ  |  d¡}d|krt dd¡‚d|kr>|d dkr>t dd¡‚|  |¡}| j d|¡ | j||d	 y¤|d d
kr°t |d ¡}|  	||¡ |  
||¡ | j |¡s®|  |¡ nV|d dkrÖ|  ||d | d¡¡ n0|d dkrò|  |||¡ nt dd|d  ¡‚W nd tjk
r"   ‚ Y nL tk
rl } z,| jjd||dd t dd||f ¡‚W dd}~X Y nX d}|d d
kr–|  |¡ | dd¡}| j|dd}|r²||d< | j||d |S )z9Save the file model and return the model with no content.rX   r   i  zNo file type providedrb   rr   zNo file content providedz	Saving %s)r1   r)   r   r‚   rc   zUnhandled contents type: %szError while saving file: %s %sT)rJ   iô  z)Unexpected error while saving file: %s %sNÚmessageF)rb   )r1   r2   )rY   r   rN   rZ   r'   rK   Zrun_pre_save_hookÚnbformatZ	from_dictZcheck_and_signZ_save_notebookÚcheckpointsZlist_checkpointsZcreate_checkpointZ
_save_filer+   r‘   rL   rM   r‰   rP   )r=   r1   r)   r2   rŠ   rO   Zvalidation_messager7   r7   r8   ÚsaveÅ  sD    

&
zFileContentsManager.savec          	      s"  |  d¡}ˆ  |¡}tj}tj |¡s6t dd| ¡‚dd„ }‡ fdd„}ˆ jr¢t	j
dkrr||ƒrrt d	d
| ¡‚||ƒr”ˆ j d|¡ t|ƒ dS ˆ j d|¡ tj |¡rô||ƒrÆt d	d
| ¡‚ˆ j d|¡ ˆ  ¡  t |¡ W dQ R X n*ˆ j d|¡ ˆ  ¡  ||ƒ W dQ R X dS )zDelete file at path.rX   i”  z$File or directory does not exist: %sc             S   s6   t jdkrdS t | ¡j}t tj d¡¡j}||kS )N>   ÚdarwinÚwin32Tú~)ÚsysÚplatformr(   ry   Úst_devr)   Ú
expanduser)r2   Zfile_devZhome_devr7   r7   r8   Ú_check_trashý  s
    
z5FileContentsManager.delete_file.<locals>._check_trashc                s6   t j | ¡r2tˆ jdd ƒ}tt  | ¡ƒ|h r2dS dS )NZcheckpoint_dirTF)r(   r)   rS   Úgetattrr”   Úsetru   )r2   Zcp_dir)r=   r7   r8   Úis_non_empty_dir  s
    z9FileContentsManager.delete_file.<locals>.is_non_empty_dirr—   i  zDirectory %s not emptyzSending %s to trashNz<Skipping trash for %s, on different device to home directoryzRemoving directory %szUnlinking file %s)rY   rZ   r(   Úunlinkr)   r
   r   rN   Údelete_to_trashr™   rš   r'   rK   r   rB   rS   r   ÚshutilZrmtree)r=   r)   r2   Zrmr   r    r7   )r=   r8   Údelete_fileõ  s2    




zFileContentsManager.delete_filec          
   C   sÐ   |  d¡}|  d¡}||kr dS |  |¡}|  |¡}tj |¡rZt||ƒsZt dd| ¡‚y$|  ¡  t	 
||¡ W dQ R X W nL tjk
r–   ‚ Y n6 tk
rÊ } zt dd||f ¡‚W dd}~X Y nX dS )zRename a file.rX   Ni™  zFile already exists: %siô  z"Unknown error renaming file: %s %s)rY   rZ   r(   r)   r
   r   r   rN   r   r£   ZmoverL   )r=   Zold_pathÚnew_pathZnew_os_pathZold_os_pathrO   r7   r7   r8   Úrename_file.  s    




zFileContentsManager.rename_filec             C   s   t dƒ| j S )Nz*Serving notebooks from local directory: %s)r   r-   )r=   r7   r7   r8   Úinfo_stringE  s    zFileContentsManager.info_stringc             C   s0   |   |¡r|S d|kr(| dd¡d }nd}|S )zIReturn the initial API path of  a kernel associated with a given notebookrX   r   r   rŽ   )r]   rn   )r=   r)   r1   Z
parent_dirr7   r7   r8   Úget_kernel_pathH  s    
z#FileContentsManager.get_kernel_path)T)TN)T)TNN)rŽ   )rŽ   )N)$Ú__name__Ú
__module__Ú__qualname__r   r-   r   r>   r   r@   r   rD   r   rC   r   rI   rP   rT   rU   r¢   rV   rW   r   r\   r]   r
   rq   r   r‡   r‹   r+   r‘   r•   r¤   r¦   r§   r¨   r7   r7   r7   r8   r:   F   s:   
	
.
:
 

*

09r:   )5Ú__doc__r   rx   r.   r(   r£   ry   r™   r#   r…   r“   r   Ztornador   Zfilecheckpointsr   Zfileior   Zmanagerr   Zutilsr
   Zipython_genutils.importstringr   Z	traitletsr   r   r   r   r   r   r   Zipython_genutils.py3compatr   r   r   r   rk   Znotebook.utilsr   r   r   Znotebook.base.handlersr   Znotebook.transutilsr   Úos.pathr   ÚImportErrorr   r&   r9   r:   r7   r7   r7   r8   Ú<module>   s<   $