o
    /i5                    @   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mZm	Z	 d dl
mZ d dlmZmZ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 d dlmZmZmZ d dl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, ddl-m.Z. ddl/m0Z0m1Z1 ddl2m3Z3m4Z4 ddl5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z> ddl?m@Z@mAZAmBZBmCZC ddlDmEZE ddlFmGZGmHZHmIZImJZJmKZKmLZLmMZMmNZNmOZO eIrd dlPZPd dlPmQZQ ndZPdZQeHrd dlRZRdZSdZTdZUdZVdZWeX ZYeee)e*e(f  eZd< eHre(Z[ne)Z[G dd dZ\G dd dZ]G dd dZ^G dd  d Z_G d!d" d"e_e^Z`G d#d$ d$e`ZaG d%d& d&e_e^ZbG d'd( d(eaZcG d)d* d*e`Zdd+Zed,d- Zfd.d/ Zgeheieiefefejehehefegegeid0Zkd1d2 Zled3d4d5ZmG d6d7 d7eZnG d8d9 d9ZoG d:d4 d4eoenZpG d;d< d<epZqdS )=    N)ABCabstractmethod)chain)EmptyFull	LifoQueue)
AnyCallableDictIterableListLiteralOptionalTypeTypeVarUnion)parse_qsunquoteurlparse)
CacheEntryCacheEntryStatusCacheFactoryCacheFactoryInterfaceCacheInterfaceCacheKey   )Encoder_HiredisParser_RESP2Parser_RESP3Parser)TokenInterface)	NoBackoff)CredentialProvider"UsernamePasswordCredentialProvider)AfterConnectionReleasedEventEventDispatcher)	AuthenticationError$AuthenticationWrongNumberOfArgsErrorChildDeadlockedErrorConnectionError	DataErrorMaxConnectionsError
RedisErrorResponseErrorTimeoutError)MaintenanceStateMaintNotificationsConfig#MaintNotificationsConnectionHandlerMaintNotificationsPoolHandler)Retry)	CRYPTOGRAPHY_AVAILABLEHIREDIS_AVAILABLESSL_AVAILABLEcompare_versionsdeprecated_argsensure_stringformat_error_messageget_lib_versionstr_if_bytes)VerifyFlags   *   $s   
       DefaultParserc                   @   s   e Zd ZdefddZdS )HiredisRespSerializerargsc                 G   s   g }t |d trt|d   |dd  }nd|d v r.t|d  |dd  }z|t| W |S  tyN   t	
 \}}}t||w 2Pack a series of arguments into the Redis protocolr   r   N    )
isinstancestrtupleencodesplitappendhiredispack_command	TypeErrorsysexc_infor*   with_traceback)selfrD   output_value	traceback rY   P/var/www/html/flask_server/venv/lib/python3.10/site-packages/redis/connection.pypack`   s   "zHiredisRespSerializer.packN)__name__
__module____qualname__r   r[   rY   rY   rY   rZ   rC   _   s    rC   c                   @   s   e Zd ZdddZdd ZdS )PythonRespSerializerreturnNc                 C   s   || _ || _d S N)_buffer_cutoffrK   )rT   buffer_cutoffrK   rY   rY   rZ   __init__r   s   
zPythonRespSerializer.__init__c              	   G   s  g }t |d trt|d   |dd  }nd|d v r.t|d  |dd  }tttt| t	f}| j
}t| j|D ]>}t|}t||ksZ||ksZt |trtt|tt| t	f}|| || t	}qEt|tt| t	|t	f}qE|| |S rE   )rH   rI   rJ   rK   rL   	SYM_EMPTYjoinSYM_STARlenSYM_CRLFrb   map
memoryview
SYM_DOLLARrM   )rT   rD   rU   buffrc   arg
arg_lengthrY   rY   rZ   r[   v   s<   "




zPythonRespSerializer.packr`   N)r\   r]   r^   rd   r[   rY   rY   rY   rZ   r_   q   s    
r_   c                   @   s@  e Z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ed2ddZedd Zed3ddZe	d4dddddZedd  Zed!d" Zeed#eeeef eeef f fd$d%Zed&efd'd(Zed)d* Zed+d, Zed-d. Zed/d0 Zd1S )5ConnectionInterfacec                 C      d S ra   rY   rT   rY   rY   rZ   repr_pieces      zConnectionInterface.repr_piecesc                 C   rr   ra   rY   rT   callbackrY   rY   rZ   register_connect_callback   ru   z-ConnectionInterface.register_connect_callbackc                 C   rr   ra   rY   rv   rY   rY   rZ   deregister_connect_callback   ru   z/ConnectionInterface.deregister_connect_callbackc                 C   rr   ra   rY   rT   parser_classrY   rY   rZ   
set_parser   ru   zConnectionInterface.set_parserc                 C   rr   ra   rY   rs   rY   rY   rZ   get_protocol   ru   z ConnectionInterface.get_protocolc                 C   rr   ra   rY   rs   rY   rY   rZ   connect   ru   zConnectionInterface.connectc                 C   rr   ra   rY   rs   rY   rY   rZ   
on_connect   ru   zConnectionInterface.on_connectc                 G   rr   ra   rY   rT   rD   rY   rY   rZ   
disconnect   ru   zConnectionInterface.disconnectc                 C   rr   ra   rY   rs   rY   rY   rZ   check_health   ru   z ConnectionInterface.check_healthTc                 C   rr   ra   rY   rT   commandr   rY   rY   rZ   send_packed_command   ru   z'ConnectionInterface.send_packed_commandc                 O   rr   ra   rY   rT   rD   kwargsrY   rY   rZ   send_command   ru   z ConnectionInterface.send_commandr   c                 C   rr   ra   rY   rT   timeoutrY   rY   rZ   can_read   ru   zConnectionInterface.can_readFdisconnect_on_errorpush_requestc                C   rr   ra   rY   rT   disable_decodingr   r   rY   rY   rZ   read_response      z!ConnectionInterface.read_responsec                 G   rr   ra   rY   r   rY   rY   rZ   rO      ru   z ConnectionInterface.pack_commandc                 C   rr   ra   rY   rT   commandsrY   rY   rZ   pack_commands   ru   z!ConnectionInterface.pack_commandsr`   c                 C   rr   ra   rY   rs   rY   rY   rZ   handshake_metadata      z&ConnectionInterface.handshake_metadatatokenc                 C   rr   ra   rY   rT   r   rY   rY   rZ   set_re_auth_token   ru   z%ConnectionInterface.set_re_auth_tokenc                 C   rr   ra   rY   rs   rY   rY   rZ   re_auth   ru   zConnectionInterface.re_authc                 C      dS )z
        Mark the connection to be reconnected on the next command.
        This is useful when a connection is moved to a different node.
        NrY   rs   rY   rY   rZ   mark_for_reconnect   s   z&ConnectionInterface.mark_for_reconnectc                 C   r   )zG
        Returns True if the connection should be reconnected.
        NrY   rs   rY   rY   rZ   should_reconnect      z$ConnectionInterface.should_reconnectc                 C   r   )z3
        Reset the internal flag to False.
        NrY   rs   rY   rY   rZ   reset_should_reconnect  r   z*ConnectionInterface.reset_should_reconnectNTr   F)r\   r]   r^   r   rt   rx   ry   r|   r}   r~   r   r   r   r   r   r   r   rO   r   propertyr   r
   bytesrI   r   r    r   r   r   r   r   rY   rY   rY   rZ   rq      s`    









	

*


rq   c                   @   s  e Zd ZdZdejdddddfdee dee dddee	 dee
 d	ee d
ee deeeef  fddZedeeef fddZedeej fddZedee	e
f fddZeede
fddZejede
fddZeedeeee	f  fddZejedeeee	f  fddZeedeeee	f  fddZejedeeee	f  fddZedd  Ze	!dFd"d!d#d$d%Zed&d' Z					dGdee deeeef  fd(d)Zdefd*d+ZdHd,d-Z	"dHdefd.d/Z dee
 fd0d1Z!edefd2d3Z"e"jdId5d3Z"d6d7 Z#dJd8ee fd9d:Z$dJd;ee fd<d=Z%e&dfd>eee
e'f  d?ee fd@dAZ(	!	!dKdBe)dCe)fdDdEZ*dS )L$MaintNotificationsAbstractConnectiona2  
    Abstract class for handling maintenance notifications logic.
    This class is expected to be used as base class together with ConnectionInterface.

    This class is intended to be used with multiple inheritance!

    All logic related to maintenance notifications is encapsulated in this class.
    Nmaint_notifications_config maint_notifications_pool_handlermaintenance_stater/   maintenance_notification_hashorig_host_addressorig_socket_timeoutorig_socket_connect_timeoutparserc	           	      C   s(   || _ || _|| _| ||||| dS )aw  
        Initialize the maintenance notifications for the connection.

        Args:
            maint_notifications_config (MaintNotificationsConfig): The configuration for maintenance notifications.
            maint_notifications_pool_handler (Optional[MaintNotificationsPoolHandler]): The pool handler for maintenance notifications.
            maintenance_state (MaintenanceState): The current maintenance state of the connection.
            maintenance_notification_hash (Optional[int]): The current maintenance notification hash of the connection.
            orig_host_address (Optional[str]): The original host address of the connection.
            orig_socket_timeout (Optional[float]): The original socket timeout of the connection.
            orig_socket_connect_timeout (Optional[float]): The original socket connect timeout of the connection.
            parser (Optional[Union[_HiredisParser, _RESP3Parser]]): The parser to use for maintenance notifications.
                    If not provided, the parser from the connection is used.
                    This is useful when the parser is created after this object.
        N)r   r   r   $_configure_maintenance_notifications)	rT   r   r   r   r   r   r   r   r   rY   rY   rZ   rd     s   z-MaintNotificationsAbstractConnection.__init__r`   c                 C   rr   ra   rY   rs   rY   rY   rZ   _get_parser<  ru   z0MaintNotificationsAbstractConnection._get_parserc                 C   rr   ra   rY   rs   rY   rY   rZ   _get_socket@  ru   z0MaintNotificationsAbstractConnection._get_socketc                 C   r   )
        Returns:
            The RESP protocol version, or ``None`` if the protocol is not specified,
            in which case the server default will be used.
        NrY   rs   rY   rY   rZ   r}   D  s   z1MaintNotificationsAbstractConnection.get_protocolc                 C   rr   ra   rY   rs   rY   rY   rZ   hostM  r   z)MaintNotificationsAbstractConnection.hostrW   c                 C   rr   ra   rY   rT   rW   rY   rY   rZ   r   R  r   c                 C   rr   ra   rY   rs   rY   rY   rZ   socket_timeoutW  r   z3MaintNotificationsAbstractConnection.socket_timeoutc                 C   rr   ra   rY   r   rY   rY   rZ   r   \  r   c                 C   rr   ra   rY   rs   rY   rY   rZ   socket_connect_timeouta  r   z;MaintNotificationsAbstractConnection.socket_connect_timeoutc                 C   rr   ra   rY   r   rY   rY   rZ   r   f  r   c                 O   rr   ra   rY   r   rY   rY   rZ   r   k  ru   z1MaintNotificationsAbstractConnection.send_commandFTr   c                C   rr   ra   rY   r   rY   rY   rZ   r   o  r   z2MaintNotificationsAbstractConnection.read_responsec                 G   rr   ra   rY   r   rY   rY   rZ   r   y  ru   z/MaintNotificationsAbstractConnection.disconnectc                 C   s   | j r| j jsd| _d| _dS |stdt|ts#t|ts#td|r1| | _| j	|  nd| _t
