U
    h0                     @   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"rd 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r6d 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`eea d.d/d0Zbeecededebebececebedd1	Zeeefed2egf f eVd3< G d4d5 d5ed6d7Zhefehd8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   </tmp/pip-unpacked-wheel-4avdqdik/redis/asyncio/connection.pyr;   Q   s   r;   DefaultParserc                   @   s   e Zd ZddddZdS )ConnectCallbackProtocolAbstractConnection
connectionc                 C   s   d S NrA   selfrG   rA   rA   rB   __call__`   r:   z ConnectCallbackProtocol.__call__Nr<   r=   r>   rK   rA   rA   rA   rB   rD   _   s   rD   c                   @   s   e Zd ZddddZdS )AsyncConnectCallbackProtocolrE   rF   c                    s   d S rH   rA   rI   rA   rA   rB   rK   d   r:   z%AsyncConnectCallbackProtocol.__call__NrL   rA   rA   rA   rB   rM   c   s   rM   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e	e
ef ee
 ee ee ee	eef e
e
eee eeee
 ee
 ee
 ee
 ee ee ee ee ee ee dddZefedddZdd Zdd Zedd Zedd Z dd Z!dd Z"ee ddddZ#d d! Z$d\ed#d$d%Z%ed&d' Z&ee
d(d)d*Z'e(e
d+d,d-Z)d.d/ Z*dd(d0d1Z+d]edd2d3d4Z,d^edd5d6d7Z-d8d9 Z.d:d; Z/d<d= Z0e1e2 dd>d?d@Z3d_e	e2e
e1e2 f eddAdBdCZ4eeddDdEdFZ5dGdH Z6d`d"ddIeee eee dJdKdLZ7e8e9e2 dMdNdOZ:e1e1e8  e9e2 dPdQdRZ;dSdT Z<dUdV Z=e>dWdXdYZ?dZd[ Z@dS )arE   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   )rN   rT   rU   rV   rX   rY   encodingencoding_errorsdecode_responsesparser_classsocket_read_sizerZ   rP   rQ   rR   rO   retryrW   encoder_classrS   r^   event_dispatcherc                C   s  |s|r|d k	rt d|d kr*t | _n|| _|| _|| _|| _|| _|| _|| _|| _	|| _
|d krl|}|| _|| _|tkrg }|r|t |tj |tj || _|s|r|stt d| _nt|| _| j| ntt d| _|| _d| _||||	| _|| _d | _d | _|| _ | !|
 g | _"d| _#d | _$zHzt'|}W n6 t(k
rj   t)}Y n t*k
r   t%d	Y nX W 5 |dk s|dkrt%d|| _&X d S )
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  r   r   zprotocol must be either 2 or 3zprotocol must be an integer)+r*   r   _event_dispatcherrN   rP   rQ   rR   rS   rT   rO   rU   rV   rX   SENTINELappendr-   socketr!   asynciorY   r"   r#   rn   copydeepcopyZupdate_supported_errorsrZ   r[   r\   rW   r_   r`   re   
set_parserrb   rc   _re_auth_tokenr)   r^   int	TypeErrorr$   
ValueError)rJ   rN   rT   rU   rV   rX   rY   ri   rj   rk   rl   rm   rZ   rP   rQ   rR   rO   rn   rW   ro   rS   r^   rp   prA   rA   rB   __init__   sh    


