U
    Zh;B                     @  s   d dl m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	m
Z
 ddlmZmZ ddlmZmZmZmZ ddlmZmZmZ d	d
lmZ d	dlmZmZ G dd dZG dd deZG dd dZdS )    )annotationsN   )SyncBackend)SOCKET_OPTIONNetworkBackend)ConnectionNotAvailableUnsupportedProtocol)OriginProxyRequestResponse)EventShieldCancellation
ThreadLock   )HTTPConnection)ConnectionInterfaceRequestInterfacec                   @  sZ   e Zd ZdddddZddddd	Zdd
ddZddddddZdd
ddZdS )PoolRequestr   Nonerequestreturnc                 C  s   || _ d | _t | _d S N)r   
connectionr   _connection_acquired)selfr    r   B/tmp/pip-unpacked-wheel-s37ty00c/httpcore/_sync/connection_pool.py__init__   s    zPoolRequest.__init__zConnectionInterface | None)r   r   c                 C  s   || _ | j  d S r   )r   r   set)r   r   r   r   r   assign_to_connection   s    z PoolRequest.assign_to_connectionr   c                 C  s   d | _ t | _d S r   )r   r   r   r   r   r   r   clear_connection   s    zPoolRequest.clear_connectionNfloat | Noner   )timeoutr   c                 C  s,   | j d kr| jj|d | j d k	s&t| j S )Nr&   )r   r   waitAssertionError)r   r&   r   r   r   wait_for_connection   s    
zPoolRequest.wait_for_connectionboolc                 C  s
   | j d kS r   )r   r#   r   r   r   	is_queued'   s    zPoolRequest.is_queued)N)__name__
__module____qualname__r   r!   r$   r*   r,   r   r   r   r   r      s    r   c                   @  s   e Zd ZdZd4ddd	d	d
dddddddddddZdddddZeddddZdddd d!Zddd"d#Z	ddd$d%d&Z
ddd'd(Zd dd)d*Zd5d+d,d-dd.d/d0Zd1dd2d3ZdS )6ConnectionPoolz5
    A connection pool for making HTTP requests.
    N
   TFr   zssl.SSLContext | NonezProxy | Nonez
int | Noner%   r+   intz
str | NonezNetworkBackend | Nonez%typing.Iterable[SOCKET_OPTION] | Noner   )ssl_contextproxymax_connectionsmax_keepalive_connectionskeepalive_expiryhttp1http2retrieslocal_addressudsnetwork_backendsocket_optionsr   c                 C  s   || _ || _|dkrtjn|| _|dkr.tjn|| _t| j| j| _|| _|| _|| _	|| _
|	| _|
| _|dkrvt n|| _|| _g | _g | _t | _dS )a  
        A connection pool for making HTTP requests.

        Parameters:
            ssl_context: An SSL context to use for verifying connections.
                If not specified, the default `httpcore.default_ssl_context()`
                will be used.
            max_connections: The maximum number of concurrent HTTP connections that
                the pool should allow. Any attempt to send a request on a pool that
                would exceed this amount will block until a connection is available.
            max_keepalive_connections: The maximum number of idle HTTP connections
                that will be maintained in the pool.
            keepalive_expiry: The duration in seconds that an idle HTTP connection
                may be maintained for before being expired from the pool.
            http1: A boolean indicating if HTTP/1.1 requests should be supported
                by the connection pool. Defaults to True.
            http2: A boolean indicating if HTTP/2 requests should be supported by
                the connection pool. Defaults to False.
            retries: The maximum number of retries when trying to establish a
                connection.
            local_address: Local address to connect from. Can also be used to connect
                using a particular address family. Using `local_address="0.0.0.0"`
                will connect using an `AF_INET` address (IPv4), while using
                `local_address="::"` will connect using an `AF_INET6` address (IPv6).
            uds: Path to a Unix Domain Socket to use instead of TCP sockets.
            network_backend: A backend instance to use for handling network I/O.
            socket_options: Socket options that have to be included
             in the TCP socket when the connection was established.
        N)_ssl_context_proxysysmaxsize_max_connections_max_keepalive_connectionsmin_keepalive_expiry_http1_http2_retries_local_address_udsr   _network_backend_socket_options_connections	_requestsr   _optional_thread_lock)r   r3   r4   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r   r   r   r   0   s0    , zConnectionPool.__init__r	   r   )originr   c                 C  s   | j d k	r| j jjdkrPddlm} || j jj| j j|| j| j| j	| j
