o
    Ch                    @   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mZ d dl	m
Z
 d dlmZmZmZ d dlmZmZmZmZmZmZmZmZ d dlmZmZmZ d dlmZmZmZm Z m!Z!m"Z" dd	l#m$Z$m%Z%m&Z&m'Z' dd
l(m)Z) ddl*m+Z+ ddl,m-Z-m.Z. ddl/m0Z0m1Z1 ddl2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z; ddl<m=Z= ddl>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZG eArd dlHZHndZHe@rd dlIZIdZJdZKdZLdZMdZNeO ZPeee&e'e%f  eQd< e@re%ZRne&ZRG dd dZSG dd dZTG dd dZUG dd deUZVG dd  d eVZWG d!d" d"eUZXG d#d$ d$eWZYG d%d& d&eVZZd'Z[d(d) Z\e]e^e^e\e\e_e]e]e\e^d*
Z`d+d, Zaed-d.d/ZbG d0d. d.ZcG d1d2 d2ecZddS )3    N)abstractmethod)chain)EmptyFull	LifoQueue)AnyCallableDictListOptionalTypeTypeVarUnion)parse_qsunquoteurlparse)
CacheEntryCacheEntryStatusCacheFactoryCacheFactoryInterfaceCacheInterfaceCacheKey   )Encoder_HiredisParser_RESP2Parser_RESP3Parser)TokenInterface)	NoBackoff)CredentialProvider"UsernamePasswordCredentialProvider)AfterConnectionReleasedEventEventDispatcher)	AuthenticationError$AuthenticationWrongNumberOfArgsErrorChildDeadlockedErrorConnectionError	DataErrorMaxConnectionsError
RedisErrorResponseErrorTimeoutError)Retry)	CRYPTOGRAPHY_AVAILABLEHIREDIS_AVAILABLESSL_AVAILABLEcompare_versionsdeprecated_argsensure_stringformat_error_messageget_lib_versionstr_if_bytes   *   $s   
       DefaultParserc                   @   s   e Zd ZdefddZdS )HiredisRespSerializerargsc                 G   s   g }t |d trt|d   |dd  }nd|d v r.t|d  |dd  }z|t| W |S  tyN   t	
 \}}}t||w 2Pack a series of arguments into the Redis protocolr   r   N    )
isinstancestrtupleencodesplitappendhiredispack_command	TypeErrorsysexc_infor'   with_traceback)selfr<   output_value	traceback rQ   b/var/www/html/myvaluetrips/my_value_trip_new/venv/lib/python3.10/site-packages/redis/connection.pypackM   s   "zHiredisRespSerializer.packN)__name__
__module____qualname__r
   rS   rQ   rQ   rQ   rR   r;   L   s    r;   c                   @   s   e Zd ZdddZdd ZdS )PythonRespSerializerreturnNc                 C   s   || _ || _d S N)_buffer_cutoffrC   )rL   buffer_cutoffrC   rQ   rQ   rR   __init___   s   
zPythonRespSerializer.__init__c              	   G   s  g }t |d trt|d   |dd  }nd|d v r.t|d  |dd  }tttt| t	f}| j
}t| j|D ]>}t|}t||ksZ||ksZt |trtt|tt| t	f}|| || t	}qEt|tt| t	|t	f}qE|| |S r=   )r@   rA   rB   rC   rD   	SYM_EMPTYjoinSYM_STARlenSYM_CRLFrZ   map
memoryview
SYM_DOLLARrE   )rL   r<   rM   buffr[   arg
arg_lengthrQ   rQ   rR   rS   c   s<   "




zPythonRespSerializer.packrX   N)rT   rU   rV   r\   rS   rQ   rQ   rQ   rR   rW   ^   s    
rW   c                   @   s  e Zd Zedd Zedd Zedd Zedd Zed	d
 Zedd Z	edd Z
edd Zedd Zed,ddZedd Zed-ddZe	d.dddddZedd  Zed!d" Zeed#eeeef eeef f fd$d%Zed&efd'd(Zed)d* Zd+S )/ConnectionInterfacec                 C      d S rY   rQ   rL   rQ   rQ   rR   repr_pieces      zConnectionInterface.repr_piecesc                 C   rj   rY   rQ   rL   callbackrQ   rQ   rR   register_connect_callback   rm   z-ConnectionInterface.register_connect_callbackc                 C   rj   rY   rQ   rn   rQ   rQ   rR   deregister_connect_callback   rm   z/ConnectionInterface.deregister_connect_callbackc                 C   rj   rY   rQ   rL   parser_classrQ   rQ   rR   
set_parser   rm   zConnectionInterface.set_parserc                 C   rj   rY   rQ   rk   rQ   rQ   rR   get_protocol   rm   z ConnectionInterface.get_protocolc                 C   rj   rY   rQ   rk   rQ   rQ   rR   connect   rm   zConnectionInterface.connectc                 C   rj   rY   rQ   rk   rQ   rQ   rR   
on_connect   rm   zConnectionInterface.on_connectc                 G   rj   rY   rQ   rL   r<   rQ   rQ   rR   
disconnect   rm   zConnectionInterface.disconnectc                 C   rj   rY   rQ   rk   rQ   rQ   rR   check_health   rm   z ConnectionInterface.check_healthTc                 C   rj   rY   rQ   rL   commandrz   rQ   rQ   rR   send_packed_command   rm   z'ConnectionInterface.send_packed_commandc                 O   rj   rY   rQ   rL   r<   kwargsrQ   rQ   rR   send_command   rm   z ConnectionInterface.send_commandr   c                 C   rj   rY   rQ   rL   timeoutrQ   rQ   rR   can_read   rm   zConnectionInterface.can_readFdisconnect_on_errorpush_requestc                C   rj   rY   rQ   )rL   disable_decodingr   r   rQ   rQ   rR   read_response   s   z!ConnectionInterface.read_responsec                 G   rj   rY   rQ   rx   rQ   rQ   rR   rG      rm   z ConnectionInterface.pack_commandc                 C   rj   rY   rQ   rL   commandsrQ   rQ   rR   pack_commands   rm   z!ConnectionInterface.pack_commandsrX   c                 C   rj   rY   rQ   rk   rQ   rQ   rR   handshake_metadata   s   z&ConnectionInterface.handshake_metadatatokenc                 C   rj   rY   rQ   rL   r   rQ   rQ   rR   set_re_auth_token   rm   z%ConnectionInterface.set_re_auth_tokenc                 C   rj   rY   rQ   rk   rQ   rQ   rR   re_auth   rm   zConnectionInterface.re_authNTr   F)rT   rU   rV   r   rl   rp   rq   rt   ru   rv   rw   ry   rz   r}   r   r   r   rG   r   propertyr   r	   bytesrA   r   r   r   r   rQ   rQ   rQ   rR   ri      sT    









	

*ri   c                *   @   sV  e Zd ZdZdddddedddedddde ddddd	ddfd
edee	 dee
 dee
 dede	de	dedededee	 dee	 dee	 dee	 deedf deeg df  dee dee deeg df  dee f(ddZd d! Zed"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Z	0d`d1ed2efd3d4Zed5d6 Zed7d8 Zd9d: Zd;d< Zdad1efd=d>Z d?d@ Z!dAdB Z"dCdD Z#dEdF Z$dadGdHZ%dIdJ Z&dbdKdLZ'	dcd0ddMdNdOZ(dPdQ Z)dRdS Z*dTeee	f fdUdVZ+e,dTee-e.e.f e-e	e	f f fdWdXZ/e/j0dYee-e.e.f e-e	e	f f fdZdXZ/d[e1fd\d]Z2d^d_ Z3dS )dAbstractConnectionz0Manages communication to and from a Redis serverr   NFutf-8stricti   zredis-pyr9   dbpasswordsocket_timeoutsocket_connect_timeoutretry_on_timeoutencodingencoding_errorsdecode_responsessocket_read_sizehealth_check_intervalclient_namelib_namelib_versionusernameretryredis_connect_funccredential_providerprotocolcommand_packerevent_dispatcherc                 C   s  |s|r|durt d|du rt | _n|| _t | _|| _|| _|| _|| _	|| _
