o
    Ni                     @  s  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
mZ ddlmZ ddlmZ ddlmZ ddlmZ erPdd	lmZ dd
lmZ dZdAddZdBddZdCddZdDddZdEddZdFd"d#ZdGd%d&Zd'd(dHd+d,Zed-Z dId/d0Z!dJd2d3Z"ej#fdKd7d8Z$e$Z%e& pe' Z(ej)Z)G d9d: d:Z*ej+dd; d<k re*Z,G d=d> d>Z-dLd?d@Z.dS )Mz6Operating system-related utility functions for Sphinx.    )annotationsN)StringIOpath)Path)TYPE_CHECKING)__)TracebackType)Any/canonical_pathstrreturnc                C  s   |  ttjS N)replaceSEPr   sep)r    r   F/home/ubuntu/.local/lib/python3.10/site-packages/sphinx/util/osutil.pyos_path   s   r   native_pathstr | os.PathLike[str]c                C  s   t | tjtS )z"Return path in OS-independent form)osfspathr   r   r   r   )r   r   r   r   
canon_path#   s   r   filepathc                C  s   t | }td|S )z+Normalize path separator and unicode stringNFC)r   unicodedata	normalize)r   new_pathr   r   r   path_stabilize(   s   r    basetoc                 C  s   | tr|S | dd t}|dd t}t|dd |dd ddD ]\}}||kr4 n|d |d q*||krEdS t|dkrT|dgkrTd	t S d
t t|d  t| S )z.Return a relative URL from ``base`` to ``to``.#r   NF)strict    .z..)
startswithr   splitzippoplenjoin)r!   r"   b2t2xyr   r   r   relative_uri.   s   
&
r3   fileNonec                 C  s   t j| dd dS )zEnsure that a path exists.T)exist_okN)r   makedirs)r4   r   r   r   	ensuredirE   s   r8   sourceintc                C  s*   t | tjr
|  nt| }|jd  S )a5  Return the last modified time of ``filename``.

    The time is returned as integer microseconds.
    The lowest common denominator of modern file-systems seems to be
    microsecond-level precision.

    We prefer to err on the side of re-rendering a file,
    so we round up to the nearest microsecond.
    i)
isinstancer   DirEntrystatst_mtime_ns)r9   str   r   r   _last_modified_timeJ   s   
r@   destc                 C  s8   t | tjr
|  nt| }tj||j|jfd dS )z!Copy a file's modification times.)nsN)r;   r   r<   r=   utimest_atime_nsr>   )r9   rA   r?   r   r   r   _copy_timesY   s   rE   F)forcerF   boolc                C  s   t | } t |}|  s|  d}t||  }r#tj| |ddse|sB|rBddlm} |t}t	d}|j
|| |ddd	 d
S t| | tt t| | W d
   d
S 1 s^w   Y  d
S d
S )ae  Copy a file and its modification times, if possible.

    :param source: An existing source to copy.
    :param dest: The destination path.
    :param bool force: Overwrite the destination file even if it exists.
    :raise FileNotFoundError: The *source* does not exist.

    .. note:: :func:`copyfile` is a no-op if *source* and *dest* are identical.
    z does not existF)shallowr   )loggingzNAborted attempted copy from %s to %s (the destination path has existing data).misccopy_overwrite)typesubtypeN)r   existsFileNotFoundErrorfilecmpcmpsphinx.utilrI   	getLogger__name__r   warningshutilcopyfile
contextlibsuppressOSErrorrE   )r9   rA   rF   msgdest_existsrI   loggerr   r   r   rW   _   s,   


"rW   z[^a-zA-Z0-9_-]stringc                 C  s   t d| pdS )Nr&   sphinx)	_no_fn_resub)r^   r   r   r   make_filename   s   rb   projectc                 C  s   t | d S )Nz Documentation)rb   removesuffixlower)rc   r   r   r   make_filename_from_project   s   rf   r   startstr | os.PathLike[str] | Nonec                 C  s,   zt j| |W S  ty   t|  Y S w )a  Return a relative filepath to *path* either from the current directory or
    from an optional *start* directory.

    This is an alternative of ``os.path.relpath()``.  This returns original path
    if *path* and *start* are on different drives (for Windows platform).
    )r   r   relpath
