
    >i              
       N   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 d dl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%m&Z&m'Z'm(Z(m)Z)m*Z* ddl+m,Z, ddl-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3 e/rd dl4Z4dZ5dZ6dZ7dZ8dZ9 e:       Z;eeeeef      e<d<   e/reZ=neZ= G d d      Z> G d d      Z? G d d      Z@ G d de@      ZA G d deA      ZB G d d e@      ZCd!ZDd" ZEeFeGeGeEeEeHeFeFeEd#	ZId$ ZJ G d% d&      ZK G d' d(eK      ZLy))    N)abstractmethod)chain)EmptyFull	LifoQueue)time)OptionalTypeUnion)parse_qsunquoteurlparse   )Encoder_HiredisParser_RESP2Parser_RESP3Parser)	NoBackoff)CredentialProvider"UsernamePasswordCredentialProvider)AuthenticationError$AuthenticationWrongNumberOfArgsErrorChildDeadlockedErrorConnectionError	DataError
RedisErrorResponseErrorTimeoutError)Retry)CRYPTOGRAPHY_AVAILABLEHIREDIS_AVAILABLEHIREDIS_PACK_AVAILABLESSL_AVAILABLEget_lib_versionstr_if_bytes   *   $s   
       DefaultParserc                       e Zd Zd Zy)HiredisRespSerializerc                    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)selfargsoutput_value	tracebacks         l/var/www/html/wine-match-dev/backend/winematch-backend/venv/lib/python3.12/site-packages/redis/connection.pypackzHiredisRespSerializer.pack:   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__rD    r(   rC   r,   r,   9   s    r(   r,   c                       e Zd ZddZd Zy)PythonRespSerializerNc                      || _         || _        y N)_buffer_cutoffr4   )r=   buffer_cutoffr4   s      rC   __init__zPythonRespSerializer.__init__L   s    +r(   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.   )r1   r2   r3   r4   r5   	SYM_EMPTYjoinSYM_STARlenSYM_CRLFrM   map
