
v^j                 @   sL  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 d d l m Z d d l  m! Z! d d l" m# Z# m$ Z$ d d l% m& Z& Gd d   d  Z' d d d  Z( e j) d d  d d d   Z* e j) d d  d d    Z+ Gd d   d  Z, Gd d   d  Z- Gd  d!   d! e-  Z. e j/ d"  Z0 d# d$ d%  Z1 Gd& d'   d' e-  Z2 Gd( d)   d)  Z3 Gd* d+   d+  Z4 Gd, d-   d-  Z5 d S).z
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)	normalize)get_language   )get_converter)NoReverseMatchResolver404)get_callablec               @   s@   e  Z d  Z d d d d d d  Z d d   Z d d   Z d S)ResolverMatchNc       	      C   s  | |  _  | |  _ | |  _ | |  _ | |  _ | rF d d   | D n g  |  _ d j |  j  |  _ | r} d d   | D n g  |  _ d j |  j  |  _	 t
 | d  s | j j d | j j |  _ n | j d | j |  _ | p |  j } d j |  j | g  |  _ d  S)Nc             S   s   g  |  ] } | r |  q S r   ).0xr   r   7/tmp/pip-build-8lau8j11/django/django/urls/resolvers.py
<listcomp>*   s   	 z*ResolverMatch.__init__.<locals>.<listcomp>:c             S   s   g  |  ] } | r |  q Sr   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   s2   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__)r   r+   __qualname__r.   r0   r1   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    	r5   maxsizec             C   s   t  t d  |   S)Nz^/)URLResolverRegexPattern)r4   r   r   r   r3   I   s    r3   c             C   sC   t  |   } t |  | _ t | | j  } t t  d  | g  S)Nz^/)r8   dict
convertersr7   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-   r@   r   r   r   r.   Z   s    zLocaleRegexDescriptor.__init__Nc             C   s   | d k r |  St  | |  j  } t | t  rR | j |  | j d <| j d St   } | | j k r | j t |   | j | <| j | S)zT
        Return a compiled regular expression based on the active language.
        Nregex)getattrr@   
isinstancestr_compile__dict__r   _regex_dict)r-   instanceclsr=   language_coder   r   r   __get__]   s    	zLocaleRegexDescriptor.__get__)r   r+   r2   r.   rK   r   r   r   r   r?   Y   s   r?   c               @   s(   e  Z d  Z d d   Z d d   Z d S)CheckURLMixinc             C   s2   d j  |   } |  j r. | d j  |  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   sh   |  j  j } t j s g  S| j d  r` | j d  r` t d j |  j    d d } | g Sg  Sd S)	zM
        Check that the pattern does not begin with a forward slash.
        /^/^\/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 '/'.idz	urls.W002N)rQ   rR   rS   )	rA   r=   r   ZAPPEND_SLASH
startswithendswithr   rM   rP   )r-   regex_patternwarningr   r   r   _check_pattern_startswith_slashz   s    		z-CheckURLMixin._check_pattern_startswith_slashN)r   r+   r2   rP   rY   r   r   r   r   rL   p   s   	rL   c               @   sj   e  Z d  Z e d  Z d d d d  Z d d   Z d d	   Z d
 d   Z d d   Z	 d d   Z
 d S)r8   _regexNFc             C   s1   | |  _  i  |  _ | |  _ | |  _ i  |  _ d  S)N)rZ   rG   _is_endpointrN   r:   )r-   rA   rN   is_endpointr   r   r   r.      s
    				zRegexPattern.__init__c             C   sv   |  j  j |  } | rr | j   } | r0 f  n	 | j   } d d   | j   D } | | j   d   | | f Sd  S)Nc             S   s+   i  |  ]! \ } } | d  k	 r | |  q S)Nr   )r   kvr   r   r   
<dictcomp>   s   	 z&RegexPattern.match.<locals>.<dictcomp>)rA   search	groupdictgroupsitemsend)r-   pathmatchr!   r    r   r   r   rf      s    zRegexPattern.matchc             C   s9   g  } | j  |  j    |  j s5 | j  |  j    | S)N)extendrY   r[   _check_include_trailing_dollar)r-   warningsr   r   r   check   s
    	zRegexPattern.checkc             C   sU   |  j  j } | j d  rM | j d  rM t d j |  j    d d g Sg  Sd  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.rT   z	urls.W001)rA   r=   rV   r   rM   rP   )r-   rW   r   r   r   rh      s    
