o
    Lj                    @   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	Z	d dl
mZ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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-m.Z. e-rd dl/Z/d d
l/m0Z0m1Z1m2Z2 ndZ/dZ1dZ0dZ2ddl3m4Z4 ddl5m6Z6m7Z7 ddl8m9Z9m:Z: ddl,m;Z;m<Z< ej=dkrd dl m>Z? nd dl?m>Z? d dl@mAZAmBZBmCZC d dlDmEZEmFZFmGZGmHZHmIZI d dlJmKZK d dlLmMZM d dlNmOZOmPZP d dlQmRZRmSZSmTZTmUZUmVZVmWZWmXZXmYZY d dlZm[Z[ d dl\m]Z]m^Z^m_Z_m`Z`maZa d dlbmcZc d dldmeZe d dlfmgZgmhZhmiZimjZjmkZk ddllmmZmmnZnmoZompZp ddlqmrZrmsZsmtZtmuZumvZvmwZw dZxdZyd Zzd!Z{d"Z|ee eveweuf  e}d#< ehroeuZ~newZ~G d$d% d%eZG d&d' d'eZe eef ZG d(d) d)ZG d*d+ d+eZG d,d- d-eZG d.d/ d/eZG d0d1 d1ZG d2d3 d3eZd4Zd5ee fd6d7Zd8d9 Zeeeeeeeeeeeeeeeed:Zeeed;ef f e}d<< G d=d> d>ed?d@ZdAed5efdBdCZedDdEdFZG dGdH dHeZG dIdJ dJZG dKdE dEeeZG dLdM dMeZdS )N    N)ABCabstractmethod)chain)MappingProxyType)AnyAsyncIteratorCallableIterableListLiteral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deprecated_function)
SSLContext
TLSVersionVerifyFlags)TokenInterface)
DriverInforesolve_driver_info)!AsyncAfterConnectionReleasedEventEventDispatcher)deprecated_argsformat_error_message)      r+   )timeout)(AsyncMaintNotificationsConnectionHandler"AsyncMaintNotificationsPoolHandler!AsyncOSSMaintNotificationsHandler)record_connection_closedrecord_connection_countrecord_connection_create_timerecord_connection_wait_timerecord_error_count)Retry)	NoBackoff)CredentialProvider"UsernamePasswordCredentialProvider)AuthenticationError$AuthenticationWrongNumberOfArgsErrorConnectionError	DataErrorMaxConnectionsError
RedisErrorResponseErrorTimeoutError)HImportRegistry)MaintenanceStateMaintNotificationsConfigNodeMovingNotification'_build_moving_cleanup_connection_kwargs_build_moving_connection_kwargs)CloseReason)
EncodableT)DEFAULT_RESP_VERSIONHIREDIS_AVAILABLESENTINELcheck_protocol_versionstr_if_bytes)DEFAULT_SOCKET_CONNECT_TIMEOUTDEFAULT_SOCKET_READ_SIZEDEFAULT_SOCKET_TIMEOUT$get_default_socket_keepalive_options)AsyncPushNotificationsParser
BaseParserEncoder_AsyncHiredisParser_AsyncRESP2Parser_AsyncRESP3Parser   *   $s   
   
    DefaultParserc                   @      e Zd ZdddZdS )ConnectCallbackProtocol
connectionAbstractConnectionc                 C      d S N selfr`   rd   rd   V/home/djax/ivt_ai_plugin/venv/lib/python3.10/site-packages/redis/asyncio/connection.py__call__   s    z ConnectCallbackProtocol.__call__Nr`   ra   __name__
__module____qualname__rh   rd   rd   rd   rg   r_          r_   c                   @   r^   )AsyncConnectCallbackProtocolr`   ra   c                       d S rc   rd   re   rd   rd   rg   rh      s    z%AsyncConnectCallbackProtocol.__call__Nri   rj   rd   rd   rd   rg   ro      rn   ro   c                   @   s  e Zd ZdZdZdejddddddfdedB dedB dede	dB de
dB d	edB d
edB dedB dedB ddfddZedefddZdefddZedd ZedededdfddZe		dOddddededB ded edB def
d!d"Zede
dB fd#d$Z						dPdedB de
dB d	edB d
edB dedB dedB ddfd%d&Zdeddfd'd(Zdeddfd)d*Z	dQd+eddfd,d-Z	dQded+eddfd.d/Zde
dB fd0d1Zedefd2d3Z e j!d4eddfd5d3Z d6e	ddfd7d8Z"de#e	 fd9d:Z$d6e	ddfd;d<Z%de#e	 fd=d>Z&dRd?d@Z'	dSdAedB ddfdBdCZ(dedB ddfdDdEZ)e*dFfdGe
e+B dB dHedB ddfdIdJZ,		dTdKedLeddfdMdNZ-dS )U)AsyncMaintNotificationsAbstractConnectionaU  
    Internal mixin for async maintenance notification state and parser handlers.

    The sync implementation uses the same mixin-style structure. The async
    version keeps the notification state and parser handler installation close
    to the connection without sending the server-side handshake; that is wired
    in a later step.
    rd   Nmaint_notifications_config maint_notifications_pool_handlermaintenance_statemaintenance_notification_hashorig_host_addressorig_socket_timeoutorig_socket_connect_timeout'oss_cluster_maint_notifications_handlerparserreturnc
           
      C   s:   || _ || _|| _t | _t | _| ||||||	 d S rc   )rr   rt   ru   set$_processed_start_maint_notifications _skipped_end_maint_notifications$_configure_maintenance_notifications)
rf   rr   rs   rt   ru   rv   rw   rx   ry   rz   rd   rd   rg   __init__   s   z2AsyncMaintNotificationsAbstractConnection.__init__c                 C   rb   rc   rd   rf   rd   rd   rg   _get_parser      z5AsyncMaintNotificationsAbstractConnection._get_parserc                 C   s"   |   }t|ttfstd|S )NLMaintenance notifications are only supported with hiredis and RESP3 parsers!)r   
isinstancerV   rX   r?   )rf   rz   rd   rd   rg   _get_push_notifications_parser   s   zHAsyncMaintNotificationsAbstractConnection._get_push_notifications_parserc                 C   rb   rc   rd   r   rd   rd   rg   get_protocol   r   z6AsyncMaintNotificationsAbstractConnection.get_protocolargskwargsc                    rp   rc   rd   rf   r   r   rd   rd   rg   send_command      z6AsyncMaintNotificationsAbstractConnection.send_commandFTdisconnect_on_errorpush_requestdisable_decodingr-   r   r   c                   rp   rc   rd   )rf   r   r-   r   r   rd   rd   rg   read_response      	z7AsyncMaintNotificationsAbstractConnection.read_responsec                 C   rb   rc   rd   r   rd   rd   rg   getpeername   r   z5AsyncMaintNotificationsAbstractConnection.getpeernamec                 C   s   | j r| j jsd | _d | _d | _d S |stdt|ts&t|ts&td|r4|	 | _| j
|  nd | _t| | j | _|rJ|| _||j nd | _| jrW|| jj || jj |rb|n| j| _|rj|n| j| _|ru|| _d S | j| _d S )NzBTo configure maintenance notifications, a parser must be provided!r   )rr   enabled!_maint_notifications_pool_handler'_maint_notifications_connection_handler(_oss_cluster_maint_notifications_handlerr?   r   rV   rX   get_handler_for_connectionset_connectionr.   "set_oss_cluster_maint_push_handlerhandle_notificationset_node_moving_push_handlerset_maintenance_push_handlerhostrv   socket_timeoutrw   socket_connect_timeoutrx   )rf   rs   rv   rw   rx   ry   rz   rd   rd   rg   r      sb   zNAsyncMaintNotificationsAbstractConnection._configure_maintenance_notificationsc                 C   s`   |  }||  |  }||j || _| js)t| |j| _|	| jj d S |j| j_d S rc   )
r   r   r   r   r   r   r   r.   configr   )rf   rs   %maint_notifications_pool_handler_copyrz   rd   rd   rg   3set_maint_notifications_pool_handler_for_connection2  s$   

