U
    d.                 
   @   s|  U d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
Z
d dlZd dlmZ d dlmZ d dlmZmZmZmZmZmZmZmZmZmZmZ d dlmZmZmZm Z  d dl!Z!d dl"m#Z# d dl$m%Z% d dl&m'Z'm(Z( d d	l)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8 d d
l9m:Z:m;Z; d dl<m=Z=m>Z> dZ?e=rld dl?Z?e@ejAejBdejCdejDdiZEeFeEG ZHdZIdZJdZKdZLdZMdZNG dd dejOZPePjQZRdZSdZTdZUdZVG dd de(ddZWG dd dZXeeYeeeZ eeYeeZ f f f Z[G dd  d Z\G d!d" d"Z]G d#d$ d$e\Z^G d%d& d&e\Z_eee^e_f  e`d'< e=rve_Zane^ZaG d(d) d)e'ZbG d*d+ d+e'Zceebecf ZdG d,d- d-ZeG d.d/ d/eeZfG d0d1 d1ZgG d2d3 d3eeZhd4Zieej d5d6d7Zkeelememekekelelekd8ZneeYed9eof f e`d:< G d;d< d<e(ddZpeYepd=d>d?Zqed@dAdBZrG dCdA dAZsG dDdE dEesZtdS )F    N)chain)MappingProxyType)AnyCallableIterableListMappingOptionalSetTupleTypeTypeVarUnion)ParseResultparse_qsunquoteurlparse)Retry)	NoBackoff)Protocol	TypedDict)AuthenticationError$AuthenticationWrongNumberOfArgsErrorBusyLoadingErrorChildDeadlockedErrorConnectionError	DataErrorExecAbortErrorInvalidResponseModuleErrorNoPermissionErrorNoScriptErrorReadOnlyError
RedisErrorResponseErrorTimeoutError)
EncodableTEncodedT)HIREDIS_AVAILABLEstr_if_bytes      *   $s   
   
    zConnection closed by server.c                   @   s   e Zd Ze ZdS )	_SentinelN)__name__
__module____qualname__objectsentinel r5   r5   </tmp/pip-unpacked-wheel-f5h5_hbx/redis/asyncio/connection.pyr/   N   s   r/   z:Error loading the extension. Please check the server logs.z5Error unloading module: no such module with that namez/Error unloading module: operation not possible.z[Error unloading module: the module exports one or more module-side data types, can't unloadc                   @   sJ   e Zd ZU eegef ed< eegef ed< ee ed< ee ed< dS )_HiredisReaderArgsprotocolError
replyErrorencodingerrorsN)r0   r1   r2   r   str	Exception__annotations__r	   r5   r5   r5   r6   r7   ]   s   
r7   F)totalc                   @   sH   e Zd ZdZdZeeedddZee	dddZ
deedd	d
ZdS )Encoderz=Encode strings to bytes-like and decode bytes-like to stringsr:   encoding_errorsdecode_responsesc                 C   s   || _ || _|| _d S NrA   )selfr:   rB   rC   r5   r5   r6   __init__i   s    zEncoder.__init__)valuereturnc                 C   st   t |tr|| j| jS t |ttfr,|S t |ttfrXt |t	rLt
dt| S |jj}t
d|dd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.zInvalid input of type: z1. Convert to a bytes, string, int or float first.N)
isinstancer<   encoder:   rB   bytes
memoryviewintfloatboolr   repr	__class__r0   )rE   rG   typenamer5   r5   r6   rJ   n   s    


zEncoder.encodeFc                 C   sF   | j s
|rBt|tr$|| j| jS t|trB| | j| jS |S )z:Return a unicode string from the bytes-like representation)rC   rI   rK   decoder:   rB   rL   tobytes)rE   rG   forcer5   r5   r6   rS      s    


zEncoder.decodeN)F)r0   r1   r2   __doc__	__slots__r<   rO   rF   r&   r'   rJ   rS   r5   r5   r5   r6   r@   d   s
   r@   c                   @   s   e Zd ZU dZdZdededededeee	e
