o
    rPf                     @   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 d dl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 dd
l m!Z! ddl"m#Z#m$Z$ ddl%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z- ddl.m/Z/ ddl0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6 e2rd dl7Z7dZ8dZ9dZ:dZ;dZ<e= Z>eeeeef  e?d< e2reZ@neZ@G dd dZAG dd dZBG dd dZCG dd deCZDG dd deDZEG dd  d eCZFd!ZGd"d# ZHeIeJeJeHeHeKeIeIeHeJd$
ZLd%d& ZMG d'd( d(ZNG d)d* d*eNZOdS )+    N)abstractmethod)chain)EmptyFull	LifoQueue)time)AnyCallableListOptionalTypeUnion)parse_qsunquoteurlparse   )Encoder_HiredisParser_RESP2Parser_RESP3Parser)	NoBackoff)CredentialProvider"UsernamePasswordCredentialProvider)AuthenticationError$AuthenticationWrongNumberOfArgsErrorChildDeadlockedErrorConnectionError	DataError
RedisErrorResponseErrorTimeoutError)Retry)CRYPTOGRAPHY_AVAILABLEHIREDIS_AVAILABLEHIREDIS_PACK_AVAILABLESSL_AVAILABLE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 rC   Q/var/www/html/humari/django-venv/lib/python3.10/site-packages/redis/connection.pypack:   s   "zHiredisRespSerializer.packN)__name__
__module____qualname__r
   rE   rC   rC   rC   rD   r-   9   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_cutoffr5   )r>   buffer_cutoffr5   rC   rC   rD   __init__L   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/   )r2   r3   r4   r5   r6   	SYM_EMPTYjoinSYM_STARlenSYM_CRLFrL   map
memoryview
SYM_DOLLARr7   )r>   r.   r?   buffrM   arg
arg_lengthrC   rC   rD   rE   P   s<   "




zPythonRespSerializer.packrJ   N)rF   rG   rH   rN   rE   rC   rC   rC   rD   rI   K   s    
rI   c                *   @   s  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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  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ed/d0 Zed1d2 Zed3d4 Zd5d6 Zd7d8 Zd9d: Zd;d< Z d=d> Z!dMd@dAZ"dBdC Z#dNdDdEZ$	dOd?ddFdGdHZ%dIdJ Z&dKdL Z'dS )PAbstractConnectionz0Manages communication to and from a Redis serverr   NFutf-8stricti   zredis-pyr+   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_packerc                 C   s  |s|r|durt dt | _|| _|| _|| _|| _|| _|| _	|| _
|| _|du r/|}|| _|| _|tu r;g }|rB|t || _|sI|rb|du rUtt d| _nt|| _| j| ntt d| _|| _d| _|| _t|||	| _d| _|| _| |
 g | _ 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 integerr+      zprotocol must be either 2 or 3)*r   osgetpidpidr^   rh   ri   rj   rn   r_   rk   r`   ra   rb   SENTINELr7   r    retry_on_errorr!   r   rl   copydeepcopyupdate_supported_errorsrg   next_health_checkrm   r   encoder_sock_socket_read_size
set_parser_connect_callbacksrL   intr:   DEFAULT_RESP_VERSION
ValueErrorr   ro   _construct_command_packer_command_packer)r>   r^   r_   r`   ra   rb   rv   rc   rd   re   parser_classrf   rg   rh   ri   rj   rk   rl   rm   rn   ro   rp   prC   rC   rD   rN      sh   