zAbstractConnection.__init__)	_warningsc                 C   sP   t | dd rL|jd| t| d zt  |   W n tk
rJ   Y nX d S )Nr`   zunclosed Connection )source)getattrwarnResourceWarningrw   get_running_loop_closeRuntimeError)rJ   r   rA   rA   rB   __del__   s      zAbstractConnection.__del__c                 C   s    | j r| j   d | _ | _dS )zR
        Internal method to silently close the connection without waiting
        N)r`   closer_   rJ   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<   )rJ   Z	repr_argsrA   rA   rB   __repr__   s    zAbstractConnection.__repr__c                 C   s   d S rH   rA   r   rA   rA   rB   r      s    zAbstractConnection.repr_piecesc                 C   s   | j d k	o| jd k	S rH   )r_   r`   r   rA   rA   rB   is_connected  s    zAbstractConnection.is_connectedc                 C   s$   t |}|| jkr | j| 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
WeakMethodrb   ru   )rJ   callbackZwmrA   rA   rB   register_connect_callback  s    

z,AbstractConnection.register_connect_callbackc                 C   s0   z| j t| W n tk
r*   Y nX dS )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)rb   remover   r   r~   )rJ   r   rA   rA   rB   deregister_connect_callback  s    z.AbstractConnection.deregister_connect_callback)rl   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
        )rm   N)re   ra   )rJ   rl   rA   rA   rB   rz     s    zAbstractConnection.set_parserc                    s   | 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&  s    zAbstractConnection.connectTr   c              
      s   j r
d S z( j fdd fddI d H  W n tjk
rJ    Y n| tjtjfk
rl   tdY nZ tk
r } zt	 
|W 5 d }~X Y n, tk
r } zt	||W 5 d }~X Y nX zD js j|dI d H  n&t jr  I d H n   W n& tk
r0     I d H   Y nX dd  jD  _ jD ]0}| }| }|rJt|rJ|I d H  qJd S )Nc                      s      S rH   )_connectrA   r   rA   rB   <lambda>/  r:   z9AbstractConnection.connect_check_health.<locals>.<lambda>c                    s      S rH   
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   rn   call_with_retryrw   ZCancelledErrorrv   r!   r-   OSErrorr)   _error_message	ExceptionrW   on_connect_check_healthiscoroutinefunctionr+   r   rb   inspectisawaitable)rJ   r   eexcr   r   ZtaskrA   r   rB   r   *  s>    
 


z'AbstractConnection.connect_check_healthc                    s   d S rH   rA   r   rA   rA   rB   r   T  s    zAbstractConnection._connectr   c                 C   s   d S rH   rA   r   rA   rA   rB   _host_errorX  s    zAbstractConnection._host_error)	exceptionr   c                 C   s   t |  |S rH   )r   r   )rJ   r   rA   rA   rB   r   \  s    z!AbstractConnection._error_messagec                 C   s   | j S rH   )r^   r   rA   rA   rB   get_protocol_  s    zAbstractConnection.get_protocolc                    s   | j ddI dH  dS )z=Initialize the connection, authenticate and select a databaseTr   N)r   r   rA   rA   rB   
on_connectb  s    zAbstractConnection.on_connect)r   r   c              	      s  | j |  | j }d }| js(| js(| jrJ| jp:t| j| j}| I d H }|r| jdkrt| j t	r| 
t |j| j _| j |  t|dkrd|d g}| jd| jdf|ddiI d H  |  I d H }|d	t| jkr|d
t| jkrtdn|r| jd|ddiI d H  z|  I d H }W n> tk
rn   | jd|d ddI d H  |  I d H }Y nX t|dkrtdn`| jdk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rN| jddd| j|dI d H  | jrr| jddd| j|dI d H  | jr| jd| j|dI d H  dd | j| jfD D ]0}z|  I d H  W n tk
r   Y nX q| jrt|  I d H dkrtdd S )N)r   2rq   defaultr   ZHELLOAUTHr   Fs   protoprotozInvalid RESP versionrr   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 rH   rA   )r   sentrA   rA   rB   r     s      z=AbstractConnection.on_connect_check_health.<locals>.<genexpr>zInvalid Database)r   )ra   r   rS   rO   rT   r&   Zget_credentials_asyncr^   
isinstancer5   rz   r6   ZEXCEPTION_CLASSESlensend_commandread_responsegetr|   r)   r(   r1   r'   rP   rQ   rR   rN   r,   )rJ   r   parserZ	auth_argsZcred_providerresponseZauth_response_rA   rA   rB   r   f  s    

  




z*AbstractConnection.on_connect_check_health)nowaitr   c              
      s   zt | j4 I dH x | j  | js<W 5 Q I dH R  W dS z<z"| j  |s^| j I dH  W n t	k
