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?m@Z@ d dlAmBZB d dlCmDZD d dlEmFZF d dlGmHZHmIZI d dlJmKZKmLZLmMZMmNZNmOZOmPZPmQZQmRZR d dlSmTZT d dlUmVZV d dlWmXZXmYZY ddlZm[Z[m\Z\m]Z]m^Z^m_Z_ dZ`dZadZbdZcdZdG d d! d!ejeZfefjgZheee^e_e]f  eid"< eXrCe]Zjne^ZjG d#d$ d$eZkG d%d& d&eZleekelf ZmG d'd( d(ZnG d)d* d*enZoG d+d, d,eoZpG d-d. d.ZqG d/d0 d0enZrd1Zsd2eet fd3d4Zud5d6 Zveewexexeueueweweuevevexd7Zyeezed8e{f f eid9< G d:d; d;ed<d=Z|d>ezd2e|fd?d@Z}edAdBdCZ~G dDdB dBZG dEdF dFeZd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_count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 rO   rO   W/root/parts/websockify/install/lib/python3.10/site-packages/redis/asyncio/connection.pyrI   d   s    
rI   DefaultParserc                   @      e Zd ZdddZdS )ConnectCallbackProtocol
connectionAbstractConnectionc                 C      d S NrO   selfrT   rO   rO   rP   __call__s   s    z ConnectCallbackProtocol.__call__NrT   rU   rJ   rK   rL   rZ   rO   rO   rO   rP   rS   r       rS   c                   @   rR   )AsyncConnectCallbackProtocolrT   rU   c                       d S rW   rO   rX   rO   rO   rP   rZ   w   s    z%AsyncConnectCallbackProtocol.__call__Nr[   r\   rO   rO   rO   rP   r^   v   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 )rU   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__rc   rd   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`   rf   rg   rh   rj   rk   encodingencoding_errorsdecode_responsesparser_classsocket_read_sizerl   rb   rc   rd   driver_infora   retryri   encoder_classre   rq   event_dispatcherr`   rf   rg   rh   rj   rk   r~   r   r   r   r   rl   rb   r   ra   r   ri   r   re   rq   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),r7   r$   _event_dispatcherr`   rb   r"   r   re   rf   ra   rg   rh   rj   SENTINELappendr;   socketr)   asynciork   r/   r0   r   copydeepcopyupdate_supported_errorsrl   rm   ro   ri   rr   rs   rx   
set_parserru   rv   _re_auth_token_should_reconnectint	TypeErrorr1   
ValueErrorr6   rq   )rY   r`   rf   rg   rh   rj   rk   r~   r   r   r   r   rl   rb   rc   rd   r   ra   r   ri   r   re   rq   r   prO   rO   rP   __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 )Nrs   zunclosed Connection )source)getattrwarnResourceWarningr   get_running_loop_closeRuntimeError)rY   r   rO   rO   rP   __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)rs   closerr   rY   rO   rO   rP   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 )=NrO   .0kvrO   rO   rP   	<genexpr>&  s     z.AbstractConnection.__repr__.<locals>.<genexpr><.(z)>)joinrepr_pieces	__class__rK   rJ   )rY   	repr_argsrO   rO   rP   __repr__%  s    zAbstractConnection.__repr__c                 C   rV   rW   rO   r   rO   rO   rP   r   )     zAbstractConnection.repr_piecesc                 C   s   | j d uo	| jd uS rW   )rr   rs   r   rO   rO   rP   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
WeakMethodru   r   )rY   callbackwmrO   rO   rP   register_connect_callback1  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)ru   remover   r   r   )rY   r   rO   rO   rP   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)rx   rt   )rY   r   rO   rO   rP   r   H  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_healthrO   r   rO   rP   <lambda>U      z,AbstractConnection.connect.<locals>.<lambda>c                    s    j | |dS Nerrorfailure_count
disconnectr   r   rO   rP   r   X  r   Twith_failure_countN)r   call_with_retryr   rO   r   rP   connectP  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_attemptsrY   rO   rP   failure_callbackf  s   zAAbstractConnection.connect_check_health.<locals>.failure_callbackc                            S rW   )_connectrO   r   rO   rP   r   n      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 rO   rO   )r   refrO   rO   rP   
<listcomp>  s    z;AbstractConnection.connect_check_health.<locals>.<listcomp>)r   r   r   r   r   CancelledErrorr   r)   r;   r.   r   OSErrorr6   _error_message	Exceptionri   on_connect_check_healthiscoroutinefunctionr9   r   ru   inspectisawaitable)	rY   r   r   r   eexcr   r   taskrO   r   rP   r   ^  s   




	



	



z'AbstractConnection.connect_check_healthc                 C   
   d| _ d S )NTr   r   rO   rO   rP   mark_for_reconnect     
z%AbstractConnection.mark_for_reconnectc                 C      | j S rW   r   r   rO   rO   rP   should_reconnect     z#AbstractConnection.should_reconnectc                 C   r   )NFr   r   rO   rO   rP   reset_should_reconnect  r   z)AbstractConnection.reset_should_reconnectc                    r_   rW   rO   r   rO   rO   rP   r     s   zAbstractConnection._connectc                 C   rV   rW   rO   r   rO   rO   rP   _host_error  r   zAbstractConnection._host_error	exceptionc                 C   s   t |  |S rW   )r&   r   )rY   r   rO   rO   rP   r        z!AbstractConnection._error_messagec                 C   r   rW   )rq   r   rO   rO   rP   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   rO   rO   rP   
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)rt   r   re   ra   rf   r3   get_credentials_asyncrq   
isinstancerC   r   rD   EXCEPTION_CLASSESlensend_commandread_responsegetr   r6   r5   r?   r4   rb   r   formatted_namerd   r`   rangesumr:   )
rY   r   parser	auth_argscred_providerresponseauth_responselib_name_sentlib_version_sent_rO   rO   rP   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_timeoutrh   rt   on_disconnectr   r   rs   r   wait_closedr   rr   r   r;   r<   HEALTHCHECK_FAILEDERRORr   get_retriesr.   r   r*   APPLICATION_CLOSE)rY   r  r   r   r  r  rO   rO   rP   r   9  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  r6   r   rO   rO   rP   
_send_pingq  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   )rY   r   r   rO   rO   rP   _ping_failedw  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)	rl   r   r   timerm   r   r   r  r  r   rO   rO   rP   r   }  s   
zAbstractConnection.check_healthcommandc                    s"   | j | | j  I d H  d S rW   )rs   
writelinesdrain)rY   r!  rO   rO   rP   _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bytesrg   r   wait_forr$  rs   r"  r#  r;   r   r   r  argsr6   BaseException)rY   r!  r   r   err_noerrmsgrO   rO   rP   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  )rY   r+  r0  rO   rO   rP   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: )rt   can_read_destructiver   r   r   r6   r+  )rY   r   
host_errorrO   rO   rP   r3    s   z'AbstractConnection.can_read_destructive)disconnect_on_errorpush_requestdisable_decodingr)   r5  r6  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'   )r7  r6  )r7  Tr%  zTimeout reading from r2  z : )rg   r   rq   r  rt   r  r   r;   r   r   r6   r+  r,  rl   r   r   rm   r  r:   )
rY   r7  r)   r5  r6  read_timeoutr4  r  r   	next_timerO   rO   rP   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_CRLFrv   mapro   
memoryview
SYM_DOLLARr   )rY   r+  outputbuffbuffer_cutoffarg
arg_lengthrO   rO   rP   r1    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   )rv   r1  r  r  rC  r   r?  r   )	rY   rJ  rE  piecesbuffer_lengthrG  cmdchunkchunklenrO   rO   rP   pack_commands+  s.   

