o
    i                     @   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mZmZ d dlmZmZm Z m!Z! ddl"m#Z#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,m-Z- ndZ*dZ,dZ+dZ-ddl.m/Z/ ddl0m1Z1m2Z2 ddl3m4Z4m5Z5 ddl(m6Z6m7Z7 ej8dkrd dl m9Z: nd dl:m9Z: d dl;m<Z<m=Z=m>Z>m?Z? d dl@mAZA d dlBmCZC d dlDmEZE d dlFmGZGmHZH d dlImJZJmKZKmLZLmMZMmNZNmOZOmPZPmQZQ d dlRmSZS d dlTmUZU d dlVmWZWmXZX ddlYmZZZm[Z[m\Z\m]Z]m^Z^ dZ_dZ`dZadZbdZcG d d! d!ejdZeeejfZgeee]e^e\f  ehd"< eWrAe\Zine]ZiG d#d$ d$eZjG d%d& d&eZkeejekf ZlG d'd( d(ZmG d)d* d*emZnG d+d, d,enZoG d-d. d.ZpG d/d0 d0emZqd1Zrd2ees fd3d4Ztd5d6 Zueeveweweteteveveteueuewd7Zxeeyed8ezf f ehd9< G d:d; d;ed<d=Z{d>eyd2e{fd?d@Z|edAdBdCZ}G dDdB dBZ~G dEdF dFe~ZdS )G    N)abstractmethod)chain)MappingProxyType)AnyCallableIterableListMappingOptionalProtocolSetTupleType	TypedDictTypeVarUnion)ParseResultparse_qsunquoteurlparse   )DB_CLIENT_CONNECTION_POOL_NAMEDB_CLIENT_CONNECTION_STATEAttributeBuilderConnectionStateget_pool_name)SSL_AVAILABLE)
SSLContext
TLSVersionVerifyFlags)TokenInterface)
DriverInforesolve_driver_info)!AsyncAfterConnectionReleasedEventEventDispatcher)deprecated_argsformat_error_message)      r'   )timeout)record_connection_closedrecord_connection_create_timerecord_connection_wait_timerecord_error_count)Retry)	NoBackoff)DEFAULT_RESP_VERSION)CredentialProvider"UsernamePasswordCredentialProvider)AuthenticationError$AuthenticationWrongNumberOfArgsErrorConnectionError	DataErrorMaxConnectionsError
RedisErrorResponseErrorTimeoutError)CloseReason)
EncodableT)HIREDIS_AVAILABLE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 rN   rN   L/home/ubuntu/.local/lib/python3.10/site-packages/redis/asyncio/connection.pyrH   c   s    
rH   DefaultParserc                   @      e Zd ZdddZdS )ConnectCallbackProtocol
connectionAbstractConnectionc                 C      d S NrN   selfrS   rN   rN   rO   __call__r   s    z ConnectCallbackProtocol.__call__NrS   rT   rI   rJ   rK   rY   rN   rN   rN   rO   rR   q       rR   c                   @   rQ   )AsyncConnectCallbackProtocolrS   rT   c                       d S rV   rN   rW   rN   rN   rO   rY   v   s    z%AsyncConnectCallbackProtocol.__call__NrZ   r[   rN   rN   rN   rO   r]   u   r\   r]   c                1   @   s"  e Zd ZdZdZeddgddddddd	ed
dd	edddddd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 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/d0 Z!d1d2 Z"d3d4 Z#dee d5dfd6d7Z$d8d9 Z%	:d~d;ed<efd=d>Z&d?d@ Z'dAdB Z(dCdD Z)edEdF Z*ed5e
fdGdHZ+dIe,d5e
fdJdKZ-dLdM Z.ddNdOZ/dd;ed5dfdPdQZ0						ddRedSee1 dTee dUed5df
dVdWZ2dXdY Z3dZd[ Z4d\d] Z5d^e6e7 d5dfd_d`Z8	:dd^e	e7e
e6e7 f d;ed5dfdadbZ9dcedded5dfdedfZ:dgdh Z;			dd:d	didjedkee dledmee fdndoZ<dce=d5e>e7 fdpdqZ?dre6e6e=  d5e>e7 fdsdtZ@dudv ZAdwdx ZBdyeCfdzd{ZDd|d} ZEdS )rT   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__rb   rc   zbUse 'driver_info' parameter instead. lib_name and lib_version will be removed in a future version.)args_to_warnreasonr   NFutf-8stricti   r   )r_   re   rf   rg   ri   rj   encodingencoding_errorsdecode_responsesparser_classsocket_read_sizerk   ra   rb   rc   driver_infor`   retryrh   encoder_classrd   rp   event_dispatcherr_   re   rf   rg   ri   rj   r}   r~   r   r   r   rk   ra   r   r`   r   rh   r   rd   rp   r   c                C   s  |s|r|durt d|du rt | _n|| _|| _|| _t|||| _|| _|| _|| _	|| _
|du r7|}|| _|| _|tu rCg }|rV|t |tj |tj || _|s]|rt|sgtt d| _nt|| _| j| ntt d| _|| _d| _||||	| _|| _d| _d| _|| _ | !|
 g | _"d| _#d| _$d| _%zt&|}W n t'y   t(}Y n t)y   t*dw |d	k s|d
krt*d|| _+dS )ag  
        Initialize a new async Connection.

        Parameters
        ----------
        driver_info : DriverInfo, optional
            Driver metadata for CLIENT SETINFO. If provided, lib_name and lib_version
            are ignored. If not provided, a DriverInfo will be created from lib_name
            and lib_version (or defaults if those are also None).
        lib_name : str, optional
            **Deprecated.** Use driver_info instead. Library name for CLIENT SETINFO.
        lib_version : str, optional
            **Deprecated.** Use driver_info instead. Library version for CLIENT SETINFO.
        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  Fzprotocol must be an integerr   r'   zprotocol must be either 2 or 3),r6   r$   _event_dispatcherr_   ra   r"   r   rd   re   r`   rf   rg   ri   SENTINELappendr:   socketr)   asynciorj   r.   r/   r   copydeepcopyupdate_supported_errorsrk   rl   rn   rh   rq   rr   rw   
