
    Mh3b                     >   d 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 ddlmZ ddlmZmZmZmZ dd	lmZmZmZmZmZmZmZmZmZmZ  G d
 dej                  Z G d de          Z  G d dej!                  Z" G d dej!                  Z#eedee         eee$df         ef         eee$df         eee$ef         f         eee$df         eee$ef         e$f         f                  Z% G d de          Z& G d de e&          Z' G d d          Z( G d d          Z) G d de)          Z* G d de)          Z+ G d de)          Z, G d  d!e)          Z- G d" d#e(          Z.ed$e$d%e/fd&            Z0ed)d'            Z0d$ee$         d%ee/         fd(Z0dS )*ap  Flexible routing implementation.

Tornado routes HTTP requests to appropriate handlers using `Router`
class implementations. The `tornado.web.Application` class is a
`Router` implementation and may be used directly, or the classes in
this module may be used for additional flexibility. The `RuleRouter`
class can match on more criteria than `.Application`, or the `Router`
interface can be subclassed for maximum customization.

`Router` interface extends `~.httputil.HTTPServerConnectionDelegate`
to provide additional routing capabilities. This also means that any
`Router` implementation can be used directly as a ``request_callback``
for `~.httpserver.HTTPServer` constructor.

`Router` subclass must implement a ``find_handler`` method to provide
a suitable `~.httputil.HTTPMessageDelegate` instance to handle the
request:

.. code-block:: python

    class CustomRouter(Router):
        def find_handler(self, request, **kwargs):
            # some routing logic providing a suitable HTTPMessageDelegate instance
            return MessageDelegate(request.connection)

    class MessageDelegate(HTTPMessageDelegate):
        def __init__(self, connection):
            self.connection = connection

        def finish(self):
            self.connection.write_headers(
                ResponseStartLine("HTTP/1.1", 200, "OK"),
                HTTPHeaders({"Content-Length": "2"}),
                b"OK")
            self.connection.finish()

    router = CustomRouter()
    server = HTTPServer(router)

The main responsibility of `Router` implementation is to provide a
mapping from a request to `~.httputil.HTTPMessageDelegate` instance
that will handle this request. In the example above we can see that
routing is possible even without instantiating an `~.web.Application`.

For routing to `~.web.RequestHandler` implementations we need an
`~.web.Application` instance. `~.web.Application.get_handler_delegate`
provides a convenient way to create `~.httputil.HTTPMessageDelegate`
for a given request and `~.web.RequestHandler`.

Here is a simple example of how we can we route to
`~.web.RequestHandler` subclasses by HTTP method:

.. code-block:: python

    resources = {}

    class GetResource(RequestHandler):
        def get(self, path):
            if path not in resources:
                raise HTTPError(404)

            self.finish(resources[path])

    class PostResource(RequestHandler):
        def post(self, path):
            resources[path] = self.request.body

    class HTTPMethodRouter(Router):
        def __init__(self, app):
            self.app = app

        def find_handler(self, request, **kwargs):
            handler = GetResource if request.method == "GET" else PostResource
            return self.app.get_handler_delegate(request, handler, path_args=[request.path])

    router = HTTPMethodRouter(Application())
    server = HTTPServer(router)

`ReversibleRouter` interface adds the ability to distinguish between
the routes and reverse them to the original urls using route's name
and additional arguments. `~.web.Application` is itself an
implementation of `ReversibleRouter` class.

`RuleRouter` and `ReversibleRuleRouter` are implementations of
`Router` and `ReversibleRouter` interfaces and can be used for
creating rule-based routing configurations.

Rules are instances of `Rule` class. They contain a `Matcher`, which
provides the logic for determining whether the rule is a match for a
particular request and a target, which can be one of the following.

1) An instance of `~.httputil.HTTPServerConnectionDelegate`:

.. code-block:: python

    router = RuleRouter([
        Rule(PathMatches("/handler"), ConnectionDelegate()),
        # ... more rules
    ])

    class ConnectionDelegate(HTTPServerConnectionDelegate):
        def start_request(self, server_conn, request_conn):
            return MessageDelegate(request_conn)