z AbstractConnection.pack_commandsc                 C   s   t | jjdkS )zCheck if the socket is emptyr   )r  rr   _bufferr   rO   rO   rP   _socket_is_emptyI  s   z#AbstractConnection._socket_is_emptyc                    s,   |   s| jddI d H  |   rd S d S )NT)r6  )rR  r  r   rO   rO   rP   process_invalidation_messagesM  s   z0AbstractConnection.process_invalidation_messagestokenc                 C   s
   || _ d S rW   )r   rY   rT  rO   rO   rP   set_re_auth_tokenQ  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   rO   rO   rP   re_authT  s   



zAbstractConnection.re_auth)TTr   NT)FNNF)FN)FrJ   rK   rL   __doc__	__slots__r%   r   rQ   rA   r   r'  r   r
   r<  boollistrI   r   r@   r!   r/   ConnectCallbackTr2   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  r3  r  r=   r   r1  rP  rR  rS  r    rV  r[  rO   rO   rO   rP   rU   }   s4   

	
k


M

u
8

)
:.rU   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   rg  rh  ri  c                   s<   || _ t|| _|| _|pi | _|| _t jdi | d S NrO   )r   r   r   rg  rh  ri  superr   )rY   r   r   rg  rh  ri  r0  r   rO   rP   r   b  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`   rb   )r   r   r`   rb   r   rY   rK  rO   rO   rP   r   s  s   zConnection.repr_piecesr   c                 C   s   | j | jdS )Nr   r   rn  r   rO   rO   rP   _connection_argumentsy  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   rO   )r  rh   r   open_connectionro  rr   rs   	transportget_extra_info
setsockoptr   IPPROTO_TCPTCP_NODELAYrg  
SOL_SOCKETSO_KEEPALIVErh  itemsSOL_TCPr   r   r   )rY   readerwritersockr   r   rO   rO   rP   r   |  s.   (zConnection._connectc                 C   s   | j  d| j S )N:rn  r   rO   rO   rP   r     s   zConnection._host_error)rJ   rK   rL   r^  r'  r   r   r`  r
   r	   r)  r   r   ro  r   r   __classcell__rO   rO   rl  rP   re  _  s,    
