o
    svXj’Ú  ã                   @   sÌ  d dl mZ d dlmZ d dlmZ d dlm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mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZ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+m,Z,m-Z-m.Z.m/Z/ d dl0m1Z1 zd dl2Z2d	Z3W n e4y“   d
Z3Y nw eej5iZ6e3r°e7e2dƒr«de6e2j8< de6e2j9< nde6e2j:< e
j;e6vrºde6e
j;< e<e6 =¡ ƒZ>e1rïd dl?Z?ee?j@ƒZAeAedƒkZBeAedƒkZCeAedƒkZDeCséde?j@ ZEe FeE¡ d	ZGeCsïd
ZGdZHdZIdZJdZKdZLeMƒ ZNG dd„ deMƒZOG dd„ deMƒZPG dd„ deMƒZQG dd„ dePƒZRG dd „ d ePƒZSe1�r*eSZTneRZTG d!d"„ d"eMƒZUG d#d$„ d$eUƒZVG d%d&„ d&eUƒZWd'ZXd(d)„ ZYeZeZeYeYe[e[eYd*œZ\G d+d,„ d,eMƒZ]G d-d.„ d.e]ƒZ^dS )/é    )Úunicode_literals)ÚStrictVersion)Úchain)ÚtimeN)ÚxrangeÚimapÚunicodeÚlongÚ	nativestrÚ
basestringÚ	iteritemsÚ	LifoQueueÚEmptyÚFullÚurlparseÚparse_qsÚrecvÚ	recv_intoÚunquoteÚBlockingIOErrorÚsendallÚshutdownÚssl_wrap_socket)ÚAuthenticationErrorÚ$AuthenticationWrongNumberOfArgsErrorÚBusyLoadingErrorÚChildDeadlockedErrorÚConnectionErrorÚ	DataErrorÚExecAbortErrorÚInvalidResponseÚNoPermissionErrorÚNoScriptErrorÚReadOnlyErrorÚ
RedisErrorÚResponseErrorÚTimeoutError)ÚHIREDIS_AVAILABLETFÚSSLWantReadErroré   iÁ½ðÿz0.1.3z0.1.4z1.0.0z`redis-py works best with hiredis >= 0.1.4. You're running hiredis %s. Please consider upgrading.ó   *ó   $s   
ó    zConnection closed by server.c                   @   s*   e Zd ZdZdd„ Zdd„ Zd
dd„Zd	S )ÚEncoderz=Encode strings to bytes-like and decode bytes-like to stringsc                 C   s   || _ || _|| _d S ©N©ÚencodingÚencoding_errorsÚdecode_responses)Úselfr0   r1   r2   © r4   úM/var/www/html/myproject/venv/lib/python3.10/site-packages/redis/connection.pyÚ__init__b   ó   
zEncoder.__init__c                 C   s–   t |ttfƒr	|S t |tƒrtdƒ‚t |tƒrt|ƒ ¡ }nt |tt	fƒr,t
|ƒ ¡ }nt |tƒs<t|ƒj}td| ƒ‚t |tƒrI| | j| j¡}|S )z=Return a bytestring or bytes-like representation of the valuezNInvalid input of type: 'bool'. Convert to a bytes, string, int or float first.zLInvalid input of type: '%s'. Convert to a bytes, string, int or float first.)Ú
isinstanceÚbytesÚ
memoryviewÚboolr   ÚfloatÚreprÚencodeÚintr	   Ústrr   ÚtypeÚ__name__r   r0   r1   )r3   ÚvalueÚtypenamer4   r4   r5   r>   g   s    



ÿ
zEncoder.encodeFc                 C   s:   | j s|rt|tƒr| ¡ }t|tƒr| | j| j¡}|S )z:Return a unicode string from the bytes-like representation)r2   r8   r:   Útobytesr9   Údecoder0   r1   )r3   rC   Úforcer4   r4   r5   rF   }   s   


zEncoder.decodeN)F)rB   Ú
__module__Ú__qualname__Ú__doc__r6   r>   rF   r4   r4   r4   r5   r-   _   s
    r-   c                   @   s4   e Zd Zeeeeedœeeee	ee
dœZdd„ ZdS )Ú
BaseParser)zmax number of clients reachedz(Client sent AUTH, but no password is setzinvalid passwordz,wrong number of arguments for 'auth' commandz,wrong number of arguments for 'AUTH' command)ÚERRÚ	EXECABORTÚLOADINGÚNOSCRIPTÚREADONLYÚNOAUTHÚNOPERMc                 C   s\   |  d¡d }|| jv r*|t|ƒd d… }| j| }t|tƒr&| |t¡}||ƒS t|ƒS )zParse an error responseú r   é   N)ÚsplitÚEXCEPTION_CLASSESÚlenr8   ÚdictÚgetr%   )r3   ÚresponseÚ
error_codeÚexception_classr4   r4   r5   Úparse_errorž   s   


zBaseParser.parse_errorN)rB   rH   rI   r   r   r   r   r   r"   r#   r!   rV   r]   r4   r4   r4   r5   rK   ‡   s    õírK   c                   @   sX   e Zd Zdd„ Zedd„ ƒZdedfdd„Zd	d
„ Zdd„ Z	dd„ Z
dd„ Zdd„ ZdS )ÚSocketBufferc                 C   s,   || _ || _|| _t ¡ | _d| _d| _d S ©Nr   )Ú_sockÚsocket_read_sizeÚsocket_timeoutÚioÚBytesIOÚ_bufferÚbytes_writtenÚ
bytes_read)r3   Úsocketra   rb   r4   r4   r5   r6   «   s   

zSocketBuffer.__init__c                 C   s   | j | j S r.   )rf   rg   ©r3   r4   r4   r5   Úlengthµ   s   zSocketBuffer.lengthNTc              
   C   sp  | j }| j}| j}| | j¡ d}|tu}z˜zH|r| |¡ 	 t| j |ƒ}	t|	t	ƒr4t
|	ƒdkr4ttƒ‚| |	¡ t
|	ƒ}
|  j|
7  _||
7 }|d urQ||krQqW W |r]| | j¡ dS dS  tjyz   |rltdƒ‚Y W |rx| | j¡ dS dS  ty­ } z(t |jd¡}|s¡|j|kr¡W Y d }~W |rŸ| | j¡ dS dS td|jf ƒ‚d }~ww |r·| | j¡ w w ©Nr   TzTimeout reading from socketFéÿÿÿÿz#Error while reading from socket: %s)r`   ra   re   Úseekrf   ÚSENTINELÚ
settimeoutr   r8   r9   rW   r   ÚSERVER_CLOSED_CONNECTION_ERRORÚwriterb   rh   Útimeoutr&   ÚNONBLOCKING_EXCEPTIONSÚ#NONBLOCKING_EXCEPTION_ERROR_NUMBERSrY   Ú	__class__ÚerrnoÚargs)r3   rj   rr   Úraise_on_timeoutÚsockra   ÚbufÚmarkerÚcustom_timeoutÚdataÚdata_lengthÚexÚallowedr4   r4   r5   Ú_read_from_socket¹   sZ   