zAbstractConnection.__init__c                 C   s,   d dd |  D }| jj d| dS )N,c                 S   s   g | ]\}}| d | qS )=rC   ).0kvrC   rC   rD   
<listcomp>   s    z/AbstractConnection.__repr__.<locals>.<listcomp><>)rP   repr_pieces	__class__rF   )r>   	repr_argsrC   rC   rD   __repr__   s   zAbstractConnection.__repr__c                 C      d S rK   rC   r>   rC   rC   rD   r         zAbstractConnection.repr_piecesc                 C   s$   z|    W d S  ty   Y d S w rK   )
disconnect	Exceptionr   rC   rC   rD   __del__   s
   zAbstractConnection.__del__c                 C   s&   |d ur|S t rt S t| j| jjS rK   )r$   r-   rI   rL   r{   r5   )r>   packerrC   rC   rD   r      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   r7   )r>   callbackwmrC   rC   rD   register_connect_callback   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   )r>   r   rC   rC   rD   deregister_connect_callback   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
        )rf   N)r}   _parser)r>   r   rC   rC   rD   r~     s   zAbstractConnection.set_parserc              
      s    j rdS z j fdd fdd}W n tjy"   td ty4 } zt |d}~ww | _ z j	du rC 
  n 	  W n tyU       w dd  jD  _ jD ]}| }|rm|  qbdS )z5Connects to the Redis server if not already connectedNc                      s      S rK   )_connectrC   r   rC   rD   <lambda>  s    z,AbstractConnection.connect.<locals>.<lambda>c                    s
     | S rK   r   )errorr   rC   rD   r     s   
 zTimeout connecting to serverc                 S   s   g | ]}| r|qS rC   rC   )r   refrC   rC   rD   r   ,  s    z.AbstractConnection.connect.<locals>.<listcomp>)r|   rl   call_with_retrysockettimeoutr    OSErrorr   _error_messagerm   
on_connectr   r   r   )r>   socker   r   rC   r   rD   connect  s:   



zAbstractConnection.connectc                 C   r   rK   rC   r   rC   rC   rD   r   2  r   zAbstractConnection._connectc                 C   r   rK   rC   r   rC   rC   rD   _host_error6  r   zAbstractConnection._host_errorc                 C   r   rK   rC   )r>   	exceptionrC   rC   rD   r   :  r   z!AbstractConnection._error_messagec                 C   st  | 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   |  }nq|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 |  | d| j |  }|d| jkr|d| jkrtd| jr| dd| j t|  dkrtdz| jr| ddd| j |   W n	 ty   Y nw z| jr| ddd| j |   W n
 ty   Y nw | jr6| d| j t|  dkr8tddS dS )z=Initialize the connection, authenticate and select a databaseN)r+   2r   defaultr   HELLOAUTHcheck_healthFr   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   r   rn   rk   r_   r   get_credentialsro   r2   r   r~   r   EXCEPTION_CLASSESrR   send_commandread_responser   r'   r   getr   rh   ri   r   rj   r^   )r>   parser	auth_argscred_providerresponseauth_responserC   rC   rD   r   >  s   





zAbstractConnection.on_connectc              	   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|   rr   rs   rt   shutdownr   	SHUT_RDWRr   r:   close)r>   r.   	conn_sockrC   rC   rD   r     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   r'   r   r   r   rC   rC   rD   
_send_ping  s   zAbstractConnection._send_pingc                 C      |    dS )z Function to call when PING failsNr   )r>   r   rC   rC   rD   _ping_failed     zAbstractConnection._ping_failedc                 C   s0   | 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)rg   r   rz   rl   r   r   r   r   rC   rC   rD   r     s   zAbstractConnection.check_healthTc              
   C   s   | j s|   |r|   zt|tr|g}|D ]}| j | qW dS  tjy3   |   t	d t
yg } z)|   t|jdkrNd|jd }}n
|jd }|jd }td| d| dd}~w tyr   |    w )	z2Send an already packed command to the Redis serverzTimeout writing to socketr   UNKNOWNr   Error z while writing to socket. .N)r|   r   r   r2   r3   sendallr   r   r   r    r   rR   r.   r   BaseException)r>   commandr   itemr   errnoerrmsgrC   rC   rD   send_packed_command  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 serverr   Tr   N)r   r   rE   r   )r>   r.   kwargsrC   rC   rD   r     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|   r   r   r   can_readr   r   r   r.   )r>   r   r   
host_errorr   rC   rC   rD   r     s   zAbstractConnection.can_read)disconnect_on_errorpush_requestc             
   C   s   |   }z| jdv rts| jj||d}n| jj|d}W n> tjy2   |r+|   td|  t	yN } z|r?|   t