re  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ciphersrf   rO   )r   r9   RedisSSLContextrp   rk  r   )rY   r  r  r  r  r  r  r  r  r  r  r  r  r0  rl  rO   rP   r     s"   zSSLConnection.__init__r   c                    s   t   }| j |d< |S )Nssl)rk  ro  rp   r  rY   r0  rl  rO   rP   ro    s   
z#SSLConnection._connection_argumentsc                 C      | j jS rW   )rp   r  r   rO   rO   rP   r       zSSLConnection.keyfilec                 C   r  rW   )rp   r  r   rO   rO   rP   r    r  zSSLConnection.certfilec                 C   r  rW   )rp   r  r   rO   rO   rP   r    r  zSSLConnection.cert_reqsc                 C   r  rW   )rp   r  r   rO   rO   rP   r    r  z"SSLConnection.include_verify_flagsc                 C   r  rW   )rp   r  r   rO   rO   rP   r    r  z"SSLConnection.exclude_verify_flagsc                 C   r  rW   )rp   r  r   rO   rO   rP   r    r  zSSLConnection.ca_certsc                 C   r  rW   )rp   r  r   rO   rO   rP   r    r  zSSLConnection.ca_datac                 C   r  rW   )rp   r  r   rO   rO   rP   r    r  zSSLConnection.check_hostnamec                 C   r  rW   )rp   r  r   rO   rO   rP   r    r  zSSLConnection.min_version)NNr  NNNNNTNNN)rJ   rK   rL   r^  r
   r'  r   r  