z]AsyncMaintNotificationsAbstractConnection.set_maint_notifications_pool_handler_for_connectionc                 C   s^   |   }||j |d  d | _|| _| js(t| |j| _|	| jj d S |j| j_d S rc   )
r   r   r   r   r   r   r   r.   r   r   )rf   ry   rz   rd   rd   rg   6set_maint_notifications_cluster_handler_for_connectionR  s$   

z`AsyncMaintNotificationsAbstractConnection.set_maint_notifications_cluster_handler_for_connectioncheck_healthc                    sf   t | dd }t|  dr)| jr+| jjr-| jr/|d ur1| j| j|dI d H  d S d S d S d S d S d S )Nr   r+   )rr   r   )getattrrM   r   rr   r   r   !_enable_maintenance_notifications)rf   r   r   rd   rd   rg   0activate_maint_notifications_handling_if_enableds  s"   	zZAsyncMaintNotificationsAbstractConnection.activate_maint_notifications_handling_if_enabledc           	   
      s   z9t | dd }|d u rtd||| }| jdddd|j|dI d H  |  I d H }|r4t|dkr8td	W d S  tyj } z$t	|tr^|j
d
kr^dd l}|t}|d|  n W Y d }~d S d }~ww )Nr   zaCannot enable maintenance notifications for connection object that doesn't have a host attribute.CLIENTMAINT_NOTIFICATIONSONzmoving-endpoint-typer   OKz4The server doesn't support maintenance notificationsautor   z,Failed to enable maintenance notifications: )r   
ValueErrorget_endpoint_typer   valuer   rN   r@   	Exceptionr   r   logging	getLoggerrk   debug)	rf   rr   r   r   endpoint_typeresponseer   loggerrd   rd   rg   r     sB   

zKAsyncMaintNotificationsAbstractConnection._enable_maintenance_notificationsc              	   C   s:   z|   }|r
|W S W n ttfy   Y nw t| ddS )a6  
        Extract the resolved IP address from an established connection or host.

        First tries to get the actual peer IP from the async stream writer, then
        falls back to DNS resolution if needed.

        Returns:
            The resolved IP address, or None if it cannot be determined.
        r   N)r   AttributeErrorOSErrorr   )rf   	peer_addrrd   rd   rg   get_resolved_ip  s   z9AsyncMaintNotificationsAbstractConnection.get_resolved_ipc                 C      | j S rc   _maintenance_stater   rd   rd   rg   rt        z;AsyncMaintNotificationsAbstractConnection.maintenance_statestatec                 C   
   || _ d S rc   r   )rf   r   rd   rd   rg   rt        
idc                 C      | j | d S rc   )r}   addrf   r   rd   rd   rg   add_maint_start_notification     zFAsyncMaintNotificationsAbstractConnection.add_maint_start_notificationc                 C   r   rc   )r}   r   rd   rd   rg   !get_processed_start_notifications     zKAsyncMaintNotificationsAbstractConnection.get_processed_start_notificationsc                 C   r   rc   )r~   r   r   rd   rd   rg   add_skipped_end_notification  r   zFAsyncMaintNotificationsAbstractConnection.add_skipped_end_notificationc                 C   r   rc   )r~   r   rd   rd   rg   get_skipped_end_notifications  r   zGAsyncMaintNotificationsAbstractConnection.get_skipped_end_notificationsc                 C   s   | j   | j  d S rc   )r}   clearr~   r   rd   rd   rg   reset_received_notifications  s   
zFAsyncMaintNotificationsAbstractConnection.reset_received_notificationsrelaxed_timeoutc                 C   s    |dkr|n| j }| | d S )N)r   _reschedule_active_read_timeout)rf   r   r-   rd   rd   rg   update_current_socket_timeout  s   zGAsyncMaintNotificationsAbstractConnection.update_current_socket_timeoutc                 C   s   t | dd }|d u rd S |d u r't|dr|d  d S t|dr%|  d S t  | }t|dr;|| d S t|drG|| d S d S )N_active_read_timeout
reschedulerejectupdate)r   hasattrr   r   asyncioget_running_looptimer   )rf   r-   timeout_contextdeadlinerd   rd   rg   r     s    




zIAsyncMaintNotificationsAbstractConnection._reschedule_active_read_timeoutr   tmp_host_addresstmp_relaxed_timeoutc                 C   s2   |r|t krt|| _|dkr|| _|| _dS dS )z\
        SENTINEL keeps the host unchanged. -1 keeps the relaxed timeout unchanged.
        r   N)rL   strr   r   r   )rf   r   r   rd   rd   rg   set_tmp_settings
  s   

z:AsyncMaintNotificationsAbstractConnection.set_tmp_settingsreset_host_addressreset_relaxed_timeoutc                 C   s(   |r| j | _|r| j| _| j| _d S d S rc   )rv   r   rw   r   rx   r   )rf   r   r   rd   rd   rg   reset_tmp_settings  s   z<AsyncMaintNotificationsAbstractConnection.reset_tmp_settingsFN)NNNNNNTr{   Nrc   FF).rk   rl   rm   __doc__	__slots__rC   NONErD   r/   intr   floatr0   rT   r   r   r   rS   r   r   r   r   boolr   r   r   r   r   r   r   r   propertyrt   setterr   r|   r   r   r   r   r   r   rL   objectr   r   rd   rd   rd   rg   rq      s   		



	
T
 
"

( 



rq   c                E   @   s  e Zd ZdZdZeddgddddeed	ed
dd	e	e
ddeeedddeddddddejddddddd!deeB dedB dedB dedB dedeeB dedededee dedededB deeB dB deeB dB deeB dB dedB dedB dedB dee d edB d!edB d"ed#edB d$edB d%edB d&ed'edB d(edB d)edB d*edB d+edB d,edB fBd-d.Ze fd/e!fd0d1Z"d2d3 Z#d4d5 Z$e%d6d7 Z&e'd8d9 Z(d:d; Z)d<d= Z*dee d>dfd?d@Z+d>efdAdBZ,d>edB fdCdDZ-dEdF Z.	ddGedHefdIdJZ/dKdL Z0dMdN Z1dOdP Z2e%dQdR Z3e%d>efdSdTZ4dUe5d>efdVdWZ6dXdY Z7ddZd[Z8dd\d]Z9ddGed>dfd^d_Z:						dd`edae;e< dbe;e dced>df
dddeZ=dfdg Z>dhdi Z?djdk Z@dleAeB d>dfdmdnZC	ddleDeBeeAeB f dGed>dfdodpZEdqe!dre!d>dfdsdtZFeGdudvdwdxd>efdydzZHd>efd{d|ZI			ddd	d}d~ededB dededB fddZJ		dd~ededB fddZKdqeLd>eMeB fddZNdeAeAeL  d>eMeB fddZOdd ZPdd ZQdeRfddZSdd ZTdS )ra   z0Manages communication to and from a Redis server)dbusernameclient_namelib_namelib_versioncredential_providerpasswordr   r   redis_connect_funcretry_on_timeoutretry_on_errorhealth_check_intervalnext_health_checklast_active_atencoderssl_contextprotocol_reader_writer_parserr   _connect_callbacks_buffer_cutoff_lock_socket_read_size__dict__r   r   zbUse 'driver_info' parameter instead. lib_name and lib_version will be removed in a future version.)args_to_warnreasonr   NFutf-8strictT)!r   r   r   r   r   r   encodingencoding_errorsdecode_responsesparser_classsocket_read_sizer   r   r   r   driver_infor   retryr   encoder_classr   r  legacy_responsesevent_dispatcherrr   rs   rt   ru   rv   rw   rx   ry   himport_registryr   r   r   r   r   r   r  r  r  r  r  r   r   r  r   r  r   r  r   r  r  r  rr   rs   rt   ru   rv   rw   rx   ry   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| _|| _ 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|"| _+|| _,|
t-kr| j+d
kr|
t.krt/}
n| j+d	kr|
t/krt.}
| 0|
 |!| _1| 2  t34| |||||||| | j5
 dS )ai  
        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. Explicit None disables CLIENT SETINFO.
        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   r   ip  Fzprotocol must be an integerr   r+   zprotocol must be either 2 or 3)6r=   r(   _event_dispatcherr   r   r&   r  r   r   r   r   r   r   rL   appendrA   socketr-   r   r   r6   r7   r  copydeepcopyupdate_supported_errorsr   r   r   r   r  r  r	  r   r  r  _re_auth_token_should_reconnectr   	TypeErrorrJ   r   r<   r  r  rV   rW   rX   
set_parserr  _reset_himport_staterq   r   r  )#rf   r   r   r   r   r   r   r  r  r  r  r  r   r   r   r   r  r   r  r   r  r   r  r  r  rr   rs   rt   ru   rv   rw   rx   ry   r  prd   rd   rg   r   E  s   <


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 )Nr  zunclosed Connection )source)r   warnResourceWarningr   r   _closeRuntimeError)rf   r'  rd   rd   rg   __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  r   rd   rd   rg   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 )=Nrd   .0kvrd   rd   rg   	<genexpr>  s     z.AbstractConnection.__repr__.<locals>.<genexpr><.(z)>)joinrepr_pieces	__class__rl   rk   )rf   	repr_argsrd   rd   rg   __repr__  s    zAbstractConnection.__repr__c                 C   rb   rc   rd   r   rd   rd   rg   r:    r   zAbstractConnection.repr_piecesc                 C   s   | j d uo	| jd uS rc   )r  r  r   rd   rd   rg   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  r  )rf   callbackwmrd   rd   rg   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@  r   )rf   rA  rd   rd   rg   deregister_connect_callback  s
   z.AbstractConnection.deregister_connect_callbackr{   c                 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)r	  r  )rf   r  rd   rd   rg   r$    s   zAbstractConnection.set_parserc                 C   r   rc   )r  r   rd   rd   rg   r      r   zAbstractConnection._get_parserc                 C   s:   | j }|du r	dS |d}t|tr|rt|d S dS )z:
        Returns the peer name of the connection.
        Npeernamer   )r  get_extra_infor   tupler   )rf   writerrF  rd   rd   rg   r   #  s   
