B
    `k                 @   s  d 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 ddl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 ddlmZmZ ddlmZmZ ddlm Z  ddl!m"Z" ddl#m$Z$m%Z% ddl&m'Z' G dd dZ(d.ddZ)ej*ddd/ddZ+ej*dddd Z,G dd dZ-G dd dZ.G d d! d!e.Z/ed"Z0d0d$d%Z1G d&d' d'e.Z2G d(d) d)Z3G d*d+ d+Z4G d,d- d-Z5dS )1z
This module converts requested URLs to callback view functions.

URLResolver is the main class here. Its resolve() method takes a URL (as
a string) and returns a ResolverMatch object which provides access to all
attributes of the resolved URL match.
    N)import_module)quote)Local)settings)ErrorWarning)check_resolver)ImproperlyConfiguredViewDoesNotExist)MultiValueDict)cached_property)RFC3986_SUBDELIMSescape_leading_slashes)_lazy_re_compile	normalize)get_language   )get_converter)NoReverseMatchResolver404)get_callablec               @   s&   e Zd ZdddZdd Zdd ZdS )	ResolverMatchNc       	      C   s   || _ || _|| _|| _|| _|r0dd |D ng | _d| j| _|rVdd |D ng | _d| j| _	t
|ds|jjd |jj | _n|jd |j | _|p| j}d| j|g | _d S )Nc             S   s   g | ]}|r|qS  r   ).0xr   r   D/home/dcms/DCMS/lib/python3.7/site-packages/django/urls/resolvers.py
<listcomp>*   s    z*ResolverMatch.__init__.<locals>.<listcomp>:c             S   s   g | ]}|r|qS r   r   )r   r   r   r   r   r   ,   s    __name__.)funcargskwargsurl_nameroute	app_namesjoinapp_name
namespaces	namespacehasattr	__class__
__module__r   
_func_pathZ	view_name)	selfr    r!   r"   r#   r%   r(   r$   Z	view_pathr   r   r   __init__!   s    

zResolverMatch.__init__c             C   s   | j | j| jf| S )N)r    r!   r"   )r.   indexr   r   r   __getitem__9   s    zResolverMatch.__getitem__c             C   s$   d| j | j| j| j| j| j| jf S )Nz^ResolverMatch(func=%s, args=%s, kwargs=%s, url_name=%s, app_names=%s, namespaces=%s, route=%s))r-   r!   r"   r#   r%   r(   r$   )r.   r   r   r   __repr__<   s    zResolverMatch.__repr__)NNNN)r   r,   __qualname__r/   r1   r2   r   r   r   r   r       s   
r   c             C   s   | d krt j} t| S )N)r   ZROOT_URLCONF_get_cached_resolver)urlconfr   r   r   get_resolverC   s    r6   )maxsizec             C   s   t td| S )Nz^/)URLResolverRegexPattern)r5   r   r   r   r4   I   s    r4   c             C   s.   t | }t||_t||j}tt d|gS )Nz^/)r9   dict
convertersr8   url_patterns)Z
ns_patternresolverr;   patternZns_resolverr   r   r   get_ns_resolverN   s    
r?   c               @   s   e Zd Zdd ZdddZdS )LocaleRegexDescriptorc             C   s
   || _ d S )N)attr)r.   rA   r   r   r   r/   Z   s    zLocaleRegexDescriptor.__init__Nc             C   sj   |dkr| S t || j}t|tr<|||jd< |jd S t }||jkr`|t||j|< |j| S )zT
        Return a compiled regular expression based on the active language.
        Nregex)getattrrA   
isinstancestr_compile__dict__r   _regex_dict)r.   instanceclsr>   language_coder   r   r   __get__]   s    


zLocaleRegexDescriptor.__get__)N)r   r,   r3   r/   rL   r   r   r   r   r@   Y   s   r@   c               @   s   e Zd Zdd Zdd ZdS )CheckURLMixinc             C   s$   d | }| jr |d | j7 }|S )zI
        Format the URL pattern for display in warning messages.
        z'{}'z [name='{}'])formatname)r.   descriptionr   r   r   describeq   s    
