o
    Š¨Êhsó  ã                   @   sn  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 d dl	m
Z
 d dlmZmZmZ d dlmZ d dl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+m,Z, d	dl-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5 d	dl6m7Z7 d	dl8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@ e:r³d dlAZAdZBdZCdZDdZEdZFeGƒ ZHeee&e'e%f  eId< e:rÐe%ZJne&ZJG dd„ dƒZKG dd„ dƒZLG dd„ dƒZMG dd„ deMƒZNG dd„ deNƒZOG d d!„ d!eMƒZPG d"d#„ d#eOƒZQG d$d%„ d%eNƒZRd&ZSd'd(„ ZTeUeVeVeTeTeWeUeUeTeVd)œ
ZXd*d+„ ZYG d,d-„ d-ƒZZG d.d/„ d/eZƒZ[dS )0é    N)Úabstractmethod)Úchain)ÚEmptyÚFullÚ	LifoQueue)Útime)ÚAnyÚCallableÚDictÚListÚOptionalÚTypeÚUnion)Úparse_qsÚunquoteÚurlparse)Ú
CacheEntryÚCacheEntryStatusÚCacheFactoryÚCacheFactoryInterfaceÚCacheInterfaceÚCacheKeyé   )ÚEncoderÚ_HiredisParserÚ_RESP2ParserÚ_RESP3Parser)Ú	NoBackoff)ÚCredentialProviderÚ"UsernamePasswordCredentialProvider)ÚAuthenticationErrorÚ$AuthenticationWrongNumberOfArgsErrorÚChildDeadlockedErrorÚConnectionErrorÚ	DataErrorÚ
RedisErrorÚResponseErrorÚTimeoutError)ÚRetry)ÚCRYPTOGRAPHY_AVAILABLEÚHIREDIS_AVAILABLEÚSSL_AVAILABLEÚcompare_versionsÚensure_stringÚformat_error_messageÚget_lib_versionÚstr_if_bytesó   *ó   $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)Úselfr7   ÚoutputÚ_ÚvalueÚ	traceback© rL   úB/var/www/html/env/lib/python3.10/site-packages/redis/connection.pyÚpackE   s   "üþzHiredisRespSerializer.packN)Ú__name__Ú
__module__Ú__qualname__r   rN   rL   rL   rL   rM   r6   D   s    r6   c                   @   s   e Zd Zddd„Zdd„ ZdS )ÚPythonRespSerializerÚreturnNc                 C   s   || _ || _d S ©N)Ú_buffer_cutoffr>   )rG   Úbuffer_cutoffr>   rL   rL   rM   Ú__init__W   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 r8   )r;   r<   r=   r>   r?   Ú	SYM_EMPTYÚjoinÚSYM_STARÚlenÚSYM_CRLFrU   ÚmapÚ
memoryviewÚ
SYM_DOLLARr@   )rG   r7   rH   ÚbuffrV   ÚargÚ
arg_lengthrL   rL   rM   rN   [   s<   "ÿÿ


úÿ

zPythonRespSerializer.pack©rS   N)rO   rP   rQ   rW   rN   rL   rL   rL   rM   rR   V   s    
rR   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d„ƒZedd„ ƒZed&dd„ƒZe	d'd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d$S )(ÚConnectionInterfacec                 C   ó   d S rT   rL   ©rG   rL   rL   rM   Úrepr_piecesŠ   ó   zConnectionInterface.repr_piecesc                 C   re   rT   rL   ©rG   ÚcallbackrL   rL   rM   Úregister_connect_callbackŽ   rh   z-ConnectionInterface.register_connect_callbackc                 C   re   rT   rL   ri   rL   rL   rM   Úderegister_connect_callback’   rh   z/ConnectionInterface.deregister_connect_callbackc                 C   re   rT   rL   ©rG   Úparser_classrL   rL   rM   Ú
set_parser–   rh   zConnectionInterface.set_parserc                 C   re   rT   rL   rf   rL   rL   rM   Úconnectš   rh   zConnectionInterface.connectc                 C   re   rT   rL   rf   rL   rL   rM   Ú
on_connectž   rh   zConnectionInterface.on_connectc                 G   re   rT   rL   ©rG   r7   rL   rL   rM   Ú
disconnect¢   rh   zConnectionInterface.disconnectc                 C   re   rT   rL   rf   rL   rL   rM   Úcheck_health¦   rh   z ConnectionInterface.check_healthTc                 C   re   rT   rL   ©rG   Úcommandrt   rL   rL   rM   Úsend_packed_commandª   rh   z'ConnectionInterface.send_packed_commandc                 O   re   rT   rL   ©rG   r7   ÚkwargsrL   rL   rM   Úsend_command®   rh   z ConnectionInterface.send_commandr   c                 C   re   rT   rL   ©rG   ÚtimeoutrL   rL   rM   Úcan_read²   rh   zConnectionInterface.can_readF©Údisconnect_on_errorÚpush_requestc                C   re   rT   rL   )rG   Údisable_decodingr   r€   rL   rL   rM   Úread_response¶   s   z!ConnectionInterface.read_responsec                 G   re   rT   rL   rr   rL   rL   rM   rB   À   rh   z ConnectionInterface.pack_commandc                 C   re   rT   rL   ©rG   ÚcommandsrL   rL   rM   Úpack_commandsÄ   rh   z!ConnectionInterface.pack_commandsrS   c                 C   re   rT   rL   rf   rL   rL   rM   Úhandshake_metadataÈ   s   z&ConnectionInterface.handshake_metadataN©T©r   ©F)rO   rP   rQ   r   rg   rk   rl   ro   rp   rq   rs   rt   rw   rz   r}   r‚   rB   r…   Úpropertyr   r
   Úbytesr<   r†   rL   rL   rL   rM   rd   ‰   sH    








