
    ^j                       U 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ZddlZddlmZmZ ddl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mZmZmZm Z m!Z!m"Z"m#Z# dd
l$m%Z% ddl&m'Z' ddl(m)Z)m*Z*m+Z+ erddl,m-Z-m.Z. ed   Z/dZ0de1d<   dZ2de1d<    e3edd      Z4de1d<    e3edd      Z5de1d<   e
jl                  dk7  xr ejn                  ejp                  v Z9de1d<    e       Z:de1d<    ejv                         a<de1d<    e=       Z>d e1d!<    G d" d#e?      Z@ G d$ d%e@&      ZA G d' d(ej                        ZCdd)d@d*ZDdAd+ZEdd)dBd,ZFdd)dCd-ZGdDd.ZHdd)dEd/ZIdd)	 	 	 	 	 	 	 	 	 dFd0ZJdd)dGd1ZKdHd2ZLdId3ZMdJd4ZN ed56       G d7 d8             ZOe G d9 d:             ZP ed56       G d; d<             ZQe G d= d>             ZRdKd?ZS ej                  eS        e eA       d%gZUy)LzZCross-process and cross-host reader/writer lock built on :class:`SoftFileLock` primitives.    )annotationsN)contextmanagersuppress)	dataclass)Path)TYPE_CHECKINGFinalLiteral)WeakValueDictionary)AcquireReturnProxy_ensure_current_process_fork_transition_raise_grouped_errors_register_fork_class_register_fork_object_register_owned_descriptor_unregister_owned_descriptor)Timeout)SoftFileLock)ensure_directory_existstouch	write_all)Callable	Generator)readwritez.breakz
Final[str]_BREAK_SUFFIXi   z
Final[int]_MAX_MARKER_SIZE
O_NOFOLLOW_O_NOFOLLOW
O_NONBLOCK_O_NONBLOCKwin32zFinal[bool]_SUPPORTS_DIR_FDz2Final[WeakValueDictionary[int, SoftReadWriteLock]]_ALL_INSTANCESthreading.Lock_ALL_INSTANCES_LOCKzFinal[set[Path]]_SINGLETONS_UNDER_CONSTRUCTIONc                  f     e Zd ZU ded<   ded<   	 ddddddd		 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d fd
Z xZS )_SoftRWMeta,WeakValueDictionary[Path, SoftReadWriteLock]
_instanceszthreading.RLock_instances_lockT      >@N      ?blockingis_singletonheartbeat_intervalstale_thresholdpoll_intervalc          
        t                |st        | 	  |||||||      S t        |      j	                         }| j
                  5  | j                  j                  |      }	|	|t        v rd|}
t        |
      t        j                         }t        j                  |       	 t        | 	  |||||||      }	t        j                  |       t        j                         |k7  rd}
t        |
      |	| j                  |<   nK|	j                  |k7  s|	j                  |k7  r-d|	j                   d|	j                   d| d| }
t!        |
      |	cd d d        S # t        j                  |       w xY w# 1 sw Y   y xY w)Nr0   z2Singleton lock construction is already active for zOLock construction cannot continue after fork; construct a new lock in the childz$Singleton lock created with timeout=z, blocking=z, cannot be changed to timeout=)r   super__call__r   resolver-   r,   getr(   RuntimeErrorosgetpidadddiscardtimeoutr1   
ValueError)cls	lock_filer@   r1   r2   r3   r4   r5   
normalizedinstancemsgconstruction_pid	__class__s               b/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/filelock/_soft_rw/_sync.pyr8   z_SoftRWMeta.__call__:   s    	 !7#!)#5 /+ $   )_,,.
   	~~))*5H!??Nym\C&s++#%99; .22:>G$w/!!)%1+=(7&3  0  H 3:::F99;"22kC&s++-5z*!!W,0A0AX0M:8;K;K:LKX`XiXiWj k55<I[