d| d|j d}~w ty[   |rZ|    w | jrft | j | _t|trpz|~w |S )z0Read the response from a previously sent command)3rq   )disable_decodingr   )r   zTimeout reading from r   z : N)r   ro   r#   r   r   r   r   r   r    r   r   r.   r   rg   r   rz   r2   r   )r>   r   r   r   r   r   r   rC   rC   rD   r     s>   	
z AbstractConnection.read_responsec                 G   s   | j j| S )r0   )r   rE   )r>   r.   rC   rC   rD   r9     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   )	rL   r   rE   rR   r2   rU   r7   rO   rP   )	r>   commandsr?   piecesbuffer_lengthrM   cmdchunkchunklenrC   rC   rD   pack_commands!  s.   

z AbstractConnection.pack_commandsT)r   )F)(rF   rG   rH   __doc__ru   r,   r&   r   r   r3   floatboolr   r   r	   r   rN   r   r   r   r   r   r   r   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r9   r   rC   rC   rC   rD   r[   ~   s    	


Y
#


Z

.r[   c                       sL   e Zd ZdZ					d fdd	Z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 NrC   )hostr   portsocket_keepalivesocket_keepalive_optionssocket_typesuperrN   )r>   r   r   r   r   r   r   r   rC   rD   rN   C  s   	

zConnection.__init__c                 C   s6   d| j fd| jfd| jfg}| jr|d| jf |S )Nr   r   r^   rh   )r   r   r^   rh   r7   r>   r   rC   rC   rD   r   S  s   zConnection.repr_piecesc                 C   s  d}t | j| j| jt jD ]k}|\}}}}}d}zDt  |||}|t jt jd | j	rH|t j
t jd | j D ]\}	}
|t j|	|
 q;|| j || || j |W   S  tyy } z|}|duro|  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   getaddrinfor   r   r   SOCK_STREAM
setsockoptIPPROTO_TCPTCP_NODELAYr   
SOL_SOCKETSO_KEEPALIVEr   items
settimeoutra   r   r`   r   r   )r>   errresfamilysocktyper   	canonnamesocket_addressr   r   r   r@   rC   rC   rD   r   Y  s4   

zConnection._connectc                 C   s   | j  d| j S )N:)r   r   r   rC   rC   rD   r     s   zConnection._host_errorc                 C   s   |   }t|jdkr*zd| d|jd  dW S  ty)   d|jd   Y S w zd|jd  d| d	|jd  dW S  tyN   d|jd   Y S w )
Nr   zError connecting to z.                         r   r   zConnection Error: r   z connecting to . )r   rR   r.   AttributeErrorr>   r   r   rC   rC   rD   r     s&   
zConnection._error_message)r   r   FNr   
rF   rG   rH   r   rN   r   r   r   r   __classcell__rC   rC   r   rD   r   @  s    )r   c                       sJ   e Zd ZdZ														d	 fdd	Z f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requiredFc                    s   t std|| _|| _|du rtj}nt|tr1tjtjtj	d}||vr-t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). 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: rC   )r%   r   keyfilecertfilessl	CERT_NONEr2   r3   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   rN   )r>   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   rC   rD   rN     s:   (
zSSLConnection.__init__c           
         s  t   }t }| j|_| j|_| js| jr"|j	| j| j| j
d | jdus1| jdus1| jdur<|j| j| j| jd | jdurE| j|_| jrN|| j |j|| jd}| jdu rctdu rctd| jrm| jrmt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 Wrap the socket with SSL support)r  r  r_   N)cafilecapathcadata)server_hostnameTFzcryptography is not installed.zKEither an OCSP staple or pure OCSP connection must be validated - not both.r   r   )ocsp_staple_verifier)OCSPVerifierzocsp validation error).r   r   r  create_default_contextr   r  verify_moder  r  load_cert_chainr!  r  r  r  load_verify_locationsr&  minimum_versionr'  set_cipherswrap_socketr   r"  r"   r   r#  OpenSSLocspr5  r$  SSLContextSSLv23_METHODuse_certificate_fileuse_privatekey_fileset_ocsp_client_callbackr%  r   r   request_ocspr   r   do_handshaker   r6  is_validr   )
r>   r   contextsslsockr>  r5  
staple_ctxconr6  or   rC   rD   r     sf   





zSSLConnection._connect)NNr  NNFNNFFNNNN)rF   rG   rH   r   rN   r   r  rC   rC   r   rD   r    s$    Hr  c                       sB   e Zd ZdZd fdd	Z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 r   )pathr`   r   rN   )r>   rP  r`   r   r   rC   rD   rN   4  s   z#UnixDomainSocketConnection.__init__c                 C   s.   d| j fd| jfg}| jr|d| jf |S )NrP  r^   rh   )rP  r^   rh   r7   r   rC   rC   rD   r   9  s   z&UnixDomainSocketConnection.repr_piecesc                 C   s8   t  t jt j}|| j || j || j |S )z&Create a Unix domain socket connection)r   AF_UNIXr   r  ra   r   rP  r`   )r>   r   rC   rC   rD   r   ?  s
   z#UnixDomainSocketConnection._connectc                 C   s   | j S rK   )rP  r   rC   rC   rD   r   G  s   z&UnixDomainSocketConnection._host_errorc                 C   sR   |   }t|jdkrd| d|jd  dS d|jd  d| d|jd  dS )Nr   z!Error connecting to unix socket: r  r   r   r   z connecting to unix socket: )r   rR   r.   r  rC   rC   rD   r   J  s   z)UnixDomainSocketConnection._error_message)rO  Nr  rC   rC   r   rD   rN  1  s    rN  )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 )NrO  F)r2   r3   upperFALSE_STRINGSr   )rA   rC   rC   rD   to_bool\  s
   rY  )