e	ee	ee	i	eeeeeedZeed	< ed
ddZdd ZeedddZdd ZddddZeedddZd ee e!ede"e! f dddZ#dS )!
BaseParserPlain Python parsing class_stream_buffer
_read_sizez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)ZERRZ	EXECABORTZLOADINGZNOSCRIPTZREADONLYZNOAUTHZNOPERMEXCEPTION_CLASSESsocket_read_sizec                 C   s   d | _ d | _|| _d S rD   rZ   rE   r`   r5   r5   r6   rF      s    zBaseParser.__init__c                 C   s&   z|    W n tk
r    Y nX d S rD   )on_disconnectr=   rE   r5   r5   r6   __del__   s    zBaseParser.__del__)responserH   c                 C   s\   | dd }|| jkrT|t|d d }| j| }t|trL||t}||S t|S )zParse an error response r      N)splitr^   lenrI   dictgetr$   )rE   re   Z
error_codeZexception_classr5   r5   r6   parse_error   s    


zBaseParser.parse_errorc                 C   s
   t  d S rD   NotImplementedErrorrc   r5   r5   r6   rb      s    zBaseParser.on_disconnect
Connection
connectionc                 C   s
   t  d S rD   rm   rE   rq   r5   r5   r6   
on_connect   s    zBaseParser.on_connecttimeoutrH   c                    s
   t  d S rD   rm   rE   ru   r5   r5   r6   can_read   s    zBaseParser.can_readFNdisable_decodingrH   c                    s
   t  d S rD   rm   )rE   ry   r5   r5   r6   read_response   s    zBaseParser.read_response)F)$r0   r1   r2   rV   rW   r   r   r   MODULE_LOAD_ERRORr   MODULE_EXPORTS_DATA_TYPES_ERRORNO_SUCH_MODULE_ERROR MODULE_UNLOAD_NOT_POSSIBLE_ERRORr   r   r!   r"   r    r^   ExceptionMappingTr>   rM   rF   rd   r<   r$   rl   rb   rs   rN   rO   rw   r   r&   r   rz   r5   r5   r5   r6   rX      sN   
          rX   c                   @   s   e Zd ZdZejeee dddZ	e
dd Zdedfee eedef eed	d
dZeedddZeedddZedddZdd Zdd ZdS )SocketBufferzAsync-friendly re-impl of redis-py's SocketBuffer.

    TODO: We're currently passing through two buffers,
        the asyncio.StreamReader and this. I imagine we can reduce the layers here
        while maintaining compliance with prior art.
    )stream_readerr`   socket_timeoutc                 C   s,   || _ || _|| _t | _d| _d| _d S Nr   )r[   r`   r   ioBytesIOr\   bytes_written
bytes_read)rE   r   r`   r   r5   r5   r6   rF      s    
zSocketBuffer.__init__c                 C   s   | j | j S rD   )r   r   rc   r5   r5   r6   length   s    zSocketBuffer.lengthNT)r   ru   raise_on_timeoutrH   c           
   
      sh  | j }|d ks| jd kr td|| j d}|tk	r<|n| j}zt|4 I d H  | j	| j
I d H }W 5 Q I d H R X t|trt|dkrtt|| t|}|  j|7  _||7 }|d k	r||krqDW dS  tjtjfk
r   |r tdY dS  tk
rb } z>t|jd}	|sB|j|	krBW Y dS td|j W 5 d }~X Y nX d S )NBuffer is closed.r   TTimeout reading from socketF!Error while reading from socket: )r\   r[   r#   seekr   SENTINELr   async_timeoutru   readr`   rI   rK   ri   r   SERVER_CLOSED_CONNECTION_ERRORwritesocketasyncior%   NONBLOCKING_EXCEPTIONS#NONBLOCKING_EXCEPTION_ERROR_NUMBERSrk   rQ   errnoargs)
rE   r   ru   r   bufmarkerdataZdata_lengthexallowedr5   r5   r6   _read_from_socket   s6    $

zSocketBuffer._read_from_socketrt   c                    s   t | jp| j|ddI d H S )NFru   r   )rO   r   r   rv   r5   r5   r6   rw     s     zSocketBuffer.can_read)r   rH   c                    s   |d }|| j kr(| || j  I d H  | jd kr:td| j| j | j|}|  jt|7  _| j| jkrz| 	  |d d S )Nr*   r   )
r   r   r\   r#   r   r   r   ri   r   purge)rE   r   r   r5   r5   r6   r     s    

zSocketBuffer.readrH   c                    s   | j }|d krtd|| j | }|tsX|  I d H  || j | }q*|  jt|7  _| j| j	kr~| 
  |d d S )Nr   r   )r\   r#   r   r   readlineendswithSYM_CRLFr   ri   r   r   )rE   r   r   r5   r5   r6   r   0  s    

zSocketBuffer.readlinec                 C   s8   | j d krtd| j d | j   d| _d| _d S )Nr   r   )r\   r#   r   truncater   r   rc   r5   r5   r6   r   F  s    

zSocketBuffer.purgec                 C   s<   z|    | j  W n tk
r*   Y nX d | _d | _d S rD   )r   r\   closer=   r[   rc   r5   r5   r6   r   O  s    zSocketBuffer.close)r0   r1   r2   rV   r   StreamReaderrM   r	   rN   rF   propertyr   r   r   r/   rO   r   rw   rK   r   r   r   r   r5   r5   r5   r6   r      s*   	
*	r   c                       sp   e Zd ZdZejd Zed fddZdddd	Zd
d Z	e
dddZdeeeedf dddZ  ZS )PythonParserrY   )encoderr_   c                    s   t  | d | _d S rD   )superrF   r   ra   rQ   r5   r6   rF   c  s    zPythonParser.__init__ro   rp   c                 C   s:   |j | _| jdkrtdt| j| j|j| _|j| _dS )zCalled when the stream connectsNr   )_readerr[   r#   r   r]   r   r\   r   rr   r5   r5   r6   rs   g  s    
  zPythonParser.on_connectc                 C   s4   | j dk	rd| _ | jdk	r*| j  d| _d| _dS )z"Called when the stream disconnectsN)r[   r\   r   r   rc   r5   r5   r6   rb   r  s    