z+RegexPattern._check_include_trailing_dollarc             C   sV   y t  j |  SWn> t  j k
 rQ } z t d | | f   WYd d } ~ Xn Xd S)z0Compile and return the given regular expression.z*"%s" is not a valid regular expression: %sN)recompileerrorr	   )r-   rA   er   r   r   rE      s
    zRegexPattern._compilec             C   s   t  |  j  S)N)rD   rZ   )r-   r   r   r   __str__   s    zRegexPattern.__str__)r   r+   r2   r?   rA   r.   rf   rj   rh   rE   rp   r   r   r   r   r8      s   	r8   z/<(?:(?P<converter>[^>:]+):)?(?P<parameter>\w+)>Fc       
      C   s  t  |   j t j  s( t d |    |  } d g } i  } x6t j |   } | sl | j t j	 |    P| j t j	 |  d | j
      |  | j   d  }  | j d  } | j   s t d | | f   | j d  } | d k r d } y t |  } Wn; t k
 rG}	 z t d | |	 f   WYd d }	 ~	 Xn X| | | <| j d	 | d
 | j d  q@ W| r| j d  d j |  | 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.	converterrD   z)URL route '%s' uses invalid converter %s.z(?P<>)rk    )set
isdisjointstring
whitespacer	   _PATH_PARAMETER_COMPONENT_REr`   appendrl   escapestartrd   groupisidentifierr   KeyErrorrA   r%   )
r#   r\   Zoriginal_routepartsr:   rf   rr   Zraw_converterrs   ro   r   r   r   _route_to_regex   s<    	&&
$r   c               @   s^   e  Z d  Z e d  Z d d d d  Z d d   Z d d	   Z d
 d   Z d d   Z	 d S)RoutePattern_routeNFc             C   sD   | |  _  i  |  _ | |  _ | |  _ t t |  |  d |  _ d  S)Nr   )r   rG   r[   rN   r   rD   r:   )r-   r#   rN   r\   r   r   r   r.      s
    				zRoutePattern.__init__c             C   s   |  j  j |  } | r | j   } xW | j   D]I \ } } |  j | } y | j |  | | <Wq1 t k
 ry d  SYq1 Xq1 W| | j   d   f  | f Sd  S)N)rA   r`   ra   rc   r:   Z	to_python
ValueErrorrd   )r-   re   rf   r!   keyvaluers   r   r   r   rf      s    zRoutePattern.matchc             C   sk   |  j    } |  j } d | k s? | j d  s? | j d  rg | j t d j |  j    d d  | S)Nz(?P<rq   rk   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().rT   z2_0.W001)rY   r   rU   rV   r|   r   rM   rP   )r-   ri   r#   r   r   r   rj     s    	*	
zRoutePattern.checkc             C   s   t  j t | |  j  d  S)Nr   )rl   rm   r   r[   )r-   r#   r   r   r   rE     s    zRoutePattern._compilec             C   s   t  |  j  S)N)rD   r   )r-   r   r   r   rp     s    zRoutePattern.__str__)
r   r+   r2   r?   rA   r.   rf   rj   rE   rp   r   r   r   r   r      s   r   c               @   ss   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 |  j  S)N)rl   rm   language_prefix)r-   r   r   r   rA   &  s    zLocalePrefixPattern.regexc             C   s;   t    p t j } | t j k r/ |  j r/ d Sd | Sd  S)Nrv   z%s/)r   r   ZLANGUAGE_CODEr   )r-   rJ   r   r   r   r   +  s    z#LocalePrefixPattern.language_prefixc             C   s9   |  j  } | j |  r5 | t |  d   f  i  f Sd  S)N)r   rU   len)r-   re   r   r   r   r   rf   3  s    	zLocalePrefixPattern.matchc             C   s   g  S)Nr   )r-   r   r   r   rj   9  s    zLocalePrefixPattern.checkc             C   s   d j  |   S)Nz'{}')rM   )r-   r   r   r   rP   <  s    zLocalePrefixPattern.describec             C   s   |  j  S)N)r   )r-   r   r   r   rp   ?  s    zLocalePrefixPattern.__str__N)r   r+   r2   r.   propertyrA   r   rf   rj   rP   rp   r   r   r   r   r   !  s   r   c               @   sd   e  Z d  Z d 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_argsrN   )r-   r=   r   r   rN   r   r   r   r.   D  s    		zURLPattern.__init__c             C   s   d |  j  j |  j j   f S)Nz<%s %s>)r*   r   r=   rP   )r-   r   r   r   r1   J  s    zURLPattern.__repr__c             C   s&   |  j    } | j |  j j    | S)N)_check_pattern_namerg   r=   rj   )r-   ri   r   r   r   rj   M  s    zURLPattern.checkc             C   sW   |  j  j d k	 rO d |  j  j k rO t d j |  j  j    d d } | g Sg  Sd 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.rT   z	urls.W003)r=   rN   r   rM   rP   )r-   rX   r   r   r   r   R  s    $	zURLPattern._check_pattern_namec             C   sf   |  j  j |  } | rb | \ } } } | j |  j  t |  j | | |  j  j d t |  j   Sd  S)Nr#   )r=   rf   updater   r   r   rN   rD   )r-   re   rf   new_pathr    r!   r   r   r   resolve`  s
    zURLPattern.resolvec             C   sZ   |  j  } t | t j  r$ | j } t | d  sH | 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   rC   	functoolspartialr   r)   r+   r*   r   r2   )r-   r   r   r   r   