þû	

.rd   c                *   @   s  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fd
edee	 dee
 dee
 de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  f&dd„Zdd „ Zed!d"„ ƒZd#d$„ Zd%d&„ Zd'd(„ Zd)d*„ Zd+d,„ Zd-d.„ Zed/d0„ ƒZed1d2„ ƒZd3d4„ Zd5d6„ Zd7d8„ Zd9d:„ Zd;d<„ Z d=d>„ Z!dTd@dA„Z"dBdC„ Z#dUdDdE„Z$	dVd?ddFœdGdH„Z%dIdJ„ Z&dKdL„ Z'dMepÔe	fdNdO„Z(e)dMee*e+e+f e*e	e	f f fdPdQ„ƒZ,e,j-dRee*e+e+f e*e	e	f f fdSdQ„ƒZ,dS )WÚAbstractConnectionz0Manages communication to and from a Redis serverr   NFúutf-8Ústricti   zredis-pyr4   ÚdbÚpasswordÚsocket_timeoutÚsocket_connect_timeoutÚretry_on_timeoutÚ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_packerc                 C   s¦  |s|r|durt dƒ‚t ¡ | _|| _|| _|| _|| _|| _|| _	|| _
|| _|du r/|}|| _|| _|tu r;g }|rB| t¡ || _|sI|rb|du rUttƒ dƒ| _nt |¡| _| j |¡ nttƒ dƒ| _|| _d| _|| _t|||	ƒ| _d| _d| _|| _|   |
¡ g | _!d| _"z-zt#|ƒ}W n t$yŸ   t%}Y n t&y©   t'dƒ‚w W |dk s³|dkr·t'd	ƒ‚|| _(n|dk sÃ|dkrÇt'd	ƒ‚|| _(w |  )|¡| _*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 integerr4   é   zprotocol must be either 2 or 3)+r$   ÚosÚgetpidÚpidr�   r™   rš   r›   rŸ   r�   rœ   r‘   r’   r“   ÚSENTINELr@   r'   Úretry_on_errorr(   r   r�   ÚcopyÚdeepcopyÚupdate_supported_errorsr˜   Únext_health_checkrž   r   Úencoderr†   Ú_sockÚ_socket_read_sizero   Ú_connect_callbacksrU   ÚintrC   ÚDEFAULT_RESP_VERSIONÚ
ValueErrorr#   r    Ú_construct_command_packerÚ_command_packer)rG   r�   r�   r‘   r’   r“   r§   r”   r•   r–   rn   r—   r˜   r™   rš   r›   rœ   r�   rž   rŸ   r    r¡   ÚprL   rL   rM   rW   Ñ   sj   ÿ


ÿ€ýzAbstractConnection.__init__c                 C   s8   d  dd„ |  ¡ D ƒ¡}d| jj› d| jj› d|› d�S )Nú,c                 S   s   g | ]\}}|› d |› �‘qS )ú=rL   )Ú.0ÚkÚvrL   rL   rM   Ú
<listcomp>,  s    z/AbstractConnection.__repr__.<locals>.<listcomp>ú<Ú.ú(ú)>)rY   rg   Ú	__class__rP   rO   )rG   Ú	repr_argsrL   rL   rM   Ú__repr__+  s    zAbstractConnection.__repr__c                 C   re   rT   rL   rf   rL   rL   rM   rg   /  rh   zAbstractConnection.repr_piecesc                 C   s$   z|   ¡  W d S  ty   Y d S w rT   )rs   Ú	Exceptionrf   rL   rL   rM   Ú__del__3  s
   ÿzAbstractConnection.__del__c                 C   s&   |d ur|S t rtƒ S t| j| jjƒS rT   )r*   r6   rR   rU   r¬   r>   )rG   ÚpackerrL   rL   rM   r³   9  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¯   r@   )rG   rj   ÚwmrL   rL   rM   rk   A  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²   ri   rL   rL   rM   rl   M  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®   Ú_parserrm   rL   rL   rM   ro   X  s   zAbstractConnection.set_parserc              
      sà   ˆ j rdS zˆ j ‡ fdd„‡ fdd„¡}W n tjy"   tdƒ‚ ty4 } ztˆ  |¡ƒ‚d}~ww |ˆ _ zˆ j	du rCˆ  