| | j | _| jrE|| jj || jj |rP|n| j| _|rX|n| j| _|rc|| _dS | j| _dS )z
        Enable maintenance notifications by setting up
        handlers and storing original connection parameters.

        Should be used ONLY with parsers that support push notifications.
        NzBTo configure maintenance notifications, a parser must be provided!zLMaintenance notifications are only supported with hiredis and RESP3 parsers!)r   enabled!_maint_notifications_pool_handler'_maint_notifications_connection_handlerr,   rH   r   r   get_handler_for_connectionset_connectionr1   set_node_moving_push_handlerhandle_notificationset_maintenance_push_handlerr   r   r   r   r   r   )rT   r   r   r   r   r   rY   rY   rZ   r   }  sN   
zIMaintNotificationsAbstractConnection._configure_maintenance_notificationsc                 C   s`   |  }||  |  |j || _| js)t| |j| _|  	| jj d S |j| j_d S ra   )
r   r   r   r   r   r   r   r1   configr   )rT   r   %maint_notifications_pool_handler_copyrY   rY   rZ   3set_maint_notifications_pool_handler_for_connection  s"   

zXMaintNotificationsAbstractConnection.set_maint_notifications_pool_handler_for_connectionc                 C   sR   |   dvr| jr!| jjr#| jr%t| dr'| j| j|d d S d S d S d S d S d S )NrA   2r   )r   r   )r}   r   r   r   hasattr!_enable_maintenance_notifications)rT   r   rY   rY   rZ   0activate_maint_notifications_handling_if_enabled  s   
zUMaintNotificationsAbstractConnection.activate_maint_notifications_handling_if_enabledc           	   
   C   s   z3t | dd }|d u rtd||| }| jdddd|j|d |  }|r-t|dkr1td	W d S  tyc } z$t	|trW|j
d
krWd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: )getattr
ValueErrorget_endpoint_typer   rW   r   r<   r-   	ExceptionrH   r   logging	getLoggerr\   warning)	rT   r   r   r   endpoint_typeresponseer   loggerrY   rY   rZ   r     s@   

zFMaintNotificationsAbstractConnection._enable_maintenance_notificationsc              
   C   s   z|   }|dur| }|rt|dkr|d W S W n ttfy&   Y nw z+t| dd}t| dd}|rMt||tjtj	}|rPt
|d d d W S W dS W dS  tttjfy`   Y dS w )	a  
        Extract the resolved IP address from an
        established connection or resolve it from the host.

        First tries to get the actual IP from the socket (most accurate),
        then falls back to DNS resolution if needed.

        Args:
            connection: The connection object to extract the IP from

        Returns:
            str: The resolved IP address, or None if it cannot be determined
        Nr   r   r   	localhostport     )r   getpeernamerh   AttributeErrorOSErrorr   socketgetaddrinfo	AF_UNSPECSOCK_STREAMrI   gaierror)rT   conn_socket	peer_addrr   r   	addr_inforY   rY   rZ   get_resolved_ip"  s6   
	z4MaintNotificationsAbstractConnection.get_resolved_ipc                 C      | j S ra   _maintenance_staters   rY   rY   rZ   r   U     z6MaintNotificationsAbstractConnection.maintenance_statestatec                 C   
   || _ d S ra   r   )rT   r   rY   rY   rZ   r   Y     
c                 C   s   |   }|r| d S dS )z:
        Returns the peer name of the connection.
        r   N)r   r   )rT   r   rY   rY   rZ   r   ]  s   z0MaintNotificationsAbstractConnection.getpeernamerelaxed_timeoutc                 C   s:   |   }|r|dkr|n| j}|| | | d S d S )N)r   r   
settimeoutupdate_parser_timeout)rT   r   r   r   rY   rY   rZ   update_current_socket_timeoutf  s   
zBMaintNotificationsAbstractConnection.update_current_socket_timeoutr   c                 C   sL   |   }|r |jr"t|tr|r||j_d S t|tr$||_d S d S d S d S ra   )r   _bufferrH   r   r   r   _socket_timeout)rT   r   r   rY   rY   rZ   r   m  s   


z:MaintNotificationsAbstractConnection.update_parser_timeouttmp_host_addresstmp_relaxed_timeoutc                 C   s2   |r|t krt|| _|dkr|| _|| _dS dS )zd
        The value of SENTINEL is used to indicate that the property should not be updated.
        r   N)SENTINELrI   r   r   r   )rT   r   r   rY   rY   rZ   set_tmp_settingsu  s   

z5MaintNotificationsAbstractConnection.set_tmp_settingsreset_host_addressreset_relaxed_timeoutc                 C   s(   |r| j | _|r| j| _| j| _d S d S ra   )r   r   r   r   r   r   )rT   r   r   rY   rY   rZ   reset_tmp_settings  s   z7MaintNotificationsAbstractConnection.reset_tmp_settingsr   )NNNNNr   )r   r/   ra   FF)+r\   r]   r^   __doc__r/   NONEr   r0   r2   intrI   floatr   r   r   rd   r   r   r   r   r}   r   r   setterr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   objectr   boolr   rY   rY   rY   rZ   r     s    	

'
	

K

!
&3	

