o
    ;h                     @   s<  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Zd dlm	Z	 d dl
mZ d dlmZ d dlmZmZmZmZmZmZmZmZmZmZmZmZmZ d dlmZmZmZm Z  ddl!m"Z" e"rrd dl#Z#d d	l#m$Z$m%Z% ndZ#dZ%dZ$dd
l&m'Z' ddl(m)Z)m*Z* ddl!m+Z+m,Z, ej-dkrd dl m.Z/ nd dl/m.Z/ d dl0m1Z1 d dl2m3Z3 d dl4m5Z5 d dl6m7Z7m8Z8 d dl9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@ d dlAmBZB d dlCmDZDmEZEmFZF ddlGmHZHmIZImJZJmKZKmLZL dZMdZNdZOdZPdZQG dd dejRZSeSjTZUeeeKeLeJf  eVd< eDreJZWneKZWG dd  d eZXG d!d" d"eZYeeXeYf ZZG d#d$ d$Z[G d%d& d&e[Z\G d'd( d(e\Z]G d)d* d*Z^G d+d, d,e[Z_d-Z`d.eea fd/d0Zbeecededebebececebedd1	Zeeefed2egf f eVd3< G d4d5 d5ed6d7Zhd8efd.ehfd9d:Zied;d<d=ZjG d>d< d<ZkG d?d@ d@ekZldS )A    N)abstractmethod)chain)MappingProxyType)AnyCallableIterableListMappingOptionalProtocolSetTupleType	TypedDictTypeVarUnion)ParseResultparse_qsunquoteurlparse   )SSL_AVAILABLE)
SSLContext
TLSVersion)TokenInterface)!AsyncAfterConnectionReleasedEventEventDispatcher)deprecated_argsformat_error_message)      r   )timeout)Retry)	NoBackoff)DEFAULT_RESP_VERSION)CredentialProvider"UsernamePasswordCredentialProvider)AuthenticationError$AuthenticationWrongNumberOfArgsErrorConnectionError	DataError
RedisErrorResponseErrorTimeoutError)
EncodableT)HIREDIS_AVAILABLEget_lib_versionstr_if_bytes)
BaseParserEncoder_AsyncHiredisParser_AsyncRESP2Parser_AsyncRESP3Parser   *   $s   
   
    c                   @   s   e Zd Ze ZdS )	_SentinelN)__name__