¡  nˆ  	ˆ ¡ W n tyU   ˆ  ¡  ‚ w dd„ ˆ jD ƒˆ _ˆ jD ]}|ƒ }|rm|ˆ ƒ qbdS )z5Connects to the Redis server if not already connectedNc                      s   ˆ   ¡ S rT   )Ú_connectrL   rf   rL   rM   Ú<lambda>f  s    z,AbstractConnection.connect.<locals>.<lambda>c                    s
   ˆ   | ¡S rT   ©rs   )Úerrorrf   rL   rM   rÌ   f  s   
 zTimeout connecting to serverc                 S   s   g | ]}|ƒ r|‘qS rL   rL   )r¸   ÚrefrL   rL   rM   r»   }  s    z.AbstractConnection.connect.<locals>.<listcomp>)r­   r�   Úcall_with_retryÚsocketr|   r'   ÚOSErrorr#   Ú_error_messagerž   rq   r%   rs   r¯   )rG   ÚsockÚerÏ   rj   rL   rf   rM   rp   `  s:   ÿ€ÿ


€ý
€ýzAbstractConnection.connectc                 C   re   rT   rL   rf   rL   rL   rM   rË   ƒ  rh   zAbstractConnection._connectc                 C   re   rT   rL   rf   rL   rL   rM   Ú_host_error‡  rh   zAbstractConnection._host_errorc                 C   s   t |  ¡ |ƒS rT   )r.   rÖ   )rG   Ú	exceptionrL   rL   rM   rÓ   ‹  ó   z!AbstractConnection._error_messagec                 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 Ž  |  ¡ | _nt|r”| jdg|¢R dd	iŽ z|  ¡ }W n tyˆ   | jd|d
 d	d� |  ¡ }Y nw t|ƒdkr“tdƒ‚n=| jdvrÑt| j t	ƒr¯|  
t¡ |j| j _| j  | ¡ |  d| j¡ |  ¡ | _| j d¡| jkrÑ| j d¡| jkrÑtdƒ‚| jrè|  dd| j¡ t|  ¡ ƒdkrètdƒ‚z| jrù|  ddd| j¡ |  ¡  W n
 t�y   Y nw z| j�r|  ddd| j¡ |  ¡  W n
 t�y"   Y nw | j�r;|  d| j¡ t|  ¡ ƒdk�r=tdƒ‚dS dS )z=Initialize the connection, authenticate and select a databaseN)r4   Ú2r   Údefaultr   ÚHELLOÚAUTHrt   Féÿÿÿÿ©rt   ÚOKzInvalid Username or Passwords   protoÚprotozInvalid RESP versionÚCLIENTÚSETNAMEzError setting client nameÚSETINFOzLIB-NAMEzLIB-VERÚSELECTzInvalid Database)rÊ   rq   rŸ   rœ   r�   r   Úget_credentialsr    r;   r   ro   r   ÚEXCEPTION_CLASSESr[   rz   r‚   r†   r!   r0   r    Úgetr#   r™   rš   r&   r›   r�   )rG   ÚparserÚ	auth_argsÚcred_providerÚauth_responserL   rL   rM   rq   Ž  s€   þ

úÿ



€ÿ€ÿýzAbstractConnection.on_connectc              	   G   s|   | j  ¡  | j}d| _|du rdS t ¡ | jkr,z| tj¡ W n t	t
fy+   Y nw z| ¡  W dS  t	y=   Y dS w )z!Disconnects from the Redis serverN)rÊ   Úon_disconnectr­   r£   r¤   r¥   ÚshutdownrÑ   Ú	SHUT_RDWRrÒ   rC   Úclose)rG   r7   Ú	conn_sockrL   rL   rM   rs   è  s    
ÿÿzAbstractConnection.disconnectc                 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)rz   r0   r‚   r#   rf   rL   rL   rM   Ú
_send_pingü  s   ÿzAbstractConnection._send_pingc                 C   ó   |   ¡  dS )z Function to call when PING failsNrÍ   )rG   rÎ   rL   rL   rM   Ú_ping_failed  ó   zAbstractConnection._ping_failedc                 C   s0   | 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˜   r   r«   r�   rÐ   ró   rõ   rf   rL   rL   rM   rt     s   ÿzAbstractConnection.check_healthTc              
   C   sæ   | j s|  ¡  |r|  ¡  zt|tƒr|g}|D ]}| j  |¡ qW dS  tjy3   |  ¡  t	dƒ‚ t