zAbstractConnection.getpeernamec                    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)r   retry_socket_connect)connect_check_healthrd   r   rd   rg   <lambda>4      z,AbstractConnection.connect.<locals>.<lambda>c                    s    j | |dS Nerrorfailure_count
disconnectrO  r   rd   rg   rL  7  rM  Twith_failure_countN)r  call_with_retryr   rd   r   rg   connect/  s   

zAbstractConnection.connectr   rJ  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 rN  rR  rO  actual_retry_attemptsrf   rd   rg   failure_callbackE  s   zAAbstractConnection.connect_check_health.<locals>.failure_callbackc                            S rc   )_connectrd   r   rd   rg   rL  M      z9AbstractConnection.connect_check_health.<locals>.<lambda>TrT  zTimeout connecting to serverr   portF)server_addressserver_portnetwork_peer_addressnetwork_peer_port
error_typeretry_attemptsis_internalr   c                 S   s   g | ]}| r|qS rd   rd   )r2  refrd   rd   rg   
<listcomp>  s    z;AbstractConnection.connect_check_health.<locals>.<listcomp>)r>  r  rV  r\  r   CancelledErrorr  r-   rA   r5   r   r   r<   _error_messager   r   on_connect_check_healthiscoroutinefunctionr?   rS  r  inspectisawaitable)	rf   r   rJ  rZ  r   excrf  rA  taskrd   rX  rg   rK  =  s   




	



	



z'AbstractConnection.connect_check_healthc                 C   
   d| _ d S )NTr"  r   rd   rd   rg   mark_for_reconnect     
z%AbstractConnection.mark_for_reconnectc                 C   r   rc   rq  r   rd   rd   rg   should_reconnect  r   z#AbstractConnection.should_reconnectc                 C   rp  )NFrq  r   rd   rd   rg   reset_should_reconnect  rs  z)AbstractConnection.reset_should_reconnectc                    rp   rc   rd   r   rd   rd   rg   r\    r   zAbstractConnection._connectc                 C   rb   rc   rd   r   rd   rd   rg   _host_error  r   zAbstractConnection._host_error	exceptionc                 C   s   t |  |S rc   )r*   rv  )rf   rw  rd   rd   rg   ri       z!AbstractConnection._error_messagec                 C   r   rc   )r  r   rd   rd   rg   r     r   zAbstractConnection.get_protocolc                 C   s   i | _ d| _d S )Nr   )_himport_prepared_himport_reconciled_revisionr   rd   rd   rg   r%    s   
z'AbstractConnection._reset_himport_statec                    s   | j ddI dH  dS )z=Initialize the connection, authenticate and select a databaseTr   N)rj  r   rd   rd   rg   
on_connect  s   zAbstractConnection.on_connectc           
   	      sD  |    | j|  | j}d }| js| js| jr*| jp"t| j| j}| I d H }|rt| j	drt
| jtrH| t |j| j_| j|  t|dkrTd|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nr|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/t| j	drt
| jtr| t |j| j_| j|  | jd| j	|dI d H  |  I d H }| j|d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r@| jjr@| jddd| jj|dI d H  d}| jrZ| jjrZ| jddd| jj|dI d H  d}| jrj| jd| j|dI d H  tt||gD ]}	z
|  I d H  W qr t y   Y qrw | jrt|  I d H dkrtdd S d S )Nr+   r  defaultr   HELLOAUTHr   Fs   protoprotozInvalid RESP versionr   r   r   zInvalid Username or Passwordr   SETNAMEzError setting client nameSETINFOzLIB-NAMETzLIB-VERSELECTzInvalid Database)!r%  r  r{  r   r   r   r9   get_credentials_asyncrM   r  r   rW   r$  rX   EXCEPTION_CLASSESlenr   r   getr   r<   r;   rN   r:   r   r   r  formatted_namer   r   rangesumr@   )
rf   r   rz   	auth_argscred_providerr   auth_responselib_name_sentlib_version_sent_rd   rd   rg   rj    s   



	z*AbstractConnection.on_connect_check_healthnowaitrP  rQ  health_check_failedc              	      s  |    t du r| j  |   |   dS zet| j4 I dH O | j  |   | j	s>	 W d  I dH  W dS z#z| j
  |sO| j
 I dH  W n	 tyY   Y nw W d| _d| _
nd| _d| _
w W d  I dH  n1 I dH syw   Y  W n tjy   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  n	ttjdI dH  | jtjkr| jdd	 tj| _|   dS dS )
z!Disconnects from the Redis serverNz#Timed out closing connection after r   r^  )r_  r`  ra  rb  rc  rd  )close_reasonrc  )r  T)r   )r%  r   current_taskr  on_disconnectru  r+  async_timeoutr   r>  r  r.  wait_closedr   r  rA   rH   HEALTHCHECK_FAILEDERRORr  get_retriesr5   r   r1   APPLICATION_CLOSErt   rC   MAINTENANCEr   r   r   )rf   r  rP  rQ  r  r  rd   rd   rg   rS  *  sz   