r   c                :   @   sn  e Zd ZdZdddddedddedddde ddddd	ddddejddddfd
e	de
e de
e de
e dedeeee  ef dededede	de	de
e de
e de
e de
e deedf de
eg df  de
e de
e	 de
eg df  de
e de
e d e
e d!d"d#e
e	 d$e
e d%e
e d&e
e f8d'd(Zd)d* Zed+d, Zd-d. Zd/d0 Zd1d2 Zd3d4 Z d5d6 Z!d7ee"e#e$f fd8d9Z%d:d; Z&	<dyd=ed>efd?d@Z'edAdB Z(edCdD Z)dEdF Z*dGdH Z+dzd=efdIdJZ,dKdL Z-dMdN Z.dOdP Z/dQdR Z0dSdT Z1dUdV Z2dWdX Z3dzdYdZZ4d[d\ Z5d{d]d^Z6	d|d<dd_d`daZ7dbdc Z8ddde Z9d7ee	ef fdfdgZ:e;d7ee<e=e=f e<eef f fdhdiZ>e>j?djee<e=e=f e<eef f fdkdiZ>dle@fdmdnZAdodp ZBd7e
eCjC fdqdrZDe;d7e
eee	f  fdsdtZEeEj?dje
eee	f  fdudtZEe;d7e
eee	f  fdvdwZFeFj?dje
eee	f  fdxdwZFdS )}AbstractConnectionz0Manages communication to and from a Redis serverr   NFutf-8stricti   zredis-pyrA   dbpasswordr   r   retry_on_timeoutretry_on_errorencodingencoding_errorsdecode_responsessocket_read_sizehealth_check_intervalclient_namelib_namelib_versionusernameretryredis_connect_funccredential_providerprotocolcommand_packerevent_dispatcherr   r   r   r/   r   r   r   r   c                  C   s  |s|r|durt d|du rt | _n|| _t | _|| _|| _|| _|| _	|| _
|| _|| _|| _|du r;|}|| _|| _|tu rHg }nt|}|rS|t || _|s[| jrx|du rgtt d| _nt|| _| jrw| j| j ntt d| _|| _d| _|| _t|||	| _d| _ d| _!|| _"g | _#d| _$d| _%z-zt&|}W n t'y   t(}Y n t)y   t*dw W |dk s|dkrt*d	|| _+n|dk s|dkrt*d	|| _+w | j+dkr|
t,krt-}
| .|
 | /|| _0d
| _1t23| |||||||| j4	 dS )a2  
        Initialize a new Connection.
        To specify a retry policy for specific errors, first set
        `retry_on_error` to a list of the error/s to retry on, then set
        `retry` to a valid `Retry` object.
        To retry on TimeoutError, `retry_on_timeout` can also be set to `True`.
        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  zprotocol must be an integerrA      zprotocol must be either 2 or 3F)5r*   r%   _event_dispatcherosgetpidpidr  r  r  r  r  r	  r  r   _socket_connect_timeoutr
  r   listrM   r.   r  r3   r!   r  copydeepcopyupdate_supported_errorsr  next_health_checkr  r   encoderr   _sock_socket_read_size_connect_callbacksrb   _re_auth_tokenr   rP   DEFAULT_RESP_VERSIONr   r)   r  r   r   r|   _construct_command_packer_command_packer_should_reconnectr   rd   _parser) rT   r  r	  r   r   r
  r  r  r  r  r{   r  r  r  r  r  r  r  r  r  r  r  r  r   r   r   r   r   r   r   retry_on_errors_listprY   rY   rZ   rd     s   )




zAbstractConnection.__init__c                 C   s8   d dd |  D }d| jj d| jj d| dS )N,c                 S      g | ]\}}| d | qS =rY   .0kvrY   rY   rZ   
<listcomp>      z/AbstractConnection.__repr__.<locals>.<listcomp><.(z)>)rf   rt   	__class__r]   r\   )rT   	repr_argsrY   rY   rZ   __repr__  s    zAbstractConnection.__repr__c                 C   rr   ra   rY   rs   rY   rY   rZ   rt     ru   zAbstractConnection.repr_piecesc                 C   s$   z|    W d S  ty   Y d S w ra   )r   r   rs   rY   rY   rZ   __del__  s
   zAbstractConnection.__del__c                 C   s&   |d ur|S t rt S t| j| jjS ra   )r5   rC   r_   rb   r&  rK   )rT   packerrY   rY   rZ   r,  "  s
   z,AbstractConnection._construct_command_packerc                 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)  rM   )rT   rw   wmrY   rY   rZ   rx   *  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)  removerD  rE  r   rv   rY   rY   rZ   ry   6  s
   z.AbstractConnection.deregister_connect_callbackc                 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/  rz   rY   rY   rZ   r|   A  s   zAbstractConnection.set_parserr`   c                 C   r   ra   )r/  rs   rY   rY   rZ   r   I     zAbstractConnection._get_parserc                 C   s   | j dd dS )z5Connects to the Redis server if not already connectedTr   N)connect_check_healthrs   rY   rY   rZ   r~   L  s   zAbstractConnection.connectTr   retry_socket_connectc              
      s    j rd S z|r j fdd fdd}n  }W n tjy)   td ty; } zt 	|d }~ww | _ z j
d u rL j|d n 
  W n ty^       w dd  jD  _ jD ]}| }|rv|  qkd S )Nc                            S ra   )_connectrY   rs   rY   rZ   <lambda>X      z9AbstractConnection.connect_check_health.<locals>.<lambda>c                    
     | S ra   r   errorrs   rY   rZ   rM  X     
 zTimeout connecting to serverr   c                 S   s   g | ]}| r|qS rY   rY   )r7  refrY   rY   rZ   r:  q  s    z;AbstractConnection.connect_check_health.<locals>.<listcomp>)r'  r  call_with_retryrL  r   r   r.   r   r)   _error_messager  on_connect_check_healthr,   r   r)  )rT   r   rJ  sockr   rT  rw   rY   rs   rZ   rI  P  s@   


z'AbstractConnection.connect_check_healthc                 C   rr   ra   rY   rs   rY   rY   rZ   rL  w  ru   zAbstractConnection._connectc                 C   rr   ra   rY   rs   rY   rY   rZ   _host_error{  ru   zAbstractConnection._host_errorc                 C   s   t |  |S ra   )r:   rY  )rT   	exceptionrY   rY   rZ   rV       z!AbstractConnection._error_messagec                 C   s   | j dd d S )NTr   )rW  rs   rY   rY   rZ   r        zAbstractConnection.on_connectc                 C   s  | j |  | j }d}| js| js| jr"| jpt| j| j}| }|r`| jdvr`t| j t	r?| 
t |j| j _| j |  t|dkrKd|d g}| jd| jdg|R dd	i |  | _nv|r| jdg|R dd	i z|  }W n ty   | jd|d
 d	d |  }Y nw t|dkrtdn?| jdvrt| j t	r| 
t |j| j _| j |  | jd| j|d |  | _| jd| jkr| jd| jkrtd| j|d | jr| jdd| j|d t|  dkrtdz| jr	| jddd| j|d |   W n
 ty   Y nw z| jr)| jddd| j|d |   W n
 ty4   Y nw | jrO| jd| j|d t|  dkrQtddS dS )z=Initialize the connection, authenticate and select a databaseNr   r   defaultr   HELLOAUTHr   Fr   r   r   zInvalid Username or Passwords   protoprotozInvalid RESP versionr   SETNAMEzError setting client nameSETINFOzLIB-NAMEzLIB-VERSELECTzInvalid Database)r/  r   r  r  r	  r#   get_credentialsr  rH   r   r|   r   EXCEPTION_CLASSESrh   r   r   r   r'   r<   r&   getr)   r   r  r  r-   r  r  )rT   r   r   	auth_argscred_providerauth_responserY   rY   rZ   rW    s   





z*AbstractConnection.on_connect_check_healthc              	   G   s   | j   | j}d| _|   |du rdS t | jkr0z|tj	 W n t
tfy/   Y nw z|  W dS  t
yA   Y dS w )z!Disconnects from the Redis serverN)r/  on_disconnectr'  r   r  r  r  shutdownr   	SHUT_RDWRr   rP   close)rT   rD   	conn_sockrY   rY   rZ   r     s"   
zAbstractConnection.disconnectc                 C   
   d| _ d S )NTr.  rs   rY   rY   rZ   r        
z%AbstractConnection.mark_for_reconnectc                 C   r   ra   rp  rs   rY   rY   rZ   r     rH  z#AbstractConnection.should_reconnectc                 C   ro  )NFrp  rs   rY   rY   rZ   r     rq  z)AbstractConnection.reset_should_reconnectc                 C   s*   | j ddd t|  dkrtddS )z Send PING, expect PONG in returnPINGFr   PONGz#Bad response from PING health checkN)r   r<   r   r)   rs   rY   rY   rZ   
_send_ping  s   zAbstractConnection._send_pingc                 C      |    dS )z Function to call when PING failsNrP  rT   rR  rY   rY   rZ   _ping_failed     zAbstractConnection._ping_failedc                 C   s2   | j rt | jkr| j| j| j dS dS dS )z3Check the health of the connection with a PING/PONGN)r  time	monotonicr%  r  rU  rt  rw  rs   rY   rY   rZ   r   "  s   zAbstractConnection.check_healthc              
   C   s   | j s	| jdd |r|   zt|tr|g}|D ]}| j | qW d
S  tjy5   |   t	d t
yi } z)|   t|jdkrPd|jd }}n
|jd }|jd }td| d| d	d
}~w tyt   |    w )z2Send an already packed command to the Redis serverFr   zTimeout writing to socketr   UNKNOWNr   zError z while writing to socket. r=  N)r'  rI  r   rH   rI   sendallr   r   r   r.   r   rh   rD   r)   BaseException)rT   r   r   itemr   errnoerrmsgrY   rY   rZ   r   '  s2   


z&AbstractConnection.send_packed_commandc                 O   s"   | j | jj| |ddd dS )z+Pack and send a command to the Redis serverr   Tr   N)r   r-  r[   rf  r   rY   rY   rZ   r   F  s   