ÿñÿõÿýÿ€øÿzSocketBuffer._read_from_socketc                 C   s   t | jƒp| j|dd�S )NF©rr   rx   )r;   rj   r�   ©r3   rr   r4   r4   r5   Úcan_readä   s
   
ÿÿzSocketBuffer.can_readc                 C   sn   |d }|| j kr|  || j  ¡ | j | j¡ | j |¡}|  jt|ƒ7  _| j| jkr1|  ¡  |d d… S )Nr)   éþÿÿÿ)	rj   r�   re   rm   rg   ÚreadrW   rf   Úpurge)r3   rj   r}   r4   r4   r5   r†   é   s   
zSocketBuffer.readc                 C   s|   | j }| | j¡ | ¡ }| t¡s%|  ¡  | | j¡ | ¡ }| t¡r|  jt|ƒ7  _| j| jkr8|  	¡  |d d… S )Nr…   )
re   rm   rg   ÚreadlineÚendswithÚSYM_CRLFr�   rW   rf   r‡   )r3   rz   r}   r4   r4   r5   rˆ   ú   s   

üzSocketBuffer.readlinec                 C   s&   | j  d¡ | j  ¡  d| _d| _d S r_   )re   rm   Útruncaterf   rg   ri   r4   r4   r5   r‡     s   

zSocketBuffer.purgec                 C   s:   z|   ¡  | j ¡  W n	 ty   Y nw d | _d | _d S r.   )r‡   re   ÚcloseÚ	Exceptionr`   ri   r4   r4   r5   rŒ     s   ú
zSocketBuffer.close)rB   rH   rI   r6   Úpropertyrj   rn   r�   r„   r†   rˆ   r‡   rŒ   r4   r4   r4   r5   r^   ª   s    


ÿ+r^   c                   @   s@   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dS )ÚPythonParserzPlain Python parsing classc                 C   s   || _ d | _d | _d | _d S r.   )ra   Úencoderr`   re   ©r3   ra   r4   r4   r5   r6   $  s   
zPythonParser.__init__c                 C   ó$   z|   ¡  W d S  ty   Y d S w r.   ©Úon_disconnectr�   ri   r4   r4   r5   Ú__del__*  ó
   ÿzPythonParser.__del__c                 C   s(   |j | _ t| j | j|jƒ| _|j| _dS )zCalled when the socket connectsN)r`   r^   ra   rb   re   r�   ©r3   Ú
connectionr4   r4   r5   Ú
on_connect0  s   þzPythonParser.on_connectc                 C   s*   d| _ | jdur| j ¡  d| _d| _dS )z"Called when the socket disconnectsN)r`   re   rŒ   r�   ri   r4   r4   r5   r”   8  s
   