__module____qualname__objectsentinel rA   rA   K/var/www/html/venv/lib/python3.10/site-packages/redis/asyncio/connection.pyr;   Q   s    
r;   DefaultParserc                   @      e Zd ZdddZdS )ConnectCallbackProtocol
connectionAbstractConnectionc                 C      d S NrA   selfrF   rA   rA   rB   __call__`   s    z ConnectCallbackProtocol.__call__NrF   rG   r<   r=   r>   rL   rA   rA   rA   rB   rE   _       rE   c                   @   rD   )AsyncConnectCallbackProtocolrF   rG   c                       d S rI   rA   rJ   rA   rA   rB   rL   d   s    z%AsyncConnectCallbackProtocol.__call__NrM   rN   rA   rA   rA   rB   rP   c   rO   rP   c                .   @   s  e Zd ZdZdZdddddedddedddd	e dddedd
ddde	e
ef dee
 dee dee dede	eef de
de
dedee dededee
 dee
 dee
 dee
 dee dee dee dee d ee d!ee f,d"d#Zefd$efd%d&Zd'd( Zd)d* Zed+d, Zed-d. Z d/d0 Z!d1d2 Z"dee d3dfd4d5Z#d6d7 Z$drd9efd:d;Z%ed<d= Z&ed3e
fd>d?Z'd@e(d3e
fdAdBZ)dCdD Z*dsdEdFZ+drd9ed3dfdGdHZ,dtdIed3dfdJdKZ-dLdM Z.dNdO Z/dPdQ Z0dRe1e2 d3dfdSdTZ3	8drdRe	e2e
e1e2 f d9ed3dfdUdVZ4dWedXed3dfdYdZZ5d[d\ Z6		dud8dd]d^ed_ee d`edaee fdbdcZ7dWe8d3e9e2 fdddeZ:dfe1e1e8  d3e9e2 fdgdhZ;didj Z<dkdl Z=dme>fdndoZ?dpdq Z@dS )vrG   z0Manages communication to and from a Redis server)dbusernameclient_namelib_namelib_versioncredential_providerpasswordsocket_timeoutsocket_connect_timeoutredis_connect_funcretry_on_timeoutretry_on_errorhealth_check_intervalnext_health_checkZlast_active_atencoderssl_contextprotocol_reader_writer_parser_connect_callbacks_buffer_cutoff_lock_socket_read_size__dict__r   NFutf-8stricti   zredis-pyr   )rR   rX   rY   rZ   r\   r]   encodingencoding_errorsdecode_responsesparser_classsocket_read_sizer^   rT   rU   rV   rS   retryr[   encoder_classrW   rb   event_dispatcherrR   rX   rY   rZ   r\   r]   rm   rn   ro   rp   rq   r^   rT   rU   rV   rS   rr   r[   rs   rW   rb   rt   c                C   s  |s|r|d urt d|d u rt | _n|| _|| _|| _|| _|| _|| _|| _|| _	|| _
|d u r6|}|| _|| _|tu rBg }|rU|t |tj |tj || _|s\|rs|sftt d| _nt|| _| j| ntt d| _|| _d| _||||	| _|| _d | _d | _|| _ | !|
 g | _"d| _#d | _$z.zt%|}W n t&y   t'}Y n t(y   t)dw W |dk s|dkrt)d	|| _*d S |dk s|dkrt)d	|| _*w )
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   ip  zprotocol must be an integerr   r   zprotocol must be either 2 or 3)+r*   r   _event_dispatcherrR   rT   rU   rV   rW   rX   rS   rY   rZ   r\   SENTINELappendr-   socketr!   asyncior]   r"   r#   rr   copydeepcopyZupdate_supported_errorsr^   r_   r`   r[   rc   rd   ri   
set_parserrf   rg   _re_auth_tokenint	TypeErrorr$   
ValueErrorr)   rb   )rK   rR   rX   rY   rZ   r\   r]   rm   rn   ro   rp   rq   r^   rT   rU   rV   rS   rr   r[   rs   rW   rb   rt   prA   rA   rB   __init__   sr   



zAbstractConnection.__init__	_warningsc                 C   sR   t | dd r'|jd| t| d zt  |   W d S  ty&   Y d S w d S )Nrd   zunclosed Connection )source)getattrwarnResourceWarningr{   get_running_loop_closeRuntimeError)rK   r   rA   rA   rB   __del__   s   zAbstractConnection.__del__c                 C   s$   | j r| j   d | _ | _dS dS )zR
        Internal method to silently close the connection without waiting
        N)rd   closerc   rK   rA   rA   rB   r      s   
zAbstractConnection._closec                 C   s8   d dd |  D }d| jj d| jj d| dS )N,c                 s   s"    | ]\}}| d | V  qdS )=NrA   ).0kvrA   rA   rB   	<genexpr>   s     z.AbstractConnection.__repr__.<locals>.<genexpr><.()>)joinrepr_pieces	__class__r=   r<   )rK   Z	repr_argsrA   rA   rB   __repr__   s    zAbstractConnection.__repr__c                 C   rH   rI   rA   r   rA   rA   rB   r         zAbstractConnection.repr_piecesc                 C   s   | j d uo	| jd uS rI   )rc   rd   r   rA   rA   rB   is_connected  s   zAbstractConnection.is_connectedc                 C   s(   t |}|| jvr| j| dS dS )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
WeakMethodrf   ry   )rK   callbackZwmrA   rA   rB   register_connect_callback  s   

z,AbstractConnection.register_connect_callbackc                 C   s.   z| j t| W dS  ty   Y dS 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)rf   remover   r   r   )rK   r   rA   rA   rB   deregister_connect_callback  s
   z.AbstractConnection.deregister_connect_callbackreturnc                 C   s   || j d| _dS )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
        )rq   N)ri   re   )rK   rp   rA   rA   rB   r~     s   zAbstractConnection.set_parserc                       | j ddI dH  dS )z5Connects to the Redis server if not already connectedTcheck_healthN)connect_check_healthr   rA   rA   rB   connect&     zAbstractConnection.connectTr   c              
      sT   j rd S z j fdd fddI d H  W n9 tjy#     tjtjfy1   td tyC } zt	 