zCheckURLMixin.describec             C   sJ   | j j}tjsg S |drB|dsBtd|  dd}|gS g S dS )zM
        Check that the pattern does not begin with a forward slash.
        )/z^/z^\/rR   zYour URL pattern {} has a route beginning with a '/'. Remove this slash as it is unnecessary. If this pattern is targeted in an include(), ensure the include() pattern has a trailing '/'.z	urls.W002)idN)	rB   r>   r   ZAPPEND_SLASH
startswithendswithr   rN   rQ   )r.   regex_patternwarningr   r   r   _check_pattern_startswith_slashz   s    z-CheckURLMixin._check_pattern_startswith_slashN)r   r,   r3   rQ   rX   r   r   r   r   rM   p   s   	rM   c               @   sF   e Zd ZedZdddZdd Zdd	 Zd
d Zdd Z	dd Z
dS )r9   _regexNFc             C   s"   || _ i | _|| _|| _i | _d S )N)rY   rH   _is_endpointrO   r;   )r.   rB   rO   is_endpointr   r   r   r/      s
    zRegexPattern.__init__c             C   sT   | j |}|rP| }|r dn| }dd | D }|| d  ||fS d S )Nr   c             S   s   i | ]\}}|d k	r||qS )Nr   )r   kvr   r   r   
<dictcomp>   s    z&RegexPattern.match.<locals>.<dictcomp>)rB   search	groupdictgroupsitemsend)r.   pathmatchr"   r!   r   r   r   re      s    zRegexPattern.matchc             C   s*   g }| |   | js&| |   |S )N)extendrX   rZ   _check_include_trailing_dollar)r.   warningsr   r   r   check   s
    zRegexPattern.checkc             C   s<   | j j}|dr4|ds4td|  ddgS g S d S )N$z\$zYour URL pattern {} uses include with a route ending with a '$'. Remove the dollar from the route to avoid problems including URLs.z	urls.W001)rS   )rB   r>   rU   r   rN   rQ   )r.   rV   r   r   r   rg      s    
z+RegexPattern._check_include_trailing_dollarc          
   C   sF   y
t |S  t jk
r@ } ztd||f |W dd}~X Y nX dS )z0Compile and return the given regular expression.z*"%s" is not a valid regular expression: %sN)recompileerrorr	   )r.   rB   er   r   r   rF      s    
zRegexPattern._compilec             C   s
   t | jS )N)rE   rY   )r.   r   r   r   __str__   s    zRegexPattern.__str__)NF)r   r,   r3   r@   rB   r/   re   ri   rg   rF   ro   r   r   r   r   r9      s   
	r9   z1<(?:(?P<converter>[^>:]+):)?(?P<parameter>[^>]+)>Fc       
   
   C   s4  t | tjstd|  | }dg}i }xt| }|sL|t	|  P |t	| d|
   | | d } |d }| std||f |d }|dkrd}yt|}W n4 tk
r }	 ztd||f |	W dd}	~	X Y nX |||< |d	| d
 |j d  q,W |r&|d d||fS )a  
    Convert a path pattern into a regular expression. Return the regular
    expression and a dictionary mapping the capture names to the converters.
    For example, 'foo/<int:pk>' returns '^foo\/(?P<pk>[0-9]+)'
    and {'pk': <django.urls.converters.IntConverter>}.
    z)URL route '%s' cannot contain whitespace.^N	parameterzLURL route '%s' uses parameter name %r which isn't a valid Python identifier.	converterrE   z'URL route %r uses invalid converter %r.z(?P<>)rj    )set
isdisjointstring
whitespacer	   _PATH_PARAMETER_COMPONENT_REr_   appendrk   escapestartrc   isidentifierr   KeyErrorrB   r&   )
r$   r[   Zoriginal_routepartsr;   re   rq   Zraw_converterrr   rn   r   r   r   _route_to_regex   s@    

 
r   c               @   s>   e Zd ZedZdddZdd Zdd	 Zd
d Zdd Z	dS )RoutePattern_routeNFc             C   s0   || _ i | _|| _|| _tt||d | _d S )Nr   )r   rH   rZ   rO   r   rE   r;   )r.   r$   rO   r[   r   r   r   r/      s
    zRoutePattern.__init__c          	   C   sz   | j |}|rv| }xF| D ]:\}}| j| }y||||< W q" tk
rZ   d S X q"W || d  d|fS d S )Nr   )rB   r_   r`   rb   r;   Z	to_python
ValueErrorrc   )r.   rd   re   r"   keyvaluerr   r   r   r   re     s    

