U
    d                  
   @   sH  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	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( 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=rdd dl?Z?dZ@dZAdZBdZCdZDdZEG dd dejFZGeGjHZIdZJdZKdZLdZMe*e*dZNG dd de%ddZOG dd dZPeeQeeeR eeQeeR f f f ZSG d d! d!ZTG d"d# d#eTZUG d$d% d%eTZVeeeUeVf  eWd&< e=rBeVZXneUZXG d'd( d(e$ZYG d)d* d*e$ZZeeYeZf Z[G d+d, d,Z\G d-d. d.e\Z]G d/d0 d0Z^G d1d2 d2e\Z_d3Z`eea d4d5d6Zbeecededebebececebd7ZeeeQed8eff f eWd9< G d:d; d;e%ddZgeQegd<d=d>Zhed?d@dAZiG dBd@ d@ZjG dCdD dDejZkdS )E    N)chain)MappingProxyType)AnyCallableIterableListMappingOptionalSetTupleTypeTypeVarUnion)ParseResultparse_qsunquoteurlparse)Retry)	NoBackoff)Protocol	TypedDict)CredentialProvider"UsernamePasswordCredentialProvider)AuthenticationError$AuthenticationWrongNumberOfArgsErrorBusyLoadingErrorChildDeadlockedErrorConnectionError	DataErrorExecAbortErrorInvalidResponseModuleErrorNoPermissionErrorNoScriptError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 r7   r7   </tmp/pip-unpacked-wheel-xj5sloo9/redis/asyncio/connection.pyr1   B   s   r1   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)r2   r3   r4   r   str	Exception__annotations__r	   r7   r7   r7   r8   r:   Z   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r=   encoding_errorsdecode_responsesc                 C   s   || _ || _|| _d S NrD   )selfr=   rE   rF   r7   r7   r8   __init__f   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=   rE   bytes
memoryviewintfloatboolr   repr	__class__r2   )rH   rJ   typenamer7   r7   r8   rM   k   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)rF   rL   rN   decoder=   rE   rO   tobytes)rH   rJ   forcer7   r7   r8   rV      s    


zEncoder.decodeN)F)r2   r3   r4   __doc__	__slots__r?   rR   rI   r(   r)   rM   rV   r7   r7   r7   r8   rC   a   s
   rC   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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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_sizezmax number of clients reachedr9   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NOPERMEXCEPTION_CLASSESsocket_read_sizec                 C   s   d | _ || _d S rG   r]   rH   rb   r7   r7   r8   rI      s    zBaseParser.__init__c                 C   s&   z|    W n tk
r    Y nX d S rG   )on_disconnectr@   rH   r7   r7   r8   __del__   s    zBaseParser.__del__)responserK   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`   lenrL   dictgetr&   )rH   rg   Z
error_codeZexception_classr7   r7   r8   parse_error   s    


zBaseParser.parse_errorc                 C   s
   t  d S rG   NotImplementedErrorre   r7   r7   r8   rd      s    zBaseParser.on_disconnect
Connection
connectionc                 C   s
   t  d S rG   ro   rH   rs   r7   r7   r8   
on_connect   s    zBaseParser.on_connectrK   c                    s
   t  d S rG   ro   re   r7   r7   r8   can_read_destructive   s    zBaseParser.can_read_destructiveFNdisable_decodingrK   c                    s
   t  d S rG   ro   )rH   ry   r7   r7   r8   read_response   s    zBaseParser.read_response)F)$r2   r3   r4   rY   rZ   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`   ExceptionMappingTrA   rP   rI   rf   r?   r&   rn   rd   ru   rR   rw   r   r(   r   rz   r7   r7   r7   r8   r[      sT   
          r[   c                       s   e Zd ZdZej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 ) PythonParserr\   )encoder_buffer_pos_chunksra   c                    s(   t  | d | _d| _g | _d| _d S )Nr0   r   )superrI   r   r   r   r   rc   rT   r7   r8   rI      s
    zPythonParser.__init__c                 C   s   d| _ | j  d S )Nr0   )r   r   clearre   r7   r7   r8   _clear   s    zPythonParser._clearrq   rr   c                 C   s&   |j | _| jdkrtd|j| _dS )zCalled when the stream connectsNBuffer is closed.)_readerr^   r%   r   rt   r7   r7   r8   ru      s    