(




	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   rN   r   r<   r   rd   rd   rg   
_send_pingy  s
   zAbstractConnection._send_pingc                    s   | j ||ddI dH  dS )z Function to call when PING failsT)rP  rQ  r  NrR  )rf   rP  rQ  rd   rd   rg   _ping_failed  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/PONGTrT  N)	r   r   r   r   r   r  rV  r  r  r   rd   rd   rg   r     s   
zAbstractConnection.check_healthcommandc                    s"   | j | | j  I d H  d S rc   )r  
writelinesdrain)rf   r  rd   rd   rg   _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. r7  )r>  rK  r   r   r   encodebytesr   r   wait_forr  r  r  r  rA   rS  r   r  r   r<   BaseException)rf   r  r   r   err_noerrmsgrd   rd   rg   send_packed_command  sF   




z&AbstractConnection.send_packed_commandr   r   c                    s(   | j | j| |dddI dH  dS )z+Pack and send a command to the Redis serverr   Tr   N)r  pack_commandr  r   rd   rd   rg   r     s   zAbstractConnection.send_commandz8.0.0zUse can_read() insteadcan_read_destructive)versionr  namec              
      ^   z	| j  I dH W S  ty. } z| jddI dH  |  }td| d|j d}~ww z=Check the socket to see if there's data loaded in the buffer.NTr  Error while reading from z: r  can_readr   rS  rv  r<   r   rf   r   
host_errorrd   rd   rg   r    s   z'AbstractConnection.can_read_destructivec              
      r  r  r  r  rd   rd   rg   r    s   zAbstractConnection.can_readr   r   r-   r   r   c             
      s  |t jkr	d}n	|dur|n| j}|  }zs|dur~t|}|du rW|4 I dH "}|| _z| j||dI dH }	W d| _nd| _w W d  I dH  n1 I dH sQw   Y  n1|4 I dH  | j||dI dH }	W d  I dH  n1 I dH sxw   Y  n
| 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 )a  Read the response from a previously sent command.

        ``timeout`` semantics:
        - ``None`` (default): fall back to ``self.socket_timeout``.
        - ``math.inf``: block indefinitely with no timeout. Used by PubSub
          blocking reads (``listen()`` / ``get_message(timeout=None)`` /
          ``parse_response(block=True)``) where the configured
          ``socket_timeout`` must not abort the read.
        - ``float``: apply that timeout in seconds for this single read.

        TODO(next-major): replace the ``math.inf`` opt-in with a SENTINEL
        default for ``timeout``. After that change, ``timeout=None`` will
        mean "no timeout, block until a response arrives" (matching the
        long-standing PubSub docstring contract) and the SENTINEL default
        will be the value that falls back to ``self.socket_timeout``.
        That swap is a breaking change, so it must wait for a major
        release. Until then, callers that need an indefinitely blocking
        read pass ``math.inf`` explicitly.
        Nr   r   Tr  zTimeout reading from r  z : )mathinfr   rv  r  r   _read_response_from_parserr   rA   rS  r   r<   r   r  r   r   r   r   r   r@   )rf   r   r-   r   r   read_timeoutr  r   active_timeoutr   r   	next_timerd   rd   rg   r     sj   
!(
(
z AbstractConnection.read_responsec                    s8   t | jdr| jj||dI d H S | jj|dI d H S )Nr+   r  )r   )rM   r  r  r   )rf   r   r   rd   rd   rg   r  3  s   z-AbstractConnection._read_response_from_parserc              	   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   r   r   rH  r  split	SYM_EMPTYr9  SYM_STARr  SYM_CRLFr  mapr   
memoryview
SYM_DOLLARr  )rf   r   outputbuffbuffer_cutoffarg
arg_lengthrd   rd   rg   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   )r  r  r  r   r  r  r  r9  )	rf   r  r  piecesbuffer_lengthr  cmdchunkchunklenrd   rd   rg   pack_commandsj  s.   

z AbstractConnection.pack_commandsc                 C   s   t | jjdkS )zCheck if the socket is emptyr   )r  r  _bufferr   rd   rd   rg   _socket_is_empty  s   z#AbstractConnection._socket_is_emptyc                    s,   |   s| jddI d H  |   rd S d S )NT)r   )r  r   r   rd   rd   rg   process_invalidation_messages  s   z0AbstractConnection.process_invalidation_messagestokenc                 C   r   rc   )r!  rf   r  rd   rd   rg   set_re_auth_token  rs  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   rd   rd   rg   re_auth  s   



zAbstractConnection.re_auth)TTr   r   )FNNFr   r   )Urk   rl   rm   r   r   r)   rQ   rO   rL   r]   rP   rU   rC   r   r   r   r   r   listr   r   rT   r%   r6   ConnectCallbackTr8   r(   rD   r/   r0   rB   r   warningsr   r-  r+  r=  r   r:  r   r>  rC  rE  r$  r   r   rW  rK  rr  rt  ru  r\  rv  r  ri  r   r%  r{  rj  r   r   rS  r  r  r   r	   r  r  r   r  r   r    r  r  r   r  rI   r
   r  r  r  r  r$   r  r  rd   rd   rd   rg   ra   $  s   	



 !"#%' 


M


	~
O

)	
[
	.ra   c                       s   e Zd ZdZdddedddedeeB d	ed
eeee	B f e
B dB 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  Tr   )r   r^  socket_keepalivesocket_keepalive_optionssocket_typer   r^  r  r  Nr  c                   sJ   || _ t|| _|| _|tu rt }|pi | _|| _t j	di | dS )a  
        Initialize a TCP connection.

        Parameters
        ----------
        socket_keepalive : bool
            If `True`, TCP keepalive is enabled for TCP socket connections.
        socket_keepalive_options : Mapping[int, int | bytes] | object | None
            Mapping of TCP keepalive socket option constants to values, for
            example `{socket.TCP_KEEPIDLE: 30}`. If left unspecified, redis-py
            uses TCP keepalive defaults when `socket_keepalive` is enabled:
            idle 30 seconds, interval 5 seconds, and 3 probes. Platform-specific
            options that are not available are skipped. Pass `None` or `{}` to
            avoid setting additional TCP keepalive options.
        Nrd   )
r   r   r^  r  rL   rR   r  r  superr   )rf   r   r^  r  r  r  r   r;  rd   rg   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^  r   r   )r   r^  r   r   r  rf   r  rd   rd   rg   r:    s   zConnection.repr_piecesr{   c                 C   s   | j | jdS )Nr   r^  r  r   rd   rd   rg   _connection_arguments  rx  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  rd   )r  r   r   open_connectionr  r  r  	transportrG  
setsockoptr  IPPROTO_TCPTCP_NODELAYr  
SOL_SOCKETSO_KEEPALIVEr  itemsSOL_TCPr   r#  r.  )rf   readerrI  sockr3  r4  rd   rd   rg   r\    s.   (zConnection._connectc                 C   s   | j  d| j S )N:r  r   rd   rd   rg   rv    s   zConnection._host_error)rk   rl   rm   r   rL   r   r   r   r   r  r   r   r:  r  r\  rv  __classcell__rd   rd   r  rg   r    s,    "r  c                       s$  e Zd ZdZ												d)dee dee deeejf dee	d	  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ciphersr   rd   )r   r?   RedisSSLContextr  r  r   )rf   r  r  r  r  r  r   r  r  r  r  r  r  r   r  rd   rg   r     s"   zSSLConnection.__init__r{   c                    s   t   }| j |d< |S )Nssl)r  r  r  r  rf   r   r  rd   rg   r    s   
z#SSLConnection._connection_argumentsc                 C      | j jS rc   )r  r  r   rd   rd   rg   r       zSSLConnection.keyfilec                 C   r  rc   )r  r	  r   rd   rd   rg   r	    r  zSSLConnection.certfilec                 C   r  rc   )r  r
  r   rd   rd   rg   r
    r  zSSLConnection.cert_reqsc                 C   r  rc   )r  r  r   rd   rd   rg   r  "  r  z"SSLConnection.include_verify_flagsc                 C   r  rc   )r  r  r   rd   rd   rg   r  &  r  z"SSLConnection.exclude_verify_flagsc                 C   r  rc   )r  r  r   rd   rd   rg   r  *  r  zSSLConnection.ca_certsc                 C   r  rc   )r  r  r   rd   rd   rg   r  .  r  zSSLConnection.ca_datac                 C   r  rc   )r  r  r   rd   rd   rg   r  2  r  zSSLConnection.check_hostnamec                 C   r  rc   )r  r  r   rd   rd   rg   r  6  r  zSSLConnection.min_version)NNr  NNNNNTNNN)rk   rl   rm   r   r   r   r   r  