zPythonParser.on_disconnectc                 C   s   | j o| j  |¡S r.   )re   r„   rƒ   r4   r4   r5   r„   @  s   zPythonParser.can_readc                    s  ˆ j  ¡ }|sttƒ‚|d d… |dd … }}|dvr"td| ƒ‚|dkr8t|ƒ}ˆ  |¡}t|tƒr6|‚|S |dkr=n7|dkrFt|ƒ}n.|dkr[t	|ƒ}|dkrTd S ˆ j  
|¡}n|d	krtt	|ƒ}|dkrid S ‡ fd
d„t|ƒD ƒ}t|tƒrˆ j |¡}|S )NrT   )ó   -ó   +ó   :r+   r*   zProtocol Error: %rrš   r›   rœ   r+   rl   r*   c                    s   g | ]}ˆ   ¡ ‘qS r4   )Úread_response)Ú.0Úiri   r4   r5   Ú
<listcomp>k  s    z.PythonParser.read_response.<locals>.<listcomp>)re   rˆ   r   rp   r    r
   r]   r8   r	   r?   r†   r   r9   r�   rF   )r3   ÚrawÚbyterZ   Úerrorrj   r4   ri   r5   r�   C  s:   




zPythonParser.read_responseN)
rB   rH   rI   rJ   r6   r•   r™   r”   r„   r�   r4   r4   r4   r5   r�   "  s    r�   c                   @   sN   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Ze	dfdd„Z
dd„ ZdS )ÚHiredisParserz*Parser class for connections using Hiredisc                 C   s(   t stdƒ‚|| _trt|ƒ| _d S d S )NzHiredis is not installed)r'   r$   ra   ÚHIREDIS_USE_BYTE_BUFFERÚ	bytearrayre   r‘   r4   r4   r5   r6   s  s   ÿzHiredisParser.__init__c                 C   r’   r.   r“   ri   r4   r4   r5   r•   {  r–   zHiredisParser.__del__c                 C   sh   |j | _ |j| _t| jdœ}tst|d< |jjr|jj	|d< t
r&|jj|d< tjdi |¤Ž| _d| _d S )N)ÚprotocolErrorÚ
replyErrorr¨   r0   ÚerrorsFr4   )r`   rb   Ú_socket_timeoutr    r]   Ú HIREDIS_SUPPORTS_CALLABLE_ERRORSr%   r�   r2   r0   Ú HIREDIS_SUPPORTS_ENCODING_ERRORSr1   ÚhiredisÚReaderÚ_readerÚ_next_response)r3   r˜   Úkwargsr4   r4   r5   r™   �  s   þ
zHiredisParser.on_connectc                 C   s   d | _ d | _d| _d S ©NF)r`   r¯   r°   ri   r4   r4   r5   r”   ”  r7   zHiredisParser.on_disconnectc                 C   s@   | j sttƒ‚| jdu r| j  ¡ | _| jdu r| j|dd�S dS )NFr‚   T)r¯   r   rp   r°   ÚgetsÚread_from_socketrƒ   r4   r4   r5   r„   ™  s   

ÿzHiredisParser.can_readTc           	   
   C   s\  | j }|tu}zœzL|r| |¡ tr+t| j | jƒ}|dkr!ttƒ‚| j 	| jd|¡ nt