zPythonParser.on_connectc                 C   s"   | j dk	rd| _ d| _|   dS )z"Called when the stream disconnectsN)r^   r   r   re   r7   r7   r8   rd      s    
zPythonParser.on_disconnectrv   c                    s   | j r
dS | jd krtdzJt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
r~   Y dS X d S )NTr   r   ri   F)r   r^   r%   async_timeouttimeoutreadasyncior'   re   r7   r7   r8   rw      s    
6z!PythonParser.can_read_destructiveFry   c                    sJ   | j r&|  jd| j 7  _| j   d| _| j|dI d H }|   |S )Nr0   r   r   )r   r   joinr   r   _read_responser   rH   ry   rg   r7   r7   r8   rz      s    
zPythonParser.read_responseNrx   c                    s8  j rjstt I d H }|d d |dd   }}|dkrRtd||dkr|jddd}|}t|tr	  ||S |dkrn||d	krt
|}nj|d
krt
|}|dkrd S |I d H }n<|dkrt
|}|dkrd S  fddt|D I d H }t|tr4 dkr4j|}|S )Nri   )   -   +   :r-   r,   zProtocol Error: r   utf-8replace)r>   r   r   r-   r,   c                    s   g | ]}  I d H qS rG   )r   ).0_ry   rH   r7   r8   
<listcomp>0  s    z/PythonParser._read_response.<locals>.<listcomp>F)r^   r   r   SERVER_CLOSED_CONNECTION_ERROR	_readliner    rV   rn   rL   r   rP   _readrangerN   )rH   ry   rawbyterg   errorlengthr7   r   r8   r     s@    



zPythonParser._read_response)r   rK   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   rk   r   r^   Zreadexactlyr   ZIncompleteReadErrorr   r   r   append)rH   r   Zwantendresulttaildatar   r7   r7   r8   r   7  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.
        r.   r   Nr   r   )r   findr   r^   readlineendswithr   r   r   r   rk   )rH   foundr   r   r   r7   r7   r8   r   K  s    
zPythonParser._readline)F)F)r2   r3   r4   rY   r[   rZ   rP   rI   r   ru   rd   rR   rw   rz   r   r(   r&   r   rN   r   r   __classcell__r7   r7   r   r8   r      s   
 2r   c                       st   e Zd ZdZej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   
_connectedra   c                    s*   t stdt j|d d | _d| _d S )NzHiredis is not available.ra   F)r*   r%   r   rI   r   r   rc   r   r7   r8   rI   c  s
    zHiredisParser.__init__rq   rr   c                 C   sL   |j | _t| jd}|jjr4|jj|d< |jj|d< tj	f || _ d| _
d S )N)r;   r<   r=   r>   T)r   r^   r    rn   r   rF   r=   rE   hiredisReaderr   )rH   rs   kwargsr7   r7   r8   ru   j  s    zHiredisParser.on_connectc                 C   s
   d| _ d S )NF)r   re   r7   r7   r8   rd   w  s    zHiredisParser.on_disconnectc                    s   | j stt| j rdS zFt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
rz   Y dS X d S )NTr   F)
r   r   r   r   getsr   r   read_from_socketr   r'   re   r7   r7   r8   rw   z  s    
2z"HiredisParser.can_read_destructivec                    s<   | j | jI d H }|r"t|ts,ttd | j| dS )NT)	r^   r   r_   rL   rN   r   r   r   feed)rH   bufferr7   r7   r8   r     s
    
zHiredisParser.read_from_socketFrx   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   )r   r   r   r   r   r   rL   listr   r7   r7   r8   rz     s     