T  !o%=	 	& 3:::F'	 	s&   	AE8)E?BE8E55E88F)rC   str | os.PathLike[str]r@   floatr1   boolr2   rN   r3   rM   r4   float | Noner5   rM   returnSoftReadWriteLock)__name__
__module____qualname____annotations__r8   __classcell__rH   s   @rI   r*   r*   6   s    <<$$
 6
 !$((,#6)6 6
 6 6 "6 &6 6 
6 6    r*   c                     e Zd ZU dZ e       Zded<    ej                         Z		 d$dddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d%d	Z
ed&d
       Zed'ddd(d       Zed'ddd(d       Zd'ddd)dZd'ddd)dZe	 d$dd	 	 	 	 	 	 	 d*d       Zd&dZddd+dZd,dZ	 	 	 	 	 	 	 	 d-dZ	 	 	 	 	 	 	 	 	 	 d.dZd/dZ	 	 	 	 	 	 	 	 d0dZd1dZd1dZ	 	 	 	 	 	 	 	 d0dZ	 	 	 	 	 	 	 	 d2dZd&dZd3dZd4d Z d5d!Z!d3d"Z"d&d#Z#y)6rQ   u
  
    Cross-process and cross-host reader/writer lock built on :class:`SoftFileLock` primitives.

    Use this class instead of :class:`~filelock.ReadWriteLock` when the lock file lives on a network
    filesystem (NFS, Lustre with ``-o flock``, HPC cluster shared storage). ``ReadWriteLock`` is backed
    by SQLite and cannot run on NFS because SQLite's ``fcntl`` locking is unreliable there.

    Layout on disk for a lock at ``foo.lock``:

    - ``foo.lock.state`` — a :class:`SoftFileLock` taken only during state transitions (microseconds).
    - ``foo.lock.write`` — writer marker; its presence means a writer is claiming or holding the lock.
    - ``foo.lock.readers/<host>.<pid>.<uuid>`` — one file per reader.

    Each marker stores a random token (``secrets.token_hex(16)``), the holder's pid, and the holder's
    hostname. A daemon heartbeat thread refreshes ``mtime`` on every held marker. A marker whose mtime
    has not advanced in ``stale_threshold`` seconds may be evicted by any process on any host, giving
    correct behavior when a compute node crashes with a lock held.

    Writer acquire is two-phase and writer-preferring: phase 1 claims ``.write`` (blocking any new
    reader), phase 2 waits for existing readers to drain. Writer starvation is impossible.

    Reentrancy, upgrade/downgrade rules, thread pinning, and singleton caching by resolved path match
    :class:`~filelock.ReadWriteLock`.

    Forking invalidates the inherited instance in the child so the child cannot double-own the lock with its parent;
    ``release()`` on that instance is a no-op, and the child must construct a new instance if it needs a lock.

    Trust boundary: protects against same-UID non-cooperating processes (one host or cross-host) and
    same-host different-UID users via ``0o600`` / ``0o700`` permissions. Does not protect against root
    compromise, NTP tampering on same-UID cross-host nodes, or multi-tenant mounts where hostile
    co-tenants share the UID.

    :param lock_file: path to the lock file; sidecar state/write/readers live next to it
    :param timeout: maximum wait time in seconds; ``-1`` means block indefinitely
    :param blocking: if ``False``, raise :class:`~filelock.Timeout` immediately on contention
    :param is_singleton: if ``True``, reuse existing instances for the same resolved path
    :param heartbeat_interval: seconds between heartbeat refreshes; default 30 s
    :param stale_threshold: seconds of ``mtime`` inactivity before a marker is stale; defaults to
        ``3 * heartbeat_interval``, matching etcd's ``LeaseKeepAlive`` convention
    :param poll_interval: seconds between acquire retries under contention; default 0.25 s

    .. versionadded:: 3.27.0

    r+   r,   Tr.   Nr/   r0   c               6   t        j                         | _        |dk  rd| }t        |      ||dz  }||k  rd| d| d}t        |      |dk  rd| }t        |      t        j                  |      | _        || _        || _        || _        || _	        || _
        t        | j
                   d| j
                   d	| j
                   d
      | _        t        | j
                         t        t        j                          t        j                          t#        | j                  j$                  d            | _        d | _        d | _        d | _        d| _        t0        5  | t2        t5        |       <   d d d        t7        |        y # 1 sw Y   xY w)Nr   z)heartbeat_interval must be positive, got    z0stale_threshold must exceed heartbeat_interval (z <= )z$poll_interval must be positive, got z.statez.writez.readers)stater   readersrK   r@   internaltransactionr]   F)r<   r=   _creator_pidrA   fspathrC   r@   r1   r3   r4   r5   _Paths_pathsr   _Locks	threadingLockr   r]   _locks_readers_dir_fd_readers_dir_fd_token_hold_closedr'   r%   idr   )	selfrC   r@   r1   r2   r3   r4   r5   rF   s	            rI   __init__zSoftReadWriteLock.__init__   s    IIK"=>P=QRCS/!"014O00D_DUUYZlYmmnoCS/!A8HCS/! ii	2%&);&5$1^^$F+^^$F+~~&h/

 	 /^^%!(t{{00"=

 ,015"#'
"  	,'+N2d8$	,d#	, 	,s   (FFc                    t        j                         at               | _        t        j
                         | _        t        j                          y N)	rh   ri   r'   r   r,   RLockr-   r(   clear)rB   s    rI   _reset_class_after_forkz)SoftReadWriteLock._reset_class_after_fork   s6     (nn.,.'oo/&,,.rX   r1   c             #     K   | j                  ||       	 d | j                          y# | j                          w xY ww)a  
        Context manager that acquires and releases a shared read lock.

        Falls back to instance defaults for *timeout* and *blocking* when ``None``.

        :param timeout: maximum wait time in seconds, or ``None`` to use the instance default
        :param blocking: if ``False``, raise :class:`~filelock.Timeout` immediately; ``None`` uses the instance default

        :raises RuntimeError: if a write lock is already held on this instance
        :raises Timeout: if the lock cannot be acquired within *timeout* seconds

        rw   N)acquire_readreleaserp   r@   r1   s      rI   	read_lockzSoftReadWriteLock.read_lock   s5      	'H5	LLNDLLN   A, A>Ac             #     K   | j                  ||       	 d | j                          y# | j                          w xY ww)a@  
        Context manager that acquires and releases an exclusive write lock.

        Falls back to instance defaults for *timeout* and *blocking* when ``None``.

        :param timeout: maximum wait time in seconds, or ``None`` to use the instance default
        :param blocking: if ``False``, raise :class:`~filelock.Timeout` immediately; ``None`` uses the instance default

        :raises RuntimeError: if a read lock is already held, or a write lock is held by a different thread
        :raises Timeout: if the lock cannot be acquired within *timeout* seconds

        rw   N)acquire_writerz   r{   s      rI   
write_lockzSoftReadWriteLock.write_lock   s5      	7X6	LLNDLLNr}   c               *    | j                  d||      S )uf  
        Acquire a shared read lock.

        If this instance already holds a read lock, the lock level is incremented (reentrant). Attempting to acquire a
        read lock while holding a write lock raises :class:`RuntimeError` (downgrade not allowed). On the 0→1
        transition a daemon heartbeat thread is started that refreshes the reader marker's ``mtime`` every
        ``heartbeat_interval`` seconds so peers on other hosts do not evict the marker as stale.

        :param timeout: maximum wait time in seconds, or ``None`` to use the instance default; ``-1`` means block
            indefinitely
        :param blocking: if ``False``, raise :class:`~filelock.Timeout` immediately when the lock is unavailable;
            ``None`` uses the instance default

        :returns: a proxy that can be used as a context manager to release the lock

        :raises RuntimeError: if a write lock is already held on this instance, if this instance was invalidated by
            :func:`os.fork`, or if :meth:`close` was called
        :raises Timeout: if the lock cannot be acquired within *timeout* seconds

        r   rw   _acquirer{   s      rI   ry   zSoftReadWriteLock.acquire_read  s    * }}VWx}@@rX   c               *    | j                  d||      S )a  
        Acquire an exclusive write lock.

        If this instance already holds a write lock from the same thread, the lock level is incremented (reentrant).
        Attempting to acquire a write lock while holding a read lock raises :class:`RuntimeError` (upgrade not
        allowed). Write locks are pinned to the acquiring thread: a different thread trying to re-enter also raises
        :class:`RuntimeError`.

        Writer acquisition runs in two phases. Phase 1 atomically claims ``<path>.write`` via ``O_CREAT | O_EXCL``,
        which immediately blocks any new reader on any host. Phase 2 waits for existing readers to drain. Writer
        starvation is impossible: new readers see ``<path>.write`` during phase 2 and wait behind the pending writer.

        :param timeout: maximum wait time in seconds, or ``None`` to use the instance default; ``-1`` means block
            indefinitely
        :param blocking: if ``False``, raise :class:`~filelock.Timeout` immediately when the lock is unavailable;
            ``None`` uses the instance default

        :returns: a proxy that can be used as a context manager to release the lock

        :raises RuntimeError: if a read lock is already held, if a write lock is held by a different thread, if this
            instance was invalidated by :func:`os.fork`, or if :meth:`close` was called
        :raises Timeout: if the lock cannot be acquired within *timeout* seconds

        r   rw   r   r{   s      rI   r   zSoftReadWriteLock.acquire_write  s    2 }}Wg}AArX   c                    | |||      S )a  
        Return the singleton :class:`SoftReadWriteLock` for *lock_file*.

        :param lock_file: path to the lock file; sidecar state/write/readers live next to it
        :param timeout: maximum wait time in seconds; ``-1`` means block indefinitely
        :param blocking: if ``False``, raise :class:`~filelock.Timeout` immediately when the lock is unavailable

        :returns: the singleton lock instance

        :raises ValueError: if an instance already exists for this path with different *timeout* or *blocking* values

        rw    )rB   rC   r@   r1   s       rI   get_lockzSoftReadWriteLock.get_lock9  s    ( 9g99rX   c                <   | j                   t        j                         k7  ry| j                  d       | j                  j
                  5  | j                  r
	 ddd       yd| _        | j                  |t               5  | j                  t        | j                         d| _	        | j                  dc}| _        t        t              5  t        j                  |       ddd       ddd       ddd       y# 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y   yxY w)u  
        Release any held lock and release internal filesystem resources.

        Idempotent. After calling this method the instance can no longer acquire locks — subsequent acquires raise
        :class:`RuntimeError`. A fork-invalidated instance is closed without raising.
        NTforce)rc   r<   r=   rz   rj   ra   rn   rk   r   rl   r   r   OSErrorclose)rp   fds     rI   r   zSoftReadWriteLock.closeO  s     		+4 [[!! 	%||	% 	%  DL##/%' %11=4T5O5OP15D./3/C/CT,B,!'* %%%	% 	%% %% %	% 	%sC   D"D?ADC:!D)D:D?DD	DDFr   c                  | j                   t        j                         k7  ry| j                  j                  5  | j
                  }|3|r
	 ddd       yd| j                   dt        |        d}t        |      |rd|_	        n|xj                  dz  c_	        |j                  dkD  r
	 ddd       yd| _        ddd       j                  j                          |j                  j                  | j                  dz          |j                  r"t!        |j"                  | j$                  	       y| j'                  |j(                         y# 1 sw Y   xY w)