zRoutePattern.matchc             C   sJ   |   }| j}d|ks*|ds*|drF|td|  dd |S )Nz(?P<rp   rj   zYour URL pattern {} has a route that contains '(?P<', begins with a '^', or ends with a '$'. This was likely an oversight when migrating to django.urls.path().z2_0.W001)rS   )rX   r   rT   rU   r{   r   rN   rQ   )r.   rh   r$   r   r   r   ri     s    
zRoutePattern.checkc             C   s   t t|| jd S )Nr   )rk   rl   r   rZ   )r.   r$   r   r   r   rF     s    zRoutePattern._compilec             C   s
   t | jS )N)rE   r   )r.   r   r   r   ro     s    zRoutePattern.__str__)NF)
r   r,   r3   r@   rB   r/   re   ri   rF   ro   r   r   r   r   r      s   
r   c               @   sN   e Zd ZdddZedd Zedd Zdd	 Zd
d Zdd Z	dd Z
dS )LocalePrefixPatternTc             C   s   || _ i | _d S )N)prefix_default_languager;   )r.   r   r   r   r   r/   #  s    zLocalePrefixPattern.__init__c             C   s   t | jS )N)rk   rl   language_prefix)r.   r   r   r   rB   '  s    zLocalePrefixPattern.regexc             C   s,   t  p
tj}|tjkr | js dS d| S d S )Nru   z%s/)r   r   ZLANGUAGE_CODEr   )r.   rK   r   r   r   r   ,  s    z#LocalePrefixPattern.language_prefixc             C   s*   | j }||r&|t|d  di fS d S )Nr   )r   rT   len)r.   rd   r   r   r   r   re   4  s    
zLocalePrefixPattern.matchc             C   s   g S )Nr   )r.   r   r   r   ri   :  s    zLocalePrefixPattern.checkc             C   s
   d | S )Nz'{}')rN   )r.   r   r   r   rQ   =  s    zLocalePrefixPattern.describec             C   s   | j S )N)r   )r.   r   r   r   ro   @  s    zLocalePrefixPattern.__str__N)T)r   r,   r3   r/   propertyrB   r   re   ri   rQ   ro   r   r   r   r   r   "  s   
r   c               @   sB   e Zd ZdddZdd Zdd Zdd	 Zd
d Zedd Z	dS )
URLPatternNc             C   s    || _ || _|pi | _|| _d S )N)r>   callbackdefault_argsrO   )r.   r>   r   r   rO   r   r   r   r/   E  s    
zURLPattern.__init__c             C   s   d| j j| j f S )Nz<%s %s>)r+   r   r>   rQ   )r.   r   r   r   r2   K  s    zURLPattern.__repr__c             C   s   |   }|| j  |S )N)_check_pattern_namerf   r>   ri   )r.   rh   r   r   r   ri   N  s    zURLPattern.checkc             C   s>   | j jdk	r6d| j jkr6td| j  dd}|gS g S dS )zG
        Check that the pattern name does not contain a colon.
        Nr   zjYour URL pattern {} has a name including a ':'. Remove the colon, to avoid ambiguous namespace references.z	urls.W003)rS   )r>   rO   r   rN   rQ   )r.   rW   r   r   r   r   S  s    
zURLPattern._check_pattern_namec             C   sH   | j |}|rD|\}}}|| j t| j||| j jt| j dS d S )N)r$   )r>   re   updater   r   r   rO   rE   )r.   rd   re   new_pathr!   r"   r   r   r   resolvea  s
    
zURLPattern.resolvec             C   sD   | j }t|tjr|j}t|ds4|jd |jj S |jd |j	 S )zw
        A string that identifies the view (e.g. 'path.to.view_function' or
        'path.to.ClassBasedView').
        r   r   )