zPythonParser.on_disconnectru   c                    s   | j ot| j |I d H S rD   )r\   rO   rw   rv   r5   r5   r6   rw   {  s    zPythonParser.can_readFNrx   c                    sB  j rjsttj  I d H }|s0tt|d d |dd   }}|dkr`td||dkr|jddd}|}t|tr||S |dkrn|d	krt	|}nn|d
krt	|}|dkrd S j 
|I d H }n>|dkrt	|}|dk rd S  fddt|D I d H }t|tr> dkr>j|}|S )Nrg   )   -   +   :r,   r+   zProtocol Error: r   utf-8replace)r;   r   r   r,   r   r+   c                    s   g | ]}  I d H qS rD   )rz   ).0_ry   rE   r5   r6   
<listcomp>  s    z.PythonParser.read_response.<locals>.<listcomp>F)r\   r   r   r   r   r   rS   rl   rI   rM   r   rangerK   )rE   ry   rawbytere   errorr   r5   r   r6   rz   ~  sB    




zPythonParser.read_response)F)r0   r1   r2   rV   rX   rW   rM   rF   rs   rb   rN   rw   rO   r   r&   r$   rz   __classcell__r5   r5   r   r6   r   ^  s   
	 r   c                       s   e Zd ZU dZejd Zeed< ed fddZ	ddd	d
Z
dd ZedddZedfeedef edddZdeeeee f dddZ  ZS )HiredisParserz*Parser class for connections using Hiredis)_next_responser   _socket_timeoutr   r_   c                    s*   t stdt j|d d | _d | _d S )NzHiredis is not available.r_   )r(   r#   r   rF   r   r   ra   r   r5   r6   rF     s
    zHiredisParser.__init__ro   rp   c                 C   sT   |j | _t| jd}|jjr4|jj|d< |jj|d< tj	f || _ d| _
|j| _d S )N)r8   r9   r:   r;   F)r   r[   r   rl   r   rC   r:   rB   hiredisReaderr   r   r   )rE   rq   kwargsr5   r5   r6   rs     s    zHiredisParser.on_connectc                 C   s   d | _ d | _d| _d S )NF)r[   r   r   rc   r5   r5   r6   rb     s    zHiredisParser.on_disconnectr   c                    sL   | j r| jstt| jdkr*| j | _| jdkrH| j|ddI d H S dS )NFr   T)r[   r   r   r   r   getsread_from_socketrv   r5   r5   r6   rw     s    

zHiredisParser.can_readTNr   c              
      s6  |t kr| jn|}z|d kr2| j| jI d H }n8t|4 I d H  | j| jI d H }W 5 Q I d H R X |rxt|tst	t
d | j| W dS  tjk
r    Y n tjtjfk
r   |rtdd Y dS  tk
r0 } z>t|jd}|s|j|krW Y dS t	d|j W 5 d }~X Y nX d S )NTr   Fr   r   )r   r   r[   r   r]   r   ru   rI   rK   r   r   r   feedr   CancelledErrorr   r%   r   r   rk   rQ   r   r   )rE   ru   r   bufferr   r   r5   r5   r6   r     s*    $


zHiredisParser.read_from_socketFrx   c                    s   | j r| js|   ttd | jdk	r8| j}d| _|S | j }|dkrd|  I d H  | j }qBt|trt|n$t|t	r|rt|d tr|d |S )NFr   )
r[   r   rb   r   r   r   r   r   rI   list)rE   ry   re   r5   r5   r6   rz     s*    



zHiredisParser.read_response)F)r0   r1   r2   rV   rX   rW   rO   r>   rM   rF   rs   rb   rN   rw   r   r   r/   r   r&   r   rz   r   r5   r5   r   r6   r     s$   

# r   DefaultParserc                   @   s   e Zd ZddddZdS )ConnectCallbackProtocolro   rp   c                 C   s   d S rD   r5   rr   r5   r5   r6   __call__'  s    z ConnectCallbackProtocol.__call__Nr0   r1   r2   r   r5   r5   r5   r6   r   &  s   r   c                   @   s   e Zd ZddddZdS )AsyncConnectCallbackProtocolro   rp   c                    s   d S rD   r5   rr   r5   r5   r6   r   ,  s    z%AsyncConnectCallbackProtocol.__call__Nr   r5   r5   r5   r6   r   +  s   r   c                   @   s  e Zd ZdZdZddddddddddedd	ded
dddddedee	ee
f e	ee
f ee ee ee eeee
e	e
ef f  e
ee	eef eeeee e
eee ee ee ee ee dddZdd Zdd Zdd Zedd Zdd Zdd Zee ddddZdd Zdd  Z d!d" Z!dd#d$d%Z"dd#d&d'Z#d(d) Z$d*d+ Z%d,d- Z&e'e dd.d/d0Z(dFe	eee'e f edd2d3d4Z)e*e*dd5d6d7Z+dGed8d9d:Z,dHed;d<d=Z-dIed;d>d?Z.e/e0e d@dAdBZ1e'e'e/  e0e dCdDdEZ2dS )Jro   z4Manages TCP communication to and from a Redis server)pidhostportdbusernameclient_namepasswordr   socket_connect_timeoutsocket_keepalivesocket_keepalive_optionssocket_typeredis_connect_funcretry_on_timeoutretry_on_errorhealth_check_intervalnext_health_checkZlast_active_atr   ssl_contextr   _writer_parser_connect_callbacks_buffer_cutoff_lock_socket_read_size__dict__	localhosti  r   NFr   strict   )r   r   r   r   r   r   r   r   r   r   r   r:   rB   rC   parser_classr`   r   r   r   retryr   encoder_classc                C   s  t  | _|| _t|| _|| _|| _|| _|| _	|| _
|pB|pBd | _|| _|pRi | _|	| _|
| _|tkrng }|
r||t || _|r|stt d| _nt|| _| j| ntt d| _|| _d| _d | _||||| _|| _d | _d | _ || _!| "| g | _#d| _$t%& | _'d S )Nrg   r   r   p  )(osgetpidr   r   rM   r   r   r   r   r   r   r   r   r   r   r   r   appendr%   r   r   r   r   copydeepcopyupdate_supported_errorsr   r   r   r   r   r   r   r   
set_parserr   r   r   Lockr   )rE   r   r   r   r   r   r   r   r   r   r   r   r:   rB   rC   r   r`   r   r   r   r   r   r   r5   r5   r6   rF   U  sH    




zConnection.__init__c                 C   s,   d dd |  D }| jj d| dS )N,c                 s   s    | ]\}}| d | V  qdS )=Nr5   )r   kvr5   r5   r6   	<genexpr>  s     z&Connection.__repr__.<locals>.<genexpr><>)joinrepr_piecesrQ   r0   )rE   Z	repr_argsr5   r5   r6   __repr__  s    zConnection.__repr__c                 C   s6   d| j fd| jfd| jfg}| jr2|d| jf |S )Nr   r   r   r   )r   r   r   r   r   rE   piecesr5   r5   r6   r     s    zConnection.repr_piecesc                 C   sR   z8| j r6t }|  }| r,|| n
|| W n tk
rL   Y nX d S rD   )is_connectedr   get_event_loop
disconnectZ
is_runningZcreate_taskZrun_until_completer=   )rE   Zloopcoror5   r5   r6   rd     s    zConnection.__del__c                 C   s   | j d k	o| jd k	S rD   )r   r   rc   r5   r5   r6   r    s    zConnection.is_connectedc                 C   s   | j t| d S rD   )r   r   weakref
WeakMethod)rE   callbackr5   r5   r6   register_connect_callback  s    z$Connection.register_connect_callbackc                 C   s
   g | _ d S rD   )r   rc   r5   r5   r6   clear_connect_callbacks  s    z"Connection.clear_connect_callbacks)r   rH   c                 C   s   || j d| _dS )z
        Creates a new instance of parser_class with socket size:
        _socket_read_size and assigns it to the parser for the connection
        :param parser_class: The required parser class
        r_   N)r   r   )rE   r   r5   r5   r6   r     s    zConnection.set_parserc              
      sT  | j r
dS z|  I dH  W n tjk
r4    Y n| tjtjfk
rV   tdY nZ tk
r } zt| 	|W 5 d}~X Y n, t
k
r } zt||W 5 d}~X Y nX z@| js|  I dH  n&t| jr| | I dH n| |  W n& tk
r   |  I dH   Y nX | jD ]0}| }|| }|rt|r|I dH  qdS )z5Connects to the Redis server if not already connectedNzTimeout connecting to server)r  _connectr   r   r   ru   r%   OSErrorr   _error_messager=   r   rs   iscoroutinefunctionr#   r  r   inspectisawaitable)rE   eexcrefr	  Ztaskr5   r5   r6   connect  s8    
zConnection.connectc              
      s   t | j4 I dH 4 tj| j| j| jr2| j nddI dH \}}W 5 Q I dH R X || _	|| _
|jd}|r|tjtjd z@| jr|tjtjd | j D ]\}}|tj|| qW n" ttfk
r   |   Y nX dS )zCreate a TCP socket connectionN)r   r   sslr   rg   )r   ru   r   r   Zopen_connectionr   r   r   rk   r   r   	transportZget_extra_info
setsockoptr   IPPROTO_TCPTCP_NODELAYr   
SOL_SOCKETSO_KEEPALIVEr   itemsSOL_TCPr  	TypeErrorr   )rE   readerwritersockr   r   r5   r5   r6   r    s&     zConnection._connectc              	   C   s~   |j sd| j d| j dS t|j dkrLd| j d| j d|j d  dS d|j d  d	| j d| j d|j d  d	S d S )
NzError connecting to :z. Connection reset by peerrg   . r   .Error z connecting to )r   r   r   ri   rE   	exceptionr5   r5   r6   r    s    ",zConnection._error_messager   c                    s2  | j |  | js| jr| jr0| j| jp*df}n| jp8df}| jd|ddiI dH  z|  I dH }W n: tk
r   | jd| jddI dH  |  I dH }Y nX t|dkrtd| j	r| d	d
| j	I dH  t|  I dH dkrt
d| jr.| d| jI dH  t|  I dH dkr.t
ddS )z=Initialize the connection, authenticate and select a database AUTHcheck_healthFNr+  OKzInvalid Username or PasswordZCLIENTZSETNAMEzError setting client nameZSELECTzInvalid Database)r*  )r   rs   r   r   send_commandrz   r   r)   r   r   r   r   )rE   Z	auth_argsZauth_responser5   r5   r6   rs     s*    zConnection.on_connectc              
      s   zt | j4 I dH  | j  | js>W 5 Q I dH R  W dS zRz8t	 | j
krv| j  t| jdrv| j I dH  W n tk
r   Y nX W 5 d| _d| _X W 5 Q I dH R X W n( tjk
r   td| j dY nX dS )z!Disconnects from the Redis serverNwait_closedz#Timed out closing connection after )r   ru   r   r   rb   r  r   r   r   r   r   r   hasattrr/  r  r   r%   rc   r5   r5   r6   r  <  s(    



zConnection.disconnectc                    s6   | j dddI dH  t|  I dH dkr2tddS )z Send PING, expect PONG in returnZPINGFr,  NZPONGz#Bad response from PING health check)r.  r)   rz   r   rc   r5   r5   r6   
_send_pingS  s    zConnection._send_pingc                    s   |   I dH  dS )z Function to call when PING failsNr  )rE   r   r5   r5   r6   _ping_failedY  s    zConnection._ping_failedc                    sR   t jdd dkrtj}ntj}| jrN|  | jkrN| j	| j
| jI dH  dS )z3Check the health of the connection with a PING/PONGr   r*         N)sysversion_infor   r  get_running_loopr   timer   r   Zcall_with_retryr1  r3  )rE   funcr5   r5   r6   r+  ]  s
    zConnection.check_health)commandrH   c                    s    | j | | j  I d H  d S rD   )r   
writelinesdrain)rE   r<  r5   r5   r6   _send_packed_commandg  s    zConnection._send_packed_commandT)r<  r+  rH   c              
      s`  | j s|  I d H  n|r(|  I d H  zdt|tr<| }t|trL|g}| jrnt	| 