|d }~w tyS } zt	||d }~ww z" jsb j|dI d H  nt jrp  I d H n   W n ty     I d H   w dd  jD  _ jD ]}| }| }|rt|r|I d H  qd S )Nc                            S rI   )_connectrA   r   rA   rB   <lambda>/      z9AbstractConnection.connect_check_health.<locals>.<lambda>c                    r   rI   
disconnecterrorr   rA   rB   r   /  r   zTimeout connecting to serverr   c                 S   s   g | ]}| r|qS rA   rA   )r   refrA   rA   rB   
<listcomp>M  s    z;AbstractConnection.connect_check_health.<locals>.<listcomp>)r   rr   call_with_retryr{   ZCancelledErrorrz   r!   r-   OSErrorr)   _error_message	Exceptionr[   on_connect_check_healthiscoroutinefunctionr+   r   rf   inspectisawaitable)rK   r   eexcr   r   taskrA   r   rB   r   *  sJ   



z'AbstractConnection.connect_check_healthc                    rQ   rI   rA   r   rA   rA   rB   r   T  s   zAbstractConnection._connectc                 C   rH   rI   rA   r   rA   rA   rB   _host_errorX  r   zAbstractConnection._host_error	exceptionc                 C   s   t |  |S rI   )r   r   )rK   r   rA   rA   rB   r   \     z!AbstractConnection._error_messagec                 C      | j S rI   )rb   r   rA   rA   rB   get_protocol_     zAbstractConnection.get_protocolc                    r   )z=Initialize the connection, authenticate and select a databaseTr   N)r   r   rA   rA   rB   
on_connectb  r   zAbstractConnection.on_connectc              	      s  | j |  | j }d }| js| js| jr&| jpt| j| j}| I d H }|r| jdvrt| j t	rC| 
t |j| j _| j |  t|dkrOd|d g}| jd| jdg|R ddiI d H  |  I d H }|d	t| jkr|d
t| jkrtdnq|r| jdg|R ddiI d H  z	|  I d H }W n ty   | jd|d ddI d H  |  I d H }Y nw t|dkrtdn.| jdvrt| j t	r| 
t |j| j _| j |  | jd| j|dI d H  |  I d H }| jr| jdd| j|dI d H  t|  I d H dkrtd| jr%| jddd| j|dI d H  | jr7| jddd| j|dI d H  | jrG| jd| j|dI d H  dd | j| jfD D ]}z
|  I d H  W qR tyi   Y qRw | jr~t|  I d H dkrtdd S d S )N)r   2ru   defaultr   ZHELLOAUTHr   Fs   protoprotozInvalid RESP versionrv   r   OKzInvalid Username or PasswordZCLIENTZSETNAMEzError setting client nameZSETINFOzLIB-NAMEzLIB-VERZSELECTc                 s   s    | ]}|r|V  qd S rI   rA   )r   sentrA   rA   rB   r         z=AbstractConnection.on_connect_check_health.<locals>.<genexpr>zInvalid Database)re   r   rW   rS   rX   r&   Zget_credentials_asyncrb   
isinstancer5   r~   r6   ZEXCEPTION_CLASSESlensend_commandread_responsegetr   r)   r(   r1   r'   rT   rU   rV   rR   r,   )rK   r   parserZ	auth_argsZcred_providerresponseZauth_response_rA   rA   rB   r   f  s   




z*AbstractConnection.on_connect_check_healthnowaitc              	      s   zdt | j4 I dH M | j  | js!	 W d  I dH  W dS z#z| j  |s2| j I dH  W n	 ty<   Y nw W d| _	d| _nd| _	d| _w W d  I dH  W dS 1 I dH s^w   Y  W dS  t
jyv   td| j dw )z!Disconnects from the Redis serverNz#Timed out closing connection after )async_timeoutrZ   re   Zon_disconnectr   rd   r   Zwait_closedr   rc   r{   r-   )rK   r   rA   rA   rB   r     s8   


2
zAbstractConnection.disconnectc                    s8   | j dddI dH  t|  I dH dkrtddS )z Send PING, expect PONG in returnZPINGFr   NZPONGz#Bad response from PING health check)r   r1   r   r)   r   rA   rA   rB   
_send_ping  s
   zAbstractConnection._send_pingc                       |   I dH  dS )z Function to call when PING failsNr   rK   r   rA   rA   rB   _ping_failed     zAbstractConnection._ping_failedc                    s>   | j rt  | jkr| j| j| jI dH  dS dS dS )z3Check the health of the connection with a PING/PONGN)	r^   r{   r   timer_   rr   r   r   r   r   rA   rA   rB   r     s   zAbstractConnection.check_healthcommandc                    s"   | j | | j  I d H  d S rI   )rd   
writelinesdrain)rK   r   rA   rA   rB   _send_packed_command  s   z'AbstractConnection._send_packed_commandc              
      sX  | j s| jddI d H  |r|  I d H  z5t|tr | }t|tr(|g}| jr;t	| 
