o
    'i;                     @  s  U 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
mZ d dlmZmZ d dlmZ ddlmZ ddlmZ erMd d	lmZ ed
Ze Zded< e ZdddZee dZ d ddZ!G dd de"Z#G dd de#dZ$dS )!    )annotationsN)contextmanagersuppress)TYPE_CHECKINGLiteral)WeakValueDictionary   )AcquireReturnProxy)Timeout)	Generatorfilelockzset[sqlite3.Connection]_all_connectionsreturnNonec               
   C  sj   t ) ttD ]} ttj |   W d    n1 sw   Y  qW d    d S 1 s.w   Y  d S N)_all_connections_locklistr   r   sqlite3ProgrammingErrorclose)con r   P/home/jeff/fluffinator/venv/lib/python3.10/site-packages/filelock/_read_write.py_cleanup_connections   s   
"r   i5wtimeoutfloatblockingboolalready_waitedintc                C  sx   |du rdS | dkrt S | dk rd}t|| dkr!t| | dn| }t|d }|t ks1|dk r:td| t  t S |S )NFr   z+timeout must be a non-negative number or -1i  z7timeout %s is too large for SQLite, using %s ms instead)_MAX_SQLITE_TIMEOUT_MS
ValueErrormaxr   _LOGGERwarning)r   r   r   msg	remaining
timeout_msr   r   r   timeout_for_sqlite'   s   r)   c                      s@   e Zd ZU dZded< ded< 	ddddd fddZ  ZS )_ReadWriteLockMetaa!  
    Metaclass that handles singleton resolution when is_singleton=True.

    Singleton logic lives here rather than in ReadWriteLock.get_lock so that ``ReadWriteLock(path)`` transparently
    returns cached instances without a 2-arg ``super()`` call that type checkers cannot verify.
    0WeakValueDictionary[pathlib.Path, ReadWriteLock]
_instanceszthreading.Lock_instances_lockr    Tr   is_singleton	lock_filestr | os.PathLike[str]r   r   r   r   r/   r   ReadWriteLockc             	     s   |st  j||||dS t| }| jB || jvr,t  j||||d}|| j|< n| j| }|j|ks;|j|krOd|j d|j d| d| }t	||W  d    S 1 s[w   Y  d S )Nr.   z$Singleton lock created with timeout=z, blocking=z, cannot be changed to timeout=)
super__call__pathlibPathresolver-   r,   r   r   r"   )clsr0   r   r   r/   
normalizedinstancer&   	__class__r   r   r4   E   s$   

$z_ReadWriteLockMeta.__call__r    )
r0   r1   r   r   r   r   r/   r   r   r2   )__name__
__module____qualname____doc____annotations__r4   __classcell__r   r   r;   r   r*   :   s   
 r*   c                   @  s   e Zd ZU dZe Zded< e Z	e
	d7ddd8ddZ	d7dddd9ddZd:ddZd;ddZd<d d!Zd=d"d#Zd7ddd>d$d%Zd7ddd>d&d'Zd(d)d?d+d,Zed@d-ddAd1d2Zed@d-ddAd3d4ZdBd5d6Zd-S )Cr2   a  
    Cross-process read-write lock backed by SQLite.

    Allows concurrent shared readers or a single exclusive writer. The lock is reentrant within the same mode
    (multiple ``acquire_read`` calls nest, as do multiple ``acquire_write`` calls from the same thread), but
    upgrading from read to write or downgrading from write to read raises :class:`RuntimeError`. Write locks are
    pinned to the thread that acquired them.

    By default, ``is_singleton=True``: calling ``ReadWriteLock(path)`` with the same resolved path returns the same
    instance. The lock file must use a ``.db`` extension (SQLite database).

    :param lock_file: path to the SQLite database file used as the lock
    :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
    :param is_singleton: if ``True``, reuse existing instances for the same resolved path

    .. versionadded:: 3.21.0
    r+   r,   r    Tr   r0   r1   r   r   r   r   r   c                C  s   | |||dS )a  
        Return the singleton :class:`ReadWriteLock` for *lock_file*.

        :param lock_file: path to the SQLite database file used as the lock
        :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
        :raises ValueError: if an instance already exists for this path with different *timeout* or *blocking* values
        :return: the singleton lock instance
        rD   r   )r8   r0   r   r   r   r   r   get_lockx   s   zReadWriteLock.get_lockr.   r/   r   c                C  s   t || _|| _|| _t | _t | _d| _	d | _
d | _tj| jdd| _t t| j W d    d S 1 s<w   Y  d S )Nr   F)check_same_thread)osfspathr0   r   r   	threadingLock_transaction_lock_internal_lock_lock_level_current_mode_write_thread_idr   connect_conr   r   add)selfr0   r   r   r/   r   r   r   __init__   s   

"zReadWriteLock.__init__c                C  s8   |dkr| j |}n| j ||}|st| jd d S )Nr    )rK   acquirer
   r0   )rS   r   r   acquiredr   r   r   _acquire_transaction_lock   s   z'ReadWriteLock._acquire_transaction_lockmodeLiteral['read', 'write']oppositestr	directionr	   c                 C  s   | j |krd| d| j dt|  d| d| d}t||dkrAt  }| jkrAd| j dt|  d	| d