|| _|| _|| _|du r;|}|| _|| _|tu rGg }|rN|t || _|sU|rn|du ratt d| _nt|| _| j| ntt d| _|| _d| _|| _t|||	| _d| _d| _ || _!| "|
 g | _#d| _$d| _%z-zt&|}W n t'y   t(}Y n t)y   t*dw W |dk s|dkrt*d	|| _+n|dk s|dkrt*d	|| _+w | ,|| _-dS )
a2  
        Initialize a new Connection.
        To specify a retry policy for specific errors, first set
        `retry_on_error` to a list of the error/s to retry on, then set
        `retry` to a valid `Retry` object.
        To retry on TimeoutError, `retry_on_timeout` can also be set to `True`.
        Nz'username' and 'password' cannot be passed along with 'credential_provider'. Please provide only one of the following arguments: 
1. 'password' and (optional) 'username'
2. 'credential_provider'r   r   ip  zprotocol must be an integerr9      zprotocol must be either 2 or 3).r'   r"   _event_dispatcherosgetpidpidr   r   r   r   r   r   r   r   r   r   SENTINELrE   r+   retry_on_errorr,   r   r   copydeepcopyupdate_supported_errorsr   next_health_checkr   r   encoderr   _sock_socket_read_sizert   _connect_callbacksrZ   _re_auth_tokenintrH   DEFAULT_RESP_VERSION
ValueErrorr&   r   _construct_command_packer_command_packer)rL   r   r   r   r   r   r   r   r   r   rs   r   r   r   r   r   r   r   r   r   r   r   r   prQ   rQ   rR   r\      sr    



zAbstractConnection.__init__c                 C   s8   d dd |  D }d| jj d| jj d| dS )N,c                 S      g | ]\}}| d | qS =rQ   .0kvrQ   rQ   rR   
<listcomp>F      z/AbstractConnection.__repr__.<locals>.<listcomp><.(z)>)r^   rl   	__class__rU   rT   )rL   	repr_argsrQ   rQ   rR   __repr__E  s    zAbstractConnection.__repr__c                 C   rj   rY   rQ   rk   rQ   rQ   rR   rl   I  rm   zAbstractConnection.repr_piecesc                 C   s$   z|    W d S  ty   Y d S w rY   )ry   	Exceptionrk   rQ   rQ   rR   __del__M  s
   zAbstractConnection.__del__c                 C   s&   |d ur|S t rt S t| j| jjS rY   )r.   r;   rW   rZ   r   rC   )rL   packerrQ   rQ   rR   r   S  s
   z,AbstractConnection._construct_command_packerc                 C   s(   t |}|| jvr| j| dS dS )a^  
        Register a callback to be called when the connection is established either
        initially or reconnected.  This allows listeners to issue commands that
        are ephemeral to the connection, for example pub/sub subscription or
        key tracking.  The callback must be a _method_ and will be kept as
        a weak reference.
        N)weakref
WeakMethodr   rE   )rL   ro   wmrQ   rQ   rR   rp   [  s   

z,AbstractConnection.register_connect_callbackc                 C   s.   z| j t| W dS  ty   Y dS w )z
        De-register a previously registered callback.  It will no-longer receive
        notifications on connection events.  Calling this is not required when the
        listener goes away, since the callbacks are kept as weak methods.
        N)r   remover   r   r   rn   rQ   rQ   rR   rq   g  s
   z.AbstractConnection.deregister_connect_callbackc                 C   s   || j d| _dS )z
        Creates a new instance of parser_class with socket size:
        _socket_read_size and assigns it to the parser for the connection
        :param parser_class: The required parser class
        )r   N)r   _parserrr   rQ   rQ   rR   rt   r  s   zAbstractConnection.set_parserc                 C   s   | j dd dS )z5Connects to the Redis server if not already connectedTrz   N)connect_check_healthrk   rQ   rQ   rR   rv   z  s   zAbstractConnection.connectTrz   retry_socket_connectc              
      s    j rd S z|r j fdd fdd}n  }W n tjy)   td ty; } zt 	|d }~ww | _ z j