|| jI d H  n| j| | j I d H  W n tjk
r   |  I d H  tdd Y n tk
r6 } z^|  I d H  t|jdkrd|jd  }}n|jd }|jd }td| d| d|W 5 d }~X Y n& tk
rZ   |  I d H   Y nX d S )NzTimeout writing to socketrg   UNKNOWNr   r&  z while writing to socket. r%  )r  r  r+  rI   r<   rJ   rK   r   r   wait_forr?  r   r=  r>  r%   r  r  ri   r   r   BaseException)rE   r<  r+  r  Zerr_noerrmsgr5   r5   r6   send_packed_commandk  sB    

 

zConnection.send_packed_command)r   r   rH   c                    s&   | j | j| |dddI dH  dS )z+Pack and send a command to the Redis serverr+  Tr,  N)rD  pack_commandrk   )rE   r   r   r5   r5   r6   r.    s     
zConnection.send_commandr   c              
      s~   | j s|  I dH  z| j|I dH W S  tk
rx } z2|  I dH  td| j d| j d|j	 W 5 d}~X Y nX dS )z8Poll the socket to see if there's data that can be read.NError while reading from r#  z: )
r  r  r   rw   r  r  r   r   r   r   )rE   ru   r  r5   r5   r6   rw     s    zConnection.can_readry   c                    s~  zz| j 4 I dH \ | jrTt| j4 I dH  | jj|dI dH }W 5 Q I dH R X n| jj|dI dH }W 5 Q I dH R X W n tjk
r   |  I dH  td| j	 d| j
 Y nv tk