zAbstractConnection.send_commandc              
   C   s`   | j }|s	|   |  }z| j|W S  ty/ } z|   td| d|j d}~ww )z8Poll the socket to see if there's data that can be read.Error while reading from z: N)	r'  r~   rY  r/  r   r   r   r)   rD   )rT   r   rX  
host_errorr   rY   rY   rZ   r   M  s   zAbstractConnection.can_readr   c             
   C   s   |   }z| jdv r| jj||d}n| jj|d}W n> tjy0   |r)|   td|  tyL } z|r=|   t	d| d|j
 d}~w tyY   |rX|    w | jret | j | _t|troz|~w |S )z0Read the response from a previously sent command)3r  )r   r   )r   zTimeout reading from r  z : N)rY  r  r/  r   r   r   r   r.   r   r)   rD   r}  r  ry  rz  r%  rH   r-   )rT   r   r   r   r  r   r   rY   rY   rZ   r   \  s:   	

z AbstractConnection.read_responsec                 G      | j j| S )rF   )r-  r[   r   rY   rY   rZ   rO     rx  zAbstractConnection.pack_commandc           	      C   s   g }g }d}| j }|D ]B}| jj| D ]9}t|}||ks&||ks&t|tr4|r0|t| d}g }||ks=t|trC|| q|| ||7 }qq|rX|t| |S )z.Pack multiple commands into the Redis protocolr   )	rb   r-  r[   rh   rH   rk   rM   re   rf   )	rT   r   rU   piecesbuffer_lengthrc   cmdchunkchunklenrY   rY   rZ   r     s.   

z AbstractConnection.pack_commandsc                 C   r   ra   )r  rs   rY   rY   rZ   r}     rH  zAbstractConnection.get_protocolc                 C   r   ra   _handshake_metadatars   rY   rY   rZ   r     r   z%AbstractConnection.handshake_metadatarW   c                 C   r   ra   r  r   rY   rY   rZ   r     r   r   c                 C   r   ra   )r*  r   rY   rY   rZ   r     rq  z$AbstractConnection.set_re_auth_tokenc                 C   s<   | j d ur| d| j d| j   |   d | _ d S d S Nr_  oid)r*  r   try_get	get_valuer   rs   rY   rY   rZ   r     s   


zAbstractConnection.re_authc                 C   r   ra   )r'  rs   rY   rY   rZ   r     rH  zAbstractConnection._get_socketc                 C   r   ra   r   rs   rY   rY   rZ   r     r   z!AbstractConnection.socket_timeoutc                 C   r   ra   r  r   rY   rY   rZ   r     r   c                 C   r   ra   r   rs   rY   rY   rZ   r     r   z)AbstractConnection.socket_connect_timeoutc                 C   r   ra   r  r   rY   rY   rZ   r     r   )TTr   r   r   )Gr\   r]   r^   r   r   rB   r;   r/   r   r   r   rI   r  r  r   r   r   r   r  r   r	   r"   r%   r0   r2   rd   rA  r   rt   rB  r,  rx   ry   r|   r   r   r   r   r~   rI  rL  rY  rV  r   rW  r   r   r   r   rt  rw  r   r   r   r   r   rO   r   r}   r   r
   r   r   r  r    r   r   r   r   r   r   rY   rY   rY   rZ   r    s&   	

 
 

'

t

,((
 r  c                       sj   e Zd ZdZ					d fdd	Zd	d
 Zdd Zdd Zede	fddZ
e
jde	fddZ
  ZS )
Connectionz4Manages TCP communication to and from a Redis serverr   r   FNr   c                    s<   || _ t|| _|| _|pi | _|| _t jdi | d S NrY   )_hostr   r   socket_keepalivesocket_keepalive_optionssocket_typesuperrd   )rT   r   r   r  r  r  r   r?  rY   rZ   rd     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  rM   rT   r  rY   rY   rZ   rt     s   zConnection.repr_piecesc                 C   s,  d}t | j| j| jt jD ]}}|\}}}}}d}zDt  |||}|t jt jd | j	rH|t j
t jd | j D ]\}	}
|t j|	|
 q;|| j || || j |W   S  ty } z"|}|durz|t j W n	 ty|   Y nw |  W Y d}~qd}~ww |dur|td)zCreate a TCP socket connectionNr   z)socket.getaddrinfo returned an empty list)r   r   r   r   r  r   
setsockoptIPPROTO_TCPTCP_NODELAYr  
SOL_SOCKETSO_KEEPALIVEr  itemsr   r   r~   r   r   rk  rl  rm  )rT   errresfamilysocktyper`  	canonnamesocket_addressrX  r8  r9  rV   rY   rY   rZ   rL    s>   

	zConnection._connectc                 C   s   | j  d| j S )N:)r   r   rs   rY   rY   rZ   rY    s   zConnection._host_errorr`   c                 C   r   ra   r  rs   rY   rY   rZ   r      r   zConnection.hostrW   c                 C   r   ra   r  r   rY   rY   rZ   r   $  r   )r   r   FNr   )r\   r]   r^   r   rd   rt   rL  rY  r   rI   r   r  __classcell__rY   rY   r  rZ   r    s    .r  c                   @   s  e Zd ZdZdZdZdededej	fddZ
d	d
 Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd ZdhddZd d! Zdid#d$Z	%djdd%d&d'd(Zd)d* Zd+d, Zed-eeeef eeef f fd.d/Z d0e!fd1d2Z"d3d4 Z#d5d6 Z$d7d8 Z%d9d: Z&ed-efd;d<Z'e'j(d=efd>d<Z'ed-e)ee*e+f  fd?d@Z,e,j(d=e)ee*e+f  fdAd@Z,ed-e)ee*e+f  fdBdCZ-e-j(d=e)ee*e+f  fdDdCZ-d-e)e.j. fdEdFZ/d-e0fdGdHZ1ed-e2fdIdJZ3e3j(dKe2fdLdJZ3dMdN Z4dOdP Z5dkdRe)e* fdSdTZ6	Q	QdldUe)e dVe)e* fdWdXZ7	%	%dmdYe8dZe8fd[d\Z9d]d^ Z:d_d` Z;ded-dQfdadbZ<dcdd Z=dee>eee)e>e  f  fdfdgZ?dQS )nCacheProxyConnections   fooz7.4.0redisconncache	pool_lockc                 C   s   t  | _|| _| jj| _| jj| _| jj| _|j| _|| _|| _	t
 | _d | _d | _| | j t| jtrXt| | jj| jj| jj| jj| jj| jj| jj| j 	 d S d S ra   )r  r  r  _connr  r   r   r  
_pool_lock_cache	threadingRLock_cache_lock_current_command_cache_key_current_optionsrx   _enable_tracking_callbackrH   r   rd   r   r   r   r   r   r   r   )rT   r  r  r  rY   rY   rZ   rd   .  s2   




zCacheProxyConnection.__init__c                 C   
   | j  S ra   )r  rt   rs   rY   rY   rZ   rt   N  rq  z CacheProxyConnection.repr_piecesc                 C      | j | d S ra   )r  rx   rv   rY   rY   rZ   rx   Q  r\  z.CacheProxyConnection.register_connect_callbackc                 C   r  ra   )r  ry   rv   rY   rY   rZ   ry   T  r\  z0CacheProxyConnection.deregister_connect_callbackc                 C   r  ra   )r  r|   rz   rY   rY   rZ   r|   W  r\  zCacheProxyConnection.set_parserc                 C   s    t | jtr| j| d S d S ra   )rH   r  r   r   rT   r   rY   rY   rZ   r   Z  s
   zHCacheProxyConnection.set_maint_notifications_pool_handler_for_connectionc                 C   r  ra   )r  r}   rs   rY   rY   rZ   r}   b  rq  z!CacheProxyConnection.get_protocolc                 C   s   | j   | j jdd }|d u r| j jdd }| j jdd }|d u r-| j jdd }|d u s5|d u r9tdt|}t|}|| jksNt|| jdkrRtdd S )Ns   serverservers   versionversionz0Cannot retrieve information about server versionr   ziTo maximize compatibility with all Redis products, client-side caching is supported by Redis 7.4 or later)	r  r~   r   rf  r)   r9   DEFAULT_SERVER_NAMEr7   MIN_ALLOWED_VERSION)rT   server_name
server_verrY   rY   rZ   r~   e  s"   