d u rL j|d n 
  W n ty^       w dd  jD  _ jD ]}| }|rv|  qkd S )Nc                            S rY   )_connectrQ   rk   rQ   rR   <lambda>      z9AbstractConnection.connect_check_health.<locals>.<lambda>c                    
     | S rY   ry   errorrk   rQ   rR   r        
 zTimeout connecting to serverr   c                 S   s   g | ]}| r|qS rQ   rQ   )r   refrQ   rQ   rR   r     s    z;AbstractConnection.connect_check_health.<locals>.<listcomp>)r   r   call_with_retryr   socketr   r+   OSErrorr&   _error_messager   on_connect_check_healthr)   ry   r   )rL   rz   r   socker   ro   rQ   rk   rR   r   ~  s@   


z'AbstractConnection.connect_check_healthc                 C   rj   rY   rQ   rk   rQ   rQ   rR   r     rm   zAbstractConnection._connectc                 C   rj   rY   rQ   rk   rQ   rQ   rR   _host_error  rm   zAbstractConnection._host_errorc                 C   s   t |  |S rY   )r3   r   )rL   	exceptionrQ   rQ   rR   r        z!AbstractConnection._error_messagec                 C   s   | j dd d S )NTr   )r   rk   rQ   rQ   rR   rw        zAbstractConnection.on_connectc                 C   s  | j |  | j }d}| js| js| jr"| jpt| j| j}| }|r`| jdvr`t| j t	r?| 
t |j| j _| j |  t|dkrKd|d g}| jd| jdg|R dd	i |  | _nv|r| jdg|R dd	i z|  }W n ty   | jd|d
 d	d |  }Y nw t|dkrtdn?| jdvrt| j t	r| 
t |j| j _| j |  | jd| j|d |  | _| jd| jkr| jd| jkrtd| jr| jdd| j|d t|  dkrtdz| jr| jddd| j|d |   W n
 ty   Y nw z| jr#| jddd| j|d |   W n
 ty.   Y nw | jrI| jd| j|d t|  dkrKtddS dS )z=Initialize the connection, authenticate and select a databaseN)r9   2r   defaultr   HELLOAUTHrz   Fr   OKzInvalid Username or Passwords   protoprotozInvalid RESP versionCLIENTSETNAMEzError setting client nameSETINFOzLIB-NAMEzLIB-VERSELECTzInvalid Database)r   rw   r   r   r   r    get_credentialsr   r@   r   rt   r   EXCEPTION_CLASSESr`   r   r   r   r$   r5   r#   getr&   r   r   r*   r   r   )rL   rz   parser	auth_argscred_providerauth_responserQ   rQ   rR   r     s   





z*AbstractConnection.on_connect_check_healthc              	   G   s|   | j   | j}d| _|du rdS t | jkr,z|tj W n t	t
fy+   Y nw z|  W dS  t	y=   Y dS w )z!Disconnects from the Redis serverN)r   on_disconnectr   r   r   r   shutdownr   	SHUT_RDWRr   rH   close)rL   r<   	conn_sockrQ   rQ   rR   ry   "  s    
zAbstractConnection.disconnectc                 C   s*   | j ddd t|  dkrtddS )z Send PING, expect PONG in returnPINGFr   PONGz#Bad response from PING health checkN)r   r5   r   r&   rk   rQ   rQ   rR   
_send_ping6  s   zAbstractConnection._send_pingc                 C      |    dS )z Function to call when PING failsNr   rL   r   rQ   rQ   rR   _ping_failed<     zAbstractConnection._ping_failedc                 C   s2   | j rt | jkr| j| j| j dS dS dS )z3Check the health of the connection with a PING/PONGN)r   time	monotonicr   r   r   r  r  rk   rQ   rQ   rR   rz   @  s   zAbstractConnection.check_healthc              
   C   s   | j s	| jdd |r|   zt|tr|g}|D ]}| j | qW d
S  tjy5   |   t	d t
yi } z)|   t|jdkrPd|jd }}n
|jd }|jd }td| d| d	d
}~w tyt   |    w )z2Send an already packed command to the Redis serverFr   zTimeout writing to socketr   UNKNOWNr   zError z while writing to socket. r   N)r   r   rz   r@   rA   sendallr   r   ry   r+   r   r`   r<   r&   BaseException)rL   r|   rz   itemr   errnoerrmsgrQ   rQ   rR   r}   E  s2   


z&AbstractConnection.send_packed_commandc                 O   s"   | j | jj| |ddd dS )z+Pack and send a command to the Redis serverrz   Tr   N)r}   r   rS   r   r~   rQ   rQ   rR   r   d  s   


