o
    KK&hY                     @   s  d dl Z d dlZd dlZd dlmZmZ d dlmZ d dl	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 dd	lmZ dd
lmZmZ ddlmZ ddlmZmZ ddlm Z 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(m)Z)m*Z*m+Z+ G dd deZ,dS )    N)ABCabstractmethod)SimpleNamespace)warn)
RouteGroup)	ParamInfo   )	BadMethodFinalizationErrorInvalidUsageNoMethodNotFound)Line)REGEX_TYPESREGEX_TYPES_ANNOTATION)Route)NodeTree)parts_to_pathpath_to_parts)datetime)unquote)UUID)
parse_datealphaslugnonemptystrc                   @   s^  e Zd ZU dZe Zejedf e	d< de
eeeddfdedeje
 deje d	eje d
eje dededdfddZedd Zdddddedeje deje dejejeef  dejeejdejf ejeejf f f
ddZ							dIdddedejdejejeje eje ef  deje dejejeejf  d ed!ed"ed#ed$edefd%d&Zefd'ed(ejegejf d)ejejef d*eje fd+d,ZdJd.ed/efd0d1Z d2d3 Z!d4edej"e fd5d6Z#dKd7d8Z$	dJd.ed/eddfd9d:Z%e&d;d< Z'e&d=d> Z(e&d?d@ Z)e&dAdB Z*dKdCdDZ+e,dEdF Z-defdGdHZ.dS )L
BaseRouterBASE.ALLOWED_METHODS/F	delimiter	exceptionmethod_handler_exceptionroute_classgroup_classstackingcascade_not_foundreturnNc                 C   s   d | _ d | _i | _i | _i | _i | _|| _|| _|| _|| _	|| _
t| d| _d| _|| _t | _|| _i | _t D ]\}\}	}
}| ||	|
| q;d S )NrouterF)_find_route	_matchersstatic_routesdynamic_routesregex_routes
name_indexr!   r"   r#   r$   r%   r   tree	finalizedr&   r   ctxr'   regex_typesr   itemsregister_pattern)selfr!   r"   r#   r$   r%   r&   r'   labelcastpatternparam_info_class r<   G/var/www/html/venv/lib/python3.10/site-packages/sanic_routing/router.py__init__'   s(   
zBaseRouter.__init__c                 K   s   d S Nr<   )r7   kwargsr<   r<   r=   getG   s   zBaseRouter.get)methodorigextrapathrB   rC   rD   c             
   C   s  z|  ||| i i d|\}}W n0 ttfy@ } z"|| jr3| j|d d |||dW  Y d }~S |jt||dd }~ww t|t	rdz|j
| }W n tyc   | jd| d| ||jdw |d }|rn|d	 r|j D ]2\}	}
z|d	 |	 }W n	 ty   Y qsw t|tr|
|| qs|jr|jr|
jtur|||
j< qs|jr|r|d |jd kr| jd
|d||jvr| jd| d| ||jd||j|fS )N)
__params____matches__)rE   rB   rC   rD   )rE   zMethod 'z' not found on )rB   allowed_methodsrF   rG   zPath not found)
find_router   r   endswithr!   resolve	__class__str
isinstancer   methods_indexKeyErrorr#   methodsparamsr5   tupleprocessregexr9   namestrictrE   r"   handler)r7   rE   rB   rC   rD   routeparam_basketerS   idxparamvaluer<   r<   r=   rL   K   sl   