|| jI d H  W d S | j| | j I d H  W d S  tjya   | jddI d H  tdd  ty } z/| jddI d H  t|jdkrd|jd }}n
|jd }|jd }td	| d
| d|d }~w ty   | jddI d H   w )NFr   Tr   zTimeout writing to socketru   UNKNOWNr   zError z while writing to socket. r   )r   r   r   r   strencodebytesrY   r{   wait_forr   rd   r   r   r-   r   r   r   argsr)   BaseException)rK   r   r   r   Zerr_noerrmsgrA   rA   rB   send_packed_command  sF   




z&AbstractConnection.send_packed_commandr   kwargsc                    s(   | j | j| |dddI dH  dS )z+Pack and send a command to the Redis serverr   Tr   N)r   pack_commandr   )rK   r   r   rA   rA   rB   r   (  s   zAbstractConnection.send_commandc              
      s^   z	| j  I dH W S  ty. } z| jddI dH  |  }td| d|j d}~ww )z8Poll the socket to see if there's data that can be read.NTr   Error while reading from z: )re   can_read_destructiver   r   r   r)   r   )rK   r   
host_errorrA   rA   rB   r   .  s   z'AbstractConnection.can_read_destructive)disconnect_on_errorpush_requestdisable_decodingr!   r   r   c          
   
      s  |dur|n| j }|  }z}|durB| jdv rBt|4 I dH  | jj||dI dH }W d  I dH  n1 I dH s<w   Y  nH|durot|4 I dH  | jj|dI dH }W d  I dH  n1 I dH siw   Y  n| jdv r| jj||dI dH }n
| jj|dI dH }W nT tjy   |durY dS |r| jddI dH  td|  t	y } z|r| jddI dH  t
d| d	|j d}~w ty   |r| jddI dH   w | jrt  | j }	|	| _t|tr|d|S )
z0Read the response from a previously sent commandN)3r   )r   r   )r   Tr   zTimeout reading from r   z : )rY   r   rb   r   re   r   r{   r-   r   r   r)   r   r   r^   r   r   r_   r   r,   )
rK   r   r!   r   r   read_timeoutr   r   r   Z	next_timerA   rA   rB   r   7  s`   	((

z AbstractConnection.read_responsec              	   G   s*  g }t |d trJ t |d tr#t|d   |dd  }nd|d v r7t|d  |dd  }tttt	| t
f}| j}t| jj|D ]>}t	|}t	||ksd||ksdt |tr~t|tt| t
f}|| || t
}qOt|tt| t
|t
f}qO|| |S )z2Pack a series of arguments into the Redis protocolr   ru   N    )r   floatr   tupler   split	SYM_EMPTYr   SYM_STARr   SYM_CRLFrg   mapr`   
memoryview
SYM_DOLLARry   )rK   r   outputZbuffbuffer_cutoffargZ
arg_lengthrA   rA   rB   r   q  s>   "




zAbstractConnection.pack_commandcommandsc           	      C   s   g }g }d}| j }|D ]A}| j| D ]9}t|}||ks%||ks%t|tr3|r/|t| d}g }||ks<t|trB|| q|| ||7 }qq|rW|t| |S )z.Pack multiple commands into the Redis protocolr   )rg   r   r   r   r   ry   r   r   )	rK   r  r  piecesZbuffer_lengthr  cmdchunkZchunklenrA   rA   rB   pack_commands  s.   

z AbstractConnection.pack_commandsc                 C   s   t | jjdkS )zCheck if the socket is emptyr   )r   rc   _bufferr   rA   rA   rB   _socket_is_empty  s   z#AbstractConnection._socket_is_emptyc                    s,   |   s| jddI d H  |   rd S d S )NT)r   )r  r   r   rA   rA   rB   process_invalidation_messages  s   z0AbstractConnection.process_invalidation_messagestokenc                 C   s
   || _ d S rI   )r   rK   r  rA   rA   rB   set_re_auth_token  s   
z$AbstractConnection.set_re_auth_tokenc                    sJ   | j d ur#| d| j d| j  I d H  |  I d H  d | _ d S d S Nr   oid)r   r   try_get	get_valuer   r   rA   rA   rB   re_auth  s   