| j | jƒ}t|tƒr=t|ƒdkrAttƒ‚| j 	|¡ W W |rS| | j¡ dS dS  tjyp   |rbtdƒ‚Y W |rn| | j¡ dS dS  ty£ } z(t |jd¡}|s—|j|kr—W Y d }~W |r•| | j¡ dS dS td|jf ƒ‚d }~ww |r­| | j¡ w w rk   )r`   rn   ro   r¥   r   re   r   rp   r¯   Úfeedr   ra   r8   r9   rW   rª   rh   rr   r&   rs   rt   rY   ru   rv   rw   )	r3   rr   rx   ry   r|   ÚbufflenÚbufferr   r€   r4   r4   r5   r´   ¤  sP   
ÿñÿõÿýÿ€øÿzHiredisParser.read_from_socketc                 C   sÞ   | j sttƒ‚| jdur| j}d| _|S | j  ¡ }|du r*|  ¡  | j  ¡ }|du stsTt|tƒr:|  	|j
d ¡}nt|tƒrT|rTt|d tƒrT|  	|d j
d ¡|d< t|tƒr[|‚t|tƒrm|rmt|d tƒrm|d ‚|S )NFr   )r¯   r   rp   r°   r³   r´   r«   r8   r%   r]   rw   Úlist)r3   rZ   r4   r4   r5   r�   Ê  s2   


þ
ÿ
ÿzHiredisParser.read_responseN)rB   rH   rI   rJ   r6   r•   r™   r”   r„   rn   r´   r�   r4   r4   r4   r5   r¤   q  s    &r¤   c                   @   sÊ   e Zd ZdZddddddddddddded	ddd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d d!„ Zd/d#d$„Zd%d&„ Zd0d'd(„Zd)d*„ Zd+d,„ Zd-d.„ ZdS )1Ú
Connectionz4Manages TCP communication to and from a Redis serverÚ	localhostéë  r   NFúutf-8Ústricté   c                 C   sš   t  ¡ | _|| _t|ƒ| _|| _|| _|| _|| _	|| _
|p|| _|| _|p'i | _|	| _|
| _|| _d| _t|||ƒ| _d | _||d�| _g | _d| _d S ©Nr   )ra   ip  )ÚosÚgetpidÚpidÚhostr?   ÚportÚdbÚusernameÚclient_nameÚpasswordrb   Úsocket_connect_timeoutÚsocket_keepaliveÚsocket_keepalive_optionsÚsocket_typeÚretry_on_timeoutÚhealth_check_intervalÚnext_health_checkr-   r�   r`   Ú_parserÚ_connect_callbacksÚ_buffer_cutoff)r3   rÃ   rÄ   rÅ   rÈ   rb   rÉ   rÊ   rË   rÌ   rÍ   r0   r1   r2   Úparser_classra   rÎ   rÇ   rÆ   r4   r4   r5   r6   ô  s(   




zConnection.__init__c                 C   s(   d  dd„ |  ¡ D ƒ¡}d| jj|f S )Nú,c                 S   s   g | ]
\}}d ||f ‘qS )z%s=%sr4   )rž   ÚkÚvr4   r4   r5   r      s    z'Connection.__repr__.<locals>.<listcomp>ú%s<%s>)ÚjoinÚrepr_piecesru   rB   )r3   Ú	repr_argsr4   r4   r5   Ú__repr__  s   zConnection.__repr__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Ç   Úappend©r3   Úpiecesr4   r4   r5   rÙ     s   ýzConnection.repr_piecesc                 C   r’   r.   )Ú
disconnectr�   ri   r4   r4   r5   r•     r–   zConnection.__del__c                 C   s   | j  |¡ d S r.   )rÑ   rÜ   )r3   Úcallbackr4   r4   r5   Úregister_connect_callback$  s   z$Connection.register_connect_callbackc                 C   s
   g | _ d S r.   )rÑ   ri   r4   r4   r5   Úclear_connect_callbacks'  s   
z"Connection.clear_connect_callbacksc              
   C   sš   | j rdS z|  ¡ }W n tjy   tdƒ‚ tjy* } zt|  |¡ƒ‚d}~ww || _ z|  ¡  W n t	y@   |  
¡  ‚ w | jD ]}|| ƒ qDdS )z5Connects to the Redis server if not already connectedNzTimeout connecting to server)r`   Ú_connectrh   rr   r&   r£   r   Ú_error_messager™   r$   rß   rÑ   )r3   ry   Úerà   r4   r4   r5   Úconnect*  s(   €ÿý

ÿzConnection.connectc                 C   s  d}t  | j| j| jt j¡D ]l}|\}}}}}d}zDt   |||¡}| t jt jd¡ | j	rH| t j
t jd¡ t| jƒD ]\}	}
| t j|	|
¡ q;| | j¡ | |¡ | | j¡ |W   S  t jyz } z|}|durp| ¡  W Y d}~qd}~ww |dur�|‚t  d¡‚)zCreate a TCP socket connectionNrT   z)socket.getaddrinfo returned an empty list)rh   ÚgetaddrinforÃ   rÄ   rÌ   ÚSOCK_STREAMÚ
setsockoptÚIPPROTO_TCPÚTCP_NODELAYrÊ   Ú
SOL_SOCKETÚSO_KEEPALIVEr   rË   ro   rÉ   ræ   rb   r£   rŒ   )r3   ÚerrÚresÚfamilyÚsocktypeÚprotoÚ	canonnameÚsocket_addressry   rÕ   rÖ   Ú_r4   r4   r5   rã   B  s4   ÿ

€ý
zConnection._connectc                 C   sF   t |jƒdkrd| j| j|jd f S d|jd | j| j|jd f S )NrT   zError connecting to %s:%s. %s.r   z!Error %s connecting to %s:%s. %s.)rW   rw   rÃ   rÄ   ©r3   Ú	exceptionr4   r4   r5   rä   j  s   ÿÿzConnection._error_messagec                 C   s   | j  | ¡ | js| jrO| jr| j| jpdf}n| jf}| jdg|¢R ddiŽ z|  ¡ }W n tyD   | jd| jdd� |  ¡ }Y nw t|ƒdkrOtdƒ‚| j	rf|  dd	| j	¡ t|  ¡ ƒdkrft
d
ƒ‚| jr||  d| j¡ t|  ¡ ƒdkr~t
dƒ‚dS dS )z=Initialize the connection, authenticate and select a databaseÚ ÚAUTHÚcheck_healthF©rú   ÚOKzInvalid Username or PasswordÚCLIENTÚSETNAMEzError setting client nameÚSELECTzInvalid DatabaseN)rÐ   r™   rÆ   rÈ   Úsend_commandr�   r   r
   r   rÇ   r   rÅ   )r3   Ú	auth_argsÚauth_responser4   r4   r5   r™   t  s0   úýzConnection.on_connectc                 C   sb   | j  ¡  | jdu rdS zt ¡ | jkrt| jtjƒ | j 	¡  W n
 tj
y+   Y nw d| _dS )z!Disconnects from the Redis serverN)rÐ   r”   r`   rÀ   rÁ   rÂ   r   rh   Ú	SHUT_RDWRrŒ   r£   ri   r4   r4   r5   rß   ›  s   