VerifyModer
   r   r"   r   r   r  r   r  r	  r
  r  r  r  r  r  r  r  rd   rd   r  rg   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  r   NFr  r	  r
  r  r  r  r  r  r  r  r  r  r   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   r?   r  r	  r  	CERT_NONEr   r   CERT_OPTIONALCERT_REQUIREDr
  r  r  r  r  r  r  r  r  r   r  )rf   r  r	  r
  r  r  r  r  r  r  r  r  r   	CERT_REQSrd   rd   rg   r   L  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  r   )cafilecapathcadata)r  r  create_default_contextr  r
  verify_moder  verify_flagsr  r	  r  load_cert_chainr   r  r  r  load_verify_locationsr  minimum_versionr  set_ciphers)rf   r  flagrd   rd   rg   r  {  s4   



zRedisSSLContext.get)NNNNNNNNFNNN)rk   rl   rm   r   r   r   r   r  r  r
   r   r"   r   r!   r  rd   rd   rd   rg   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 )Nrd   )r.  r  r   )rf   r.  r   r  rd   rg   r     s   z#UnixDomainSocketConnection.__init__r{   c                 C   s.   d| j fd| jfg}| jr|d| jf |S )Nr.  r   r   )r.  r   r   r  r  rd   rd   rg   r:    s   z&UnixDomainSocketConnection.repr_piecesc              	      sv   t | j4 I d H  tj| jdI d H \}}W d   I d H  n1 I d H s'w   Y  || _|| _|  I d H  d S )Nr-  )r  r   r   open_unix_connectionr.  r  r  r{  )rf   r  rI  rd   rd   rg   r\    s   (z#UnixDomainSocketConnection._connectc                 C   r   rc   r-  r   rd   rd   rg   rv    r   z&UnixDomainSocketConnection._host_error)rk   rl   rm   r   r   r   r	   r   r   r   r:  r\  rv  r  rd   rd   r  rg   r+    s    "r+  )0FFALSENNOr{   c                 C   s6   | d u s| dkr
d S t | tr|  tv rdS t| S )Nr,  F)r   r   upperFALSE_STRINGSr   )r   rd   rd   rg   to_bool  s
   r7  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  stripr   r#   r   r  r   )r   verify_flags_strr%  r*  rd   rd   rg   parse_ssl_verify_flags  s   
r=  )r   r   r   r  r  r   max_connectionsr   r  r  r  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   r   connection_classr   r^  r   r.  N)rk   rl   rm   r   __annotations__r   ra   r   rd   rd   rd   rg   r@    s   
 r@  F)totalurlc              
   C   sx  t | }i }t|j D ]5\}}|rBt|dkrB|d }t|}|r>z||||< W q ttfy=   td| dw |||< q|j	rMt
|j	|d< |jrWt
|j|d< |jdkrl|jrft
|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   r   unixr.  rA  )redisredissr   r^  r   /r,  rG  zredis://, rediss://, unix://z5Redis URL must specify one of the following schemes ())r   r   queryr  r  r?  r  r#  r   r   r   r   schemer.  r+  hostnamer^  r   r:  r   r  )rD  parsedr   r  
value_listr   rz   valid_schemesrd   rd   rg   	parse_url  sR   




rP  _CPConnectionPool)boundc                   @   s   e Zd Zedd Zed&ddZeedgdd	d
	d'dee de	de	ddfddZ