2) A callable accepting a single argument of `~.httputil.HTTPServerRequest` type:

.. code-block:: python

    router = RuleRouter([
        Rule(PathMatches("/callable"), request_callable)
    ])

    def request_callable(request):
        request.write(b"HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nOK")
        request.finish()

3) Another `Router` instance:

.. code-block:: python

    router = RuleRouter([
        Rule(PathMatches("/router.*"), CustomRouter())
    ])

Of course a nested `RuleRouter` or a `~.web.Application` is allowed:

.. code-block:: python

    router = RuleRouter([
        Rule(HostMatches("example.com"), RuleRouter([
            Rule(PathMatches("/app1/.*"), Application([(r"/app1/handler", Handler)])),
        ]))
    ])

    server = HTTPServer(router)

In the example below `RuleRouter` is used to route between applications:

.. code-block:: python

    app1 = Application([
        (r"/app1/handler", Handler1),
        # other handlers ...
    ])

    app2 = Application([
        (r"/app2/handler", Handler2),
        # other handlers ...
    ])

    router = RuleRouter([
        Rule(PathMatches("/app1.*"), app1),
        Rule(PathMatches("/app2.*"), app2)
    ])

    server = HTTPServer(router)

For more information on application-level routing see docs for `~.web.Application`.

.. versionadded:: 4.5

    N)partial)httputil)_CallableAdapter)
url_escapeurl_unescapeutf8)app_log)basestring_typeimport_objectre_unescapeunicode_type)
AnyUnionOptional	AwaitableListDictPatternTupleoverloadSequencec                   n    e Zd ZdZdej        dedeej                 fdZ	de
dej        dej        fdZd	S )
RouterzAbstract router interface.requestkwargsreturnc                     t                      )a  Must be implemented to return an appropriate instance of `~.httputil.HTTPMessageDelegate`
        that can serve the request.
        Routing implementations may pass additional kwargs to extend the routing logic.

        :arg httputil.HTTPServerRequest request: current HTTP request.
        :arg kwargs: additional keyword arguments passed by routing implementation.
        :returns: an instance of `~.httputil.HTTPMessageDelegate` that will be used to
            process the request.
        NotImplementedError)selfr   r   s      O/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/tornado/routing.pyfind_handlerzRouter.find_handler   s     "###    server_connrequest_connc                 $    t          | ||          S N)_RoutingDelegate)r    r$   r%   s      r!   start_requestzRouter.start_request   s      k<@@@r#   N)__name__
__module____qualname____doc__r   HTTPServerRequestr   r   HTTPMessageDelegater"   objectHTTPConnectionr)    r#   r!   r   r      s        $$$1$=@$	(.	/$ $ $ $A!A191HA		%A A A A A Ar#   r   c                   2    e Zd ZdZdededee         fdZdS )ReversibleRouterzxAbstract router interface for routers that can handle named routes
    and support reversing them to original urls.
    nameargsr   c                     t                      )a  Returns url string for a given route name and arguments
        or ``None`` if no match is found.

        :arg str name: route name.
        :arg args: url parameters.
        :returns: parametrized url string for a given route name (or ``None``).
        r   )r    r5   r6   s      r!   reverse_urlzReversibleRouter.reverse_url   s     "###r#   N)r*   r+   r,   r-   strr   r   r8   r2   r#   r!   r4   r4      sK         $ $C $HSM $ $ $ $ $ $r#   r4   c                       e Zd Zdededej        ddfdZdeej	        ej
        f         dej        deed                  fd	Zd
edeed                  fdZddZddZdS )r(   routerr$   r%   r   Nc                 >    || _         || _        d | _        || _        d S r'   )r$   r%   delegater;   )r    r;   r$   r%   s       r!   __init__z_RoutingDelegate.__init__   s&     '(r#   
start_lineheadersc                 r   t          |t          j                  sJ t          j        | j        | j        ||          }| j                            |          | _        | j        9t          j
        d|j        |j                   t          | j                  | _        | j                            ||          S )N)
