
    h                        U 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 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 d dlmZmZmZ dd	lmZmZmZm Z m!Z! dd
l"m#Z#m$Z$m%Z%m&Z& ddl'm(Z( ddl)m*Z*m+Z+ ddl,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4 ddl5m6Z6 ddlm7Z7m8Z8 ddl9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z? e;rd dl@Z@dZAdZBdZCdZDdZE eF       ZGeee%e&e$f      eHd<   e;re$ZIne%ZI G d d      ZJ G d d      ZK G d d      ZL G d deL      ZM G d d eM      ZN G d! d"eL      ZOd#ZPd$ ZQeReSeSeQeQeTeReReQeSd%
ZUd& ZV G d' d(      ZW G d) d*eW      ZXy)+    N)abstractmethod)chain)EmptyFull	LifoQueue)time)AnyCallableListOptionalSequenceTypeUnion)parse_qsunquoteurlparse   )DEFAULT_ALLOW_LISTDEFAULT_DENY_LISTDEFAULT_EVICTION_POLICYAbstractCache_LocalCache)Encoder_HiredisParser_RESP2Parser_RESP3Parser)	NoBackoff)CredentialProvider"UsernamePasswordCredentialProvider)AuthenticationError$AuthenticationWrongNumberOfArgsErrorChildDeadlockedErrorConnectionError	DataError
RedisErrorResponseErrorTimeoutError)Retry)KeysT	ResponseT)CRYPTOGRAPHY_AVAILABLEHIREDIS_AVAILABLEHIREDIS_PACK_AVAILABLESSL_AVAILABLEget_lib_versionstr_if_bytes   *   $s   
       DefaultParserc                       e Zd ZdefdZy)HiredisRespSerializerargsc                    g }t        |d   t              r1t        |d   j                         j	                               |dd z   }n)d|d   v r"t        |d   j	                               |dd z   }	 |j                  t        j                  |             |S # t        $ r3 t        j                         \  }}}t        |      j                  |      w xY w2Pack a series of arguments into the Redis protocolr   r   N    )
isinstancestrtupleencodesplitappendhiredispack_command	TypeErrorsysexc_infor$   with_traceback)selfr8   output_value	tracebacks         [/var/www/html/retail-simulation-api/retail/lib/python3.12/site-packages/redis/connection.pypackzHiredisRespSerializer.packB   s    d1gs#a)//12T!"X=DT!W_a)DH4D	=MM'..t45
 	  	="%,,.AuiE"11)<<	=s   1$B <CN)__name__
__module____qualname__r   rO    r3   rN   r7   r7   A   s    $ r3   r7   c                       e Zd ZddZd Zy)PythonRespSerializerNc                      || _         || _        y N)_buffer_cutoffr@   )rI   buffer_cutoffr@   s      rN   __init__zPythonRespSerializer.__init__T   s    +r3   c           	      n   g }t        |d   t              r1t        |d   j                         j	                               |dd z   }n)d|d   v r"t        |d   j	                               |dd z   }t
        j                  t        t        t        |            j                         t        f      }| j                  }t        | j                  |      D ]  }t        |      }t        |      |kD  s||kD  st        |t              rat
        j                  |t        t        |      j                         t        f      }|j                  |       |j                  |       t        }t
        j                  |t        t        |      j                         t        |t        f      } |j                  |       |S r:   )r=   r>   r?   r@   rA   	SYM_EMPTYjoinSYM_STARlenSYM_CRLFrX   map
memoryview
SYM_DOLLARrB   )rI   r8   rJ   buffrY   arg
arg_lengths          rN   rO   zPythonRespSerializer.packX   sd    d1gs#a)//12T!"X=DT!W_a)DH4D~~xSY)>)>)@(KL++t{{D)C SJD	M)-c:. ~~:s:'='='?J d#c" ~~"J..0  	! *4 	dr3   returnN)rP   rQ   rR   rZ   rO   rS   r3   rN   rU   rU   S   s    +r3   rU   c            6       ~   e Zd ZdZdddddedddedddd e       ddddd	dddd
deee	fde
dee   dee   dee   dedededede
de
dee   dee   dee   dee   deedf   deeg df      dee   dee
   deeg df      dedee   d e
d!e
d"ed#ee   d$ee   f4d%Zd& Zed'        Zd( Zd) Zd* Zd+ Zd, Zd- Zed.        Zed/        Z ed0        Z!d1 Z"d2 Z#d3 Z$d4 Z%d5 Z&dJd7Z'd8 Z(dKd9Z)	 dLd6dd:d;Z*d< Z+d= Z,d>eeeeee      f      d?dfd@Z-dAe.e   fdBZ/dAe.e   dCe0dDee1   fdEZ2dF Z3dAeee.e   f   fdGZ4dHe1fdIZ5y)MAbstractConnectionz0Manages communication to and from a Redis serverr   NFutf-8stricti   zredis-pyr4   i'  dbpasswordsocket_timeoutsocket_connect_timeoutretry_on_timeoutencodingencoding_errorsdecode_responsessocket_read_sizehealth_check_intervalclient_namelib_namelib_versionusernameretryredis_connect_funccredential_providerprotocolcommand_packercache_enabledclient_cachecache_max_size	cache_ttlcache_policycache_deny_listcache_allow_listc                 r   |s|r|t        d      t        j                         | _        || _        || _        || _        || _        || _        || _	        || _
        || _        ||}|| _        || _        |t        u rg }|r|j                  t                || _        |s|rR|t%        t'               d      | _        nt+        j,                  |      | _        | j(                  j/                  |       nt%        t'               d      | _        || _        d| _        || _        t7        |||	      | _        d| _        || _        | j?                  |
       g | _         d| _!        	 tE        |      }|dk  s|dkD  rtM        d	      || _'        | jQ                  |      | _)        |rtU        |||      }nd}||n|| _+        | jV                  (| jN                  d