r } z2|  I dH  td| j	 d| j
 d|j W 5 d}~X Y n& tk
r*   |  I dH   Y nX | jrhtjdd d	krPtj}ntj}|  | j | _t|trz|d|S 
z0Read the response from a previously sent commandNrG  zTimeout reading from r#  rF  z : r   r*   r4  )r   r   r   ru   r   rz   r   r%   r  r   r   r  r   r   rB  r   r7  r8  r  r9  r:  r   rI   r$   rE   ry   re   r  r;  r5   r5   r6   rz     s:     zConnection.read_responsec              
      s\  zZ| j rDt| j 4 I dH  | jj|dI dH }W 5 Q I dH R X n| jj|dI dH }W n tjk
r   |  I dH  td| j d| j	 Y nt t
k
r } z2|  I dH  td| j d| j	 d|j W 5 d}~X Y n& tk
r   |  I dH   Y nX | jrFtjdd d	kr.tj}ntj}|  | j | _t|trX|d|S rH  )r   r   ru   r   rz   r   r%   r  r   r   r  r   r   rB  r   r7  r8  r  r9  r:  r   rI   r$   rI  r5   r5   r6   read_response_without_lock  s8    z%Connection.read_response_without_lock)r   rH   c              	   G   s*  g }t |d trtt |d trFt|d   |dd  }n(d|d krnt|d  |dd  }tt	tt
| tf}| j}t| jj|D ]|}t
|}t
||ks||kst |trt|tt| tf}|| || t}qt|tt| t|tf}q|| |S )z2Pack a series of arguments into the Redis protocolr   rg   N    )rI   rN   AssertionErrorr<   tuplerJ   rh   	SYM_EMPTYr   SYM_STARri   r   r   mapr   rL   
SYM_DOLLARr   )rE   r   outputZbuffbuffer_cutoffargZ
arg_lengthr5   r5   r6   rE    sB    "