set_parserrt   ru   _re_auth_token_should_reconnectint	TypeErrorr0   
ValueErrorr5   rp   )rX   r_   re   rf   rg   ri   rj   r}   r~   r   r   r   rk   ra   rb   rc   r   r`   r   rh   r   rd   rp   r   prN   rN   rO   __init__   sj   .



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 )Nrr   zunclosed Connection )source)getattrwarnResourceWarningr   get_running_loop_closeRuntimeError)rX   r   rN   rN   rO   __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)rr   closerq   rX   rN   rN   rO   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 )=NrN   .0kvrN   rN   rO   	<genexpr>%  s     z.AbstractConnection.__repr__.<locals>.<genexpr><.(z)>)joinrepr_pieces	__class__rJ   rI   )rX   	repr_argsrN   rN   rO   __repr__$  s    zAbstractConnection.__repr__c                 C   rU   rV   rN   r   rN   rN   rO   r   (     zAbstractConnection.repr_piecesc                 C   s   | j d uo	| jd uS rV   )rq   rr   r   rN   rN   rO   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
WeakMethodrt   r   )rX   callbackwmrN   rN   rO   register_connect_callback0  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)rt   remover   r   r   )rX   r   rN   rN   rO   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
        )r   N)rw   rs   )rX   r   rN   rN   rO   r   G  s   zAbstractConnection.set_parserc                    s.    j j fdd fddddI dH  dS )z5Connects to the Redis server if not already connectedc                      s    j dddS )NTF)check_healthretry_socket_connect)connect_check_healthrN   r   rN   rO   <lambda>T      z,AbstractConnection.connect.<locals>.<lambda>c                    s    j | |dS Nerrorfailure_count
disconnectr   r   rN   rO   r   W  r   Twith_failure_countN)r   call_with_retryr   rN   r   rO   connectO  s   

zAbstractConnection.connectTr   r   c           	         s  j rd S d  fdd}z|r#jjfdd|ddI d H  n I d H  W ny tjy4     tjtjfyb   td}t	t
d	d t
d
d t
d	d t
d
d | ddI d H  | ty } z't|}t	t
d	d t
d
d t
d	d t
d
d | ddI d H  |d }~w ty } zt||d }~ww z"jsj|dI d H  ntjr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 )Nr   c                    s   | j | |dS r   r   r   actual_retry_attemptsrX   rN   rO   failure_callbacke  s   zAAbstractConnection.connect_check_health.<locals>.failure_callbackc                            S rV   )_connectrN   r   rN   rO   r   m      z9AbstractConnection.connect_check_health.<locals>.<lambda>Tr   zTimeout connecting to serverhostportF)server_addressserver_portnetwork_peer_addressnetwork_peer_port
error_typeretry_attemptsis_internalr   c                 S   s   g | ]}| r|qS rN   rN   )r   refrN   rN   rO   
<listcomp>  s    z;AbstractConnection.connect_check_health.<locals>.<listcomp>)r   r   r   r   r   CancelledErrorr   r)   r:   r-   r   OSErrorr5   _error_message	Exceptionrh   on_connect_check_healthiscoroutinefunctionr8   r   rt   inspectisawaitable)	rX   r   r   r   eexcr   r   taskrN   r   rO   r   ]  s   




	



	



z'AbstractConnection.connect_check_healthc                 C   
   d| _ d S )NTr   r   rN   rN   rO   mark_for_reconnect     
z%AbstractConnection.mark_for_reconnectc                 C      | j S rV   r   r   rN   rN   rO   should_reconnect     z#AbstractConnection.should_reconnectc                 C   r   )NFr   r   rN   rN   rO   reset_should_reconnect  r   z)AbstractConnection.reset_should_reconnectc                    r^   rV   rN   r   rN   rN   rO   r     s   zAbstractConnection._connectc                 C   rU   rV   rN   r   rN   rN   rO   _host_error  r   zAbstractConnection._host_error	exceptionc                 C   s   t |  |S rV   )r&   r   )rX   r   rN   rN   rO   r        z!AbstractConnection._error_messagec                 C   r   rV   )rp   r   rN   rN   rO   get_protocol  r   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   rN   rN   rO   
on_connect  s   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d}d}| jr1| jjr1| jddd| jj|dI d H  d}| jrK| jjrK| jddd| jj|dI d H  d}| jr[| jd| j|dI d H  tt||gD ]}	z
|  I d H  W qc tyz   Y qcw | jrt|  I d H dkrtdd S d S )N)r   2r   defaultr   HELLOAUTHr   Fs   protoprotozInvalid RESP versionr   r   OKzInvalid Username or PasswordCLIENTSETNAMEzError setting client nameSETINFOzLIB-NAMETzLIB-VERSELECTzInvalid Database)rs   r   rd   r`   re   r2   get_credentials_asyncrp   
isinstancerB   r   rC   EXCEPTION_CLASSESlensend_commandread_responsegetr   r5   r4   r>   r3   ra   r   formatted_namerc   r_   rangesumr9   )
rX   r   parser	auth_argscred_providerresponseauth_responselib_name_sentlib_version_sent_rN   rN   rO   r     s   