rt   Y nX W 5 d| _d| _X W 5 Q I dH R X W n( t
jk
r   td| j dY nX dS )z!Disconnects from the Redis serverNz#Timed out closing connection after )async_timeoutrV   ra   Zon_disconnectr   r_   r`   r   Zwait_closedr   rw   r-   )rJ   r   rA   rA   rB   r     s&    



zAbstractConnection.disconnectc                    s6   | j dddI dH  t|  I dH dkr2t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                    s   |   I dH  dS )z Function to call when PING failsNr   rJ   r   rA   rA   rB   _ping_failed  s    zAbstractConnection._ping_failedc                    s4   | j r0t  | jkr0| j| j| jI dH  dS )z3Check the health of the connection with a PING/PONGN)	rZ   rw   r   timer[   rn   r   r   r   r   rA   rA   rB   r     s
    zAbstractConnection.check_health)commandr   c                    s    | j | | j  I d H  d S rH   )r`   
writelinesdrain)rJ   r   rA   rA   rB   _send_packed_command  s    z'AbstractConnection._send_packed_command)r   r   r   c              
      sp  | j s| jddI d H  |r*|  I d H  zdt|tr>| }t|trN|g}| jrpt	| 
|| jI d H  n| j| | j I d H  W n tjk
r   | jddI d H  tdd Y n tk
rB } zd| jddI d H  t|jdkrd|jd  }}n|jd }|jd }td	| d
| d|W 5 d }~X Y n* tk
rj   | jddI d H   Y nX d S )NFr   Tr   zTimeout writing to socketrq   UNKNOWNr   zError z while writing to socket. r   )r   r   r   r   strencodebytesrU   rw   wait_forr   r`   r   r   r-   r   r   r   argsr)   BaseException)rJ   r   r   r   Zerr_noerrmsgrA   rA   rB   send_packed_command  sB    

 

z&AbstractConnection.send_packed_command)r   kwargsr   c                    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   )rJ   r   r   rA   rA   rB   r   (  s     
zAbstractConnection.send_commandc              
      sj   z| j  I dH W S  tk
rd } z4| jddI dH  |  }td| d|j W 5 d}~X Y nX dS )z8Poll the socket to see if there's data that can be read.NTr   Error while reading from z: )ra   can_read_destructiver   r   r   r)   r   )rJ   r   
host_errorrA   rA   rB   r   .  s    z'AbstractConnection.can_read_destructive)disconnect_on_errorpush_request)disable_decodingr!   r   r   c          
   
      s  |dk	r|n| j }|  }z|dk	rl| jdkrltslt|4 I dH  | jj||dI dH }W 5 Q I dH R X nz|dk	rt|4 I dH  | jj|dI dH }W 5 Q I dH R X n:| jdkrts| jj||dI dH }n| jj|dI dH }W n tjk