zAbstractConnection.send_commandc              
   C   s`   | j }|s	|   |  }z| j|W S  ty/ } z|   td| d|j d}~ww )z8Poll the socket to see if there's data that can be read.Error while reading from z: N)	r   rv   r   r   r   r   ry   r&   r<   )rL   r   r   
host_errorr   rQ   rQ   rR   r   k  s   zAbstractConnection.can_readr   c             
   C   s   |   }z| jdv r| jj||d}n| jj|d}W n> tjy0   |r)|   td|  tyL } z|r=|   t	d| d|j
 d}~w tyY   |rX|    w | jret | j | _t|troz|~w |S )z0Read the response from a previously sent command)3r   )r   r   )r   zTimeout reading from r  z : N)r   r   r   r   r   r   ry   r+   r   r&   r<   r  r   r  r  r   r@   r*   )rL   r   r   r   r  responser   rQ   rQ   rR   r   y  s:   	

z AbstractConnection.read_responsec                 G      | j j| S )r>   )r   rS   rx   rQ   rQ   rR   rG     r  zAbstractConnection.pack_commandc           	      C   s   g }g }d}| j }|D ]B}| jj| D ]9}t|}||ks&||ks&t|tr4|r0|t| d}g }||ks=t|trC|| q|| ||7 }qq|rX|t| |S )z.Pack multiple commands into the Redis protocolr   )	rZ   r   rS   r`   r@   rc   rE   r]   r^   )	rL   r   rM   piecesbuffer_lengthr[   cmdchunkchunklenrQ   rQ   rR   r     s.   

z AbstractConnection.pack_commandsrX   c                 C      | j S rY   )r   rk   rQ   rQ   rR   ru        zAbstractConnection.get_protocolc                 C   r#  rY   _handshake_metadatark   rQ   rQ   rR   r     s   z%AbstractConnection.handshake_metadatarO   c                 C   
   || _ d S rY   r%  )rL   rO   rQ   rQ   rR   r     s   
r   c                 C   r'  rY   )r   r   rQ   rQ   rR   r        
z$AbstractConnection.set_re_auth_tokenc                 C   s<   | j d ur| d| j d| j   |   d | _ d S d S Nr   oid)r   r   try_get	get_valuer   rk   rQ   rQ   rR   r     s   


zAbstractConnection.re_auth)TTr   r   r   )4rT   rU   rV   __doc__r   r:   r4   r   r   rA   floatboolr   r   r   r   r"   r\   r   r   rl   r   r   rp   rq   rt   rv   r   r   r   r   rw   r   ry   r  r  rz   r}   r   r   r   rG   r   ru   r   r	   r   r   setterr   r   r   rQ   rQ   rQ   rR   r      s    	