z*AbstractConnection.on_connect_check_healthnowaitr   r   health_check_failedc              	      s  zet | j4 I dH O | j  |   | js%	 W d  I dH  W dS z#z| j  |s6| j I dH  W n	 t	y@   Y nw W d| _
d| _nd| _
d| _w W d  I dH  n1 I dH s`w   Y  W n tjyw   td| j dw |r|rtj}ntj}|dur|| j krtt| ddt| ddt| ddt| dd||dI dH  t||dI dH  dS ttjdI dH  dS )z!Disconnects from the Redis serverNz#Timed out closing connection after r   r   )r   r   r   r   r   r   )close_reasonr   )r  )async_timeoutrg   rs   on_disconnectr   r   rr   r   wait_closedr   rq   r   r:   r;   HEALTHCHECK_FAILEDERRORr   get_retriesr-   r   r*   APPLICATION_CLOSE)rX   r  r   r   r  r  rN   rN   rO   r   8  sd   


(




	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  r5   r   rN   rN   rO   
_send_pingp  s
   zAbstractConnection._send_pingc                    s   | j ||ddI dH  dS )z Function to call when PING failsT)r   r   r  Nr   )rX   r   r   rN   rN   rO   _ping_failedv  s   zAbstractConnection._ping_failedc                    sB   | j rt  | jkr| jj| j| jddI dH  dS dS dS )z3Check the health of the connection with a PING/PONGTr   N)	rk   r   r   timerl   r   r   r  r  r   rN   rN   rO   r   |  s   
zAbstractConnection.check_healthcommandc                    s"   | j | | j  I d H  d S rV   )rr   
writelinesdrain)rX   r   rN   rN   rO   _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 socketr   UNKNOWNr   zError z while writing to socket. r   )r   r   r   r   strencodebytesrf   r   wait_forr#  rr   r!  r"  r:   r   r   r  argsr5   BaseException)rX   r   r   r   err_noerrmsgrN   rN   rO   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  )rX   r*  r/  rN   rN   rO   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: )rs   can_read_destructiver   r   r   r5   r*  )rX   r   
host_errorrN   rN   rO   r2    s   z'AbstractConnection.can_read_destructive)disconnect_on_errorpush_requestdisable_decodingr)   r4  r5  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'   )r6  r5  )r6  Tr$  zTimeout reading from r1  z : )rf   r   rp   r  rs   r  r   r:   r   r   r5   r*  r+  rk   r   r  rl   r   r9   )
rX   r6  r)   r4  r5  read_timeoutr3  r  r   	next_timerN   rN   rO   r    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   r   N    )r   floatr&  tupler'  split	SYM_EMPTYr   SYM_STARr  SYM_CRLFru   maprn   
memoryview
SYM_DOLLARr   )rX   r*  outputbuffbuffer_cutoffarg
arg_lengthrN   rN   rO   r0    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   )ru   r0  r  r   rB  r   r>  r   )	rX   rI  rD  piecesbuffer_lengthrF  cmdchunkchunklenrN   rN   rO   pack_commands*  s.   

z AbstractConnection.pack_commandsc                 C   s   t | jjdkS )zCheck if the socket is emptyr   )r  rq   _bufferr   rN   rN   rO   _socket_is_emptyH  s   z#AbstractConnection._socket_is_emptyc                    s,   |   s| jddI d H  |   rd S d S )NT)r5  )rQ  r  r   rN   rN   rO   process_invalidation_messagesL  s   z0AbstractConnection.process_invalidation_messagestokenc                 C   s
   || _ d S rV   )r   rX   rS  rN   rN   rO   set_re_auth_tokenP  r   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   rN   rN   rO   re_authS  s   



zAbstractConnection.re_auth)TTr   NT)FNNF)FN)FrI   rJ   rK   __doc__	__slots__r%   r   rP   r@   r   r&  r   r
   r;  boollistrH   r   r?   r!   r.   ConnectCallbackTr1   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  r2  r  r<   r   r0  rO  rQ  rR  r    rU  rZ  rN   rN   rN   rO   rT   |   s4   

	
k


M

u
8

)
:.rT   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   )r   r   socket_keepalivesocket_keepalive_optionssocket_typer   r   rf  rg  rh  c                   s<   || _ t|| _|| _|pi | _|| _t jdi | d S NrN   )r   r   r   rf  rg  rh  superr   )rX   r   r   rf  rg  rh  r/  r   rN   rO   r   a  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   r_   ra   )r   r   r_   ra   r   rX   rJ  rN   rN   rO   r   r  s   zConnection.repr_piecesr   c                 C   s   | j | jdS )Nr   r   rm  r   rN   rN   rO   _connection_argumentsx  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 connectionNr   r   rN   )r  rg   r   open_connectionrn  rq   rr   	transportget_extra_info
setsockoptr   IPPROTO_TCPTCP_NODELAYrf  
SOL_SOCKETSO_KEEPALIVErg  itemsSOL_TCPr   r   r   )rX   readerwritersockr   r   rN   rN   rO   r   {  s.   (zConnection._connectc                 C   s   | j  d| j S )N:rm  r   rN   rN   rO   r     s   zConnection._host_error)rI   rJ   rK   r]  r&  r   r   r_  r
   r	   r(  r   r   rn  r   r   __classcell__rN   rN   rk  rO   rd  ^  s,    
rd  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	  d
ee	d	  dee dee dee de
de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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_include_verify_flagsssl.VerifyFlagsssl_exclude_verify_flagsssl_ca_certsssl_ca_datassl_ca_pathssl_check_hostnamessl_min_versionssl_ciphersssl_passwordc                    sD   t stdt|||||||||	|
||d| _t jdi | d S )N$Python wasn't built with SSL support)keyfilecertfile	cert_reqsinclude_verify_flagsexclude_verify_flagsca_certsca_dataca_pathcheck_hostnamemin_versionciphersre   rN   )r   r8   RedisSSLContextro   rj  r   )rX   r  r  r  r  r  r  r  r  r  r  r  r  r/  rk  rN   rO   r     s"   zSSLConnection.__init__r   c                    s   t   }| j |d< |S )Nssl)rj  rn  ro   r  rX   r/  rk  rN   rO   rn    s   
z#SSLConnection._connection_argumentsc                 C      | j jS rV   )ro   r  r   rN   rN   rO   r       zSSLConnection.keyfilec                 C   r  rV   )ro   r  r   rN   rN   rO   r    r  zSSLConnection.certfilec                 C   r  rV   )ro   r  r   rN   rN   rO   r    r  zSSLConnection.cert_reqsc                 C   r  rV   )ro   r  r   rN   rN   rO   r    r  z"SSLConnection.include_verify_flagsc                 C   r  rV   )ro   r  r   rN   rN   rO   r    r  z"SSLConnection.exclude_verify_flagsc                 C   r  rV   )ro   r  r   rN   rN   rO   r    r  zSSLConnection.ca_certsc                 C   r  rV   )ro   r  r   rN   rN   rO   r    r  zSSLConnection.ca_datac                 C   r  rV   )ro   r  r   rN   rN   rO   r    r  zSSLConnection.check_hostnamec                 C   r  rV   )ro   r  r   rN   rN   rO   r    r  zSSLConnection.min_version)NNr  NNNNNTNNN)rI   rJ   rK   r]  r
   r&  r   r  
VerifyModer   r_  r   r   r	   rn  rc  r  r  r  r  r  r  r  r  r  r}  rN   rN   rk  rO   r~    st    

	
#







r~  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  d	ee	d  d
ee dee dee de
dee dee dee fddZdefddZdS )r  )r  r  r  r  r  r  r  r  contextr  r  r  re   NFr  r  r  r  r  r  r  r  r  r  r  r  re   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rK|	nd| _|
| _|| _|| _d | _d S )Nr  )noneoptionalr  z+Invalid SSL Certificate Requirements Flag: F)r   r8   r  r  r  	CERT_NONEr   r&  CERT_OPTIONALCERT_REQUIREDr  r  r  r  r  r  r  r  r  re   r  )rX   r  r  r  r  r  r  r  r  r  r  r  re   	CERT_REQSrN   rN   rO   r     s8   

zRedisSSLContext.__init__r   c                 C   s   | j slt }| j|_| j|_| jr| jD ]	}| j|O  _q| jr0| jD ]
}| j| M  _q%| j	s6| j
rA|j| j	| j
| jd | jsJ| jsJ| jrU|j| j| j| jd | jd ur^| j|_| jd uri|| j || _ | j S )N)r  r  re   )cafilecapathcadata)r  r  create_default_contextr  r  verify_moder  verify_flagsr  r  r  load_cert_chainre   r  r  r  load_verify_locationsr  minimum_versionr  set_ciphers)rX   r  flagrN   rN   rO   r  *  s4   



zRedisSSLContext.get)NNNNNNNNFNNN)rI   rJ   rK   r^  r
   r&  r   r  r  r   r_  r   r   r   r  rN   rN   rN   rO   r    sP    

	

/r  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 ri  )r  rj  r   )rX   r  r/  rk  rN   rO   r   J  s   z#UnixDomainSocketConnection.__init__r   c                 C   s.   d| j fd| jfg}| jr|d| jf |S )Nr  r_   ra   )r  r_   ra   r   rl  rN   rN   rO   r   N  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  rg   r   open_unix_connectionr  rq   rr   r   )rX   ry  rz  rN   rN   rO   r   T  s   (z#UnixDomainSocketConnection._connectc                 C   r   rV   r  r   rN   rN   rO   r   [  r   z&UnixDomainSocketConnection._host_error)rI   rJ   rK   r]  r&  r   r   r   r   r   r   r   r   r}  rN   rN   rk  rO   r  G  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_  )valuerN   rN   rO   to_boolb  s
   r  c                 C   s\   |  dd dd}g }|dD ]}| }tt|s#td| |tt| q|S )N[r  ]r   zInvalid ssl verify flag: )replacer=  striphasattrr   r   r   r   )r  verify_flags_strr  r  rN   rN   rO   parse_ssl_verify_flagsj  s   
r  )r_   rf   rg   rf  ri   max_connectionsrk   r  r  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 )	ConnectKwargsr`   re   connection_classr   r   r_   r  N)rI   rJ   rK   r&  __annotations__r   rT   r   rN   rN   rN   rO   r    s   
 r  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.r`   re   unixr  r  )redisredissr   r   r_   /r  r  zredis://, rediss://, unix://z5Redis URL must specify one of the following schemes ())r   r   queryrw  r  r   r  r  r   r   r`   re   schemer  r  hostnamer   r   r  AttributeErrorr~  )r  parsedr/  name