zCacheProxyConnection.connectc                 C      | j   d S ra   )r  r   rs   rY   rY   rZ   r   |  r[  zCacheProxyConnection.on_connectc                 G   s@   | j  | j  W d    n1 sw   Y  | jj|  d S ra   )r  r  flushr  r   r   rY   rY   rZ   r     s   zCacheProxyConnection.disconnectc                 C   r  ra   )r  r   rs   rY   rY   rZ   r     r[  z!CacheProxyConnection.check_healthTc                 C   r  ra   )r  r   r   rY   rY   rZ   r     s   z(CacheProxyConnection.send_packed_commandc              	   O   s  |    | j) | jt|d dds)d | _| jj|i | 	 W d    d S W d    n1 s3w   Y  |dd u rCt	dt|d t
|dd| _| jY | j| jr| j| j}|j| jkr| j |j r~|jjdd |j srW d    n1 sw   Y  	 W d    d S | jt| j| jtj| jd W d    n1 sw   Y  | jj|i | d S )	Nr   rY   )r   
redis_keyskeyszCannot create cache key.Tr   )	cache_keycache_valuestatusconnection_ref)_process_pending_invalidationsr  r  is_cachabler   r  r  r   rf  r   rJ   r  r  r   r   setr   DUMMY_CACHE_VALUEr   IN_PROGRESS)rT   rD   r   entryrY   rY   rZ   r     sH   

z!CacheProxyConnection.send_commandr   c                 C      | j |S ra   )r  r   r   rY   rY   rZ   r        zCacheProxyConnection.can_readFr   c                C   s@  | j 8 | jd ur4| j| jd ur4| j| jjtjkr4t| j| jj	}d | _|W  d    S W d    n1 s>w   Y  | j
j|||d}| j G | jd u r^|W  d    S |d u rs| j| jg |W  d    S | j| j}|d urtj|_||_	| j| d | _W d    |S 1 sw   Y  |S )N)r   r   r   )r  r  r  rf  r  r   r  r"  r#  r  r  r   delete_by_cache_keysVALIDr  )rT   r   r   r   r  r   cache_entryrY   rY   rZ   r     sJ   
 
	
z"CacheProxyConnection.read_responsec                 G   r  ra   )r  rO   r   rY   rY   rZ   rO     r  z!CacheProxyConnection.pack_commandc                 C   r  ra   )r  r   r   rY   rY   rZ   r     r  z"CacheProxyConnection.pack_commandsr`   c                 C      | j jS ra   )r  r   rs   rY   rY   rZ   r        z'CacheProxyConnection.handshake_metadatar   c                 C   r  ra   )r  r   r   rY   rY   rZ   r     r\  z&CacheProxyConnection.set_re_auth_tokenc                 C   r  ra   )r  r   rs   rY   rY   rZ   r     r[  zCacheProxyConnection.re_authc                 C   r  ra   )r  r   rs   rY   rY   rZ   r     r[  z'CacheProxyConnection.mark_for_reconnectc                 C   r  ra   )r  r   rs   rY   rY   rZ   r     rq  z%CacheProxyConnection.should_reconnectc                 C   r  ra   )r  r   rs   rY   rY   rZ   r     r[  z+CacheProxyConnection.reset_should_reconnectc                 C   r  ra   r  r   rs   rY   rY   rZ   r     r  zCacheProxyConnection.hostrW   c                 C      || j _d S ra   r  r   rY   rY   rZ   r   	  rx  c                 C   r  ra   r  r   rs   rY   rY   rZ   r     r  z#CacheProxyConnection.socket_timeoutc                 C   r  ra   r  r   rY   rY   rZ   r     rx  c                 C   r  ra   r  r   rs   rY   rY   rZ   r     r  z+CacheProxyConnection.socket_connect_timeoutc                 C   r  ra   r  r   rY   rY   rZ   r     rx  c                 C   s   t | jtr| j S td)NCMaintenance notifications are not supported by this connection type)rH   r  r   r   NotImplementedErrorrs   rY   rY   rZ   r     s
   
z CacheProxyConnection._get_socketc                 C   s   t |ts	td|S )a|  
        Validate that connection instance supports maintenance notifications.
        With this helper method we ensure that we are working
        with the correct connection type.
        After twe validate that connection instance supports maintenance notifications
        we can safely return the connection instance
        as MaintNotificationsAbstractConnection.
        r  )rH   r   r  rT   
connectionrY   rY   rZ   ,_get_maint_notifications_connection_instance%  s
   
zACacheProxyConnection._get_maint_notifications_connection_instancec                 C   s   |  | j}|jS ra   r  r  r   rT   conrY   rY   rZ   r   7  s   z&CacheProxyConnection.maintenance_stater   c                 C   s   |  | j}||_d S ra   r  )rT   r   r  rY   rY   rZ   r   <  s   
c                 C      |  | j}| S ra   )r  r  r   r  rY   rY   rZ   r   A     z CacheProxyConnection.getpeernamec                 C   r  ra   )r  r  r   r  rY   rY   rZ   r   E  r  z$CacheProxyConnection.get_resolved_ipNr   c                 C   s   |  | j}|| d S ra   )r  r  r   )rT   r   r  rY   rY   rZ   r   I  s   z2CacheProxyConnection.update_current_socket_timeoutr   r   c                 C      |  | j}||| d S ra   )r  r  r   )rT   r   r   r  rY   rY   rZ   r   M     z%CacheProxyConnection.set_tmp_settingsr   r   c                 C   r  ra   )r  r  r   )rT   r   r   r  rY   rY   rZ   r   U  r  z'CacheProxyConnection.reset_tmp_settingsc                 C   r  ra   )r  rL  rs   rY   rY   rZ   rL  ]  r[  zCacheProxyConnection._connectc                 C   r  ra   )r  rY  rs   rY   rY   rZ   rY  `  r[  z CacheProxyConnection._host_errorc                 C   s(   | ddd |  |j| j d S )Nr   TRACKINGr   )r   r   r/  set_invalidation_push_handler_on_invalidation_callback)rT   r  rY   rY   rZ   r  c  s   z.CacheProxyConnection._enable_tracking_callbackc                 C   s&   |   r| jjdd |   sd S d S )NTr  )r   r  r   rs   rY   rY   rZ   r  h  s   z3CacheProxyConnection._process_pending_invalidationsdatac                 C   sd   | j % |d d u r| j  n| j|d  W d    d S W d    d S 1 s+w   Y  d S )Nr   )r  r  r  delete_by_redis_keys)rT   r  rY   rY   rZ   r  l  s   "z.CacheProxyConnection._on_invalidation_callbackr   r   r   ra   )NNr   )@r\   r]   r^   r  r  r  rq   r   r  r  rd   rt   rx   ry   r|   r   r}   r~   r   r   r   r   r   r   r   rO   r   r   r   r
   r   rI   r   r    r   r   r   r   r   r   r  r   r  r   r   r   r   r   r   r  r/   r   r   r   r   r   r  r   rL  rY  r  r  r   r  rY   rY   rY   rZ   r  )  s    
 

0-(



&r  c                       sp   e Zd ZdZ																ddeed  deed  f fd	d
Z fddZ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requiredTFssl_include_verify_flagsr=   ssl_exclude_verify_flagsc                    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| _|
| _|| _|| _|| _|| _|| _|| _t jdi | dS )a!  Constructor

        Args:
            ssl_keyfile: Path to an ssl private key. Defaults to None.
            ssl_certfile: Path to an ssl certificate. Defaults to None.
            ssl_cert_reqs: The string value for the SSLContext.verify_mode (none, optional, required),
                           or an ssl.VerifyMode. Defaults to "required".
            ssl_include_verify_flags: A list of flags to be included in the SSLContext.verify_flags. Defaults to None.
            ssl_exclude_verify_flags: A list of flags to be excluded from the SSLContext.verify_flags. Defaults to None.
            ssl_ca_certs: The path to a file of concatenated CA certificates in PEM format. Defaults to None.
            ssl_ca_data: Either an ASCII string of one or more PEM-encoded certificates or a bytes-like object of DER-encoded certificates.
            ssl_check_hostname: If set, match the hostname during the SSL handshake. Defaults to True.
            ssl_ca_path: The path to a directory containing several CA certificates in PEM format. Defaults to None.
            ssl_password: Password for unlocking an encrypted private key. Defaults to None.

            ssl_validate_ocsp: If set, perform a full ocsp validation (i.e not a stapled verification)
            ssl_validate_ocsp_stapled: If set, perform a validation on a stapled ocsp response
            ssl_ocsp_context: A fully initialized OpenSSL.SSL.Context object to be used in verifying the ssl_ocsp_expected_cert
            ssl_ocsp_expected_cert: A PEM armoured string containing the expected certificate to be returned from the ocsp verification service.
            ssl_min_version: The lowest supported SSL version. It affects the supported SSL versions of the SSLContext. None leaves the default provided by ssl module.
            ssl_ciphers: A string listing the ciphers that are allowed to be used. Defaults to None, which means that the default ciphers are used. See https://docs.python.org/3/library/ssl.html#ssl.SSLContext.set_ciphers for more information.

        Raises:
            RedisError
        z$Python wasn't built with SSL supportN)noneoptionalr  z+Invalid SSL Certificate Requirements Flag: FrY   )r6   r,   keyfilecertfilessl	CERT_NONErH   rI   CERT_OPTIONALCERT_REQUIRED	cert_reqsr  r  ca_certsca_dataca_pathcheck_hostnamecertificate_passwordssl_validate_ocspssl_validate_ocsp_stapledssl_ocsp_contextssl_ocsp_expected_certssl_min_versionssl_ciphersr  rd   )rT   ssl_keyfilessl_certfilessl_cert_reqsr  r  ssl_ca_certsssl_ca_datassl_check_hostnamessl_ca_pathssl_passwordr  r  r   r  r  r  r   	CERT_REQSr  rY   rZ   rd   {  s@   -
