U
    ZhC                     @  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   )AutoBackend)SOCKET_OPTIONAsyncNetworkBackend)ConnectionNotAvailableUnsupportedProtocol)OriginProxyRequestResponse)
AsyncEventAsyncShieldCancellationAsyncThreadLock   )AsyncHTTPConnection)AsyncConnectionInterfaceAsyncRequestInterfacec                   @  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 )AsyncPoolRequestr   Nonerequestreturnc                 C  s   || _ d | _t | _d S N)r   
connectionr   _connection_acquired)selfr    r   C/tmp/pip-unpacked-wheel-s37ty00c/httpcore/_async/connection_pool.py__init__   s    zAsyncPoolRequest.__init__zAsyncConnectionInterface | None)r   r   c                 C  s   || _ | j  d S r   )r   r   set)r   r   r   r   r   assign_to_connection   s    z%AsyncPoolRequest.assign_to_connectionr   c                 C  s   d | _ t | _d S r   )r   r   r   r   r   r   r   clear_connection   s    z!AsyncPoolRequest.clear_connectionNfloat | Noner   )timeoutr   c                   s2   | j d kr| jj|dI d H  | j d k	s,t| j S )Nr&   )r   r   waitAssertionError)r   r&   r   r   r   wait_for_connection   s    
z$AsyncPoolRequest.wait_for_connectionboolc                 C  s
   | j d kS r   )r   r#   r   r   r   	is_queued'   s    zAsyncPoolRequest.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AsyncConnectionPoolz5
    A connection pool for making HTTP requests.
    N
   TFr   zssl.SSLContext | NonezProxy | Nonez
int | Noner%   r+   intz
str | NonezAsyncNetworkBackend | 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AsyncConnectionPool.__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   )AsyncSocks5Connection)proxy_origin
proxy_authremote_originr3   r7   r8   r9   r=   s   http)AsyncForwardHTTPConnection)rS   proxy_headersproxy_ssl_contextrU   r7   r=   )AsyncTunnelHTTPConnection)	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%AsyncConnectionPool.create_connectionzlist[AsyncConnectionInterface]r"   c                 C  s
   t | jS )a  
        Return a list of the connections currently in the pool.

        For example:

        ```python
        >>> pool.connections
        [
            <AsyncHTTPConnection ['https://example.com:443', HTTP/1.1, ACTIVE, Request Count: 6]>,
            <AsyncHTTPConnection ['https://example.com:443', HTTP/1.1, IDLE, Request Count: 9]> ,
            <AsyncHTTPConnection ['http://example.com:80', HTTP/1.1, IDLE, Request Count: 1]>,
        ]
        ```
        )listrN   r#   r   r   r   connections   s    zAsyncConnectionPool.connectionsr   r   r   c           
        s  |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 zx| j | 
 }W 5 Q R X | |I dH  |j|d	I dH }z||jI dH }W q tk
r   |  Y qvX qqvW n` tk
rL }	 z@| j | j| | 
 }W 5 Q R X | |I dH  |	dW 5 d}	~	X Y nX t|jtjsbt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_async_requestr   r   r$   BaseExceptionremove
isinstancerg   typingAsyncIterabler)   r   ri   r]   PoolByteStream)
r   r   r[   Ztimeoutsr&   rh   closingr   responseexcr   r   r   rq      sV    
  z(AsyncConnectionPool.handle_async_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     zGAsyncConnectionPool._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    






z3AsyncConnectionPool._assign_requests_to_connections)rx   r   c              	     s.   t   |D ]}| I d H  qW 5 Q R X d S r   )r   aclose)r   rx   r   r   r   r   rp   U  s    z&AsyncConnectionPool._close_connectionsc              	     s6   | j  t| j}g | _W 5 Q R X | |I d H  d S r   )rP   r_   rN   rp   )r   r   r   r   r   r   [  s    
zAsyncConnectionPool.aclosec                   s   | S r   r   r#   r   r   r   
__aenter__c  s    zAsyncConnectionPool.__aenter__ztype[BaseException] | NonezBaseException | Noneztypes.TracebackType | None)exc_type	exc_value	tracebackr   c                   s   |   I d H  d S r   )r   )r   r   r   r   r   r   r   	__aexit__f  s    zAsyncConnectionPool.__aexit__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     z0AsyncConnectionPool.__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AsyncConnectionPool.__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.AsyncIterable[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.AsyncIterator[bytes]r"   c              
   C s\   z | j 2 z3 d H W }|V  q6 W n6 tk
rV } z|  I d H  |d W 5 d }~X Y nX d S r   )r   rr   r   )r   partrz   r   r   r   	__aiter__  s    zPoolByteStream.__aiter__c              	     s~   | j szd| _ t " t| jdr0| j I d H  W 5 Q R X | jj  | jj| j	 | j
 }W 5 Q R X | j|I d H  d S )NTr   )r   r   hasattrr   r   r   rP   rO   rs   r   ro   rp   )r   rx   r   r   r   r     s    
zPoolByteStream.acloseN)r-   r.   r/   r   r   r   r   r   r   r   rw     s   rw   )
__future__r   sslrA   typesru   Z_backends.autor   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      \