a8  
        Release one level of the current lock.

        When the lock level reaches zero the heartbeat thread is stopped and the held marker file is unlinked. On a
        fork-invalidated instance (that is, the child of a :func:`os.fork` call made while the parent held a lock)
        this method is a no-op so inherited ``with`` blocks can unwind cleanly in the child.

        :param force: if ``True``, release the lock completely regardless of the current lock level

        :raises RuntimeError: if no lock is currently held and *force* is ``False``

        NzCannot release a lock on  (lock id: z) that is not heldr      g      ?r_   dir_fd)rc   r<   r=   rj   ra   rm   rC   ro   r;   levelheartbeat_stopsetheartbeat_threadjoinr3   	is_reader_unlinkmarker_namerk   _unlink_writer_marker_if_ourstoken)rp   r   holdrF   s       rI   rz   zSoftReadWriteLock.releasef  s$    		+[[!! 	::D|		 	
 2$..1ARPTXJVhi"3''


a
zzA~	 	 DJ	" 	!""4+B+BS+H"I>>D$$T-A-AB..tzz:-	 	s   EAE3EEc                P   | j                   j                  5  t        | j                  j                        x}
	 d d d        y |\  }}| t        j                  |j                  |      s
	 d d d        y t        | j                  j                         d d d        y # 1 sw Y   y xY wrs   )	rj   r]   _read_markerrf   r   hmaccompare_digestr   r   )rp   r   r   info_s        rI   r   z/SoftReadWriteLock._unlink_writer_marker_if_ours  s     [[ 	'$T[[%6%677@	' 	' GD!|4#6#6tzz5#I	' 	' DKK%%&	' 	' 	's   #B(B4BB%c                  | j                   t        j                         k7  rd| j                   d}t	        |      || j
                  n|}|| j                  n|}| j                  j                  5  | j                  rd| j                   d}t	        |      | j                  | j                  |      cd d d        S 	 d d d        t        j                         }|s'| j                  j                  j                  d      }nS|dk(  r'| j                  j                  j                  d      }n'| j                  j                  j                  d|      }|st!        | j                        d 	 | j#                  ||||      | j                  j                  j%                          S # 1 sw Y   xY w# | j                  j                  j%                          w xY w)	NzSoftReadWriteLock on z4 was invalidated by fork(); construct a new instancez has been closedFrw   rK   T)r1   r@   )rc   r<   r=   rC   r;   r@   r1   rj   ra   rn   rm   _validate_reentranttimeperf_counterrb   acquirer   _do_acquire_innerrz   )rp   moder@   r1   rF   startacquireds          rI   r   zSoftReadWriteLock._acquire  s    		+)$..)99mnCs##")/$,,w$,$44==([[!! 	6||-dnn-==MN"3''zz%//5	6 	6 &		6 !!#{{..666FH]{{..666EH{{..66g6VH$..)t3	.))$)RKK##++-'	6 	6& KK##++-s   3AF,3F8 ,F58&Gc                  | j                   j                  5  | j                  | j                  |      cd d d        S 	 d d d        |dk(  rd n||z   }t	        j
                  d      }|dk(  r| j                  |||      \  }}n| j                  |||      \  }}t        j                         }	t        | j                  | j                  |	dt        |       d      }