ÿ
zConnection.disconnectc              	   C   sŽ   | j rCtƒ | jkrEz| jddd� t|  ¡ ƒdkrtdƒ‚W dS  ttfyB   |  ¡  | jddd� t|  ¡ ƒdkr?tdƒ‚Y dS w dS dS )z3Check the health of the connection with a PING/PONGÚPINGFrû   ÚPONGz#Bad response from PING health checkN)	rÎ   r   rÏ   r   r
   r�   r   r&   rß   ri   r4   r4   r5   rú   ¨  s$   ÿÿÿÿýúzConnection.check_healthTc              
   C   sâ   | j s|  ¡  |r|  ¡  zt|tƒr|g}|D ]}t| j |ƒ qW dS  tjy3   |  ¡  t	dƒ‚ tj
ye } z&|  ¡  t|jƒdkrOd|jd }}n
|jd }|jd }td||f ƒ‚d}~w typ   |  ¡  ‚ w )z2Send an already packed command to the Redis serverzTimeout writing to socketrT   ÚUNKNOWNr   z%Error %s while writing to socket. %s.N)r`   ræ   rú   r8   r@   r   rh   rr   rß   r&   r£   rW   rw   r   ÚBaseException)r3   Úcommandrú   Úitemrå   rv   Úerrmsgr4   r4   r5   Úsend_packed_command·  s6   
ÿ

ÿ€þzConnection.send_packed_commandc                 O   s    | j | j|Ž | dd¡d� dS )z+Pack and send a command to the Redis serverrú   Trû   N)r  Úpack_commandrY   )r3   rw   r±   r4   r4   r5   r   Ó  s   

ÿzConnection.send_commandc                 C   s$   | j }|s|  ¡  | j }| j |¡S )z8Poll the socket to see if there's data that can be read.)r`   ræ   rÐ   r„   )r3   rr   ry   r4   r4   r5   r„   Ø  s
   zConnection.can_readc              
   C   s°   z| j  ¡ }W n= tjy   |  ¡  td| j| jf ƒ‚ tjy9 } z|  ¡  t	d| j| j|j
f ƒ‚d}~w tyD   |  ¡  ‚ w | jrOtƒ | j | _t|tƒrV|‚|S )z0Read the response from a previously sent commandzTimeout reading from %s:%sz#Error while reading from %s:%s : %sN)rÐ   r�   rh   rr   rß   r&   rÃ   rÄ   r£   r   rw   r  rÎ   r   rÏ   r8   r%   )r3   rZ   rå   r4   r4   r5   r�   à  s,   
ÿÿ€þ
zConnection.read_responsec              	   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j|ƒD ]>}t	|ƒ}t	|ƒ|ks[||ks[t |tƒrut |tt|ƒ ¡ t
f¡}| |¡ | |¡ t
}qFt |tt|ƒ ¡ t
|t
f¡}qF| |¡ |S )z2Pack a series of arguments into the Redis protocolr   rT   Nó    )r8   r   Útupler>   rU   Ú	SYM_EMPTYrØ   ÚSYM_STARr@   rW   rŠ   rÒ   r   r�   r:   Ú
SYM_DOLLARrÜ   )r3   rw   ÚoutputÚbuffÚbuffer_cutoffÚargÚ
arg_lengthr4   r4   r5   r  ÷  s2   "ÿÿ

ÿÿ
zConnection.pack_commandc           	      C   s®   g }g }d}| j }|D ]?}| j|Ž D ]7}t|ƒ}||ks%||ks%t|tƒr1| t |¡¡ d}g }||ks:t|tƒr@| |¡ q| |¡ ||7 }qq|rU| t |¡¡ |S )z.Pack multiple commands into the Redis protocolr   )rÒ   r  rW   r8   r:   rÜ   r  rØ   )	r3   Úcommandsr  rÞ   Úbuffer_lengthr  ÚcmdÚchunkÚchunklenr4   r4   r5   Úpack_commands  s*   ÿ