lookup_strh  s    		zURLPattern.lookup_str)
r   r+   r2   r.   r1   rj   r   r   r   r   r   r   r   r   r   C  s   r   c               @   s   e  Z d  Z d d 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)"r7   Nc             C   s|   | |  _  | |  _ d  |  _ | p$ i  |  _ | |  _ | |  _ i  |  _ i  |  _ i  |  _ t	   |  _
 d |  _ t   |  _ d  S)NF)r=   urlconf_namer   default_kwargsr(   r&   _reverse_dict_namespace_dict	_app_dictrw   _callback_strs
_populatedr   _local)r-   r=   r   r   r&   r(   r   r   r   r.   w  s    									zURLResolver.__init__c             C   sp   t  |  j t  r5 |  j r5 d |  j d j j } n t |  j  } d |  j j | |  j |  j |  j j	   f S)Nz	<%s list>r   z<%s %s (%s:%s) %s>)
rC   r   listr*   r   reprr&   r(   r=   rP   )r-   Zurlconf_reprr   r   r   r1     s    zURLResolver.__repr__c             C   sS   g  } x$ |  j  D] } | j t |   q W| j |  j    | pR |  j j   S)N)r;   rg   r   _check_custom_error_handlersr=   rj   )r-   messagesr=   r   r   r   rj     s
    zURLResolver.checkc             C   sc  g  } xVd d d d g D]B\ } } y |  j  |  \ } } Wn t t f k
 r } z[ t |  j d |  } d j d	 | d
 |  } | j t | d t |  d d  w WYd  d  } ~ Xn Xt	 j
 |  }	 d  g | }
 y |	 j |
   Wq t k
 rZd j d	 | d
 | j d | j d | d k r4d n d  } | j t | d d  Yq Xq W| S)N           r   z	handler%szDThe custom handler{status_code} view '{path}' could not be imported.status_codere   ZhintrT   z	urls.E008zeThe custom handler{status_code} view '{path}' does not take the correct number of arguments ({args}).r   r    zrequest, exceptionrequestz	urls.E007)r   r   )r   r   )r   r   )r   r   )resolve_error_handlerImportErrorr
   rB   urlconf_modulerM   r|   r   rD   inspect	signaturebind	TypeErrorr+   r2   )r-   r   r   Znum_parametershandlerZ
param_dictro   re   msgr   r    r   r   r   r     s*    	%	"z(URLResolver._check_custom_error_handlersc             C   s  t  |  j d d  r d  Szd |  j _ t   } i  } i  } t   } xVt |  j  D]E} | j j j } | j	 d  r | d d   } t
 | t  r#|  j j | j  t | j j j  } | j | j | | | j | j j f  | j d  k	 r| j | j | | | j | j j f  qV | j   | j rk| j | j g   j | j  | | f | | j <nx | j D]} } xt | j j |  D]` \ }	 }
 } } t | |
  } | j | | | |
 | | j  |  j j | j j |  f  qWquWxV | j j   D]E \ } \ } } | j j } | j j j |  | | | f | | <qWx6 | j  j   D]% \ } } | j | g   j! |  q_W|  j j | j  qV W| |  j" | <| |  j# | <| |  j$ | <d |  _% Wd  d |  j _ Xd  S)N