`

'

o

,((r   c                       sD   e Zd ZdZ					d fdd	Zd	d
 Zdd Zdd Z  ZS )
Connectionz4Manages TCP communication to and from a Redis server	localhost  FNr   c                    s<   || _ t|| _|| _|pi | _|| _t jdi | d S NrQ   )hostr   portsocket_keepalivesocket_keepalive_optionssocket_typesuperr\   )rL   r5  r6  r7  r8  r9  r   r   rQ   rR   r\     s   	

zConnection.__init__c                 C   s6   d| j fd| jfd| jfg}| jr|d| jf |S )Nr5  r6  r   r   )r5  r6  r   r   rE   rL   r  rQ   rQ   rR   rl     s   zConnection.repr_piecesc                 C   s,  d}t | j| j| jt jD ]}}|\}}}}}d}zDt  |||}|t jt jd | j	rH|t j
t jd | j D ]\}	}
|t j|	|
 q;|| j || || j |W   S  ty } z"|}|durz|t j W n	 ty|   Y nw |  W Y d}~qd}~ww |dur|td)zCreate a TCP socket connectionNr   z)socket.getaddrinfo returned an empty list)r   getaddrinfor5  r6  r9  SOCK_STREAM
setsockoptIPPROTO_TCPTCP_NODELAYr7  
SOL_SOCKETSO_KEEPALIVEr8  items
settimeoutr   rv   r   r   r  r  r  )rL   errresfamilysocktyper   	canonnamesocket_addressr   r   r   rN   rQ   rQ   rR   r     s>   

	zConnection._connectc                 C   s   | j  d| j S )N:)r5  r6  rk   rQ   rQ   rR   r   &  s   zConnection._host_error)r2  r3  FNr   	rT   rU   rV   r-  r\   rl   r   r   __classcell__rQ   rQ   r;  rR   r1    s    -r1  c                   @   sD  e Zd ZdZdZdZdededej	fddZ
d	d
 Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd?ddZdd Zd@dd Z	!dAdd!d"d#d$Zd%d& Zd'd( Zed)eeeef eeef f fd*d+Zd,d- Zd.d/ Z ded)d0fd1d2Z!d3d4 Z"d5e#eee$e#e  f  fd6d7Z%d8d9 Z&d:e'fd;d<Z(d=d> Z)d0S )BCacheProxyConnections   fooz7.4.0redisconncache	pool_lockc                 C   sh   t  | _|| _| jj| _| jj| _| jj| _|j| _|| _|| _	t
 | _d | _d | _| | j d S rY   )r   r   r   _connr   r5  r6  r   
_pool_lock_cache	threadingRLock_cache_lock_current_command_cache_key_current_optionsrp   _enable_tracking_callback)rL   rQ  rR  rS  rQ   rQ   rR   r\   /  s   




zCacheProxyConnection.__init__c                 C   
   | j  S rY   )rT  rl   rk   rQ   rQ   rR   rl   B  r(  z CacheProxyConnection.repr_piecesc                 C      | j | d S rY   )rT  rp   rn   rQ   rQ   rR   rp   E  r   z.CacheProxyConnection.register_connect_callbackc                 C   r^  rY   )rT  rq   rn   rQ   rQ   rR   rq   H  r   z0CacheProxyConnection.deregister_connect_callbackc                 C   r^  rY   )rT  rt   rr   rQ   rQ   rR   rt   K  r   zCacheProxyConnection.set_parserc                 C   s   | j   | j jdd }|d u r| j jdd }| j jdd }|d u r-| j jdd }|d u s5|d u r9tdt|}t|}|| jksNt|| jdkrRtdd S )Ns   serverservers   versionversionz0Cannot retrieve information about server versionr   ziTo maximize compatibility with all Redis products, client-side caching is supported by Redis 7.4 or later)	rT  rv   r   r   r&   r2   DEFAULT_SERVER_NAMEr0   MIN_ALLOWED_VERSION)rL   server_name
server_verrQ   rQ   rR   rv   N  s"   

zCacheProxyConnection.connectc                 C      | j   d S rY   )rT  rw   rk   rQ   rQ   rR   rw   e  r   zCacheProxyConnection.on_connectc                 G   s@   | j  | j  W d    n1 sw   Y  | jj|  d S rY   )rY  rV  flushrT  ry   rx   rQ   rQ   rR   ry   h  s   zCacheProxyConnection.disconnectc                 C   re  rY   )rT  rz   rk   rQ   rQ   rR   rz   m  r   z!CacheProxyConnection.check_healthTc                 C   r^  rY   )rT  r}   r{   rQ   rQ   rR   r}   p  s   z(CacheProxyConnection.send_packed_commandc              	   O   s  |    | j) | jt|d dds)d | _| jj|i | 	 W d    d S W d    n1 s3w   Y  |dd u rCt	dt|d t
|dd| _| jY | j| jr| j| j}|j| jkr| j |j r~|jjdd |j srW d    n1 sw   Y  	 W d    d S | jt| j| jtj| jd W d    n1 sw   Y  | jj|i | d S )	Nr   rQ   )r|   
redis_keyskeyszCannot create cache key.Tr   )	cache_keycache_valuestatusconnection_ref)_process_pending_invalidationsrY  rV  is_cachabler   rZ  rT  r   r   r   rB   rm  rU  r   r   setr   DUMMY_CACHE_VALUEr   IN_PROGRESS)rL   r<   r   entryrQ   rQ   rR   r   u  sH   

z!CacheProxyConnection.send_commandr   c                 C      | j |S rY   )rT  r   r   rQ   rQ   rR   r        zCacheProxyConnection.can_readFr   c                C   s@  | j 8 | jd ur4| j| jd ur4| j| jjtjkr4t| j| jj	}d | _|W  d    S W d    n1 s>w   Y  | j
j|||d}| j G | jd u r^|W  d    S |d u rs| j| jg |W  d    S | j| j}|d urtj|_||_	| j| d | _W d    |S 1 sw   Y  |S )N)r   r   r   )rY  rZ  rV  r   rl  r   rr  r   r   rk  rT  r   delete_by_cache_keysVALIDrp  )rL   r   r   r   rG  r  cache_entryrQ   rQ   rR   r     sJ   
 
	
z"CacheProxyConnection.read_responsec                 G   r  rY   )rT  rG   rx   rQ   rQ   rR   rG     ru  z!CacheProxyConnection.pack_commandc                 C   rt  rY   )rT  r   r   rQ   rQ   rR   r     ru  z"CacheProxyConnection.pack_commandsrX   c                 C   s   | j jS rY   )rT  r   rk   rQ   rQ   rR   r     s   z'CacheProxyConnection.handshake_metadatac                 C   re  rY   )rT  r   rk   rQ   rQ   rR   r     r   zCacheProxyConnection._connectc                 C   re  rY   )rT  r   rk   rQ   rQ   rR   r     r   z CacheProxyConnection._host_errorNc                 C   s(   | ddd |  |j| j d S )Nr   TRACKINGON)r   r   r   set_invalidation_push_handler_on_invalidation_callback)rL   rQ  rQ   rQ   rR   r\    s   z.CacheProxyConnection._enable_tracking_callbackc                 C   s&   |   r| jjdd |   sd S d S )NTri  )r   rT  r   rk   rQ   rQ   rR   rn    s   z3CacheProxyConnection._process_pending_invalidationsdatac                 C   sd   | j % |d d u r| j  n| j|d  W d    d S W d    d S 1 s+w   Y  d S )Nr   )rY  rV  rf  delete_by_redis_keys)rL   r}  rQ   rQ   rR   r|    s   "z.CacheProxyConnection._on_invalidation_callbackc                 C   r]  rY   )rT  ru   rk   rQ   rQ   rR   ru     r(  z!CacheProxyConnection.get_protocolr   c                 C   r^  rY   )rT  r   r   rQ   rQ   rR   r     r   z&CacheProxyConnection.set_re_auth_tokenc                 C   re  rY   )rT  r   rk   rQ   rQ   rR   r     r   zCacheProxyConnection.re_authr   r   r   )*rT   rU   rV   rq  rb  ra  ri   r   rW  rX  r\   rl   rp   rq   rt   rv   rw   ry   rz   r}   r   r   r   rG   r   r   r   r	   r   rA   r   r   r   r\  rn  r
   r   r|  ru   r   r   r   rQ   rQ   rQ   rR   rO  *  sL    


0-("rO  c                       sR   e Zd ZdZ														d fdd	Z fdd	Z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requiredTFc                    s   t std|| _|| _|du rtj}nt|tr1tjtjtj	d}||vr-td| || }|| _
|| _|| _|| _| j
tjkrE|nd| _|| _|	| _|
| _|| _|| _|| _|| _t jdi | dS )a  Constructor

        Args:
            ssl_keyfile: Path to an ssl private key. Defaults to None.
            ssl_certfile: Path to an ssl certificate. Defaults to None.
            ssl_cert_reqs: The string value for the SSLContext.verify_mode (none, optional, required), or an ssl.VerifyMode. Defaults to "required".
            ssl_ca_certs: The path to a file of concatenated CA certificates in PEM format. Defaults to None.
            ssl_ca_data: Either an ASCII string of one or more PEM-encoded certificates or a bytes-like object of DER-encoded certificates.
            ssl_check_hostname: If set, match the hostname during the SSL handshake. Defaults to False.
            ssl_ca_path: The path to a directory containing several CA certificates in PEM format. Defaults to None.
            ssl_password: Password for unlocking an encrypted private key. Defaults to None.

            ssl_validate_ocsp: If set, perform a full ocsp validation (i.e not a stapled verification)
            ssl_validate_ocsp_stapled: If set, perform a validation on a stapled ocsp response
            ssl_ocsp_context: A fully initialized OpenSSL.SSL.Context object to be used in verifying the ssl_ocsp_expected_cert
            ssl_ocsp_expected_cert: A PEM armoured string containing the expected certificate to be returned from the ocsp verification service.
            ssl_min_version: The lowest supported SSL version. It affects the supported SSL versions of the SSLContext. None leaves the default provided by ssl module.
            ssl_ciphers: A string listing the ciphers that are allowed to be used. Defaults to None, which means that the default ciphers are used. See https://docs.python.org/3/library/ssl.html#ssl.SSLContext.set_ciphers for more information.

        Raises:
            RedisError
        z$Python wasn't built with SSL supportN)noneoptionalr  z+Invalid SSL Certificate Requirements Flag: FrQ   )r/   r)   keyfilecertfilessl	CERT_NONEr@   rA   CERT_OPTIONALCERT_REQUIRED	cert_reqsca_certsca_dataca_pathcheck_hostnamecertificate_passwordssl_validate_ocspssl_validate_ocsp_stapledssl_ocsp_contextssl_ocsp_expected_certssl_min_versionssl_ciphersr:  r\   )rL   ssl_keyfilessl_certfilessl_cert_reqsssl_ca_certsssl_ca_datassl_check_hostnamessl_ca_pathssl_passwordr  r  r  r  r  r  r   	CERT_REQSr;  rQ   rR   r\     s<   (
zSSLConnection.__init__c              	      s4   t   }z| |W S  ttfy   |   w )zN
        Wrap the socket with SSL support, handling potential errors.
        )r:  r   _wrap_socket_with_sslr   r)   r  rL   r   r;  rQ   rR   r   P  s   
zSSLConnection._connectc           
      C   s  t  }| j|_| j|_| js| jr|j| j| j| jd | j	dus,| j
dus,| jdur7|j| j	| j
| jd | jdur@| j|_| jrI|| j | jdu rVtdu rVtd| jr`| jr`td|j|| jd}| jrd	dl}d
dlm} | jdu r|j|jj}|| j || j n| j}| || j! |j"|t## }|$  |%| j| j&f |'  |(  |S | jdu rtrd
dlm)} ||| j| j&| j	}	|	* r|S t+d|S )z
        Wraps the socket with SSL support.

        Args:
            sock: The plain socket to wrap with SSL.

        Returns:
            An SSL wrapped socket.
        )r  r  r   N)cafilecapathcadataTFzcryptography is not installed.zKEither an OCSP staple or pure OCSP connection must be validated - not both.)server_hostnamer   r   )ocsp_staple_verifier)OCSPVerifierzocsp validation error),r  create_default_contextr  r  verify_moder  r  load_cert_chainr  r  r  r  load_verify_locationsr  minimum_versionr  set_ciphersr  r-   r)   r  wrap_socketr5  OpenSSLocspr  r  SSLContextSSLv23_METHODuse_certificate_fileuse_privatekey_fileset_ocsp_client_callbackr  r1  r   request_ocsprv   r6  do_handshaker  r  is_validr&   )
rL   r   contextsslsockr  r  
staple_ctxconr  orQ   rQ   rR   r  [  sd   





z#SSLConnection._wrap_socket_with_ssl)NNr  NNTNNFFNNNN)rT   rU   rV   r-  r\   r   r  rN  rQ   rQ   r;  rR   r     s&    Jr  c                       s:   e Zd ZdZd fdd	Zdd Zdd	 Zd
d Z  ZS )UnixDomainSocketConnectionz4Manages UDS communication to and from a Redis server Nc                    s"   t  jdi | || _|| _d S r4  )r:  r\   pathr   )rL   r  r   r   r;  rQ   rR   r\     s   
z#UnixDomainSocketConnection.__init__c                 C   s.   d| j fd| jfg}| jr|d| jf |S )Nr  r   r   )r  r   r   rE   r<  rQ   rQ   rR   rl     s   z&UnixDomainSocketConnection.repr_piecesc                 C   sz   t  t jt j}|| j z|| j W n ty4   z|t j	 W n	 ty.   Y nw |
   w || j |S )z&Create a Unix domain socket connection)r   AF_UNIXr>  rE  r   rv   r  r   r  r  r  r   r  rQ   rQ   rR   r     s   z#UnixDomainSocketConnection._connectc                 C   r#  rY   )r  rk   rQ   rQ   rR   r     r$  z&UnixDomainSocketConnection._host_error)r  NrM  rQ   rQ   r;  rR   r    s    r  )0FFALSENNOc                 C   s6   | d u s| dkr
d S t | tr|  tv rdS t| S )Nr  F)r@   rA   upperFALSE_STRINGSr/  )rO   rQ   rQ   rR   to_bool  s
   r  )
r   r   r   r7  r   r   max_connectionsr   r  r   c              
   C   s  |  ds|  ds|  dstdt| } i }t| j D ]7\}}|rWt|dkrWt|d }t	|}|rSz||||< W q  t
tfyR   td| dw |||< q | jrbt| j|d< | jrlt| j|d	< | jd
kr| jr{t| j|d< t|d< |S | jrt| j|d< | jrt| j|d< | jrd|vrztt| jdd|d< W n ttfy   Y nw | jdkrt|d< |S )Nzredis://z	rediss://zunix://zRRedis URL must specify one of the following schemes (redis://, rediss://, unix://)r   zInvalid value for 'z' in connection URL.r   r   unixr  connection_classr5  r6  r   /r  rediss)
startswithr   r   r   queryrD  r`   r   URL_QUERY_ARGUMENT_PARSERSr   rH   r   r   schemer  r  hostnamer6  r   replaceAttributeErrorr  )urlr   namerO   r  rQ   rQ   rR   	parse_url  sZ   