vrtY        d      || _-        || _.        yy# tF        $ r	 tH        }Y tJ        $ r tM        d      w xY w# dk  s|dkD  rtM        d	      || _'        w xY w)a2  
        Initialize a new Connection.
        To specify a retry policy for specific errors, first set
        `retry_on_error` to a list of the error/s to retry on, then set
        `retry` to a valid `Retry` object.
        To retry on TimeoutError, `retry_on_timeout` can also be set to `True`.
        Nz'username' and 'password' cannot be passed along with 'credential_provider'. Please provide only one of the following arguments: 
1. 'password' and (optional) 'username'
2. 'credential_provider'r   r   ip  zprotocol must be an integerr4      zprotocol must be either 2 or 3)r   3zBclient caching is only supported with protocol version 3 or higher)/r$   osgetpidpidrm   rw   rx   ry   r}   rn   rz   ro   rp   rq   SENTINELrB   r'   retry_on_errorr(   r   r{   copydeepcopyupdate_supported_errorsrv   next_health_checkr|   r   encoder_sock_socket_read_size
set_parser_connect_callbacksrX   intrE   DEFAULT_RESP_VERSION
ValueErrorr#   r~   _construct_command_packer_command_packerr   r   r%   r   r   )rI   rm   rn   ro   rp   rq   r   rr   rs   rt   parser_classru   rv   rw   rx   ry   rz   r{   r|   r}   r~   r   r   r   r   r   r   r   r   p_caches                                  rN   rZ   zAbstractConnection.__init__   sG   L &9&E+  99;& &#6   ,!)%3"&<# 0X%N!!,/,N}"9;2
 "]]51
JJ..~>y{A.DJ%:"!""4x:JK
!1%"$"
	HA 1uA%&FGGDM#==nM LIFF,8,DL&(}}H, X  $3D $4D! )  	%$A 	A!"?@@	A 1uA%&FGGDMs$   !G0 0H?H HH H6c           	          dj                  | j                         D cg c]  \  }}| d|  c}}      }d| j                  j                   d| j                  j                   d| dS c c}}w )N,=<.()>)r]   repr_pieces	__class__rQ   rP   )rI   kv	repr_argss       rN   __repr__zAbstractConnection.__repr__   sp    HHT5E5E5GH5GTQ1QCj5GHI	4>>,,-Qt~~/F/F.GqSUVV Is   A,
c                      y rW   rS   rI   s    rN   r   zAbstractConnection.repr_pieces       r3   c                 D    	 | j                          y # t        $ r Y y w xY wrW   )
disconnect	Exceptionr   s    rN   __del__zAbstractConnection.__del__   s#    	OO 		s    	c                 ~    ||S t         r
t               S t        | j                  | j                  j
                        S rW   )r-   r7   rU   rX   r   r@   )rI   packers     rN   r   z,AbstractConnection._construct_command_packer  s6    M#(**'(;(;T\\=P=PQQr3   c                     t        j                  |      }|| j                  vr| j                  j                  |       yy)a^  
        Register a callback to be called when the connection is established either
        initially or reconnected.  This allows listeners to issue commands that
        are ephemeral to the connection, for example pub/sub subscription or
        key tracking.  The callback must be a _method_ and will be kept as
        a weak reference.
        N)weakref
WeakMethodr   rB   )rI   callbackwms      rN   register_connect_callbackz,AbstractConnection.register_connect_callback  s;     )T,,,##**2. -r3   c                     	 | j                   j                  t        j                  |             y# t        $ r Y yw xY w)z
        De-register a previously registered callback.  It will no-longer receive
        notifications on connection events.  Calling this is not required when the
        listener goes away, since the callbacks are kept as weak methods.
        N)r   remover   r   r   )rI   r   s     rN   deregister_connect_callbackz.AbstractConnection.deregister_connect_callback  s8    	##**7+=+=h+GH 		s   .1 	==c                 4     || j                         | _        y)z
        Creates a new instance of parser_class with socket size:
        _socket_read_size and assigns it to the parser for the connection
        :param parser_class: The required parser class
        )ru   N)r   _parser)rI   r   s     rN   r   zAbstractConnection.set_parser"  s     $T5K5KLr3   c                 <     j                   ry	  j                  j                   fd fd      }| _         	  j                   j                          n j                           j                  D cg c]  } |       s| c} _         j                  D ]  } |       }|s |         y# t        j                  $ r t        d      t        $ r}t         j                  |            d}~ww xY w# t        $ r  j                           w xY wc c}w )z5Connects to the Redis server if not already connectedNc                  $     j                         S rW   )_connectr   s   rN   <lambda>z,AbstractConnection.connect.<locals>.<lambda>0  s    r3   c                 &    j                  |       S rW   r   )errorrI   s    rN   r   z,AbstractConnection.connect.<locals>.<lambda>0  s    tu7Mr3   zTimeout connecting to server)r   r{   call_with_retrysockettimeoutr'   OSErrorr#   _error_messager|   