zAbstractConnection.re_authTr   N)F)FN)Ar<   r=   r>   __doc__	__slots__rx   rC   r0   r3   r   r   r   r
   r   boollistr;   r   r2   r"   ConnectCallbackTr%   r   r   warningsr   r   r   r   r   r   propertyr   r   r   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r.   r   r   r	  r  r  r   r  r  rA   rA   rA   rB   rG   j   s     

	

Y

*

l
)
:.rG   c                       s   e Zd ZdZddddddded	eeef d
edee	eeee
f f  def
 fddZdd Zde	fddZdd ZdefddZ  ZS )
Connectionz4Manages TCP communication to and from a Redis server	localhosti  FNr   )hostportsocket_keepalivesocket_keepalive_optionssocket_typer   r!  r"  r#  r$  c                   s<   || _ t|| _|| _|pi | _|| _t jdi | d S NrA   )r   r   r!  r"  r#  r$  superr   )rK   r   r!  r"  r#  r$  r   r   rA   rB   r     s   


zConnection.__init__c                 C   s6   d| j fd| jfd| jfg}| jr|d| jf |S )Nr   r!  rR   rT   )r   r!  rR   rT   ry   rK   r  rA   rA   rB   r     s   zConnection.repr_piecesr   c                 C   s   | j | jdS )Nr   r!  r)  r   rA   rA   rB   _connection_arguments  r   z Connection._connection_argumentsc              	      s   t | j4 I dH  tjdi |  I dH \}}W d  I dH  n1 I dH s*w   Y  || _|| _|jd}|ry|	t
jt
jd z$| jre|	t
jt
jd | j D ]\}}|	t
j|| qXW dS W dS  ttfyx   |   w dS )zCreate a TCP socket connectionNrz   ru   rA   )r   rZ   r{   Zopen_connectionr*  rc   rd   	transportZget_extra_info
setsockoptrz   IPPROTO_TCPTCP_NODELAYr"  
SOL_SOCKETSO_KEEPALIVEr#  itemsSOL_TCPr   r   r   )rK   readerwritersockr   r   rA   rA   rB   r     s.   (zConnection._connectc                 C   s   | j  d| j S )N:r)  r   rA   rA   rB   r     s   zConnection._host_error)r<   r=   r>   r  r   r   r   r  r
   r	   r   r   r   r*  r   r   __classcell__rA   rA   r'  rB   r    s,    
r  c                       s   e Zd ZdZ								d dee dee deeejf dee d	ee d
e	dee
 dee f fddZdef fddZedd Zedd Zedd Zedd Zedd Zedd Zedd Z  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)
    NrequiredTssl_keyfilessl_certfilessl_cert_reqsssl_ca_certsssl_ca_datassl_check_hostnamessl_min_versionssl_ciphersc	           
   
      s<   t stdt||||||||d| _t jdi |	 d S )N$Python wasn't built with SSL support)keyfilecertfile	cert_reqsca_certsca_datacheck_hostnamemin_versionciphersrA   )r   r+   RedisSSLContextra   r&  r   )
rK   r:  r;  r<  r=  r>  r?  r@  rA  r   r'  rA   rB   r     s   
zSSLConnection.__init__r   c                    s   t   }| j |d< |S )Nssl)r&  r*  ra   r   rK   r   r'  rA   rB   r*  -  s   
z#SSLConnection._connection_argumentsc                 C      | j jS rI   )ra   rC  r   rA   rA   rB   rC  2     zSSLConnection.keyfilec                 C   rN  rI   )ra   rD  r   rA   rA   rB   rD  6  rO  zSSLConnection.certfilec                 C   rN  rI   )ra   rE  r   rA   rA   rB   rE  :  rO  zSSLConnection.cert_reqsc                 C   rN  rI   )ra   rF  r   rA   rA   rB   rF  >  rO  zSSLConnection.ca_certsc                 C   rN  rI   )ra   rG  r   rA   rA   rB   rG  B  rO  zSSLConnection.ca_datac                 C   rN  rI   )ra   rH  r   rA   rA   rB   rH  F  rO  zSSLConnection.check_hostnamec                 C   rN  rI   )ra   rI  r   rA   rA   rB   rI  J  rO  zSSLConnection.min_version)NNr9  NNTNN)r<   r=   r>   r  r
   r   r   rL  
VerifyModer  r   r   r	   r*  r  rC  rD  rE  rF  rG  rH  rI  r7  rA   rA   r'  rB   r8    sT    	