zHiredisParser.read_response)F)r2   r3   r4   rY   r[   rZ   rP   rI   ru   rd   rw   r   rR   r   r(   r   rz   r   r7   r7   r   r8   r   ^  s   

 r   DefaultParserc                   @   s   e Zd ZddddZdS )ConnectCallbackProtocolrq   rr   c                 C   s   d S rG   r7   rt   r7   r7   r8   __call__  s    z ConnectCallbackProtocol.__call__Nr2   r3   r4   r   r7   r7   r7   r8   r     s   r   c                   @   s   e Zd ZddddZdS )AsyncConnectCallbackProtocolrq   rr   c                    s   d S rG   r7   rt   r7   r7   r8   r     s    z%AsyncConnectCallbackProtocol.__call__Nr   r7   r7   r7   r8   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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 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#dDedd&d'd(Z$d)d* Z%d+d, Z&d-d. Z'e(e dd/d0d1Z)dEe	eee(e f edd3d4d5Z*e+e+dd6d7d8Z,d9d: Z-dFeee d;d<d=Z.e/e0e d>d?d@Z1e(e(e/  e0e dAdBdCZ2dS )Grq   z4Manages TCP communication to and from a Redis server)pidhostportdbusernameclient_namecredential_providerpasswordsocket_timeout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=   rE   rF   parser_classrb   r   r   r   retryr   encoder_classr   c                C   sN  |s|r|d k	rt dt | _|| _t|| _|| _|| _|| _	|| _
|| _|| _|p`|p`d | _|| _|ppi | _|	| _|
| _|tkrg }|
r|t |tj |tj || _|s|r|stt d| _nt|| _| j| ntt d| _|| _d| _ d | _!||||| _"|| _#d | _$d | _%|| _&| '| g | _(d| _)d S )N'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'ri   r   r   p  )*r   osgetpidr   r   rP   r   r   r   r   r   r   r   r   r   r   r   r   SENTINELr   r'   socketr   r   r   r   r   r   copydeepcopyupdate_supported_errorsr   r   r   r   r   r   r   r   
set_parserr   r   )rH   r   r   r   r   r   r   r   r   r   r   r   r=   rE   rF   r   rb   r   r   r   r   r   r   r   r7   r7   r8   rI     sT    




zConnection.__init__c                 C   s,   d dd |  D }| jj d| dS )N,c                 s   s    | ]\}}| d | V  qdS )=Nr7   )r   kvr7   r7   r8   	<genexpr>/  s     z&Connection.__repr__.<locals>.<genexpr><>)r   repr_piecesrT   r2   )rH   Z	repr_argsr7   r7   r8   __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   rH   piecesr7   r7   r8   r   2  s    zConnection.repr_piecesc                 C   sR   z8| j r6t }|  }| r,|| n
|| W n tk
rL   Y nX d S rG   )is_connectedr   get_running_loop
disconnectZ
is_runningZcreate_taskZrun_until_completer@   )rH   Zloopcoror7   r7   r8   rf   8  s    zConnection.__del__c                 C   s   | j d k	o| jd k	S rG   )r   r   re   r7   r7   r8   r   D  s    zConnection.is_connectedc                 C   s   | j t| d S rG   )r   r   weakref
WeakMethod)rH   callbackr7   r7   r8   register_connect_callbackH  s    z$Connection.register_connect_callbackc                 C   s
   g | _ d S rG   )r   re   r7   r7   r8   clear_connect_callbacksK  s    z"Connection.clear_connect_callbacks)r   rK   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
        ra   N)r   r   )rH   r   r7   r7   r8   r   N  s    zConnection.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 rG   )_connectr7   re   r7   r8   <lambda>\  r0   z$Connection.connect.<locals>.<lambda>c                    s      S rG   r   )r   re   r7   r8   r   \  r0   zTimeout connecting to server)r   r   call_with_retryr   CancelledErrorr   r   r'   OSErrorr   _error_messager@   r   ru   iscoroutinefunctionr%   r   r   inspectisawaitable)rH   eexcrefr   Ztaskr7   re   r8   connectV  s>    
 

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   ri   )r   r   r   r   Zopen_connectionr   r   r   rm   r   r   	transportZget_extra_info
setsockoptr   IPPROTO_TCPTCP_NODELAYr   
SOL_SOCKETSO_KEEPALIVEr   itemsSOL_TCPr  	TypeErrorclose)rH   readerwritersockr   r   r7   r7   r8   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 peerri   . r   .Error z connecting to )argsr   r   rk   rH   	exceptionr7   r7   r8   r    s    ",zConnection._error_messagerv   c                    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   ru   r   r   r   r   Zget_credentialssend_commandrz   r   r+   r   r   r   r   )rH   Zcred_providerZ	auth_argsZauth_responser7   r7   r8   ru     s,    zConnection.on_connect)nowaitrK   c              
      s   zt | j4 I dH  | j  | js>W 5 Q I dH R  W dS zJz0t	 | j