r  _CPConnectionPool)boundc                   @   s  e Zd ZdZedee dedefddZe	ddfde
e d	e
e fd
dZdefddZdd Zd4ddZd4ddZedgdddd5d6ddZdefddZd7ddZd8d!d"Zd ddefd#d$Zd9d&eddfd'd(Zd4d)d*Zd+eddfd,d-Zd.efd/d0Zd1e fd2d3Z!dS ):r  a  
    Create a connection pool. ``If max_connections`` is set, then this
    object raises :py:class:`~redis.exceptions.ConnectionError` when the pool's
    limit is reached.

    By default, TCP connections are created unless ``connection_class``
    is specified. Use class:`.UnixDomainSocketConnection` for
    unix sockets.
    :py:class:`~redis.SSLConnection` can be used for SSL enabled connections.

    Any additional keyword arguments are passed to the constructor of
    ``connection_class``.
    clsr  rX   c                 K   s4   t |}d|v r|d |d< || | di |S )a  
        Return a connection pool configured from the given URL.

        For example::

            redis://[[username]:[password]]@localhost:6379/0
            rediss://[[username]:[password]]@localhost:6379/0
            unix://[username@]/path/to/socket.sock?db=0[&password=password]

        Three URL schemes are supported:

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

        The username, password, hostname, path and all querystring values
        are passed through urllib.parse.unquote in order to replace any
        percent-encoded values with their corresponding characters.

        There are several ways to specify a database number. The first value
        found will be used:

            1. A ``db`` querystring option, e.g. redis://localhost?db=0
            2. If using the redis:// or rediss:// schemes, the path argument
               of the url, e.g. redis://localhost/0
            3. A ``db`` keyword argument to this function.

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

        All querystring options are cast to their appropriate Python types.
        Boolean arguments can be specified with string values "True"/"False"
        or "Yes"/"No". Values that cannot be properly cast cause a
        ``ValueError`` to be raised. Once parsed, the querystring arguments
        and keyword arguments are passed to the ``ConnectionPool``'s
        class initializer. In the case of conflicting arguments, querystring
        arguments always win.
        r  NrQ   )r  update)r  r  r   url_optionsrQ   rQ   rR   from_url2  s
   )