r8  c                   @   s   e Zd ZdZ								ddee dee deeeejf  dee dee d	e	d
ee
 dee fddZdefddZdS )rK  )	rC  rD  rE  rF  rG  contextrH  rI  rJ  NFrC  rD  rE  rF  rG  rH  rI  rJ  c	           
      C   s   t std|| _|| _|d u rtj}nt|tr1tjtjtj	d}	||	vr-td| |	| }|| _
|| _|| _| j
tjkrB|nd| _|| _|| _d | _d S )NrB  )noneoptionalr9  z+Invalid SSL Certificate Requirements Flag: F)r   r+   rC  rD  rL  	CERT_NONEr   r   CERT_OPTIONALCERT_REQUIREDrE  rF  rG  rH  rI  rJ  rQ  )
rK   rC  rD  rE  rF  rG  rH  rI  rJ  Z	CERT_REQSrA   rA   rB   r   \  s0   

zRedisSSLContext.__init__r   c                 C   s   | j sDt }| j|_| j|_| jr| jr|j| j| jd | j	s$| j
r-|j| j	| j
d | jd ur6| j|_| jd urA|| j || _ | j S )N)rD  rC  )cafilecadata)rQ  rL  create_default_contextrH  rE  verify_moderD  rC  load_cert_chainrF  rG  load_verify_locationsrI  minimum_versionrJ  set_ciphers)rK   rQ  rA   rA   rB   r     s   

zRedisSSLContext.get)NNNNNFNN)r<   r=   r>   r  r
   r   r   rL  rP  r  r   r   r   r   rA   rA   rA   rB   rK  O  s8    	
'rK  c                       sd   e Zd ZdZdddef fddZdeeeeee	f f  fdd	Z
d
d ZdefddZ  ZS )UnixDomainSocketConnectionz4Manages UDS communication to and from a Redis server pathrb  c                   s   || _ t jdi | d S r%  )rb  r&  r   )rK   rb  r   r'  rA   rB   r     s   z#UnixDomainSocketConnection.__init__r   c                 C   s.   d| j fd| jfg}| jr|d| jf |S )Nrb  rR   rT   )rb  rR   rT   ry   r(  rA   rA   rB   r     s   z&UnixDomainSocketConnection.repr_piecesc              	      sv   t | j4 I d H  tj| jdI d H \}}W d   I d H  n1 I d H s'w   Y  || _|| _|  I d H  d S )Nra  )r   rZ   r{   Zopen_unix_connectionrb  rc   rd   r   )rK   r3  r4  rA   rA   rB   r     s   (z#UnixDomainSocketConnection._connectc                 C   r   rI   ra  r   rA   rA   rB   r     r   z&UnixDomainSocketConnection._host_error)r<   r=   r>   r  r   r   r   r   r   r   r   r   r   r7  rA   rA   r'  rB   r_    s    "r_  )0FFALSENNOr   c                 C   s6   | d u s| dkr
d S t | tr|  tv rdS t| S )Nr`  F)r   r   upperFALSE_STRINGSr  )valuerA   rA   rB   to_bool  s
   rk  )	rR   rY   rZ   r"  r\   max_connectionsr^   r?  r!   .URL_QUERY_ARGUMENT_PARSERSc                   @   sJ   e Zd ZU eed< eed< ee ed< eed< eed< eed< eed< dS )	ConnectKwargsrS   rX   connection_classr   r!  rR   rb  N)r<   r=   r>   r   __annotations__r   rG   r   rA   rA   rA   rB   rn    s   
 rn  F)totalurlc              
   C   s|  t | }i }t|j D ]7\}}|rDt|dkrDt|d }t|}|r@z||||< W q tt	fy?   t	d| dw |||< q|j
rOt|j
|d< |jrYt|j|d< |jdkrn|jrht|j|d< t|d< |S |jd	v r|jr}t|j|d
< |jrt|j|d< |jrd|vrztt|jdd|d< W n tt	fy   Y nw |jdkrt|d< |S d}t	d| d)Nr   zInvalid value for 'z' in connection URL.rS   rX   unixrb  ro  )Zredisredissr   r!  rR   /r`  rt  zredis://, rediss://, unix://z5Redis URL must specify one of the following schemes ())r   r   queryr1  r   r   rm  r   r   r   rS   rX   schemerb  r_  hostnamer!  r   replaceAttributeErrorr8  )rr  parsedr   nameZ
value_listrj  r   Zvalid_schemesrA   rA   rB   	parse_url  sR   