krn| j  |sn| 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   r   rd   r   r   r   r   r   r   r  Zwait_closedr  r   r'   )rH   r'  r7   r7   r8   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   re   r7   r7   r8   
_send_ping  s    zConnection._send_pingc                    s   |   I dH  dS )z Function to call when PING failsNr  )rH   r   r7   r7   r8   _ping_failed  s    zConnection._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   r   timer   r   r  r(  r)  re   r7   r7   r8   r#    s
    zConnection.check_health)commandrK   c                    s    | j | | j  I d H  d S rG   )r   
writelinesdrain)rH   r+  r7   r7   r8   _send_packed_command  s    zConnection._send_packed_commandT)r+  r#  rK   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 socketri   UNKNOWNr   r  z while writing to socket. r  )r   r  r#  rL   r?   rM   rN   r   r   wait_forr.  r   r,  r-  r'   r   r  rk   r  r   r@   )rH   r+  r#  r	  Zerr_noerrmsgr7   r7   r8   send_packed_command  sB    

 

zConnection.send_packed_command)r  r   rK   c                    s&   | j | j| |dddI dH  dS )z+Pack and send a command to the Redis serverr#  Tr$  N)r3  pack_commandrm   )rH   r  r   r7   r7   r8   r&  &  s     
zConnection.send_commandc              
      sl   z| j  I dH W S  tk
rf } z6| jdd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.NTr/  Error while reading from r  z: )r   rw   r  r   r   r   r   r  )rH   r	  r7   r7   r8   rw   ,  s    zConnection.can_read_destructive)ry   r   c              
      s  |dk	r|n| j }zZ|dk	rVt|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 | jddI dH  td| j d| j	 Y n t
k
r } z6| jddI dH  td| j d| j	 d|j W 5 d}~X Y nB tjk
r&    Y n* tk
rN   | jddI dH   Y nX | jrpt  | j }|| _t|tr|d|S )	z0Read the response from a previously sent commandNr   Tr/  zTimeout reading from r  r5  z : )r   r   r   r   rz   r   r'   r   r   r   r  r   r  r  r@   r   r   r*  r   rL   r&   )rH   ry   r   read_timeoutrg   r	  Z	next_timer7   r7   r8   rz   6  s>    zConnection.read_response)r  rK   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   ri   N    )rL   rQ   AssertionErrorr?   tuplerM   rj   	SYM_EMPTYr   SYM_STARrk   SYM_CRLFr   mapr   rO   
SYM_DOLLARr   )rH   r  outputZbuffbuffer_cutoffargZ
arg_lengthr7   r7   r8   r4  c  sB    "





zConnection.pack_command)commandsrK   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   r4  rk   rL   rO   r   r:  r   )	rH   rB  r?  r   Zbuffer_lengthr@  cmdchunkZchunklenr7   r7   r8   pack_commands  s0    
zConnection.pack_commands)F)T)FN)3r2   r3   r4   rY   rZ   r   r   rC   r?   r   rP   r	   rQ   rR   r   rN   r   r1   r   r[   r   ConnectCallbackTr   rI   r   r   rf   propertyr   r   r   r   r  r   r  ru   r   r(  r)  r#  r   r.  r3  r   r&  rw   rz   r(   r   r4  rE  r7   r7   r7   r8   rq     s   #


M
'(  %  -.rq   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   rI   RedisSSLContextr   )rH   rJ  rK  rL  rM  rN  rO  r   r   r7   r8   rI     s    
zSSLConnection.__init__c                 C   s   | j jS rG   )r   rQ  re   r7   r7   r8   rQ    s    zSSLConnection.keyfilec                 C   s   | j jS rG   )r   rR  re   r7   r7   r8   rR    s    zSSLConnection.certfilec                 C   s   | j jS rG   )r   rS  re   r7   r7   r8   rS    s    zSSLConnection.cert_reqsc                 C   s   | j jS rG   )r   rT  re   r7   r7   r8   rT    s    zSSLConnection.ca_certsc                 C   s   | j jS rG   )r   rU  re   r7   r7   r8   rU    s    zSSLConnection.ca_datac                 C   s   | j jS rG   )r   rV  re   r7   r7   r8   rV    s    zSSLConnection.check_hostname)NNrI  NNF)r2   r3   r4   r	   r?   rR   rI   rG  rQ  rR  rS  rT  rU  rV  r   r7   r7   r   r8   rH    s4         