ed(ddZed)ddZed*deddfddZed&ddZed+dd Zed!eddfd"d#Zedeeeef  fd$d%ZdS ),ConnectionPoolInterfacec                 C   rb   rc   rd   r   rd   rd   rg   r   $  r   z$ConnectionPoolInterface.get_protocolr{   Nc                 C   rb   rc   rd   r   rd   rd   rg   reset(  r   zConnectionPoolInterface.reset*)Use get_connection() without args instead5.3.0r  r  r  command_namekeysoptionsra   c                    rp   rc   rd   )rf   rZ  r[  r\  rd   rd   rg   get_connection,  r   z&ConnectionPoolInterface.get_connectionrU   c                 C   rb   rc   rd   r   rd   rd   rg   get_encoder7  r   z#ConnectionPoolInterface.get_encoderr`   c                    rp   rc   rd   re   rd   rd   rg   release;  r   zConnectionPoolInterface.releaseTinuse_connectionsc                    rp   rc   rd   )rf   r`  rd   rd   rg   rS  ?  r   z"ConnectionPoolInterface.disconnectc                    rp   rc   rd   r   rd   rd   rg   acloseC  r   zConnectionPoolInterface.acloser  r6   c                 C   rb   rc   rd   )rf   r  rd   rd   rg   	set_retryG  r   z!ConnectionPoolInterface.set_retryr  c                    rp   rc   rd   r  rd   rd   rg   re_auth_callbackK  r   z(ConnectionPoolInterface.re_auth_callbackc                 C   s   dS )D
        Returns a connection count (both idle and in use).
        Nrd   r   rd   rd   rg   get_connection_countO  s   z,ConnectionPoolInterface.get_connection_countr   rc   )r{   rU   )r`   ra   r{   Nr   r  r6   r{   N)rk   rl   rm   r   r   rU  r)   r   r   r   r]  r^  r_  r   rS  ra  rb  r$   rc  r
   r   r   dictre  rd   rd   rd   rg   rT  #  sF    
 rT  c                   @   sP  e Zd ZdZ		dRdedB dddeddfdd	ZdSd
dZee	de
eef fddZeje	de
eef ddfddZe	dejfddZe	ded fddZe	ded fddZdefddZdefddZdd Z	dTdededB ddfddZ		dRdedB dedB ddfd d!Z		dRdedB dedB ddfd"d#Z	$		dUd%dd&ed'edB d(edB def
d)d*Z					+	+	+dVd%d,d-edB d.edB d/edB d0e dB d1ed2ed3eddfd4d5Z!							$	+	+	+	6dWd-edB d.edB d/edB d0e dB d'edB d(edB d&e"d7 d1ed2ed3ed8eddfd9d:Z#							$	+	+	+	6dWd-edB d.edB d/edB d0e dB d'edB d(edB d&e"d7 d1ed2ed3ed8eddfd;d<Z$deddfd=d>Z%	+dXd?e&d@edAedB dBeddf
dCdDZ'	dTdAedB ddfdEdFZ(	dTdAedB ddfdGdHZ)dIed3ed2eddfdJdKZ*dLed ddfdMdNZ+dOeddfdPdQZ,dS )Y-AsyncMaintNotificationsAbstractConnectionPoola,  
    Internal mixin for async maintenance notification pool wiring.

    The handler owns notification policy.
    This mixin owns pool state mutation because `_available_connections`,
    `_in_use_connections`, `connection_kwargs`, and the non-reentrant `asyncio.Lock`
    all live on the pool.
    Nrr   ry   z(AsyncOSSMaintNotificationsHandler | Noner   r{   c           	      K   s  | d}t|d}|  }|d u r|r|rt }|rz|jrz|sQ|jdu rId| jv r.td|  sEt| dd }t|d|}td| td	d | _	d | _
d S |sWtd
|rh|| _
| j| j
d d | _	d S d | _
t| || _	| j| j	d d S d | _	d | _
d S )Nr  r+   Tr.  NMaintenance notifications are not supported for Unix domain socket connectionsrA  rk   AMaintenance notifications are not supported for connection class JMaintenance notifications are not supported for connections without a hostzWMaintenance notifications handlers on connection are only supported with RESP version 3)ry   )rs   )r  rM   $_maintenance_notifications_supportedrD   r   connection_kwargsr?   5_maintenance_notifications_connection_class_supportedr   r   r   1_update_connection_kwargs_for_maint_notificationsr/   )	rf   rr   ry   r   r  is_protocol_supportedis_connection_supportedrA  connection_class_namerd   rd   rg   r   a  sf   







z6AsyncMaintNotificationsAbstractConnectionPool.__init__c                    s$   | j dur| j  I dH  dS dS )zGHook invoked from the pool's ``aclose()`` before the pool is shut down.N)r   cancel_scheduled_tasksr   rd   rd   rg   	_on_close  s   
z7AsyncMaintNotificationsAbstractConnectionPool._on_closec                 C   rb   rc   rd   r   rd   rd   rg   rm       z?AsyncMaintNotificationsAbstractConnectionPool.connection_kwargsr   c                 C   rb   rc   rd   rf   r   rd   rd   rg   rm    ru  c                 C   rb   rc   rd   r   rd   rd   rg   _get_pool_lock  r   z<AsyncMaintNotificationsAbstractConnectionPool._get_pool_lockra   c                 C   rb   rc   rd   r   rd   rd   rg   _get_free_connections  r   zCAsyncMaintNotificationsAbstractConnectionPool._get_free_connectionsc                 C   rb   rc   rd   r   rd   rd   rg   _get_in_use_connections  r   zEAsyncMaintNotificationsAbstractConnectionPool._get_in_use_connectionsc                 C   s*   d| j v rdS |  sdS t| j dS )Nr.  Fr   )rm  rn  r   r  r   rd   rd   rg   rl    s
   
zRAsyncMaintNotificationsAbstractConnectionPool._maintenance_notifications_supportedc                 C   s:   t | dd }|d u rdS zt|tW S  ty   Y dS w )NrA  F)r   
issubclassrq   r#  )rf   rA  rd   rd   rg   rn    s   zcAsyncMaintNotificationsAbstractConnectionPool._maintenance_notifications_connection_class_supportedc                 C   s,   | j r| j j}n	| jr| jjnd}|o|jS )a  
        Returns:
            True if the maintenance notifications are enabled, False otherwise.
            The maintenance notifications config is stored in the pool handler.
            If the pool handler is not set, the maintenance notifications are not enabled.
        N)r   r   r   r   )rf   rr   rd   rd   rg   maint_notifications_enabled  s   

zIAsyncMaintNotificationsAbstractConnectionPool.maint_notifications_enabledc                    s   |   r|jstd|r|| _d| _nK|jrJ|  sJ|jdu rEd| jv r*td|  sAt	| dd}t	|d|}td| td	d| _dS | jrR|| j_
n| js\t| || _n|| j_
| j| j| jd
 | j| j| jd
I dH  dS )a#  
        Updates the maintenance notifications configuration.
        This method should be called only if the pool was created
        without enabling the maintenance notifications and
        in a later point in time maintenance notifications
        are requested to be enabled.
        z<Cannot disable maintenance notifications after enabling themNTr.  ri  rA  rk   rj  rk  )rs   ry   )r{  r   r   r   r   rl  rm  r?   rn  r   r   r/   ro  3_update_maint_notifications_configs_for_connections)rf   rr   ry   rA  rr  rd   rd   rg   !update_maint_notifications_config  sh   

zOAsyncMaintNotificationsAbstractConnectionPool.update_maint_notifications_configrs   c                 C   s   |   sdS |r| j||jd |r%| j||jd | jdd | jdddu rH| j| jd| jdt| jdtd	 dS dS )
zJ
        Update the connection kwargs for all future connections.
        N)rs   rr   )ry   rr   rs   rv   r   r   r   )rv   rw   rx   )r{  rm  r   r   popr  rQ   rO   )rf   rs   ry   rd   rd   rg   ro  J  s6   	
z_AsyncMaintNotificationsAbstractConnectionPool._update_connection_kwargs_for_maint_notificationsc              	      s   |   4 I dH a t|  D ]%}|r|| |j|_n|r*|| |j|_ntd| I dH  qt| 	 D ]"}|rJ|| |j|_n|rV|| |j|_ntd|
  q<W d  I dH  dS 1 I dH spw   Y  dS )zLUpdate the maintenance notifications config for all connections in the pool.Nz^Either maint_notifications_pool_handler or oss_cluster_maint_notifications_handler must be set)rw  r  rx  r   r   rr   r   r   rS  ry  rr  )rf   rs   ry   connrd   rd   rg   r|  |  sL   

.zaAsyncMaintNotificationsAbstractConnectionPool._update_maint_notifications_configs_for_connectionsconnected_addressr  matching_patternmatching_addressmatching_notification_hashc                 C   s`   |dkr|r|  |krdS dS |dkr|r|j|krdS dS |dkr.|dur.|j|kr.dS dS )z[
        Check if the connection should be updated based on the matching criteria.
        r  Fconfigured_addressnotification_hashNT)r   r   ru   )rf   r  r  r  r  rd   rd   rg   _should_update_connection  s   


