+
    j5                     N   R t ^ RIt^ RIt^RIHt ^RIHtHtHtH	t	H
t
HtHtHtHtHtHtHt  ! R R]4      t ! R R]4      t ! R R	]4      t ! R
 R4      t ! R R4      t]P.                  ! 4       tRsR tR tR tR tRR ltR tRR lt R t!R t"R t#RR lt$R t%R t&R t'R# )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                       ] tR t^EtRtRtR# )
StashErrorz$Base exception for stash operations. N)__name__
__module____qualname____firstlineno____doc____static_attributes__r       I/var/www/idalgo/venv/lib/python3.14/site-packages/gunicorn/dirty/stash.pyr   r   E   s    .r   r   c                   6   a a ] tR t^It oRtV 3R ltRtVtV ;t# )StashTableNotFoundErrorz#Raised when a table does not exist.c                8   < Wn         \        SV `	  R V 24       R# )zStash table not found: N)
table_namesuper__init__)selfr   	__class__s   &&r   r    StashTableNotFoundError.__init__L   s    $2:,?@r   )r   	r   r   r   r   r   r   r   __classdictcell____classcell__r!   __classdict__s   @@r   r   r   I   s     -A Ar   r   c                   6   a a ] tR t^Qt oRtV 3R ltRtVtV ;t# )StashKeyNotFoundErrorz,Raised when a key does not exist in a table.c                J   < Wn         W n        \        SV `  R V RV 24       R# )zKey not found in z: N)r   keyr   r   )r    r   r+   r!   s   &&&r   r   StashKeyNotFoundError.__init__T   s(    $,ZL3%@Ar   )r+   r   r#   r&   s   @@r   r)   r)   Q   s     6B Br   r)   c                      a  ] tR t^Zt o RtRR ltR tR tR tRR lt	R t
RR	 ltR
 tRR ltR tR tR tRR ltR tR tR tR tR tR tRtV tR# )StashClientz`
Client for stash operations.