zConnection.pack_command)commandsrH   c           	      C   s   g }g }d}| j }|D ]~}| j| D ]n}t|}||ksJ||ksJt|trb|t| d}g }||kstt|tr|| q$|| ||7 }q$q|r|t| |S )z.Pack multiple commands into the Redis protocolr   )r   rE  ri   rI   rL   r   rN  r   )	rE   rU  rR  r  Zbuffer_lengthrS  cmdchunkZchunklenr5   r5   r6   pack_commands  s.    
zConnection.pack_commands)T)r   )F)F)3r0   r1   r2   rV   rW   r   r   r@   r<   r   rM   r	   rN   rO   r   rK   r   r/   r   rX   r   ConnectCallbackTrF   r   r   rd   r   r  r
  r  r   r  r  r  rs   r  r1  r3  r+  r   r?  rD  r   r.  rw   rz   rJ  r&   r   rE  rX  r5   r5   r5   r6   ro   3  s   "


C
%)
  %$#.ro   c                       s   e Zd Zdee ee eee ee ed fddZedd Zed	d
 Z	edd Z
edd Zedd Zedd Z  ZS )SSLConnectionNrequiredF)ssl_keyfilessl_certfilessl_cert_reqsssl_ca_certsssl_ca_datassl_check_hostnamec                    s(   t  jf | t||||||d| _d S )Nkeyfilecertfile	cert_reqsca_certsca_datacheck_hostname)r   rF   RedisSSLContextr   )rE   r\  r]  r^  r_  r`  ra  r   r   r5   r6   rF   6  s    
zSSLConnection.__init__c                 C   s   | j jS rD   )r   rc  rc   r5   r5   r6   rc  J  s    zSSLConnection.keyfilec                 C   s   | j jS rD   )r   rd  rc   r5   r5   r6   rd  N  s    zSSLConnection.certfilec                 C   s   | j jS rD   )r   re  rc   r5   r5   r6   re  R  s    zSSLConnection.cert_reqsc                 C   s   | j jS rD   )r   rf  rc   r5   r5   r6   rf  V  s    zSSLConnection.ca_certsc                 C   s   | j jS rD   )r   rg  rc   r5   r5   r6   rg  Z  s    zSSLConnection.ca_datac                 C   s   | j jS rD   )r   rh  rc   r5   r5   r6   rh  ^  s    zSSLConnection.check_hostname)NNr[  NNF)r0   r1   r2   r	   r<   rO   rF   r   rc  rd  re  rf  rg  rh  r   r5   r5   r   r6   rZ  5  s4         




rZ  c                   @   sN   e Zd ZdZd
ee ee ee ee ee edddZej	ddd	Z
dS )ri  )rc  rd  re  rf  rg  contextrh  NFrb  c                 C   sv   || _ || _|d krtj| _n<t|trZtjtjtjd}||krPt	d| || | _|| _
|| _|| _d | _d S )N)noneoptionalr[  z+Invalid SSL Certificate Requirements Flag: )rc  rd  r  	CERT_NONEre  rI   r<   CERT_OPTIONALCERT_REQUIREDr#   rf  rg  rh  rj  )rE   rc  rd  re  rf  rg  rh  Z	CERT_REQSr5   r5   r6   rF   n  s$    	


zRedisSSLContext.__init__r   c                 C   sf   | j s`t }| j|_| j|_| jr<| jr<|j| j| jd | j	sH| j
rZ|j| j	| j
d || _ | j S )N)rd  rc  )cafilecadata)rj  r  create_default_contextrh  re  verify_moderd  rc  load_cert_chainrf  rg  load_verify_locations)rE   rj  r5   r5   r6   rk     s    zRedisSSLContext.get)NNNNNF)r0   r1   r2   rW   r	   r<   rO   rF   r  
SSLContextrk   r5   r5   r5   r6   ri  c  s          ri  c                   @   s   e Zd Zddddddddddeedddddd	eeeef ee ee ee	 ee	 eee
e
eeef ee ee	eee d
ddZeeeeeef f  dddZdd Zdd ZdS )UnixDomainSocketConnectionr)  r   Nr   r   Fr   g        )pathr   r   r   r   r   r:   rB   rC   r   r   r   r`   r   r   r   r   )rx  r   r   r   r   r   r:   rB   rC   r   r   r   r`   r   r   r   c                C   s  t  | _|| _|| _|| _|| _|| _|| _|p8|p8d| _	|
| _
|tkrNg }|
r\|t || _|r|dkr~tt d| _nt|| _| j| ntt d| _|| _d| _|| _t|||	| _d| _d| _d| _|| _| | g | _d| _ t!" | _#dS )z
        Initialize a new UnixDomainSocketConnection.
        To specify a retry policy, first set `retry_on_timeout` to `True`
        then set `retry` to a valid `Retry` object
        Nrg   r   r   r   )$r   r   r   rx  r   r   r   r   r   r   r   r   r   r%   r   r   r   r   r   r   r   r   r   r   r@   r   _sockr   r   r   r   r   r   r   r   r   )rE   rx  r   r   r   r   r   r:   rB   rC   r   r   r   r`   r   r   r   r   r5   r5   r6   rF     s@    


z#UnixDomainSocketConnection.__init__r   c                 C   s.   d| j fd| jfg}| jr*|d| jf |S )Nrx  r   r   )rx  r   r   r   r  r5   r5   r6   r     s    z&UnixDomainSocketConnection.repr_piecesc              
      s\   t | j4 I d H  tj| jdI d H \}}W 5 Q I d H R X || _|| _|  I d H  d S )N)rx  )	r   ru   r   r   Zopen_unix_connectionrx  r   r   rs   )rE   r   r!  r5   r5   r6   r    s
    (z#UnixDomainSocketConnection._connectc                 C   sR   t |jdkr(d| j d|jd  dS d|jd  d| j d|jd  dS d S )Nrg   z!Error connecting to unix socket: r$  r   r%  r&  z connecting to unix socket: )ri   r   rx  r'  r5   r5   r6   r    s    $z)UnixDomainSocketConnection._error_message)r0   r1   r2   r   r   r<   r   rM   r	   rN   rO   r   r/   r   rX   r   rF   r   r   r   r  r  r5   r5   r5   r6   rw    sL   

?"rw  )0FFALSENNOr   c                 C   s6   | d ks| dkrd S t | tr.|  tkr.dS t| S )Nr)  F)rI   r<   upperFALSE_STRINGSrO   )rG   r5   r5   r6   to_bool  s
    r  )r   r   r   r   r   max_connectionsr   ra  .URL_QUERY_ARGUMENT_PARSERSc                   @   sJ   e Zd ZU eed< eed< ee ed< eed< eed< eed< eed< dS )	ConnectKwargsr   r   connection_classr   r   r   rx  N)r0   r1   r2   r<   r>   r   ro   rM   r5   r5   r5   r6   r  
  s   
r  )urlrH   c              
   C   s  t | }i }t|j D ]v\}}|rt|dkrt|d }t|}|rz||||< W q tt	fk
r   t	d| dY qX q|||< q|j
rt|j
|d< |jrt|j|d< |jdkr|jrt|j|d< t|d< n|jd	kr||jrt|j|d
< |jrt|j|d< |jrfd|krfztt|jdd|d< W n tt	fk
rd   Y nX |jdkrt|d< nd}t	d| d|S )Nr   zInvalid value for `z` in connection URL.r   r   unixrx  r  )Zredisredissr   r   r   /r)  r  zredis://, rediss://, unix://z5Redis URL must specify one of the following schemes ())r   r   queryr  ri   r   r  rk   r  
ValueErrorr   r   schemerx  rw  hostnamer   rM   r   AttributeErrorrZ  )r  parsedr   nameZ
value_listrG   parserZvalid_schemesr5   r5   r6   	parse_url  sJ    





r  _CPConnectionPool)boundc                   @   s   e Zd ZdZeee eedddZe	dfee	 e
e dddZd	d
 Zdd Zdd Zdd Zdd Zdd Ze	dddZe	dddZdedddZdS )r  a  
    Create a connection pool. ``If max_connections`` is set, then this
    object raises :py:class:`~redis.ConnectionError` when the pool's
    limit is reached.

    By default, TCP connections are created unless ``connection_class``
    is specified. Use :py:class:`~redis.UnixDomainSocketConnection` for
    unix sockets.

    Any additional keyword arguments are passed to the constructor of
    ``connection_class``.
    )clsr  rH   c                 K   s   t |}|| | f |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://` 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  update)r  r  r   Zurl_optionsr5   r5   r6   from_urlY  s    (
zConnectionPool.from_urlNr  r  c                 K   sp   |pd}t |tr|dk r"td|| _|| _|| _t | _t	 | _
|  |  |  |   | jdt| _d S )Nl        r   z,"max_connections" must be a positive integerr   )rI   rM   r  r  connection_kwargsr  	threadingr   
_fork_lockr   r   resetrk   r@   r   )rE   r  r  r  r5   r5   r6   rF     s    