r6   |dk	rY dS |r$| j	ddI dH  td| Y n t
k
r } z2|r`| j	ddI dH  td| d	|j W 5 d}~X Y n0 tk
r   |r| j	ddI dH   Y nX | 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 : )rU   r   r^   r/   r   ra   r   rw   r-   r   r   r)   r   r   rZ   r   r   r[   r   r,   )
rJ   r   r!   r   r   read_timeoutr   r   r   Z	next_timerA   rA   rB   r   7  s^    	  
&z AbstractConnection.read_response)r   r   c              	   G   s*  g }t |d trtt |d trFt|d   |dd  }n(d|d krnt|d  |dd  }tt	tt
| tf}| j}t| jj|D ]|}t
|}t
||ks||kst |trt|tt| tf}|| || t}qt|tt| t|tf}q|| |S )z2Pack a series of arguments into the Redis protocolr   rq   N    )r   floatAssertionErrorr   tupler   split	SYM_EMPTYr   SYM_STARr   SYM_CRLFrc   mapr\   
memoryview
SYM_DOLLARru   )rJ   r   outputZbuffbuffer_cutoffargZ
arg_lengthrA   rA   rB   r   u  sB    "





zAbstractConnection.pack_command)commandsr   c           	      C   s   g }g }d}| j }|D ]}| j| D ]r}t|}||ksJ||ksJt|trf|r^|t| d}g }||ksxt|tr|| q$|| ||7 }q$q|r|t| |S )z.Pack multiple commands into the Redis protocolr   )rc   r   r   r   r   ru   r   r   )	rJ   r   r   piecesZbuffer_lengthr   cmdchunkZchunklenrA   rA   rB   pack_commands  s0    
z AbstractConnection.pack_commandsc                 C   s   t | jjdkS )zCheck if the socket is emptyr   )r   r_   _bufferr   rA   rA   rB   _socket_is_empty  s    z#AbstractConnection._socket_is_emptyc                    s    |   s| jddI d H  q d S )NT)r   )r   r   r   rA   rA   rB   process_invalidation_messages  s    z0AbstractConnection.process_invalidation_messagestokenc                 C   s
   || _ d S rH   )r{   rJ   r   rA   rA   rB   set_re_auth_token  s    z$AbstractConnection.set_re_auth_tokenc                    sD   | j d k	r@| d| j d| j  I d H  |  I d H  d | _ d S Nr   oid)r{   r   try_get	get_valuer   r   rA   rA   rB   re_auth  s    


zAbstractConnection.re_auth)T)T)F)T)FN)Ar<   r=   r>   __doc__	__slots__rt   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   rz   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   rE   j   s    

Y

*
l  )  >.rE   c                
       s   e Zd ZdZddddddeeeef eee	eeee
f f  ed fdd	Zd
d Ze	dddZdd ZedddZ  ZS )
Connectionz4Manages TCP communication to and from a Redis server	localhosti  FNr   )hostportsocket_keepalivesocket_keepalive_optionssocket_typec                   s8   || _ t|| _|| _|pi | _|| _t jf | d S rH   )r  r|   r  r  r  r  superr   )rJ   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r2|d| jf |S )Nr  r  rN   rP   )r  r  rN   rP   ru   rJ   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  s    z Connection._connection_argumentsc              
      s   t | j4 I dH   tjf |  I dH \}}W 5 Q I dH R X || _|| _|jd}|r|	t
jt
jd z@| jr|	t
jt
jd | j D ]\}}|	t
j|| qW n" ttfk
r   |   Y nX dS )zCreate a TCP socket connectionNrv   rq   )r   rV   rw   Zopen_connectionr  r_   r`   	transportZget_extra_info
setsockoptrv   IPPROTO_TCPTCP_NODELAYr  
SOL_SOCKETSO_KEEPALIVEr  itemsSOL_TCPr   r}   r   )rJ   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ee ee eeejf ee ee e	ee
 ee d fddZed 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	           
   
      s8   t stdt||||||||d| _t jf |	 d S )N$Python wasn't built with SSL supportkeyfilecertfile	cert_reqsca_certsca_datacheck_hostnamemin_versionciphers)r   r+   RedisSSLContextr]   r  r   )