memoryview
SYM_DOLLARr6   )r=   r>   r?   buffrN   arg
arg_lengths          rC   rD   zPythonRespSerializer.packP   si    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r(   )returnN)rE   rF   rG   rO   rD   rH   r(   rC   rJ   rJ   K   s    +r(   rJ   c                      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fd
ee   dee	   fd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d        Zd Zd Zd Zd Zd Zd%dZd Zd&d Z	 d'ddd!d"Zd# Z d$ Z!y)(AbstractConnectionz0Manages communication to and from a Redis serverr   NFutf-8stricti   zredis-pyr)   credential_providerprotocolc                    |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                  |      | _)        y# tF        $ r	 tH        }Y DtJ        $ 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 integerr)      zprotocol must be either 2 or 3)*r   osgetpidpiddbclient_namelib_namelib_versionra   passwordusernamesocket_timeoutsocket_connect_timeoutretry_on_timeoutSENTINELr6   r   retry_on_errorr   r   retrycopydeepcopyupdate_supported_errorshealth_check_intervalnext_health_checkredis_connect_funcr   encoder_sock_socket_read_size
set_parser_connect_callbacksrM   intr9   DEFAULT_RESP_VERSION
ValueErrorr   rb   _construct_command_packer_command_packer)r=   rh   rl   rn   ro   rp   rr   encodingencoding_errorsdecode_responsesparser_classsocket_read_sizerw   ri   rj   rk   rm   rs   ry   ra   rb   command_packerps                          rC   rO   zAbstractConnection.__init__   s   > &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  	%$A 	A!"?@@	A 1uA%&FGGDMs$   !F G.G 0GG G%c           	          dj                  | j                         D cg c]  \  }}| d|  c}}      }| j                  j                   d| dS c c}}w )N,=<>)rR   repr_pieces	__class__rE   )r=   kv	repr_argss       rC   __repr__zAbstractConnection.__repr__   sV    HHT5E5E5GHTQ1QCjHI	..))*!I;a88 Is   A
c                      y rL   rH   r=   s    rC   r   zAbstractConnection.repr_pieces       r(   c                 D    	 | j                          y # t        $ r Y y w xY wrL   )
disconnect	Exceptionr   s    rC   __del__zAbstractConnection.__del__   s#    	OO 		s    	c                 ~    ||S t         r
t               S t        | j                  | j                  j
                        S rL   )r"   r,   rJ   rM   rz   r4   )r=   packers     rC   r   z,AbstractConnection._construct_command_packer   s6    M#(**'(;(;T\\=P=PQQr(   c                 `    | j                   j                  t        j                  |             y rL   )r~   r6   weakref
WeakMethod)r=   callbacks     rC   register_connect_callbackz,AbstractConnection.register_connect_callback   s!    &&w'9'9('CDr(   c                     g | _         y rL   )r~   r   s    rC   clear_connect_callbacksz*AbstractConnection.clear_connect_callbacks   s
    "$r(   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
        )r   N)r|   _parser)r=   r   s     rC   r}   zAbstractConnection.set_parser   s     $T5K5KLr(   c                      j                   ry	  j                  j                   fd fd      }| _         	  j                   j                          n j                           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)z5Connects to the Redis server if not already connectedNc                  $     j                         S rL   )_connectr   s   rC   <lambda>z,AbstractConnection.connect.<locals>.<lambda>  s     r(   c                 &    j                  |       S rL   r   )errorr=   s    rC   r   z,AbstractConnection.connect.<locals>.<lambda>  s    tu7M r(   zTimeout connecting to server)r{   rs   call_with_retrysockettimeoutr   OSErrorr   _error_messagery   
on_connectr   r   r~   )r=   sockerefr   s   `    rC   connectzAbstractConnection.connect   s    ::	:::--')MD 

	&&.! ''- ** 	CuH	) ~~ 	?=>> 	:!$"5"5a"899	:  	OO	s"   "B .C &C2CCC/c                      y rL   rH   r   s    rC   r   zAbstractConnection._connect  r   r(   c                      y rL   rH   r   s    rC   _host_errorzAbstractConnection._host_error#  r   r(   c                      y rL   rH   )r=   	exceptions     rC   r   z!AbstractConnection._error_message'  r   r(   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                  rD| j                  d| j2                         t#        | j                               dk7  rt)        d      yy# t         $ r+ | j                  d|d
   d	       | j                         }Y Iw 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)r)   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)r   r   ra   rm   rl   r   get_credentialsrb   r1   r   r}   r   EXCEPTION_CLASSESrT   send_commandread_responser   r%   r   getr   ri   rj   r   rk   rh   )r=   parser	auth_argscred_providerresponseauth_responses         rC   r   zAbstractConnection.on_connect+  sG   %	##(( 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 : a 8 5
 !!&)B-e!L $ 2 2 45J  		  		s6    N  :N= ;:O 0N:9N:=	O	O		OOc                 D   | j                   j                          | j                  }d| _        |yt        j                         | j
                  k(  r 	 |j                  t        j                         	 |j                          y# t        $ r Y w xY w# t        $ r Y yw xY w)z!Disconnects from the Redis serverN)r   on_disconnectr{   re   rf   rg   shutdownr   	SHUT_RDWRr   close)r=   r>   	conn_socks      rC   r   zAbstractConnection.disconnect  s    ""$JJ	
99;$(("""6#3#34	OO	  
  		s$   B 3B 	BB	BB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   r%   r   r   r   s    rC   
_send_pingzAbstractConnection._send_ping  s<    &u5**,-7!"GHH 8r(   c                 $    | j                          y)z Function to call when PING failsNr   )r=   r   s     rC   _ping_failedzAbstractConnection._ping_failed  s    r(   c                     | j                   rIt               | j                  kD  r1| j                  j	                  | j
                  | j                         yyy)z3Check the health of the connection with a PING/PONGN)rw   r   rx   rs   r   r   r   r   s    rC   r   zAbstractConnection.check_health  sA    %%$&43I3I*IJJ&&t8I8IJ +J%r(   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. .N)r{   r   r   r1   r2   sendallr   r   r   r   r   rT   r>   r   BaseException)r=   commandr   itemr   errnoerrmsgs          rC   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   rD   r   )r=   r>   kwargss      rC   r   zAbstractConnection.send_command  s9      %D  %%t,ND9 	! 	
r(   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   r>   )r=   r   r   
host_errorr   s        rC   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                N   | 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)z0Read the response from a previously sent command)3rd   )disable_decodingr   )r   zTimeout reading from r   z : N)r   rb   r!   r   r   r   r   r   r   r   r   r>   r   rw   r   rx   r1   r   )r=   r   r   r   r   r   r   s          rC   r   z AbstractConnection.read_response  s    %%'
	}}(1B<<55%5L 6   <<55GW5X& %%%)Vd.H.H%HD"h.N/ ~~ 	E"!!6zlCDD 	"!!+J<3qvvhG   	 #!	s   AB ;D$-D D$c                 4     | j                   j                  | S )r/   )r   rD   )r=   r>   s     rC   r8   zAbstractConnection.pack_command  s    (t##(($//r(   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   )	rM   r   rD   rT   r1   rW   r6   rQ   rR   )	r=   commandsr?   piecesbuffer_lengthrN   cmdchunkchunklens	            rC   pack_commandsz AbstractConnection.pack_commands  s    ++ 	.C2--22C8 .u:!M1-/!%4innV&<=$%MFm+z%/LMM%(MM%(!X-M!.	.& MM)..01r(   T)r   )F)"rE   rF   rG   __doc__rq   r*   r$   r	   r   r   rO   r   r   r   r   r   r   r   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r8   r  rH   r(   rC   r^   r^   ~   s9   6 # "#%<@"#-WN( &&89)WN* 3-+WNr9  RE%MB      X:t(IK
>
V  ) !)V0r(   r^   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 NrH   )hostr   portsocket_keepalivesocket_keepalive_optionssocket_typesuperrO   )r=   r  r	  r
  r  r  r   r   s          rC   rO   zConnection.__init__-  sD     	I	 0(@(FB%&"6"r(   c                     d| j                   fd| j                  fd| j                  fg}| j                  r|j	                  d| j                  f       |S )Nr  r	  rh   ri   )r  r	  rh   ri   r6   r=   r   s     rC   r   zConnection.repr_pieces=  sM    499%		':T477OLMM=$*:*:;<r(   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   getaddrinfor  r	  r  SOCK_STREAM
setsockoptIPPROTO_TCPTCP_NODELAYr
  
SOL_SOCKETSO_KEEPALIVEr  items
settimeoutro   r   rn   r   r   )r=   errresfamilysocktyper   	canonnamesocket_addressr   r   r   r@   s               rC   r   zConnection._connectC  sg   
 %%IItyy$"2"2F4F4F
 	!C BE>FHeYD!}}VXu= 2 2F4F4FJ ((OOF$5$5v7J7JAN $ = = C C E B1(:(:AqAB  ; ;< ^,  3 341	!> ?IABB  !#JJL!s   DE55	F>FFc                 8    | j                    d| j                   S )N:)r  r	  r   s    rC   r   zConnection._host_errorl  s    ))Adii[))r(   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   rT   r>   AttributeErrorr=   r   r   s      rC   r   zConnection._error_messageo  s     %%'
y~~!#@-j\ :"*+1. .
@Y^^A./!l"Y^^A%6$7q:	 " @+INN1,=+>??@ " @+INN1,=+>??@s#   A' %B 'BBB&%B&)	localhosti  FNr   
rE   rF   rG   r  rO   r   r   r   r   __classcell__r   s   @rC   r  r  *  s3    : !%# 'CR*@r(   r  c                   F     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)        | T  di | y)ae  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.

        Raises:
            RedisError
        z$Python wasn't built with SSL supportN)noneoptionalrequiredz+Invalid SSL Certificate Requirements Flag: rH   )r#   r   keyfilecertfilessl	CERT_NONEr1   r2   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_certr  rO   )r=   ssl_keyfilessl_certfilessl_cert_reqsssl_ca_certsssl_ca_datassl_check_hostnamessl_ca_pathssl_passwordr<  r=  r>  r?  r   	CERT_REQSr   s                  rC   rO   zSSLConnection.__init__  s    H CDD"$ MMMs+----I
 I- A-Q  &m4M&$""0$0!!2)B& 0&<#"6"r(   c                    t         
|          }t        j                         }| j                  |_        | j
                  |_        | j                  s| j                  r2|j                  | j                  | j                  | j                         | j                  | j                  | j                  2|j                  | j                  | j                  | j                         |j                  || j                         }| j"                  du rt$        du rt'        d      | j(                  r| j"                  rt'        d      | j(                  r+d	dl}d
dlm} | j0                  f|j2                  j5                  |j2                  j6                        }|j9                  | j                         |j;                  | j                         n| j0                  }|j=                  || j>                         |j2                  jA                  |tC        jB                               }|jE                          |jG                  | j                   | jH                  f       |jK                          |jM                          |S | j"                  du rRt$        rLd
dlm'}  ||| j                   | jH                  | j                        }	|	jQ                         r|S tS        d      |S )z Wrap the socket with SSL support)r1  r0  rl   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   r2  create_default_contextr:  r6  verify_moder1  r0  load_cert_chainr;  r7  r9  r8  load_verify_locationswrap_socketr  r<  r    r   r=  OpenSSLocsprN  r>  SSLContextSSLv23_METHODuse_certificate_fileuse_privatekey_fileset_ocsp_client_callbackr?  r  r   request_ocspr   r	  do_handshaker   rO  is_validr   )r=   r   contextsslsockrU  rN  
staple_ctxconrO  or   s             rC   r   zSSLConnection._connect  sH   w!,,.!%!4!4"nn==DLL##22 $  MM%||'||'))}}T\\$,, *  %%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|%&=>>r(   )NNr/  NNFNNFFNN)rE   rF   rG   r  rO   r   r(  r)  s   @rC   r+  r+    sA       "'#@#DA Ar(   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 r  )pathrn   r  rO   )r=   rh  rn   r   r   s       rC   rO   z#UnixDomainSocketConnection.__init__  s"    	,"6"r(   c                     d| j                   fd| j                  fg}| j                  r|j                  d| j                  f       |S )Nrh  rh   ri   )rh  rh   ri   r6   r  s     rC   r   z&UnixDomainSocketConnection.repr_pieces  sB    499%dgg7MM=$*:*:;<r(   c                    t        j                   t         j                  t         j                        }|j                  | j                         |j                  | j                         |j                  | j                         |S )z&Create a Unix domain socket connection)r   AF_UNIXr  r  ro   r   rh  rn   )r=   r   s     rC   r   z#UnixDomainSocketConnection._connect  sU    }}V^^V-?-?@334TYY++,r(   c                     | j                   S rL   )rh  r   s    rC   r   z&UnixDomainSocketConnection._host_error'  s    yyr(   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: r#  r   r   r   z connecting to unix socket: )r   rT   r>   r%  s      rC   r   z)UnixDomainSocketConnection._error_message*  s}     %%'
y~~!#3J<r)..QRBSATTUV
 *++G,b!2 316r(   ) Nr'  r)  s   @rC   rf  rf    s    :#
r(   rf  )0FFALSENNOc                 v    | | dk(  ry t        | t              r| j                         t        v ryt	        |       S )Nrn  F)r1   r2   upperFALSE_STRINGSbool)rA   s    rC   to_boolrx  <  s4    }%%++-="@;r(   )	rh   rn   ro   r
  rp   rr   max_connectionsrw   rE  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.rm   rl   unixrh  connection_classr  r	  rh   /rn  rediss)
startswithr   r   r   queryr  rT   r   URL_QUERY_ARGUMENT_PARSERSr   r9   rm   rl   schemerh  rf  hostnamer	  r   replacer$  r+  )urlr   namerA   r   s        rC   	parse_urlr  Q  s   z">>+&>>)$5
 	

 3-CF		*002 
%eSZ!^E!H%E/33D9FW#)%=F4L  %t
% ||$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                   l    e Zd ZdZed        ZedfdZd Zd Z	d Z
d Zd	 Zd
 Zd Zd ZddZd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|  rH   )r  update)clsr  r   url_optionss       rC   from_urlzConnectionPool.from_url  s?    R  n'.45G.HK*+k"}V}r(   Nc                     |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)
r1   r   r   r|  connection_kwargsry  	threadingLock
_fork_lockreset)r=   r|  ry  r  s       rC   rO   zConnectionPool.__init__  s\     *2U/3/?Q3FKLL 0!2. $..*

r(   c           	      ~    t        |       j                   dt         | j                  di | j                         dS )Nr   r   rH   )typerE   reprr|  r  r   s    rC   r   zConnectionPool.__repr__  sC    Dz""#*T**DT-C-CDEFaI	
r(   c                     t        j                         | _        d| _        g | _        t               | _        t        j                         | _	        y )Nr   )
r  r  _lock_created_connections_available_connectionsset_in_use_connectionsre   rf   rg   r   s    rC   r  zConnectionPool.reset  s9    ^^%
$%!&(##&5  99;r(   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   )rg   re   rf   r  acquirer   r  release)r=   acquireds     rC   	_checkpidzConnectionPool._checkpid  s    F 88ryy{"..q.9H***88ryy{*JJL'') # '')s   1B B0c                 N   | j                          | j                  5  	 | j                  j                         }| j                  j                  |       ddd       	 j                          	 |j                         rt        d      	 |S # t        $ r | j                         }Y nw xY w# 1 sw Y   Xx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=   command_namekeysoptions
connections        rC   get_connectionzConnectionPool.get_connection%  s'   ZZ 	54!88<<>
 $$((4	5	 
B&&()*?@@ ) 3  4!113
4	5 	5" $W- B%%'""$&&()*@AA ) B
  	 LL$		sX   B+BB+D .B7 B(%B+'B((B++B47A
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 settingsr   r_   r   r`   r   F)r   r   r   )r  r   r   )r=   r   s     rC   get_encoderzConnectionPool.get_encoderF  sF    ''ZZ
G4"JJ'8(C#ZZ(:EB
 	