zSSLConnection.__init__c              	      s4   t   }z| |W S  ttfy   |   w )zN
        Wrap the socket with SSL support, handling potential errors.
        )r  rL  _wrap_socket_with_sslr   r,   rm  rT   rX  r  rY   rZ   rL    s   
zSSLConnection._connectc                 C   s  t  }| j|_| j|_| jr| jD ]	}| j|O  _q| jr-| jD ]
}| j| M  _q"| js3| j	r>|j
| j| j	| jd | jdusM| jdusM| jdurX|j| j| j| jd | jdura| j|_| jrj|| j | jdu rwtdu rwtd| jr| jrtd|j|| jd}| jrd	dl}d
dlm} | jdu r|j|jj }|!| j |"| j	 n| j}|#|| j$ |j%|t&& }|'  |(| j| j)f |*  |+  |S | jdu rtrd
dlm,}	 |	|| j| j)| j}
|
- r|S t.d|S )z
        Wraps the socket with SSL support.

        Args:
            sock: The plain socket to wrap with SSL.

        Returns:
            An SSL wrapped socket.
        )r  r  r	  N)cafilecapathcadataTFzcryptography is not installed.zKEither an OCSP staple or pure OCSP connection must be validated - not both.)server_hostnamer   r   )ocsp_staple_verifier)OCSPVerifierzocsp validation error)/r  create_default_contextr  r  verify_moder  verify_flagsr  r  r  load_cert_chainr  r  r  r  load_verify_locationsr  minimum_versionr  set_ciphersr  r4   r,   r  wrap_socketr   OpenSSLocspr  r   SSLContextSSLv23_METHODuse_certificate_fileuse_privatekey_fileset_ocsp_client_callbackr  r  r   request_ocspr~   r   do_handshakerk  r  is_validr)   )rT   rX  contextflagsslsockr  r  
staple_ctxr  r  orY   rY   rZ   r    sp   







z#SSLConnection._wrap_socket_with_ssl)NNr  NNNNTNNFFNNNN)
r\   r]   r^   r   r   r   rd   rL  r  r  rY   rY   r  rZ   r  u  s2    

Qr  c                       s:   e Zd ZdZd fdd	Zdd Zdd	 Zd
d Z  ZS )UnixDomainSocketConnectionz4Manages UDS communication to and from a Redis server Nc                    s"   t  jdi | || _|| _d S r  )r  rd   pathr   )rT   r/  r   r   r  rY   rZ   rd   0  s   
z#UnixDomainSocketConnection.__init__c                 C   s.   d| j fd| jfg}| jr|d| jf |S )Nr/  r  r  )r/  r  r  rM   r  rY   rY   rZ   rt   5  s   z&UnixDomainSocketConnection.repr_piecesc                 C   sz   t  t jt j}|| j z|| j W n ty4   z|t j	 W n	 ty.   Y nw |
   w || j |S )z&Create a Unix domain socket connection)r   AF_UNIXr   r   r   r~   r/  r   rk  rl  rm  r   r  rY   rY   rZ   rL  ;  s   z#UnixDomainSocketConnection._connectc                 C   r   ra   )r/  rs   rY   rY   rZ   rY  L  rH  z&UnixDomainSocketConnection._host_error)r.  N)	r\   r]   r^   r   rd   rt   rL  rY  r  rY   rY   r  rZ   r-  -  s    r-  )0FFALSENNOc                 C   s6   | d u s| dkr
d S t | tr|  tv rdS t| S )Nr.  F)rH   rI   upperFALSE_STRINGSr  )rW   rY   rY   rZ   to_boolS  s
   r8  c                 C   s\   |  dd dd}g }|dD ]}| }tt|s#td| |tt| q|S )N[r.  ]r2  zInvalid ssl verify flag: )replacerL   stripr   r=   r   rM   r   )rW   verify_flags_strr  r)  rY   rY   rZ   parse_ssl_verify_flags[  s   
r>  )r  r   r   r  r
  r  max_connectionsr  r	  r  r  r   c              
   C   s  |  ds|  ds|  dstdt| } i }t| j D ]7\}}|rWt|dkrWt|d }t	|}|rSz||||< W q  t
tfyR   td| dw |||< q | jrbt| j|d< | jrlt| j|d	< | jd
kr| jr{t| j|d< t|d< |S | jrt| 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 )Nzredis://z	rediss://zunix://zRRedis URL must specify one of the following schemes (redis://, rediss://, unix://)r   zInvalid value for 'z' in connection URL.r  r	  unixr/  connection_classr   r   r  /r.  rediss)
startswithr   r   r   queryr  rh   r   URL_QUERY_ARGUMENT_PARSERSrf  rP   r  r	  schemer/  r-  hostnamer   r   r;  r   r  )urlr   namerW   r   rY   rY   rZ   	parse_urly  sZ   


rK  _CPConnectionPool)boundc                   @   s   e Zd Zedd Zedd Zeedgdddd	ee d
e	fddZ
edd Zede	fddZeddefddZedd ZedefddZedefddZdS ) ConnectionPoolInterfacec                 C   rr   ra   rY   rs   rY   rY   rZ   r}     ru   z$ConnectionPoolInterface.get_protocolc                 C   rr   ra   rY   rs   rY   rY   rZ   reset  ru   zConnectionPoolInterface.reset*)Use get_connection() without args instead5.3.0args_to_warnreasonr  command_namer`   c                 O   rr   ra   rY   )rT   rW  r  optionsrY   rY   rZ   get_connection  s   	z&ConnectionPoolInterface.get_connectionc                 C   rr   ra   rY   rs   rY   rY   rZ   get_encoder  ru   z#ConnectionPoolInterface.get_encoderr  c                 C   rr   ra   rY   r  rY   rY   rZ   release  ru   zConnectionPoolInterface.releaseTinuse_connectionsc                 C   rr   ra   rY   )rT   r\  rY   rY   rZ   r     ru   z"ConnectionPoolInterface.disconnectc                 C   rr   ra   rY   rs   rY   rY   rZ   rm    ru   zConnectionPoolInterface.closer  c                 C   rr   ra   rY   )rT   r  rY   rY   rZ   	set_retry  ru   z!ConnectionPoolInterface.set_retryr   c                 C   rr   ra   rY   r   rY   rY   rZ   re_auth_callback  ru   z(ConnectionPoolInterface.re_auth_callbackNr   )r\   r]   r^   r   r}   rP  r8   r   rI   rq   rY  rZ  r[  r  r   rm  r3   r]  r    r^  rY   rY   rY   rZ   rO    s8    



rO  c                   @   s  e Zd ZdZ	d9dee fddZeede	e
ef fddZejed	e	e
ef 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d ZdefddZdefddZdefddZ			d:ddded dee
 d ee def
d!d"Z					#	#	#d;ddd$ed% d&ee d'ee
 d(ee d)ed*ed+efd,d-Z								#	#	#	.d<d$ed% d&ee d'ee
 d(ee dee
 d ee ded d)ed*ed+ed/efd0d1Zd2d3 Z 	d9d4ee
 fd5d6Z!	d9d4ee
 fd7d8Z"dS )=(MaintNotificationsAbstractConnectionPoola(  
    Abstract class for handling maintenance notifications logic.
    This class is mixed into the ConnectionPool classes.

    This class is not intended to be used directly!

    All logic related to maintenance notifications and
    connection pool handling is encapsulated in this class.
    Nr   c                 K   s\   | ddv }|d u r|rt }|r)|jr)|stdt| || _| | j d S d | _d S )Nr  r  r  zWMaintenance notifications handlers on connection are only supported with RESP version 3)rf  r0   r   r,   r2   r   1_update_connection_kwargs_for_maint_notifications)rT   r   r   is_protocol_supportedrY   rY   rZ   rd     s   

z1MaintNotificationsAbstractConnectionPool.__init__r`   c                 C   rr   ra   rY   rs   rY   rY   rZ   connection_kwargs  r   z:MaintNotificationsAbstractConnectionPool.connection_kwargsrW   c                 C   rr   ra   rY   r   rY   rY   rZ   rc    r   c                 C   rr   ra   rY   rs   rY   rY   rZ   _get_pool_lock  ru   z7MaintNotificationsAbstractConnectionPool._get_pool_lockr   c                 C   rr   ra   rY   rs   rY   rY   rZ   _get_free_connections  ru   z>MaintNotificationsAbstractConnectionPool._get_free_connectionsc                 C   rr   ra   rY   rs   rY   rY   rZ   _get_in_use_connections  s   z@MaintNotificationsAbstractConnectionPool._get_in_use_connectionsc                 C   s   | 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   rT   r   rY   rY   rZ   maint_notifications_enabled  s
   	