| jdS |jdkrddlm} || j jj| j j| j j|| j| jdS ddlm} || j jj| j j| j j|| j| j| j	| j
| jd		S t|| j| j| j	| j
| j| j| j| j| jd

S )N)s   socks5s   socks5hr   )Socks5Connection)proxy_origin
proxy_authremote_originr3   r7   r8   r9   r=   s   http)ForwardHTTPConnection)rS   proxy_headersproxy_ssl_contextrU   r7   r=   )TunnelHTTPConnection)	rS   rW   rX   rU   r3   r7   r8   r9   r=   )
rQ   r3   r7   r8   r9   r:   r;   r<   r=   r>   )r@   urlschemeZsocks_proxyrR   rQ   authr?   rF   rG   rH   rL   Z
http_proxyrV   headersr3   rY   r   rI   rJ   rK   rM   )r   rQ   rR   rV   rY   r   r   r   create_connection   s^    


z ConnectionPool.create_connectionzlist[ConnectionInterface]r"   c                 C  s
   t | jS )a  
        Return a list of the connections currently in the pool.

        For example:

        ```python
        >>> pool.connections
        [
            <HTTPConnection ['https://example.com:443', HTTP/1.1, ACTIVE, Request Count: 6]>,
            <HTTPConnection ['https://example.com:443', HTTP/1.1, IDLE, Request Count: 9]> ,
            <HTTPConnection ['http://example.com:80', HTTP/1.1, IDLE, Request Count: 1]>,
        ]
        ```
        )listrN   r#   r   r   r   connections   s    zConnectionPool.connectionsr   r   r   c           
      C  sl  |j j }|dkrtd|dkr4td| d|jdi }|dd}| j t|}| j	| W 5 Q R X zf| j | 
 }W 5 Q R X | | |j|d	}z||j}W q tk
r   |  Y qvX qqvW nZ tk
r4 }	 z:| j | j| | 
 }W 5 Q R X | | |	dW 5 d}	~	X Y nX t|jtjsJtt|j|jt|j|| d
|jdS )z
        Send an HTTP request, and return an HTTP response.

        This is the core implementation that is called into by `.request()` or `.stream()`.
         z;Request URL is missing an 'http://' or 'https://' protocol.)httphttpswswssz)Request URL has an unsupported protocol 'z://'.r&   poolNr'   )streampool_requestrf   )statusr]   content
extensions)rZ   r[   decoder   rk   getrP   r   rO   append_assign_requests_to_connections_close_connectionsr*   handle_requestr   r   r$   BaseExceptionremove
isinstancerg   typingIterabler)   r   ri   r]   PoolByteStream)
r   r   r[   Ztimeoutsr&   rh   closingr   responseexcr   r   r   rq      sV    


  zConnectionPool.handle_requestc                   s\  g }t | jD ]r}| r(| j| q| rH| j| || q| rtdd | jD | jkr| j| || qdd | j	D }|D ]}|j
jj  fdd| jD }dd | jD }|r|d }|| qt| j| jk r|  }| j| || q|r|d }| j| || |  }| j| || q|S )aE  
        Manage the state of the connection pool, assigning incoming
        requests to connections as available.

        Called whenever a new request is added or removed from the pool.

        Any closing connections are returned, allowing the I/O for closing
        those connections to be handled seperately.
        c                 S  s   g | ]}|  qS r   is_idle.0r   r   r   r   
