
    IbY                     N   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
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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. ddl/m0Z0 da1d Z2 G d dee      Z3y)z?A contents manager that uses the local file system for storage.    )datetimeN)
send2trash)TrashPermissionError)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)_)samefilec                    ddl m} t        j                  dt               | d   dk7  ryt
        	 ||      a|j                  }t        j                  j                  |      \  }}t
        j                  |      \  }}	||	j                  dd	      z   }
|j                  d
t        |
|j                               t        |
dd      5 }|j!                  |       ddd       y# 1 sw Y   yxY w)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)parentoutput_extensionz.txtzSaving script /%swzutf-8)encoding)nbconvert.exporters.scriptr!   warningswarnDeprecationWarning_script_exporterlogospathsplitextfrom_filenamegetinfor   root_diropenwrite)modelos_pathcontents_managerkwargsr!   r-   baseextscript	resourcesscript_fnamefs               H/usr/lib/python3/dist-packages/notebook/services/contents/filemanager.py_post_save_scriptrB   *   s    
 :MMY[mnV}
" )1AB


C  )ID#(66w?FI)--(:FCCLHH +l<L<U<U"VW	lC'	2 a	  s   C##C,c                      e Zd Z ed      Z ed      d        Z eddd      Z e	d      d	        Z
 ed
ddd      Z ed      d        Zd Z ed      d        Z ed      d        Z eddd      Z ed      d        Z ed      d        Zd Zd Zd Zd Zd Zd(dZd)dZd(dZd*d Zd+d!Zd+d"Zd# Z d$ Z!d% Z"d,d&Z#e$d'        Z%y
)-FileContentsManagerT)configr4   c                 b    	 | j                   j                  S # t        $ r t               cY S w xY wN)r$   notebook_dirAttributeErrorr   selfs    rA   _default_root_dirz%FileContentsManager._default_root_dirF   s-    	;;+++ 	8O	s    ..Fz?DEPRECATED, use post_save_hook. Will be removed in Notebook 5.0)rE   helpsave_scriptc                 \    |d   sy | j                   j                  d       t        | _        y )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-   warningrB   post_save_hook)rK   changes     rA   _update_save_scriptz'FileContentsManager._update_save_scriptN   s-    e}  	 0    Na   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
        )rE   
allow_nonerM   rR   c                 r    |d   }t        |t              rt        |      }t        |      st	        d      |S )Nvaluezpost_save_hook must be callable)
isinstancer   r   callabler   rK   proposalrX   s      rA   _validate_post_save_hookz,FileContentsManager._validate_post_save_hooku   s8    !e\*&E>??rU   c                    | j                   r2	 | j                  j                  d|       | j                  |||        yy# t        $ r=}| j                  j	                  d|d       t        j                  dd|       |d}~ww xY w)	z1Run the post-save hook if defined, and log errorszRunning post-save hook on %s)r8   r7   r9   zPost-save hook failed o-n %sTexc_info  z/Unexpected error while running post hook save: N)rR   r-   debug	Exceptionerrorr   	HTTPError)rK   r7   r8   es       rA   run_post_save_hookz&FileContentsManager.run_post_save_hook~   s    g=wG##G5SW#X   g=wQUVmmC+Z[\Z])^_effgs   0A   	B	8BBc                     |d   }t         j                  j                  |      st         j                  j                  |      }t         j                  j	                  |      st        |d      |S )z'Do a bit of validation of the root_dir.rX    is not a directory)r.   r/   isabsabspathisdirr   r[   s      rA   _validate_root_dirz&FileContentsManager._validate_root_dir   sX     !ww}}U#GGOOE*Eww}}U#y(;<==rU   checkpoints_classc                     t         S rG   r   rJ   s    rA   _checkpoints_class_defaultz.FileContentsManager._checkpoints_class_default   s    rU   zIf 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.files_handler_classc                     t         S rG   r   rJ   s    rA   _files_handler_class_defaultz0FileContentsManager._files_handler_class_default   s    ''rU   files_handler_paramsc                     d| j                   iS )Nr/   )r4   rJ   s    rA   _files_handler_params_defaultz1FileContentsManager._files_handler_params_default   s    &&rU   c                 t    |j                  d      }| j                  |      }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   r4   rK   r/   r8   s      rA   r   zFileContentsManager.is_hidden   s5     zz####.$--00rU   c                     |j                  d      }| j                  |      }t        j                  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   )rz   r{   r.   r/   isfiler|   s      rA   file_existszFileContentsManager.file_exists   s4     zz###D)ww~~g&&rU   c                     |j                  d      }| j                  |      }t        j                  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   ry   )rz   r{   r.   r/   rl   r|   s      rA   
dir_existszFileContentsManager.dir_exists   s7      zz####.ww}}W%%rU   c                 ^    |j                  d      }| j                  |      }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   ry   )rz   r{   r   r|   s      rA   r   zFileContentsManager.exists   s.     zz####.grU   c           	         | j                  |      }t        j                  |      }d|z  }t        || j                        r>| j
                  s2| j                  j                  d|       t        j                  d|      	 |j                  }	 t        j                  |j                         }	 t        j                  |j&                        }i }|j)                  dd      d   |d<   ||d<   ||d<   ||d<   d|d<   d|d<   d|d<   ||d<   	 t        j*                  |t        j,                        |d<   |S # t        t        f$ r  | j                  j                  d       d}Y w xY w# t        t        f$ rJ | j                  j                  d|j                   |       t#        dddd	d	t        j$                  
      }Y w xY w# t        t        f$ rJ | j                  j                  d|j&                  |       t#        dddd	d	t        j$                  
      }Y Mw xY w# t        $ r% | j                  j/                  d|       d|d<   Y |S w xY w)z)Build the common base of a contents model$file or directory does not exist: %r<Refusing to serve hidden file or directory %r, via 404 Error  zUnable to get size.NzInvalid mtime %s for %si  r   r   )tzinfozInvalid ctime %s for %srx   namer/   last_modifiedcreatedcontentformatmimetypesizewritablez'Failed to check write permissions on %sF)r{   r.   lstatr   r4   allow_hiddenr-   r3   r   re   st_size