ValueErrorr   )r   rg   r   r   r   ri      s
   	ri   c                   @  s.   e Zd ZdZdddZddd	ZdddZdS )_chdirz>Remove this fall-back once support for Python 3.10 is removed.
target_dirr   r   r5   c                C  s   || _ g | _d S r   )r   _dirs)selfrl   r   r   r   __init__      
z_chdir.__init__c                 C  s    | j t  t| j d S r   )rm   appendr   getcwdchdirr   rn   r   r   r   	__enter__   s   z_chdir.__enter__rL   type[BaseException] | NonevalueBaseException | None	tracebackTracebackType | Nonec                C  s   t | j  d S r   )r   rs   rm   r,   )rn   rL   rw   ry   r   r   r   __exit__   s   z_chdir.__exit__N)rl   r   r   r5   r   r5   )rL   rv   rw   rx   ry   rz   r   r5   )rT   
__module____qualname____doc__ro   ru   r{   r   r   r   r   rk      s
    

rk      )      c                   @  sL   e Zd ZdZdddZdd
dZdddZd ddZd!ddZd"ddZ	dS )#FileAvoidWritea  File-like object that buffers output and only writes if content changed.

    Use this class like when writing to a file to avoid touching the original
    file if the content hasn't changed. This is useful in scenarios where file
    mtime is used to invalidate caches or trigger new behavior.

    When writing to this file handle, all writes are buffered until the object
    is closed.

    Objects can be used as context managers.
    r   
str | Pathr   r5   c                 C  s   || _ d | _d S r   )_path_io)rn   r   r   r   r   ro      rp   zFileAvoidWrite.__init__datar   c                 C  s   | j st | _ | j | d S r   )r   r   write)rn   r   r   r   r   r      s   zFileAvoidWrite.writec                 C  s   | j s	d}t||  }| j   z+t| jdd}| }||kr-	 W d   W dS W d   n1 s7w   Y  W n	 tyF   Y nw t| jddd}|| W d   dS 1 s`w   Y  dS )z0Stop accepting writes and write file, if needed.z,FileAvoidWrite does not support empty files.zutf-8)encodingNw)	r   	Exceptiongetvaluecloseopenr   readrZ   r   )rn   r[   bufold_fold_contentfr   r   r   r      s(   
"zFileAvoidWrite.closec                 C  s   | S r   r   rt   r   r   r   ru      s   zFileAvoidWrite.__enter__exc_typetype[Exception]	exc_valuer   ry   r
   rG   c                 C  s   |    dS )NT)r   )rn   r   r   ry   r   r   r   r{      s   zFileAvoidWrite.__exit__namec                 C  s   | j s	d}t|t| j |S )Nz=Must write to FileAvoidWrite before other methods can be used)r   r   getattr)rn   r   r[   r   r   r   __getattr__   s   zFileAvoidWrite.__getattr__N)r   r   r   r5   )r   r   r   r5   r|   )r   r   )r   r   r   r   ry   r
   r   rG   )r   r   r   r
   )
rT   r}   r~   r   ro   r   r   ru   r{   r   r   r   r   r   r      s    




r   c                 C  s(   t j| rt|  d S t |  d S r   )r   r   isdirrV   rmtreeremover   r   r   r   r     s   r   )r   r   r   r   )r   r   r   r   )r   r   r   r   )r!   r   r"   r   r   r   )r4   r   r   r5   )r9   r   r   r:   )r9   r   rA   r   r   r5   )r9   r   rA   r   rF   rG   r   r5   )r^   r   r   r   )rc   r   r   r   )r   r   rg   rh   r   r   )r   r   r   r5   )/r   
__future__r   rX   rP   r   rerV   sysr   ior   r   pathlibr   typingr   sphinx.localer   typesr	   r
   r   r   r   r    r3   r8   r@   rE   rW   compiler`   rb   rf   curdirri   safe_relpathgetfilesystemencodinggetdefaultencodingfs_encodingabspathrk   version_infocdr   r   r   r   r   r   <module>   sP    








0

<