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
mZ d dlmZ d dlmZ d dlmZmZmZmZmZmZmZmZmZmZmZ d dlmZmZmZm Z  ej!dkrd dl m"Z# nd dl#m"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- d dl.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z> d dl?m@Z@mAZA d dlBmCZCmDZD dZEeCrd dlEZEdZFdZGdZHdZIdZJdZKG dd dejLZMeMjNZOdZPdZQdZRdZSe/e/dZTG dd de*dd ZUG d!d" d"ZVeeWeeeX eeWeeX f f f ZYG d#d$ d$ZZG d%d& d&eZZ[G d'd( d(eZZ\eee[e\f  e]d)< eCrve\Z^ne[Z^G d*d+ d+e)Z_G d,d- d-e)Z`ee_e`f ZaG d.d/ d/ZbG d0d1 d1ebZcG d2d3 d3ecZdG d4d5 d5ZeG d6d7 d7ebZfd8Zgeeh d9d:d;Zieejekekeieiejejeid<ZleeWed=emf f e]d>< G d?d@ d@e*dd ZneWendAdBdCZoedDdEdFZpG dGdE dEZqG dHdI dIeqZrdS )J    N)abstractmethod)chain)MappingProxyType)AnyCallableIterableListMappingOptionalSetTupleTypeTypeVarUnion)ParseResultparse_qsunquoteurlparse)      r   timeout)Retry)	NoBackoff)Protocol	TypedDict)CredentialProvider"UsernamePasswordCredentialProvider)AuthenticationError$AuthenticationWrongNumberOfArgsErrorBusyLoadingErrorChildDeadlockedErrorConnectionError	DataErrorExecAbortErrorInvalidResponseModuleErrorNoPermissionErrorNoScriptErrorOutOfMemoryErrorReadOnlyError
RedisErrorResponseErrorTimeoutError)
EncodableTEncodedT)HIREDIS_AVAILABLEstr_if_bytes   *   $   
   
    zConnection closed by server.c                   @   s   e Zd Ze ZdS )	_SentinelN)__name__
__module____qualname__objectsentinel r=   r=   U/var/www/html/myproject/myenv/lib/python3.8/site-packages/redis/asyncio/connection.pyr7   K   s   r7   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 unload)zxAUTH <password> called without any password configured for the default user. Are you sure your configuration is correct?(Client sent AUTH, but no password is setc                   @   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)r8   r9   r:   r   str	Exception__annotations__r
   r=   r=   r=   r>   r@   c   s   
r@   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rC   encoding_errorsdecode_responsesc                 C   s   || _ || _|| _d S NrJ   )selfrC   rK   rL   r=   r=   r>   __init__o   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)
isinstancerE   encoderC   rK   bytes
memoryviewintfloatboolr#   repr	__class__r8   )rN   rP   typenamer=   r=   r>   rS   t   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)rL   rR   rT   decoderC   rK   rU   tobytes)rN   rP   forcer=   r=   r>   r\      s    


zEncoder.decodeN)F)r8   r9   r:   __doc__	__slots__rE   rX   rO   r.   r/   rS   r\   r=   r=   r=   r>   rI   j   s
   rI   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eeed	Zeed	< ed
ddZeeedddZdd ZddddZ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
_read_size
_connectedzmax number of clients reachedr?   zinvalid passwordz,wrong number of arguments for 'auth' commandz,wrong number of arguments for 'AUTH' command)	ZERRZ	WRONGPASSZ	EXECABORTZLOADINGZNOSCRIPTZREADONLYZNOAUTHZNOPERMZOOMEXCEPTION_CLASSESsocket_read_sizec                 C   s   d | _ || _d| _d S NFrc   rN   ri   r=   r=   r>   rO      s    zBaseParser.__init__)responserQ   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)splitrg   lenrR   dictgetr,   )clsrl   Z
error_codeZexception_classr=   r=   r>   parse_error   s    


zBaseParser.parse_errorc                 C   s
   t  d S rM   NotImplementedErrorrN   r=   r=   r>   on_disconnect   s    zBaseParser.on_disconnectAbstractConnection