ValueErrorOSErrorrQ   tzutcfromtimestampst_mtimer   UTCst_ctimersplitaccessW_OKrd   )	rK   r/   r8   r3   four_o_fourr   r   r   r7   s	            rA   _base_modelzFileContentsManager._base_model   s&   ##D)xx <tCWdmm,T5F5FHHMMXZab--[11	<<D
	F//>M	@))$--8G C+B/ff!.o"iih jf	& "		'277 ;E* I G$ 	HH23D	 G$ 	F
 HH6wO$T1aAbffEM	F G$ 	@HH6wOtQ1a?G	@"  	&HHNNDgN %E*	&sJ   D4 E& .G 'H 4,E#"E#&AF?>F?AHH*IIc                    | j                  |      }d|}t        j                  j                  |      st	        j
                  d|      t        || j                        r>| j                  s2| j                  j                  d|       t	        j
                  d|      | j                  |      }d|d<   d|d<   |r<g x|d<   }| j                  |      }t        j                  |      D ]  }	 t        j                  j                  ||      }	 t        j                   |      }
t)        j*                  |
j,                        s[t)        j.                  |
j,                        s<t)        j0                  |
j,                        s| j                  j3                  d|       	 | j5                  |      r@| j                  st7        ||
      s'|j9                  | j;                  | d| d             	 d|d<   |S # t        $ r(}	| j                  j                  d	||	       Y d}	~	=d}	~	ww xY w# t"        $ rb}	|	j$                  t$        j&                  k(  r| j                  j                  d
|       n| j                  j                  d||	       Y d}	~	d}	~	ww xY w# t"        $ rF}	|	j$                  t$        j<                  k7  r| j                  j                  d|d       Y d}	~	d}	~	ww xY w)zpBuild a model for a directory

        if content is requested, will include a listing of the directory
        zdirectory does not exist: r   z4Refusing to serve hidden directory %r, via 404 Error	directoryr"   Nr   r   z"failed to decode filename '%s': %sz%s doesn't existzError stat-ing %s: %sz%s not a regular file)stat_resrx   F)r/   r   z+Unknown error checking if file %r is hiddenTr_   jsonr   )r{   r.   r/   rl   r   re   r   r4   r   r-   r3   r   listdirjoinUnicodeDecodeErrorrQ   r   r   errnoENOENTstatS_ISLNKst_modeS_ISREGS_ISDIRrb   should_listr   appendr2   ELOOP)rK   r/   r   r8   r   r7   contentsos_dirr   rf   sts              rA   
_dir_modelzFileContentsManager._dir_model$  sq   
 ##D)24(;ww}}W%--[11w.t7H7HHHMMP --[11  &#ff*,,E)x&&t,F

6* % ggll648G'*B RZZ0 $RZZ 8 $RZZ 8HHNN#:GD''-,,N7UW4X$OO$(HHTF!D62BEH$R7%L %E(OK * HH$$<dAG  ww%,,.(();WE(()@'1M(  ww%++-((I#%) ) sJ   0 G<H0!AJ<	H-H((H-0	J9AJJ	K-';K((K-c                    | j                  |      }d|d<   | j                  |      }t        j                  |      d   |d<   |r:| j	                  ||      \  }}|d   ddd|   }||d<   |j                  ||       |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   r   z
text/plainzapplication/octet-stream)textbase64r   r   )r   r{   	mimetypes
guess_type
_read_fileupdate)rK   r/   r   r   r7   r8   default_mimes          rA   _file_modelzFileContentsManager._file_modelf  s       &f##D)%009!<j"oogv>OGVZ ((8    %1j!LL  
 rU   c                     | j                  |      }d|d<   | j                  |      }|r@| j                  |d      }| j                  ||       ||d<   d|d<   | j	                  |       |S )zBuild a notebook model

        if content is requested, the notebook content will be populated
        as a JSON structure (not double-serialized)
        r#   r"      )