value_listr  r	  valid_schemesrN   rN   rO   	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d7ddZdd Zdd Zdd Zde
fdd Zde
fd!d"Zd8d$efd%d&Zd'd( Zd9d)d*Zd:d-d.Zd/efd0d1Zd2efd3d4Z de!e"ee#f  fd5d6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.
    :py:class:`~redis.SSLConnection` can be used for SSL enabled connections.

    Any additional keyword arguments are passed to the constructor of
    ``connection_class``.
    clsr  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.
        NrN   )r  update)r  r  r/  url_optionsrN   rN   rO   from_url  s   +
zConnectionPool.from_urlNr  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 u rAt | _d S d S )Nl        r   z,"max_connections" must be a positive integerr   r   )r   r   r   r  connection_kwargsr  _available_connectionsset_in_use_connectionsr  r@   r   r   Lockrv   r   r$   )rX   r  r  r  rN   rN   rO   r   	  s   

zConnectionPool.__init__c                 C   sN   d dd | j D }d| jj d| jj d| jj d| jj d| dS )	Nr   c                 S   s   g | ]\}}| d | qS )r   rN   r   rN   rN   rO   r      s    z+ConnectionPool.__repr__.<locals>.<listcomp>r   r   z(<r   z)>)>)r   r  rw  r   rJ   rI   r  )rX   conn_kwargsrN   rN   rO   r     s   zConnectionPool.__repr__c                 C   s   g | _ t | _d S rV   )r  r   WeakSetr  r   rN   rN   rO   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  r  r   rN   rN   rO   can_get_connection+  s   z!ConnectionPool.can_get_connection*)Use get_connection() without args instead5.3.0ry   rz   versionc           	   	      s   | j 4 I dH + t| jt| j }t }|  }t| jt| j }||k}W d  I dH  n1 I dH s9w   Y  z| |I dH  |rVt| t | dI dH  |W S  t	yh   | 
|I dH   w )z(Get a connected connection from the poolNconnection_poolduration_seconds)rv   r  r  r  r  	monotonicget_available_connectionensure_connectionr+   r+  release)	rX   command_namekeysoptionsconnections_beforestart_time_createdrS   connections_after
is_createdrN   rN   rO   get_connection2  s0   