zGAsyncMaintNotificationsAbstractConnectionPool._should_update_connectionFrq   r   ru   host_addressr   update_notification_hashr   r   c	           	      C   s`   |r||_ |r
||_|dur|j|d |dur|j|d |s"|r)|j||d || dS )z>
        Update the settings for a single connection.
        N)r   )r   )r   r   )rt   ru   r   r   r   )	rf   r  r   ru   r  r   r  r   r   rd   rd   rg   update_connection_settings  s   zHAsyncMaintNotificationsAbstractConnectionPool.update_connection_settingsT)r  r  r  include_free_connectionsc                    sd   |   4 I dH  | j|||||||||	|
|d W d  I dH  dS 1 I dH s+w   Y  dS )a  
        Update the settings for all matching connections in the pool.

        This method does not create new connections.
        This method does not affect the connection kwargs.

        :param state: The maintenance state to set for the connection.
        :param maintenance_notification_hash: The hash of the maintenance notification
                                               to set for the connection.
        :param host_address: The host address to set for the connection.
        :param relaxed_timeout: The relaxed timeout to set for the connection.
        :param matching_address: The address to match for the connection.
        :param matching_notification_hash: The notification hash to match for the connection.
        :param matching_pattern: The pattern to match for the connection.
        :param update_notification_hash: Whether to update the notification hash for the connection.
        :param reset_host_address: Whether to reset the host address to the original address.
        :param reset_relaxed_timeout: Whether to reset the relaxed timeout to the original timeout.
        :param include_free_connections: Whether to include free/available connections.
        N)r   ru   r  r   r  r  r  r  r   r   r  )rw  ,_update_connections_settings_without_locking)rf   r   ru   r  r   r  r  r  r  r   r   r  rd   rd   rg   update_connections_settings  s    #.zIAsyncMaintNotificationsAbstractConnectionPool.update_connections_settingsc                 C   s|   |   D ]}| ||||r| j|||||||	|
d q|r:|  D ]}| ||||r9| j|||||||	|
d q"dS dS )a-  
        Update matching connections while the caller already holds the pool lock.

        This helper intentionally does not acquire the pool lock so callers can
        compose several pool mutations inside one critical section without
        deadlocking the non-reentrant `asyncio.Lock`.
        )r   ru   r  r   r  r   r   N)ry  r  r  rx  )rf   r   ru   r  r   r  r  r  r  r   r   r  r  rd   rd   rg   r  '	  sN   zZAsyncMaintNotificationsAbstractConnectionPool._update_connections_settings_without_lockingc                 K   s   | j | dS )z
        Update the connection kwargs for all future connections.

        This method updates the connection kwargs for all future connections created by the pool.
        Existing connections are not affected.
        N)rm  r   r  rd   rd   rg   update_connection_kwargsc	  s   zFAsyncMaintNotificationsAbstractConnectionPool.update_connection_kwargsnotificationr   moving_address_srcrun_proactive_reconnectc                    s   |   4 I dH F | d z.| jtjt||j|j|dddd |r,| |I dH  | j	di t
|| W | d n| d w W d  I dH  dS 1 I dH sUw   Y  dS )a  
        Apply the pool state transition for a MOVING notification atomically.

        Async pools use a non-reentrant `asyncio.Lock`, so the handler cannot
        safely compose several separately locked calls. Existing connection
        updates, optional proactive reconnect, and future `connection_kwargs`
        changes must happen under one pool-owned lock; otherwise a connection
        can move between active/free lists and escape handling.
        NTr  )r   ru   r   r  r  r  r  r  Frd   )rw  _set_in_maintenancer  rC   MOVINGhashr   new_node_host(_run_proactive_reconnect_without_lockingr  rG   )rf   r  r   r  r  rd   rd   rg   apply_moving_notificationl	  s.   

.zGAsyncMaintNotificationsAbstractConnectionPool.apply_moving_notificationc              	      sT   |   4 I dH  | |I dH  W d  I dH  dS 1 I dH s#w   Y  dS )ab  
        Mark active connections and disconnect free connections atomically.

        This operation is pool-owned because the active/free lists can change
        while tasks acquire or release connections. Keeping the mark/disconnect
        pass under one lock avoids a connection moving between lists between
        separately locked calls.
        N)rw  r  )rf   r  rd   rd   rg   r  	  s   .zEAsyncMaintNotificationsAbstractConnectionPool.run_proactive_reconnectc                    sR     D ]}|d r|  q fdd D }|I dH  dS )a  
        Mark and disconnect matching connections while the caller holds the pool lock.

        This helper intentionally does not acquire the pool lock so it can be
        reused by larger atomic operations that already hold the non-reentrant
        `asyncio.Lock`.
        r  c                    s   g | ]} |d  r|qS )r  )r  )r2  r  r  rf   rd   rg   rg  	  s    zjAsyncMaintNotificationsAbstractConnectionPool._run_proactive_reconnect_without_locking.<locals>.<listcomp>N)ry  r  rr  rx  _disconnect_connections)rf   r  r  free_connectionsrd   r  rg   r  	  s   zVAsyncMaintNotificationsAbstractConnectionPool._run_proactive_reconnect_without_lockingr  c                    s   |   4 I dH - t| j|}|dur| jdi | | jdtjd|dd||dd	 W d  I dH  dS 1 I dH s<w   Y  dS )ah  
        Revert MOVING pool state atomically after the notification TTL.

        Future connection kwargs and existing connection state must be cleaned
        up in the same critical section. Splitting the cleanup lets an
        acquire/release interleave, which can leave stale MOVING state or undo a
        newer overlapping MOVING notification.
        Nr   r  T)	r   r   ru   r  r  r  r   r   r  rd   )rw  rF   rm  r  r  rC   r   )rf   r  r   r   r   rd   rd   rg   cleanup_moving_notification	  s&   .zIAsyncMaintNotificationsAbstractConnectionPool.cleanup_moving_notificationconnectionsc                    sR   t |}|s	d S tjdd |D ddiI d H }tdd |D d }|r'|d S )Nc                 s       | ]}|  V  qd S rc   rR  r2  r`   rd   rd   rg   r5  	      zXAsyncMaintNotificationsAbstractConnectionPool._disconnect_connections.<locals>.<genexpr>return_exceptionsTc                 s       | ]
}t |tr|V  qd S rc   r   r  )r2  resultrd   rd   rg   r5  	      )rH  r   gathernext)rf   r  resultsrn  rd   rd   rg   r  	  s   zEAsyncMaintNotificationsAbstractConnectionPool._disconnect_connectionsin_maintenancec                 C   s$   t | dd}t|r|| dS dS )zLFlip the pool's maintenance flag if it exposes one (BlockingConnectionPool).set_in_maintenanceN)r   callable)rf   r  r  rd   rd   rg   r  	  s   zAAsyncMaintNotificationsAbstractConnectionPool._set_in_maintenance)NNr   rc   )r  NN)NNNNFFF)NNNNNNr  FFFT)F)-rk   rl   rm   r   rD   r   r   rt  r   r   rg  r   rm  r   r   Lockrw  r	   rx  ry  r   rl  rn  r{  r0   r}  r/   ro  r|  r   r  rC   r   r  r   r  r  r  rE   r  r  r  r  r  r  rd   rd   rd   rg   rh  W  s   

M
`
6
A
	

%
4
<
.


!
rh  c                   @   s  e Zd ZdZedee dedefddZe	ddfdee
 d	ee d
edB fddZeh dZedhZdd Zedeeef fddZejdeeef ddfddZdejfddZdee
 fddZdee
 fddZdd Zdd ZdMdd Z de!fd!d"Z"e#d#gd$d%d&dNd'd(Z$d)d* Z%d+d, Z&d-d. Z'd/e
fd0d1Z(d/e
fd2d3Z)dOd5e!fd6d7Z*d8d9 Z+dMd:d;Z,d<edefd=d>Z-dMd?d@Z.dPdCdDZ/dEe0fdFdGZ1dHe2fdIdJZ3de4e5eef  fdKdLZ6dS )QrR  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``.
    clsrD  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.
        Nrd   )rP  r   )r  rD  r   url_optionsrd   rd   rg   from_url

  s   +
zConnectionPool.from_urlNrA  r>  rr   c                 K   s   |pd}t |tr|dk rtd|| _|| _|| _|d}|d u r*t }||d< || _g | _	t
 | _| jdt| _t | _| jdd | _| jd u rRt | _tj| fd|i| d S )Nd   r   z,"max_connections" must be a positive integerr  r  r  rr   )r   r   r   rA  _connection_kwargsr>  r  rB   r  _available_connectionsr|   _in_use_connectionsrm  rU   r  r   r  r  r  r(   rh  r   )rf   rA  r>  rr   rm  r  rd   rd   rg   r   9
  s2   
	


zConnectionPool.__init__>   r   r   r  r   r  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                    s6   g | ]\}}| j vr| d | jv rdn| qS )r0  z
<REDACTED>)OMIT_REPR_KEYSSENSITIVE_REPR_KEYSr1  r   rd   rg   rg  r
  s
    
z+ConnectionPool.__repr__.<locals>.<listcomp>r6  r7  z(<r8  z)>)>)r9  rm  r  r;  rl   rk   rA  )rf   conn_kwargsrd   r   rg   r=  p
  s   
zConnectionPool.__repr__c                 C   r   rc   r  r   rd   rd   rg   rm  ~
  r   z ConnectionPool.connection_kwargsr   c                 C   r   rc   r  rv  rd   rd   rg   rm  
  r   c                 C   r   rc   )r  r   rd   rd   rg   rw  
  r   zConnectionPool._get_pool_lockc                 C   r   rc   )r  r   rd   rd   rg   rx  
  r   z$ConnectionPool._get_free_connectionsc                 C   r   rc   )r  r   rd   rd   rg   ry  
  r   z&ConnectionPool._get_in_use_connectionsc                 C   s   | j ddS )z
        Returns:
            The RESP protocol version, or ``None`` if the protocol is not specified,
            in which case the server default will be used.
        r  N)rm  r  r   rd   rd   rg   r   
  s   zConnectionPool.get_protocolc                 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   r2   	pool_nameconnection_statecounter)r   r  r  r  r   redis.observability.recorderr2   r   IDLEUSEDr?  WeakSetrf   
idle_countin_use_countr  sync_record_connection_countrd   rd   rg   rU  
  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  r2   r   r  r  r   r  rd   rd   rg   r-  
  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   rd   rd   rg   can_get_connection
  s   z!ConnectionPool.can_get_connectionrV  rW  rX  rY  c           
   	      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)r  r  r  r  r   	monotonicget_available_connectionr   r2   r   r  r  ensure_connectionr3   r  r_  )
rf   rZ  r[  r\  connections_beforestart_time_createdr`   connections_after
is_createdr  rd   rd   rg   r]  
  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  r~  