r   rD   	functoolspartialr    r*   r,   r+   r   r3   )r.   r   r   r   r   
lookup_stri  s    
zURLPattern.lookup_str)NN)
r   r,   r3   r/   r2   ri   r   r   r   r   r   r   r   r   r   D  s   
r   c               @   s   e Zd Zd"ddZdd Zdd Zdd	 Zd
d Zedd Z	edd Z
edd Zedd Zdd Zdd Zedd Zedd Zdd Zdd Zd d! ZdS )#r8   Nc             C   sT   || _ || _d | _|pi | _|| _|| _i | _i | _i | _t	 | _
d| _t | _d S )NF)r>   urlconf_namer   default_kwargsr)   r'   _reverse_dict_namespace_dict	_app_dictrv   _callback_strs
_populatedr   _local)r.   r>   r   r   r'   r)   r   r   r   r/   x  s    
zURLResolver.__init__c             C   sP   t | jtr&| jr&d| jd jj }n
t| j}d| jj|| j| j| j	 f S )Nz	<%s list>r   z<%s %s (%s:%s) %s>)
rD   r   listr+   r   reprr'   r)   r>   rQ   )r.   Zurlconf_reprr   r   r   r2     s    
zURLResolver.__repr__c             C   s>   g }x| j D ]}|t| qW ||   |p<| j S )N)r<   rf   r   _check_custom_error_handlersr>   ri   )r.   messagesr>   r   r   r   ri     s
    zURLResolver.checkc             C   s   g }xdD ]\}}y|  |\}}W n^ ttfk
r } z<t| jd| }dj||d}|t|t|dd w
W d d }~X Y nX t	
|}	d g| }
y|	j|
  W q
 tk
r   dj||jd |j |d	krd
ndd}|t|dd Y q
X q
W |S )N))i     )i  r   )i  r   )i  r   z	handler%szDThe custom handler{status_code} view '{path}' could not be imported.)status_coderd   z	urls.E008)hintrS   zeThe custom handler{status_code} view '{path}' does not take the correct number of arguments ({args}).r   r   zrequest, exceptionrequest)r   rd   r!   z	urls.E007)rS   )resolve_error_handlerImportErrorr
   rC   urlconf_modulerN   r{   r   rE   inspect	signaturebind	TypeErrorr,   r3   )r.   r   r   Znum_parametershandlerZ
param_dictrn   rd   msgr   r!   r   r   r   r     s*    


z(URLResolver._check_custom_error_handlersc             C   s(  t | jddrd S zd| j_t }i }i }t }xt| jD ]}|jjj}|	drf|dd  }t
|tr| j|j t|jjj}||j|||j|jjf |jd k	r||j|||j|jjf q@|  |jr||jg |j ||f||j< nxh|jD ]^}xV|j|D ]F\}	}
}}t||
 }|||||
 ||j| jj|jj|f q W qW xB|j D ]4\}\}}|jj}|jj| || |f||< q|W x*|j  D ]\}}||g !| qW | j|j q@W || j"|< || j#|< || j$|< d| _%W d d| j_X d S )N
populatingFTrp   r   )&rC   r   r   r   r   reversedr<   r>   rB   rT   rD   r   r   addr   r   Z
appendlistr   r   r;   rO   	_populater'   
setdefaultr{   r)   reverse_dictgetlistr   namespace_dictrb   r   app_dictrf   r   r   r   r   )r.   Zlookupsr(   ZappsrK   Zurl_patternZ	p_patternbitsrO   matchespatdefaultsr;   Znew_matchesr)   prefixZsub_patternZcurrent_convertersr'   Znamespace_listr   r   r   r     s^    



"



zURLResolver._populatec             C   s"   t  }|| jkr|   | j| S )N)r   r   r   )r.   rK   r   r   r   r     s    
zURLResolver.reverse_dictc             C   s"   t  }|| jkr|   | j| S )N)r   r   r   )r.   rK   r   r   r   r     s    
zURLResolver.namespace_dictc             C   s"   t  }|| jkr|   | j| S )N)r   r   r   )r.   rK   r   r   r   r     s    
zURLResolver.app_dictc             C   s&   | s|S | dr|dd }| | S )z<Join two routes, without the starting ^ in the second route.rp   r   N)rT   )Zroute1Zroute2r   r   r   _join_route  s
    