as_versionr   r   r   )r   r{   _read_notebookmark_trusted_cellsvalidate_notebook_model)rK   r/   r   r7   r8   nbs         rA   _notebook_modelz#FileContentsManager._notebook_model  s{       &"f##D)$$W$;B##B-!E)$E(O((/rU   c                    |j                  d      }| j                  |      }d|z  }| j                  |      st        j                  d|      t        || j                        r>| j                  s2| j                  j                  d|       t        j                  d|      t        j                  j                  |      r6|dvrt        j                  d| d| d	      | j                  ||
      }|S |dk(  s|&|j                  d      r| j                  ||
      }|S |dk(  rt        j                  d| dd	      | j!                  |||      }|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   r   r   r   )Nr     z is a directory, not a zbad type)reasonr   r#   z.ipynbr   ri   r   )rz   r{   r   r   re   r   r4   r   r-   r3   r.   r/   rl   r   endswithr   r   )rK   r/   r   r"   r   r8   r   r7   s           rA   r2   zFileContentsManager.get  s^   , zz###D)<tC{{4 --[11Wdmm,T5F5FHHMMXZab--[11 77==!..mmC'+f,CD6$JS]_ _OOD'O:E  ZDLT]]85L((w(?E  {"mmf/0E E $$T76$JErU   c                    t        || j                        r%| j                  st        j                  dd|      t
        j                  j                  |      s/| j                         5  t        j                  |       ddd       yt
        j                  j                  |      st        j                  dd|       | j                  j                  d|       y# 1 sw Y   yxY w)zcreate a directoryr   zCannot create directory NzNot a directory: zDirectory %r already exists)r   r4   r   r   re   r.   r/   r   perm_to_403mkdirrl   r-   rb   )rK   r8   r7   r/   s       rA   _save_directoryz#FileContentsManager._save_directory  s    Wdmm,T5F5F--'?{%KLLww~~g&!!# "!" "w'--'8	%BCCHHNN8'B" "s   +CC(c                    |j                  d      }d|vrt        j                  dd      d|vr|d   dk7  rt        j                  dd      | j                  |      }t	        || j
                        r%| j                  st        j                  dd|      | j                  j                  d	|       | j                  ||
       	 |d   dk(  rit        j                  |d         }| j                  ||       | j                  ||       | j                  j                  |      sx| j!                  |       nf|d   dk(  r&| j#                  ||d   |j%                  d             n8|d   dk(  r| j'                  |||       nt        j                  dd|d          d}|d   dk(  r#| j-                  |       |j%                  dd      }| j%                  |d      }|r||d<   | j/                  ||       |S # t        j                  $ r  t(        $ rA}| j                  j+                  d||d       t        j                  dd| d|       |d}~ww xY w)z9Save the file model and return the model with no content.rx   r"   r   zNo file type providedr   r   zNo file content providedz Cannot create file or directory z	Saving %s)r7   r/   r#   r   r   zUnhandled contents type: zError while saving file: %s %sTr_   ra   z$Unexpected error while saving file:  NmessageFr   )r7   r8   )rz   r   re   r{   r   r4   r   r-   rb   run_pre_save_hooknbformat	from_dictcheck_and_sign_save_notebookcheckpointslist_checkpointscreate_checkpoint
_save_filer2   r   rc   rd   r   rg   )rK   r7   r/   r8   r   rf   validation_messages          rA   savezFileContentsManager.save  sK   zz#--%<==E!eFm{&B--%?@@##D)Wdmm,T5F5F--'G{%STT{G,U6	_V}
*''i(89##B-##GR0''88>**40v&(y)9599X;NOv+-$$WeT:mmC+DU6]O)TUU "=J&((/!&9d!;u-1E)eW=# }} 	 	_HHNN;T1tNT--'KD6QRSTRU%VW]^^	_s   
CG= =I<IIc                 >    |j                  d      } j                  |      }t        j                  }d|z  } j	                  |      st        j                  d|      t        | j                        r% j                  st        j                  dd|       fd} j                  r^t        j                  dk(  r" ||      rt        j                  dd| d	      	  j                  j                  d
|       t        |       yt        j$                  j'                  |      rm ||      rt        j                  dd| d	       j                  j                  d|        j)                         5  t+        j,                  |       ddd       y j                  j                  d|        j)                         5   ||       ddd       y# t         $ r'} j                  j#                  d||       Y d}~d}~ww xY w# 1 sw Y   yxY w# 1 sw Y   yxY w)zDelete file at path.rx   r   r   r   z Cannot delete file or directory c                     t         j                  j                  |       r:t        j                  dd       }t        t        j                  |             |hz
  ryy)Ncheckpoint_dirTF)r.   r/   rl   getattrr   setr   )r8   cp_dirrK   s     rA   is_non_empty_dirz9FileContentsManager.delete_file.<locals>.is_non_empty_dir  sH    ww}}W% !!1!13CTJrzz'*+vh6rU   win32z