rH  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 )rW  )rQ  rR  rS  rT  rU  contextrV  NFrP  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optionalrI  z+Invalid SSL Certificate Requirements Flag: )rQ  rR  r  	CERT_NONErS  rL   r?   CERT_OPTIONALCERT_REQUIREDr%   rT  rU  rV  rX  )rH   rQ  rR  rS  rT  rU  rV  Z	CERT_REQSr7   r7   r8   rI     s$    	


zRedisSSLContext.__init__rv   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)rR  rQ  )cafilecadata)rX  r  create_default_contextrV  rS  verify_moderR  rQ  load_cert_chainrT  rU  load_verify_locations)rH   rX  r7   r7   r8   rm     s    zRedisSSLContext.get)NNNNNF)r2   r3   r4   rZ   r	   r?   rR   rI   r  
SSLContextrm   r7   r7   r7   r8   rW    s          rW  c                   @   s   e Zd Zddddddddddeed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 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 )UnixDomainSocketConnection r   Nr   r   Fr   g        )pathr   r   r   r   r   r=   rE   rF   r   r   r   rb   r   r   r   r   r   )rg  r   r   r   r   r   r=   rE   rF   r   r   r   rb   r   r   r   r   c                C   s  |s|r|dk	rt dt | _|| _|| _|| _|| _|| _|| _	|| _
|pV|pVd| _|
| _|tkrlg }|
rz|t || _|r|dkrtt d| _nt|| _| j| ntt d| _|| _d| _|| _t|||	| _d| _d| _d| _|| _|  | g | _!d| _"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
        Nr   ri   r   r   r   )#r   r   r   r   rg  r   r   r   r   r   r   r   r   r   r   r'   r   r   r   r   r   r   r   r   r   r   rC   r   _sockr   r   r   r   r   r   )rH   rg  r   r   r   r   r   r=   rE   rF   r   r   r   rb   r   r   r   r   r   r7   r7   r8   rI     sH    


z#UnixDomainSocketConnection.__init__rv   c                 C   s.   d| j fd| jfg}| jr*|d| jf |S )Nrg  r   r   )rg  r   r   r   r   r7   r7   r8   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)rg  )	r   r   r   r   Zopen_unix_connectionrg  r   r   ru   )rH   r  r  r7   r7   r8   r   a  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 )Nri   z!Error connecting to unix socket: r  r   r  r  z connecting to unix socket: )rk   r  rg  r   r7   r7   r8   r  h  s    $z)UnixDomainSocketConnection._error_message)r2   r3   r4   r   r   r?   r   rP   r	   rQ   rR   r   r1   r   r[   r   r   rI   r   r   r   r   r  r7   r7   r7   r8   re    sP   

G"re  )0FFALSENNOrv   c                 C   s6   | d ks| dkrd S t | tr.|  tkr.dS t| S )Nrf  F)rL   r?   upperFALSE_STRINGSrR   )rJ   r7   r7   r8   to_boolw  s
    rp  )r   r   r   r   r   max_connectionsr   rO  .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   rg  N)r2   r3   r4   r?   rA   r   rq   rP   r7   r7   r7   r8   rs    s   