populatingFTrq   r   )&rB   r   r   r   r   reversedr;   r=   rA   rU   rC   r   r   addr   r   Z
appendlistr   r   r:   rN   	_populater&   
setdefaultr|   r(   reverse_dictgetlistr   namespace_dictrc   r   app_dictrg   r   r   r   r   )r-   Zlookupsr'   ZappsrJ   Zurl_patternZ	p_patternbitsrN   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   |  j | S)N)r   r   r   )r-   rJ   r   r   r   r     s    	
zURLResolver.reverse_dictc             C   s-   t    } | |  j k r" |  j   |  j | S)N)r   r   r   )r-   rJ   r   r   r   r     s    	
zURLResolver.namespace_dictc             C   s-   t    } | |  j k r" |  j   |  j | S)N)r   r   r   )r-   rJ   r   r   r   r     s    	
zURLResolver.app_dictc             C   s1   |  s
 | S| j  d  r) | d d  } |  | S)z<Join two routes, without the starting ^ in the second route.rq   r   N)rU   )Zroute1Zroute2r   r   r   _join_route  s
    zURLResolver._join_routec             C   s    |  j  s |  j   | |  j k S)N)r   r   r   )r-   rN   r   r   r   _is_callback  s    	
zURLResolver._is_callbackc                s  t  |  } g  } |  j j |  } | r| \ } } } xa|  j D]V  y   j |  } Wnz t k
 r } zZ | j d j d  }	 |	 d  k	 r | j   f d d   |	 D  n | j	   g  WYd  d  } ~ XqC X| r| |  j
  }
 |
 j | j  | j } |
 s| | j } t   t  r/d n t    j  } t | j | |
 | j |  j g | j |  j g | j |  j | | j   S| j	   g  qC Wt d | d | i   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>rv   re   )rD   r=   rf   r;   r   r   r    getrg   r|   r   r   r!   rC   r   r   r   r"   r&   r$   r(   r'   r   r#   )r-   re   r   rf   r   r    r!   Z	sub_matchro   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 Sd  S)N)rC   r   rD   r   )r-   r   r   r   r   B  s    zURLResolver.urlconf_modulec             C   s`   t  |  j d |  j  } y t |  Wn3 t k
 r[ d } t | j d |  j    Yn 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.rN   )rB   r   iterr   r	   rM   r   )r-   patternsr   r   r   r   r;   I  s     zURLResolver.url_patternsc             C   sR   t  |  j d | d   } | sB d d l m } t  | d |  } t |  i  f S)Nz	handler%sr   )urls)rB   r   django.confr   r   )r-   Z	view_typer   r   r   r   r   r   X  s
    z!URLResolver.resolve_error_handlerc             O   s   |  j  | d | |  S)Nrv   )_reverse_with_prefix)r-   lookup_viewr    r!   r   r   r   reversea  s    zURLResolver.reversec                s  | r   r t  d   |  j s+ |  j   |  j j |  } xu| D]m\ } } } }	 xX| D]P\ }
 } | r t |  t |  k r q] t t | |   } nO t    j	 |  j
 |  r q] t   f d d   | j   D  r q]   } i  } xP | j   D]B \ } } | |	 k r6|	 | j |  | | <qt |  | | <qW| j d d  |
 } t j d t j |  | f | |  r] t | | d t d } t |  Sq] WqD Wt | d	 d   } t | d
 d   } | d  k	 r| d  k	 rd | | f } n | } d d   | D } | rt| r9d | f } n   rOd   f } 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-   |  ]# \ } }   j  | |  | k Vq d  S)N)r   )r   r]   r^   )r!   r   r   r   v  s    z3URLResolver._reverse_with_prefix.<locals>.<genexpr>%z%%z^%s%ssafez/~:@r+   r   z%s.%sc             S   s"   g  |  ] \ } } } } |  q Sr   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   r9   ziprw   symmetric_difference
differenceanyrc   Zto_urlrD   replacerl   r`   r}   r   r   r   rB   r   )r-   r   _prefixr    r!   possibilitiesZpossibilityr=   r   r:   resultparamsZcandidate_subsZtext_candidate_subsr]   r^   Zcandidate_paturlmnZlookup_view_sr   Zarg_msgr   r   )r!   r   r   d  sT    	
%)z URLResolver._reverse_with_prefix)r   r+   r2   r.   r1   rj   r   r   r   r   r   r   staticmethodr   r   r   r   r   r;   r   r   r   r   r   r   r   r7   v  s    =	(	r7   )6__doc__r   r   rl   ry   	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   Zdjango.utils.translationr   r:   r   
exceptionsr   r   utilsr   r   r5   	lru_cacher3   r>   r?   rL   r8   rm   r{   r   r   r   r   r7   r   r   r   r   <module>   sD   #!6	*+"3