VerifyModer   r`  r   r   r	   ro  rd  r  r  r  r  r  r  r  r  r  r~  rO   rO   rl  rP   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  rf   NFr  r  r  r  r  r  r  r  r  r  r  r  rf   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   r9   r  r  r  	CERT_NONEr  r'  CERT_OPTIONALCERT_REQUIREDr  r  r  r  r  r  r  r  r  rf   r  )rY   r  r  r  r  r  r  r  r  r  r  r  rf   	CERT_REQSrO   rO   rP   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  rf   )cafilecapathcadata)r  r  create_default_contextr  r  verify_moder  verify_flagsr  r  r  load_cert_chainrf   r  r  r  load_verify_locationsr  minimum_versionr  set_ciphers)rY   r  flagrO   rO   rP   r  +  s4   



zRedisSSLContext.get)NNNNNNNNFNNN)rJ   rK   rL   r_  r
   r'  r   r  r  r   r`  r   r   r   r  rO   rO   rO   rP   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 rj  )r  rk  r   )rY   r  r0  rl  rO   rP   r   K  s   z#UnixDomainSocketConnection.__init__r   c                 C   s.   d| j fd| jfg}| jr|d| jf |S )Nr  r`   rb   )r  r`   rb   r   rm  rO   rO   rP   r   O  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  rh   r   open_unix_connectionr  rr   rs   r   )rY   rz  r{  rO   rO   rP   r   U  s   (z#UnixDomainSocketConnection._connectc                 C   r   rW   r  r   rO   rO   rP   r   \  r   z&UnixDomainSocketConnection._host_error)rJ   rK   rL   r^  r'  r   r   r   r   r   r   r   r   r~  rO   rO   rl  rP   r  H  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`  )valuerO   rO   rP   to_boolc  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  rO   rO   rP   parse_ssl_verify_flagsk  s   
r  )r`   rg   rh   rg  rj   max_connectionsrl   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 )	ConnectKwargsra   rf   connection_classr   r   r`   r  N)rJ   rK   rL   r'  __annotations__r   rU   r   rO   rO   rO   rP   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.ra   rf   unixr  r  )redisredissr   r   r`   /r  r  zredis://, rediss://, unix://z5Redis URL must specify one of the following schemes ())r   r   queryrx  r  r   r  r  r   r   ra   rf   schemer  r  hostnamer   r   r  AttributeErrorr  )r  parsedr0  name
value_listr  r
  valid_schemesrO   rO   rP   	parse_url  sR   




r  _CPConnectionPool)boundc                   @   s2  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eh dZdd Zdd Zd:ddZdefddZedgdddd;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+ Zd:d,d-Zd=d0d1Zd2e fd3d4Z!d5e"fd6d7Z#de$e%ee&f  fd8d9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.
        NrO   )r  update)r  r  r0  url_optionsrO   rO   rP   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  rA   r   r   Lockrw   r   r$   )rY   r  r  r  rO   rO   rP   r   
  s   

zConnectionPool.__init__>   rf   ra   r  re   c                    sR   d  fdd j D }d jj d jj d jj d jj d| dS )	Nr   c                    s,   g | ]\}}| d | j v rdn| qS )r   z
<REDACTED>)SENSITIVE_REPR_KEYSr   r   rO   rP   r   ,  s    z+ConnectionPool.__repr__.<locals>.<listcomp>r   r   z(<r   z)>)>)r   r  rx  r   rK   rJ   r  )rY   conn_kwargsrO   r   rP   r   *  s   
zConnectionPool.__repr__c                 C   s   t | dr@t | dr@t| j}t| j}|dks|dkr@t| }ddlm} |dkr3||tj| d |dkr@||tj	| d g | _t
 | _d S )Nr  r  r   r+   	pool_nameconnection_statecounter)r  r  r  r  r   redis.observability.recorderr+   r   IDLEUSEDr   WeakSetrY   
idle_countin_use_countr  sync_record_connection_countrO   rO   rP   reset7  s,   

zConnectionPool.resetc                 C   s   zLt | drt | dsW dS t| j}t| j}|dks |dkrGt| }ddlm} |dkr7||tj| d |dkrJ||tj	| d W dS W dS W dS  t
yV   Y dS w )zCClean up connection pool and record metrics when garbage collected.r  r  Nr   r  r  )r  r  r  r  r   r  r+   r   r  r  r   r  rO   rO   rP   r   V  s6   

zConnectionPool.__del__c                 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   rO   rO   rP   can_get_connectionu  s   z!ConnectionPool.can_get_connection*)Use get_connection() without args instead5.3.0rz   r{   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  t| }	|rPt|	t	j
ddI dH  nt|	t	jddI dH  t|	t	j
ddI dH  z| |I dH  |r~t| t | dI dH  |W S  ty   | |I dH   w )z(Get a connected connection from the poolNr   r  r   connection_poolduration_seconds)rw   r  r  r  r   	monotonicget_available_connectionr   r+   r   r  r  ensure_connectionr,   r,  release)
rY   command_namekeysoptionsconnections_beforestart_time_createdrT   connections_after
is_createdr  rO   rO   rP   get_connection|  sR   