(
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  r  r7   make_connectionaddrW   rN   rN   rO   r  T  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 settingsr}   r{   r~   r|   r   F)r}   r~   r   )r  r   r  r  rN   rN   rO   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.NrN   )r  r  r   rN   rN   rO   r  h  s   zConnectionPool.make_connectionrS   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   r2  r5   r:   r   r   rW   rN   rN   rO   r  l  s   

z ConnectionPool.ensure_connectionc                    sJ   | j | | r| I dH  | j| | jt|I dH  dS )z(Releases the connection back to the poolN)	r  r   r   r   r  r   r   dispatch_asyncr#   rW   rN   rN   rO   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 rV   r   )r   rS   rN   rN   rO   r     s    z,ConnectionPool.disconnect.<locals>.<genexpr>return_exceptionsTNc                 s   s    | ]
}t |tr|V  qd S rV   )r   r+  )r   rrN   rN   rO   r     s    )r   r  r  r   gathernext)rX   r  connectionsrespr   rN   rN   rO   r     s   zConnectionPool.disconnectc              	      sV   | j 4 I dH  | jD ]}|  qW d  I dH  dS 1 I dH s$w   Y  dS )z<
        Mark all active connections for reconnect.
        N)rv   r  r   )rX   connrN   rN   rO   'update_active_connections_for_reconnect  s   

