o
    j:                     @  sb  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	 d dl
mZmZmZ d dl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 erfd dlm Z m!Z! ej"dddG dd dZ#ej"dddG dd dZ$ej"dddG dd de$Z%ej"dddG dd de$Z&ej"dddG dd de$Z'dS )    )annotationsN)wraps)TracebackType)TYPE_CHECKINGcastoverload)request)Response)RateLimitItem
parse_many   )CallableIterableIteratorPRSelfSequence)get_qualified_name)LimiterRequestLimitT)equnsafe_hashc                   @  s   e Zd ZU dZded< ded< ded< dZd	ed
< dZded< dZded< dZded< dZ	ded< dZ
ded< dZded< dZded< dZd	ed< dZded< d/d d!Zed0d"d#Zed1d%d&Zed0d'd(Zd2d-d.ZdS )3RuntimeLimitzV
    Final representation of a rate limit before it is triggered during a request
    r
   limitCallable[[], str]key_func!str | Callable[[str], str] | NonescopeFbool
per_methodNSequence[str] | Nonemethodsstr | Callable[[], str] | Noneerror_messageCallable[[], bool] | Noneexempt_whenbool | Noneoverride_defaults!Callable[[Response], bool] | Nonededuct_when0Callable[[RequestLimit], Response | None] | None	on_breachr   zCallable[[], int] | intcostsharedztuple[RuntimeLimit, ...] | Nonemeta_limitsreturnNonec                 C  s$   | j rtdd | j D | _ d S d S )Nc                 S     g | ]}|  qS  lower.0kr3   r3   J/var/www/ai-app/venv/lib/python3.10/site-packages/flask_limiter/_limits.py
<listcomp>-       z.RuntimeLimit.__post_init__.<locals>.<listcomp>)r"   tupleselfr3   r3   r9   __post_init__+   s   zRuntimeLimit.__post_init__c                 C  s   | j r|   S dS )zCheck if the limit is exempt.F)r&   r=   r3   r3   r9   	is_exempt/   s   zRuntimeLimit.is_exemptintc                 C  s   t | jr	|  S | jS )z!How much to deduct from the limit)callabler-   r=   r3   r3   r9   deduction_amount8   s   zRuntimeLimit.deduction_amountc                 C  s   | j duotj | j vS )z4Check if the limit is not applicable for this methodN)r"   r   methodr5   r=   r3   r3   r9   method_exempt>   s   zRuntimeLimit.method_exemptendpointstrrD   
str | Nonec                 C  sh   t | jr| tjpdn| j}|r | jr|}n
| d| }n|}| jr2|s)J |d|  7 }|S )z
        Derive final bucket (scope) for this limit given the endpoint and request method.
        If the limit is shared between multiple routes, the scope does not include the endpoint.
         :)rB   r   r   rF   r.   r    upper)r>   rF   rD   limit_scoper   r3   r3   r9   	scope_forD   s    zRuntimeLimit.scope_forr0   r1   )r0   r   )r0   rA   )rF   rG   rD   rH   r0   rG   )__name__
__module____qualname____doc____annotations__r    r"   r$   r&   r(   r*   r,   r-   r.   r/   r?   propertyr@   rC   rE   rM   r3   r3   r3   r9   r      s.   
 