on_connectr%   r   r   )rI   sockerefr   s   `    rN   connectzAbstractConnection.connect*  s   ::	:::--')MD 

	&&.! ''- 372I2I"S2I3SU32I"S**CuH +- ~~ 	?=>> 	:!$"5"5a"899	:  	OO	 #Ts.   "B3 .C; 6DD3&C8C33C8;Dc                      y rW   rS   r   s    rN   r   zAbstractConnection._connectM  r   r3   c                      y rW   rS   r   s    rN   _host_errorzAbstractConnection._host_errorQ  r   r3   c                      y rW   rS   )rI   	exceptions     rN   r   z!AbstractConnection._error_messageU  r   r3   c                 `   | j                   j                  |        | j                   }d}| j                  s| j                  s| j                  r>| j                  xs  t        | j                  | j                        }|j                         }|r| j                  dvrt        | j                   t              rK| j                  t               |j                  | j                   _        | j                   j                  |        t        |      dk(  rd|d   g} | j                  d| j                  dg|  | j                         }n(|r@ | j                  dg|dd	i 	 | j                         }t#        |      dk7  rt%        d      | j                  dvrt        | j                   t              rK| j                  t               |j                  | j                   _        | j                   j                  |        | j                  d| j                         | j                         }|j'                  d      | j                  k7  r)|j'                  d      | j                  k7  rt)        d      | j*                  rD| j                  dd| j*                         t#        | j                               dk7  rt)        d      	 | j,                  r.| j                  ddd| j,                         | j                          	 | j0                  r.| j                  ddd| j0                         | j                          | j2                  rC| j                  d| j2                         t#        | j                               dk7  rt)        d      | j4                  rI| j                  ddd       | j                          | j                   j7                  | j8                         yy# t         $ r+ | j                  d|d
   d	       | j                         }Y w xY w# t.        $ r Y #w xY w# t.        $ r Y w xY w)z=Initialize the connection, authenticate and select a databaseN)r4   2r   defaultr   HELLOAUTHcheck_healthFr   OKzInvalid Username or Passwords   protoprotozInvalid RESP versionCLIENTSETNAMEzError setting client nameSETINFOzLIB-NAMEzLIB-VERSELECTzInvalid DatabaseTRACKINGON)r   r   r}   rz   rn   r   get_credentialsr~   r=   r   r   r   EXCEPTION_CLASSESr_   send_commandread_responser!   r0   r    getr#   rw   rx   r&   ry   rm   r   set_invalidation_push_handler_cache_invalidation_process)rI   parser	auth_argscred_providerresponseauth_responses         rN   r   zAbstractConnection.on_connectY  s   %	##(( T5dmmT]]S  &557I h6$,,5-171I1I.''-9~"&	!5	Dgt}}fIyI))+H
  DfEyEuE5 $ 2 2 4 M*d2)*HII ]](*$,,5-171I1I.''-gt}}5))+HX&$--7LL)T]]:%&<== h	43C3CDD..01T9%&ABB	}}!!(Iz4==Q""$	!!(Iy$BRBRS""$
 77h0D..01T9%&899 h
D9 LL66t7W7WX m 8 5
 !!&)B-e!L $ 2 2 45J  		  		s6    O  :P ;:P! 0PP	PP!	P-,P-c                    | j                   j                          | j                  }d| _        |yt        j                         | j
                  k(  r 	 |j                  t        j                         	 |j                          | j                  r| j                  j                          yy# t        t        f$ r Y Jw xY w# t        $ r Y Hw xY w)z!Disconnects from the Redis serverN)r   on_disconnectr   r   r   r   shutdownr   	SHUT_RDWRr   rE   closer   flush)rI   r8   	conn_socks      rN   r   zAbstractConnection.disconnect  s    ""$JJ	
99;$(("""6#3#34	OO ##%  Y' 
  		s$   B+ 3C  +B=<B= 	CCc                 x    | j                  dd       t        | j                               dk7  rt        d      y)z Send PING, expect PONG in returnPINGFr   PONGz#Bad response from PING health checkN)r   r0   r   r#   r   s    rN   
_send_pingzAbstractConnection._send_ping  s<    &u5**,-7!"GHH 8r3   c                 $    | j                          y)z Function to call when PING failsNr   )rI   r   s     rN   _ping_failedzAbstractConnection._ping_failed      r3   c                     | j                   rIt               | j                  kD  r1| j                  j	                  | j
                  | j                         yyy)z3Check the health of the connection with a PING/PONGN)rv   r   r   r{   r   r   r   r   s    rN   r   zAbstractConnection.check_health  sA    %%$&43I3I*IJJ&&t8I8IJ +J%r3   Tc                 N   | j                   s| j                          |r| j                          	 t        |t              r|g}|D ]  }| j                   j                  |        y# t        j                  $ r | j                          t        d      t        $ ro}| j                          t        |j                        dk(  rd|j                  d   }}n|j                  d   }|j                  d   }t        d| d| d      d}~wt        $ r | j                           w xY w)	z2Send an already packed command to the Redis serverzTimeout writing to socketr   UNKNOWNr   Error z while writing to socket. r   N)r   r   r   r=   r>   sendallr   r   r   r'   r   r_   r8   r#   BaseException)rI   commandr   itemr   errnoerrmsgs          rN   send_packed_commandz&AbstractConnection.send_packed_command  s    zzLLN	'3'")

""4(  ~~ 	<OO:;; 	WOO166{a )166!9vq	!F5'1KF8ST"UVV 	
 OO	s   5A& &6D$A*DD$c                 x    | j                   | j                  j                  | |j                  dd             y)z+Pack and send a command to the Redis serverr   Tr   N)r  r   rO   r   )rI   r8   kwargss      rN   r   zAbstractConnection.send_command  s9      %D  %%t,ND9 	! 	
r3   c                    | j                   }|s| j                          | j                         }	 | j                  j	                  |      S # t
        $ r0}| j                          t        d| d|j                         d}~ww xY w)z8Poll the socket to see if there's data that can be read.Error while reading from z: N)	r   r   r   r   can_readr   r   r#   r8   )rI   r   r   
host_errorr   s        rN   r  zAbstractConnection.can_read  sy    zzLLN%%'
	V<<((11 	VOO!$=j\AFF8"TUU	Vs   A 	B+A??B)disconnect_on_errorpush_requestc                \   | j                         }	 | j                  dv r$t        s| j                  j	                  ||      }n| j                  j	                  |      }| j                  rt               | j                  z   | _        t!        |t"              r	 ||S # t
        j                  $ r! |r| j                          t        d|       t        $ r2}|r| j                          t        d| d|j                         d}~wt        $ r |r| j                           w xY w# ~w xY w)z0Read the response from a previously sent command)r   r   )disable_decodingr  )r  zTimeout reading from r  z : N)r   r~   r,   r   r   r   r   r   r'   r   r#   r8   r  rv   r   r   r=   r&   )rI   r  r  r  r  r   r   s          rN   r   z AbstractConnection.read_response  s(    %%'
	}}(1B<<55%5L 6   <<55GW5X& %%%)Vd.H.H%HD"h. 5 ~~ 	E"!!6zlCDD 	"!!+J<3qvvhG   	 #!	 s$   AB D( ;D%-D D%(D+c                 4     | j                   j                  | S )r;   )r   rO   )rI   r8   s     rN   rD   zAbstractConnection.pack_commandA  s    (t##(($//r3   c                    g }g }d}| j                   }|D ]  } | j                  j                  | D ]  }t        |      }||kD  s||kD  st	        |t
              r*|r$|j                  t        j                  |             d}g }||kD  st	        |t
              r|j                  |       y|j                  |       ||z  }  |r$|j                  t        j                  |             |S )z.Pack multiple commands into the Redis protocolr   )	rX   r   rO   r_   r=   rb   rB   r\   r]   )	rI   commandsrJ   piecesbuffer_lengthrY   cmdchunkchunklens	            rN   pack_commandsz AbstractConnection.pack_commandsE  s    ++C2--22C8u:!M1-/!%4innV&<=$%MFm+z%/LMM%(MM%(!X-M! 9 & MM)..01r3   datarh   c                     |d   | j                   j                          y|d   D ]&  }| j                   j                  t        |             ( y)a6  
        Invalidate (delete) all redis commands associated with a specific key.
        `data` is a list of strings, where the first string is the invalidation message
        and the second string is the list of keys to invalidate.
        (if the list of keys is None, then all keys are invalidated)
        r   N)r   r   invalidate_keyr0   )rI   r  keys      rN   r   z.AbstractConnection._cache_invalidation_processc  sF     7?##%Aw!!00c1BC r3   r  c                     | j                   "|d   | j                  v s|d   | j                  vry| j                         r#| j	                  d       | j                         r#| j                   j                  |      S )zK
        If the command is in the local cache, return the response
        Nr   T)r  )r   r   r   r  r   r   rI   r  s     rN   _get_from_local_cachez(AbstractConnection._get_from_local_cacher  ss    
 %qzT111qz!6!66mmoD1 mmo  $$W--r3   r   keysc                     | j                   `| j                  g k(  s|d   | j                  vr?| j                  g k(  s|d   | j                  v r| j                   j                  |||       yyyy)zp
        Add the command and response to the local cache if the command
        is allowed to be cached
        Nr   )r   r   r   set)rI   r  r   r&  s       rN   _add_to_local_cachez&AbstractConnection._add_to_local_cache  sw     )%%+wqzAUAU/U&&",
d>S>S0S!!'8T: 1T 0V *r3   c                 R    | j                   r| j                   j                          y y rW   )r   r   r   s    rN   flush_cachezAbstractConnection.flush_cache  s"    ##% r3   c                 T    | j                   r| j                   j                  |       y y rW   )r   delete_commandr$  s     rN   delete_command_from_cachez,AbstractConnection.delete_command_from_cache  s$    ,,W5 r3   r"  c                 T    | j                   r| j                   j                  |       y y rW   )r   r!  )rI   r"  s     rN   invalidate_key_from_cachez,AbstractConnection.invalidate_key_from_cache  s$    ,,S1 r3   T)r   )F)6rP   rQ   rR   __doc__r   r5   r/   r   r   r   r   r   r>   floatboolr   r	   r
   r   r   r   rZ   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r  r   rD   r  r   r   r%  r*   r)   r)  r+  r.  r0  rS   r3   rN   rj   rj      s0   6 "&*.26!&'!&" %%&%)",%4%6"&"&;?<@"#7;#04#3%6&8;j5j5 3-j5 !	j5
 !)j5 j5 j5 j5 j5 j5  #j5 c]j5 3-j5  c]!j5" 3-#j5$ S$Y%j5& %Xb$h%78'j5( &&89)j5* 3-+j5, !"d(!34-j5. /j50 }-1j52 3j54 5j56 7j58 c9j5: s);j5XW  R
/	M!F      ^Y@&.IK
>
V  , !,\0<DsHT#Y$7789D	D.Xc] .;};09;AEe;&6sHSM7I1J 62U 2r3   rj   c                   F     e Zd ZdZ	 	 	 	 	 d fd	Zd Zd Zd Zd Z xZ	S )
Connectionz4Manages TCP communication to and from a Redis serverc                     || _         t        |      | _        || _        |xs i | _        || _        t        |   di | y NrS   )hostr   portsocket_keepalivesocket_keepalive_optionssocket_typesuperrZ   )rI   r9  r:  r;  r<  r=  r  r   s          rN   rZ   zConnection.__init__  sD     	I	 0(@(FB%&"6"r3   c                     d| j                   fd| j                  fd| j                  fg}| j                  r|j	                  d| j                  f       |S )Nr9  r:  rm   rw   )r9  r:  rm   rw   rB   rI   r  s     rN   r   zConnection.repr_pieces  sM    499%		':T477OLMM=$*:*:;<r3   c                 @   d}t        j                  | j                  | j                  | j                  t         j
                        D ]  }|\  }}}}}d}	 t        j                   |||      }|j                  t         j                  t         j                  d       | j                  rr|j                  t         j                  t         j                  d       | j                  j                         D ]&  \  }	}
|j                  t         j                  |	|
       ( |j                  | j                         |j!                  |       |j                  | j"                         |c S  ||t%        d      # t$        $ r}|}||j'                          Y d}~Qd}~ww xY w)zCreate a TCP socket connectionNr   z)socket.getaddrinfo returned an empty list)r   getaddrinfor9  r:  r=  SOCK_STREAM
setsockoptIPPROTO_TCPTCP_NODELAYr;  
SOL_SOCKETSO_KEEPALIVEr<  items
settimeoutrp   r   ro   r   r   )rI   errresfamilysocktyper   	canonnamesocket_addressr   r   r   rK   s               rN   r   zConnection._connect  s\   
 %%IItyy$"2"2F4F4F
C BE>FHeYD!}}VXu= 2 2F4F4FJ ((OOF$5$5v7J7JAN $ = = C C E1(:(:AqA !F  ; ;< ^,  3 341
> ?IABB  !#JJL!s   DE55	F>FFc                 8    | j                    d| j                   S )N:)r9  r:  r   s    rN   r   zConnection._host_error  s    ))Adii[))r3   c                 R   | j                         }t        |j                        dk(  r	 d| d|j                  d    dS 	 d|j                  d    d| d	|j                  d    dS # t        $ r d|j                  d    cY S w xY w# t        $ r d|j                  d    cY S w xY w)
Nr   zError connecting to z.                         r   r   zConnection Error: r  z connecting to . )r   r_   r8   AttributeErrorrI   r   r  s      rN   r   zConnection._error_message  s     %%'
y~~!#@-j\ :"*+1. .
@Y^^A./!l"Y^^A%6$7q:	 " @+INN1,=+>??@ " @+INN1,=+>??@s#   A' %B 'BBB&%B&)	localhosti  FNr   
rP   rQ   rR   r2  rZ   r   r   r   r   __classcell__r   s   @rN   r6  r6    s3    : !%# 'CR*@r3   r6  c                   J     e Zd ZdZ	 	 	 	 	 	 	 	 	 	 	 	 	 	 d fd	Z fdZ xZS )SSLConnectionzManages SSL connections to and from the Redis server(s).
    This class extends the Connection class, adding SSL functionality, and making
    use of ssl.SSLContext (https://docs.python.org/3/library/ssl.html#ssl.SSLContext)
    c                    t         st        d      || _        || _        |t        j
                  }nWt        |t              rGt        j
                  t        j                  t        j                  d}||vrt        d|       ||   }|| _
        || _        || _        || _        || _        || _        |	| _        |
| _        || _        || _        || _        || _        t-        | \  di | y)a  Constructor

        Args:
            ssl_keyfile: Path to an ssl private key. Defaults to None.
            ssl_certfile: Path to an ssl certificate. Defaults to None.
            ssl_cert_reqs: The string value for the SSLContext.verify_mode (none, optional, required). Defaults to "required".
            ssl_ca_certs: The path to a file of concatenated CA certificates in PEM format. Defaults to None.
            ssl_ca_data: Either an ASCII string of one or more PEM-encoded certificates or a bytes-like object of DER-encoded certificates.
            ssl_check_hostname: If set, match the hostname during the SSL handshake. Defaults to False.
            ssl_ca_path: The path to a directory containing several CA certificates in PEM format. Defaults to None.
            ssl_password: Password for unlocking an encrypted private key. Defaults to None.

            ssl_validate_ocsp: If set, perform a full ocsp validation (i.e not a stapled verification)
            ssl_validate_ocsp_stapled: If set, perform a validation on a stapled ocsp response
            ssl_ocsp_context: A fully initialized OpenSSL.SSL.Context object to be used in verifying the ssl_ocsp_expected_cert
            ssl_ocsp_expected_cert: A PEM armoured string containing the expected certificate to be returned from the ocsp verification service.
            ssl_min_version: The lowest supported SSL version. It affects the supported SSL versions of the SSLContext. None leaves the default provided by ssl module.
            ssl_ciphers: A string listing the ciphers that are allowed to be used. Defaults to None, which means that the default ciphers are used. See https://docs.python.org/3/library/ssl.html#ssl.SSLContext.set_ciphers for more information.

        Raises:
            RedisError
        z$Python wasn't built with SSL supportN)noneoptionalrequiredz+Invalid SSL Certificate Requirements Flag: rS   )r.   r%   keyfilecertfilessl	CERT_NONEr=   r>   CERT_OPTIONALCERT_REQUIRED	cert_reqsca_certsca_dataca_pathcheck_hostnamecertificate_passwordssl_validate_ocspssl_validate_ocsp_stapledssl_ocsp_contextssl_ocsp_expected_certssl_min_versionssl_ciphersr>  rZ   )rI   ssl_keyfilessl_certfilessl_cert_reqsssl_ca_certsssl_ca_datassl_check_hostnamessl_ca_pathssl_passwordrm  rn  ro  rp  rq  rr  r  	CERT_REQSr   s                    rN   rZ   zSSLConnection.__init__  s    P CDD"$ MMMs+----I
 I- A-Q  &m4M&$""0$0!!2)B& 0&<#.&"6"r3   c                 J   t         
|          }t        j                         }| j                  |_        | j
                  |_        | j                  s| j                  r2|j                  | j                  | j                  | j                         | j                  | j                  | j                  2|j                  | j                  | j                  | j                         | j                  | j                  |_        | j"                  r|j%                  | j"                         |j'                  || j(                        }| j*                  du rt,        du rt/        d      | j0                  r| j*                  rt/        d      | j0                  r+d	dl}d
dlm} | j8                  f|j:                  j=                  |j:                  j>                        }|jA                  | j                         |jC                  | j                         n| j8                  }|jE                  || jF                         |j:                  jI                  |tK        jJ                               }|jM                          |jO                  | j(                  | jP                  f       |jS                          |jU                          |S | j*                  du rRt,        rLd
dlm+}  ||| j(                  | jP                  | j                        }	|	jY                         r|S t[        d      |S )z Wrap the socket with SSL support)rb  ra  rn   N)cafilecapathcadata)server_hostnameTFzcryptography is not installed.zKEither an OCSP staple or pure OCSP connection must be validated - not both.r   r   )ocsp_staple_verifier)OCSPVerifierzocsp validation error).r>  r   rc  create_default_contextrk  rg  verify_moderb  ra  load_cert_chainrl  rh  rj  ri  load_verify_locationsrq  minimum_versionrr  set_cipherswrap_socketr9  rm  r+   r%   rn  OpenSSLocspr  ro  SSLContextSSLv23_METHODuse_certificate_fileuse_privatekey_fileset_ocsp_client_callbackrp  r6  r   request_ocspr   r:  do_handshaker   r  is_validr#   )rI   r   contextsslsockr  r  
staple_ctxconr  or   s             rN   r   zSSLConnection._connectD  s   w!,,.!%!4!4"nn==DLL##22 $  MM%||'||'))}}T\\$,, *  +&*&:&:G# 0 01%%dDII%F!!T).D.M=>>))d.D.D  ))2 $$,$[[001J1JK
//>..t||<!22
//$d&A&A
 ++((V]]_ECKKDII./LLNN !!T).D*WdiiDMMJAzz|%&=>>r3   )NNr`  NNFNNFFNNNN)rP   rQ   rR   r2  rZ   r   rY  rZ  s   @rN   r\  r\    sG       "'#F#PE Er3   r\  c                   <     e Zd ZdZd fd	Zd Zd Zd Zd Z xZ	S )UnixDomainSocketConnectionz4Manages UDS communication to and from a Redis serverc                 @    || _         || _        t        |   di | y r8  )pathro   r>  rZ   )rI   r  ro   r  r   s       rN   rZ   z#UnixDomainSocketConnection.__init__  s"    	,"6"r3   c                     d| j                   fd| j                  fg}| j                  r|j                  d| j                  f       |S )Nr  rm   rw   )r  rm   rw   rB   r@  s     rN   r   z&UnixDomainSocketConnection.repr_pieces  sB    499%dgg7MM=$*:*:;<r3   c                    t        j                   t         j                  t         j                        }|j                  | j                         |j                  | j                         |j                  | j                         |S )z&Create a Unix domain socket connection)r   AF_UNIXrC  rJ  rp   r   r  ro   )rI   r   s     rN   r   z#UnixDomainSocketConnection._connect  sU    }}V^^V-?-?@334TYY++,r3   c                     | j                   S rW   )r  r   s    rN   r   z&UnixDomainSocketConnection._host_error  s    yyr3   c                     | j                         }t        |j                        dk(  rd| d|j                  d    dS d|j                  d    d| d|j                  d    dS )Nr   z!Error connecting to unix socket: rT  r   r   r  z connecting to unix socket: )r   r_   r8   rV  s      rN   r   z)UnixDomainSocketConnection._error_message  s}     %%'
y~~!#3J<r)..QRBSATTUV
 *++G,b!2 316r3   ) NrX  rZ  s   @rN   r  r    s    :#
r3   r  )0FFALSENNOc                 v    | | dk(  ry t        | t              r| j                         t        v ryt	        |       S )Nr  F)r=   r>   upperFALSE_STRINGSr4  )rL   s    rN   to_boolr    s4    }%%++-="@;r3   )
rm   ro   rp   r;  rq   r   max_connectionsrv   rx  r   c                 B   | j                  d      s-| j                  d      s| j                  d      st        d      t        |       } i }t        | j                        j                         D ]N  \  }}|s	t        |      dkD  st        |d         }t        j                  |      }|r	  ||      ||<   J|||<   P | j                  rt        | j                        |d<   | j                  rt        | j                        |d	<   | j                  d
k(  r/| j                  rt        | j                        |d<   t        |d<   |S | j                   rt        | j                         |d<   | j"                  rt%        | j"                        |d<   | j                  r6d|vr2	 t%        t        | j                        j'                  dd            |d<   | j                  dk(  r	t*        |d<   |S # t        t        f$ r t        d| d      w xY w# t(        t        f$ r Y Mw xY w)Nzredis://z	rediss://zunix://zRRedis URL must specify one of the following schemes (redis://, rediss://, unix://)r   zInvalid value for `z` in connection URL.rz   rn   unixr  connection_classr9  r:  rm   /r  rediss)
startswithr   r   r   queryrI  r_   r   URL_QUERY_ARGUMENT_PARSERSr   rE   rz   rn   schemer  r  hostnamer:  r   replacerU  r\  )urlr  namerL   r   s        rN   	parse_urlr    s   z">>+&>>)$5
 	

 3-CF		*002eSZ!^E!H%E/33D9FW#)%=F4L  %t 3 ||$S\\2z
||$S\\2z zzV88$SXX.F6N%?!"& M! <<$S\\2F6N88 ]F6N 88F*"7388#4#<#<S"#EFt ::!)6F%&MC ":. W$':4&@T%UVVW6 #J/ s   -G*1H *H	HHc                       e Zd ZdZed        Zedfdee   fdZ	de
e
ffdZddZdd	Zd
e
ddfdZdefdZddZddZdddefdZddeddfdZddZddZd Zde
fdZde
fdZy) ConnectionPoola  
    Create a connection pool. ``If max_connections`` is set, then this
    object raises :py:class:`~redis.exceptions.ConnectionError` when the pool's
    limit is reached.

    By default, TCP connections are created unless ``connection_class``
    is specified. Use class:`.UnixDomainSocketConnection` for
    unix sockets.

    Any additional keyword arguments are passed to the constructor of
    ``connection_class``.
    c                 b    t        |      }d|v r|d   |d<   |j                  |        | di |S )a  
        Return a connection pool configured from the given URL.

        For example::

            redis://[[username]:[password]]@localhost:6379/0
            rediss://[[username]:[password]]@localhost:6379/0
            unix://[username@]/path/to/socket.sock?db=0[&password=password]

        Three URL schemes are supported:

        - `redis://` creates a TCP socket connection. See more at:
          <https://www.iana.org/assignments/uri-schemes/prov/redis>
        - `rediss://` creates a SSL wrapped TCP socket connection. See more at:
          <https://www.iana.org/assignments/uri-schemes/prov/rediss>
        - ``unix://``: creates a Unix Domain Socket connection.

        The username, password, hostname, path and all querystring values
        are passed through urllib.parse.unquote in order to replace any
        percent-encoded values with their corresponding characters.

        There are several ways to specify a database number. The first value
        found will be used:

            1. A ``db`` querystring option, e.g. redis://localhost?db=0
            2. If using the redis:// or rediss:// schemes, the path argument
               of the url, e.g. redis://localhost/0
            3. A ``db`` keyword argument to this function.

        If none of these options are specified, the default db=0 is used.

        All querystring options are cast to their appropriate Python types.
        Boolean arguments can be specified with string values "True"/"False"
        or "Yes"/"No". Values that cannot be properly cast cause a
        ``ValueError`` to be raised. Once parsed, the querystring arguments
        and keyword arguments are passed to the ``ConnectionPool``'s
        class initializer. In the case of conflicting arguments, querystring
        arguments always win.
        r  rS   )r  update)clsr  r  url_optionss       rN   from_urlzConnectionPool.from_url  s?    R  n'.45G.HK*+k"}V}r3   Nr  c                     |xs d}t        |t              r|dk  rt        d      || _        || _        || _        t        j                         | _        | j                          y )Nl        r   z,"max_connections" must be a positive integer)
r=   r   r   r  connection_kwargsr  	threadingLock
_fork_lockreset)rI   r  r  r  s       rN   rZ   zConnectionPool.__init__E  s\     *2U/3/?Q3FKLL 0!2. $..*

r3   rh   c                     dt        |       j                   dt        |       j                   dt         | j                  di | j
                         dS )Nr   r   r   r   rS   )typerQ   rP   reprr  r  r   s    rN   r   zConnectionPool.__repr__^  sV    T
%%&aT
(;(;'<*T**DT-C-CDEFbJ	
r3   c                     t        j                         | _        d| _        g | _        t               | _        t        j                         | _	        y )Nr   )
r  r  _lock_created_connections_available_connectionsr(  _in_use_connectionsr   r   r   r   s    rN   r  zConnectionPool.resetd  s9    ^^%
$%!&(##&5  99;r3   c                 f   | j                   t        j                         k7  rq| j                  j	                  d      }|st
        	 | j                   t        j                         k7  r| j                          | j                  j                          y y # | j                  j                          w xY w)N   )r   )r   r   r   r  acquirer"   r  release)rI   acquireds     rN   	_checkpidzConnectionPool._checkpidu  s    F 88ryy{"..q.9H***88ryy{*JJL'') # '')s   1B B0command_namer6  c                 d   | j                          | j                  5  	 | j                  j                         }| j                  j                  |       ddd       	 j                          	 |j                         r|j                  t        d      |S # t        $ r | j                         }Y yw xY w# 1 sw Y   cxY w# t        t        f$ r? |j                          |j                          |j                         rt        d      Y |S w xY w# t        $ r | j                          w xY w)zGet a connection from the poolNConnection has dataConnection not ready)r  r  r  pop
IndexErrormake_connectionr  addr   r  r   r#   r   r   r  r  rI   r  r&  options
connections        rN   get_connectionzConnectionPool.get_connection  s%   ZZ4!88<<>
 $$((4 	 B&&(Z-D-D-L)*?@@ 9  4!113
4 Z( $W- B%%'""$&&()*@AA ) B
  	 LL$		sX   B6BB6D .'C B30B62B33B66B?A
DD DD D/c                     | j                   }t        |j                  dd      |j                  dd      |j                  dd            S )z,Return an encoder based on encoding settingsrr   rk   rs   rl   rt   F)rr   rs   rt   )r  r   r   )rI   r  s     rN   get_encoderzConnectionPool.get_encoder  sF    ''ZZ
G4"JJ'8(C#ZZ(:EB
 	
r3   c                     | j                   | j                  k\  rt        d      | xj                   dz  c_          | j                  di | j                  S )zCreate a new connectionzToo many connectionsr   rS   )r  r  r#   r  r  r   s    rN   r  zConnectionPool.make_connection  sO    $$(<(<<!"899!!Q&!$t$$>t'='=>>r3   r  c                 v   | j                          | j                  5  	 | j                  j                  |       | j                  |      r| j                  j                  |       n/| xj                  dz  c_        |j                          	 ddd       y	 ddd       y# t        $ r Y qw xY w# 1 sw Y   yxY w)z(Releases the connection back to the poolr   N)
r  r  r  r   KeyErrorowns_connectionr  rB   r  r   rI   r  s     rN   r  zConnectionPool.release  s    ZZ((//
; ##J/++22:>
 ))Q.)%%'!	 	 ? Z    Zs.   B/B AB/ 	B,)B/+B,,B//B8c                 4    |j                   | j                   k(  S rW   )r   r  s     rN   r  zConnectionPool.owns_connection  s    ~~))r3   inuse_connectionsc                     | j                          | j                  5  |r!t        | j                  | j                        }n| j                  }|D ]  }|j                           	 ddd       y# 1 sw Y   yxY w)z
        Disconnects connections in the pool

        If ``inuse_connections`` is True, disconnect connections that are
        current in use, potentially by other threads. Otherwise only disconnect
        connections that are idle in the pool.
        N)r  r  r   r  r  r   )rI   r  connectionsr  s       rN   r   zConnectionPool.disconnect  s`     	ZZ #//1I1I #99)
%%' * ZZs   AA..A7c                 $    | j                          y)z-Close the pool, disconnecting all connectionsNr   r   s    rN   r   zConnectionPool.close  r   r3   c                     | j                   j                  d|i       | j                  D ]	  }||_         | j                  D ]	  }||_         y )Nr{   )r  r  r  r{   r  )rI   r{   conns      rN   	set_retryzConnectionPool.set_retry  sI    %%w&67//DDJ 0,,DDJ -r3   c                     | j                          | j                  5  t        | j                  | j                        }|D ]  }|j                           	 d d d        y # 1 sw Y   y xY wrW   )r  r  r   r  r  r+  )rI   r  r  s      rN   r+  zConnectionPool.flush_cache  sK    ZZ ; ;T=U=UVK)
&&( * ZZs   8AA(r  c                     | j                          | j                  5  t        | j                  | j                        }|D ]  }|j                  |        	 d d d        y # 1 sw Y   y xY wrW   )r  r  r   r  r  r.  )rI   r  r  r  s       rN   r.  z(ConnectionPool.delete_command_from_cache  sM    ZZ ; ;T=U=UVK)
44W= * ZZ   9A  A)r"  c                     | j                          | j                  5  t        | j                  | j                        }|D ]  }|j                  |        	 d d d        y # 1 sw Y   y xY wrW   )r  r  r   r  r  r0  )rI   r"  r  r  s       rN   r0  z(ConnectionPool.invalidate_key_from_cache  sM    ZZ ; ;T=U=UVK)
44S9 * ZZr  rg   )rh   r6  )r  r6  rh   Nr1  )r{   r(   rh   N)rP   rQ   rR   r2  classmethodr  r6  r   r   rZ   r>   r   r  r  r  r   r  r  r  r  r4  r   r   r  r+  r.  r0  rS   r3   rN   r  r    s     . .d $)- "#2
3* 
"-*^"3 "\ "H
W 
?**, *3 *(D (D (()> >:S :r3   r  c                   J     e Zd ZdZddeef fd	Zd Zd Zd Z	d Z
d	 Z xZS )
BlockingConnectionPoola  
    Thread-safe blocking connection pool::

        >>> from redis.client import Redis
        >>> client = Redis(connection_pool=BlockingConnectionPool())

    It performs the same function as the default
    :py:class:`~redis.ConnectionPool` implementation, in that,
    it maintains a pool of reusable connections that can be shared by
    multiple redis clients (safely across threads if required).

    The difference is that, in the event that a client tries to get a
    connection from the pool when all of connections are in use, rather than
    raising a :py:class:`~redis.ConnectionError` (as the default
    :py:class:`~redis.ConnectionPool` implementation does), it
    makes the client wait ("blocks") for a specified number of seconds until
    a connection becomes available.

    Use ``max_connections`` to increase / decrease the pool size::

        >>> pool = BlockingConnectionPool(max_connections=10)

    Use ``timeout`` to tell it either how many seconds to wait for a connection
    to become available, or to block forever:

        >>> # Block forever.
        >>> pool = BlockingConnectionPool(timeout=None)

        >>> # Raise a ``ConnectionError`` after five seconds if a connection is
        >>> # not available.
        >>> pool = BlockingConnectionPool(timeout=5)
    2      c                 F    || _         || _        t        |   d||d| y )N)r  r  rS   )queue_classr   r>  rZ   )rI   r  r   r  r  r  r   s         rN   rZ   zBlockingConnectionPool.__init__G  s6     ' 	
-+	
  	
r3   c                     | j                  | j                        | _        	 	 | j                  j                  d        # t        $ r Y nw xY wg | _        t        j                         | _        y rW   )	r  r  pool
put_nowaitr   _connectionsr   r   r   r   s    rN   r  zBlockingConnectionPool.resetW  sf    $$T%9%9:			$$T*   
  99;s   ? 	A
Ac                 t     | j                   di | j                  }| j                  j                  |       |S )zMake a fresh connection.rS   )r  r  r   rB   r  s     rN   r  z&BlockingConnectionPool.make_connectiono  s7    *T**DT-C-CD
  ,r3   c                 
   | j                          d}	 | j                  j                  d| j                        }|| j                         }	 |j                          	 |j                         rt        d      	 |S # t        $ r t        d      w xY w# t
        t        f$ r? |j                          |j                          |j                         rt        d      Y |S w xY w# t        $ r | j                  |        w xY w)a7  
        Get a connection, blocking for ``self.timeout`` until a connection
        is available from the pool.

        If the connection returned is ``None`` then creates a new connection.
        Because we use a last-in first-out queue, the existing connections
        (having been returned to the pool after the initial ``None`` values
        were added) will be returned before ``None`` values. This means we only
        create new connections when we need to, i.e.: the actual number of
        connections will only increase in response to demand.
        NT)blockr   zNo connection available.r  r  )r  r  r   r   r   r#   r  r   r  r   r   r  r  r  s        rN   r  z%BlockingConnectionPool.get_connectionu  s    	 
	>T4<<HJ --/J	 
B&&()*?@@ ) =  	> ""<==	>( $W- B%%'""$&&()*@AA ) B
  	LL$	s6   'A= C& B =BA
C#C& "C##C& &Dc                     | j                          | j                  |      s,|j                          | j                  j	                  d       y	 | j                  j	                  |       y# t
        $ r Y yw xY w)z)Releases the connection back to the pool.N)r  r  r   r  r  r   r  s     rN   r  zBlockingConnectionPool.release  sj     	##J/
 !!#II  &	II  , 	 	s   A+ +	A76A7c                 f    | j                          | j                  D ]  }|j                           y)z(Disconnects all connections in the pool.N)r  r   r   r  s     rN   r   z!BlockingConnectionPool.disconnect  s(    ++J!!# ,r3   )rP   rQ   rR   r2  r6  r   rZ   r  r  r  r  r   rY  rZ  s   @rN   r  r  %  s6    F #
 02h*$r3   r  )Yr   r   r   rc  rF   r  r   abcr   	itertoolsr   queuer   r   r   r   typingr	   r
   r   r   r   r   r   urllib.parser   r   r   r   r   r   r   r   r   _parsersr   r   r   r   backoffr   credentialsr   r   
exceptionsr    r!   r"   r#   r$   r%   r&   r'   r{   r(   r)   r*   utilsr+   r,   r-   r.   r/   r0   rC   r^   rc   r`   r\   r   objectr   __annotations__r5   r7   rU   rj   r6  r\  r  r  r  r   r3  listr  r  r  r  rS   r3   rN   <module>r     se    	  
 
     ( (  G G G 4 4  J I  O	 	 	  $  
	 8E,nDEF F"M M $0 0fR2 R2jX@# X@vSJ Sl%!3 %P / # ! 6r\: \:~]$^ ]$r3   