| j                   j                  5  t        d||dk(  rt        j                         nd ||||
|		      | _        d d d        |
j!                          t#        | 
      S # 1 sw Y   xY w# 1 sw Y   2xY w)NrK      r   deadliner1   zfilelock-heartbeat-x)refreshinterval
stop_eventnamer   )r   r   write_thread_idr   r   r   r   r   lock)rj   ra   rm   r   secrets	token_hex_acquire_writer_slot_acquire_reader_slotrh   Event_HeartbeatThread_refresh_markerr3   ro   _Hold	get_identr   r   )rp   r   effective_timeoutr   r1   r   r   r   r   r   	heartbeats              rI   r   z#SoftReadWriteLock._do_acquire_inner  s]    [[!! 	6zz%//5	6 	6%	6 -24@Q8Q!!"%7?%)%>%>uxbj%>%k"K%)%>%>uxbj%>%k"K__&
$((,,!&r$xl3	
	 [[!! 
	9=	 3 3 5d'#!*)	DJ
	 	!t,,9	6 	6 
	 
	s   E62EEE"c                   | j                   }|J |j                  |k7  rB|dk(  rdnd}|dk(  rdnd}d| d| j                   dt        |        d| d	| d
}t	        |      |dk(  rYt        j                         x}|j                  k7  r6d| j                   dt        |        d| d|j                   }t	        |      |xj                  dz  c_        t        |       S )Nr   r   	downgradeupgradezCannot acquire z	 lock on r   z): already holding a z lock (z not allowed)zCannot acquire write lock on z) from thread z while it is held by thread r   r   )
rm   r   rC   ro   r;   rh   r   r   r   r   )rp   r   r   opposite	directionrF   curs          rI   r   z%SoftReadWriteLock._validate_reentrant  s   zz99"&&.wfH'+v~9I!$y0@BtH: V%%-Jgi[O  s##7?y':':'< <AUAUU//?{2d8* U"e#?@T@T?UW  s##