r   c                   @  s  e Zd ZU dZded< dZded< dZded< dZd	ed
< dZded< dZ	ded< dZ
ded< dZded< dZded< dZded< dZded< dZded< ejdddZded< ejdddddZd ed!< ejdd"Zded#< d3d&d'Zd4d)d*Zed5d,d-Zd6d1d2ZdS )7Limita  
    The definition of a rate limit to be used by the extension as a default limit::


        def default_key_function():
            return request.remote_addr

        def username_key_function():
            return request.headers.get("username", "guest")

        limiter = flask_limiter.Limiter(
            default_key_function,
            default_limits = [
                # 10/second by username
                flask_limiter.Limit("10/second", key_function=username_key_function),
                # 100/second by ip (i.e. default_key_function)
                flask_limiter.Limit("100/second),

            ]
        )
        limit.init_app(app)

    - For application wide limits see :class:`ApplicationLimit`
    - For meta limits see :class:`MetaLimit`
    zCallable[[], str] | strlimit_providerNCallable[[], str] | Nonekey_functionr   r   zCallable[[], int] | int | Noner-   Fr   r.   r!   r"   r    r#   r$   z4Iterable[Callable[[], str] | str | MetaLimit] | Noner/   r%   r&   r)   r*   r+   r,   )defaultinitr'   r(   T)rZ   hashkw_onlyreprzweakref.ProxyType[Limiter]limiterrY   	finalizedr0   r1   c                 C  s6   | j rtdd | j D | _ | jrt| j| _d S d S )Nc                 S  r2   r3   r4   r6   r3   r3   r9   r:      r;   z'Limit.__post_init__.<locals>.<listcomp>)r"   r<   r/   r=   r3   r3   r9   r?      s
   zLimit.__post_init__Iterator[RuntimeLimit]c                 #  s    t  jr
  n j}|rt|ng }d} jr)ttj fdd jD  }|D ]!}t| j j	 j
 j j j j j j jpEd j|dV  q+d S )Nr3   c                   s,   g | ]}t t|tst| n|qS r3   )list
isinstance	MetaLimitbind_parentr7   
meta_limitr=   r3   r9   r:      s    z"Limit.__iter__.<locals>.<listcomp>r   )r   r    r"   r$   r&   r*   r(   r,   r-   r.   r/   )rB   rV   r   r/   r<   	itertoolschainr   limit_byr   r    r"   r$   r&   r*   r(   r,   r-   r.   )r>   	limit_strlimit_itemsr/   r   r3   r=   r9   __iter__   s:   

zLimit.__iter__r   c                 C  s   | j p| jjS N)rX   r^   	_key_funcr=   r3   r3   r9   rj      s   zLimit.limit_byr>   r   r   c                   s(   t  | _ fdd| jpdD  | S )z
        Returns an instance of the limit definition that binds to a weak reference of an instance
        of :class:`Limiter`.

        :meta private:
        c                   s    g | ]}t |tr| qS r3   )rc   rd   bindrf   r^   r3   r9   r:      s    zLimit.bind.<locals>.<listcomp>r3   )weakrefproxyr^   r/   r>   r^   r3   rq   r9   rp      s
   
z
Limit.bindrN   )r0   ra   r0   r   )r>   r   r^   r   r0   r   )rO   rP   rQ   rR   rS   rX   r   r-   r.   r"   r    r$   r/   r&   r*   r,   dataclassesfieldr(   r^   r`   r?   rm   rT   rj   rp   r3   r3   r3   r9   rU   Z   s0   
 	

$rU   )r   r\   c                      s~   e Zd ZU dZdZded< ejddZded< d  fddZ	d!ddZ
d"ddZed#ddZed$ddZd%ddZ  ZS )&
RouteLimita  
    A variant of :class:`Limit` that can be used to to decorate a flask route or blueprint directly
    instead of by using :meth:`Limiter.limit` or :meth:`Limiter.shared_limit`.

    Decorating individual routes::

        limiter = flask_limiter.Limiter(.....)
        limiter.init_app(app)

        @app.route("/")
        @flask_limiter.RouteLimit("2/second", limiter=limiter)
        def view_function():
            ...

    Fr'   r(   )r[   zdataclasses.InitVar[Limiter]r^   r   r0   r1   c                   s   |  | t   d S rn   )rp   superr?   rt   	__class__r3   r9   r?     s   
