U
    j7g.4                     @   s   d Z ddlmZ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 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 dd
lmZ ddlmZ ddlmZmZmZm Z m!Z! G dd dZ"dS )zQ
Main API client asynchronous handler for fetching data from the IPinfo service.
    )IPv4AddressIPv6AddressN   )APIError)DefaultCache)Details)RequestQuotaExceededErrorTimeoutExceededError)API_URLBATCH_MAX_SIZECACHE_MAXSIZE	CACHE_TTLREQUEST_TIMEOUT_DEFAULTBATCH_REQ_TIMEOUT_DEFAULT	cache_key)handler_utils)is_bogon)
continents	countriescountries_currencieseu_countriescountries_flagsc                   @   s`   e Zd ZdZdddZdd Zdd Zdd	d
ZdeddfddZ	dd Z
dd ZdddZdS )AsyncHandlerz
    Allows client to request data for specified IP address asynchronously.
    Instantiates and maintains access to cache.
    Nc                 K   s   || _ |dpt| _|dp"t| _|dp2t| _|dpBt| _|dpRt| _|di | _d| jkrxt| jd< d| _	d	|kr|d	 | _
n8|d
i }d|krt|d< d|krt|d< tf || _
|dd| _dS )zi
        Initialize the Handler object with country name list and the
        cache initialized.
        r   r   r   r   Z	continentrequest_optionstimeoutNcachecache_optionsmaxsizeZttlheaders)access_tokengetr   r   r   r   r   r   r   httpsessr   r   r   r   r   )selfr   kwargsr    r$   8/tmp/pip-unpacked-wheel-bv8pilsi/ipinfo/handler_async.py__init__*   s(    

zAsyncHandler.__init__c                    s   |   I dH  dS )z
        Initializes internal aiohttp connection pool.

        This isn't _required_, as the pool is initialized lazily when needed.
        But in case you require non-lazy initialization, you may await this.

        This is idempotent.
        N)_ensure_aiohttp_readyr"   r$   r$   r%   initX   s    	zAsyncHandler.initc                    s    | j r| j  I dH  d| _ dS )z
        Deinitialize the async handler.

        This is required in case you need to let go of the memory/state
        associated with the async handler in a long-running process.

        This is idempotent.
        N)r!   closer(   r$   r$   r%   deinitc   s    	zAsyncHandler.deinitc              
      sx  |    t|tst|tr"|j}|r@t|r@|dd}t|S z| jt| }t|W S  t	k
rl   Y nX t
}|r|d| 7 }t| j| j}i }|dk	r||d< | jj|fd|i|4 I dH r}|jdkrt |jdkr&|j}	|jd	}
|
d
kr| I dH }nd| i}t|	|| I dH }W 5 Q I dH R X t|| j| j| j| j| j || jt|< t|S )z9Get details for specified IP address as a Details object.Tipbogon/Nr   r     i  zContent-Typeapplication/jsonerror)r'   
isinstancer   r   explodedr   r   r   r   KeyErrorr
   r   get_headersr   r   r!   r    statusr   jsontextr   format_detailsr   r   r   r   r   )r"   
ip_addressr   detailscached_ipaddrurlr   Zreq_optsrespZ
error_codecontent_typeZerror_responser$   r$   r%   
getDetailsp   sT     

"


zAsyncHandler.getDetailsTc              
      s      dkrt i g |D ]X}t|ts8t|tr>|j}zjt| }||< W q  tk
rv   	| Y q X q sS |dk	rt

 }td tjjdd<  fddtdt D }	zxtj|	|tjdI dH \}
}|s
W S |D ]6}z|  |I dH  W n tjk
r@   Y nX qtt W S  tk
r } zt| W Y S d}~X Y nX S )	a  
        Get details for a batch of IP addresses at once.

        There is no specified limit to the number of IPs this function can
        accept; it can handle as much as the user can fit in RAM (along with
        all of the response data, which is at least a magnitude larger than the
        input list).

        The input list is broken up into batches to abide by API requirements.
        The batch size can be adjusted with `batch_size` but is clipped to
        `BATCH_MAX_SIZE`.
        Defaults to `BATCH_MAX_SIZE`.

        For each batch, `timeout_per_batch` indicates the maximum seconds to
        spend waiting for the HTTP request to complete. If any batch fails with
        this timeout, the whole operation fails.
        Defaults to `BATCH_REQ_TIMEOUT_DEFAULT` seconds.

        `timeout_total` is a seconds-denominated hard-timeout for the time
        spent in HTTP operations; regardless of whether all batches have
        succeeded so far, if `timeout_total` is reached, the whole operation
        will fail by raising `TimeoutExceededError`.
        Defaults to being turned off.

        `raise_on_fail`, if turned off, will return any result retrieved so far
        rather than raise an exception when errors occur, including timeout and
        quota errors.
        Defaults to on.

        The concurrency level is currently unadjustable; coroutines will be
        created and consumed for all batches at once.
        N/batchr1   content-typec              
      s,   g | ]$} ||   qS r$   )_do_batch_req).0i
batch_sizer   lookup_addressesraise_on_failresultr"   timeout_per_batchr>   r$   r%   
<listcomp>   s   	z0AsyncHandler.getBatchDetails.<locals>.<listcomp>r   )r   Zreturn_when)r'   r   r3   r   r   r4   r   r   r5   appendtimer
   r   r6   r   r   rangelenasynciowaitZFIRST_EXCEPTIONcancelZCancelledErrorreturn_or_failr	   	Exception)r"   ip_addressesrH   rL   Ztimeout_totalrJ   r;   r=   
start_timereqs_pendingcoer$   rG   r%   getBatchDetails   s`    ( 	
  $zAsyncHandler.getBatchDetailsc              
      s  z$| j j|t|||dI dH }W n4 tk