connectionserver_connectionr?   r@   z$Delegate for %s %s request not found)
isinstancer   RequestStartLiner.   r%   r$   r;   r"   r=   r	   debugmethodpath_DefaultMessageDelegateheaders_received)r    r?   r@   r   s       r!   rJ   z!_RoutingDelegate.headers_received   s    
 *h&?@@@@@,(".!	
 
 
 0099= M6!  
 4D4EFFDM}--j'BBBr#   chunkc                 H    | j         J | j                             |          S r'   )r=   data_received)r    rK   s     r!   rM   z_RoutingDelegate.data_received  s&    }(((}**5111r#   c                 J    | j         J | j                                          d S r'   )r=   finishr    s    r!   rO   z_RoutingDelegate.finish  s*    }(((r#   c                 J    | j         J | j                                          d S r'   )r=   on_connection_closerP   s    r!   rR   z$_RoutingDelegate.on_connection_close  s*    }((())+++++r#   r   N)r*   r+   r,   r   r0   r   r1   r>   r   rE   ResponseStartLineHTTPHeadersr   r   rJ   bytesrM   rO   rR   r2   r#   r!   r(   r(      s        +1AIAX	   C(3X5OOPC %C 
)D/	"	C C C C025 2Xio-F 2 2 2 2   , , , , , ,r#   r(   c                   0    e Zd Zdej        ddfdZddZdS )rI   rB   r   Nc                     || _         d S r'   )rB   )r    rB   s     r!   r>   z _DefaultMessageDelegate.__init__  s    $r#   c                     | j                             t          j        ddd          t          j                               | j                                          d S )NzHTTP/1.1i  z	Not Found)rB   write_headersr   rT   rU   rO   rP   s    r!   rO   z_DefaultMessageDelegate.finish"  sV    %%&z3DD ""	
 	
 	
 	     r#   rS   )r*   r+   r,   r   r1   r>   rO   r2   r#   r!   rI   rI     sM        %8#: %t % % % %! ! ! ! ! !r#   rI   RuleMatcherc            	           e Zd ZdZddee         ddfdZdeddfdZdd	Zd
e	j
        dedee	j                 fdZded
e	j
        dedee	j                 fdZdS )
RuleRouterz!Rule-based router implementation.Nrulesr   c                 F    g | _         |r|                     |           dS dS )aI  Constructs a router from an ordered list of rules::

            RuleRouter([
                Rule(PathMatches("/handler"), Target),
                # ... more rules
            ])

        You can also omit explicit `Rule` constructor and use tuples of arguments::

            RuleRouter([
                (PathMatches("/handler"), Target),
            ])

        `PathMatches` is a default matcher, so the example above can be simplified::

            RuleRouter([
                ("/handler", Target),
            ])

        In the examples above, ``Target`` can be a nested `Router` instance, an instance of
        `~.httputil.HTTPServerConnectionDelegate` or an old-style callable,
        accepting a request argument.

        :arg rules: a list of `Rule` instances or tuples of `Rule`
            constructor arguments.
        N)r_   	add_rules)r    r_   s     r!   r>   zRuleRouter.__init__:  s5    6 
 	"NN5!!!!!	" 	"r#   c                 b   |D ]}t          |t          t          f          r`t          |          dv sJ t          |d         t                    r)t          t          |d                   g|dd         R  }n	t          | }| j                            | 	                    |                     dS )zAppends new rules to the router.

        :arg rules: a list of Rule instances (or tuples of arguments, which are
            passed to Rule constructor).
        )         r      N)