rJ   r*  r+  r,  r-  r.  r/  r0  r1  r   r  rA   rB   r     s    
zSSLConnection.__init__r   c                    s   t   }| j |d< |S )Nssl)r  r  r]   r   rJ   r   r  rA   rB   r  1  s    
z#SSLConnection._connection_argumentsc                 C   s   | j jS rH   )r]   r4  r   rA   rA   rB   r4  6  s    zSSLConnection.keyfilec                 C   s   | j jS rH   )r]   r5  r   rA   rA   rB   r5  :  s    zSSLConnection.certfilec                 C   s   | j jS rH   )r]   r6  r   rA   rA   rB   r6  >  s    zSSLConnection.cert_reqsc                 C   s   | j jS rH   )r]   r7  r   rA   rA   rB   r7  B  s    zSSLConnection.ca_certsc                 C   s   | j jS rH   )r]   r8  r   rA   rA   rB   r8  F  s    zSSLConnection.ca_datac                 C   s   | j jS rH   )r]   r9  r   rA   rA   rB   r9  J  s    zSSLConnection.check_hostnamec                 C   s   | j jS rH   )r]   r:  r   rA   rA   rB   r:  N  s    zSSLConnection.min_version)NNr)  NNTNN)r<   r=   r>   r  r
   r   r   r=  
VerifyModer
  r   r   r	   r  r  r4  r5  r6  r7  r8  r9  r:  r'  rA   rA   r  rB   r(    sD           





r(  c                
   @   sb   e Zd ZdZd
ee ee eeeejf  ee ee e	ee
 ee dddZeddd	ZdS )r<  )	r4  r5  r6  r7  r8  contextr9  r:  r;  NFr3  c	           
      C   s   t std|| _|| _|d kr(tj}n:t|trbtjtjtj	d}	||	krZtd| |	| }|| _
|| _|| _| j
tjkr|nd| _|| _|| _d | _d S )Nr2  )noneoptionalr)  z+Invalid SSL Certificate Requirements Flag: F)r   r+   r4  r5  r=  	CERT_NONEr   r   CERT_OPTIONALCERT_REQUIREDr6  r7  r8  r9  r:  r;  r@  )
rJ   r4  r5  r6  r7  r8  r9  r:  r;  Z	CERT_REQSrA   rA   rB   r   `  s0    
zRedisSSLContext.__init__r   c                 C   s   | j st }| j|_| j|_| jr<| jr<|j| j| jd | j	sH| j
rZ|j| j	| j
d | jd k	rl| j|_| jd k	r|| j || _ | j S )N)r5  r4  )cafilecadata)r@  r=  create_default_contextr9  r6  verify_moder5  r4  load_cert_chainr7  r8  load_verify_locationsr:  minimum_versionr;  set_ciphers)rJ   r@  rA   rA   rB   r     s    

zRedisSSLContext.get)NNNNNFNN)r<   r=   r>   r	  r
   r   r   r=  r?  r
  r   r   r   r   rA   rA   rA   rB   r<  S  s(           'r<  c                       sd   e Zd ZdZdded fddZeeeeee	f f  dddZ
d	d
 ZedddZ  ZS )UnixDomainSocketConnectionz4Manages UDS communication to and from a Redis server pathc                   s   || _ t jf | d S rH   )rQ  r  r   )rJ   rQ  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 )NrQ  rN   rP   )rQ  rN   rP   ru   r  rA   rA   rB   r     s    z&UnixDomainSocketConnection.repr_piecesc              
      sZ   t | j4 I d H  tj| jdI d H \}}W 5 Q I d H R X || _|| _|  I d H  d S )NrP  )r   rV   rw   Zopen_unix_connectionrQ  r_   r`   r   )rJ   r#  r$  rA   rA   rB   r     s
    (z#UnixDomainSocketConnection._connectc                 C   s   | j S rH   rP  r   rA   rA   rB   r     s    z&UnixDomainSocketConnection._host_error)r<   r=   r>   r  r   r   r   r   r   r|   r   r   r   r'  rA   rA   r  rB   rN    s
   "rN  )0FFALSENNOr   c                 C   s6   | d ks| dkrd S t | tr.|  tkr.dS t| S )NrO  F)r   r   upperFALSE_STRINGSr
  )valuerA   rA   rB   to_bool  s
    rZ  )	rN   rU   rV   r  rX   max_connectionsrZ   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 )	ConnectKwargsrO   rT   connection_classr  r  rN   rQ  N)r<   r=   r>   r   __annotations__r   rE   r|   rA   rA   rA   rB   r]    s   