r(   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   rH   )r  ry  r   r|  r  r   s    rC   r  zConnectionPool.make_connectionO  sO    $$(<(<<!"899!!Q&!$t$$>t'='=>>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  removeKeyErrorowns_connectionr  r6   r  r   r=   r  s     rC   r  zConnectionPool.releaseV  s    ZZ 	((//
; ##J/++22:>
 ))Q.)%%'!	 	 ?	 	   	 	s.   B/B AB/ 	B,)B/+B,,B//B8c                 4    |j                   | j                   k(  S rL   )rg   r  s     rC   r  zConnectionPool.owns_connectionk  s    ~~))r(   c                     | 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   )r=   inuse_connectionsconnectionsr  s       rC   r   zConnectionPool.disconnectn  sp     	ZZ 		( #//1I1I #99) (
%%'(		( 		( 		(s   AA..A7c                     | j                   j                  d|i       | j                  D ]	  }||_         | j                  D ]	  }||_         y )Nrs   )r  r  r  rs   r  )r=   rs   conns      rC   	set_retryzConnectionPool.set_retry  sS    %%w&67// 	DDJ	,, 	DDJ	r(   r  )rs   r   r\   N)rE   rF   rG   r  classmethodr  r  rO   r   r  r  r  r  r  r  r  r   r  rH   r(   rC   r  r    s\     . .b  *4,
"-*^B
?**((r(   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|  ry  rH   )queue_classr   r  rO   )r=   ry  r   r|  r  r  r   s         rC   rO   zBlockingConnectionPool.__init__  s6     ' 	
-+	
  	
r(   c                     | j                  | j                        | _        	 	 | j                  j                  d        # t        $ r Y nw xY wg | _        t        j                         | _        y rL   )	r  ry  pool
put_nowaitr   _connectionsre   rf   rg   r   s    rC   r  zBlockingConnectionPool.reset  sf    $$T%9%9:			$$T*   
  99;s   ? 	A
Ac                 t     | j                   di | j                  }| j                  j                  |       |S )zMake a fresh connection.rH   )r|  r  r  r6   r  s     rC   r  z&BlockingConnectionPool.make_connection  s7    *T**DT-C-CD
  ,r(   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        rC   r  z%BlockingConnectionPool.get_connection  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     rC   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     rC   r   z!BlockingConnectionPool.disconnect$  s-    ++ 	$J!!#	$r(   )rE   rF   rG   r  r  r   rO   r  r  r  r  r   r(  r)  s   @rC   r  r    s6    F #
"02h*$r(   r  )Mrt   re   r   r2  r:   r  r   abcr   	itertoolsr   queuer   r   r   r   typingr	   r
   r   urllib.parser   r   r   _parsersr   r   r   r   backoffr   credentialsr   r   
exceptionsr   r   r   r   r   r   r   r   rs   r   utilsr    r!   r"   r#   r$   r%   r7   rS   rX   rU   rQ   r   objectrq   __annotations__r*   r,   rJ   r^   r  r+  rf  rv  rx  r   floatlistr  r  r  r  rH   r(   rC   <module>r     sO    	  
 
     ( (  ( ( 4 4 I I  O	 	 	   
	 8E,nDEF F"M M $0 0fi iXX@# X@vIJ IX%!3 %P / # !
 6r} }@^$^ ^$r(   