(
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  r8   make_connectionaddrX   rO   rO   rP   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 settingsr~   r|   r   r}   r   F)r~   r   r   )r  r   r  r  rO   rO   rP   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.NrO   )r  r  r   rO   rO   rP   r    s   zConnectionPool.make_connectionrT   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   r3  r6   r;   r   r   rX   rO   rO   rP   r    s   

z ConnectionPool.ensure_connectionc                    s~   | j | | r| I dH  | j| | jt|I dH  t	| }t
|tjddI dH  t
|tjddI dH  dS )z(Releases the connection back to the poolNr   r  r   )r  r   r   r   r  r   r   dispatch_asyncr#   r   r+   r   r  r  )rY   rT   r  rO   rO   rP   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 rW   r   )r   rT   rO   rO   rP   r   	  s    z,ConnectionPool.disconnect.<locals>.<genexpr>return_exceptionsTNc                 s   s    | ]
}t |tr|V  qd S rW   )r  r,  )r   rrO   rO   rP   r     s    )r   r  r  r   gathernext)rY   r  connectionsrespr   rO   rO   rP   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)rw   r  r   )rY   connrO   rO   rP   '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   rO   rO   rP   aclose  s   zConnectionPool.acloser   r/   c                 C   s(   | j D ]}||_q| jD ]}||_qd S rW   )r  r   r  )rY   r   r  rO   rO   rP   	set_retry  s
   

zConnectionPool.set_retryrT  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 rW  )r  rY  rZ  rO   )r  rT  rO   rP   r   '  s    z1ConnectionPool.re_auth_callback.<locals>.<lambda>c                    
     | S rW   _mockr   r   rO   rP   r   *     
 c                      r   rW   )r  rO   )r  rO   rP   r   -  r   c                    r  rW   r  r!  r   rO   rP   r   -  r"  )rw   r  r   r   r  rV  rU  rO   )r  rY   rT  rP   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:
        NrO   )rY   r   rO   rO   rP   r   2  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   r  r  r   r  r  r  r  )rY   
attributesfree_connections_attributesin_use_connections_attributesrO   rO   rP   get_connection_count:  s   z#ConnectionPool.get_connection_countr\  rW   r]  )r   r/   r   N)(rJ   rK   rL   r^  classmethodr   r  r'  r  re  rU   r
   r   r   	frozensetr  r   r  r   r`  r  r%   r  r  r  r  r  r  r   r  r  r  r    r#  r9   r   r   r=  dictr(  rO   rO   rO   rP   r    sH    0
	
4	

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  rO   )rk  r   r   	Condition
_conditionr)   )rY   r  r)   r  r/  r  rl  rO   rP   r   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  )r  r   )r   r  r1  r  r)   r*  r  r  r  r  rk  r  r   r;   r6   r  r,   r-   r   r,  r  )rY   r  r  r  start_time_acquiredr  r	  rT   r
  r  errrl  rO   rP   r    sL   



*(


z%BlockingConnectionPool.get_connectionrT   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)r1  rk  r  notifyrX   rl  rO   rP   r    s
   .zBlockingConnectionPool.releaserW   )rJ   rK   rL   r^  re  r   	LifoQueuer   r
   r<  r   rU   Queuer   r%   r  r  r~  rO   rO   rl  rP   r,  P  s,    #*r,  )r   r   enumr   r   sysr   rc  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-   r.   redis.asyncio.retryr/   redis.backoffr0   redis.connectionr1   redis.credentialsr2   r3   redis.exceptionsr4   r5   r6   r7   r8   r9   r:   r;   redis.observability.metricsr<   redis.typingr=   redis.utilsr>   r?   _parsersr@   rA   rB   rC   rD   r@  rD  rA  SYM_LFr?  EnumrI   rN   r   r  rQ   rS   r^   rb  rU   re  r  r  r  r  r`  r  r  r   r<  r  r'  rM   r  r  r  r  r,  rO   rO   rO   rP   <module>   s   
 <
(
     g9S]
5   