.z6ConnectionPool.update_active_connections_for_reconnectc                    s   |   I dH  dS )z-Close the pool, disconnecting all connectionsNr   r   rN   rN   rO   aclose  s   zConnectionPool.acloser   r.   c                 C   s(   | j D ]}||_q| jD ]}||_qd S rV   )r  r   r  )rX   r   r  rN   rN   rO   	set_retry  s
   

zConnectionPool.set_retryrS  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 rV  )r  rX  rY  rN   )r  rS  rN   rO   r     s    z1ConnectionPool.re_auth_callback.<locals>.<lambda>c                    
     | S rV   _mockr   r   rN   rO   r        
 c                      r   rV   )r  rN   )r  rN   rO   r     r   c                    r  rV   r  r  r   rN   rO   r     r  )rv   r  r   r   r  rU  rT  rN   )r  rX   rS  rO   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:
        NrN   )rX   r   rN   rN   rO   r    s   zConnectionPool._mockc                 C   sX   t  }t| |t< | }| }tjj|t< tj	j|t< t
| j|ft
| j|fgS )zD
        Returns a connection count (both idle and in use).
        )r   build_base_attributesr   r   r   r   IDLEr  r   USEDr  r  r  )rX   
attributesfree_connections_attributesin_use_connections_attributesrN   rN   rO   get_connection_count  s   z#ConnectionPool.get_connection_countrV   r\  r[  )r   r.   r   N)%rI   rJ   rK   r]  classmethodr   r  r&  r  rd  rT   r
   r   r   r   r  r_  r  r%   r  r  r  r  r  r  r   r  r  r  r    r  r8   r  r   r<  dictr  rN   rN   rN   rO   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      r  r)   r  queue_classc                    s,   t  jd||d| t | _|| _d S )N)r  r  rN   )rj  r   r   	Condition