zURLResolver._join_routec             C   s   | j s|   || jkS )N)r   r   r   )r.   rO   r   r   r   _is_callback  s    zURLResolver._is_callbackc                sR  t |}g }| j|}|rB|\}}}x| jD ] y |}W n` tk
r } zB|jd d}	|	d k	r| fdd|	D  n|	 g W d d }~X Y q2X |r$|| j
}
|
|j |j}|
s||j }t trdnt  j}t|j||
|j| jg|j | jg|j | ||jS |	 g q2W t||dtd|id S )Nr   triedc             3   s   | ]} g| V  qd S )Nr   )r   t)r>   r   r   	<genexpr>'  s    z&URLResolver.resolve.<locals>.<genexpr>ru   )r   rd   rd   )rE   r>   re   r<   r   r   r!   getrf   r{   r   r   r"   rD   r   r   r    r#   r'   r%   r)   r(   r   r$   )r.   rd   r   re   r   r!   r"   Z	sub_matchrn   Z	sub_triedZsub_match_dictZsub_match_argsZcurrent_router   )r>   r   r     s>    


zURLResolver.resolvec             C   s    t | jtrt| jS | jS d S )N)rD   r   rE   r   )r.   r   r   r   r   C  s    
zURLResolver.urlconf_modulec          
   C   s\   t | jd| j}yt| W n: tk
rV } zd}t|j| jd|W d d }~X Y nX |S )NZurlpatternszThe included URLconf '{name}' does not appear to have any patterns in it. If you see valid patterns in the file then the issue is probably caused by a circular import.)rO   )rC   r   iterr   r	   rN   r   )r.   patternsrn   r   r   r   r   r<   J  s    &zURLResolver.url_patternsc             C   s<   t | jd| d }|s0ddlm} t |d| }t|i fS )Nz	handler%sr   )urls)rC   r   django.confr   r   )r.   Z	view_typer   r   r   r   r   r   Y  s
    z!URLResolver.resolve_error_handlerc             O   s   | j |df||S )Nru   )_reverse_with_prefix)r.   lookup_viewr!   r"   r   r   r   reverseb  s    zURLResolver.reversec                s  |r rt d| js|   | j|}xD|D ]:\}}}}	x*|D ] \}
}|rxt|t|krhqHtt||}n6t 	|
|rqHt fdd| D rqH }i }d}x`| D ]T\}}||	kry|	| |||< W n t k
r   d}P Y nX qt|||< qW |s qH|dd|
 }tdt||f || rHt|| td	 d
}t|S qHW q2W t|dd }t|dd }|d k	r|d k	rd||f }n|}dd |D }|r |rd|f }n rd  }nd}d||t||f }ndd|i }t|d S )Nz2Don't mix *args and **kwargs in call to reverse()!c             3   s"   | ]\}}  |||kV  qd S )N)r   )r   r\   r]   )r"   r   r   r   w  s    z3URLResolver._reverse_with_prefix.<locals>.<genexpr>TF%z%%z^%s%sz/~:@)safer,   r   z%s.%sc             S   s   g | ]\}}}}|qS r   r   )r   _r>   r   r   r   r     s    z4URLResolver._reverse_with_prefix.<locals>.<listcomp>zarguments '%s'zkeyword arguments '%s'zno argumentsz;Reverse for '%s' with %s not found. %d pattern(s) tried: %szZReverse for '%(view)s' not found. '%(view)s' is not a valid view function or pattern name.view)r   r   r   r   r   r   r:   ziprv   symmetric_difference
differenceanyrb   Zto_urlrE   replacerk   r_   r|   r   r   r   rC   r   )r.   r   _prefixr!   r"   possibilitiesZpossibilityr>   r   r;   resultparamsZcandidate_subsZtext_candidate_subsre   r\   r]   Zcandidate_paturlmnZlookup_view_sr   Zarg_msgr   r   )r"   r   r   e  sb    



z URLResolver._reverse_with_prefix)NNN)r   r,   r3   r/   r2   ri   r   r   r   r   r   r   staticmethodr   r   r   r   r   r<   r   r   r   r   r   r   r   r8   w  s    
=	(	r8   )N)N)F)6__doc__r   r   rk   rx   	importlibr   urllib.parser   Zasgiref.localr   r   r   Zdjango.core.checksr   r   Zdjango.core.checks.urlsr   Zdjango.core.exceptionsr	   r
   Zdjango.utils.datastructuresr   Zdjango.utils.functionalr   Zdjango.utils.httpr   r   Zdjango.utils.regex_helperr   r   Zdjango.utils.translationr   r;   r   
exceptionsr   r   utilsr   r   r6   	lru_cacher4   r?   r@   rM   r9   rz   r   r   r   r   r8   r   r   r   r   <module>   sD   #

!6
++"3