IndexErrorr  r  r>  r>   make_connectionr   re   rd   rd   rg   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  )rm  r  r  r  rd   rd   rg   r^     s   


zConnectionPool.get_encoderc                 C   s   | j di | jS )z=Create a new connection.  Can be overridden by child classes.Nrd   )rA  rm  r   rd   rd   rg   r  )  s   zConnectionPool.make_connectionr`   c              
      s   |  I dH  z| I dH r|  stddW dS W dS  tttfyL   | I dH  |  I dH  | I dH rF|  sItddY dS Y dS w )z8Ensure that the connection object is connected and validNzConnection has datazConnection not ready)rW  r  r{  r<   rA   r   rS  re   rd   rd   rg   r  /  s   

z ConnectionPool.ensure_connectionc              	      s   | j 4 I dH " | j| | r| I dH  | j| W d  I dH  n1 I dH s0w   Y  | 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  rD  rt  rS  r  r  r  dispatch_asyncr'   r   r2   r   r  r  )rf   r`   r  rd   rd   rg   r_  ?  s*   (
zConnectionPool.releaseTr`  c                    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   r  rc   rR  r  rd   rd   rg   r5  k  r  z,ConnectionPool.disconnect.<locals>.<genexpr>r  TNc                 s   r  rc   r  )r2  rrd   rd   rg   r5  o  r  )r   r  r  r   r  r  )rf   r`  r  resprn  rd   rd   rg   rS  \  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)r  r  rr  )rf   r  rd   rd   rg   'update_active_connections_for_reconnects  s   

.z6ConnectionPool.update_active_connections_for_reconnectc                    s"   |   I dH  |  I dH  dS )z-Close the pool, disconnecting all connectionsN)rt  rS  r   rd   rd   rg   ra  {  s   zConnectionPool.acloserf   c                    s   | S rc   rd   r   rd   rd   rg   
__aenter__  s   zConnectionPool.__aenter__c                    s   |   I d H  d S rc   )ra  )rf   exc_type	exc_value	tracebackrd   rd   rg   	__aexit__  s   zConnectionPool.__aexit__r  r6   c                 C   s(   | j D ]}||_q| jD ]}||_qd S rc   )r  r  r  )rf   r  r  rd   rd   rg   rb    s
   

zConnectionPool.set_retryr  c              	      s   j 4 I d H B jD ]'  j fddfddI d H   j fddfddI d H  qjD ]   q7W d   I d H  d S 1 I d H sPw   Y  d S )Nc                      s     dd S r  )r   r  r  rd   )r  r  rd   rg   rL    s    z1ConnectionPool.re_auth_callback.<locals>.<lambda>c                    
     | S rc   _mockrP  r   rd   rg   rL       
 c                      r[  rc   )r   rd   )r  rd   rg   rL    r]  c                    r  rc   r  r  r   rd   rg   rL    r  )r  r  r  rV  r  r  r  rd   )r  rf   r  rg   rc    s   



.zConnectionPool.re_auth_callbackrP  c                    s   dS )z
        Dummy functions, needs to be passed as error callback to retry object.
        :param error:
        :return:
        Nrd   )rf   rP  rd   rd   rg   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 )rd  )r   build_base_attributesr   r   r  r   r  r   r   r  r  r  r  )rf   
attributesfree_connections_attributesin_use_connections_attributesrd   rd   rg   re    s   z#ConnectionPool.get_connection_countr   rc   r   rf  )7rk   rl   rm   r   classmethodr   rQ  r   r  r  ra   r   r   rD   r   	frozensetr  r  r=  r   rg  r   rm  r   r   r  rw  r	   rx  ry  r   rU  r-  r   r  r)   r]  r  r^  r  r  r_  rS  r  ra  r  r  rb  r$   rc  r?   r  r
   rH  re  rd   rd   rd   rg   rR  	  sd    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d
eddfddZejded 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-   rA  queue_classc                    s2   t  jd||d| t | _|| _d| _d S )N)rA  r>  Frd   )r  r   r   	Condition
_conditionr-   _in_maintenance)rf   r>  r-   rA  r  rm  r  rd   rg   r     s   

zBlockingConnectionPool.__init__r  r{   Nc                 C   s
   || _ dS )a  
        Toggle the pool's maintenance mode.

        While maintenance mode is on, ``get_connection`` and ``release``
        serialize their pool mutations through ``self._lock`` so they cannot
        interleave with a MOVING notification handler that is currently
        rewriting pool state under the same lock. Outside of maintenance the
        mutations skip the lock, since their critical sections are pure-Python
        and already atomic under asyncio's single-threaded scheduling.
        N)r  )rf   r  rd   rd   rg   r    s   
z)BlockingConnectionPool.set_in_maintenancec              	   C  sX   | j r'| j4 I d H  d V  W d   I d H  d S 1 I d H s w   Y  d S d V  d S rc   )r  r  r   rd   rd   rg   _maybe_pool_lock  s   .
z'BlockingConnectionPool._maybe_pool_lockrV  rW  rX  rY  c                    s  t  }z| j4 I dH s t| j4 I dH T | j| jI dH  |  4 I dH , t| j	t| j
 }t  }t  }t| j	t| j
 }||k}	W d  I dH  n1 I dH s\w   Y  W d  I dH  n1 I dH sqw   Y  W d  I dH  n1 I dH sw   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  r  r  r-   r  r  r  r  r  r  r  r  r   rA   r<   r  r3   r4   r   r  r_  )rf   rZ  r[  r\  start_time_acquiredr  r  r`   r  r  errr  rd   rg   r]    sP   



**(


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_  notifyre   r  rd   rg   r_  1  s
   .zBlockingConnectionPool.releaserc   )rk   rl   rm   r   r  r   	LifoQueuer   r   r   r   ra   Queuer   r   r  
contextlibasynccontextmanagerr   r  r)   r]  r_  r  rd   rd   r  rg   r    s2    #+r  )r   r  r  rl  r  r  sysr   r  r?  abcr   r   	itertoolsr   typesr   typingr   r   r   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"   r#   
auth.tokenr$   r  r%   r&   eventr'   r(   r)   r*   version_infor-   r  !redis.asyncio.maint_notificationsr.   r/   r0   $redis.asyncio.observability.recorderr1   r2   r3   r4   r5   redis.asyncio.retryr6   redis.backoffr7   redis.credentialsr8   r9   redis.exceptionsr:   r;   r<   r=   r>   r?   r@   rA   redis.himportrB   redis.maint_notificationsrC   rD   rE   rF   rG   redis.observability.metricsrH   redis.typingrI   redis.utilsrJ   rK   rL   rM   rN   	_defaultsrO   rP   rQ   rR   _parsersrS   rT   rU   rV   rW   rX   r  r  r  SYM_LFr  rB  r]   r_   ro   r  rq   ra   r  r  r  r+  r6  r   r7  r=  r   r   r?  r   r   r@  rP  rQ  rT  rh  rR  r  rd   rd   rd   rg   <module>   s   
 D
(
 	          JS]
84     
'   C