o
    3g$                     @  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mZ zddl	Z	W n< e
y`   ddlZzddlmZ ddlmZmZ ddlmZmZmZ W n e
yU   ed  w ejdd
dZY nw ee	droejdddZnejdddZG dd dZG dd dZG dd deZG dd dZdS )z
Atomic file operations
    )annotationsN)local)error)LOCKFILE_EXCLUSIVE_LOCKLOCKFILE_FAIL_IMMEDIATELY)
OVERLAPPED
LockFileEx
UnlockFilezDOn Windows, Plumbum requires Python for Windows Extensions (pywin32)Tc                 c  s    t | }zt|t|rdntB ddt  W n ty) } zt|j d d }~ww zd V  W t	|dddd d S t	|dddd w )Nr   l    )
msvcrtget_osfhandler   r   r   r   WinErrorOSErrorargsr	   )filenoblockinghndlex r   I/home/garg/my-data/venv/lib/python3.10/site-packages/plumbum/fs/atomic.pylocked_file   s&   

&r   lockfc              
   c  J    t | t j|r
dnt jB  zd V  W t | t j d S t | t j w Nr   )fcntlr   LOCK_EXLOCK_NBLOCK_UNr   r   r   r   r   r   3   
   "c              
   c  r   r   )r   flockr   r   r   r   r   r   r   r   =   r   c                   @  s   e Zd ZdZdZd ddZdd Zdd	 Zd
d Zdd Z	dd Z
dd Zejd!ddZdd Zdd Zdd Zdd Zdd ZdS )"
AtomicFilea%  
    Atomic file operations implemented using file-system advisory locks (``flock`` on POSIX,
    ``LockFile`` on Windows).

    .. note::
        On Linux, the manpage says ``flock`` might have issues with NFS mounts. You should
        take this into account.

    .. versionadded:: 1.3
    i   Fc                 C  s4   t || _|| _t | _d | _d | _|   d S N)	r   path_ignore_deletion	threadingLock_thdlock	_owned_by_fileobjreopen)selffilenameignore_deletionr   r   r   __init__T   s   
zAtomicFile.__init__c                 C  s   | j r
d| j dS dS )Nz<AtomicFile: >z<AtomicFile: closed>)r(   r"   r*   r   r   r   __repr__\   s   zAtomicFile.__repr__c                 C     |    d S r!   closer/   r   r   r   __del___      zAtomicFile.__del__c                 C     | S r!   r   r/   r   r   r   	__enter__b      zAtomicFile.__enter__c                 C  r1   r!   r2   r*   tvtbr   r   r   __exit__e   r5   zAtomicFile.__exit__c                 C  s"   | j d ur| j   d | _ d S d S r!   )r(   r3   r/   r   r   r   r3   h   s   


zAtomicFile.closec                 C  s4   |    ttt| jtjtjB ddd| _dS )z
        Close and reopen the file; useful when the file was deleted from the file system
        by a different process
        i  zr+br   N)	r3   osfdopenopenstrr"   O_CREATO_RDWRr(   r/   r   r   r   r)   m   s   
zAtomicFile.reopenTc              
   c  s    | j t krdV  dS | jG t| j |& | j s&| j	s&t
dt | _ zdV  W d| _ nd| _ w W d   n1 sBw   Y  W d   dS W d   dS 1 sZw   Y  dS )a  
        A context manager that locks the file; this function is reentrant by the thread currently
        holding the lock.

        :param blocking: if ``True``, the call will block until we can grab the file system lock.
                         if ``False``, the call may fail immediately with the underlying exception
                         (``IOError`` or ``WindowsError``)
        Nz#Atomic file removed from filesystem)r'   r$   	get_identr&   r   r(   r   r"   existsr#   
ValueError)r*   r   r   r   r   lockedw   s   

PzAtomicFile.lockedc                 C  s8   |    | j  W d   dS 1 sw   Y  dS )zL
        Atomically delete the file (holds the lock while doing it)
        N)rG   r"   deleter/   r   r   r   rH      s   
"zAtomicFile.deletec                 C  sF   | j d g }	 | j | j}|| t|| jk rnq	d|S )Nr   T    )r(   seekread
CHUNK_SIZEappendlenjoin)r*   databufr   r   r   	_read_all   s   

zAtomicFile._read_allc                 C  s4   |    |  W  d   S 1 sw   Y  dS )zAtomically read the entire fileN)rG   rR   r/   r   r   r   read_atomic   s   
$zAtomicFile.read_atomicc                 C  s   |   S )z*Read the file **without** holding the lock)rR   r/   r   r   r   read_shared   s   zAtomicFile.read_sharedc                 C  s   |   2 | jd |r$|d| j }| j| |t|d }|s| j  | j  W d   dS 1 s9w   Y  dS )zWrites the given data atomically to the file. Note that it overwrites the entire file;
        ``write_atomic("foo")`` followed by ``write_atomic("bar")`` will result in only ``"bar"``.
        r   N)rG   r(   rJ   rL   writerN   flushtruncate)r*   rP   chunkr   r   r   write_atomic   s   

"zAtomicFile.write_atomicN)FT)__name__
__module____qualname____doc__rL   r-   r0   r4   r7   r=   r3   r)   
contextlibcontextmanagerrG   rH   rR   rS   rT   rY   r   r   r   r   r    F   s"    


r    c                   @  sP   e Zd ZdZdddZdd Zdd Zd	d
 Zedd Z	dddZ
dd ZdS )AtomicCounterFileal  
    An atomic counter based on AtomicFile. Each time you call ``next()``, it will
    atomically read and increment the counter's value, returning its previous value

    Example::

        acf = AtomicCounterFile.open("/some/file")
        print(acf.next())  # e.g., 7
        print(acf.next())  # 8
        print(acf.next())  # 9

    .. versionadded:: 1.3
    r   c                 C  s   || _ || _dS )z
        :param atomicfile: an :class:`AtomicFile <plumbum.atomic.AtomicFile>` instance
        :param initial: the initial value (used when the first time the file is created)
        N)
atomicfileinitial)r*   rb   rc   r   r   r   r-      s   
zAtomicCounterFile.__init__c                 C  r6   r!   r   r/   r   r   r   r7      r8   zAtomicCounterFile.__enter__c                 C  r1   r!   r2   r9   r   r   r   r=      r5   zAtomicCounterFile.__exit__c                 C     | j   d S r!   rb   r3   r/   r   r   r   r3         zAtomicCounterFile.closec                 C  s   | t |S )zJ
        Shortcut for ``AtomicCounterFile(AtomicFile(filename))``
        )r    )clsr+   r   r   r   r@      s   zAtomicCounterFile.openNc                 C  sD   |du r| j }t|tstdt|| jt|d dS )z
        Reset the counter's value to the one given. If ``None``, it will default to the
        initial value provided to the constructor
        Nzvalue must be an integer, not utf8)	rc   
isinstanceint	TypeErrortyperb   rY   rA   encode)r*   valuer   r   r   reset   s
   
zAtomicCounterFile.resetc                 C  sn   | j  ( | j  d}|s| jnt|}| j t|d d |W  d   S 1 s0w   Y  dS )zN
        Read and increment the counter, returning its previous value
        rh      N)	rb   rG   rS   decoderc   rj   rY   rA   rm   )r*   currr   r   r   next   s   $zAtomicCounterFile.next)r   r!   )r[   r\   r]   r^   r-   r7   r=   r3   classmethodr@   ro   rs   r   r   r   r   ra      s    


ra   c                   @  s   e Zd ZdZdd ZdS )PidFileTakenz
    This exception is raised when PidFile.acquire fails to lock the pid file. Note that it
    derives from ``SystemExit``, so unless explicitly handled, it will terminate the process
    cleanly
    c                 C  s   t | | || _d S r!   )
SystemExitr-   pid)r*   msgrw   r   r   r   r-      s   
zPidFileTaken.__init__N)r[   r\   r]   r^   r-   r   r   r   r   ru      s    ru   c                   @  sH   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dS )PidFileaj  
    A PID file is a file that's locked by some process from the moment it starts until it dies
    (the OS will clear the lock when the process exits). It is used to prevent two instances
    of the same process (normally a daemon) from running concurrently. The PID file holds its
    process' PID, so you know who's holding it.

    .. versionadded:: 1.3
    c                 C  s   t || _d | _d S r!   )r    rb   _ctx)r*   r+   r   r   r   r-     s   

zPidFile.__init__c                 C  r1   r!   )acquirer/   r   r   r   r7     r5   zPidFile.__enter__c                 C  r1   r!   )releaser9   r   r   r   r=     r5   zPidFile.__exit__c                 C  s8   t t |   W d    d S 1 sw   Y  d S r!   )r_   suppress	Exceptionr|   r/   r   r   r   r4     s   
"zPidFile.__del__c                 C  rd   r!   re   r/   r   r   r   r3     rf   zPidFile.closec                 C  s   | j durdS | jjdd| _ z| j   W n0 tyF   d| _ z| j  d}W n ty7   d}Y nw td| jj	d| |dw | j
tt d t| j dS )z
        Attempt to acquire the PID file. If it's already locked, raises
        :class:`PidFileTaken <plumbum.atomic.PidFileTaken>`. You should normally acquire
        the file as early as possible when the program starts
        NF)r   rh   Unknownz	PID file z taken by process )rz   rb   rG   r7   r   rT   striprq   ru   r"   rY   rA   r>   getpidrm   atexitregisterr|   )r*   rw   r   r   r   r{     s*   

zPidFile.acquirec                 C  s>   | j du rdS | j  z| j ddd W d| _ dS d| _ w )zW
        Release the PID file (should only happen when the program terminates)
        N)rz   rb   rH   r=   r/   r   r   r   r|   1  s   

zPidFile.releaseN)r[   r\   r]   r^   r-   r7   r=   r4   r3   r{   r|   r   r   r   r   ry      s    	ry   rZ   )r^   
__future__r   r   r_   r>   r$   plumbum.machines.localr   r   ImportErrorr
   
pywintypesr   r   win32conr   r   	win32filer   r   r	   printr`   r   hasattrr    ra   rv   ru   ry   r   r   r   r   <module>   sB    
!	o=