o
    `f3                     @   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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 d dlmZmZmZmZ ddl m!Z! ej"d	krod d
l m#Z$ nd d
l$m#Z$ d dl%m&Z& d dl'm(Z( d dl)m*Z*m+Z+ d dl,m-Z- d dl.m/Z/m0Z0 d dl1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8 d dl9m:Z: d dl;m<Z<m=Z=m>Z> ddl?m@Z@mAZAmBZBmCZCmDZD dZEdZFdZGdZHdZIG dd dejJZKeKjLZMeeeCeDeBf  eNd< e<reBZOneCZOG dd de*ZPG dd de*ZQeePeQf ZRG d d! d!ZSG d"d# d#eSZTG d$d% d%eTZUG d&d' d'ZVG d(d) d)eSZWd*ZXd+eeY fd,d-ZZee[e\e\eZeZe[e[eZe\d.	Z]ee^ed/e_f f eNd0< G d1d2 d2e+d3d4Z`d5e^d+e`fd6d7Zaed8d9d:ZbG d;d9 d9ZcG d<d= d=ecZddS )>    N)abstractmethod)chain)MappingProxyType)AnyCallableIterableListMappingOptionalSetTupleTypeTypeVarUnion)ParseResultparse_qsunquoteurlparse   )format_error_message)      r   )timeout)Retry)	NoBackoff)Protocol	TypedDict)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 r:   r:   Q/home/ubuntu/webapp/venv/lib/python3.10/site-packages/redis/asyncio/connection.pyr4   E   s    
r4   DefaultParserc                   @      e Zd ZdddZdS )ConnectCallbackProtocol
connectionAbstractConnectionc                 C      d S Nr:   selfr?   r:   r:   r;   __call__T   s   z ConnectCallbackProtocol.__call__Nr?   r@   r5   r6   r7   rE   r:   r:   r:   r;   r>   S       r>   c                   @   r=   )AsyncConnectCallbackProtocolr?   r@   c                       d S rB   r:   rC   r:   r:   r;   rE   Y   s   z%AsyncConnectCallbackProtocol.__call__NrF   rG   r:   r:   r:   r;   rI   X   rH   rI   c                ,   @   st  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 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 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.d/ Z d0d1 Z!dee d2dfd3d4Z"d5d6 Z#ed7d8 Z$ed2e
fd9d:Z%d;e&d2e
fd<d=Z'dbd>d?Z(dcd@ed2dfdAdBZ)dCdD Z*dEdF Z+dGdH Z,dIe-e. d2dfdJdKZ/	LdddIe	e.e
e-e. f dMed2dfdNdOZ0dPedQed2dfdRdSZ1dTdU Z2		dedLddVdWedXee dYedZee fd[d\Z3dPe4d2e5e. fd]d^Z6d_e-e-e4  d2e5e. fd`daZ7dS )fr@   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_check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   )rK   rQ   rR   rS   rU   rV   encodingencoding_errorsdecode_responsesparser_classsocket_read_sizerW   rM   rN   rO   rL   retryrT   encoder_classrP   r\   rK   rQ   rR   rS   rU   rV   rg   rh   ri   rj   rk   rW   rM   rN   rO   rL   rl   rT   rm   rP   r\   c                C   s  |s|r|d urt d|| _|| _|| _|| _|| _|| _|| _|| _|d u r*|}|| _	|| _
|tu r6g }|rI|t |tj |tj || _|sP|rg|sZtt d| _nt|| _| j| ntt d| _|| _d| _||||	| _|| _d | _d | _|| _| |
 g | _ 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#   rK   rM   rN   rO   rP   rQ   rL   rR   rS   rU   SENTINELappendr&   socketr   asynciorV   r   r   rl   copydeepcopyupdate_supported_errorsrW   rX   rZ   rT   r]   r^   rc   