rD   tuplelistlenr
   r[   PathMatchesr_   appendprocess_rule)r    r_   rules      r!   ra   zRuleRouter.add_rulesY  s      	7 	7D$.. '4yyI----d1g77 'DG 4 4@tABBx@@@DD;DJd//556666	7 	7r#   rm   r[   c                     |S )zOverride this method for additional preprocessing of each rule.

        :arg Rule rule: a rule to be processed.
        :returns: the same or modified Rule instance.
        r2   )r    rm   s     r!   rl   zRuleRouter.process_rulei  s	     r#   r   r   c                     | j         D ]I}|j                            |          }|+|j        r
|j        |d<    | j        |j        |fi |}||c S Jd S )Ntarget_kwargs)r_   matchermatchrp   get_target_delegatetarget)r    r   r   rm   target_paramsr=   s         r!   r"   zRuleRouter.find_handlerq  s     J 	$ 	$D L..w77M(% H595GM/2343K ,9  '#OOOtr#   rt   ru   c                 B   t          |t                    r |j        |fi |S t          |t          j                  r)|j        J |                    |j        |j                  S t          |          r)|j        J t          t          |fi ||j                  S dS )a  Returns an instance of `~.httputil.HTTPMessageDelegate` for a
        Rule's target. This method is called by `~.find_handler` and can be
        extended to provide additional target types.

        :arg target: a Rule's target.
        :arg httputil.HTTPServerRequest request: current request.
        :arg target_params: additional parameters that can be useful
            for `~.httputil.HTTPMessageDelegate` creation.
        N)rD   r   r"   r   HTTPServerConnectionDelegaterB   r)   rC   callabler   r   )r    rt   r   ru   s       r!   rs   zRuleRouter.get_target_delegate  s     ff%% 	&6&w@@-@@@ EFF 	%111''(A7CUVVVf 	%111#00-00'2D   tr#   r'   rm   r[   r   r[   )r*   r+   r,   r-   r   	_RuleListr>   ra   rl   r   r.   r   r/   r"   rs   r2   r#   r!   r^   r^   7  s        ++" "hy1 "T " " " ">7y 7T 7 7 7 7    1=@	(.	/   $$,$>QT	(.	/     r#   r^   c                   f     e Zd ZdZddee         ddf fdZd fdZd	ed
e	dee         fdZ
 xZS )ReversibleRuleRoutera  A rule-based router that implements ``reverse_url`` method.

    Each rule added to this router may have a ``name`` attribute that can be
    used to reconstruct an original uri. The actual reconstruction takes place
    in a rule's matcher (see `Matcher.reverse`).
    Nr_   r   c                 X    i | _         t                                          |           d S r'   )named_rulessuperr>   )r    r_   	__class__s     r!   r>   zReversibleRuleRouter.__init__  s)    r#   rm   r[   c                     t                                          |          }|j        r7|j        | j        v rt	          j        d|j                   || j        |j        <   |S )Nz4Multiple handlers named %s; replacing previous value)r   rl   r5   r~   r	   warning)r    rm   r   s     r!   rl   z!ReversibleRuleRouter.process_rule  se    ww##D))9 	/yD,,,JDI   +/DTY'r#   r5   r6   c                     || j         v r | j         |         j        j        | S | j        D ]5}t	          |j        t                    r |j        j        |g|R  }||c S 6d S r'   )r~   rq   reverser_   rD   rt   r4   r8   )r    r5   r6   rm   reversed_urls        r!   r8   z ReversibleRuleRouter.reverse_url  s    4###94#D)194@@J 	( 	(D$+'788 (6t{6tCdCCC+''''tr#   r'   ry   )r*   r+   r,   r-   r   rz   r>   rl   r9   r   r8   __classcell__r   s   @r!   r|   r|     s            hy1  T            
 
 
 
 
 

 
C 
HSM 
 
 
 
 
 
 
 