ôzConnection.pack_commands©T)r   )rB   rH   rI   rJ   ÚDefaultParserr6   rÛ   rÙ   r•   rá   râ   ræ   rã   rä   r™   rß   rú   r  r   r„   r�   r  r  r4   r4   r4   r5   r¹   ñ  s6    
ú
(
'

"r¹   c                       s0   e Zd Z			d‡ fdd„	Z‡ fdd„Z‡  ZS )	ÚSSLConnectionNÚrequiredFc                    sŒ   t stdƒ‚tt| ƒjdi |¤Ž || _|| _|d u rtj}nt	|t
ƒr;tjtjtjdœ}||vr7td| ƒ‚|| }|| _|| _|| _d S )Nz$Python wasn't built with SSL support)ÚnoneÚoptionalr   z-Invalid SSL Certificate Requirements Flag: %sr4   )Ússl_availabler$   Úsuperr  r6   ÚkeyfileÚcertfileÚsslÚ	CERT_NONEr8   r   ÚCERT_OPTIONALÚCERT_REQUIREDÚ	cert_reqsÚca_certsÚcheck_hostname)r3   Ússl_keyfileÚssl_certfileÚssl_cert_reqsÚssl_ca_certsÚssl_check_hostnamer±   Ú	CERT_REQS©ru   r4   r5   r6   6  s,   
ýÿÿ
zSSLConnection.__init__c                    s”   t t| ƒ ¡ }ttdƒr:t ¡ }| j|_| j|_| j	r'| j
r'|j| j	| j
d� | jr0| | j¡ t||| jd�}|S tt|| j| j
| j	| jd�}|S )z Wrap the socket with SSL supportÚcreate_default_context)r&  r%  )Úserver_hostname)r+  r%  r&  r,  )r$  r  rã   Úhasattrr'  r5  r-  r+  Úverify_moder&  r%  Úload_cert_chainr,  Úload_verify_locationsr   rÃ   )r3   ry   Úcontextr4  r4   r5   rã   Q  s*   
ÿ
úûzSSLConnection._connect)NNr   NF)rB   rH   rI   r6   rã   Ú__classcell__r4   r4   r4  r5   r  4  s    þr  c                   @   sH   e Zd Zdddddddddedddfdd	„Zd
d„ Zdd„ Zdd„ ZdS )ÚUnixDomainSocketConnectionrø   r   Nr¼   r½   Fr¾   c                 C   sp   t  ¡ | _|| _|| _|| _|| _|| _|| _|	| _	|| _
d| _t|||ƒ| _d | _|
|d�| _g | _d| _d S r¿   )rÀ   rÁ   rÂ   ÚpathrÅ   rÆ   rÇ   rÈ   rb   rÍ   rÎ   rÏ   r-   r�   r`   rÐ   rÑ   rÒ   )r3   r>  rÅ   rÆ   rÈ   rb   r0   r1   r2   rÍ   rÓ   ra   rÎ   rÇ   r4   r4   r5   r6   l  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Ý   r4   r4   r5   rÙ   ‚  s   þz&UnixDomainSocketConnection.repr_piecesc                 C   s,   t   t jt j¡}| | j¡ | | j¡ |S )z&Create a Unix domain socket connection)rh   ÚAF_UNIXrè   ro   rb   ræ   r>  )r3   ry   r4   r4   r5   rã   ‹  s   z#UnixDomainSocketConnection._connectc                 C   s>   t |jƒdkrd| j|jd f S d|jd | j|jd f S )NrT   z(Error connecting to unix socket: %s. %s.r   z+Error %s connecting to unix socket: %s. %s.)rW   rw   r>  rö   r4   r4   r5   rä   ’  s   ÿÿz)UnixDomainSocketConnection._error_message)rB   rH   rI   r  r6   rÙ   rã   rä   r4   r4   r4   r5   r=  j  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)r8   r   ÚupperÚFALSE_STRINGSr;   )rC   r4   r4   r5   Úto_bool   s
   rG  )rb   rÉ   rÊ   rÍ   Úmax_connectionsrÎ   r2  c                   @   sv   e Zd ZdZeddd„ƒZed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d„ZdS )ÚConnectionPoolzGeneric connection poolNFc              
   K   s*  t |ƒ}i }tt|jƒƒD ]8\}}|rEt|ƒdkrEt |¡}|r?z
||d ƒ||< W q ttfy>   t	 
td| ƒ¡ Y qw |d ||< q|rq|jrPt|jƒnd}	|jrZt|jƒnd}
|jrdt|jƒnd}|jrnt|jƒnd}n|jpud}	|jpzd}
|j}|j}|jdkr‘| |	|
|tdœ¡ nG|jdv rÍ| |t|jpždƒ|	|
dœ¡ d	|vrÃ|rÃzt| d
d¡ƒ|d	< W n ttfyÂ   Y nw |jdkrÌt|d< nd d¡}td| ƒ‚t| d	|pßd¡ƒ|d	< | |¡ d|v rût	 
tdƒ¡ | d¡|d< d|v �rt	 
tdƒ¡ | 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]:[password]]@/path/to/socket.sock?db=0

        Three URL schemes are supported:

        - ```redis://``
          <https://www.iana.org/assignments/uri-schemes/prov/redis>`_ creates a
          normal TCP socket connection
        - ```rediss://``
          <https://www.iana.org/assignments/uri-schemes/prov/rediss>`_ creates
          a SSL wrapped TCP socket connection
        - ``unix://`` creates a Unix Domain Socket connection

        There are several ways to specify a database number. The parse function
        will return the first specified option:
            1. A ``db`` querystring option, e.g. redis://localhost?db=0
            2. If using the redis:// scheme, the path argument of the url, e.g.
               redis://localhost/0
            3. The ``db`` argument to this function.

        If none of these options are specified, db=0 is used.

        The ``decode_components`` argument allows this function to work with
        percent-encoded URLs. If this argument is set to ``True`` all ``%xx``
        escapes will be replaced by their single-character equivalents after
        the URL has been parsed. This only applies to the ``hostname``,
        ``path``, ``username`` and ``password`` components.

        Any additional querystring arguments and keyword arguments will be
        passed along to the ConnectionPool class's initializer. The querystring
        arguments ``socket_connect_timeout`` and ``socket_timeout`` if supplied
        are parsed as float values. The arguments ``socket_keepalive`` and
        ``retry_on_timeout`` are parsed to boolean values that accept
        True/False, Yes/No values to indicate state. Invalid types cause a
        ``UserWarning`` to be raised. In the case of conflicting arguments,
        querystring arguments always win.

        r   z)Invalid value for `%s` in connection URL.NÚunix)rÆ   rÈ   r>  Úconnection_class)ÚredisÚredissr»   )rÃ   rÄ   rÆ   rÈ   rÅ   ú/rø   rM  rK  z, )zredis://z	rediss://zunix://z8Redis URL must specify one of the following schemes (%s)Úcharsetz/"charset" is deprecated. Use "encoding" insteadr0   r©   z5"errors" is deprecated. Use "encoding_errors" insteadr1   r4   )r   r   r   ÚqueryrW   ÚURL_QUERY_ARGUMENT_PARSERSrY   Ú	TypeErrorÚ