| j }t||  jd7  _t| dS )NzCannot acquire z	 lock on  (lock id: z): already holding a z lock (z not allowed)writezCannot acquire write lock on z) from thread z while it is held by thread r   lock)	rN   r0   idRuntimeErrorrI   	get_identrO   rM   r	   )rS   rX   rZ   r\   r&   curr   r   r   _validate_reentrant   s$   

z!ReadWriteLock._validate_reentrant
start_timec          	      C  s   t  | }t|||d}| jd| d | jd t  | }t|||d }|kr8| jd| d |dkr>dnd}| j| |dkrR| jd	 d S d S )
N)r   r   zPRAGMA busy_timeout=;zPRAGMA journal_mode=MEMORY;r^   zBEGIN EXCLUSIVE TRANSACTION;zBEGIN TRANSACTION;readz'SELECT name FROM sqlite_schema LIMIT 1;)timeperf_counterr)   rQ   execute)	rS   rX   r   r   rf   waitedr(   
recomputedstmtr   r   r   _configure_and_begin   s   z"ReadWriteLock._configure_and_beginc             
   C  s  |dkrdnd}|dkrdnd}| j  | jdkr'| |||W  d    S W d    n1 s1w   Y  t }| j||d zzd| j " | jdkra| |||W  d    W W | j  S W d    n1 skw   Y  | j||||d | j  || _	d| _|dkrt
 | _W d    n1 sw   Y  t| d	W W | j  S  tjy } zd
t|vr t| jd d }~ww | j  w )Nrh   r^   	downgradeupgrader   )r   r   )r   rf   r   r_   zdatabase is locked)rL   rM   re   ri   rj   rW   rK   releasero   rN   rI   rc   rO   r	   r   OperationalErrorr[   r
   r0   )rS   rX   r   r   rZ   r\   rf   excr   r   r   _acquire   sF   


zReadWriteLock._acquirec                C     | j d||dS )a  
        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).

        :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
        :raises RuntimeError: if a write lock is already held on this instance
        :raises Timeout: if the lock cannot be acquired within *timeout* seconds
        :return: a proxy that can be used as a context manager to release the lock
        rh   rD   ru   rS   r   r   r   r   r   acquire_read   s   zReadWriteLock.acquire_readc                C  rv   )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`.

        :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
        :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
        :return: a proxy that can be used as a context manager to release the lock
        r^   rD   rw   rx   r   r   r   acquire_write   s   zReadWriteLock.acquire_writeFforcer|   c                C  s   d}| j B | jdkr&|r	 W d   dS d| j dt|  d}t||r,d| _n|  jd8  _| jdkr@d| _d| _d}W d   n1 sJw   Y  |rX| j  dS dS )	aj  
        Release one level of the current lock.

        When the lock level reaches zero the underlying SQLite transaction is rolled back, releasing the database lock.

        :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``
        Fr   NzCannot release a lock on r]   z) that is not heldr   T)	rL   rM   r0   ra   rb   rN   rO   rQ   rollback)rS   r|   should_rollbackr&   r   r   r   rr     s(   	

zReadWriteLock.releaseNfloat | Nonebool | NoneGenerator[None]c                c  L    |du r| j }|du r| j}| j||d z
dV  W |   dS |   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
        NrD   )r   r   ry   rr   rx   r   r   r   	read_lock)     
zReadWriteLock.read_lockc                c  r   )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
        NrD   )r   r   rz   rr   rx   r   r   r   
write_lock=  r   zReadWriteLock.write_lockc                 C  sL   | j dd | j  t t| j W d   dS 1 sw   Y  dS )z
        Release the lock (if held) and close the underlying SQLite connection.

        After calling this method, the lock instance is no longer usable.
        Tr{   N)rr   rQ   r   r   r   discard)rS   r   r   r   r   Q  s
   
"zReadWriteLock.closer=   )r0   r1   r   r   r   r   r   r2   )
r0   r1   r   r   r   r   r/   r   r   r   )r   r   r   r   r   r   )rX   rY   rZ   r[   r\   r[   r   r	   )
rX   rY   r   r   r   r   rf   r   r   r   )rX   rY   r   r   r   r   r   r	   )r   r   r   r   r   r	   )r|   r   r   r   r   )r   r   r   r   r   r   r   r   )r>   r?   r@   rA   r   r,   rB   rI   rJ   r-   classmethodrE   rT   rW   re   ro   ru   ry   rz   rr   r   r   r   r   r   r   r   r   r2   a   s4   
 

	

!r2   )	metaclassr   )r   r   r   r   r   r   r   r   )%
__future__r   atexitloggingrG   r5   r   rI   ri   
contextlibr   r   typingr   r   weakrefr   _apir	   _errorr
   collections.abcr   	getLoggerr$   setr   rB   rJ   r   r   registerr!   r)   typer*   r2   r   r   r   r   <module>   s0    



'