U
    j7g                     @   s  d 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m	Z	m
Z
mZ ddlmZ ddlmZ ejdk rddlZejej_ddddde
e e	e
e  e	e e	e e	ej ejd	d
dZdejeeeeef   ee	e
e  ejdddZde
e eee dddZdS )zBase implementation.    N)ListOptionalSequenceUnion   )
_staggered)AddrInfoType)         )local_addr_infoshappy_eyeballs_delay
interleaveloop)
addr_infosr   r   r   r   returnc             
      s  |  st   t| dk}|dk	r0|dkr0d}|rB|sBt| |} d}g |dksV|r| D ]@}zt |I dH }W  qW qZ ttfk
r   Y qZY qZX qZn*t fdd| D |I dH \}}}|dkrdd D }	z|	d }
t|	dkr|
nt	|
t
fdd|	D r |
d	d
dd |	D }t|
trp|
jt
fdd|	D rt|n(t|
trt
dd |	D rt|t|W 5 d}	dX |S )aM  
    Connect to a TCP server.

    Create a socket connection to a specified destination.  The
    destination is specified as a list of AddrInfoType tuples as
    returned from getaddrinfo().

    The arguments are, in order:

    * ``family``: the address family, e.g. ``socket.AF_INET`` or
        ``socket.AF_INET6``.
    * ``type``: the socket type, e.g. ``socket.SOCK_STREAM`` or
        ``socket.SOCK_DGRAM``.
    * ``proto``: the protocol, e.g. ``socket.IPPROTO_TCP`` or
        ``socket.IPPROTO_UDP``.
    * ``canonname``: the canonical name of the address, e.g.
        ``"www.python.org"``.
    * ``sockaddr``: the socket address

    This method is a coroutine which will try to establish the connection
    in the background. When successful, the coroutine returns a
    socket.

    The expected use case is to use this method in conjunction with
    loop.create_connection() to establish a connection to a server::

            socket = await start_connection(addr_infos)
            transport, protocol = await loop.create_connection(
                MyProtocol, sock=socket, ...)
    r   Nc                 3   s    | ]}t t |V  qd S N)	functoolspartial_connect_sock).0addrinfo)current_loop
exceptionsr    9/tmp/pip-unpacked-wheel-gwo2f_cs/aiohappyeyeballs/impl.py	<genexpr>Z   s       z#start_connection.<locals>.<genexpr>c                 S   s   g | ]}|D ]}|qqS r   r   )r   subexcr   r   r   
<listcomp>d   s       z$start_connection.<locals>.<listcomp>r   c                 3   s   | ]}t | kV  qd S r   strr   r   )modelr   r   r   l   s     zMultiple exceptions: {}z, c                 s   s   | ]}t |V  qd S r   r    r"   r   r   r   r   q   s     c                 3   s"   | ]}t |to|j kV  qd S r   )
isinstanceOSErrorerrnor"   )first_errnor   r   r   w   s   c                 s   s   | ]}t |tV  qd S r   )r$   RuntimeErrorr"   r   r   r   r   |   s    )asyncioZget_running_looplen_interleave_addrinfosr   r(   r%   r   Zstaggered_racer!   allformatjoinr$   r&   )r   r   r   r   r   Zsingle_addr_infosockr   _Zall_exceptionsZfirst_exceptionmsgr   )r   r   r'   r   r#   r   start_connection   sj    &
   





r2   )r   r   	addr_infor   r   c                    sz  g }| | |\}}}}}	d}
zHztj|||d}
|
d |dk	r|D ]|\}}}}}||krdqLz|
| W  qW qL tk
r } z0d|d|j  }t|j|}| | W 5 d}~X Y qLX qL|r| ntd|d| 	|
|	I dH  |
W W jS  t
tfk
rH } z"| | |
dk	r6|
   W 5 d}~X Y n    |
dk	r`|
   Y nX W 5 d }}X dS )z$Create, bind and connect one socket.N)familytypeprotoFz*error while attempting to bind on address z: z&no matching local address with family=z found)appendsocketsetblockingbindr%   strerrorlowerr&   popZsock_connectr(   close)r   r   r3   r   Zmy_exceptionsr4   type_r6   r0   addressr/   Zlfamilyladdrr   r1   r   r   r   r      sD    








r   )	addrinfosfirst_address_family_countr   c                 C   s   t  }| D ]*}|d }||kr(g ||< || | qt| }g }|dkr|||d d|d   |d d|d = |dd tjtj	| D  |S )z-Interleave list of addrinfo tuples by family.r   r   Nc                 s   s   | ]}|d k	r|V  qd S r   r   )r   ar   r   r   r      s   z(_interleave_addrinfos.<locals>.<genexpr>)
collectionsOrderedDictr7   listvaluesextend	itertoolschainfrom_iterablezip_longest)rB   rC   Zaddrinfos_by_familyaddrr4   Zaddrinfos_listsZ	reorderedr   r   r   r+      s     
r+   )N)r   )__doc__r)   rE   r   rJ   r8   systypingr   r   r   r    r   typesr   version_infoZasyncio.futuresTimeoutErrorZfuturesfloatintZAbstractEventLoopr2   r%   r(   r   r+   r   r   r   r   <module>   sL   


v 
3  