r]  F)total)urlr   c              
   C   s  t | }i }t|j D ]v\}}|rt|dkrt|d }t|}|rz||||< W q tt	fk
r   t	d| dY qX q|||< q|j
rt|j
|d< |jrt|j|d< |jdkr|jrt|j|d< t|d< n|jd	kr||jrt|j|d
< |jrt|j|d< |jrfd|krfztt|jdd|d< W n tt	fk
rd   Y nX |jdkrt|d< nd}t	d| d|S )Nr   zInvalid value for 'z' in connection URL.rO   rT   unixrQ  r^  )Zredisredissr  r  rN   /rO  rc  zredis://, rediss://, unix://z5Redis URL must specify one of the following schemes ())r   r   queryr!  r   r   r\  r   r}   r~   rO   rT   schemerQ  rN  hostnamer  r|   replaceAttributeErrorr(  )ra  parsedr   nameZ
value_listrY  r   Zvalid_schemesrA   rA   rB   	parse_url  sJ    





rm  _CPConnectionPool)boundc                   @   s   e Zd ZdZeee eedddZe	dfee
 ee dddZd	d
 Zdd ZedddZedgdddd1ddZdd Zdd Zdd Ze
dddZe
ddd Zd2ed"d#d$Zddd%d&Zd'dd(d)d*Zed+d,d-Zed.d/d0ZdS )3ro  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``.
    )clsra  r   c                 K   s   t |}|| | f |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.
        )rm  update)rq  ra  r   Zurl_optionsrA   rA   rB   from_url  s    +
zConnectionPool.from_urlNr^  r[  c                 K   s   |pd}t |tr|dk r"td|| _|| _|| _g | _t | _| j	dt
| _t | _| j	dd | _| jd kr~t | _d S )Nl        r   z,"max_connections" must be a positive integerro   rp   )r   r|   r~   r^  connection_kwargsr[  _available_connectionsset_in_use_connectionsr   r3   ro   rw   Lockrd   rs   r   )rJ   r^  r[  ru  rA   rA   rB   r   H  s    

zConnectionPool.__init__c                 C   s*   d| j j d| j j d| jf | jdS )Nr   r   r   r   )r   r=   r<   r^  ru  r   rA   rA   rB   r   ^  s    (zConnectionPool.__repr__c                 C   s   g | _ t | _d S rH   )rv  r   WeakSetrx  r   rA   rA   rB   resetd  s    zConnectionPool.resetr   c                 C   s   | j pt| j| jk S )z;Return True if a connection can be retrieved from the pool.)rv  r   rx  r[  r   rA   rA   rB   can_get_connectionh  s    z!ConnectionPool.can_get_connection*)Use get_connection() without args instead5.3.0Zargs_to_warnreasonversionc              
      sh   | j 4 I d H J |  }z| |I d H  W n& tk
rR   | |I d H   Y nX W 5 Q I d H R X |S rH   )rd   get_available_connectionensure_connectionr   release)rJ   command_namekeysoptionsrG   rA   rA   rB   get_connectiono  s    zConnectionPool.get_connectionc                 C   sV   z| j  }W n6 tk
rD   t| j| jkr8tdd|  }Y nX | j| |S )zCGet a connection from the pool, without making sure it is connectedzToo many connectionsN)	rv  pop
IndexErrorr   rx  r[  r)   make_connectionaddrI   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 settingsri   rg   rj   rh   rk   F)ri   rj   rk   )ru  ro   r   r>  rA   rA   rB   get_encoder  s    