connectionc                 C   s
   t  d S rM   ru   rN   r{   r=   r=   r>   
on_connect   s    zBaseParser.on_connectrQ   c                    s
   t  d S rM   ru   rw   r=   r=   r>   can_read_destructive   s    zBaseParser.can_read_destructiveFNdisable_decodingrQ   c                    s
   t  d S rM   ru   )rN   r   r=   r=   r>   read_response   s    zBaseParser.read_response)F)%r8   r9   r:   r_   r`   r"   r   r   MODULE_LOAD_ERRORr&   MODULE_EXPORTS_DATA_TYPES_ERRORNO_SUCH_MODULE_ERROR MODULE_UNLOAD_NOT_POSSIBLE_ERRORNO_AUTH_SET_ERRORr$   r    r(   r*   r'   r)   rg   ExceptionMappingTrG   rV   rO   classmethodrE   r,   rt   rx   r}   rX   r   r   r.   r   r   r=   r=   r=   r>   ra      sV   
          ra   c                       s   e Zd ZdZdZed fddZdd Zdd	d
dZdd Z	e
dddZde
dddZde
eeedf dddZeedddZedddZ  ZS ) PythonParserrb   )encoder_buffer_pos_chunksrh   c                    s(   t  | d | _d| _g | _d| _d S )Nr6   r   )superrO   r   r   r   r   rk   rZ   r=   r>   rO      s
    zPythonParser.__init__c                 C   s   d| _ | j  d S )Nr6   )r   r   clearrw   r=   r=   r>   _clear   s    zPythonParser._clearry   rz   c                 C   s4   |j | _| jdkrtd|j| _|   d| _dS )zCalled when the stream connectsNBuffer is closed.T)_readerrd   r+   r   r   rf   r|   r=   r=   r>   r}      s    
zPythonParser.on_connectc                 C   s
   d| _ dS )z"Called when the stream disconnectsFNrf   rw   r=   r=   r>   rx      s    zPythonParser.on_disconnectr~   c                    s~   | j std| jrdS zHtd4 I d H ( | jdI d H W  5 Q I d H R  W S Q I d H R X W n tjk
rx   Y dS X d S )Nr   Tr   rn   F)rf   r+   r   async_timeoutrd   readasyncior-   rw   r=   r=   r>   r      s    6z!PythonParser.can_read_destructiveFr   c                    sX   | j stt| jr4|  jd| j7  _| j  d| _| j|dI d H }| 	  |S )Nr6   r   r   )
rf   r"   SERVER_CLOSED_CONNECTION_ERRORr   r   joinr   r   _read_responser   rN   r   rl   r=   r=   r>   r      s    
zPythonParser.read_responseNr   c                    s    I d H }|d d |dd   }}|dkrb|jddd}|}t|tr^  ||S |dkrln|dkr|t|S |dkr|d	krd S |dkrt|I d H }nN|d
kr|d	krd S |d
kr fddtt|D I d H }nt	d| dkrj
|}|S )Nrn      -utf-8replace)rD      +   :r3   s   -1r2   c                    s   g | ]}  I d H qS rM   )r   ).0_r   rN   r=   r>   
<listcomp>/  s   z/PythonParser._read_response.<locals>.<listcomp>zProtocol Error: F)	_readliner\   rt   rR   r"   r   rV   _readranger%   r   )rN   r   rawbyterl   errorr=   r   r>   r     s6    



zPythonParser._read_response)lengthrQ   c              
      s   |d }| j | }t| j|kr6| j| j |d  }nz| j| j d }z| j|t| I dH }W n. tjk
r } ztt|W 5 d}~X Y nX || dd }| j	
| |  j |7  _ |S )z
        Read `length` bytes of data.  These are assumed to be followed
        by a '
' terminator which is subsequently discarded.
           N)r   rp   r   rd   readexactlyr   IncompleteReadErrorr"   r   r   append)rN   r   Zwantendresulttaildatar   r=   r=   r>   r   :  s    
zPythonParser._readc                    s   | j d| j}|dkr*| j | j| }nN| j | jd }| j I dH }|ds\tt|| dd }| j	| |  jt
|d 7  _|S )zq
        read an unknown number of bytes up to the next '
'
        line separator, which is discarded.
        r4   r   Nr   r   )r   findr   rd   readlineendswithr"   r   r   r   rp   )rN   foundr   r   r   r=   r=   r>   r   N  s    
zPythonParser._readline)F)F)r8   r9   r:   r_   r`   rV   rO   r   r}   rx   rX   r   r   r   r.   r,   r   rT   r   r   __classcell__r=   r=   r   r>   r      s   	 /r   c                       sn   e Zd ZdZdZed fddZdddd	Zd
d Zdd Z	dd Z
deeeee f dddZ  ZS )HiredisParserz*Parser class for connections using Hiredis)r   rh   c                    s$   t stdt j|d d | _d S )NzHiredis is not available.rh   )r0   r+   r   rO   r   rk   r   r=   r>   rO   f  s    zHiredisParser.__init__ry   rz   c                 C   sL   |j | _t| jd}|jjr4|jj|d< |jj|d< tj	f || _ d| _
d S )N)rA   rB   rC   rD   T)r   rd   r%   rt   r   rL   rC   rK   hiredisReaderrf   )rN   r{   kwargsr=   r=   r>   r}   l  s    zHiredisParser.on_connectc                 C   s
   d| _ d S rj   r   rw   r=   r=   r>   rx   y  s    zHiredisParser.on_disconnectc                    s~   | j stt| j rdS zDtd4 I d H $ |  I d H W  5 Q I d H R  W S Q I d H R X W n tjk