yg } z)|  ¡  t|jƒdkrNd|jd }}n
|jd }|jd }td|› d|› d�ƒ‚d}~w tyr   |  ¡  ‚ w )	z2Send an already packed command to the Redis serverzTimeout writing to socketr   ÚUNKNOWNr   zError z while writing to socket. r½   N)r­   rp   rt   r;   r<   ÚsendallrÑ   r|   rs   r'   rÒ   r[   r7   r#   ÚBaseException)rG   rv   rt   ÚitemrÕ   ÚerrnoÚerrmsgrL   rL   rM   rw     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 serverrt   TrÞ   N)rw   r´   rN   rç   rx   rL   rL   rM   rz   *  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­   rp   rÖ   rÊ   r}   rÒ   rs   r#   r7   )rG   r|   rÔ   Ú
host_errorrÕ   rL   rL   rM   r}   1  s   €þzAbstractConnection.can_readr~   c             
   C   sä   |   ¡ }z| jdv rts| jj||d�}n| jj|d�}W n> tjy2   |r+|  ¡  td|› �ƒ‚ t	yN } z|r?|  ¡  t
d|› d|j› �ƒ‚d}~w ty[   |rZ|  ¡  ‚ w | jrftƒ | j | _t|tƒrpz|‚~w |S )z0Read the response from a previously sent command)Ú3r¢   )r�   r€   )r�   zTimeout reading from rý   z : N)rÖ   r    r*   rÊ   r‚   rÑ   r|   rs   r'   rÒ   r#   r7   rù   r˜   r   r«   r;   r&   )rG   r�   r   r€   rþ   ÚresponserÕ   rL   rL   rM   r‚   ?  s>   	ÿ€ÿ€ú
z AbstractConnection.read_responsec                 G   ó   | j j|Ž S )r9   )r´   rN   rr   rL   rL   rM   rB   m  rö   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   )	rU   r´   rN   r[   r;   r^   r@   rX   rY   )	rG   r„   rH   ÚpiecesÚbuffer_lengthrV   ÚcmdÚchunkÚchunklenrL   rL   rM   r…   q  s.   ÿ

ðz AbstractConnection.pack_commandsrS   c                 C   ó   | j S rT   )r    rf   rL   rL   rM   Úget_protocol�  ó   zAbstractConnection.get_protocolc                 C   r  rT   ©Ú_handshake_metadatarf   rL   rL   rM   r†   ’  s   z%AbstractConnection.handshake_metadatarJ   c                 C   s
   || _ d S rT   r
  )rG   rJ   rL   rL   rM   r†   –  s   
r‡   rˆ   r‰   ).rO   rP   rQ   Ú__doc__r¦   r5   r/   r°   r   r<   ÚfloatÚboolr   r   r	   r   rW   rÂ   r   rg   rÄ   r³   rk   rl   ro   rp   rË   rÖ   rÓ   rq   rs   ró   rõ   rt   rw   rz   r}   r‚   rB   r…   r  rŠ   r
   r‹   r†   ÚsetterrL   rL   rL   rM   rŒ   Î   sÀ    êþýüûúø	÷
öôóòñðï
îíìë
êZ
#

Z

þû.(,rŒ   c                       sD   e Zd ZdZ					d‡ fdd„	Zd	d
„ Zdd„ Zdd„ Z‡  ZS )Ú
Connectionz4Manages TCP communication to and from a Redis serverÚ	localhostéë  FNr   c                    s<   || _ t|ƒ| _|| _|pi | _|| _tƒ jdi |¤Ž d S ©NrL   )Úhostr°   ÚportÚsocket_keepaliveÚsocket_keepalive_optionsÚsocket_typeÚsuperrW   )rG   r  r  r  r  r  ry   ©rÀ   rL   rM   rW   ž  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@   ©rG   r  rL   rL   rM   rg   ®  s   zConnection.repr_piecesc                 C   s  d}t  | j| j| jt j¡D ]k}|\}}}}}d}zDt   |||¡}| t jt jd¡ | j	rH| t j
t jd¡ | j ¡ D ]\}	}
| t j|	|
¡ q;| | j¡ | |¡ | | j¡ |W   S  tyy } z|}|duro| ¡  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Ñ   Úgetaddrinfor  r  r  ÚSOCK_STREAMÚ
setsockoptÚIPPROTO_TCPÚTCP_NODELAYr  Ú
SOL_SOCKETÚSO_KEEPALIVEr  ÚitemsÚ
settimeoutr’   rp   r‘   rÒ   rï   )rG   ÚerrÚresÚfamilyÚsocktyperà   Ú	canonnameÚsocket_addressrÔ   r¹   rº   rI   rL   rL   rM   rË   ´  s4   ÿ

