Ë
    "ïàjé5  ã                   ó¢   — d Z ddlZddlZddlZddlmZ ddlmZmZm	Z	m
Z
 ddlmZ dZ ej                  d«      Z G d„ d	«      Z G d
„ de«      Zy)au  
Implements two storage providers for `LockManager`.

Two alternative lock storage classes are defined here: one in-memory
(dict-based), and one persistent low performance variant using shelve.

See :class:`~wsgidav.lock_man.lock_manager.LockManager`
See :class:`~wsgidav.lock_man.lock_storage.LockStorageDict`
See :class:`~wsgidav.lock_man.lock_storage.LockStorageShelve`
é    N)Úutil)Úgenerate_lock_tokenÚlock_stringÚnormalize_lock_rootÚvalidate_lock)ÚReadWriteLockÚreStructuredTextzwsgidav.lock_manc                   ó`   — e Zd ZdZdZdZd„ Zd„ Zd„ Zd„ Z	d„ Z
d	„ Zd
„ Zd„ Zd„ Zd„ Zd„ Zd„ Zy)ÚLockStorageDictaq  
    An in-memory lock manager storage implementation using a dictionary.

    R/W access is guarded by a thread.lock object.

    Also, to make it work with a Shelve dictionary, modifying dictionary
    members is done by re-assignment and we call a _flush() method.

    This is obviously not persistent, but should be enough in some cases.
    For a persistent implementation, see lock_storage.LockStorageShelve().

    Notes:
        expire is stored as expiration date in seconds since epoch (not in
        seconds until expiration).

    The dictionary is built like::

        { 'URL2TOKEN:/temp/litmus/lockme': ['opaquelocktoken:0x1d7b86...',
                                            'opaquelocktoken:0xd7d4c0...'],
          'opaquelocktoken:0x1d7b86...': {
            'depth': '0',
            'owner': "<?xml version='1.0' encoding='UTF-8'?>\n<owner xmlns="DAV:">"
                + "litmus test suite</owner>\n",
            'principal': 'tester',
            'root': '/temp/litmus/lockme',
            'scope': 'shared',
            'expire': 1261328382.4530001,
            'token': 'opaquelocktoken:0x1d7b86...',
            'type': 'write',
            },
          'opaquelocktoken:0xd7d4c0...': {
            'depth': '0',
            'owner': '<?xml version='1.0' encoding='UTF-8'?>\n<owner xmlns="DAV:">'
                + 'litmus: notowner_sharedlock</owner>\n',
            'principal': 'tester',
            'root': '/temp/litmus/lockme',
            'scope': 'shared',
            'expire': 1261328381.6040001,
            'token': 'opaquelocktoken:0xd7d4c0...',
            'type': 'write'
           },
         }
    i€:	 i ê$ c                 ó0   — d | _         t        «       | _        y ©N)Ú_dictr   Ú_lock©Úselfs    úL/srv/dav/.venv/lib/python3.12/site-packages/wsgidav/lock_man/lock_storage.pyÚ__init__zLockStorageDict.__init__b   s   € ØˆŒ
Ü"“_ˆ�
ó    c                 ó.   — | j                   j                  S r   )Ú	__class__Ú__name__r   s    r   Ú__repr__zLockStorageDict.__repr__f   s   € Ø�~‰~×&Ñ&Ð&r   c                  ó   — y)z$Overloaded by Shelve implementation.N© r   s    r   Ú_flushzLockStorageDict._flushl   ó   € àr   c                 ó.   — | j                   �J ‚i | _         y)zVCalled before first use.

        May be implemented to initialize a storage.
        N©r   r   s    r   ÚopenzLockStorageDict.openp   s   € ð
 �z‰zÐ!Ð!Ð!Øˆ�
r   c                 ó   — d| _         y)zCalled on shutdown.Nr   r   s    r   ÚclosezLockStorageDict.closex   s	   € àˆ�
r   c                  ó   — y)zPurge expired locks (optional).Nr   r   s    r   ÚcleanupzLockStorageDict.cleanup|   r   r   c                 óR   — | j                   �| j                   j                  «        yy©zDelete all entries.N)r   Úclearr   s    r   r&   zLockStorageDict.clear€   s!   € à�:‰:Ð!Ø�J‰J×ÑÕð "r   c                 óh  — | j                   j                  «        	 | j                  j                  |«      }|€Et        j                  d|› �«       | j                  |«       	 | j                   j                  «        yt        |d   «      }|dk\  rh|t        j                  «       k  rQt        j                  d|› dt        |«      › �«       | j                  |«       	 | j                   j                  «        y|| j                   j                  «        S # | j                   j                  «        w xY w)a#  Return a lock dictionary for a token.

        If the lock does not exist or is expired, None is returned.

        token:
            lock token
        Returns:
            Lock dictionary or <None>

        Side effect: if lock is expired, it will be purged and None is returned.
        NzLock purged dangling: Úexpirer   zLock timed-out(ú): )r   Úacquire_readr   ÚgetÚ_loggerÚdebugÚdeleteÚreleaseÚfloatÚtimer   )r   ÚtokenÚlockr(   s       r   r+   zLockStorageDict.get…   sï   € ð 	�
‰
×ÑÔ!ð	!Ø—:‘:—>‘> %Ó(ˆDØˆ|ä—‘Ð 6°u°gÐ>Ô?Ø—‘˜EÔ"Øð �J‰J×ÑÕ ô ˜4 ™>Ó*ˆFØ˜Š{˜v¬¯	©	«Ò3Ü—‘ °¨x°s¼;ÀtÓ;LÐ:MÐNÔOØ—‘˜EÔ"Øð �J‰J×ÑÕ ð à�J‰J×ÑÕ øˆD�J‰J×ÑÕ ús   œAD Á>AD Ã9D ÄD1c                 ó€  — | j                   j                  «        	 |j                  d«      �J ‚|j                  d«      �J d«       ‚|rd|v sJ ‚|}t        |«      }||d<   t	        |j                  d«      «      }|€t
        j                  }n(|dk  s|t
        j                  kD  rt
        j                  }||d<   t        j                  «       |z   |d<   t        |«       t        «       }||d<   || j                  |<   d|› �}|| j                  vr|g| j                  |<   n/| j                  |   }|j                  |«       || j                  |<   | j                  «        t        j                  d	|›d
t!        |«      › �«       || j                   j#                  «        S # | j                   j#                  «        w xY w)aî  Create a direct lock for a resource path.

        path:
            Normalized path (utf8 encoded string, no trailing '/')
        lock:
            lock dictionary, without a token entry
        Returns:
            New unique lock token.: <lock

        **Note:** the lock dictionary may be modified on return:

        - lock['root'] is ignored and set to the normalized <path>
        - lock['timeout'] may be normalized and shorter than requested
        - lock['token'] is added
        r2   r(   zUse timeout instead of expireú/ÚrootÚtimeoutr   ú
URL2TOKEN:zLockStorageDict.set(r)   )r   Úacquire_writer+   r   r0   r   ÚLOCK_TIME_OUT_DEFAULTÚLOCK_TIME_OUT_MAXr1   r   r   r   Úappendr   r,   r-   r   r/   )r   Úpathr3   Úorg_pathr7   r2   ÚkeyÚtokLists           r   ÚcreatezLockStorageDict.create¢   sš  € ð  	�
‰
× Ñ Ô"ð+	!à—8‘8˜GÓ$Ð,Ð,Ð,Ø—8‘8˜HÓ%Ð-ÐNÐ/NÓNÐ-Ù˜C 4™KÐ'Ð'ð ˆHÜ& tÓ,ˆDØˆD�‰Lô ˜DŸH™H YÓ/Ó0ˆGØˆÜ)×?Ñ?‘Ø˜1’ ¬/×*KÑ*KÒ KÜ)×;Ñ;�à%ˆD�‰OÜ!ŸY™Y›[¨7Ñ2ˆD�‰Nä˜$Ôä'Ó)ˆEØ!ˆD�‰Mð !%ˆD�J‰J�uÑð ˜t˜fÐ%ˆCØ˜$Ÿ*™*Ñ$Ø#( '�—
‘
˜3’ð Ÿ*™* S™/�Ø—‘˜uÔ%Ø")�—
‘
˜3‘Ø�K‰KŒMÜ�M‰MÐ0°°¸CÄÈDÓ@QÐ?RÐSÔTØà�J‰J×ÑÕ øˆD�J‰J×ÑÕ ús   œE*F! Æ!F=c                óÚ  — || j                   v sJ d«       ‚|dk(  s|dkD  sJ ‚|dk  s|t        j                  kD  rt        j                  }| j                  j	                  «        	 | j                   |   }||d<   t        j
                  «       |z   |d<   || j                   |<   | j                  «        | j                  j                  «        |S # | j                  j                  «        w xY w)aM  Modify an existing lock's timeout.

        token:
            Valid lock token.
        timeout:
            Suggested lifetime in seconds (-1 for infinite).
            The real expiration time may be shorter than requested!
        Returns:
            Lock dictionary.
            Raises ValueError, if token is invalid.
        zLock must existéÿÿÿÿr   r7   r(   )r   r   r;   r   r9   r1   r   r/   )r   r2   r7   r3   s       r   ÚrefreshzLockStorageDict.refreshà   sÐ   € ð ˜Ÿ
™
Ñ"Ð5Ð$5Ó5Ð"Ø˜"Š} ¨!¢Ð+Ð+Ø�QŠ;˜'¤O×$EÑ$EÒEÜ%×7Ñ7ˆGà�
‰
× Ñ Ô"ð		!ð —:‘:˜eÑ$ˆDØ%ˆD�‰OÜ!ŸY™Y›[¨7Ñ2ˆD�‰NØ $ˆD�J‰J�uÑØ�K‰KŒMà�J‰J×ÑÔ Øˆøð �J‰J×ÑÕ ús   Á%AC ÃC*c                 óŒ  — | j                   j                  «        	 | j                  j                  |«      }t        j                  dt        |«      › �«       |€	 | j                   j                  «        ydj                  |j                  d«      «      }|| j                  v rK| j                  |   }t        |«      dkD  r!|j                  |«       || j                  |<   n| j                  |= | j                  |= | j                  «        | j                   j                  «        y# | j                   j                  «        w xY w)zfDelete lock.

        Returns True on success. False, if token does not exist, or is expired.
        zdelete FzURL2TOKEN:{}r6   é   T)r   r9   r   r+   r,   r-   r   r/   ÚformatÚlenÚremover   )r   r2   r3   r?   r@   s        r   r.   zLockStorageDict.deleteþ   s   € ð
 	�
‰
× Ñ Ô"ð	!Ø—:‘:—>‘> %Ó(ˆDÜ�M‰M˜G¤K°Ó$5Ð#6Ð7Ô8Øˆ|Øð$ �J‰J×ÑÕ ð! !×'Ñ'¨¯©°Ó(8Ó9ˆCØ�d—j‘jÑ àŸ*™* S™/�Ü�w“< !Ò#ð —N‘N 5Ô)Ø&-�D—J‘J˜s’OàŸ
™
 3˜à—
‘
˜5Ð!à�K‰KŒMà�J‰J×ÑÔ Øøð �J‰J×ÑÕ ús   œ>D' Á6BD' Ä'Ec                ó  ‡ ‡‡
— t        j                  |«      sJ ‚|r|j                  d«      sJ ‚|s|sJ ‚ˆ
ˆ ˆfd„}t        |«      }‰ j                  j                  «        	 d|› �}‰ j                  j                  |g «      }g Š
|r ||«       |rA‰ j                  j                  «       D ]$  \  }}	t        j                  ||«      sŒ ||	«       Œ& ‰
‰ j                  j                  «        S # ‰ j                  j                  «        w xY w)aw  Return a list of direct locks for <path>.

        Expired locks are *not* returned (but may be purged).

        path:
            Normalized path (utf8 encoded string, no trailing '/')
        include_root:
            False: don't add <path> lock (only makes sense, when include_children
            is True).
        include_children:
            True: Also check all sub-paths for existing locks.
        token_only:
            True: only a list of token is returned. This may be implemented
            more efficiently by some providers.
        Returns:
            List of valid lock dictionaries (may be empty).
        r5   c                 óŒ   •— | D ]>  }‰j                  |«      }|sŒ‰r‰j                  |d   «       Œ.‰j                  |«       Œ@ y )Nr2   )r+   r<   )Útoklistr2   r3   ÚlockListr   Ú
token_onlys      €€€r   Ú__appendLocksz4LockStorageDict.get_lock_list.<locals>.__appendLocks3  sC   ø€ ð !ò .�Ø—x‘x “�ÚÙ!Ø Ÿ™¨¨W©Õ6à Ÿ™¨Õ-ñ.r   r8   )r   Úis_strÚ
startswithr   r   r*   r   r+   ÚitemsÚis_child_urir/   )r   r=   Úinclude_rootÚinclude_childrenrN   Ú_LockStorageDict__appendLocksr?   r@   ÚuÚltoksrM   s   `   `     @r   Úget_lock_listzLockStorageDict.get_lock_list  sî   ú€ ô$ �{‰{˜4Ô Ð Ð Ù˜Ÿ™¨Ô,Ð,Ð,ÙÑ/Ð/Ð/ö		.ô # 4Ó(ˆØ�
‰
×ÑÔ!ð	!Ø˜t˜fÐ%ˆCØ—j‘j—n‘n S¨"Ó-ˆGØˆHÙÙ˜gÔ&áØ $§
¡
× 0Ñ 0Ó 2ò -‘H�A�uÜ×(Ñ(¨¨aÕ0Ù% eÕ,ð-ð à�J‰J×ÑÕ øˆD�J‰J×ÑÕ ús   Á#A%C/ Ã	C/ Ã/DN)r   Ú
__module__Ú__qualname__Ú__doc__r:   r;   r   r   r   r   r!   r#   r&   r+   rA   rD   r.   rY   r   r   r   r   r   2   sS   „ ñ*ðX #ÐØ"Ðò%ò'òòòòòò
!ò:<!ò|ò<ó>1!r   r   c                   ó@   ‡ — e Zd ZdZˆ fd„Zd„ Zd„ Zd„ Zd„ Zd„ Z	ˆ xZ
S )ÚLockStorageShelvezE
    A low performance lock manager implementation using shelve.
    c                 ój   •— t         ‰| �  «        t        j                  j	                  |«      | _        y r   )Úsuperr   Úosr=   ÚabspathÚ_storage_path)r   Ústorage_pathr   s     €r   r   zLockStorageShelve.__init__[  s#   ø€ Ü‰ÑÔÜŸW™WŸ_™_¨\Ó:ˆÕr   c                 ó"   — d| j                   ›d�S )NzLockStorageShelve(ú))rc   r   s    r   r   zLockStorageShelve.__repr___  s   € Ø# D×$6Ñ$6Ð#9¸Ð;Ð;r   c                 ó
  — t         j                  d«       | j                  j                  «        	 | j                  j                  «        | j                  j                  «        y# | j                  j                  «        w xY w)z$Write persistent dictionary to disc.z_flush()N)r,   r-   r   r9   r   Úsyncr/   r   s    r   r   zLockStorageShelve._flushb  sR   € ä�‰�jÔ!Ø�
‰
× Ñ Ô"ð	!Ø�J‰J�O‰OÔà�J‰J×ÑÕ øˆD�J‰J×ÑÕ ús   ±A& Á&Bc                 ó¢  — | j                   j                  «        	 | j                  du }|r| j                  «        t	        | j                  «      r4| j                  j                  «        | j                  j                  «        |r| j                  «        | j                   j                  «        y# | j                   j                  «        w xY wr%   )	r   r9   r   r   rH   r&   rh   r!   r/   )r   Ú
was_closeds     r   r&   zLockStorageShelve.cleark  s‡   € à�
‰
× Ñ Ô"ð
	!ØŸ™ tÐ+ˆJÙØ—	‘	”Ü�4—:‘:ŒØ—
‘
× Ñ Ô"Ø—
‘
—‘Ô!ÙØ—
‘
”à�J‰J×ÑÕ øˆD�J‰J×ÑÕ ús   œA;B2 Â2Cc                 ó–   — t         j                  d| j                  ›d�«       t        j                  | j                  d¬«      | _        y )Nzopen(rf   F)Ú	writeback)r,   r-   rc   Úshelver   r   r   s    r   r   zLockStorageShelve.openz  s8   € Ü�‰˜˜d×0Ñ0Ð3°1Ð5Ô6ô —[‘[ ×!3Ñ!3¸uÔEˆ�
r   c                 ó0  — t         j                  d«       | j                  j                  «        	 | j                  �!| j                  j                  «        d | _        | j                  j                  «        y # | j                  j                  «        w xY w)Nzclose())r,   r-   r   r9   r   r!   r/   r   s    r   r!   zLockStorageShelve.close„  se   € Ü�‰�iÔ Ø�
‰
× Ñ Ô"ð	!Ø�z‰zÐ%Ø—
‘
× Ñ Ô"Ø!�”
à�J‰J×ÑÕ øˆD�J‰J×ÑÕ ús   ±-A9 Á9B)r   rZ   r[   r\   r   r   r   r&   r   r!   Ú__classcell__)r   s   @r   r^   r^   V  s'   ø„ ñô;ò<ò!ò!òFö!r   r^   )r\   ra   rm   r1   Úwsgidavr   Úwsgidav.lock_man.lock_managerr   r   r   r   Úwsgidav.rw_lockr   Ú__docformat__Úget_module_loggerr,   r   r^   r   r   r   ú<module>ru      sZ   ðñ
	ó 
Û Û å ÷ó õ *à"€ð !ˆ$×
 Ñ
 Ð!3Ó
4€÷$\!ñ \!ôH	6!˜õ 6!r   