rX } zt||d W Y S d}~X Y nX z|jdkrlt |	  W n4 tk
r } zt||d W Y S d}~X Y nX | I dH }	|	
 D ]>\}
}t|trt|| j| j| j| j| j || jt|
< q||	 dS )zV
        Coroutine which will do the actual POST request for getBatchDetails.
        )datar   r   Nr0   )r!   postr8   dumpsrV   r   rU   r7   r   raise_for_statusitemsr3   dictr:   r   r   r   r   r   r   r   update)r"   chunkr>   r   rL   rJ   rK   r?   r]   Z	json_respr;   r<   r$   r$   r%   rD   !  s8    $
$
zAsyncHandler._do_batch_reqc                 C   s.   | j r
dS tj| jd d}tj|d| _ dS )z.Ensures aiohttp internal state is initialized.Nr   )total)r   )r!   aiohttpZClientTimeoutr   ClientSession)r"   r   r$   r$   r%   r'   K  s    z"AsyncHandler._ensure_aiohttp_readyc              
     sT  |d krt }i g }|D ]z}t|ts0t|tr6|j}|rXt|rX|dd}t|V  qzjt| }||< W q t	k
r   |
| Y qX q|s V  td tjj d d<  fdd}tdt||D ]j}	||	|	|  }
||
I d H   D ]>\}}t|tr@t|jjjjj ||fV  qqd S )	NTr,   rB   r1   rC   c              
      s|   t j d4 I d H X}|j| dI d H }|  | I d H }| D ]\}}|jt|< ||< qHW 5 Q I d H R X d S )N)r   )r8   )rh   ri   r`   rb   r8   rc   r   r   )batchsessionresponseZjson_responser;   r<   r   resultsr"   r>   r$   r%   process_batchu  s    z7AsyncHandler.getBatchDetailsIter.<locals>.process_batchr   )r   r3   r   r   r4   r   r   r   r   r5   rN   rc   r
   r   r6   r   r   rP   rQ   rd   r:   r   r   r   r   r   )r"   rW   rH   rJ   rI   r;   r<   r=   ro   rF   rj   r$   rm   r%   getBatchDetailsIterS  sL     

	z AsyncHandler.getBatchDetailsIter)N)NN)NT)__name__
__module____qualname____doc__r&   r)   r+   rA   r   r^   rD   r'   rp   r$   r$   r$   r%   r   $   s   
.
=
w*  r   )#rt   	ipaddressr   r   rR   r8   rO   rh   r2   r   Zcache.defaultr   r<   r   
exceptionsr   r	   r   r
   r   r   r   r   r   r    r.   r   r_   r   r   r   r   r   r   r$   r$   r$   r%   <module>   s   $		