zConnectionPool.__init__c                 C   s   | j j d| jf | jdS )Nr   r   )rQ   r0   r  r  rc   r5   r5   r6   r     s    zConnectionPool.__repr__c                 C   s,   t  | _d| _g | _t | _t | _	d S r   )
r   r   r   _created_connections_available_connectionsset_in_use_connectionsr   r   r   rc   r5   r5   r6   r    s
    
zConnectionPool.resetc                 C   sP   | j t krL| jjdd}|s$tz| j t kr<|   W 5 | j  X d S )N   r   )r   r   r   r  acquirer   releaser  )rE   Zacquiredr5   r5   r6   	_checkpid  s    #zConnectionPool._checkpidc              
      s  |    | j4 I dH > z| j }W n tk
rB   |  }Y nX | j| W 5 Q I dH R X zx| I dH  z|	 I dH rt
ddW nH t
k
r   | I dH  | I dH  |	 I dH rt
ddY nX W n& tk
r   | |I dH   Y nX |S )zGet a connection from the poolNConnection has dataConnection not ready)r  r   r  pop
IndexErrormake_connectionr  addr  rw   r   r  rB  r  rE   command_namekeysoptionsrq   r5   r5   r6   get_connection  s*    zConnectionPool.get_connectionc                 C   s.   | j }| j|dd|dd|dddS )z,Return an encoder based on encoding settingsr:   r   rB   r   rC   FrA   )r  r   rk   )rE   r   r5   r5   r6   get_encoder
  s    