r#   r|   c                       e Zd ZdZ	 	 ddddedeeeef                  dee         ddf
d	Zd
edee         fdZ	defdZ
dS )r[   zA routing rule.Nrq   r\   rt   rp   r5   r   c                     t          |t                    rt          |          }|| _        || _        |r|ni | _        || _        dS )ad  Constructs a Rule instance.

        :arg Matcher matcher: a `Matcher` instance used for determining
            whether the rule should be considered a match for a specific
            request.
        :arg target: a Rule's target (typically a ``RequestHandler`` or
            `~.httputil.HTTPServerConnectionDelegate` subclass or even a nested `Router`,
            depending on routing implementation).
        :arg dict target_kwargs: a dict of parameters that can be useful
            at the moment of target instantiation (for example, ``status_code``
            for a ``RequestHandler`` subclass). They end up in
            ``target_params['target_kwargs']`` of `RuleRouter.get_target_delegate`
            method.
        :arg str name: the name of the rule that can be used to find it
            in `ReversibleRouter.reverse_url` implementation.
        N)rD   r9   r   rq   rt   rp   r5   )r    rq   rt   rp   r5   s        r!   r>   zRule.__init__  sO    . fc"" 	+ #6**F.;C]]			r#   r6   c                       | j         j        | S r'   )rq   r   r    r6   s     r!   r   zRule.reverse  s    #t|#T**r#   c                 p    d                     | j        j        | j        | j        | j        | j                  S Nz${}({!r}, {}, kwargs={!r}, name={!r}))formatr   r*   rq   rt   rp   r5   rP   s    r!   __repr__zRule.__repr__  s7    5<<N#LKI
 
 	
r#   NN)r*   r+   r,   r-   r   r   r   r9   r>   r   r   r2   r#   r!   r[   r[     s         37"    S#X/	
 sm 
   B+S +Xc] + + + +
# 
 
 
 
 
 
r#   c                   d    e Zd ZdZdej        deeee	f                  fdZ
de	dee         fdZdS )r\   z*Represents a matcher for request features.r   r   c                     t                      )a1  Matches current instance against the request.

        :arg httputil.HTTPServerRequest request: current HTTP request
        :returns: a dict of parameters to be passed to the target handler
            (for example, ``handler_kwargs``, ``path_args``, ``path_kwargs``
            can be passed for proper `~.web.RequestHandler` instantiation).
            An empty dict is a valid (and common) return value to indicate a match
            when the argument-passing features are not used.
            ``None`` must be returned to indicate that there is no match.r   r    r   s     r!   rr   zMatcher.match  s     "###r#   r6   c                     dS )zEReconstructs full url from matcher instance and additional arguments.Nr2   r   s     r!   r   zMatcher.reverse  s    tr#   N)r*   r+   r,   r-   r   r.   r   r   r9   r   rr   r   r2   r#   r!   r\   r\     sr        44
$X7 
$HT#s(^<T 
$ 
$ 
$ 
$S Xc]      r#   c                   H    e Zd ZdZdej        deeee	f                  fdZ
dS )
AnyMatcheszMatches any request.r   r   c                     i S r'   r2   r   s     r!   rr   zAnyMatches.match  s    	r#   N)r*   r+   r,   r-   r   r.   r   r   r9   r   rr   r2   r#   r!   r   r   	  sL        X7 HT#s(^<T      r#   r   c                   h    e Zd ZdZdeeef         ddfdZdej	        de
eeef                  fdZdS )HostMatchesz@Matches requests from hosts specified by ``host_pattern`` regex.host_patternr   Nc                     t          |t                    r5|                    d          s|dz  }t          j        |          | _        d S || _        d S )N$)rD   r
   endswithrecompiler   )r    r   s     r!   r>   zHostMatches.__init__  sZ    lO44 	-((-- $# "
< 8 8D ,Dr#   r   c                 H    | j                             |j                  ri S d S r'   )r   rr   	host_namer   s     r!   rr   zHostMatches.match  s(    ""7#455 	Itr#   )r*   r+   r,   r-   r   r9   r   r>   r   r.   r   r   r   rr   r2   r#   r!   r   r     sw        JJ-U3<%8 -T - - - -X7 HT#s(^<T      r#   r   c                   \    e Zd ZdZdededdfdZdej        de	e
eef                  fdZdS )	DefaultHostMatcheszMatches requests from host that is equal to application's default_host.
    Always returns no match if ``X-Real-Ip`` header is present.
    applicationr   r   Nc                 "    || _         || _        d S r'   )r   r   )r    r   r   s      r!   r>   zDefaultHostMatches.__init__'  s    &(r#   r   c                 d    d|j         vr&| j                            | j        j                  ri S d S )Nz	X-Real-Ip)r@   r   rr   r   default_hostr   s     r!   rr   zDefaultHostMatches.match+  s8    go-- &&t'7'DEE 	tr#   )r*   r+   r,   r-   r   r   r>   r   r.   r   r   r9   rr   r2   r#   r!   r   r   "  sy         )C )w )4 ) ) ) )X7 HT#s(^<T      r#   r   c                       e Zd ZdZdeeef         ddfdZdej	        de