rx   Y dS X d S )NTr   F)	rf   r"   r   r   getsr   read_from_socketr   r-   rw   r=   r=   r>   r   |  s    
2z"HiredisParser.can_read_destructivec                    s<   | j | jI d H }|r"t|ts,ttd | j| dS )NT)	rd   r   re   rR   rT   r"   r   r   feed)rN   bufferr=   r=   r>   r     s
    
zHiredisParser.read_from_socketFr   c                    st   | j sttd | j }|dkr<|  I d H  | j }qt|trL|n$t|trp|rpt|d trp|d |S )NFr   )rf   r"   r   r   r   r   rR   listr   r=   r=   r>   r     s     


zHiredisParser.read_response)F)r8   r9   r:   r_   r`   rV   rO   r}   rx   r   r   rX   r   r.   r   r   r   r=   r=   r   r>   r   a  s   
 r   DefaultParserc                   @   s   e Zd ZddddZdS )ConnectCallbackProtocolry   rz   c                 C   s   d S rM   r=   r|   r=   r=   r>   __call__  s    z ConnectCallbackProtocol.__call__Nr8   r9   r:   r   r=   r=   r=   r>   r     s   r   c                   @   s   e Zd ZddddZdS )AsyncConnectCallbackProtocolry   rz   c                    s   d S rM   r=   r|   r=   r=   r>   r     s    z%AsyncConnectCallbackProtocol.__call__Nr   r=   r=   r=   r>   r     s   r   c                   @   s  e Zd ZdZdZdddddedddeddddddedd	ee	e
f ee	 ee ee eeeef e	e	eee e
eee	 ee	 ee ee ee ee d	d
dZdd Zedd Zedd Zdd Zdd Zee ddddZdd Zedd Zee	dddZ ee!e	d d!d"Z"ddd#d$Z#dDedd%d&d'Z$d(d) Z%d*d+ Z&d,d- Z'e(e) dd.d/d0Z*dEee)e	e(e) f edd2d3d4Z+e,e,dd5d6d7Z-d8d9 Z.dFd1d:eee ed;d<d=Z/e0e1e) d>d?d@Z2e(e(e0  e1e) dAdBdCZ3dS )Gry   z0Manages communication to and from a Redis server)piddbusernameclient_namecredential_providerpasswordsocket_timeoutsocket_connect_timeout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__r   NFr   stricti   )r   r   r   r   r   r   rC   rK   rL   parser_classri   r   r   r   retryr   encoder_classr   c                C   s&  |s|r|d k	rt dt | _|| _|| _|| _|| _|| _|| _	|d krR|}|| _
|| _|tkrjg }|r|t |tj |tj || _|s|r|stt d| _nt|| _| j| ntt d| _|| _d| _||||	| _|| _d | _d | _|| _|  |
 g | _!d| _"d S )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'rn   r   ip  )#r#   osgetpidr   r   r   r   r   r   r   r   r   SENTINELr   r-   socketr   r   r   r   r   r   copydeepcopyZupdate_supported_errorsr   r   r   r   r   r   r   
set_parserr   r   )rN   r   r   r   r   r   r   rC   rK   rL   r   ri   r   r   r   r   r   r   r   r=   r=   r>   rO     sL    


zAbstractConnection.__init__c                 C   s,   d dd |  D }| jj d| dS )N,c                 s   s    | ]\}}| d | V  qdS )=Nr=   )r   kvr=   r=   r>   	<genexpr>#  s     z.AbstractConnection.__repr__.<locals>.<genexpr><>)r   repr_piecesrZ   r8   )rN   Z	repr_argsr=   r=   r>   __repr__"  s    zAbstractConnection.__repr__c                 C   s   d S rM   r=   rw   r=   r=   r>   r   &  s    zAbstractConnection.repr_piecesc                 C   s   | j d k	o| jd k	S rM   )r   r   rw   r=   r=   r>   is_connected*  s    zAbstractConnection.is_connectedc                 C   s   | j t| d S rM   )r   r   weakref
WeakMethod)rN   callbackr=   r=   r>   register_connect_callback.  s    z,AbstractConnection.register_connect_callbackc                 C   s
   g | _ d S rM   )r   rw   r=   r=   r>   clear_connect_callbacks1  s    z*AbstractConnection.clear_connect_callbacks)r   rQ   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
        rh   N)r   r   )rN   r   r=   r=   r>   r   4  s    zAbstractConnection.set_parserc              
      sj   j r
dS z( j fdd fddI dH  W n tjk
rJ    Y n| tjtjfk
rl   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}| }| }|r4t|r4|I dH  q4dS )z5Connects to the Redis server if not already connectedNc                      s      S rM   )_connectr=   rw   r=   r>   <lambda>B  r6   z,AbstractConnection.connect.<locals>.<lambda>c                    s      S rM   
disconnect)r   rw   r=   r>   r   B  r6   zTimeout connecting to server)r   r   call_with_retryr   CancelledErrorr   r   r-   OSErrorr"   _error_messagerF   r   r}   iscoroutinefunctionr+   r   r   inspectisawaitable)rN   eexcrefr   taskr=   rw   r>   connect<  s>    
 

zAbstractConnection.connectc                    s   d S rM   r=   rw   r=   r=   r>   r   c  s    zAbstractConnection._connectr~   c                 C   s   d S rM   r=   rw   r=   r=   r>   _host_errorg  s    zAbstractConnection._host_error	exceptionrQ   c                 C   s   d S rM   r=   )rN   r  r=   r=   r>   r  k  s    z!AbstractConnection._error_messagec                    s2  | j |  | js| js| jr| jp0t| j| j}| }| jd|ddiI dH  z|  I dH }W n< t	k
r   | jd|d 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_healthFNr   r  OKzInvalid Username or PasswordZCLIENTZSETNAMEzError setting client nameZSELECTzInvalid Database)r  )r   r}   r   r   r   r   Zget_credentialssend_commandr   r   r1   r   r   r"   r   )rN   Zcred_providerZ	auth_argsZauth_responser=   r=   r>   r}   o  s,    zAbstractConnection.on_connect)nowaitrQ   c              
      s   zt | j4 I dH  | j  | js<W 5 Q I dH R  W dS zJz0t | j	krl| j
  |sl| 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 serverNz#Timed out closing connection after )r   r   r   rx   r   r   r   r   r   r   closewait_closedr   r   r-   )rN   r  r=   r=   r>   r     s(    



zAbstractConnection.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  r1   r   r"   rw   r=   r=   r>   
_send_ping  s    zAbstractConnection._send_pingc                    s   |   I dH  dS )z Function to call when PING failsNr   )rN   r   r=   r=   r>   _ping_failed  s    zAbstractConnection._ping_failedc                    s4   | j r0t  | jkr0| j| j| jI dH  dS )z3Check the health of the connection with a PING/PONGN)	r   r   get_running_looptimer   r   r   r  r  rw   r=   r=   r>   r    s
    zAbstractConnection.check_health)commandrQ   c                    s    | j | | j  I d H  d S rM   )r   
writelinesdrain)rN   r  r=   r=   r>   _send_packed_command  s    z'AbstractConnection._send_packed_commandT)r  r  rQ   c              
      sn  | 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   | jddI d H  tdd Y n tk
r@ } zd| jddI d H  t|jdkrd|jd  }}n|jd }|jd }td| d| d	|W 5 d }~X Y n* tk
rh   | jddI d H   Y nX d S )
NTr  zTimeout writing to socketrn   UNKNOWNr   Error z while writing to socket. .)r   r	  r  rR   rE   rS   rT   r   r   wait_forr  r   r  r  r-   r   r   rp   argsr"   BaseException)rN   r  r  r  Zerr_noerrmsgr=   r=   r>   send_packed_command  sB    

 

z&AbstractConnection.send_packed_command)r"  r   rQ   c                    s&   | j | j| |dddI dH  dS )z+Pack and send a command to the Redis serverr  Tr  N)r%  pack_commandrr   )rN   r"  r   r=   r=   r>   r    s     
zAbstractConnection.send_commandc              
      sj   z| j  I dH W S  tk
rd } z4| jddI dH  |  }td| d|j W 5 d}~X Y nX dS )z8Poll the socket to see if there's data that can be read.NTr  Error while reading from z: )r   r   r   r   r
  r"   r"  )rN   r  
host_errorr=   r=   r>   r     s    z'AbstractConnection.can_read_destructive)disconnect_on_error)r   r   r)  c          	   
      sn  |dk	r|n| j }|  }zX|dk	r\t|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   |dk	rY dS |r| jddI dH  td| Y n~ tk
r } z0|r| jddI dH  t	d| d|j
 W 5 d}~X Y n0 tk
r6   |r0| jddI dH   Y nX | jrXt  | j }|| _t|trj|d|S )z0Read the response from a previously sent commandNr   Tr  zTimeout reading from r'  z : )r   r
  r   r   r   r   r-   r   r   r"   r"  r#  r   r  r  r   rR   r,   )	rN   r   r   r)  read_timeoutr(  rl   r  Z	next_timer=   r=   r>   r     s>    &z AbstractConnection.read_response)r"  rQ   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   rn   N    )rR   rW   AssertionErrorrE   tuplerS   ro   	SYM_EMPTYr   SYM_STARrp   SYM_CRLFr   mapr   rU   
SYM_DOLLARr   )rN   r"  outputZbuffbuffer_cutoffargZ
arg_lengthr=   r=   r>   r&  -  sB    "





zAbstractConnection.pack_command)commandsrQ   c           	      C   s   g }g }d}| j }|D ]}| j| D ]r}t|}||ksJ||ksJt|trf|r^|t| d}g }||ksxt|tr|| q$|| ||7 }q$q|r|t| |S )z.Pack multiple commands into the Redis protocolr   )r   r&  rp   rR   rU   r   r.  r   )	rN   r6  r3  piecesZbuffer_lengthr4  cmdchunkZchunklenr=   r=   r>   pack_commands[  s0    
z AbstractConnection.pack_commands)F)T)FN)4r8   r9   r:   r_   r`   r   r   rI   r   rE   rV   r
   rW   rX   r   r7   r   ra   r   ConnectCallbackTr   rO   r   r   r   propertyr   r   r   r   r	  r   r
  r#  r  r}   r   r  r  r  r   rT   r  r%  r   r  r   r   r.   r   r&  r:  r=   r=   r=   r>   ry     s   