ValueErrorÚwarningsÚwarnÚUserWarningrÆ   r   rÈ   r>  ÚhostnameÚschemeÚupdater=  r?   rÄ   ÚreplaceÚAttributeErrorr  rØ   ÚDeprecationWarningÚpop)ÚclsÚurlrÅ   Údecode_componentsr±   Úurl_optionsÚnamerC   ÚparserrÆ   rÈ   r>  rW  Úvalid_schemesr4   r4   r5   Úfrom_urlµ  s€   .

ÿÿ€



ü
ü	ÿ
€
ÿ
ÿ
ÿzConnectionPool.from_urlc                 K   sN   |pd}t |ttfƒr|dk rtdƒ‚|| _|| _|| _t ¡ | _	|  
¡  dS )a™  
        Create a connection pool. If max_connections is set, then this
        object raises redis.ConnectionError when the pool's limit is reached.

        By default, TCP connections are created unless connection_class is
        specified. Use redis.UnixDomainSocketConnection for unix sockets.

        Any additional keyword arguments are passed to the constructor of
        connection_class.
        l        r   z,"max_connections" must be a positive integerN)r8   r?   r	   rS  rK  Úconnection_kwargsrH  Ú	threadingÚLockÚ
_fork_lockÚreset)r3   rK  rH  rf  r4   r4   r5   r6   0  s   

zConnectionPool.__init__c                 C   s$   dt | ƒjt| jdi | j¤Žƒf S )Nr×   r4   )rA   rB   r=   rK  rf  ri   r4   r4   r5   rÛ   O  s   þzConnectionPool.__repr__c                 C   s,   t  ¡ | _d| _g | _tƒ | _t ¡ | _	d S r_   )
rg  rh  Ú_lockÚ_created_connectionsÚ_available_connectionsÚsetÚ_in_use_connectionsrÀ   rÁ   rÂ   ri   r4   r4   r5   rj  U  s
   
zConnectionPool.resetc                 C   s’   | j t ¡ krGtƒ d }d}tƒ |k r!| j d¡}|rntƒ |k s|s%t‚z| j t ¡ kr9|  ¡  W | j ¡  d S W | j ¡  d S | j ¡  w d S )Né   F)	rÂ   rÀ   rÁ   r   ri  Úacquirer   rj  Úrelease)r3   Ú
timeout_atÚacquiredr4   r4   r5   Ú	_checkpidf  s"   #