Communicates with the arbiter which stores all tables in memory.
c                `    Wn         W n        RV n        \        P                  ! 4       V n        R# )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    r0   r1   s   &&&r   r   StashClient.__init__a   s$     '
^^%
r   c                >    \        \        P                  ! 4       4      # )zGenerate a unique request ID.)struuiduuid4r    s   &r   _get_request_idStashClient._get_request_idn   s    4::<  r   c                   ^ RI pV P                  e   R#  VP                  VP                  VP                  4      V n        V P                  P	                  V P
                  4       V P                  P                  V P                  4       R#   TP                  \        3 d   pRT n        \        RT 24      ThRp?ii ; i)z Establish connection to arbiter.NzFailed to connect to arbiter: )socketr2   AF_UNIXSOCK_STREAM
settimeoutr1   connectr0   errorOSErrorr   )r    r?   es   &  r   _connectStashClient._connectr   s    ::!	Jv~~v7I7IJDJJJ!!$,,/JJt//0g& 	JDJ=aSABI	Js   A5B B?$B::B?c                    V P                   e%    V P                   P                  4        RV n         R# R#   \         d     Li ; i)zClose the connection.N)r2   close	Exceptionr;   s   &r   _closeStashClient._close   sC    ::!

  " DJ "  s   5 AANc                v   V P                   ;_uu_ 4        V P                  f   V P                  4        V P                  4       p\	        WaVW4VR7      p \
        P                  ! V P                  V4       \
        P                  ! V P                  4      pVP                  R4      p	V	\
        P                  8X  d   VP                  R4      uuRRR4       # V	\
        P                  8X  df   VP                  R/ 4      p
V
P                  RR4      pV
P                  RR	4      pVR
8X  d   \        V4      hVR8X  d   \        W#4      h\        V4      h\        RV	 24      h  \         d<   pT P                  4        \!        T\        4      '       d   h \        RT 24      ThRp?ii ; i  + '       g   i     R# ; i)z
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resultrD   
error_typer   messagezUnknown errorr   r)   zUnexpected response type: zStash operation failed: )r5   r2   rG   r<   r   r   write_messageread_messagegetMSG_TYPE_RESPONSEMSG_TYPE_ERRORr   r)   r   rK   rL   
isinstance)r    optabler+   rO   rP   
request_idrT   responsemsg_type
error_inforS   	error_msgrF   s   &&&&&&        r   _executeStashClient._execute   so    ZZZzz!--/J(gG
H++DJJ@(55djjA#<</}>>>#<<1! Z" !=!==!)gr!:J!+l!KJ *y/ JI!%>>5e<<!%<<3E??$Y//$'A(%LMM Ha,, #;A3!?@aG	H= ZZs1   >F'A7EBEF$)6FF$$F''F8	c                6    V P                  \        WVR7       R# )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+   rO   N)rb   r   )r    r\   r+   rO   s   &&&&r   putStashClient.put   s     	lE%@r   c                X     V P                  \        WR7      #   \         d    Tu # i ; i)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+   )rb   r   r)   )r    r\   r+   defaults   &&&&r   rW   StashClient.get   s.    	==u=>>$ 	N	s    ))c                0    V P                  \        WR7      # )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
rh   )rb   r   r    r\   r+   s   &&&r   deleteStashClient.delete        }}_e}==r   c                0    V P                  \        WR7      # )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
rP   )rb   r   )r    r\   rP   s   &&&r   keysStashClient.keys   s     }}]E}CCr   c                2    V P                  \        V4       R# )z=
Delete all entries in a table.

Args:
    table: Table name
N)rb   r   r    r\   s   &&r   clearStashClient.clear   s     	ne,r   c                .    V P                  \        V4      # )zm
Get information about a table.

Args:
    table: Table name

Returns:
    Dict with table info (size, etc.)
)rb   r	   ru   s   &&r   infoStashClient.info   s     }}]E22r   c                2    V P                  \        V4       R# )z
Ensure a table exists (create if not exists).

This is idempotent - calling it multiple times is safe.

Args:
    table: Table name
N)rb   r
   ru   s   &&r   ensureStashClient.ensure  s     	ou-r   c                0    V P                  \        WR7      # )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
rh   )rb   r   rl   s   &&&r   existsStashClient.exists  ro   r   c                2    V P                  \        V4       R# )z6
Delete an entire table.

Args:
    table: Table name
N)rb   r   ru   s   &&r   delete_tableStashClient.delete_table$  s     	+U3r   c                .    V P                  \        R4      # )z4
List all tables.

Returns:
    List of table names
 )rb   r   r;   s   &r   tablesStashClient.tables-  s     }}_b11r   c                    \        W4      # )ze
Get a dict-like interface to a table.

Args:
    name: Table name

Returns:
    StashTable instance
)
StashTable)r    names   &&r   r\   StashClient.table6  s     $%%r   c                    V P                   ;_uu_ 4        V P                  4        RRR4       R#   + '       g   i     R# ; i)zClose the client connection.N)r5   rL   r;   s   &r   rJ   StashClient.closeB  s     ZZZKKM ZZZs	   0A	c                    V # Nr   r;   s   &r   	__enter__StashClient.__enter__G  s    r   c                &    V P                  4        R # r   )rJ   )r    exc_typeexc_valexc_tbs   &&&&r   __exit__StashClient.__exit__J  s    

r   )r5   r2   r0   r1   )g      >@)NNNr   )r   r   r   r   r   r   r<   rG   rL   rb   re   rW   rm   rr   rv   ry   r|   r   r   r   r\   rJ   r   r   r   r$   r'   s   @r   r.   r.   Z   ss     &!J0HlA">D-
3	.>42
&
 r   r.   c                      a  ] tR tRt o RtR t]R 4       tR tR t	R t
R tR	 tR
 tRR ltRR ltR tR tR tRtV tR# )r   iN  a
  
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                    Wn         W n        R # r   _client_name)r    clientr   s   &&&r   r   StashTable.__init__^  s    
r   c                    V P                   # )zTable name.)r   r;   s   &r   r   StashTable.nameb  s     zzr   c                    V P                   P                  V P                  V4      pVf8   V P                   P                  V P                  V4      '       g   \	        V4      hV# r   )r   rW   r   r   KeyError)r    r+   rR   s   && r   __getitem__StashTable.__getitem__g  sK    !!$**c2><<&&tzz377sm#r   c                R    V P                   P                  V P                  W4       R # r   )r   re   r   )r    r+   rO   s   &&&r   __setitem__StashTable.__setitem__o  s    S0r   c                t    V P                   P                  V P                  V4      '       g   \        V4      hR # r   )r   rm   r   r   r    r+   s   &&r   __delitem__StashTable.__delitem__r  s,    ||""4::s333- 4r   c                N    V P                   P                  V P                  V4      # r   )r   r   r   r   s   &&r   __contains__StashTable.__contains__v  s    ||""4::s33r   c                ^    \        V P                  P                  V P                  4      4      # r   )iterr   rr   r   r;   s   &r   __iter__StashTable.__iter__y  s     DLL%%djj122r   c                p    V P                   P                  V P                  4      pVP                  R ^ 4      # )size)r   ry   r   rW   )r    ry   s   & r   __len__StashTable.__len__|  s+    ||  ,xx""r   Nc                N    V P                   P                  V P                  W4      # )zGet value with default.)r   rW   r   )r    r+   ri   s   &&&r   rW   StashTable.get  s    ||

C99r   c                P    V P                   P                  V P                  VR7      # )z-Get all keys, optionally filtered by pattern.rq   )r   rr   r   )r    rP   s   &&r   rr   StashTable.keys  s     ||  W ==r   c                P    V P                   P                  V P                  4       R# )zDelete all entries.N)r   rv   r   r;   s   &r   rv   StashTable.clear  s    4::&r   c              #     "   V P                   P                  V P                  4       F,  pWP                   P                  V P                  V4      3x  K.  	  R# 5i)z Iterate over (key, value) pairs.Nr   rr   r   rW   r   s   & r   itemsStashTable.items  s@     <<$$TZZ0C||''

C888 1s   AAc              #     "   V P                   P                  V P                  4       F+  pV P                   P                  V P                  V4      x  K-  	  R# 5i)zIterate over values.Nr   r   s   & r   valuesStashTable.values  s=     <<$$TZZ0C,,""4::s33 1s   AAr   r   )r   r   r   r   r   r   propertyr   r   r   r   r   r   r   rW   rr   rv   r   r   r   r$   r   s   @r   r   r   N  s_       1 43#:>'9
4 4r   r   c                
    V s R# )z@Set the global stash socket path (called during initialization).N)_stash_socket_path)paths   &r   set_stash_socket_pathr     s
     r   c                     ^ RI p \        f1   V P                  P                  R4      pV'       d   V# \	        R4      h\        # )zGet the stash socket path.NGUNICORN_DIRTY_SOCKETz\Stash socket path not configured. Make sure dirty_workers > 0 and dirty_apps are configured.)osr   environrW   r   )r   r   s     r   get_stash_socket_pathr     sA    !zz~~56KI
 	
 r   c                 p    \        \        RR4      p V f!   \        4       p\        V4      p V \        n        V # )z*Get or create a thread-local stash client.stash_clientN)getattr_thread_localr   r.   r   )r   r0   s     r   _get_clientr     s4    ]ND9F~+-[)%+"Mr   c                :    \        4       P                  WV4       R# )zStore a value in a table.N)r   re   )r\   r+   rO   s   &&&r   re   re     s    Me%(r   c                6    \        4       P                  WV4      # )zRetrieve a value from a table.)r   rW   )r\   r+   ri   s   &&&r   rW   rW     s    =U11r   c                4    \        4       P                  W4      # )zDelete a key from a table.)r   rm   r\   r+   s   &&r   rm   rm         =++r   c                4    \        4       P                  W4      # )zGet all keys in a table.)r   rr   )r\   rP   s   &&r   rr   rr     s    =e--r   c                8    \        4       P                  V 4       R# )zDelete all entries in a table.N)r   rv   r\   s   &r   rv   rv     s    Mr   c                4    \        4       P                  V 4      # )zGet information about a table.)r   ry   r   s   &r   ry   ry     s    =e$$r   c                8    \        4       P                  V 4       R# )zEnsure a table exists.N)r   r|   r   s   &r   r|   r|     s    Mr   c                4    \        4       P                  W4      # )zCheck if a table or key exists.)r   r   r   s   &&r   r   r     r   r   c                8    \        4       P                  V 4       R# )zDelete an entire table.N)r   r   r   s   &r   r   r     s    Mu%r   c                 2    \        4       P                  4       # )zList all tables.)r   r   r   r   r   r   r     s    =!!r   c                4    \        4       P                  V 4      # )z%Get a dict-like interface to a table.)r   r\   )r   s   &r   r\   r\     s    =t$$r   r   )(r   r3   r9   errorsr   protocolr   r   r   r   r   r   r	   r
   r   r   r   r   r   r   r)   r.   r   localr   r   r   r   r   re   rW   rm   rr   rv   ry   r|   r   r   r   r\   r   r   r   <module>r      s   
*X       / /Aj ABJ Bq qhF4 F4\ !  )
2
,
.

%
 
,
&
"
%r   