D

'
(  )  0.ry   c                
       s   e Zd ZdZddddddeeeef eee	eeee
f f  ed fdd	Zd
d Ze	dddZdd ZedddZeedddZ  ZS )
Connectionz4Manages TCP communication to and from a Redis server	localhosti  FNr   )hostportsocket_keepalivesocket_keepalive_optionssocket_typec                   s8   || _ t|| _|| _|pi | _|| _t jf | d S rM   )r?  rV   r@  rA  rB  rC  r   rO   )rN   r?  r@  rA  rB  rC  r   r   r=   r>   rO   }  s    


zConnection.__init__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   rN   r7  r=   r=   r>   r     s    zConnection.repr_piecesr~   c                 C   s   | j | jdS )Nr?  r@  rE  rw   r=   r=   r>   _connection_arguments  s    z Connection._connection_argumentsc              
      s   t | j4 I dH   tjf |  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 connectionNr   rn   )r   r   r   open_connectionrF  r   r   	transportget_extra_info
setsockoptr   IPPROTO_TCPTCP_NODELAYrA  
SOL_SOCKETSO_KEEPALIVErB  itemsSOL_TCPr   	TypeErrorr  )rN   readerwritersockr   r   r=   r=   r>   r     s"    zConnection._connectc                 C   s   | j  d| j S )N:rE  rw   r=   r=   r>   r
    s    zConnection._host_errorr  c                 C   sh   |   }|jsd| dS t|jdkr@d| d|jd  dS d|jd  d| d|jd  dS d S )	NzError connecting to z. Connection reset by peerrn   . r   r   r  z connecting to )r
  r"  rp   rN   r  r(  r=   r=   r>   r    s    "zConnection._error_message)r8   r9   r:   r_   rE   r   rV   rX   r
   r	   rT   rO   r   rF  r   r
  r#  r  r   r=   r=   r   r>   r=  z  s$   