ý
ýïzConnectionPool._checkpidc              	   O   sØ   |   ¡  | j�# z| j ¡ }W n ty   |  ¡ }Y nw | j |¡ W d  ƒ n1 s-w   Y  z,| ¡  z| 	¡ r@t
dƒ‚W W |S  t
y^   | ¡  | ¡  | 	¡ rZt
dƒ‚Y W |S w  tyk   |  |¡ ‚ w )zGet a connection from the poolNúConnection has dataúConnection not ready)ru  rk  rm  r]  Ú
IndexErrorÚmake_connectionro  Úaddræ   r„   r   rß   r  rr  ©r3   Úcommand_nameÚkeysÚoptionsr˜   r4   r4   r5   Úget_connectionœ  s8   ÿûÿõÿõ
üzConnectionPool.get_connectionc                 C   s,   | j }t| dd¡| dd¡| dd¡d�S )z,Return an encoder based on encoding settingsr0   r¼   r1   r½   r2   Fr/   )rf  r-   rY   )r3   r±   r4   r4   r5   Úget_encoder½  s   


ýzConnectionPool.get_encoderc                 C   s4   | j | jkr
tdƒ‚|  j d7  _ | jdi | j¤ŽS )zCreate a new connectionzToo many connectionsrT   Nr4   )rl  rH  r   rK  rf  ri   r4   r4   r5   ry  Æ  s   zConnectionPool.make_connectionc              	   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 poolrT   N)
ru  rk  ro  ÚremoveÚKeyErrorÚowns_connectionrm  rÜ   rl  rß   r—   r4   r4   r5   rr  Í  s   ý
ð	"÷zConnectionPool.releasec                 C   s   |j | j kS r.   )rÂ   r—   r4   r4   r5   rƒ  â  s   zConnectionPool.owns_connectionTc                 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)ru  rk  r   rm  ro  rß   )r3   Úinuse_connectionsÚconnectionsr˜   r4   r4   r5   rß   å  s   ÿ
ÿ"ùzConnectionPool.disconnectr²   r  )rB   rH   rI   rJ   Úclassmethodre  r¹   r6   rÛ   rj  ru  r  r€  ry  rr  rƒ  rß   r4   r4   r4   r5   rI  ³  s    z6!	rI  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 )ÚBlockingConnectionPoola6  
    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.connection.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.exceptions.ConnectionError`` (as the default
    ``:py:class: ~redis.connection.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t| ƒjd||dœ|¤Ž d S )N)rK  rH  r4   )Úqueue_classrr   r$  r‡  r6   )r3   rH  rr   rK  rŠ  rf  r4  r4   r5   r6     s   þ
ýzBlockingConnectionPool.__init__c                 C   sJ   |   | j¡| _	 z| j d ¡ W n	 ty   Y nw qg | _t ¡ | _d S r.   )	rŠ  rH  ÚpoolÚ
put_nowaitr   Ú_connectionsrÀ   rÁ   rÂ   ri   r4   r4   r5   rj  %  s   ÿýzBlockingConnectionPool.resetc                 C   s"   | j di | j¤Ž}| j |¡ |S )zMake a fresh connection.Nr4   )rK  rf  r�  rÜ   r—   r4   r4   r5   ry  =  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yQ   | 	¡  | ¡  | ¡ rMt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)Úblockrr   zNo connection available.rv  rw  )ru  r‹  rY   rr   r   r   ry  ræ   r„   rß   r  rr  r{  r4   r4   r5   r  C  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)ru  rƒ  rß   r‹  rŒ  r   r—   r4   r4   r5   rr  w  s   
ýzBlockingConnectionPool.releasec                 C   s    |   ¡  | jD ]}| ¡  qdS )z(Disconnects all connections in the pool.N)ru  r�  rß   r—   r4   r4   r5   rß   Œ  s   

ÿz!BlockingConnectionPool.disconnect)rB   rH   rI   rJ   r¹   r   r6   rj  ry  r  rr  rß   r<  r4   r4   r4  r5   r‡  ù  s     ÿ4r‡  )_Ú
__future__r   Údistutils.versionr   Ú	itertoolsr   r   rv   rc   rÀ   rh   rg  rT  Úredis._compatr   r   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   Úredis.exceptionsr   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   Úredis.utilsr'   r'  r#  ÚImportErrorÚEWOULDBLOCKrt   r7  r(   ÚSSLWantWriteErrorÚSSLErrorr£   r  r}  rs   r­   Ú__version__Úhiredis_versionr«   ÚHIREDIS_SUPPORTS_BYTE_BUFFERr¬   ÚmsgrU  r¥   r  r  rŠ   r  rp   Úobjectrn   r-   rK   r^   r�   r¤   r  r¹   r  r=  rF  rG  r<   r?   rQ  rI  r‡  r4   r4   r4   r5   Ú<module>   sž    T@ÿÿ



	


ÿ
ÿ
ÿÿ
(#xOz  E63	ù  H