eeef                  fdZdede
e         fd	Zdee
e         e
e         f         fd
ZdS )rj   z@Matches requests with paths specified by ``path_pattern`` regex.path_patternr   Nc                 d   t          |t                    r4|                    d          s|dz  }t          j        |          | _        n|| _        t          | j        j                  d| j        j        fv sJ d| j        j	        z              | 
                                \  | _        | _        d S )Nr   r   zDgroups in url regexes must either be all named or all positional: %r)rD   r
   r   r   r   regexri   
groupindexgroupspattern_find_groups_path_group_count)r    r   s     r!   r>   zPathMatches.__init__6  s    lO44 	&((-- $#L11DJJ%DJ4:())a1B-CCCC#z12 DCC
 )-(9(9(;(;%
D%%%r#   r   c                 D   | j                             |j                  }|d S | j         j        si S g }i }| j         j        r1d |                                                                D             }nd |                                D             }t          ||          S )Nc                 N    i | ]"\  }}t          |          t          |          #S r2   )r9   _unquote_or_none).0kvs      r!   
<dictcomp>z%PathMatches.match.<locals>.<dictcomp>T  s:       06AA(++  r#   c                 ,    g | ]}t          |          S r2   )r   )r   ss     r!   
<listcomp>z%PathMatches.match.<locals>.<listcomp>X  s!    EEE)!,,EEEr#   )	path_argspath_kwargs)r   rr   rH   r   r   	groupdictitemsdict)r    r   rr   r   r   s        r!   rr   zPathMatches.matchE  s    
  ..=4z  	I	 :  	F :?//:K:K:Q:Q:S:S  KK FEellnnEEEIi[AAAAr#   r6   c                    | j         t          d| j        j        z             t	          |          | j        k    s
J d            t	          |          s| j         S g }|D ]^}t          |t          t          f          st          |          }|
                    t          t          |          d                     _| j         t          |          z  S )NzCannot reverse url regex z&required number of arguments not foundF)plus)r   
ValueErrorr   r   ri   r   rD   r   rV   r9   rk   r   r   rg   )r    r6   converted_argsas       r!   r   zPathMatches.reverse\  s    :84:;MMNNN4yyD----7 .-- 4yy 	: 	C 	CAa,!677 FF!!*T!WW5"A"A"ABBBBzE.1111r#   c                    | j         j        }|                    d          r
|dd         }|                    d          r
|dd         }| j         j        |                    d          k    rdS g }|                    d          D ]}d|v rb|                    d          }|d	k    rF	 t          ||dz   d                   }n# t          $ r Y  dS w xY w|
                    d
|z              h	 t          |          }n# t          $ r Y  dS w xY w|
                    |           d                    |          | j         j        fS )zReturns a tuple (reverse string, group count) for a url.

        For example: Given the url pattern /([0-9]{4})/([a-z-]+)/, this method
        would return ('/%s/%s/', 2).
        ^rf   Nr   (r   )r   z%s )r   r   