r=  c                       s   e Zd ZdZdee ee eee ee ed fddZ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 )SSLConnectionzManages SSL connections to and from the Redis server(s).
    This class extends the Connection class, adding SSL functionality, and making
    use of ssl.SSLContext (https://docs.python.org/3/library/ssl.html#ssl.SSLContext)
    NrequiredF)ssl_keyfilessl_certfilessl_cert_reqsssl_ca_certsssl_ca_datassl_check_hostnamec                    s(   t ||||||d| _t jf | d S )Nkeyfilecertfile	cert_reqsca_certsca_datacheck_hostname)RedisSSLContextr   r   rO   )rN   rZ  r[  r\  r]  r^  r_  r   r   r=   r>   rO     s    
zSSLConnection.__init__r~   c                    s   t   }| j |d< |S )Nssl)r   rF  r   rr   rN   r   r   r=   r>   rF    s    
z#SSLConnection._connection_argumentsc                 C   s   | j jS rM   )r   ra  rw   r=   r=   r>   ra    s    zSSLConnection.keyfilec                 C   s   | j jS rM   )r   rb  rw   r=   r=   r>   rb    s    zSSLConnection.certfilec                 C   s   | j jS rM   )r   rc  rw   r=   r=   r>   rc    s    zSSLConnection.cert_reqsc                 C   s   | j jS rM   )r   rd  rw   r=   r=   r>   rd    s    zSSLConnection.ca_certsc                 C   s   | j jS rM   )r   re  rw   r=   r=   r>   re    s    zSSLConnection.ca_datac                 C   s   | j jS rM   )r   rf  rw   r=   r=   r>   rf    s    zSSLConnection.check_hostname)NNrY  NNF)r8   r9   r:   r_   r
   rE   rX   rO   r	   rF  r<  ra  rb  rc  rd  re  rf  r   r=   r=   r   r>   rX    s8         