r^   r`   ra   r   rb   rv   max_connectionsrg   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.rk   r_   unixrP  connection_classr   r   r^   /rO  rediss)
startswithr   r   r   queryr  rR   r   URL_QUERY_ARGUMENT_PARSERSr   r:   rk   r_   schemerP  rN  hostnamer   r   replacer  r  )urlr   namerA   r   rC   rC   rD   	parse_urlr  sZ   


rg  c                   @   s   e Zd ZdZedd Zedfdee fddZ	de
e
ffd	d
Zd&ddZd&ddZde
ddfddZdefddZd'ddZd(ddZdddefddZd)deddfddZd&d d!Zd*d$d%ZdS )+ConnectionPoola  
    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.

    Any additional keyword arguments are passed to the constructor of
    ``connection_class``.
    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\  NrC   )rg  update)clsre  r   url_optionsrC   rC   rD   from_url  s
   )
zConnectionPool.from_urlNrZ  c                 K   sJ   |pd}t |tr|dk rtd|| _|| _|| _t | _| 	  d S )Nl        r   z,"max_connections" must be a positive integer)
r2   r   r   r\  connection_kwargsrZ  	threadingLock
_fork_lockreset)r>   r\  rZ  rm  rC   rC   rD   rN     s   

zConnectionPool.__init__rJ   c                 C   s(   t | j dt| jdi | j dS )Nr   r   rC   )typerF   reprr\  rm  r   rC   rC   rD   r     s   zConnectionPool.__repr__c                 C   s,   t  | _d| _g | _t | _t | _	d S )Nr   )
rn  ro  _lock_created_connections_available_connectionsset_in_use_connectionsrr   rs   rt   r   rC   rC   rD   rq  	  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   )rt   rr   rs   rp  acquirer   rq  release)r>   acquiredrC   rC   rD   	_checkpid  s   #
zConnectionPool._checkpidcommand_namer   c              	   O   s   |    | j# z| j }W n ty   |  }Y nw | j| W d   n1 s-w   Y  z.|  z|	 r@t
dW W |S  t
tfy`   |  |  |	 r\t
dY W |S w  tym   | |  w )zGet a connection from the poolNConnection has dataConnection not ready)r}  rt  rv  pop
IndexErrormake_connectionrx  addr   r   r   r   r   r   r{  r>   r~  keysoptions
connectionrC   rC   rD   get_connectionI  s8   
zConnectionPool.get_connectionc                 C   s,   | j }t|dd|dd|dddS )z,Return an encoder based on encoding settingsrc   r\   rd   r]   re   F)rc   rd   re   )rm  r   r   )r>   r   rC   rC   rD   get_encoderj  s   