set_parserr`   ra   int	TypeErrorr   
ValueErrorr"   r\   )rD   rK   rQ   rR   rS   rU   rV   rg   rh   ri   rj   rk   rW   rM   rN   rO   rL   rl   rT   rm   rP   r\   pr:   r:   r;   __init__   sj   


zAbstractConnection.__init__	_warningsc                 C   s2   t | dd r|jd| t| d |   d S d S )Nr^   zunclosed Connection )source)getattrwarnResourceWarning_close)rD   r}   r:   r:   r;   __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)r^   closer]   rD   r:   r:   r;   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 )=Nr:   ).0kvr:   r:   r;   	<genexpr>   s     z.AbstractConnection.__repr__.<locals>.<genexpr><.()>)joinrepr_pieces	__class__r6   r5   )rD   	repr_argsr:   r:   r;   __repr__   s    zAbstractConnection.__repr__c                 C   rA   rB   r:   r   r:   r:   r;   r         zAbstractConnection.repr_piecesc                 C   s   | j d uo	| jd uS rB   )r]   r^   r   r:   r:   r;   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
WeakMethodr`   rq   )rD   callbackwmr:   r:   r;   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)r`   remover   r   rz   )rD   r   r:   r:   r;   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
        )rk   N)rc   r_   )rD   rj   r:   r:   r;   rw     s   zAbstractConnection.set_parserc              
      sP   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s`  I dH  nt jrn  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 )z5Connects to the Redis server if not already connectedNc                            S rB   )_connectr:   r   r:   r;   <lambda>      z,AbstractConnection.connect.<locals>.<lambda>c                    r   rB   
disconnect)errorr   r:   r;   r     r   zTimeout connecting to serverc                 S   s   g | ]}| r|qS r:   r:   )r   refr:   r:   r;   
<listcomp>1  s    z.AbstractConnection.connect.<locals>.<listcomp>)r   rl   call_with_retryrs   CancelledErrorrr   r   r&   OSErrorr"   _error_message	ExceptionrT   
on_connectiscoroutinefunctionr$   r   r`   inspectisawaitable)rD   eexcr   r   taskr:   r   r;   connect  sL   


zAbstractConnection.connectc                    rJ   rB   r:   r   r:   r:   r;   r   8  s   zAbstractConnection._connectc                 C   rA   rB   r:   r   r:   r:   r;   _host_error<  r   zAbstractConnection._host_error	exceptionc                 C   s   t |  |S rB   )r   r   )rD   r   r:   r:   r;   r   @     z!AbstractConnection._error_messagec              	      s  | j |  | j }d}| js| js| jr#| jpt| j| j}| }|r{| jdvr{t| j t	r@| 
t |j| j _| j |  t|dkrLd|d g}| jd| jdg|R  I dH  |  I dH }|dt| jkrz|d	t| jkrztd
no|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 |  | d| jI dH  |  I dH }| jr	| dd| jI dH  t|  I dH dkr	td| jr| ddd| jI dH  | jr)| ddd| jI dH  | jr7| d| jI dH  dd | j| jfD D ]}z
|  I dH  W qB tyY   Y qBw | jrnt|  I dH dkrptddS dS )z=Initialize the connection, authenticate and select a databaseN)r   2rn   defaultr   HELLOAUTHs   protoprotozInvalid RESP versioncheck_healthFro   r   OKzInvalid Username or PasswordCLIENTSETNAMEzError setting client nameSETINFOzLIB-NAMEzLIB-VERSELECTc                 s   s    | ]}|r|V  qd S rB   r:   )r   sentr:   r:   r;   r         z0AbstractConnection.on_connect.<locals>.<genexpr>zInvalid Database)r_   r   rP   rL   rQ   r   get_credentialsr\   
isinstancer.   rw   r/   EXCEPTION_CLASSESlensend_commandread_responsegetrx   r"   r!   r*   r    rM   rN   rO   rK   r%   )rD   parser	auth_argscred_providerresponseauth_response_r:   r:   r;   r   C  s   




zAbstractConnection.on_connect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_timeoutrS   r_   on_disconnectr   r^   r   wait_closedr   r]   rs   r&   )rD   r   r:   r:   r;   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 returnPINGFr   NPONGz#Bad response from PING health check)r   r*   r   r"   r   r:   r:   r;   
_send_ping  s
   zAbstractConnection._send_pingc                       |   I dH  dS )z Function to call when PING failsNr   )rD   r   r:   r:   r;   _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)	rW   rs   get_running_looptimerX   rl   r   r   r   r   r:   r:   r;   r     s   zAbstractConnection.check_healthcommandc                    s"   | j | | j  I d H  d S rB   )r^   
writelinesdrain)rD   r   r:   r:   r;   _send_packed_command  s   z'AbstractConnection._send_packed_commandTr   c              
      sV  | j s|  I d H  n	|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y`   | 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 )