rX  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 )rg  )ra  rb  rc  rd  re  contextrf  NFr`  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optionalrY  z+Invalid SSL Certificate Requirements Flag: )ra  rb  rh  	CERT_NONErc  rR   rE   CERT_OPTIONALCERT_REQUIREDr+   rd  re  rf  rj  )rN   ra  rb  rc  rd  re  rf  Z	CERT_REQSr=   r=   r>   rO     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)rb  ra  )cafilecadata)rj  rh  create_default_contextrf  rc  verify_moderb  ra  load_cert_chainrd  re  load_verify_locations)rN   rj  r=   r=   r>   rr   (  s    zRedisSSLContext.get)NNNNNF)r8   r9   r:   r`   r
   rE   rX   rO   rh  
SSLContextrr   r=   r=   r=   r>   rg     s          rg  c                       st   e Zd ZdZdded fddZeeeeee	f f  dddZ
d	d
 ZedddZeedddZ  ZS )UnixDomainSocketConnectionz4Manages UDS communication to and from a Redis server pathc                   s   || _ t jf | d S rM   )rz  r   rO   )rN   rz  r   r   r=   r>   rO   8  s    z#UnixDomainSocketConnection.__init__r~   c                 C   s.   d| j fd| jfg}| jr*|d| jf |S )Nrz  r   r   )rz  r   r   r   rD  r=   r=   r>   r   <  s    z&UnixDomainSocketConnection.repr_piecesc              
      sZ   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 )Nry  )r   r   r   open_unix_connectionrz  r   r   r}   )rN   rR  rS  r=   r=   r>   r   B  s
    (z#UnixDomainSocketConnection._connectc                 C   s   | j S rM   ry  rw   r=   r=   r>   r
  I  s    z&UnixDomainSocketConnection._host_errorr  c                 C   sV   |   }t|jdkr.d| d|jd  dS d|jd  d| d|jd  dS d S )Nrn   z!Error connecting to unix socket: rV  r   r   r  z connecting to unix socket: )r
  rp   r"  rW  r=   r=   r>   r  L  s    "z)UnixDomainSocketConnection._error_message)r8   r9   r:   r_   rE   rO   r   r   r   rV   r   r   r
  r#  r  r   r=   r=   r   r>   rw  5  s   "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 )Nrx  F)rR   rE   upperFALSE_STRINGSrX   )rP   r=   r=   r>   to_bool^  s
    r  )r   r   r   rA  r   max_connectionsr   r_  .URL_QUERY_ARGUMENT_PARSERSc                   @   sJ   e Zd ZU eed< eed< ee ed< eed< eed< eed< eed< dS )	ConnectKwargsr   r   connection_classr?  r@  r   rz  N)r8   r9   r:   rE   rG   r   ry   rV   r=   r=   r=   r>   r  t  s   