zConnectionPool.get_encoderc                 C   s4   | j | jkr
td|  j d7  _ | jdi | jS )zCreate a new connectionzToo many connectionsr   NrC   )ru  rZ  r   r\  rm  r   rC   rC   rD   r  s  s   zConnectionPool.make_connectionr  c              	   C   s   |    | j; z| j| W n	 ty   Y nw | |r&| j| n|  jd8  _|	  	 W d   dS W d   dS 1 sEw   Y  dS )z(Releases the connection back to the poolr   N)
r}  rt  rx  r   KeyErrorowns_connectionrv  r7   ru  r   r>   r  rC   rC   rD   r{  z  s   
	"zConnectionPool.releasec                 C   s   |j | j kS rK   )rt   r  rC   rC   rD   r    s   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}  rt  r   rv  rx  r   )r>   r  connectionsr  rC   rC   rD   r     s   
"zConnectionPool.disconnectc                 C   r   )z-Close the pool, disconnecting all connectionsNr   r   rC   rC   rD   r     r   zConnectionPool.closerl   r!   c                 C   s8   | j d|i | jD ]}||_q| jD ]}||_qd S )Nrl   )rm  ri  rv  rl   rx  )r>   rl   connrC   rC   rD   	set_retry  s   

zConnectionPool.set_retryrZ   )rJ   r   )r  r   rJ   Nr   )rl   r!   rJ   N)rF   rG   rH   r   classmethodrl  r   r   r   rN   r3   r   rq  r}  r  r   r  r  r{  r  r   r   r   r  rC   rC   rC   rD   rh    s(    
2


/!
	

rh  c                       sR   e Zd ZdZddeef fdd	Zdd Zdd	 Zd
d Z	dd Z
dd Z  ZS )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\  rZ  rC   )queue_classr   r   rN   )r>   rZ  r   r\  r  rm  r   rC   rD   rN     s   
zBlockingConnectionPool.__init__c                 C   sJ   |  | j| _	 z| jd  W n	 ty   Y nw qg | _t | _d S rK   )	r  rZ  pool
put_nowaitr   _connectionsrr   rs   rt   r   rC   rC   rD   rq    s   zBlockingConnectionPool.resetc                 C   s"   | j di | j}| j| |S )zMake a fresh connection.NrC   )r\  rm  r  r7   r  rC   rC   rD   r    s   z&BlockingConnectionPool.make_connectionc              	   O   s   |    d}z| jjd| jd}W n ty   tdw |du r%|  }z.|  z| r3tdW W |S  tt	fyS   |
  |  | rOtdY W |S w  ty`   | |  w )a7  
        Get a connection, blocking for ``self.timeout`` until a connection
        is available from the pool.

        If the connection returned is ``None`` then creates a new connection.
        Because we use a last-in first-out queue, the existing connections
        (having been returned to the pool after the initial ``None`` values
        were added) will be returned before ``None`` values. This means we only
        create new connections when we need to, i.e.: the actual number of
        connections will only increase in response to demand.
        NT)blockr   zNo connection available.r  r  )r}  r  r   r   r   r   r  r   r   r   r   r   r{  r  rC   rC   rD   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  r   r  r  r   r  rC   rC   rD   r{  6  s   
zBlockingConnectionPool.releasec                 C   s    |    | jD ]}|  qdS )z(Disconnects all connections in the pool.N)r}  r  r   r  rC   rC   rD   r   K  s   

z!BlockingConnectionPool.disconnect)rF   rG   rH   r   r   r   rN   rq  r  r  r{  r   r  rC   rC   r   rD   r    s    #4r  )Prw   rr   r   r  r;   rn  r   abcr   	itertoolsr   queuer   r   r   r   typingr   r	   r
   r   r   r   urllib.parser   r   r   _parsersr   r   r   r   backoffr   credentialsr   r   
exceptionsr   r   r   r   r   r   r   r    rl   r!   utilsr"   r#   r$   r%   r&   r'   r8   rQ   rV   rS   rO   r   objectru   __annotations__r,   r-   rI   r[   r   r  rN  rX  rY  r   r   listra  rg  rh  r  rC   rC   rC   rD   <module>   sv   
  (
 	3   E[ (	9  	