zBaseRouter.resolver   )priorityrY   rR   rW   requirementsrX   r   	overwriteappendr`   c
                   s  |r|	rt d|
r|	st d|s jg}t|dr%t|ts%t|}n
t|tr/t|g} jrQt fdd|D rQ fdd|D }td| d	 j  j	rXt d
d|vo_|d u } 
|}|rk j}n	|rq j}n j}tt| j j}|r|jn|j}| j} j ||pd||||||||
d} |}|r|j jv r j}|s|j jv rĈ j|j}||||	 n|j|v r||j }||||	 |||j< |r| j|< |  |S )Nz?Cannot add a route with both overwrite and append equal to Truez3Cannot add a route with priority if append is False__iter__c                 3   s    | ]}| j vV  qd S r?   r   .0rB   r7   r<   r=   	<genexpr>   s    

z!BaseRouter.add.<locals>.<genexpr>c                    s   g | ]	}| j vr|qS r<   re   rf   rh   r<   r=   
<listcomp>   s
    
z"BaseRouter.add.<locals>.<listcomp>zBad method: z. Must be one of: &Cannot finalize router more than once.< )rY   rR   ra   rX   r   staticrV   r`   )r
   DEFAULT_METHODhasattrrO   	frozensetrN   r   anyr	   r2   	_is_regexr/   r-   r.   r   r   r!   lstripstripr$   r%   segmentspopmerger0   finalize)r7   rE   rY   rR   rW   ra   rX   r   rb   rc   r`   badrn   rV   routesru   rZ   groupexisting_groupr<   rh   r=   add   s   










zBaseRouter.addr8   r9   r:   r;   c                 C   s   t |tstd| t|std| t |ts.t |tjs.td| dt| t |tr8t|}|t	 |j
< |||f| j|< dS )a"  
        Add a custom parameter type to the router. The cast should raise a
        ValueError if it is an incorrect type. The order of registration is
        important if it is possible that a single value could pass multiple
        pattern types. Therefore, patterns are tried in the REVERSE order of
        registration. All custom patterns will be evaluated before any built-in
        patterns.

        :param label: The parts that is used to signify the type: example

        :type label: str
        :param cast: The callable that casts the value to the desired type, or
            fails trying
        :type cast: t.Callable[[str], t.Any]
        :param pattern: A regular expression that could also match the path
            segment
        :type pattern: Union[t.Pattern, str]
        z>When registering a pattern, label must be a string, not label=z>When registering a pattern, cast must be a callable, not cast=zOWhen registering a pattern, pattern must be a string or a Pattern, not pattern=z, type=N)rO   rN   r   callabletPatterntyperecompileglobals__name__r4   )r7   r8   r9   r:   r;   r<   r<   r=   r6     s0   


zBaseRouter.register_patternT
do_compiledo_optimizec                 C   s   | j rtd| jstdd| _ t| j t| j  t| j  D ]}|  |jD ]}|  q/|	  q&| 
  | || dS )a]  
        After all routes are added, we can put everything into a final state
        and build the routing dource

        :param do_compile: Whether to compile the source, mainly a debugging
            tool, defaults to True
        :type do_compile: bool, optional
        :param do_optimize: Experimental feature that uses AST module to make
            some optimizations, defaults to False
        :type do_optimize: bool, optional
        :raises FinalizationError: Cannot finalize if there are no routes, or
            the router has already been finalized (can call reset() to undo it)
        rk   z'Cannot finalize with no routes defined.TN)r2   r
   r{   listr-   valuesr.   r/   ry   prioritize_routes_generate_tree_render)r7   r   r   r|   rZ   r<   r<   r=   ry   7  s"   


zBaseRouter.finalizec                 C   sh   d| _ t| d| _d | _t| j t| j  t| j  D ]}|	  |j
D ]}|	  q*q!d S )NFr)   )r2   r   r1   r+   r   r-   r   r.   r/   resetr{   )r7   r|   rZ   r<   r<   r=   r   \  s   

zBaseRouter.resethas_dynamic_pathc                    s8   t  fddt| j t| j  D dd ddS )a  
        Paths that have some matching params (includes dynamic and regex),
        but excludes any routes with a <path:path> or delimiter in its regex.
        This is because those special cases need to be evaluated seperately.
        Anything else can be evaluated in the node tree.

        :param has_dynamic_path: Whether the path catches a path, or path-like
        type
        :type has_dynamic_path: bool
        :return: list of routes that have no path, but do need matching
        :rtype: List[RouteGroup]
        c                    s   g | ]	}|j  u r|qS r<   )dynamic_path)rg   r|   r   r<   r=   rj   z  s
    
z>BaseRouter._get_non_static_non_path_groups.<locals>.<listcomp>c                 S      | j S r?   )depthxr<   r<   r=   <lambda>      z<BaseRouter._get_non_static_non_path_groups.<locals>.<lambda>Tkeyreverse)sortedr   r.   r   r/   )r7   r   r<   r   r=   _get_non_static_non_path_groupsj  s   
z*BaseRouter._get_non_static_non_path_groupsc                 C   s    | j | d | j   d S )NF)r1   generater   ry   rh   r<   r<   r=   r     s   zBaseRouter._generate_treec                 C   s  t ddt ddg}g }| jr+|t ddt ddt ddt d	dt d
dt ddg7 }| jrct| j dd dd}|t dd t|D ]\}}||_|t d|j dd qF|t dd | j	si| jrx|t ddg7 }|| j
 7 }| dD ]W}|jrdnd}d}	g }
|jrd}	t |
d| |	dkrt|jdkrd}	t|
d| |t d|j ddt ddg|
t ddt d| d|j d|	 dd q}|t d d || d!tttd"d || _|ruz5t| j}|r| |jd  tj j!d#krtj j"d$krt#| d%t$| t%| t&|d!d&}W n7 t'y_ } z*d'|j( d(|j) d)|j* d*t+dt,|j-pFdd  d+  }t.d,| j d)| d }~ww i }t/|d | |d- | _0|1d.| _2d S d S )/Nz4def find_route(path, method, router, basket, extra):r   z/parts = tuple(path[1:].split(router.delimiter))r   ztry:z#group = router.static_routes[parts]   zbasket['__raw_path__'] = pathzreturn group, basketzexcept KeyError:passc                 S   s
   t | jS r?   )lenparts)rZ   r<   r<   r=   r     s   
 z$BaseRouter._render.<locals>.<lambda>Tr   zmatchers = [zre.compile(r'^z$'),]znum = len(parts)r/   r.   	route_idxzmatch = router.matchers[z].match(path)z	if match:z(basket['__params__'] = match.groupdict()zreturn router.[z][z	], basketzraise NotFoundrm   c                 S   r   r?   )renderr   r<   r<   r=   r     r      	   find_route_src_compiledexeczLine z: 
 ^zCannot compile route AST:
rJ   matchers)3r   r-   r/   r   r   rc   	enumeratepattern_idxr:   r.   r1   r   r   rV   ra   r   _inject_requirementsr   r{   _inject_method_checkextendrv   joinmaprN   filterfind_route_srcastparse	_optimizebodysysversion_infomajorminorsetattrunparsefix_missing_locationsr   SyntaxErrorlinenomsgtextmaxintoffsetr
   r   r+   rA   r,   )r7   r   r   srcdelayedr{   r]   r|   route_containerr   holdersyntax_treecompiled_srcsesyntax_errorr3   r<   r<   r=   r     s   	


 
	
zBaseRouter._renderc                 C   r   r?   )r+   rh   r<   r<   r=   rJ        zBaseRouter.find_routec                 C   r   r?   )r,   rh   r<   r<   r=   r     r   zBaseRouter.matchersc                 C   s   i | j | j| jS r?   )r-   r.   r/   rh   r<   r<   r=   groups   s   zBaseRouter.groupsc                 C   s   t dd | j D S )Nc                 S   s   g | ]	}|D ]}|qqS r<   r<   )rg   r|   rZ   r<   r<   r=   rj   +  s    z%BaseRouter.routes.<locals>.<listcomp>)rT   r   r   rh   r<   r<   r=   r{   (  s   zBaseRouter.routesc                 C   sH  t d t|dr|jD ]}| | q| |rj| |jd rj|jd }|jd jd }g }|j|jfD ]#}t|tjrD|	| q6t|tj
rXt|jtjrX||j q6	 q6tj
t |d}||_|j|_tdd |jD rt|jdkr|j^}}	|	D ]	}
|j|
j q|g|_t|dr|jD ]	}| | qd S d S )	Nz`Router AST optimization is an experimental only feature. Results may vary from unoptimized code.r   r   )opr   c                 s   s    | ]	}t |tjV  qd S r?   )rO   r   If)rg   childr<   r<   r=   ri   ]  s    z'BaseRouter._optimize.<locals>.<genexpr>r   orelse)r   rp   r   r   _is_lone_iftestrO   r   Comparerc   BoolOpr   Andr   r   allr   r   )r7   noder   currentnestedr   r   combinedfirstremitemr<   r<   r=   r   .  sB   