zDMaintNotificationsAbstractConnectionPool.maint_notifications_enabledc                 C   sN   |   r|jstd| jst| || _n|| j_| | j | | j 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 themN)rh  r   r   r   r2   r   ra  3_update_maint_notifications_configs_for_connectionsrg  rY   rY   rZ   !update_maint_notifications_config.  s$   zJMaintNotificationsAbstractConnectionPool.update_maint_notifications_configr   c                 C   sj   |   sdS | j||jd | jdddu r3| j| jd| jdd| jddd dS dS )zJ
        Update the connection kwargs for all future connections.
        N)r   r   r   r   r   r   )r   r   r   )rh  rc  updater   rf  r  rY   rY   rZ   ra  O  s&   
zZMaintNotificationsAbstractConnectionPool._update_connection_kwargs_for_maint_notificationsc                 C   s~   |   1 |  D ]}|| |j|_|  q	|  D ]}|| |j|_|  qW d   dS 1 s8w   Y  dS )zLUpdate the maintenance notifications config for all connections in the pool.N)rd  re  r   r   r   r   rf  r   )rT   r   r  rY   rY   rZ   ri  o  s"   


"z\MaintNotificationsAbstractConnectionPool._update_maint_notifications_configs_for_connectionsconnected_addressr  matching_pattern)rl  configured_addressnotification_hash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,|r,|j|kr,dS dS )z[
        Check if the connection should be updated based on the matching criteria.
        rl  Frn  ro  T)r   r   r   )rT   r  rm  rp  rq  rY   rY   rZ   _should_update_connection  s   

zBMaintNotificationsAbstractConnectionPool._should_update_connectionFr   r/   r   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   )r   r   r   r   r   )	rT   r  r   r   rs  r   rt  r   r   rY   rY   rZ   update_connection_settings  s   zCMaintNotificationsAbstractConnectionPool.update_connection_settingsTinclude_free_connectionsc                 C   s   |   K |  D ]}| ||||r | j|||||||	|
d q	|r?|  D ]}| ||||r>| j|||||||	|
d q'W d   dS W d   dS 1 sRw   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.
        )r   r   rs  r   rt  r   r   N)rd  rf  rr  ru  re  )rT   r   r   rs  r   rp  rq  rm  rt  r   r   rv  r  rY   rY   rZ   update_connections_settings  sT   
#"zDMaintNotificationsAbstractConnectionPool.update_connections_settingsc                 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)rc  rk  rT   r   rY   rY   rZ   update_connection_kwargs	  s   
zAMaintNotificationsAbstractConnectionPool.update_connection_kwargsmoving_address_srcc                 C   R   |    |  D ]}| |d|r|  q	W d   dS 1 s"w   Y  dS )z
        Mark all active connections for reconnect.
        This is used when a cluster node is migrated to a different address.

        :param moving_address_src: The address of the node that is being moved.
        rl  N)rd  rf  rr  r   rT   rz  r  rY   rY   rZ   'update_active_connections_for_reconnect	     

"zPMaintNotificationsAbstractConnectionPool.update_active_connections_for_reconnectc                 C   r{  )z
        Disconnect all free/available connections.
        This is used when a cluster node is migrated to a different address.

        :param moving_address_src: The address of the node that is being moved.
        rl  N)rd  re  rr  r   r|  rY   rY   rZ   disconnect_free_connections(	  r~  zDMaintNotificationsAbstractConnectionPool.disconnect_free_connectionsra   )rl  NN)NNNNFFF)NNNNNNrl  FFFT)#r\   r]   r^   r   r   r0   rd   r   r   r
   rI   r   rc  r  r  r  rd  r   re  rf  rh  rj  r2   ra  ri  r   r   r  rr  r  ru  rw  ry  r}  r  rY   rY   rY   rZ   r_    s    

!
 

	
%
I
r_  c                   @   sn  e Zd ZdZedee dedefddZe	dddfde
e d	e
e d
e
e fddZdefddZedeeef fddZejdeeef fddZdd Zd?ddZd?ddZedgdddd@dAddZdefd d!ZdBd#d$ZdCd&d'Zd%ddefd(d)ZdDd+eddfd,d-Z d?d.d/Z!d0e"ddfd1d2Z#d3e$fd4d5Z%d6d7 Z&d8d9 Z'd:d; Z(d<e)fd=d>Z*dS )ErM  a>  
    Create a connection pool. ``If max_connections`` is set, then this
    object raises :py:class:`~redis.exceptions.ConnectionError` when the pool's
    limit is reached.

    By default, TCP connections are created unless ``connection_class``
    is specified. Use class:`.UnixDomainSocketConnection` for
    unix sockets.
    :py:class:`~redis.SSLConnection` can be used for SSL enabled connections.

    If ``maint_notifications_config`` is provided, the connection pool will support
    maintenance notifications.
    Maintenance notifications are supported only with RESP3.
    If the ``maint_notifications_config`` is not provided but the ``protocol`` is 3,
    the maintenance notifications will be enabled by default.

    Any additional keyword arguments are passed to the constructor of
    ``connection_class``.
    clsrI  r`   c                 K   s4   t |}d|v r|d |d< || | 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.
        rA  NrY   )rK  rk  )r  rI  r   url_optionsrY   rY   rZ   from_urlO	  s
   )
zConnectionPool.from_urlNr?  cache_factoryr   c                 K   s8  |pd}t |tr|dk rtd|| _|| _|| _d | _|| _|ds*|drd| jddvr6t	d| jd}|d urMt |t
sItd	|| _n| jd urY| j | _nt| jd | _|dd  |dd  | jd
d | _| jd u rt | _t | _t | _tj| fd|i| |   d S )Nl        r   z,"max_connections" must be a positive integercache_configr  r  r`  z4Client caching is only supported with RESP version 3z#Cache must implement CacheInterfacer  r   )rH   r   r   rA  _connection_kwargsr?  r  _cache_factoryrf  r,   r   	get_cacher   popr  r%   r  r  
_fork_lock_lockr_  rd   rP  )rT   rA  r?  r  r   rc  r  rY   rY   rZ   rd   	  sL   





zConnectionPool.__init__c                 C   sN   d dd | j D }d| jj d| jj d| jj d| jj d| dS )	Nr2  c                 S   r3  r4  rY   r6  rY   rY   rZ   r:  	  r;  z+ConnectionPool.__repr__.<locals>.<listcomp>r<  r=  z(<r>  z)>)>)rf   rc  r  r?  r]   r\   rA  )rT   conn_kwargsrY   rY   rZ   rA  	  s   zConnectionPool.__repr__c                 C   r   ra   r  rs   rY   rY   rZ   rc  	  r   z ConnectionPool.connection_kwargsrW   c                 C   r   ra   r  r   rY   rY   rZ   rc  	  r   c                 C   s   | j ddS )r   r  N)rc  rf  rs   rY   rY   rZ   r}   	  s   zConnectionPool.get_protocolc                 C   s"   d| _ g | _t | _t | _d S )Nr   )_created_connections_available_connectionsr  _in_use_connectionsr  r  r  rs   rY   rY   rZ   rP  	  s   zConnectionPool.resetc                 C   sl   | j t kr4| jjdd}|stz| j t kr&|   W | j  d S W | j  d S | j  w d S )N   )r   )r  r  r  r  acquirer(   rP  r[  )rT   acquiredrY   rY   rZ   	_checkpid	  s   #
zConnectionPool._checkpidrQ  rR  rS  rT  r  c              
   O   s   |    | j# z| j }W n ty   |  }Y nw | j| W d   n1 s-w   Y  z@|  z|	 rI| j
du rM|  sQtdW W |S W W |S W W |S  tttfyr   |  |  |	 rntdY W |S w  ty   | |  w )zGet a connection from the poolNConnection has dataConnection not ready)r  r  r  r  
IndexErrormake_connectionr  addr~   r   r  rh  r)   r.   r   r   r}  r[  rT   rW  r  rX  r  rY   rY   rZ   rY  
  sH   

zConnectionPool.get_connectionc                 C   s,   | j }t|dd|dd|dddS )z,Return an encoder based on encoding settingsr  r  r  r  r  F)r  r  r  )rc  r   rf  rx  rY   rY   rZ   rZ  A
  s   


zConnectionPool.get_encoderrq   c                 C   sb   | j | jkr
td|  j d7  _ t| j}| jdur)t| jdi || j| jS | jdi |S )zCreate a new connectionzToo many connectionsr   NrY   )	r  r?  r+   dictrc  r  r  rA  r  rx  rY   rY   rZ   r  J
  s   