r~  _CPConnectionPool)boundc                   @   s   e Zd ZdZedee dedefddZe	dfdee
 d	ee fd
dZdd Zdd ZdefddZedgdddd3ddZdd Zdd Zdd Zde
fdd Zde
fd!d"Zd4d$efd%d&Zd5d'd(Zd6d+d,Zd-efd.d/Zd0efd1d2ZdS )7r  a  
    Create a connection pool. ``If max_connections`` is set, then this
    object raises :py:class:`~redis.ConnectionError` when the pool's
    limit is reached.

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

    Any additional keyword arguments are passed to the constructor of
    ``connection_class``.
    clsrr  r   c                 K   s    t |}|| | 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.
        NrA   )r~  update)r  rr  r   Zurl_optionsrA   rA   rB   from_url  s   +
zConnectionPool.from_urlNro  rl  c                 K   s   |pd}t |tr|dk rtd|| _|| _|| _g | _t | _| j	dt
| _t | _| j	dd | _| jd u rAt | _d S d S )Nl        r   z,"max_connections" must be a positive integerrs   rt   )r   r   r   ro  connection_kwargsrl  _available_connectionsset_in_use_connectionsr   r3   rs   r{   Lockrh   rw   r   )rK   ro  rl  r  rA   rA   rB   r   D  s   

zConnectionPool.__init__c              	   C   s.   d| j j d| j j d| jdi | jdS )Nr   r   r   r   rA   )r   r=   r<   ro  r  r   rA   rA   rB   r   Z  s   zConnectionPool.__repr__c                 C   s   g | _ t | _d S rI   )r  r   WeakSetr  r   rA   rA   rB   reset`  s   zConnectionPool.resetc                 C   s   | j p
t| j| jk S )z;Return True if a connection can be retrieved from the pool.)r  r   r  rl  r   rA   rA   rB   can_get_connectiond  s   z!ConnectionPool.can_get_connection*)Use get_connection() without args instead5.3.0Zargs_to_warnreasonversionc              	      s   | j 4 I d H , 	 |  }z
| |I d H  W n ty(   | |I d H   w W d   I d H  |S 1 I d H s:w   Y  |S rI   )rh   get_available_connectionensure_connectionr   release)rK   command_namekeysoptionsrF   rA   rA   rB   get_connectionk  s   		zConnectionPool.get_connectionc                 C   sT   z| j  }W n ty!   t| j| jkrtdd|  }Y nw | j| |S )zCGet a connection from the pool, without making sure it is connectedzToo many connectionsN)	r  pop
IndexErrorr   r  rl  r)   make_connectionaddrJ   rA   rA   rB   r  |  s   
z'ConnectionPool.get_available_connectionc                 C   s.   | j }| j|dd|dd|dddS )z,Return an encoder based on encoding settingsrm   rk   rn   rl   ro   F)rm   rn   ro   )r  rs   r   rM  rA   rA   rB   get_encoder  s   


zConnectionPool.get_encoderc                 C   s   | j di | jS )z=Create a new connection.  Can be overridden by child classes.NrA   )ro  r  r   rA   rA   rB   r    s   zConnectionPool.make_connectionrF   c              
      s~   |  I dH  z| I dH rtddW dS  tttfy>   | I dH  |  I dH  | I dH r;tddY dS w )z8Ensure that the connection object is connected and validNzConnection has datazConnection not ready)r   r   r)   r-   r   r   rJ   rA   rA   rB   r    s   

z ConnectionPool.ensure_connectionc                    s4   | j | | j| | jt|I dH  dS )z(Releases the connection back to the poolN)r  r   r  ry   rw   Zdispatch_asyncr   rJ   rA   rA   rB   r    s   zConnectionPool.releaseTinuse_connectionsc                    s\   |rt | j| j}n| j}tjdd |D ddiI dH }tdd |D d}|r,|dS )z
        Disconnects connections in the pool

        If ``inuse_connections`` is True, disconnect connections that are
        current in use, potentially by other tasks. Otherwise only disconnect
        connections that are idle in the pool.
        c                 s   s    | ]}|  V  qd S rI   r   )r   rF   rA   rA   rB   r     r   z,ConnectionPool.disconnect.<locals>.<genexpr>Zreturn_exceptionsTNc                 s   s    | ]
}t |tr|V  qd S rI   )r   r   )r   rrA   rA   rB   r     s    )r   r  r  r{   Zgathernext)rK   r  connectionsrespr   rA   rA   rB   r     s   zConnectionPool.disconnectc                    r   )z-Close the pool, disconnecting all connectionsNr   r   rA   rA   rB   aclose  r   zConnectionPool.acloserr   r"   c                 C   s(   | j D ]}||_q| jD ]}||_qd S rI   )r  rr   r  )rK   rr   connrA   rA   rB   	set_retry  s
   

zConnectionPool.set_retryr  c              	      s   j 4 I d H B jD ]'  j fddfddI d H   j fddfddI d H  qjD ]   q7W d   I d H  d S 1 I d H sPw   Y  d S )Nc                      s     dd S r  )r   r  r  rA   )r  r  rA   rB   r     s    z1ConnectionPool.re_auth_callback.<locals>.<lambda>c                    
     | S rI   _mockr   r   rA   rB   r        
 c                      r   rI   )r   rA   )r  rA   rB   r     r   c                    r  rI   r  r   r   rA   rB   r     r  )rh   r  rr   r   r  r  r  rA   )r  rK   r  rB   re_auth_callback  s   



.zConnectionPool.re_auth_callbackr   c                    s   dS )z
        Dummy functions, needs to be passed as error callback to retry object.
        :param error:
        :return:
        NrA   r   rA   rA   rB   r    s   zConnectionPool._mockrI   r  r  )rr   r"   r   N) r<   r=   r>   r  classmethodr   r  r   r  r  rG   r
   r   r   r   r  r  r  r   r  r  r  r  r  r  r   r  r  r   r  r+   r  rA   rA   rA   rB   r    s<    0
	


c                
       s|   e Zd ZdZddeejfdedee de	e
 de	ej f fdd	Zed
gdddd fdd	Zde
f fddZ  ZS )BlockingConnectionPoola  
    A blocking connection pool::

        >>> from redis.asyncio import Redis, BlockingConnectionPool
        >>> client = Redis.from_pool(BlockingConnectionPool())

    It performs the same function as the default
    :py:class:`~redis.asyncio.ConnectionPool` implementation, in that,
    it maintains a pool of reusable connections that can be shared by
    multiple async redis clients.

    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.asyncio.ConnectionPool` implementation does), it
    blocks the current `Task` 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      rl  r!   ro  queue_classc                    s,   t  jd||d| t | _|| _d S )N)ro  rl  rA   )r&  r   r{   	Condition
_conditionr!   )rK   rl  r!   ro  r  r  r'  rA   rB   r     s   