Directory z
 not emptyzSending %s to trashNzSkipping trash for %s, %szRemoving directory %szUnlinking file %s)rz   r{   r.   unlinkr   r   re   r   r4   r   delete_to_trashsysplatformr-   rb   r   r   rQ   r/   rl   r   shutilrmtree)rK   r/   r8   rmr   r   rf   s   `      rA   delete_filezFileContentsManager.delete_file  s   zz###D)YY<tC{{4 --[11Wdmm,T5F5F--'G{%STT	 ||w&+;G+D mmC:gYj)IJJJ4g>7# 77==!(mmC:gYj)IJJHHNN2G<!!# 'g&' ' HHNN.8!!# 7  ( J  !<gqIIJ' ' s0   "'G 7H	H	HG??HHHc                    |j                  d      }|j                  d      }||k(  ryt        || j                        st        || j                        r)| j                  st	        j
                  ddt              | j                  |       | j                  |      }| j                  |      }t        j                  j                  |      r%t        ||      st	        j
                  dd|       	 | j                         5  t        j                  ||       ddd       y# 1 sw Y   yxY w# t        j
                  $ r  t         $ r"}t	        j
                  dd| d	|       |d}~ww xY w)
zRename a file.rx   Nr   z Cannot rename file or directory i  zFile already exists: ra   zUnknown error renaming file: r   )rz   r   r4   r   r   re   r8   _validate_pathr{   r.   r/   r   r   r   r   moverc   )rK   old_pathnew_pathnew_os_pathold_os_pathrf   s         rA   rename_filezFileContentsManager.rename_file;  sB   >>#&>>#&xh.)Hdmm2T^b^o^o--'G{%STT 	H%''1''1 77>>+&x[/Q--'<XJ%GHH	\!!# 6K56 6 6}} 	 	\--'DXJaPQs%STZ[[	\s6   6D2 D&D2 &D/+D2 /D2 2E0E++E0c                 2    t        d      | j                  z  S )Nz*Serving notebooks from local directory: %s)r   r4   rJ   s    rA   info_stringzFileContentsManager.info_stringY  s    =>NNrU   c                 f    | j                  |      r|S d|v r|j                  dd      d   }|S d}|S )zIReturn the initial API path of  a kernel associated with a given notebookrx   r   r    )r   r   )rK   r/   r7   
parent_dirs       rA   get_kernel_pathz#FileContentsManager.get_kernel_path\  sD    ??4 K$;S!,Q/J  JrU   c                     t         j                  dk(  rd}nd}|D ]"  }|| v st        j                  dd|  d|        y)zOChecks if the path contains invalid characters relative to the current platformr   z?:><*"|r   r   zPath 'z' contains characters that are invalid for the filesystem. Path names on this filesystem cannot contain any of the following characters: N)r   r   r   re   )r/   invalid_charschars      rA   r   z"FileContentsManager._validate_pathf  sa     <<7"
 &M M! 	IDt|mmC6$ 888E*H I I	IrU   )T)TN)TNN)r   rG   )&__name__
__module____qualname__r   r4   r   rL   r   rN   r   rT   r   rR   r   r]   rg   rm   rp   r   rs   rv   r   r   r   r   r   r   r   r   r2   r   r   r   r   r   r   staticmethodr    rU   rA   rD   rD   B   sh   d#HZ  uT0qrK]0 0( dtN$   g j   ! " 4/0O
 "#( $( #$' %'1$'&&(&2h?DB&/b
C2h.`\<O I IrU   rD   )4__doc__r   r   r.   r   r   r   r)   r   r   r   send2trash.exceptionsr   tornador   filecheckpointsr	   fileior
   managerr   utilsr   ipython_genutils.importstringr   	traitletsr   r   r   r   r   r   r   ipython_genutils.py3compatr   r   r#   r   r   notebook.utilsr   r   r   notebook.base.handlersr   notebook.transutilsr   os.pathr   r,   rB   rD   r  rU   rA   <module>r     s    E
   	   
    ! 6  , $ $  5 P P P ;   < !  0vI*O vIrU   