zConnectionPool.get_encoderc                 C   s   | j f | jS )z=Create a new connection.  Can be overridden by child classes.)r^  ru  r   rA   rA   rB   r    s    zConnectionPool.make_connectionrF   c              
      s~   |  I dH  z| I dH r(tddW nN tttfk
rx   | I dH  |  I dH  | I dH rttddY nX dS )z8Ensure that the connection object is connected and validNzConnection has datazConnection not ready)r   r   r)   r-   r   r   rI   rA   rA   rB   r    s    z ConnectionPool.ensure_connectionc                    s2   | j | | j| | jt|I dH  dS )z(Releases the connection back to the poolN)rx  r   rv  ru   rs   Zdispatch_asyncr   rI   rA   rA   rB   r    s
    zConnectionPool.releaseT)inuse_connectionsc                    sZ   |rt | j| j}n| j}tjdd |D ddiI dH }tdd |D d}|rV|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 rH   r   )r   rG   rA   rA   rB   r     s     z,ConnectionPool.disconnect.<locals>.<genexpr>Zreturn_exceptionsTNc                 s   s   | ]}t |tr|V  qd S rH   )r   r   )r   rrA   rA   rB   r     s     
 )r   rv  rx  rw   Zgathernext)rJ   r  connectionsrespr   rA   rA   rB   r     s     zConnectionPool.disconnectc                    s   |   I dH  dS )z-Close the pool, disconnecting all connectionsNr   r   rA   rA   rB   aclose  s    zConnectionPool.acloser"   )rn   r   c                 C   s(   | j D ]
}||_q| jD ]
}||_qd S rH   )rv  rn   rx  )rJ   rn   connrA   rA   rB   	set_retry  s    

zConnectionPool.set_retryr   c              
      s   j 4 I d H r jD ]N  j fddfddI d H   j fddfddI d H  qjD ]   qlW 5 Q I d H R X 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
     | S rH   _mockr   r   rA   rB   r     r:   c                      s      S rH   )r   rA   )r  rA   rB   r     r:   c                    s
     | S rH   r  r   r   rA   rB   r     r:   )rd   rv  rn   r   rx  r  r  rA   )r  rJ   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._mock)N)T) r<   r=   r>   r  classmethodr   rn  r   rs  r  rE   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   ro    s8   0	
c                       sv   e Zd ZdZddeejfeee e	e
 e	ej d fddZedgdd	d
d fdd	Ze
d 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      )r[  r!   r^  queue_classc                    s,   t  jf ||d| t | _|| _d S )Nrt  )r  r   rw   	Condition
_conditionr!   )rJ   r[  r!   r^  r  ru  r  rA   rB   r     s    
zBlockingConnectionPool.__init__r}  r~  r  r  Nc                    s   zf| j 4 I dH H t| j4 I dH $ | j | jI dH  t  }W 5 Q I dH R X W 5 Q I dH R X W n. tjk
r } zt	d|W 5 d}~X Y nX z| 
|I dH  |W S  tk
r   | |I dH   Y nX dS )z@Gets a connection from the pool, blocking until one is availableNzNo connection available.)r  r   r!   r   r|  r  r  rw   r-   r)   r  r   r  )rJ   r  r  r  rG   errr  rA   rB   r    s    .z%BlockingConnectionPool.get_connectionrF   c              
      s@   | j 4 I dH " t |I dH  | j   W 5 Q I dH R X dS )z)Releases the connection back to the pool.N)r  r  r  notifyrI   r  rA   rB   r  3  s    zBlockingConnectionPool.release)N)r<   r=   r>   r  r  rw   	LifoQueuer|   r
   r   rE   Queuer   r   r  r  r'  rA   rA   r  rB   r    s$   #r  )mrw   rx   enumr   rv   sysr  r   abcr   	itertoolsr   typesr   typingr   r   r   r   r	   r
   r   r   r   r   r   r   r   urllib.parser   r   r   r   utilsr   r=  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@   rt   r_  rC   rD   rM   r  rE   r  r(  r<  rN  rX  r
  rZ  r|   r   r\  r   r?   r]  rm  rn  ro  r  rA   rA   rA   rB   <module>   s    <$	    q9CE
4 `