NTr   zTimeout writing to socketrn   UNKNOWNr   zError z while writing to socket. r   )r   r   r   r   strencodebytesrR   rs   wait_forr   r^   r   r   r&   r   r   r   argsr"   BaseException)rD   r   r   r   err_noerrmsgr:   r:   r;   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   )rD   r   r   r:   r:   r;   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: )r_   can_read_destructiver   r   r   r"   r   )rD   r   
host_errorr:   r:   r;   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rD| jdv rDtsDt|4 I dH  | jj||dI dH }W d  I dH  n1 I dH s>w   Y  nJ|durqt|4 I dH  | jj|dI dH }W d  I dH  n1 I dH skw   Y  n| jdv rts| 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 : )rR   r   r\   r(   r   r_   r   rs   r&   r   r   r"   r   r   rW   r   r   rX   r   r%   )
rD   r   r   r   r   read_timeoutr   r   r   	next_timer:   r:   r;   r     sf   	
((
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   rn   N    )r   floatr   tupler   split	SYM_EMPTYr   SYM_STARr   SYM_CRLFra   maprZ   
memoryview
SYM_DOLLARrq   )rD   r   outputbuffbuffer_cutoffarg
arg_lengthr:   r:   r;   r   =  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   )ra   r   r   r   r  rq   r   r   )	rD   r  r  piecesbuffer_lengthr  cmdchunkchunklenr:   r:   r;   pack_commandsk  s.   