r  )urlrQ   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   unixrz  r  )Zredisredissr?  r@  r   /rx  r  zredis://, rediss://, unix://z5Redis URL must specify one of the following schemes ())r   r   queryrO  rp   r   r  rr   rQ  
ValueErrorr   r   schemerz  rw  hostnamer@  rV   r   AttributeErrorrX  )r  parsedr   nameZ
value_listrP   parserZvalid_schemesr=   r=   r>   	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d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``.
    )rs   r  rQ   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@]/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  update)rs   r  r   Zurl_optionsr=   r=   r>   from_url  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   )rR   rV   r  r  connection_kwargsr  	threadingLock
_fork_lockr   r   resetrr   rI   r   )rN   r  r  r  r=   r=   r>   rO     s    


zConnectionPool.__init__c                 C   s   | j j d| jf | jdS )Nr   r   )rZ   r8   r  r  rw   r=   r=   r>   r     s    zConnectionPool.__repr__c                 C   s,   t  | _d| _g | _t | _t | _	d S )Nr   )
r   r  r   _created_connections_available_connectionsset_in_use_connectionsr   r   r   rw   r=   r=   r>   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  )rN   Zacquiredr=   r=   r>   	_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 z|| I dH  z|	 I dH rt
ddW nL t
tf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	  r   r"   r   r   r#  r  rN   command_namekeysoptionsr{   r=   r=   r>   get_connectionS  s*    zConnectionPool.get_connectionc                 C   s.   | j }| j|dd|dd|dddS )z,Return an encoder based on encoding settingsrC   r   rK   r   rL   FrJ   )r  r   rr   ri  r=   r=   r>   get_encodert  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 connectionsrn   )r  r  r"   r  r  rw   r=   r=   r>   r  }  s    zConnectionPool.make_connectionrz   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 poolNrn   )
r  r   r  removeKeyErrorowns_connectionr  r   r  r   r|   r=   r=   r>   r    s    
zConnectionPool.releasec                 C   s   |j | j kS rM   )r   r|   r=   r=   r>   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 rM   r   r   r{   r=   r=   r>   r     s     z,ConnectionPool.disconnect.<locals>.<genexpr>return_exceptionsTc                 s   s   | ]}t |tr|V  qd S rM   rR   r#  r   rr=   r=   r>   r     s     
 )r  r   r   r  r  r   gathernext)rN   r  connectionsrespr  r=   r=   r>   r     s      zConnectionPool.disconnectr   )r   rQ   c                 C   s(   | j D ]
}||_q| jD ]
}||_qd S rM   )r  r   r  )rN   r   connr=   r=   r>   	set_retry  s    