zBlockingConnectionPool.__init__r  r  r  r  Nc              
      s   zM| j 4 I dH 9 t| j4 I dH  | j | jI dH  t  }W d  I dH  n1 I dH s3w   Y  W d  I dH  n1 I dH sHw   Y  W n tjy` } zt	d|d}~ww z| 
|I dH  |W S  ty|   | |I dH   w )z@Gets a connection from the pool, blocking until one is availableNzNo connection available.)r  r   r!   r   r  r&  r  r{   r-   r)   r  r   r  )rK   r  r  r  rF   errr'  rA   rB   r    s(   *(
z%BlockingConnectionPool.get_connectionrF   c              	      s^   | j 4 I dH  t |I dH  | j   W d  I dH  dS 1 I dH s(w   Y  dS )z)Releases the connection back to the pool.N)r  r&  r  notifyrJ   r'  rA   rB   r  /  s
   .zBlockingConnectionPool.releaserI   )r<   r=   r>   r  r  r{   	LifoQueuer   r
   r   rG   Queuer   r   r  r  r7  rA   rA   r'  rB   r    s,    #r  )mr{   r|   enumr   rz   sysr  r   abcr   	itertoolsr   typesr   typingr   r   r   r   r	   r
   r   r   r   r   r   r   r   urllib.parser   r   r   r   utilsr   rL  r   r   Z
auth.tokenr   eventr   r   r   r   version_infor!   r   Zredis.asyncio.retryr"   Zredis.backoffr#   Zredis.connectionr$   Zredis.credentialsr%   r&   Zredis.exceptionsr'   r(   r)   r*   r+   r,   r-   Zredis.typingr.   Zredis.utilsr/   r0   r1   _parsersr2   r3   r4   r5   r6   r   r  r   ZSYM_LFr   Enumr;   r@   rx   rp  rC   rE   rP   r  rG   r  r8  rK  r_  ri  r  rk  r   r   rm  r   r?   rn  r~  r  r  r  rA   rA   rA   rB   <module>   s   
 <
$	    m9CE
4 `