€ýzConnection._connectc                 C   s   | j › d| j› �S )Nú:)r  r  rf   rL   rL   rM   rÖ   Ý  s   zConnection._host_error)r  r  FNr   ©	rO   rP   rQ   r  rW   rg   rË   rÖ   Ú__classcell__rL   rL   r  rM   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d8dd„Zdd„ Zd9dd „Z	!d:d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d,d-„ Zd.d/„ Z ded)d0fd1d2„Z!d3d4„ Z"d5e#eee$e#e  f  fd6d7„Z%d0S );ÚCacheProxyConnections   fooz7.4.0ÚredisÚconnÚcacheÚ	pool_lockc                 C   s`   t  ¡ | _|| _| jj| _| jj| _| jj| _|| _|| _t	 
¡ | _d | _d | _|  | j¡ d S rT   )r£   r¤   r¥   Ú_connr�   r  r  Ú
_pool_lockÚ_cacheÚ	threadingÚLockÚ_cache_lockÚ_current_command_cache_keyÚ_current_optionsrk   Ú_enable_tracking_callback)rG   r0  r1  r2  rL   rL   rM   rW   æ  s   




zCacheProxyConnection.__init__c                 C   s
   | j  ¡ S rT   )r3  rg   rf   rL   rL   rM   rg   ø  s   
z CacheProxyConnection.repr_piecesc                 C   ó   | j  |¡ d S rT   )r3  rk   ri   rL   rL   rM   rk   û  ó   z.CacheProxyConnection.register_connect_callbackc                 C   r<  rT   )r3  rl   ri   rL   rL   rM   rl   þ  r=  z0CacheProxyConnection.deregister_connect_callbackc                 C   r<  rT   )r3  ro   rm   rL   rL   rM   ro     r=  zCacheProxyConnection.set_parserc                 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)	r3  rp   r†   rç   r#   r-   ÚDEFAULT_SERVER_NAMEr,   ÚMIN_ALLOWED_VERSION)rG   Úserver_nameÚ
server_verrL   rL   rM   rp     s"   

ÿþzCacheProxyConnection.connectc                 C   ó   | j  ¡  d S rT   )r3  rq   rf   rL   rL   rM   rq     rØ   zCacheProxyConnection.on_connectc                 G   s@   | j � | j ¡  W d   ƒ n1 sw   Y  | jj|Ž  d S rT   )r8  r5  Úflushr3  rs   rr   rL   rL   rM   rs     s   ÿzCacheProxyConnection.disconnectc                 C   rD  rT   )r3  rt   rf   rL   rL   rM   rt   #  rØ   z!CacheProxyConnection.check_healthTc                 C   r<  rT   )r3  rw   ru   rL   rL   rM   rw   &  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 sˆw   Y  	 W d   ƒ d S | j t| j| jtj| jd�¡ W d   ƒ n1 s°w   Y  | jj|i |¤Ž d S )	Nr   rL   )rv   Ú
redis_keysÚkeyszCannot create cache key.T©r€   )Ú	cache_keyÚcache_valueÚstatusÚconnection_ref)Ú_process_pending_invalidationsr8  r5  Úis_cachabler   r9  r3  rz   rç   r²   r=   rL  r4  r}   r‚   Úsetr   ÚDUMMY_CACHE_VALUEr   ÚIN_PROGRESS)rG   r7   ry   ÚentryrL   rL   rM   rz   +  sH   úýÿ