zConnectionPool.set_retry)T)r8   r9   r:   r_   r   r   r  rE   r  r=  ry   r
   rV   rO   r   r  r  r  r  r  r  r  rX   r   r  r=   r=   r=   r>   r    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  r   r  queue_classc                    s,   || _ || _|  t jf ||d| d S )Nr  )r  r   r   rO   )rN   r  r   r  r  r  r   r=   r>   rO     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 rM   )
r  r  pool
put_nowaitr   	QueueFull_connectionsr   r   r   rw   r=   r=   r>   r    s    zBlockingConnectionPool.resetc                 C   s   | j f | j}| j| |S )zMake a fresh connection.)r  r  r  r   r|   r=   r=   r>   r    s    z&BlockingConnectionPool.make_connectionc              
      s$  |    d}z8t| 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
rh   tdY nX |dkrz| 	 }z||
 I dH  z| I dH rtddW nL ttf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   r   r  rr   r   
QueueEmptyr-   r"   r  r	  r   r   r   r#  r  r  r=   r=   r>   r    s.    $z%BlockingConnectionPool.get_connectionrz   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  r|   r=   r=   r>   r  B  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 rM   r   r  r=   r=   r>   r   \  s     z4BlockingConnectionPool.disconnect.<locals>.<genexpr>r  Tc                 s   s   | ]}t |tr|V  qd S rM   r  r  r=   r=   r>   r   _  s     
 )r  r   r   r  r  r  )rN   r  r  r  r=   r=   r>   r   W  s    z!BlockingConnectionPool.disconnect)T)r8   r9   r:   r_   r=  r   	LifoQueuerV   r
   r   ry   QueuerO   r  r  r  r  rX   r   r   r=   r=   r   r>   r    s    #5r  )sr   r   enumr  r   r   rh  sysr  r   abcr   	itertoolsr   typesr   typingr   r   r   r   r	   r
   r   r   r   r   r   urllib.parser   r   r   r   version_infor   r   Zredis.asyncio.retryr   Zredis.backoffr   Zredis.compatr   r   Zredis.credentialsr   r   Zredis.exceptionsr   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   Zredis.typingr.   r/   Zredis.utilsr0   r1   r   r/  r2  r0  ZSYM_LFr.  r   Enumr7   r<   r   r   r   r   r   r   r@   rI   rE   rF   r   ra   r   r   rG   r   r   r   r;  ry   r=  rX  rg  rw  r  rX   r  rV   rW   r  r;   r  r  r  r  r  r=   r=   r=   r>   <module>   s    4
H

)$@ K   =N85&
4  