zConnectionPool.from_urlNr  cache_factoryc                 K   s   |pd}t |tr|dk rtd|| _|| _|| _d | _|| _|ds*|drc|ddvr5t	d| jd}|d urLt |t
sHtd	|| _n| jd urX| j | _nt| jd | _|dd  |dd  | jd
d | _| jd u rt | _t | _t | _|   d S )Nl        r   z,"max_connections" must be a positive integercache_configrR  r   )r   r  z4Client caching is only supported with RESP version 3z#Cache must implement CacheInterfacer   )r@   r   r   r  connection_kwargsr  rR  _cache_factoryr   r)   r   	get_cacher   popr   r"   rW  rX  
_fork_lock_lockreset)rL   r  r  r  r  rR  rQ   rQ   rR   r\   c  s>   





zConnectionPool.__init__c                 C   sN   d dd | j D }d| jj d| jj d| jj d| jj d| dS )	Nr   c                 S   r   r   rQ   r   rQ   rQ   rR   r     r   z+ConnectionPool.__repr__.<locals>.<listcomp>r   r   z(<r   z)>)>)r^   r  rD  r   rU   rT   r  )rL   conn_kwargsrQ   rQ   rR   r     s   zConnectionPool.__repr__c                 C   s   | j ddS )z
        Returns:
            The RESP protocol version, or ``None`` if the protocol is not specified,
            in which case the server default will be used.
        r   N)r  r   rk   rQ   rQ   rR   ru     s   zConnectionPool.get_protocolc                 C   s"   d| _ g | _t | _t | _d S )Nr   )_created_connections_available_connectionsrp  _in_use_connectionsr   r   r   rk   rQ   rQ   rR   r    s   zConnectionPool.resetc                 C   sl   | j t kr4| jjdd}|stz| j t kr&|   W | j  d S W | j  d S | j  w d S )N   )r   )r   r   r   r  acquirer%   r  release)rL   acquiredrQ   rQ   rR   	_checkpid  s   #
zConnectionPool._checkpid*)Use get_connection() without args instead5.3.0args_to_warnreasonr`  r1  c              
   O   s   |    | j# z| j }W n ty   |  }Y nw | j| W d   n1 s-w   Y  z8|  z|	 rE| j
du rItdW W |S W W |S  tttfyj   |  |  |	 rftdY W |S w  tyw   | |  w )zGet a connection from the poolNConnection has dataConnection not ready)r  r  r  r  
IndexErrormake_connectionr  addrv   r   rR  r&   r+   r   ry   r  r  rL   command_namerh  options
connectionrQ   rQ   rR   get_connection  s<   
zConnectionPool.get_connectionc                 C   s,   | j }t|dd|dd|dddS )z,Return an encoder based on encoding settingsr   r   r   r   r   F)r   r   r   )r  r   r   )rL   r   rQ   rQ   rR   get_encoder  s   


zConnectionPool.get_encoderri   c                 C   s\   | j | jkr
td|  j d7  _ | jdur%t| jdi | j| j| jS | jdi | jS )zCreate a new connectionzToo many connectionsr   NrQ   )r  r  r(   rR  rO  r  r  r  rk   rQ   rQ   rR   r    s   
zConnectionPool.make_connectionr  c              	   C   s   |    | jC z| j| W n ty    Y W d   dS w | |r5| j| | j	t
| n|  	 W d   dS W d   dS 1 sMw   Y  dS )z(Releases the connection back to the poolN)r  r  r  r   KeyErrorowns_connectionr  rE   r   dispatchr!   ry   rL   r  rQ   rQ   rR   r  (  s$   

"zConnectionPool.releasec                 C   s   |j | j kS rY   )r   r  rQ   rQ   rR   r  @  ru  zConnectionPool.owns_connectionTinuse_connectionsc                 C   s`   |    | j |rt| j| j}n| j}|D ]}|  qW d   dS 1 s)w   Y  dS )z
        Disconnects connections in the pool

        If ``inuse_connections`` is True, disconnect connections that are
        current in use, potentially by other threads. Otherwise only disconnect
        connections that are idle in the pool.
        N)r  r  r   r  r  ry   )rL   r  connectionsr  rQ   rQ   rR   ry   C  s   