zRouteLimit.__post_init__c                 C  sp   t jdd}|d j d|d j d|d j }| jjj|| dd | jj| j	 | | jj
d|d d S )	N   )r   r   rJ   T)overrideFin_middlewarecallable_name)	tracebackextract_stackfilenamenamelinenor^   limit_manageradd_decorated_limitadd_endpoint_hintidentify_request_check_request_limit)r>   tbqualified_locationr3   r3   r9   	__enter__  s   &
zRouteLimit.__enter__exc_typetype[BaseException] | None	exc_valueBaseException | Noner   TracebackType | Nonec                 C     d S rn   r3   )r>   r   r   r   r3   r3   r9   __exit__  s   zRouteLimit.__exit__objCallable[P, R]c                 C  r   rn   r3   r>   r   r3   r3   r9   __call__%     zRouteLimit.__call__flask.Blueprintc                 C  r   rn   r3   r   r3   r3   r9   r   (  r    Callable[P, R] | flask.BlueprintCallable[P, R] | Nonec                   s   t tjr
j nt t tjrjj  d S jj	  jj
  td
 fdd}t|d	j |S )NaP.argsr8   P.kwargsr0   r   c                    s|   t dd jks0j }|r(tjj|d }|r(t| ks(jj	|  jj
d d tttj| i |S )N__wrapper-limiter-instanceFr~   )getattrr^   r   flaskcurrent_appview_functionsgetr   r   r   r   r   r   ensure_sync)r   r8   identity	view_funcr   r   r>   r3   r9   __inner9  s   
z$RouteLimit.__call__.<locals>.__innerr   )r   r   r8   r   r0   r   )rc   r   	Blueprintr   r   r^   r   add_blueprint_limit_marked_for_limitingaddr   r   setattr)r>   r   _RouteLimit__innerr3   r   r9   r   +  s   )r^   r   r0   r1   rN   )r   r   r   r   r   r   r0   r1   )r   r   r0   r   )r   r   r0   r1   )r   r   r0   r   )rO   rP   rQ   rR   r(   rS   rv   rw   r^   r?   r   r   r   r   __classcell__r3   r3   rz   r9   rx      s   
 

rx   )r\   r   c                   @  s<   e Zd ZU dZejddZded< ejdddZd	ed
< dS )ApplicationLimitz
    Variant of :class:`Limit` to be used for declaring an application wide limit that can be passed
    to :class:`Limiter` as one of the members of :paramref:`Limiter.application_limits`
    globalr_   r   r   FTrZ   rY   r   r.   N)	rO   rP   rQ   rR   rv   rw   r   rS   r.   r3   r3   r3   r9   r   S  s   
 r   c                   @  s   e Zd ZU dZejddZded< ejdddZd	ed
< ejdddZ	ded< ejdddZ
ded< ejdddZded< dZded< edddZdddZdS ) rd   a  
    Variant of :class:`Limit` to be used for declaring a meta limit that can be passed to
    either :class:`Limiter` as one of the  members of :paramref:`Limiter.meta_limits` or to another
    instance of :class:`Limit` as a member of :paramref:`Limit.meta_limits`
    metar_   r   r   FNr   z4Sequence[Callable[[], str] | str | MetaLimit] | Noner/   zLimit | Noneparent_limitTr   r.   r)   r*   rW   rX   r0   r   c                 C  s   | j p| jo	| jj p| jjS rn   )rX   r   r^   ro   r=   r3   r3   r9   rj     s   zMetaLimit.limit_byr>   r   parentrU   c                 C  s
   || _ | S )zt
        Binds this meta limit to be associated as a child of the ``parent`` limit.

        :meta private:
        )r   )r>   r   r3   r3   r9   re     s   zMetaLimit.bind_parentru   )r>   r   r   rU   r0   r   )rO   rP   rQ   rR   rv   rw   r   rS   r/   r   r.   r*   rX   rT   rj   re   r3   r3   r3   r9   rd   b  s   
 rd   )(
__future__r   rv   rh   r   rr   	functoolsr   typesr   typingr   r   r   r   r   flask.wrappersr	   limitsr
   r   _typingr   r   r   r   r   r   r   utilr   flask_limiterr   r   	dataclassr   rU   rx   r   rd   r3   r3   r3   r9   <module>   s6    $B c