rs  )urlrK   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   unixrg  rt  )Zredisredissr   r   r   /rf  rw  zredis://, rediss://, unix://z5Redis URL must specify one of the following schemes ())r   r   queryr  rk   r   rr  rm   r  
ValueErrorr   r   schemerg  re  hostnamer   rP   r   AttributeErrorrH  )ru  parsedr   nameZ
value_listrJ   parserZvalid_schemesr7   r7   r8   	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``.
    )clsru  rK   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)r  ru  r   Zurl_optionsr7   r7   r8   from_url  s    (
zConnectionPool.from_urlNrt  rq  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   )rL   rP   r{  rt  connection_kwargsrq  	threadingLock
_fork_lockr   r   resetrm   rC   r   )rH   rt  rq  r  r7   r7   r8   rI     s    


zConnectionPool.__init__c                 C   s   | j j d| jf | jdS )Nr   r   )rT   r2   rt  r  re   r7   r7   r8   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   re   r7   r7   r8   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  )rH   Zacquiredr7   r7   r8   	_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  rw   r   r  r   BaseExceptionr  rH   command_namekeysoptionsrs   r7   r7   r8   get_connectionl  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   rE   r   rF   FrD   )r  r   rm   )rH   r   r7   r7   r8   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 connectionsri   )r  rq  r   rt  r  re   r7   r7   r8   r    s    zConnectionPool.make_connectionrr   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 poolNri   )
r  r   r  removeKeyErrorowns_connectionr  r   r  r   rt   r7   r7   r8   r    s    
zConnectionPool.releasec                 C   s   |j | j kS rG   )r   rt   r7   r7   r8   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 rG   r  r   rs   r7   r7   r8   r     s     z,ConnectionPool.disconnect.<locals>.<genexpr>return_exceptionsTc                 s   s   | ]}t |tr|V  qd S rG   rL   r  r   rr7   r7   r8   r     s     
 )r  r   r   r  r  r   gathernext)rH   r  connectionsrespr
  r7   r7   r8   r     s      zConnectionPool.disconnectr   )r   rK   c                 C   s(   | j D ]
}||_q| jD ]
}||_qd S rG   )r  r   r  )rH   r   connr7   r7   r8   	set_retry  s    

zConnectionPool.set_retry)T)r2   r3   r4   rY   classmethodr   r  r?   r  rq   r	   rP   rI   r   r  r  r  r  r  r  r  rR   r   r  r7   r7   r7   r8   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      )rq  r   rt  queue_classc                    s,   || _ || _|  t jf ||d| d S )Nr  )r  r   r   rI   )rH   rq  r   rt  r  r  r   r7   r8   rI     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 rG   )
r  rq  pool
put_nowaitr   	QueueFull_connectionsr   r   r   re   r7   r7   r8   r    s    zBlockingConnectionPool.resetc                 C   s   | j f | j}| j| |S )zMake a fresh connection.)rt  r  r  r   rt   r7   r7   r8   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|| 	 }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  rm   r   Z
QueueEmptyr'   r   r  r  rw   r  r   r  r  r  r7   r7   r8   r  &  s.    $z%BlockingConnectionPool.get_connectionrr   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  rt   r7   r7   r8   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 rG   r  r  r7   r7   r8   r   u  s     z4BlockingConnectionPool.disconnect.<locals>.<genexpr>r  Tc                 s   s   | ]}t |tr|V  qd S rG   r  r  r7   r7   r8   r   x  s     
 )r  r   r   r  r  r  )rH   r  r  r
  r7   r7   r8   r   p  s    z!BlockingConnectionPool.disconnect)T)r2   r3   r4   rY   rq   r   	LifoQueuerP   r	   r   QueuerI   r  r  r  r  rR   r   r   r7   r7   r   r8   r    s    #5r  )lr   r   enumr  r   r   r  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.credentialsr   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   r;  r>  r<  ZSYM_LFr:  r   Enumr1   r6   r   r{   r}   r~   r|   r   r:   rC   r?   r@   r   r[   r   r   rA   r   r   r   rF  rq   rH  rW  re  ro  rR   rp  rP   rQ   rr  r5   rs  r  r  r  r  r7   r7   r7   r8   <module>   s    4D

)$C L   u.5a
4  