"zConnectionPool.disconnectc                 C   r  )z-Close the pool, disconnecting all connectionsNr   rk   rQ   rQ   rR   r  W  r  zConnectionPool.closer   c                 C   s8   | j d|i | jD ]}||_q| jD ]}||_qd S )Nr   )r  r  r  r   r  )rL   r   rQ  rQ   rQ   rR   	set_retry[  s   

zConnectionPool.set_retryr   c                    s   j 9 jD ]!  j fddfdd  j fddfdd qjD ]   q,W d    d S 1 s?w   Y  d S )Nc                      s     dd S r)  )r   r+  r,  rQ   )rQ  r   rQ   rR   r   f  s    z1ConnectionPool.re_auth_callback.<locals>.<lambda>c                    r   rY   _mockr   rk   rQ   rR   r   i  r   c                      r   rY   )r   rQ   )rQ  rQ   rR   r   l  r   c                    r   rY   r	  r   rk   rQ   rR   r   l  r   )r  r  r   r   r  r   r   rQ   )rQ  rL   r   rR   re_auth_callbackb  s   


"zConnectionPool.re_auth_callbackr   c                    s   dS )z
        Dummy functions, needs to be passed as error callback to retry object.
        :param error:
        :return:
        NrQ   r  rQ   rQ   rR   r
  q  s   zConnectionPool._mockrh   rY   )rX   r1  )rX   ri   )r  r1  rX   Nr   )"rT   rU   rV   r-  classmethodr   r  rA   r  r1  r   r   r   r\   r   ru   r  r  r1   r   r   r  r  r  r  r/  ry   r  r,   r  r   r  r)   r
  rQ   rQ   rQ   rR   r  #  s>    2
9

/"
	

c                       sd   e Zd ZdZddeef fdd	Zdd Zdd	 Ze	d
gddddddZ
dd Zdd Z  ZS )BlockingConnectionPoola  
    Thread-safe blocking connection pool::

        >>> from redis.client import Redis
        >>> client = Redis(connection_pool=BlockingConnectionPool())

    It performs the same function as the default
    :py:class:`~redis.ConnectionPool` implementation, in that,
    it maintains a pool of reusable connections that can be shared by
    multiple redis clients (safely across threads if required).

    The difference is that, in the event that a client tries to get a
    connection from the pool when all of connections are in use, rather than
    raising a :py:class:`~redis.ConnectionError` (as the default
    :py:class:`~redis.ConnectionPool` implementation does), it
    makes the client wait ("blocks") for a specified number of seconds until
    a connection becomes available.

    Use ``max_connections`` to increase / decrease the pool size::

        >>> pool = BlockingConnectionPool(max_connections=10)

    Use ``timeout`` to tell it either how many seconds to wait for a connection
    to become available, or to block forever:

        >>> # Block forever.
        >>> pool = BlockingConnectionPool(timeout=None)

        >>> # Raise a ``ConnectionError`` after five seconds if a connection is
        >>> # not available.
        >>> pool = BlockingConnectionPool(timeout=5)
    2      c                    s(   || _ || _t jd||d| d S )N)r  r  rQ   )queue_classr   r:  r\   )rL   r  r   r  r  r  r;  rQ   rR   r\     s   
zBlockingConnectionPool.__init__c                 C   sJ   |  | j| _	 z| jd  W n	 ty   Y nw qg | _t | _d S rY   )	r  r  pool
put_nowaitr   _connectionsr   r   r   rk   rQ   rQ   rR   r    s   zBlockingConnectionPool.resetc                 C   sL   | j durt| jdi | j| j | j}n	| jdi | j}| j| |S )zMake a fresh connection.NrQ   )rR  rO  r  r  r  r  rE   r  rQ   rQ   rR   r    s   
z&BlockingConnectionPool.make_connectionr  r  r  r  Nc              
   O   s   |    d}z| jjd| jd}W n ty   tdw |du r%|  }z/|  z| r3tdW W |S  tt	t
fyT   |  |  | rPtdY W |S w  tya   | |  w )a7  
        Get a connection, blocking for ``self.timeout`` until a connection
        is available from the pool.

        If the connection returned is ``None`` then creates a new connection.
        Because we use a last-in first-out queue, the existing connections
        (having been returned to the pool after the initial ``None`` values
        were added) will be returned before ``None`` values. This means we only
        create new connections when we need to, i.e.: the actual number of
        connections will only increase in response to demand.
        NT)blockr   zNo connection available.r  r  )r  r  r   r   r   r&   r  rv   r   r+   r   ry   r  r  r  rQ   rQ   rR   r     s8   
z%BlockingConnectionPool.get_connectionc                 C   sR   |    | |s|  | jd dS z	| j| W dS  ty(   Y dS w )z)Releases the connection back to the pool.N)r  r  ry   r  r  r   r  rQ   rQ   rR   r    s   
zBlockingConnectionPool.releasec                 C   s    |    | jD ]}|  qdS )z(Disconnects all connections in the pool.N)r  r  ry   r  rQ   rQ   rR   ry     s   

z!BlockingConnectionPool.disconnectrY   )rT   rU   rV   r-  r1  r   r\   r  r  r1   r   r  ry   rN  rQ   rQ   r;  rR   r  z  s"    #4r  )er   r   r   rI   rW  r  r   abcr   	itertoolsr   queuer   r   r   typingr   r   r	   r
   r   r   r   r   urllib.parser   r   r   redis.cacher   r   r   r   r   r   _parsersr   r   r   r   
auth.tokenr   backoffr   credentialsr   r    eventr!   r"   
exceptionsr#   r$   r%   r&   r'   r(   r)   r*   r+   r   r,   utilsr-   r.   r/   r0   r1   r2   r3   r4   r5   r  rF   r_   rd   ra   r]   r   objectr   __annotations__r:   r;   rW   ri   r   r1  rO  r  r  r  r  r   r.  listr  r  r  r  r  rQ   rQ   rQ   rR   <module>   s   
 ( 	,,
3Q    J W ,#	9  Y