_conditionr)   )rX   r  r)   r  r"  r  rk  rN   rO   r      s   

zBlockingConnectionPool.__init__r  r  r  r  Nc              
      sv  t  }zi| j4 I dH U t| j4 I dH 6 | j| jI dH  t| jt| j	 }t  }t
  }t| jt| j	 }||k}	W d  I dH  n1 I dH sSw   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  |	rt| t  | dI dH  tt| t  | d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  )	pool_namer  )r  r  r$  r  r)   r)  r  r  r  r  rj  r  r   r:   r5   r  r+   r,   r   r+  r  )rX   r  r  r  start_time_acquiredr  r  rS   r  r  errrk  rN   rO   r    sL   



*(


z%BlockingConnectionPool.get_connectionrS   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$  rj  r  notifyrW   rk  rN   rO   r  ?  s
   .zBlockingConnectionPool.releaserV   )rI   rJ   rK   r]  rd  r   	LifoQueuer   r
   r;  r   rT   Queuer   r%   r  r  r}  rN   rN   rk  rO   r    s,    #*r  )r   r   enumr   r   sysr  rb  r   abcr   	itertoolsr   typesr   typingr   r   r   r   r	   r
   r   r   r   r   r   r   r   urllib.parser   r   r   r   observability.attributesr   r   r   r   r   utilsr   r  r   r   r   
auth.tokenr    r   r!   r"   eventr#   r$   r%   r&   version_infor)   r  $redis.asyncio.observability.recorderr*   r+   r,   r-   redis.asyncio.retryr.   redis.backoffr/   redis.connectionr0   redis.credentialsr1   r2   redis.exceptionsr3   r4   r5   r6   r7   r8   r9   r:   redis.observability.metricsr;   redis.typingr<   redis.utilsr=   r>   _parsersr?   r@   rA   rB   rC   r?  rC  r@  SYM_LFr>  EnumrH   rM   r   r  rP   rR   r]   ra  rT   rd  r~  r  r  r  r_  r  r  r   r;  r  r&  rL   r  r  r  r  r  rN   rN   rN   rO   <module>   s   
 <
(
     g9S]
5  