zConnectionPool.get_encoderc                 C   s0   | j | jkrtd|  j d7  _ | jf | jS )zCreate a new connectionzToo many connectionsrg   )r  r  r   r  r  rc   r5   r5   r6   r    s    zConnectionPool.make_connectionrp   c              
      s   |    | j4 I dH t z| j| W n tk
r<   Y nX | |rV| j| n0|  jd8  _|	 I dH  W 5 Q I dH R  dS W 5 Q I dH R X dS )z(Releases the connection back to the poolNrg   )
r  r   r  removeKeyErrorowns_connectionr  r   r  r  rr   r5   r5   r6   r    s    
zConnectionPool.releasec                 C   s   |j | j kS rD   )r   rr   r5   r5   r6   r  /  s    zConnectionPool.owns_connectionTinuse_connectionsc              
      s   |    | j4 I dH \ |r,t| j| j}n| j}tjdd |D ddiI dH }tdd |D d}|rn|W 5 Q I dH R X dS )z
        Disconnects connections in the pool

        If ``inuse_connections`` is True, disconnect connections that are
        current in use, potentially by other tasks. Otherwise only disconnect
        connections that are idle in the pool.
        Nc                 s   s   | ]}|  V  qd S rD   r2  r   rq   r5   r5   r6   r   C  s     z,ConnectionPool.disconnect.<locals>.<genexpr>return_exceptionsTc                 s   s   | ]}t |tr|V  qd S rD   rI   rB  r   rr5   r5   r6   r   F  s     
 )r  r   r   r  r  r   gathernext)rE   r  connectionsrespr  r5   r5   r6   r  2  s      zConnectionPool.disconnect)T)r0   r1   r2   rV   classmethodr   r  r<   r  ro   r	   rM   rF   r   r  r  r  r  r  r  r  rO   r  r5   r5   r5   r6   r  K  s$   -/!	c                       s|   e Zd ZdZddeejfeee e	e e	ej
 d fddZdd Zd	d
 Zdd ZedddZded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      )r  ru   r  queue_classc                    s,   || _ || _|  t jf ||d| d S )Nr  )r  ru   r   rF   )rE   r  ru   r  r  r  r   r5   r6   rF   m  s    	zBlockingConnectionPool.__init__c                 C   sP   |  | j| _z| jd  W q tjk
r8   Y q<Y qX qg | _t | _	d S rD   )
r  r  pool
put_nowaitr   	QueueFull_connectionsr   r   r   rc   r5   r5   r6   r    s    zBlockingConnectionPool.resetc                 C   s   | j f | j}| j| |S )zMake a fresh connection.)r  r  r  r   rr   r5   r5   r6   r    s    z&BlockingConnectionPool.make_connectionc              
      s"  |    d}z:t| j4 I dH  | j I dH }W 5 Q I dH R X W n$ tjtjfk
rj   tdY nX |dkr|| 	 }zx|
 I dH  z| I dH rtddW nH tk
r   | I dH  |
 I dH  | I dH rtddY nX W n( tk
r   | |I dH   Y nX |S )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.
        NzNo connection available.r  r  )r  r   ru   r  rk   r   Z
QueueEmptyr%   r   r  r  rw   r  rB  r  r  r5   r5   r6   r    s.    $z%BlockingConnectionPool.get_connectionrp   c                    s\   |    | |s0| I dH  | jd dS z| j| W n tjk
rV   Y nX dS )z)Releases the connection back to the pool.N)r  r  r  r  r  r   r  rr   r5   r5   r6   r    s    
zBlockingConnectionPool.releaseTr  c              
      sj   |    | j4 I dH D tjdd | jD ddiI dH }tdd |D d}|rV|W 5 Q I dH R X dS )z(Disconnects all connections in the pool.Nc                 s   s   | ]}|  V  qd S rD   r2  r  r5   r5   r6   r     s     z4BlockingConnectionPool.disconnect.<locals>.<genexpr>r  Tc                 s   s   | ]}t |tr|V  qd S rD   r  r  r5   r5   r6   r     s     
 )r  r   r   r  r  r  )rE   r  r  r  r5   r5   r6   r    s    z!BlockingConnectionPool.disconnect)T)r0   r1   r2   rV   ro   r   	LifoQueuerM   r	   r   QueuerF   r  r  r  r  rO   r  r   r5   r5   r   r6   r  K  s    #5r  )ur   r   enumr   r  r   r   r   r  r7  r  r  	itertoolsr   typesr   typingr   r   r   r   r   r	   r
   r   r   r   r   urllib.parser   r   r   r   r   Zredis.asyncio.retryr   Zredis.backoffr   Zredis.compatr   r   Zredis.exceptionsr   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   Zredis.typingr&   r'   Zredis.utilsr(   r)   r   BlockingIOErrorEWOULDBLOCKSSLWantReadErrorSSLWantWriteErrorSSLErrorr   rM  r  r   rO  rQ  r   ZSYM_LFrN  r   Enumr/   r4   r   r{   r}   r~   r|   r7   r@   r<   r=   r   rX   r   r   r   r>   r   r   r   rY  ro   rZ  ri  rw  r  rO   r  rM   rN   r  r3   r  r  r  r  r  r5   r5   r5   r6   <module>   s    4D    )$B Tm    .5Y
4  