a
!t,,rX   c                    j                          d fd}d fd} j                  |||       	  j                  |||        j                  j
                  dfS # t        $ r  j                          w xY w)Nc                 ~     j                   j                  5   j                        cd d d        S # 1 sw Y   y xY wrs   )rj   r]   _claim_writer_markerrp   r   s   rI   try_claim_writerz@SoftReadWriteLock._acquire_writer_slot.<locals>.try_claim_writer  s3    "" 80078 8 8s   3<c                     j                   j                  5   j                        s j                        s
	 d d d        y j	                  t        j
                                 j                          cd d d        S # 1 sw Y   y xY wNF)rj   r]   _touch_writer_marker_if_oursr   _break_stale_readersr   _any_readersr   s   rI   readers_drained_touchingzHSoftReadWriteLock._acquire_writer_slot.<locals>.readers_drained_touching  su    "" / 88?HaHabgHh 	/ /
 ))$))+6,,../ / /s   $B3BBr   FrP   rN   )_open_readers_dir	_wait_forr   r   rf   r   )rp   r   r   r1   r   r   s   ``    rI   r   z&SoftReadWriteLock._acquire_writer_slot  s     	 	8	/ 	'(XN	NN3hQYNZ {{  %''  	 ..u5		s   A" "A>c                    t        | j                  j                  | j                  t	        j                                t        | j                  j                        ry	 t        | j                  j                  |       y# t        $ r Y yw xY w)Nr4   nowFT)_break_stale_markerrf   r   r4   r   _file_exists_atomic_create_markerFileExistsErrorr   s     rI   r   z&SoftReadWriteLock._claim_writer_marker  sq     	DKK--t?S?SY]YbYbYde))*	!$++"3"3U;   		s     B 	BBc                @   t        | j                  j                        }|y	 	 t        j                  |t
        dz         }t        |      }| t        j                  |j                  |      s	 t        j                  |       yt        t              5  t        | j                  j                  |       d d d        	 t        j                  |       y# t        $ r Y t        j                  |       yw xY w# 1 sw Y   DxY w# t        j                  |       w xY w)NFr   r   T)_open_markerrf   r   r<   r   r   r   r   _parse_marker_bytesr   r   r   r   r   )rp   r   r   datar   s        rI   r   z.SoftReadWriteLock._touch_writer_marker_if_ours'  s     $++++,:	wwr#3a#78 't,D|4#6#6tzz5#I
 HHRL	 '" 0dkk''B/0HHRL   HHRL
0 0 HHRLsG   C -D D "C:7D 	C7D 6C77D :D?D Dc               T     j                          t        j                         j                   dt	        j
                           j                  t        t         j                  j                        z        d fd} j                  |||       dfS dfS )N.c                 f   j                   j                  5  t        j                  j                  j
                  t        j                                t        j                  j                        r
	 d d d        y t                nt               	 d d d        y# 1 sw Y   y xY w)Nr   Fr   T)	rj   r]   r   rf   r   r4   r   r   r   )r   full_reader_pathreader_namerp   r   s   rI   try_claim_readerz@SoftReadWriteLock._acquire_reader_slot.<locals>.try_claim_readerH  s    "" #DKK$5$5tG[G[aeajajalm 1 12   %)+uVL)*:EB  s   AB' B''B0r   Tr   )r   uuiduuid4hexr<   r=   rk   strr   rf   r^   r   )rp   r   r   r1   r   r   r   r   s   ``   @@@rI   r   z&SoftReadWriteLock._acquire_reader_slot<  s     	 ))*!BIIK=9%%tDKK$7$78;FG		 		 	'(XN%1$NN7G$NNrX   c                  	  |       ry t        j                         }|st        | j                        |||k\  rt        | j                        | j                  }|t        |t        ||z
  d            }t        j                  |       )Ng        )r   r   r   rC   r5   minmaxsleep)rp   	predicater   r1   r   	sleep_fors         rI   r   zSoftReadWriteLock._wait_forV  s     {##%Cdnn--#xdnn--**I#	3x#~s+CD	JJy! rX   c           
        t        | j                  j                        }t        t              5  |j                  d       d d d        t        j                  | j                  j                        }t        j                  |j                        st        j                  |j                        s$| j                  j                   d}t        |      | j                  t        rt               5  t        j                   | j                  j                  t        j"                  t%        t        dd      z  t&        z        }	 t)        |      }|| _        || _        d d d        y y y # 1 sw Y   (xY w# t*        $ r?}	 t        j,                  |        # t*        $ r}t/        d||       Y d }~ d }~ww xY wd }~ww xY w# 1 sw Y   y xY w)Ni  )r   zB exists but is not a directory or is a symlink; refusing to use itO_DIRECTORYr   z>reader directory registration and descriptor close both failed)r   rf   r^   r   r   mkdirr<   lstatstatS_ISLNKst_modeS_ISDIRr;   rk   r$   r   openO_RDONLYgetattrr    r   BaseExceptionr   r   rl   )rp   readers_pathstrF   r   r   registration_errorclose_errors           rI   r   z#SoftReadWriteLock._open_readers_dirj  s}   DKK//0o& 	+E*	+ XXdkk))*<<