<listcomp>&  s     zBConnectionPool._assign_requests_to_connections.<locals>.<listcomp>c                 S  s   g | ]}|  r|qS r   r,   r~   r   r   r   r   r   .  s      c                   s"   g | ]}|  r| r|qS r   )Zcan_handle_requestZis_availabler}   rQ   r   r   r   1  s   
 c                 S  s   g | ]}|  r|qS r   r{   r}   r   r   r   r   6  s     r   )r_   rN   Z	is_closedrs   has_expiredrn   r|   lenrD   rO   r   rZ   rQ   r!   rC   r^   )r   closing_connectionsr   Zqueued_requestsrh   Zavailable_connectionsZidle_connectionsr   r   r   ro     sN    






z.ConnectionPool._assign_requests_to_connections)rx   r   c              	   C  s(   t   |D ]}|  qW 5 Q R X d S r   )r   close)r   rx   r   r   r   r   rp   U  s    z!ConnectionPool._close_connectionsc              	   C  s0   | j  t| j}g | _W 5 Q R X | | d S r   )rP   r_   rN   rp   )r   r   r   r   r   r   [  s    
zConnectionPool.closec                 C  s   | S r   r   r#   r   r   r   	__enter__c  s    zConnectionPool.__enter__ztype[BaseException] | NonezBaseException | Noneztypes.TracebackType | None)exc_type	exc_value	tracebackr   c                 C  s   |    d S r   )r   )r   r   r   r   r   r   r   __exit__f  s    zConnectionPool.__exit__strc           
   	   C  s   | j j}| jN dd | jD }dd | jD }|d}|d}|d}|d}W 5 Q R X d| d| d}d	| d| d
}	d| d| d|	 dS )Nc                 S  s   g | ]}|  qS r   r   r   r   r   r   r   q  s     z+ConnectionPool.__repr__.<locals>.<listcomp>c                 S  s   g | ]}|  qS r   r{   r}   r   r   r   r   r  s    FTz
Requests: z	 active, z queuedzConnections: z idle<z [z | z]>)	__class__r-   rP   rO   rN   count)
r   
class_nameZrequest_is_queuedZconnection_is_idleZnum_active_requestsZnum_queued_requestsZnum_active_connectionsZnum_idle_connectionsZrequests_infoZconnection_infor   r   r   __repr__n  s    


zConnectionPool.__repr__)NNr1   NNTFr   NNNN)NNN)r-   r.   r/   __doc__r   r^   propertyr`   rq   ro   rp   r   r   r   r   r   r   r   r   r0   +   s6               (P5GG   r0   c                   @  s<   e Zd ZdddddddZdd	d
dZdd	ddZdS )rw   ztyping.Iterable[bytes]r   r0   r   )rg   rh   rf   r   c                 C  s   || _ || _|| _d| _d S )NF)_stream_pool_request_pool_closed)r   rg   rh   rf   r   r   r   r     s    zPoolByteStream.__init__ztyping.Iterator[bytes]r"   c              
   c  sL   z| j D ]
}|V  qW n0 tk
rF } z|   |d W 5 d }~X Y nX d S r   )r   rr   r   )r   partrz   r   r   r   __iter__  s    
zPoolByteStream.__iter__c              	   C  sr   | j snd| _ t  t| jdr*| j  W 5 Q R X | jj  | jj| j	 | j
 }W 5 Q R X | j| d S )NTr   )r   r   hasattrr   r   r   rP   rO   rs   r   ro   rp   )r   rx   r   r   r   r     s    
zPoolByteStream.closeN)r-   r.   r/   r   r   r   r   r   r   r   rw     s   rw   )
__future__r   sslrA   typesru   Z_backends.syncr   Z_backends.baser   r   _exceptionsr   r   Z_modelsr	   r
   r   r   Z_synchronizationr   r   r   r   r   
interfacesr   r   r   r0   rw   r   r   r   r   <module>   s      \