zConnectionPool.make_connectionr  c              	   C   s   |    | jK z| j| W n ty    Y W d   dS w | |r=| r.|  | j	| | j
t| n|  	 W d   dS W d   dS 1 sUw   Y  dS )z(Releases the connection back to the poolN)r  r  r  rG  KeyErrorowns_connectionr   r   r  rM   r  dispatchr$   r  rY   rY   rZ   r[  X
  s(   
"zConnectionPool.releasec                 C   s   |j | j kS ra   )r  r  rY   rY   rZ   r  r
  r  zConnectionPool.owns_connectionTr\  c                 C   s`   |    | j |rt| j| j}n| j}|D ]}|  qW d   dS 1 s)w   Y  dS )a  
        Disconnects connections in the pool

        If ``inuse_connections`` is True, disconnect connections that are
        currently in use, potentially by other threads. Otherwise only disconnect
        connections that are idle in the pool.
        N)r  r  r   r  r  r   rT   r\  connectionsr  rY   rY   rZ   r   u
  s   
"zConnectionPool.disconnectc                 C   ru  )z-Close the pool, disconnecting all connectionsNrP  rs   rY   rY   rZ   rm  
  rx  zConnectionPool.closer  c                 C   s8   | j d|i | jD ]}||_q| jD ]}||_qd S )Nr  )rc  rk  r  r  r  )rT   r  r  rY   rY   rZ   r]  
  s   

zConnectionPool.set_retryr   c                    s   j 9 jD ]!  j fddfdd  j fddfdd qjD ]   q,W d    d S 1 s?w   Y  d S )Nc                      s     dd S r  )r   r  r  rY   )r  r   rY   rZ   rM  
  s    z1ConnectionPool.re_auth_callback.<locals>.<lambda>c                    rO  ra   _mockrQ  rs   rY   rZ   rM  
  rS  c                      rK  ra   )r   rY   )r  rY   rZ   rM  
  rN  c                    rO  ra   r  rQ  rs   rY   rZ   rM  
  rS  )r  r  r  rU  r  r   r   rY   )r  rT   r   rZ   r^  
  s   


"zConnectionPool.re_auth_callbackc                 C   r   ra   )r  rs   rY   rY   rZ   rd  
  rH  zConnectionPool._get_pool_lockc                 C   0   | j  | jW  d    S 1 sw   Y  d S ra   )r  r  rs   rY   rY   rZ   re  
     $z$ConnectionPool._get_free_connectionsc                 C   r  ra   )r  r  rs   rY   rY   rZ   rf  
  r  z&ConnectionPool._get_in_use_connectionsrR  c                    s   dS )z
        Dummy functions, needs to be passed as error callback to retry object.
        :param error:
        :return:
        NrY   rv  rY   rY   rZ   r  
  s   zConnectionPool._mockrp   ra   )r`   r  )r`   rq   )r  r  r`   Nr   )+r\   r]   r^   r   classmethodr   rL  rI   r  r  r   r   r   r0   rd   rA  r   r
   r   rc  r  r}   rP  r  r8   rY  r   rZ  r  r[  r  r  r   rm  r3   r]  r    r^  rd  re  rf  r,   r  rY   rY   rY   rZ   rM  :	  sR    2
@

/%
	

c                       s   e Zd ZdZddeef fdd	Zdd Zdd	 Ze	d
gddddddZ
dd ZddefddZdd Zdd ZdefddZ  ZS ) BlockingConnectionPoola  
    Thread-safe blocking connection pool::

        >>> from redis.client import Redis
        >>> client = Redis(connection_pool=BlockingConnectionPool())

    It performs the same function as the default
    :py:class:`~redis.ConnectionPool` implementation, in that,
    it maintains a pool of reusable connections that can be shared by
    multiple redis clients (safely across threads if required).

    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.ConnectionPool` implementation does), it
    makes the client wait ("blocks") 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      c                    s4   || _ || _d| _d| _t jd||d| d S )NF)rA  r?  rY   )queue_classr   _in_maintenance_lockedr  rd   )rT   r?  r   rA  r  rc  r  rY   rZ   rd   
  s   
zBlockingConnectionPool.__init__c                 C   s   zB| j r| j  d| _| | j| _	 z| jd  W n	 ty%   Y nw qg | _	W | jrBz| j
  W n	 ty>   Y nw d| _n| jrZz| j
  W n	 tyV   Y nw d| _w t | _d S )NTF)r  r  r  r  r  r?  pool
put_nowaitr   _connectionsr[  r   r  r  r  rs   rY   rY   rZ   rP  
  s:   
zBlockingConnectionPool.resetc                 C   s   zJ| j r| j  d| _| jdur!t| jdi | j| j| j}n	| jdi | j}| j	| |W | jrJz| j
  W n	 tyE   Y nw d| _S S | jrbz| j
  W n	 ty^   Y nw d| _w )zMake a fresh connection.TNFrY   )r  r  r  r  r  r  rA  rc  r  rM   r[  r   r  rY   rY   rZ   r    s6   

z&BlockingConnectionPool.make_connectionrQ  rR  rS  rT  Nc                 O   s>  |    d}zC| jr| j  d| _z| jjd| jd}W n ty(   t	dw |du r1| 
 }W | jrIz| j  W n	 tyE   Y nw d| _n| jraz| j  W n	 ty]   Y nw d| _w z/|  z| rpt	dW W |S  t	ttfy   |  |  | rt	dY W |S w  ty   | |  w )a7  
        Get a connection, blocking for ``self.timeout`` until a connection
        is available from the pool.

        If the connection returned is ``None`` then creates a new connection.
        Because we use a last-in first-out queue, the existing connections
        (having been returned to the pool after the initial ``None`` values
        were added) will be returned before ``None`` values. This means we only
        create new connections when we need to, i.e.: the actual number of
        connections will only increase in response to demand.
        NT)blockr   zNo connection available.Fr  r  )r  r  r  r  r  r  rf  r   r   r)   r  r[  r   r~   r   r.   r   r   r}  r  rY   rY   rZ   rY  '  s`   

z%BlockingConnectionPool.get_connectionc                 C   s  |    zl| jr| j  d| _| |s;|  | jd W | jr9z| j	  W n	 t
y3   Y nw d| _dS dS | rC|  z| j| W n	 tyT   Y nw W | jroz| j	  W n	 t
yi   Y nw d| _dS dS | jrz| j	  W n	 t
y   Y nw d| _w )z)Releases the connection back to the pool.TNF)r  r  r  r  r  r  r   r  r  r[  r   r   r   r  rY   rY   rZ   r[  k  sN   




zBlockingConnectionPool.releaseTr\  c                 C   s   |    z:| jr| j  d| _|r| j}n|  }|D ]}|  qW | jr=z| j  W n	 t	y7   Y nw d| _dS dS | jrVz| j  W n	 t	yR   Y nw d| _w )zLDisconnects either all connections in the pool or just the free connections.TFN)
r  r  r  r  r  r  re  r   r[  r   r  rY   rY   rZ   r     s2   



z!BlockingConnectionPool.disconnectc                 C   s<   | j  dd | jjD W  d    S 1 sw   Y  d S )Nc                 S      h | ]}|r|qS rY   rY   r7  r  rY   rY   rZ   	<setcomp>      z?BlockingConnectionPool._get_free_connections.<locals>.<setcomp>)r  r  queuers   rY   rY   rZ   re    s   $z,BlockingConnectionPool._get_free_connectionsc                    sP   | j  dd | jjD   fdd| jD W  d    S 1 s!w   Y  d S )Nc                 S   r  rY   rY   r  rY   rY   rZ   r    r  zABlockingConnectionPool._get_in_use_connections.<locals>.<setcomp>c                    s   h | ]}| vr|qS rY   rY   r  connections_in_queuerY   rZ   r    s    )r  r  r  r  rs   rY   r  rZ   rf    s   
$z.BlockingConnectionPool._get_in_use_connectionsin_maintenancec                 C   s
   || _ dS )a  
        Sets a flag that this Blocking ConnectionPool is in maintenance mode.

        This is used to prevent new connections from being created while we are in maintenance mode.
        The pool will be in maintenance mode only when we are processing a MOVING notification.
        N)r  )rT   r  rY   rY   rZ   set_in_maintenance  s   
z)BlockingConnectionPool.set_in_maintenancera   r   )r\   r]   r^   r   r  r   rd   rP  r  r8   rY  r[  r  r   re  rf  r  r  rY   rY   r  rZ   r  
  s(    ##?"
r  )rr"  r  r   rQ   r  ry  rD  abcr   r   	itertoolsr   r  r   r   r   typingr   r	   r
   r   r   r   r   r   r   r   urllib.parser   r   r   redis.cacher   r   r   r   r   r   _parsersr   r   r   r   
auth.tokenr    backoffr!   credentialsr"   r#   eventr$   r%   
exceptionsr&   r'   r(   r)   r*   r+   r,   r-   r.   maint_notificationsr/   r0   r1   r2   r  r3   utilsr4   r5   r6   r7   r8   r9   r:   r;   r<   r  r=   rN   rg   rl   ri   re   r+  r  r   __annotations__rB   rC   r_   rq   r   r  r  r  r  r-  r7  r8  r>  r   r  r!  rF  rK  rL  rO  r_  rM  r  rY   rY   rY   rZ   <module>   s   
 0 	,,3g       KS  N 9#9-  Z  