#4<<

+C[[(())klCs##',<!# 3WWT[[00"++M[\@]2]`k2kl6r:E (*$-2*3 3 -='	+ 	+ % 	  ) -\.' 
 		3 3s`   E(1AG E5G (E25	F=?FF8	F5F0+F80F55F88F==G  G	c                0    | j                         D ]  } y y)NTF)_iter_reader_entries)rp   r   s     rI   r   zSoftReadWriteLock._any_readers  s     **, 	A	rX   c              #    K   | j                   Wt        j                  | j                         5 }|D ](  }t        |j                        r|j                  df * 	 ddd       yt        | j                  j                        }t        j                  |      5 }|D ]4  }t        |j                        rt        ||j                  z        df 6 	 ddd       y# 1 sw Y   yxY w# 1 sw Y   yxY ww)a#  
        Yield ``(name, dirfd_relative)`` pairs for every live reader marker.

        ``dirfd_relative`` is ``True`` when *name* should be passed to ``dir_fd=``-aware syscalls; ``False``
        when *name* is a full path because dirfd-relative I/O is unavailable on this platform.
        NTF)	rk   r<   scandir_is_housekeeping_namer   r   rf   r^   r   )rp   itentryr   s       rI   r  z&SoftReadWriteLock._iter_reader_entries  s      +D001 /R /E0<#jj$..// DKK//0ZZ% 	@ @,UZZ8lUZZ78%??@	@ 	@/ 	@ 	@s@   ,C6C
C=C6C*6C*	C6C'#C6*C3/C6c                    g }	 | j                         D ]&  \  }}|j                  ||r| j                  nd f       ( 	 |D ]  \  }}t	        || j
                  ||         y # t        $ r Y y w xY w)N)r4   r   r   )r  appendrk   r   r   r4   )rp   r   namesr   dirfd_relativer   s         rI   r   z&SoftReadWriteLock._break_stale_readers  s    .0	(,(A(A(C W$ndND$8$8PTUVW  	`HD"d6J6JPS\^_	`  		s   9A" "	A.-A.c                   | j                   j                  5  | j                  }|
	 d d d        y|j                  }|j                  }|j
                  r| j                  nd }d d d        	 t              }	 	 t        |      }t        |      }| t        j                  |j                        s	 t        j                  |       yt!        t              5  t#        ||       d d d        	 t        j                  |       y# 1 sw Y   xY w# t        $ r Y yt        $ r Y yw xY w# t        $ r Y t        j                  |       yw xY w# 1 sw Y   ixY w# t        j                  |       w xY w)NFr   Tr   )rj   ra   rm   r   r   r   rk   _open_marker_fdFileNotFoundErrorr   _read_marker_fdr<   r   r   r   r   r   r   )rp   r   r   r   r   r   r   r   s           rI   r   z!SoftReadWriteLock._refresh_marker  sM   [[!! 	F::D|	F 	F **KJJE-1^^T))F	F	 V<B
	&r* 't,D |4#6#6tzz5#I HHRL	 '" *kb)*HHRLM	F 	F" ! 	 		
   HHRL* * HHRLsp   D2D+D :D* -E 	E E&E D	D'D'&D'*	E3E 