z AbstractConnection.pack_commandsr   N)FT)FN)8r5   r6   r7   __doc__	__slots__rp   r<   r)   r,   r   r   rx   r
   r   boollistr4   r   r+   r   ConnectCallbackTr   r|   warningsr   r   r   r   r   r   propertyr   r   r   rw   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@   `   s     

	

R


)

W
)
>".r@   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 Nr:   )r  rx   r  r  r  r  superr|   )rD   r  r  r  r  r  r   r   r:   r;   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  rK   rM   )r  r  rK   rM   rq   rD   r	  r:   r:   r;   r     s   zConnection.repr_piecesr   c                 C   s   | j | jdS )Nr  r  r#  r   r:   r:   r;   _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 connectionNrr   rn   r:   )r   rS   rs   open_connectionr$  r]   r^   	transportget_extra_info
setsockoptrr   IPPROTO_TCPTCP_NODELAYr  
SOL_SOCKETSO_KEEPALIVEr  itemsSOL_TCPr   ry   r   )rD   readerwritersockr   r   r:   r:   r;   r     s.   (zConnection._connectc                 C   s   | j  d| j S )N:r#  r   r:   r:   r;   r     s   zConnection._host_error)r5   r6   r7   r  r   r   rx   r  r
   r	   r   r|   r   r$  r   r   __classcell__r:   r:   r!  r;   r    s,    
r  c                       s   e Zd ZdZ								d dee dee dedee d	ee d
edeej 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requiredFssl_keyfilessl_certfilessl_cert_reqsssl_ca_certsssl_ca_datassl_check_hostnamessl_min_versionssl_ciphersc	           
   
      s0   t ||||||||d| _t jdi |	 d S )N)keyfilecertfile	cert_reqsca_certsca_datacheck_hostnamemin_versionciphersr:   )RedisSSLContextr[   r   r|   )
rD   r6  r7  r8  r9  r:  r;  r<  r=  r   r!  r:   r;   r|     s   
zSSLConnection.__init__r   c                    s   t   }| j |d< |S )Nssl)r   r$  r[   r   rD   r   r!  r:   r;   r$    s   
z#SSLConnection._connection_argumentsc                 C      | j jS rB   )r[   r>  r   r:   r:   r;   r>       zSSLConnection.keyfilec                 C   rI  rB   )r[   r?  r   r:   r:   r;   r?    rJ  zSSLConnection.certfilec                 C   rI  rB   )r[   r@  r   r:   r:   r;   r@    rJ  zSSLConnection.cert_reqsc                 C   rI  rB   )r[   rA  r   r:   r:   r;   rA    rJ  zSSLConnection.ca_certsc                 C   rI  rB   )r[   rB  r   r:   r:   r;   rB    rJ  zSSLConnection.ca_datac                 C   rI  rB   )r[   rC  r   r:   r:   r;   rC    rJ  zSSLConnection.check_hostnamec                 C   rI  rB   )r[   rD  r   r:   r:   r;   rD    rJ  zSSLConnection.min_version)NNr5  NNFNN)r5   r6   r7   r  r
   r   r  rG  
TLSVersionr|   r	   r$  r  r>  r?  r@  rA  rB  rC  rD  r3  r:   r:   r!  r;   r4    sT    	





r4  c                   @   sz   e Zd ZdZ								ddee dee dee dee dee d	ed
eej dee fddZ	dej
fddZdS )rF  )	r>  r?  r@  rA  rB  contextrC  rD  rE  NFr>  r?  r@  rA  rB  rC  rD  rE  c	           
      C   s   || _ || _|d u rtj| _nt|tr-tjtjtjd}	||	vr(t	d| |	| | _|| _
|| _|| _|| _|| _d | _d S )N)noneoptionalr5  z+Invalid SSL Certificate Requirements Flag: )r>  r?  rG  	CERT_NONEr@  r   r   CERT_OPTIONALCERT_REQUIREDr$   rA  rB  rC  rD  rE  rL  )
rD   r>  r?  r@  rA  rB  rC  rD  rE  	CERT_REQSr:   r:   r;   r|     s(   



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)r?  r>  )cafilecadata)rL  rG  create_default_contextrC  r@  verify_moder?  r>  load_cert_chainrA  rB  load_verify_locationsrD  minimum_versionrE  set_ciphers)rD   rL  r:   r:   r;   r   1  s   

zRedisSSLContext.get)NNNNNFNN)r5   r6   r7   r  r
   r   r  rG  rK  r|   
SSLContextr   r:   r:   r:   r;   rF    s8    	
!rF  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 pathr_  c                   s   || _ t jdi | d S r  )r_  r   r|   )rD   r_  r   r!  r:   r;   r|   E  s   z#UnixDomainSocketConnection.__init__r   c                 C   s.   d| j fd| jfg}| jr|d| jf |S )Nr_  rK   rM   )r_  rK   rM   rq   r"  r:   r:   r;   r   I  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 )Nr^  )r   rS   rs   open_unix_connectionr_  r]   r^   r   )rD   r/  r0  r:   r:   r;   r   O  s   (z#UnixDomainSocketConnection._connectc                 C   s   | j S rB   r^  r   r:   r:   r;   r   V  s   z&UnixDomainSocketConnection._host_error)r5   r6   r7   r  r   r|   r   r   r   rx   r   r   r   r3  r:   r:   r!  r;   r\  B  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  )valuer:   r:   r;   to_bool]  s
   ri  )	rK   rR   rS   r  rU   max_connectionsrW   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 )	ConnectKwargsrL   rQ   connection_classr  r  rK   r_  N)r5   r6   r7   r   __annotations__r   r@   rx   r:   r:   r:   r;   rl  t  s   
 rl  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.rL   rQ   unixr_  rm  )redisredissr  r  rK   /r]  rs  zredis://, rediss://, unix://z5Redis URL must specify one of the following schemes ())r   r   queryr-  r   r   rk  r   ry   rz   rL   rQ   schemer_  r\  hostnamer  rx   replaceAttributeErrorr4  )rp  parsedr   name
value_listrh  r   valid_schemesr:   r:   r;   	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dd Zdd Zdd Zdd Zde
fddZde
fddZd)d efd!d"Zd*d#d$Zd+d'd(ZdS ),r  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``.
    clsrp  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.
        Nr:   )r  update)r  rp  r   url_optionsr:   r:   r;   from_url  s   +
zConnectionPool.from_urlNrm  rj  c                 K   sV   |pd}t |tr|dk rtd|| _|| _|| _g | _t | _| j	dt
| _d S )Nl        r   z,"max_connections" must be a positive integerrm   )r   rx   rz   rm  connection_kwargsrj  _available_connectionsset_in_use_connectionsr   r,   rm   )rD   rm  rj  r  r:   r:   r;   r|     s   zConnectionPool.__init__c              	   C   s.   d| j j d| j j d| jdi | jdS )Nr   r   r   r   r:   )r   r6   r5   rm  r  r   r:   r:   r;   r     s   zConnectionPool.__repr__c                 C   s   g | _ t | _d S rB   )r  r   WeakSetr  r   r:   r:   r;   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  rj  r   r:   r:   r;   can_get_connection  s   z!ConnectionPool.can_get_connectionc                    sB   |   }z| |I dH  W |S  ty    | |I dH   w )z(Get a connected connection from the poolN)get_available_connectionensure_connectionr   release)rD   command_namekeysoptionsr?   r:   r:   r;   get_connection  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  rj  r"   make_connectionaddrC   r:   r:   r;   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 settingsrg   re   rh   rf   ri   F)rg   rh   ri   )r  rm   r   rH  r:   r:   r;   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.Nr:   )rm  r  r   r:   r:   r;   r  4  s   zConnectionPool.make_connectionr?   c              	      s|   |  I dH  z| I dH rtddW dS  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   rC   r:   r:   r;   r  8  s   

z ConnectionPool.ensure_connectionc                    s   | j | | j| dS )z(Releases the connection back to the poolN)r  r   r  rq   rC   r:   r:   r;   r  H  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 rB   r   )r   r?   r:   r:   r;   r   ^  r   z,ConnectionPool.disconnect.<locals>.<genexpr>return_exceptionsTNc                 s   s    | ]
}t |tr|V  qd S rB   )r   r   )r   rr:   r:   r;   r   a  s    )r   r  r  rs   gathernext)rD   r  connectionsrespr   r:   r:   r;   r   O  s   zConnectionPool.disconnectc                    r   )z-Close the pool, disconnecting all connectionsNr   r   r:   r:   r;   aclosee  r   zConnectionPool.acloserl   r   c                 C   s(   | j D ]}||_q| jD ]}||_qd S rB   )r  rl   r  )rD   rl   connr:   r:   r;   	set_retryi  s
   

zConnectionPool.set_retryr  r  )rl   r   r   N)r5   r6   r7   r  classmethodr   r  r   r  r  r@   r
   rx   r|   r   r  r  r  r  r  r  r  r  r  r   r  r  r:   r:   r:   r;   r    s.    0
	
c                
       sj   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 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      rj  r   rm  queue_classc                    s,   t  jd||d| t | _|| _d S )N)rm  rj  r:   )r   r|   rs   	Condition
_conditionr   )rD   rj  r   rm  r  r  r!  r:   r;   r|     s   

zBlockingConnectionPool.__init__c              
      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  rs   r&   r"   r  r   r  )rD   r  r  r  r?   errr!  r:   r;   r    s(   *(
z%BlockingConnectionPool.get_connectionr?   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  notifyrC   r!  r:   r;   r    s
   .zBlockingConnectionPool.release)r5   r6   r7   r  r  rs   	LifoQueuerx   r
   r   r@   Queuer|   r  r  r3  r:   r:   r!  r;   r  p  s"    #r  )ers   rt   enumr   rr   rG  sysr  r   abcr   	itertoolsr   typesr   typingr   r   r   r   r	   r
   r   r   r   r   r   urllib.parser   r   r   r   utilsr   version_infor   r   redis.asyncio.retryr   redis.backoffr   redis.compatr   r   redis.connectionr   redis.credentialsr   r   redis.exceptionsr    r!   r"   r#   r$   r%   r&   redis.typingr'   redis.utilsr(   r)   r*   _parsersr+   r,   r-   r.   r/   r   r  r   SYM_LFr   Enumr4   r9   rp   rn  r<   r>   rI   r  r@   r  r4  rF  r\  rg  r  ri  rx   r   rk  r   r8   rl  r  r  r  r  r:   r:   r:   r;   <module>   s   
 4
$	    .9@?
4 <