ÿ€ÿôüÿðz!CacheProxyConnection.send_commandr   c                 C   ó   | j  |¡S rT   )r3  r}   r{   rL   rL   rM   r}   [  ó   zCacheProxyConnection.can_readFr~   c                C   s@  | j �3 | jd ur/| j | j¡d ur/| j | j¡jtjkr/t | j | j¡j	¡W  d   ƒ S W d   ƒ n1 s9w   Y  | j
j|||d�}| j �L | jd u rY|W  d   ƒ S |d u rn| j | jg¡ |W  d   ƒ S | j | j¡}|d urŽtj|_||_	| j |¡ W d   ƒ |S W d   ƒ |S 1 s™w   Y  |S )N)r�   r   r€   )r8  r9  r5  rç   rK  r   rQ  r¨   r©   rJ  r3  r‚   Údelete_by_cache_keysÚVALIDrO  )rG   r�   r   r€   r   Úcache_entryrL   rL   rM   r‚   ^  sJ   
ÿÿø€ ý
ýù	
ðû
óîz"CacheProxyConnection.read_responsec                 G   r  rT   )r3  rB   rr   rL   rL   rM   rB   ‡  rT  z!CacheProxyConnection.pack_commandc                 C   rS  rT   )r3  r…   rƒ   rL   rL   rM   r…   Š  rT  z"CacheProxyConnection.pack_commandsrS   c                 C   s   | j jS rT   )r3  r†   rf   rL   rL   rM   r†   �  s   z'CacheProxyConnection.handshake_metadatac                 C   rD  rT   )r3  rË   rf   rL   rL   rM   rË   ‘  rØ   zCacheProxyConnection._connectc                 C   rD  rT   )r3  rÖ   rf   rL   rL   rM   rÖ   ”  rØ   z CacheProxyConnection._host_errorNc                 C   s(   |  ddd¡ | ¡  |j | j¡ d S )Nrá   ÚTRACKINGÚON)rz   r‚   rÊ   Úset_invalidation_push_handlerÚ_on_invalidation_callback)rG   r0  rL   rL   rM   r;  —  s   z.CacheProxyConnection._enable_tracking_callbackc                 C   s&   |   ¡ r| jjdd� |   ¡ sd S d S )NTrH  )r}   r3  r‚   rf   rL   rL   rM   rM  œ  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   )r8  r5  rE  Údelete_by_redis_keys)rG   r\  rL   rL   rM   r[     s   û"ýz.CacheProxyConnection._on_invalidation_callbackr‡   rˆ   r‰   )&rO   rP   rQ   rP  rA  r@  rd   r   r6  r7  rW   rg   rk   rl   ro   rp   rq   rs   rt   rw   rz   r}   r‚   rB   r…   rŠ   r   r
   r‹   r<   r†   rË   rÖ   r;  rM  r   r   r[  rL   rL   rL   rM   r.  á  sF    þý
ü

0ÿÿ)(&r.  c                       sR   e Zd ZdZ														d‡ fdd„	Z‡ fdd„Zd	d
„ Z‡  ZS )ÚSSLConnectionzåManages 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ÚrequiredFc                    sÀ   t stdƒ‚|| _|| _|du rtj}nt|tƒr1tjtjtj	dœ}||vr-t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). Defaults to "required".
            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 False.
            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: rL   )r+   r%   ÚkeyfileÚcertfileÚsslÚ	CERT_NONEr;   r<   ÚCERT_OPTIONALÚCERT_REQUIREDÚ	cert_reqsÚ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  rW   )rG   Ússl_keyfileÚssl_certfileÚssl_cert_reqsÚssl_ca_certsÚssl_ca_dataÚssl_check_hostnameÚssl_ca_pathÚssl_passwordrn  ro  rp  rq  rr  rs  ry   Ú	CERT_REQSr  rL   rM   rW   ¯  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  rË   Ú_wrap_socket_with_sslrÒ   r%   rï   ©rG   rÔ   r  rL   rM   rË   ÷  s   
þzSSLConnection._connectc           
      C   s¸  t  ¡ }| j|_| j|_| js| jr|j| j| j| jd� | j	dus,| j
dus,| jdur7|j| j	| j
| jd� | jdur@| j|_| jrI| | j¡ | jdu rVtdu rVtdƒ‚| jr`| jr`tdƒ‚|j|| jd�}| jr¹d	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 rÚtrÚd
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.
        )rc  rb  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),rd  Úcreate_default_contextrl  rh  Úverify_moderc  rb  Úload_cert_chainrm  ri  rk  rj  Úload_verify_locationsrr  Úminimum_versionrs  Úset_ciphersrn  r)   r%   ro  Úwrap_socketr  ÚOpenSSLÚocsprƒ  rp  ÚSSLÚContextÚSSLv23_METHODÚuse_certificate_fileÚuse_privatekey_fileÚset_ocsp_client_callbackrq  r  rÑ   Úrequest_ocsprp   r  Údo_handshakerí   r„  Úis_validr#   )
rG   rÔ   ÚcontextÚsslsockrŒ  rƒ  Ú
staple_ctxÚconr„  ÚorL   rL   rM   r}    sd   
ý