EE EE E1c                    t        t        j                         t        j                         | j                  j                        | _        d | _        d | _        d | _        y )Nr`   )rg   rh   ri   rj   r]   rm   rk   rl   rp   s    rI   _reset_after_fork_in_childz,SoftReadWriteLock._reset_after_fork_in_child  sH    ^^%!(++##

 
#%)"rX   rJ   )rC   rL   r@   rM   r1   rN   r2   rN   r3   rM   r4   rO   r5   rM   rP   NonerP   r  rs   )r@   rO   r1   bool | NonerP   zGenerator[None])r@   rO   r1   r  rP   r   )rC   rL   r@   rM   r1   rN   rP   rQ   )r   rN   rP   r  )r   r   rP   r  )r   _Moder@   rO   r1   r  rP   r   )
r   r  r   rM   r   rM   r1   rN   rP   r   )r   r  rP   r   )r   r   r   rO   r1   rN   rP   ztuple[str, bool])r   r   rP   rN   )r   Callable[[], bool]r   rO   r1   rN   rP   r  r   )rP   zGenerator[tuple[str, bool]])r   rM   rP   r  )$rR   rS   rT   __doc__r   r,   rU   rh   rt   r-   rq   classmethodrv   r   r|   r   ry   r   r   r   rz   r   r   r   r   r   r   r   r   r   r   r   r  r   r   r  r   rX   rI   rQ   rQ   s   sx   +Z @S?TJ<T%ioo'O
 1$
 !$((,#1$)1$ 1$
 1$ 1$ "1$ &1$ 1$ 
1$f / / QU  & RV  &ATX A.BUY B6  :
 :): :
 : 
: :*%. (- %;N' . .  .
  . 
 .D$-$- !$- 	$- $- 
$-L-( ( ( 	 (
  ( 
 (D*OO 	O
 O 
O4"%" 	"
 " 
"(38
@&`'R*rX   rQ   )	metaclassc                  <     e Zd Z	 	 	 	 	 	 	 	 	 	 d fdZddZ xZS )r   c                R    t         |   |d       || _        || _        || _        y )NT)r   daemon)r7   rq   _refresh	_interval_stop_event)rp   r   r   r   r   rH   s        rI   rq   z_HeartbeatThread.__init__  s-     	d40!%rX   c                    | j                   j                  | j                        sR| j                         s| j                   j	                          y | j                   j                  | j                        sQy y rs   )r#  waitr"  r!  r   r  s    rI   runz_HeartbeatThread.run  sR    ""''7==?  $$& ""''7rX   )
r   r  r   rM   r   threading.Eventr   r   rP   r  r  )rR   rS   rT   rq   r&  rV   rW   s   @rI   r   r     s=    
&#
& 
& $	
&
 
& 

&rX   r   r   c                  t        | |      }|y 	 t        j                  |      }t        j                  |j
                        s#d |j                  ft        j                  |       S t        j                  |t        dz         }	 t        j                  |       t        |      |j                  fS # t        $ r Y t        j                  |       y w xY w# t        j                  |       w xY w)Nr   r   )r   r<   fstatr   S_ISREGr   st_mtimer   r   r   r   r   )r   r   r   r  r   s        rI   r   r     s    	d6	*B	zXXb\
 ||BJJ'$
 		 wwr+a/0 	t$bkk11	  
 	s*   AB3 )B3 3	C<C CC C.c                <    t        j                  | t        dz         S )Nr   )r<   r   r   r   s    rI   r  r    s    772'!+,,rX   c                   t         j                  t        z  t        z  }t        r|t        j
                  | ||      S t        j
                  | |      S Nr   )r<   r   r    r"   r$   r   )r   r   flagss      rI   r  r    sF     KK+%3E2BvGY2774v.s_a_f_fgkmr_ssrX   c               <    	 t        | |      S # t        $ r Y y w xY wr.  )r  r   r   r   s     rI   r   r     s&    tF33 s    	c                   | rt        |       t        kD  ry 	 | j                  d      }t	        j
                  d|t        j                        }|y t        |d   d      }|dkD  ry t        |d   ||d         S # t        $ r Y y w xY w)	Nasciiu  
        \A                                  # start of string
        (?P<token>    [0-9a-f]{32}     ) \n # 128-bit hex token
        (?P<pid>      [1-9][0-9]{0,9}  ) \n # decimal pid: no leading zero, ≤ 10 digits
        (?P<hostname> [\x21-\x7e]{1,253})   # printable non-whitespace ASCII (RFC 1123 hostname limit)
        \n*                                 # tolerate sloppy writers that append extra newlines
        \Z                                  # end of string
        pid
   ir   hostname)r   r4  r6  )	lenr   decodeUnicodeDecodeErrorrematchVERBOSEint_MarkerInfo)r   textr;  r4  s       rI   r   r     s     3t9//{{7# HH	 	


E }
eElB
C
YU7^uZ?PQQ'  s   A9 9	BBc                   t        t              5  t        r|t        j                  | |       nt        |       j	                          d d d        y # 1 sw Y   y xY wr.  )r   r  r$   r<   unlinkr   r1  s     rI   r   r   5  sF    	#	$   2IId6*J     s   :AAc               (   t        | |      x}y|\  }}||z
  |k  ry|t        | |       y|  t         dt        j                          dt        j                  d       }	 t        r|t        j                  | |||       nt        |       j                  |       t        ||      }|y|\  }	}
