Ë
    Û�ði5  ã                   óF  — d 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	m
Z
mZmZmZmZmZmZmZ  G d„ de«      Z G d„ d	e«      Z G d
„ de«      Z G d„ d«      Z G d„ d«      Z ej.                  «       Zdad„ Zd„ Zd„ Zd„ Zdd„Zd„ Zdd„Z d„ Z!d„ Z"d„ Z#dd„Z$d„ Z%d„ Z&d„ Z'y)aL  
Stash - Global Shared State for Dirty Workers

Provides simple key-value tables stored in the arbiter process.
All workers can read and write to the same tables.

Usage::

    from gunicorn.dirty import stash

    # Basic operations - table is auto-created on first access
    stash.put("sessions", "user:1", {"name": "Alice", "role": "admin"})
    user = stash.get("sessions", "user:1")
    stash.delete("sessions", "user:1")

    # Dict-like interface
    sessions = stash.table("sessions")
    sessions["user:1"] = {"name": "Alice"}
    user = sessions["user:1"]
    del sessions["user:1"]

    # Query operations
    keys = stash.keys("sessions")
    keys = stash.keys("sessions", pattern="user:*")

    # Table management
    stash.ensure("cache")           # Explicit creation (idempotent)
    stash.clear("sessions")         # Delete all entries
    stash.delete_table("sessions")  # Delete the table itself
    tables = stash.tables()         # List all tables

Declarative usage in DirtyApp::

    class MyApp(DirtyApp):
        stashes = ["sessions", "cache"]  # Auto-created on arbiter start

        def __call__(self, action, *args, **kwargs):
            # Tables are ready to use
            stash.put("sessions", "key", "value")