startswithr   r   countsplitindexr   r   rk   join)r    r   piecesfragment	paren_locunescaped_fragments         r!   r   zPathMatches._find_groupsk  s    *$c"" 	"abbkGC   	#crclG:c 2 222 :c** 	2 	2Hh$NN3//	>>,-8)a-//9R-S-S**% , , ,  ,|||, MM$);";<<<()4X)>)>&&! ( ( ( (<<<( 01111wwv
 111s$   )C
CC0D  
DD)r*   r+   r,   r-   r   r9   r   r>   r   r.   r   r   r   rr   r   r   intr   r2   r#   r!   rj   rj   3  s        JJ<U3<%8 <T < < < <BX7 BHT#s(^<T B B B B.2S 2Xc] 2 2 2 2&2eHSM8C=$@A &2 &2 &2 &2 &2 &2r#   rj   c                        e Zd ZdZ	 	 d
deeef         dedee	eef                  dee         ddf
 fdZ
defd	Z xZS )URLSpeczSpecifies mappings between URLs and handlers.

    .. versionchanged: 4.5
       `URLSpec` is now a subclass of a `Rule` with `PathMatches` matcher and is preserved for
       backwards compatibility.
    Nr   handlerr   r5   r   c                     t          |          }t                                          ||||           |j        | _        | j        | _        || _        dS )a  Parameters:

        * ``pattern``: Regular expression to be matched. Any capturing
          groups in the regex will be passed in to the handler's
          get/post/etc methods as arguments (by keyword if named, by
          position if unnamed. Named and unnamed capturing groups
          may not be mixed in the same rule).

        * ``handler``: `~.web.RequestHandler` subclass to be invoked.

        * ``kwargs`` (optional): A dictionary of additional arguments
          to be passed to the handler's constructor.

        * ``name`` (optional): A name for this handler.  Used by
          `~.web.Application.reverse_url`.

        N)rj   r   r>   r   rt   handler_classr   )r    r   r   r   r5   rq   r   s         r!   r>   zURLSpec.__init__  sN    0 g&&'64888]
![r#   c                 z    d                     | j        j        | j        j        | j        | j        | j                  S r   )r   r   r*   r   r   r   r   r5   rP   s    r!   r   zURLSpec.__repr__  s:    5<<N#JKI
 
 	
r#   r   )r*   r+   r,   r-   r   r9   r   r   r   r   r>   r   r   r   s   @r!   r   r     s          ,0" sG|$  c3h(	
 sm 
     >
# 
 
 
 
 
 
 
 
r#   r   r   r   c                     d S r'   r2   r   s    r!   r   r         Dr#   c                     d S r'   r2   r   s    r!   r   r     r   r#   c                 .    | | S t          | dd          S )zNone-safe wrapper around url_unescape to handle unmatched optional
    groups correctly.

    Note that args are passed as bytes so the handler can decide what
    encoding to use.
    NF)encodingr   )r   r   s    r!   r   r     s#     	yDu5555r#   )r   Nr   N)1r-   r   	functoolsr   tornador   tornado.httpserverr   tornado.escaper   r   r   tornado.logr	   tornado.utilr
   r   r   r   typingr   r   r   r   r   r   r   r   r   r   rw   r   r4   r/   r(   rI   r9   rz   r^   r|   r[   r\   r   r   r   rj   r   rV   r   r2   r#   r!   <module>r      se  a aF 
			             / / / / / / 9 9 9 9 9 9 9 9 9 9       R R R R R R R R R R R R                       A A A A AX2 A A A.$ $ $ $ $v $ $ $ +, +, +, +, +,x3 +, +, +,\	! 	! 	! 	! 	!h: 	! 	! 	! 	S	eCN#S()eCN#S$sCx.89eCN#S$sCx.#=>		@	e e e e e e e eP" " " " "+Z " " "J.
 .
 .
 .
 .
 .
 .
 .
b       (           '   $       "^2 ^2 ^2 ^2 ^2' ^2 ^2 ^2B.
 .
 .
 .
 .
d .
 .
 .
b 
	 	 	 	 	 
	 
	 	 	 
		6 	6(5/ 	6 	6 	6 	6 	6 	6r#   