zBaseRouter._optimizec                 C   s    t | jdkot| jd tjS )Nr   r   )r   r   rO   r   r   )r   r<   r<   r=   r   l  s    zBaseRouter._is_lone_ifc                    s.   t |j}fdd t fdd|D S )Nc                    sL   |  dr	d| vrdS | dd d^}}}| dp% j| v p%| jvS )Nrl   :Fr   rH   z:path>)
startswithsplitrK   r!   r4   )part_pattern_type__rh   r<   r=   requiress  s   
z&BaseRouter._is_regex.<locals>.requiresc                 3   s    | ]} |V  qd S r?   r<   )rg   r   )r   r<   r=   ri     s    z'BaseRouter._is_regex.<locals>.<genexpr>)r   r!   rr   )r7   rE   r   r<   )r   r7   r=   rs   p  s   zBaseRouter._is_regex)NNNFFFF)TF)r(   N)/r   
__module____qualname__ro   rT   r   r   TuplerN   __annotations__r   r   r   r   Typeboolr>   r   rA   OptionalDictCallableAnyrL   UnionSequence	FrozenSetr   r~   r   r   r6   ry   r   Listr   r   r   propertyrJ   r   r   r{   r   staticmethodr   rs   r<   r<   r<   r=   r   #   s   
 	
 
&
P	

w
0%


 




>
r   )-r   r   typingr   abcr   r   typesr   warningsr   sanic_routing.groupr   sanic_routing.patternsr   
exceptionsr	   r
   r   r   r   liner   patternsr   r   rZ   r   r1   r   r   utilsr   r   r   r   urllib.parser   uuidr   r   r   r   r   r   r<   r<   r<   r=   <module>   s(    