ó
O'—^c           @  sÔ   d  Z  d d l m 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 d e f d	 „  ƒ  YZ d
 e f d „  ƒ  YZ d e f d „  ƒ  YZ d e f d „  ƒ  YZ d e f d „  ƒ  YZ d S(   u'   
Provides various throttling policies.
iÿÿÿÿ(   t   unicode_literalsN(   t   cache(   t   ImproperlyConfigured(   t   is_authenticated(   t   api_settingst   BaseThrottlec           B  s)   e  Z d  Z d „  Z d „  Z d „  Z RS(   u&   
    Rate throttling of requests.
    c         C  s   t  d ƒ ‚ d S(   uT   
        Return `True` if the request should be allowed, `False` otherwise.
        u#   .allow_request() must be overriddenN(   t   NotImplementedError(   t   selft   requestt   view(    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyt   allow_request   s    c         C  s¥   | j  j d ƒ } | j  j d ƒ } t j } | d k	 rˆ | d k sQ | d k rU | S| j d ƒ } | t | t | ƒ ƒ } | j ƒ  S| r¡ d j	 | j ƒ  ƒ S| S(   uå   
        Identify the machine making the request by parsing HTTP_X_FORWARDED_FOR
        if present and number of proxies is > 0. If not use all of
        HTTP_X_FORWARDED_FOR if it is available, if not use REMOTE_ADDR.
        u   HTTP_X_FORWARDED_FORu   REMOTE_ADDRi    u   ,u    N(
   t   METAt   getR   t   NUM_PROXIESt   Nonet   splitt   mint   lent   stript   join(   R   R   t   xfft   remote_addrt   num_proxiest   addrst   client_addr(    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyt	   get_ident   s    	
c         C  s   d S(   um   
        Optionally, return a recommended number of seconds to wait before
        the next request.
        N(   R   (   R   (    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyt   wait-   s    (   t   __name__t
   __module__t   __doc__R
   R   R   (    (    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyR      s   		t   SimpleRateThrottlec           B  sz   e  Z d  Z e Z e j Z d Z d
 Z	 e
 j Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d	 „  Z RS(   u¡  
    A simple cache implementation, that only requires `.get_cache_key()`
    to be overridden.

    The rate (requests / seconds) is set by a `throttle` attribute on the View
    class.  The attribute is a string of the form 'number_of_requests/period'.

    Period should be one of: ('s', 'sec', 'm', 'min', 'h', 'hour', 'd', 'day')

    Previous request information used for throttling is stored in the cache.
    u   throttle_%(scope)s_%(ident)sc         C  sF   t  |  d d  ƒ s$ |  j ƒ  |  _ n  |  j |  j ƒ \ |  _ |  _ d  S(   Nu   rate(   t   getattrR   t   get_ratet   ratet
   parse_ratet   num_requestst   duration(   R   (    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyt   __init__G   s    c         C  s   t  d ƒ ‚ d S(   u³   
        Should return a unique cache-key which can be used for throttling.
        Must be overridden.

        May return `None` if the request should not be throttled.
        u#   .get_cache_key() must be overriddenN(   R   (   R   R   R	   (    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyt   get_cache_keyL   s    c         C  st   t  |  d d ƒ s1 d |  j j } t | ƒ ‚ n  y |  j |  j SWn* t k
 ro d |  j } t | ƒ ‚ n Xd S(   uR   
        Determine the string representation of the allowed request rate.
        u   scopeu9   You must set either `.scope` or `.rate` for '%s' throttleu+   No default throttle rate set for '%s' scopeN(   R   R   t	   __class__R   R   t   THROTTLE_RATESt   scopet   KeyError(   R   t   msg(    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyR    U   s    c         C  se   | d k r d S| j d ƒ \ } } t | ƒ } i d d 6d d 6d d 6d d	 6| d
 } | | f S(   u‰   
        Given the request rate string, return a two tuple of:
        <allowed number of requests>, <period of time in seconds>
        u   /i   u   si<   u   mi  u   hi€Q u   di    N(   NN(   R   R   t   int(   R   R!   t   numt   periodR#   R$   (    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyR"   d   s    *c         C  sË   |  j  d k r t S|  j | | ƒ |  _ |  j d k r; t S|  j j |  j g  ƒ |  _ |  j ƒ  |  _	 x7 |  j rž |  j d |  j	 |  j
 k rž |  j j ƒ  qh Wt |  j ƒ |  j k rÁ |  j ƒ  S|  j ƒ  S(   u«   
        Implement the check to see if the request should be throttled.

        On success calls `throttle_success`.
        On failure calls `throttle_failure`.
        iÿÿÿÿN(   R!   R   t   TrueR&   t   keyR   R   t   historyt   timert   nowR$   t   popR   R#   t   throttle_failuret   throttle_success(   R   R   R	   (    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyR
   p   s    )
c         C  s9   |  j  j d |  j ƒ |  j j |  j |  j  |  j ƒ t S(   ud   
        Inserts the current request's timestamp along with the key
        into the cache.
        i    (   R1   t   insertR3   R   t   setR0   R$   R/   (   R   (    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyR6   ‰   s    c         C  s   t  S(   uP   
        Called when a request to the API has failed due to throttling.
        (   t   False(   R   (    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyR5   ’   s    c         C  sh   |  j  r' |  j |  j |  j  d } n	 |  j } |  j t |  j  ƒ d } | d k rZ d S| t | ƒ S(   uG   
        Returns the recommended next request time in seconds.
        iÿÿÿÿi   i    N(   R1   R$   R3   R#   R   R   t   float(   R   t   remaining_durationt   available_requests(    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyR   ˜   s    		N(   R   R   R   t   default_cacheR   t   timeR2   t   cache_formatR   R)   R   t   DEFAULT_THROTTLE_RATESR(   R%   R&   R    R"   R
   R6   R5   R   (    (    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyR   5   s   											t   AnonRateThrottlec           B  s   e  Z d  Z d Z d „  Z RS(   u–   
    Limits the rate of API calls that may be made by a anonymous users.

    The IP address of the request will be used as the unique cache key.
    u   anonc         C  s8   t  | j ƒ r d  S|  j i |  j d 6|  j | ƒ d 6S(   Nu   scopeu   ident(   R   t   userR   R?   R)   R   (   R   R   R	   (    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyR&   °   s
    	
(   R   R   R   R)   R&   (    (    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyRA   ¨   s   t   UserRateThrottlec           B  s   e  Z d  Z d Z d „  Z RS(   uç   
    Limits the rate of API calls that may be made by a given user.

    The user id will be used as a unique cache key if the user is
    authenticated.  For anonymous requests, the IP address of the request will
    be used.
    u   userc         C  sI   t  | j ƒ r | j j } n |  j | ƒ } |  j i |  j d 6| d 6S(   Nu   scopeu   ident(   R   RB   t   pkR   R?   R)   (   R   R   R	   t   ident(    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyR&   Ä   s    	
(   R   R   R   R)   R&   (    (    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyRC   º   s   t   ScopedRateThrottlec           B  s/   e  Z d  Z d Z d „  Z d „  Z d „  Z RS(   u,  
    Limits the rate of API calls by different amounts for various parts of
    the API.  Any view that has the `throttle_scope` property set will be
    throttled.  The unique cache key will be generated by concatenating the
    user id of the request, and the scope of the view being accessed.
    u   throttle_scopec         C  s   d  S(   N(    (   R   (    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyR%   Ù   s    c         C  sk   t  | |  j d  ƒ |  _ |  j s% t S|  j ƒ  |  _ |  j |  j ƒ \ |  _ |  _	 t
 t |  ƒ j | | ƒ S(   N(   R   t
   scope_attrR   R)   R/   R    R!   R"   R#   R$   t   superRF   R
   (   R   R   R	   (    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyR
   Þ   s    	c         C  sI   t  | j ƒ r | j j } n |  j | ƒ } |  j i |  j d 6| d 6S(   uØ   
        If `view.throttle_scope` is not set, don't apply this throttle.

        Otherwise generate the unique cache key by concatenating the user id
        with the '.throttle_scope` property of the view.
        u   scopeu   ident(   R   RB   RD   R   R?   R)   (   R   R   R	   RE   (    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyR&   î   s    	
(   R   R   R   RG   R%   R
   R&   (    (    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyRF   Ð   s
   		(   R   t
   __future__R    R>   t   django.core.cacheR   R=   t   django.core.exceptionsR   t   rest_framework.compatR   t   rest_framework.settingsR   t   objectR   R   RA   RC   RF   (    (    (    s;   /tmp/pip-unpacked-wheel-62FVgP/rest_framework/throttling.pyt   <module>   s   &s