ÿ
ÿ
ÿz#SSLConnection._wrap_socket_with_ssl)NNr_  NNFNNFFNNNN)rO   rP   rQ   r  rW   rË   r}  r-  rL   rL   r  rM   r^  ©  s&    ñH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  rW   Úpathr‘   )rG   rž  r‘   ry   r  rL   rM   rW   U  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™   r@   r  rL   rL   rM   rg   Z  s   z&UnixDomainSocketConnection.repr_piecesc                 C   sV   t   t jt j¡}| | j¡ z| | j¡ W n ty"   | ¡  ‚ w | | j	¡ |S )z&Create a Unix domain socket connection)
rÑ   ÚAF_UNIXr  r$  r’   rp   rž  rÒ   rï   r‘   r~  rL   rL   rM   rË   `  s   ýz#UnixDomainSocketConnection._connectc                 C   r  rT   )rž  rf   rL   rL   rM   rÖ   m  r	  z&UnixDomainSocketConnection._host_error)r�  Nr,  rL   rL   r  rM   rœ  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)r;   r<   ÚupperÚFALSE_STRINGSr  )rJ   rL   rL   rM   Úto_boolt  s
   r§  )
r�   r‘   r’   r  r“   r§   Úmax_connectionsr˜   ry  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r‹t| jƒ|d< | jr•t| jƒ|d< | jr·d|vr·ztt| jƒ dd¡ƒ|d< W n ttfy¶   Y nw | jdkrÀt|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#  r[   r   ÚURL_QUERY_ARGUMENT_PARSERSrç   rC   rœ   r�   Úschemerž  rœ  Úhostnamer  r°   ÚreplaceÚAttributeErrorr^  )Úurlry   ÚnamerJ   rè   rL   rL   rM   Ú	parse_urlŠ  sZ   ÿþýÿ
ÿ€
ðÿ
r¶  c                   @   sÚ   e Zd ZdZedd„ ƒZeddfdee dee	 fdd„Z
d	eeffd
d„Zdd„ Zd*dd„Zd*dd„Zded	dfdd„Zd	efdd„Zd+dd„Zd,dd„Zddd	efdd„Zd-d!ed	dfd"d#„Zd*d$d%„Zd.d(d)„ZdS )/ÚConnectionPoola¬  
    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.

    Any additional keyword arguments are passed to the constructor of
    ``connection_class``.
    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.
        rª  NrL   )r¶  Úupdate)Úclsr´  ry   Úurl_optionsrL   rL   rM   Úfrom_urlÑ  s
   )
zConnectionPool.from_urlNr¨  Úcache_factoryc                 K   sô   |pd}t |tƒr|dk rtdƒ‚|| _|| _|| _d | _|| _| d¡s*| d¡rc| d¡dvr5t	dƒ‚| j d¡}|d urLt |t
ƒsHtd	ƒ‚|| _n| jd urX| j ¡ | _nt| j d¡ƒ ¡ | _| dd ¡ | dd ¡ t ¡ | _|  ¡  d S )
Nl        r   z,"max_connections" must be a positive integerÚcache_configr1  r    )r¢   rÿ   z4Client caching is only supported with RESP version 3z#Cache must implement CacheInterface)r;   r°   r²   rª  Úconnection_kwargsr¨  r1  Ú_cache_factoryrç   r%   r   Ú	get_cacher   Úpopr6  r7  Ú
_fork_lockÚreset)rG   rª  r¨  r¼  r¾  r1  rL   rL   rM   rW     s6   


ÿþ

zConnectionPool.__init__rS   c              
   C   s6   dt | ƒj› dt | ƒj› dt| jdi | j¤Žƒ› d�S )Nr¼   r½   r¾   r¿   rL   )ÚtyperP   rO   Úreprrª  r¾  rf   rL   rL   rM   rÂ   4  s   ÿÿzConnectionPool.__repr__c                 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)r¾  rç   rf   rL   rL   rM   r  :  s   zConnectionPool.get_protocolc                 C   s,   t  ¡ | _d| _g | _tƒ | _t ¡ | _	d S )Nr   )
r6  r7  Ú_lockÚ_created_connectionsÚ_available_connectionsrO  Ú_in_use_connectionsr£   r¤   r¥   rf   rL   rL   rM   rÃ  B  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"   rÃ  Úrelease)rG   ÚacquiredrL   rL   rM   Ú	_checkpidS  s   #
ýözConnectionPool._checkpidÚcommand_namer  c              	   O   sî   |   ¡  | j�# z| j ¡ }W n ty   |  ¡ }Y nw | j |¡ W d  ƒ n1 s-w   Y  z7| ¡  z| 	¡ rE| j
du rItdƒ‚W W |S W W |S  ttfyi   | ¡  | ¡  | 	¡ retdƒ‚Y W |S w  tyv   |  |¡ ‚ w )zGet a connection from the poolNúConnection has dataúConnection not ready)rÎ  rÆ  rÈ  rÁ  Ú
IndexErrorÚmake_connectionrÉ  Úaddrp   r}   r1  r#   rÒ   rs   rù   rÌ  ©rG   rÏ  rG  ÚoptionsÚ
connectionrL   rL   rM   Úget_connection‚  s<   ÿûÿóõÿõ
ü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–   )r¾  r   rç   )rG   ry   rL   rL   rM   Úget_encoder£  s   


ýzConnectionPool.get_encoderrd   c                 C   s\   | j | jkr
tdƒ‚|  j d7  _ | jdur%t| jdi | j¤Ž| j| jƒS | jdi | j¤ŽS )zCreate a new connectionzToo many connectionsr   NrL   )rÇ  r¨  r#   r1  r.  rª  r¾  rÆ  rf   rL   rL   rM   rÓ  ¬  s   
ÿzConnectionPool.make_connectionr×  c              	   C   s˜   |   ¡  | j�; z| j |¡ W n	 ty   Y nw |  |¡r&| j |¡ n|  jd8  _| 	¡  	 W d  ƒ dS W d  ƒ dS 1 sEw   Y  dS )z(Releases the connection back to the poolr   N)
rÎ  rÆ  rÉ  rÉ   ÚKeyErrorÚowns_connectionrÈ  r@   rÇ  rs   ©rG   r×  rL   rL   rM   rÌ  ¹  s   ý
ð	"÷zConnectionPool.releasec                 C   s   |j | j kS rT   )r¥   rÜ  rL   rL   rM   rÛ  Î  rT  zConnectionPool.owns_connectionTÚinuse_connectionsc                 C   s`   |   ¡  | j� |rt| j| jƒ}n| j}|D ]}| ¡  qW d  ƒ dS 1 s)w   Y  dS )zÿ
        Disconnects connections in the pool

        If ``inuse_connections`` is True, disconnect connections that are
        current in use, potentially by other threads. Otherwise only disconnect
        connections that are idle in the pool.
        N)rÎ  rÆ  r   rÈ  rÉ  rs   )rG   rÝ  Úconnectionsr×  rL   rL   rM   rs   Ñ  s   ÿ