|	t        ||       yt        j                  |j                  |	j                        sy|
|kD  ryt        ||       y# t        $ r Y yw xY w)Nr   FTr   r   )
src_dir_fd
dst_dir_fd)r   r   r   r<   r=   r   r   r$   renamer   r   r   r   r   )r   r4   r   r   read_resultinfo_beforemtime_before
break_name
read_after
info_aftermtime_afters              rI   r   r   >  s"    $D88A +K
\_,V$6-"))+a8I8I"8M7NOJ 2IIdJ6fMJj) j8J(J
6*{00*2B2BC\!Jv&  s   %<D 	DDc          	        t         j                  t         j                  z  t         j                  z  t        z  }t
        r|t        j                  | |d|      }nt        j                  | |d      }d }	 t        j                  |      }|j                  |j                  f}t        || dt        j                          dt        j                          dj                  d             t        j                  |       y # t         $ r4 t        j                  |       |t#        | ||      rt%        | |        w xY w)Ni  r   
r3  )r<   O_CREATO_EXCLO_WRONLYr    r$   r   r)  st_devst_inor   r=   socketgethostnameencoder   r   
_same_filer   )r   r   r   r/  r   identityr  s          rI   r   r   j  s     JJ"R[[0;>EF.WWT5%7WWT5%( (,H
XXb\99bii'"r"))+b1C1C1E0FbIPPQXYZ 	  
JtXf$MD(	s   6A5D =D>c                   	 t         r|t        j                  | |      nt        j                  |       }|j                  |j
                  f|k(  S # t        $ r Y yw xY w)Nr   F)r$   r<   r   r   rR  rS  )r   rX  r   r  s       rI   rW  rW    s[    .>6CURXXd6*[][c[cdh[i IIryy!X--  s   4A 	AAc                    	 t        j                  |       }t        j                  |j
                        S # t        $ r Y yw xY wr   )r<   r   r  r   r*  r   )pathr  s     rI   r   r     s=    XXd^ <<

##  s   6 	AAc                8    | j                  d      xs t        | v S )Nr   )
startswithr   )r   s    rI   r  r    s    ??38=D#88rX   T)frozenc                  ,    e Zd ZU ded<   ded<   ded<   y)re   r   r]   r   r^   NrR   rS   rT   rU   r   rX   rI   re   re     s    JJLrX   re   c                  ,    e Zd ZU ded<   ded<   ded<   y)rg   r&   ra   rb   r   r]   Nr`  r   rX   rI   rg   rg     s    rX   rg   c                  ,    e Zd ZU ded<   ded<   ded<   y)r>  r   r   r=  r4  r6  Nr`  r   rX   rI   r>  r>    s    J	HMrX   r>  c                  b    e Zd ZU dZded<   ded<   ded<   ded	<   d
ed<   ded<   ded<   ded<   y)r   zYEverything that exists only while a lock is held; ``None`` when the instance has no lock.r=  r   r  r   
int | Noner   r   r   rN   r   r   r   r   r'  r   N)rR   rS   rT   r  rU   r   rX   rI   r   r     s1    cJ
KOJ&&##rX   r   c                     t        t        j                               D ],  } t        t              5  | j                  d       d d d        . y # 1 sw Y   9xY w)NTr   )listr%   valuesr   	Exceptionrz   )rE   s    rI   _cleanup_all_instancesri    sR    ..01 )i  	)4(	) 	))	) 	)s   AA	)r   r   r   rd  rP   z'tuple[_MarkerInfo | None, float] | None)r   r=  rP   bytes)r   r   r   rd  rP   r=  )r   r   r   rd  rP   rd  )r   rj  rP   z_MarkerInfo | None)r   r   r   rd  rP   r  )
r   r   r4   rM   r   rM   r   rd  rP   rN   )r   r   r   r   r   rd  rP   r  )r   r   rX  ztuple[int, int]r   rd  rP   rN   )r[  r   rP   rN   )r   r   rP   rN   r  )Vr  
__future__r   atexitr   r<   r:  r   rT  r   sysrh   r   r   
contextlibr   r   dataclassesr   pathlibr   typingr   r	   r
   weakrefr   filelock._apir   r   r   r   r   r   r   r   filelock._errorr   filelock._softr   filelock._utilr   r   r   collections.abcr   r   r  r   rU   r   r   r    r"   platformr   supports_dir_fdr$   r%   ri   r'   r   r(   typer*   rQ   Threadr   r   r  r  r   r   r   r   r   rW  r   r  re   rg   r>  r   ri  register__all__r   rX   rI   <module>r~     sS   ` "   	 	    
    / !  0 0 '	 	 	 $ ' D D3 	 $z $# * #!"lA6Z 6!"lA6Z 6 !$ 7 YBGGrGYGY<Y + YEXEZB Z&4inn&6 ^ 6365  0 8:$ :zf	*+ f	*Ry'' ( 59 2(- 8< t 59 R< 04   )
) ) 
	)
 ) 
)X JN 0.$9 $      $   
$ 
$ 
$) & ' & ' rX   