Note: Tables are stored in the arbiter process and are ephemeral.
If the arbiter restarts, all data is lost.
é    Né   )Ú
DirtyError)ÚDirtyProtocolÚSTASH_OP_PUTÚSTASH_OP_GETÚSTASH_OP_DELETEÚSTASH_OP_KEYSÚSTASH_OP_CLEARÚSTASH_OP_INFOÚSTASH_OP_ENSUREÚSTASH_OP_DELETE_TABLEÚSTASH_OP_TABLESÚSTASH_OP_EXISTSÚmake_stash_messagec                   ó   — e Zd ZdZy)Ú
StashErrorz$Base exception for stash operations.N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__© ó    úO/var/www/html/Extract/venv/lib/python3.12/site-packages/gunicorn/dirty/stash.pyr   r   E   s   „ Ú.r   r   c                   ó"   ‡ — e Zd ZdZˆ fd„Zˆ xZS )ÚStashTableNotFoundErrorz#Raised when a table does not exist.c                 ó8   •— || _         t        ‰| �	  d|› �«       y )NzStash table not found: )Ú
table_nameÚsuperÚ__init__)Úselfr   Ú	__class__s     €r   r   z StashTableNotFoundError.__init__L   s   ø€ Ø$ˆŒÜ‰ÑÐ2°:°,Ð?Õ@r   ©r   r   r   r   r   Ú__classcell__©r!   s   @r   r   r   I   s   ø„ Ù-÷Að Ar   r   c                   ó"   ‡ — e Zd ZdZˆ fd„Zˆ xZS )ÚStashKeyNotFoundErrorz,Raised when a key does not exist in a table.c                 óL   •— || _         || _        t        ‰| �  d|› d|› �«       y )NzKey not found in z: )r   Úkeyr   r   )r    r   r(   r!   s      €r   r   zStashKeyNotFoundError.__init__T   s,   ø€ Ø$ˆŒØˆŒÜ‰ÑÐ,¨Z¨L¸¸3¸%Ð@ÕAr   r"   r$   s   @r   r&   r&   Q   s   ø„ Ù6÷Bð Br   r&   c                   óŒ   — e Zd ZdZdd„Zd„ Zd„ Zd„ Zdd„Zd„ Z	dd	„Z
d
„ Zdd„Zd„ Zd„ Zd„ Zdd„Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zy)ÚStashClientzl
    Client for stash operations.

    Communicates with the arbiter which stores all tables in memory.
    c                 ó`   — || _         || _        d| _        t        j                  «       | _        y)z½
        Initialize the stash client.

        Args:
            socket_path: Path to the dirty arbiter's Unix socket
            timeout: Default timeout for operations in seconds
        N)Úsocket_pathÚtimeoutÚ_sockÚ	threadingÚLockÚ_lock)r    r,   r-   s      r   r   zStashClient.__init__a   s(   € ð 'ˆÔØˆŒØˆŒ
Ü—^‘^Ó%ˆ�
r   c                 ó<   — t        t        j                  «       «      S )zGenerate a unique request ID.)ÚstrÚuuidÚuuid4©r    s    r   Ú_get_request_idzStashClient._get_request_idn   s   € ä”4—:‘:“<Ó Ð r   c                 óx  — ddl }| j                  �y	 |j                  |j                  |j                  «      | _        | j                  j	                  | j
                  «       | j                  j                  | j                  «       y# |j                  t        f$ r}d| _        t        d|› �«      |‚d}~ww xY w)z Establish connection to arbiter.r   NzFailed to connect to arbiter: )Úsocketr.   ÚAF_UNIXÚSOCK_STREAMÚ
settimeoutr-   Úconnectr,   ÚerrorÚOSErrorr   )r    r9   Úes      r   Ú_connectzStashClient._connectr   s™   € ãØ�:‰:Ð!Øð	JØŸ™ v§~¡~°v×7IÑ7IÓJˆDŒJØ�J‰J×!Ñ! $§,¡,Ô/Ø�J‰J×Ñ˜t×/Ñ/Õ0øØ—‘œgÐ&ò 	JØˆDŒJÜÐ=¸a¸SÐAÓBÈÐIûð	Jús   “A5B	 Â	B9ÂB4Â4B9c                 ó€   — | j                   �#	 | j                   j                  «        d| _         yy# t        $ r Y Œw xY w)zClose the connection.N)r.   ÚcloseÚ	Exceptionr6   s    r   Ú_closezStashClient._close€   sC   € à�:‰:Ð!ðØ—
‘
× Ñ Ô"ð ˆD�Jð "øô ò Ùðús   Ž1 ±	=¼=Nc           	      ó2  — | j                   5  | j                  €| j                  «        | j                  «       }t	        ||||||¬«      }	 t        j                  | j                  |«       t        j                  | j                  «      }|j                  d«      }	|	t
        j                  k(  r|j                  d«      cddd«       S |	t
        j                  k(  rb|j                  di «      }
|
j                  dd«      }|
j                  dd	«      }|d
k(  rt        |«      ‚|dk(  rt        ||«      ‚t        |«      ‚t        d|	› �«      ‚# t        $ r5}| j                  «        t!        |t        «      r‚ t        d|› �«      |‚d}~ww xY w# 1 sw Y   yxY w)a6  
        Execute a stash operation.

        Args:
            op: Operation code (STASH_OP_*)
            table: Table name
            key: Optional key
            value: Optional value
            pattern: Optional pattern for keys operation

        Returns:
            Result from the operation
        N)r(   ÚvalueÚpatternÚtypeÚresultr>   Ú
error_typer   ÚmessagezUnknown errorr   r&   zUnexpected response type: zStash operation failed: )r1   r.   rA   r7   r   r   Úwrite_messageÚread_messageÚgetÚMSG_TYPE_RESPONSEÚMSG_TYPE_ERRORr   r&   r   rD   rE   Ú
isinstance)r    ÚopÚtabler(   rG   rH   Ú
request_idrL   ÚresponseÚmsg_typeÚ
error_inforK   Ú	error_msgr@   s                 r   Ú_executezStashClient._execute‰   s~  € ð �Z‰Zñ "	HØ�z‰zÐ!Ø—‘”à×-Ñ-Ó/ˆJÜ(Ø˜B Ø˜u¨gôˆGð
HÜ×+Ñ+¨D¯J©J¸Ô@Ü(×5Ñ5°d·j±jÓA�à#Ÿ<™<¨Ó/�Øœ}×>Ñ>Ò>Ø#Ÿ<™<¨Ó1÷!"	Hñ "	Hð" ¤×!=Ñ!=Ò=Ø!)§¡¨g°rÓ!:�JØ!+§¡°¸lÓ!K�JØ *§¡¨y¸/Ó J�Ià!Ð%>Ò>Ü5°eÓ<Ð<Ø!Ð%<Ò<Ü3°E¸3Ó?Ð?Ü$ YÓ/Ð/ä$Ð'AÀ(ÀÐ%LÓMÐMøäò HØ—‘”Ü˜a¤Ô,ØÜ Ð#;¸A¸3Ð!?Ó@ÀaÐGûð	Hú÷="	Hð "	Hús1   �>FÁA3EÃ	BEÅ	F
Å0FÆF
Æ
FÆFc                 ó6   — | j                  t        |||¬«       y)zö
        Store a value in a table.

        The table is automatically created if it doesn't exist.

        Args:
            table: Table name
            key: Key to store under
            value: Value to store (must be serializable)
        )r(   rG   N)rZ   r   )r    rT   r(   rG   s       r   ÚputzStashClient.put¿   s   € ð 	�‰”l E¨s¸%ˆÕ@r   c                 óV   — 	 | j                  t        ||¬«      S # t        $ r |cY S w xY w)zú
        Retrieve a value from a table.

        Args:
            table: Table name
            key: Key to retrieve
            default: Default value if key not found

        Returns:
            The stored value, or default if not found
        ©r(   )rZ   r   r&   )r    rT   r(   Údefaults       r   rO   zStashClient.getÌ   s0   € ð	Ø—=‘=¤¨u¸#�=Ó>Ð>øÜ$ò 	ØŠNð	ús   ‚ š(§(c                 ó2   — | j                  t        ||¬«      S )zÈ
        Delete a key from a table.

        Args:
            table: Table name
            key: Key to delete

        Returns:
            True if key was deleted, False if it didn't exist
        r^   )rZ   r   ©r    rT   r(   s      r   ÚdeletezStashClient.deleteÝ   ó   € ð �}‰}œ_¨e¸ˆ}Ó=Ð=r   c                 ó2   — | j                  t        ||¬«      S )zÞ
        Get all keys in a table, optionally filtered by pattern.

        Args:
            table: Table name
            pattern: Optional glob pattern (e.g., "user:*")

        Returns:
            List of keys
        ©rH   )rZ   r	   )r    rT   rH   s      r   ÚkeyszStashClient.keysê   s   € ð �}‰}œ]¨E¸7ˆ}ÓCÐCr   c                 ó0   — | j                  t        |«       y)z]
        Delete all entries in a table.

        Args:
            table: Table name
        N)rZ   r
   ©r    rT   s     r   ÚclearzStashClient.clear÷   s   € ð 	�‰”n eÕ,r   c                 ó.   — | j                  t        |«      S )z�
        Get information about a table.

        Args:
            table: Table name

        Returns:
            Dict with table info (size, etc.)
        )rZ   r   rh   s     r   ÚinfozStashClient.info   s   € ð �}‰}œ]¨EÓ2Ð2r   c                 ó0   — | j                  t        |«       y)z­
        Ensure a table exists (create if not exists).

        This is idempotent - calling it multiple times is safe.

        Args:
            table: Table name
        N)rZ   r   rh   s     r   ÚensurezStashClient.ensure  s   € ð 	�‰”o uÕ-r   c                 ó2   — | j                  t        ||¬«      S )zÔ
        Check if a table or key exists.

        Args:
            table: Table name
            key: Optional key to check within the table

        Returns:
            True if exists, False otherwise
        r^   )rZ   r   ra   s      r   ÚexistszStashClient.exists  rc   r   c                 ó0   — | j                  t        |«       y)zV
        Delete an entire table.

        Args:
            table: Table name
        N)rZ   r   rh   s     r   Údelete_tablezStashClient.delete_table$  s   € ð 	�‰Ô+¨UÕ3r   c                 ó.   — | j                  t        d«      S )zT
        List all tables.

        Returns:
            List of table names
        Ú )rZ   r   r6   s    r   ÚtableszStashClient.tables-  s   € ð �}‰}œ_¨bÓ1Ð1r   c                 ó   — t        | |«      S )z•
        Get a dict-like interface to a table.

        Args:
            name: Table name

        Returns:
            StashTable instance
        )Ú
StashTable)r    Únames     r   rT   zStashClient.table6  s   € ô ˜$ Ó%Ð%r   c                 óf   — | j                   5  | j                  «        ddd«       y# 1 sw Y   yxY w)zClose the client connection.N)r1   rE   r6   s    r   rC   zStashClient.closeB  s'   € à�Z‰Zñ 	Ø�K‰KŒM÷	÷ 	ñ 	ús   �'§0c                 ó   — | S ©Nr   r6   s    r   Ú	__enter__zStashClient.__enter__G  s   € Øˆr   c                 ó$   — | j                  «        y rz   )rC   )r    Úexc_typeÚexc_valÚexc_tbs       r   Ú__exit__zStashClient.__exit__J  s   € Ø�
‰
�r   )g      >@)NNNrz   )r   r   r   r   r   r7   rA   rE   rZ   r\   rO   rb   rf   ri   rk   rm   ro   rq   rt   rT   rC   r{   r€   r   r   r   r*   r*   Z   sk   „ ñó&ò!òJòó0HòlAóò">óDò-ò
3ò	.ó>ò4ò2ò
&òò
ór   r*   c                   ól   — e Zd ZdZd„ Zed„ «       Zd„ Zd„ Zd„ Z	d„ Z
d„ Zd	„ Zdd„Zdd„Zd„ Zd„ Zd„ Zy
)rv   a2  
    Dict-like interface to a stash table.

    Example::

        sessions = stash.table("sessions")
        sessions["user:1"] = {"name": "Alice"}
        user = sessions["user:1"]
        del sessions["user:1"]

        # Iteration
        for key in sessions:
            print(key, sessions[key])
    c                 ó    — || _         || _        y rz   )Ú_clientÚ_name)r    Úclientrw   s      r   r   zStashTable.__init__^  s   € ØˆŒØˆ�
r   c                 ó   — | j                   S )zTable name.)r„   r6   s    r   rw   zStashTable.nameb  s   € ð �z‰zÐr   c                 ó¸   — | j                   j                  | j                  |«      }|€1| j                   j                  | j                  |«      st	        |«      ‚|S rz   )rƒ   rO   r„   ro   ÚKeyError)r    r(   rJ   s      r   Ú__getitem__zStashTable.__getitem__g  sH   € Ø—‘×!Ñ! $§*¡*¨cÓ2ˆØˆ>à—<‘<×&Ñ& t§z¡z°3Ô7Ü˜s“mÐ#Øˆr   c                 óR   — | j                   j                  | j                  ||«       y rz   )rƒ   r\   r„   )r    r(   rG   s      r   Ú__setitem__zStashTable.__setitem__o  s   € Ø�‰×Ñ˜Ÿ™ S¨%Õ0r   c                 óf   — | j                   j                  | j                  |«      st        |«      ‚y rz   )rƒ   rb   r„   rˆ   ©r    r(   s     r   Ú__delitem__zStashTable.__delitem__r  s)   € Ø�|‰|×"Ñ" 4§:¡:¨sÔ3Ü˜3“-Ðð 4r   c                 óN   — | j                   j                  | j                  |«      S rz   )rƒ   ro   r„   r�   s     r   Ú__contains__zStashTable.__contains__v  s   € Ø�|‰|×"Ñ" 4§:¡:¨sÓ3Ð3r   c                 ó^   — t        | j                  j                  | j                  «      «      S rz   )Úiterrƒ   rf   r„   r6   s    r   Ú__iter__zStashTable.__iter__y  s    € Ü�D—L‘L×%Ñ% d§j¡jÓ1Ó2Ð2r   c                 óp   — | j                   j                  | j                  «      }|j                  dd«      S )NÚsizer   )rƒ   rk   r„   rO   )r    rk   s     r   Ú__len__zStashTable.__len__|  s+   € Ø�|‰|× Ñ  §¡Ó,ˆØ�x‰x˜ Ó"Ð"r   Nc                 óP   — | j                   j                  | j                  ||«      S )zGet value with default.)rƒ   rO   r„   )r    r(   r_   s      r   rO   zStashTable.get€  s   € à�|‰|×Ñ §
¡
¨C°Ó9Ð9r   c                 óP   — | j                   j                  | j                  |¬«      S )z-Get all keys, optionally filtered by pattern.re   )rƒ   rf   r„   )r    rH   s     r   rf   zStashTable.keys„  s    € à�|‰|× Ñ  §¡°WÐ Ó=Ð=r   c                 óN   — | j                   j                  | j                  «       y)zDelete all entries.N)rƒ   ri   r„   r6   s    r   ri   zStashTable.clearˆ  s   € à�‰×Ñ˜4Ÿ:™:Õ&r   c              #   ó´   K  — | j                   j                  | j                  «      D ],  }|| j                   j                  | j                  |«      f–— Œ. y­w)z Iterate over (key, value) pairs.N©rƒ   rf   r„   rO   r�   s     r   ÚitemszStashTable.itemsŒ  sH   è ø€ à—<‘<×$Ñ$ T§Z¡ZÓ0ò 	9ˆCØ�t—|‘|×'Ñ'¨¯
©
°CÓ8Ð8Ó8ñ	9ùs   ‚AAc              #   ó°   K  — | j                   j                  | j                  «      D ]*  }| j                   j                  | j                  |«      –— Œ, y­w)zIterate over values.Nr›   r�   s     r   ÚvalueszStashTable.values‘  sC   è ø€ à—<‘<×$Ñ$ T§Z¡ZÓ0ò 	4ˆCØ—,‘,×"Ñ" 4§:¡:¨sÓ3Ó3ñ	4ùs   ‚AArz   )r   r   r   r   r   Úpropertyrw   r‰   r‹   rŽ   r�   r“   r–   rO   rf   ri   rœ   rž   r   r   r   rv   rv   N  sW   „ ñòð ñó ðòò1ò ò4ò3ò#ó:ó>ò'ò9ó
4r   rv   c                 ó   — | a y)z@Set the global stash socket path (called during initialization).N)Ú_stash_socket_path)Úpaths    r   Úset_stash_socket_pathr£   ¢  s
   € ð Ñr   c                  óv   — ddl } t        €*| j                  j                  d«      }|r|S t	        d«      ‚t        S )zGet the stash socket path.r   NÚGUNICORN_DIRTY_SOCKETz\Stash socket path not configured. Make sure dirty_workers > 0 and dirty_apps are configured.)Úosr¡   ÚenvironrO   r   )r¦   r¢   s     r   Úget_stash_socket_pathr¨   ¨  sA   € ãÜÐ!à�z‰z�~‰~Ð5Ó6ˆÙØˆKÜðIó
ð 	
ô Ðr   c                  ól   — t        t        dd«      } | € t        «       }t        |«      } | t        _        | S )z*Get or create a thread-local stash client.Ústash_clientN)ÚgetattrÚ_thread_localr¨   r*   rª   )r…   r,   s     r   Ú_get_clientr­   ·  s4   € ä”] N°DÓ9€FØ€~Ü+Ó-ˆÜ˜[Ó)ˆØ%+ŒÔ"Ø€Mr   c                 ó:   — t        «       j                  | ||«       y)zStore a value in a table.N)r­   r\   )rT   r(   rG   s      r   r\   r\   Ã  s   € äƒM×Ñ�e˜S %Õ(r   c                 ó8   — t        «       j                  | ||«      S )zRetrieve a value from a table.)r­   rO   )rT   r(   r_   s      r   rO   rO   È  s   € ä‹=×Ñ˜U C¨Ó1Ð1r   c                 ó6   — t        «       j                  | |«      S )zDelete a key from a table.)r­   rb   ©rT   r(   s     r   rb   rb   Í  ó   € ä‹=×Ñ  sÓ+Ð+r   c                 ó6   — t        «       j                  | |«      S )zGet all keys in a table.)r­   rf   )rT   rH   s     r   rf   rf   Ò  s   € ä‹=×Ñ˜e WÓ-Ð-r   c                 ó6   — t        «       j                  | «       y)zDelete all entries in a table.N)r­   ri   ©rT   s    r   ri   ri   ×  s   € äƒM×Ñ˜Õr   c                 ó4   — t        «       j                  | «      S )zGet information about a table.)r­   rk   rµ   s    r   rk   rk   Ü  s   € ä‹=×Ñ˜eÓ$Ð$r   c                 ó6   — t        «       j                  | «       y)zEnsure a table exists.N)r­   rm   rµ   s    r   rm   rm   á  s   € äƒM×Ñ˜Õr   c                 ó6   — t        «       j                  | |«      S )zCheck if a table or key exists.)r­   ro   r±   s     r   ro   ro   æ  r²   r   c                 ó6   — t        «       j                  | «       y)zDelete an entire table.N)r­   rq   rµ   s    r   rq   rq   ë  s   € äƒM×Ñ˜uÕ%r   c                  ó2   — t        «       j                  «       S )zList all tables.)r­   rt   r   r   r   rt   rt   ð  s   € ä‹=×ÑÓ!Ð!r   c                 ó4   — t        «       j                  | «      S )z%Get a dict-like interface to a table.)r­   rT   )rw   s    r   rT   rT   õ  s   € ä‹=×Ñ˜tÓ$Ð$r   rz   )(r   r/   r4   Úerrorsr   Úprotocolr   r   r   r   r	   r
   r   r   r   r   r   r   r   r   r&   r*   rv   Úlocalr¬   r¡   r£   r¨   r­   r\   rO   rb   rf   ri   rk   rm   ro   rq   rt   rT   r   r   r   ú<module>r¿      sÊ   ðñ
*óX Û å ÷÷ ÷ ó ô /�ô /ôA˜jô AôB˜Jô B÷qñ q÷hF4ñ F4ð\  �	—‘Ó!€ð Ð òòòò)ó
2ò
,ó
.ò
ò
%ò
 ó
,ò
&ò
"ó
%r   