ÿ"øzConnectionPool.disconnectc                 C   rô   )z-Close the pool, disconnecting all connectionsNrÍ   rf   rL   rL   rM   rï   å  rö   zConnectionPool.closer�   r(   c                 C   s8   | j  d|i¡ | jD ]}||_q| jD ]}||_qd S )Nr�   )r¾  r¸  rÈ  r�   rÉ  )rG   r�   r0  rL   rL   rM   Ú	set_retryé  s   

ÿzConnectionPool.set_retryrc   )rS   rd   )r×  r  rS   Nr‡   )r�   r(   rS   N)rO   rP   rQ   r  Úclassmethodr»  r  r   r°   r   rW   r<   rÂ   r  rÃ  rÎ  rØ  r   rÙ  rÓ  rÌ  rÛ  r  rs   rï   rß  rL   rL   rL   rM   r·  Ã  s0    
2üý
ü2

/!
	

r·  c                       sR   e Zd ZdZddeef‡ fdd„	Zdd„ Zdd	„ Zd
d„ Z	dd„ Z
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                    s(   || _ || _tƒ jd||dœ|¤Ž d S )N)rª  r¨  rL   )Úqueue_classr|   r  rW   )rG   r¨  r|   rª  rä  r¾  r  rL   rM   rW     s   þ
ýzBlockingConnectionPool.__init__c                 C   sJ   |   | j¡| _	 z| j d ¡ W n	 ty   Y nw qg | _t ¡ | _d S rT   )	rä  r¨  ÚpoolÚ
put_nowaitr   Ú_connectionsr£   r¤   r¥   rf   rL   rL   rM   rÃ  #  s   ÿýzBlockingConnectionPool.resetc                 C   sL   | j durt| jdi | j¤Ž| j | jƒ}n	| jdi | j¤Ž}| j |¡ |S )zMake a fresh connection.NrL   )r1  r.  rª  r¾  rÆ  rç  r@   rÜ  rL   rL   rM   rÓ  ;  s   
ÿz&BlockingConnectionPool.make_connectionc              	   O   sÂ   |   ¡  d}z| jjd| jd�}W n ty   tdƒ‚w |du r%|  ¡ }z.| ¡  z| ¡ r3tdƒ‚W W |S  tt	fyS   | 
¡  | ¡  | ¡ rOt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.rÐ  rÑ  )rÎ  rå  rç   r|   r   r#   rÓ  rp   r}   rÒ   rs   rù   rÌ  rÕ  rL   rL   rM   rØ  F  s8   ýÿöÿö
ýz%BlockingConnectionPool.get_connectionc                 C   sR   |   ¡  |  |¡s| ¡  | j d¡ dS z	| j |¡ W dS  ty(   Y dS w )z)Releases the connection back to the pool.N)rÎ  rÛ  rs   rå  ræ  r   rÜ  rL   rL   rM   rÌ  z  s   
ýzBlockingConnectionPool.releasec                 C   s    |   ¡  | jD ]}| ¡  qdS )z(Disconnects all connections in the pool.N)rÎ  rç  rs   rÜ  rL   rL   rM   rs   �  s   

ÿz!BlockingConnectionPool.disconnect)rO   rP   rQ   r  r  r   rW   rÃ  rÓ  rØ  rÌ  rs   r-  rL   rL   r  rM   rá  ñ  s    #û4rá  )\r¨   r£   rÑ   rd  rD   r6  rÆ   Úabcr   Ú	itertoolsr   Úqueuer   r   r   r   Útypingr   r	   r
   r   r   r   r   Úurllib.parser   r   r   Úredis.cacher   r   r   r   r   r   Ú_parsersr   r   r   r   Úbackoffr   Úcredentialsr   r   Ú
exceptionsr    r!   r"   r#   r$   r%   r&   r'   r�   r(   Úutilsr)   r*   r+   r,   r-   r.   r/   r0   rA   rZ   r_   r\   rX   r±   Úobjectr¦   Ú__annotations__r5   r6   rR   rd   rŒ   r  r.  r^  rœ  r¦  r§  r°   r  Úlistr¯  r¶  r·  rá  rL   rL   rL   rM   Ú<module>   s~   
 $ 	(
(3E   PF I *	ö9  0