
    2 fa                     >   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  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e'          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- 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overloadc                   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      E/var/www/equiseq/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   r4   r5   s      r    reverse_urlzReversibleRouter.reverse_url   s     "###r"   N)r)   r*   r+   r,   strr   r   r7   r1   r"   r    r3   r3      sK         $ $C $HSM $ $ $ $ $ $r"   r3   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    rI   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   rJ   s     r    rL   z_RoutingDelegate.data_received  s&    }(((}**5111r"   c                 J    | j         J | j                                          d S r&   )r<   finishr   s    r    rN   z_RoutingDelegate.finish
  s*    }(((r"   c                 J    | j         J | j                                          d S r&   )r<   on_connection_closerO   s    r    rQ   z$_RoutingDelegate.on_connection_close  s*    }((())+++++r"   r   N)r)   r*   r+   r   r/   r   r0   r=   r   rD   ResponseStartLineHTTPHeadersr   r   rI   bytesrL   rN   rQ   r1   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 )rH   rA   r   Nc                     || _         d S r&   )rA   )r   rA   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)rA   write_headersr   rS   rT   rN   rO   s    r    rN   z_DefaultMessageDelegate.finish  sV    %%&z3DD ""	
 	
 	
 	     r"   rR   )r)   r*   r+   r   r0   r=   rN   r1   r"   r    rH   rH     sM        %8#: %t % % % %! ! ! ! ! !r"   rH   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)
rC   tuplelistlenr
   rZ   PathMatchesr^   appendprocess_rule)r   r^   rules      r    r`   zRuleRouter.add_rulesN  s      	7 	7D$.. '4yyI----d1g77 'DG 4 4@tABBx@@@DD;DJd//556666	7 	7r"   rl   rZ   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.
        r1   )r   rl   s     r    rk   zRuleRouter.process_rule^  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matchro   get_target_delegatetarget)r   r   r   rl   target_paramsr<   s         r    r!   zRuleRouter.find_handlerf  s     J 	$ 	$D L..w77M(% H595GM/2343K ,9  '#OOOtr"   rs   rt   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)rC   r   r!   r   HTTPServerConnectionDelegaterA   r(   rB   callabler   r   )r   rs   r   rt   s       r    rr   zRuleRouter.get_target_delegatex  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&   rl   rZ   r   rZ   )r)   r*   r+   r,   r   	_RuleListr=   r`   rk   r   r-   r   r.   r!   rr   r1   r"   r    r]   r]   ,  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"   rl   rZ   c                     t                                          |          }|j        r7|j        | j        v rt	          j        d|j                   || j        |j        <   |S )Nz4Multiple handlers named %s; replacing previous value)r~   rk   r4   r}   r	   warning)r   rl   r   s     r    rk   z!ReversibleRuleRouter.process_rule  se    ww##D))9 	/yD,,,JDI   +/DTY'r"   r4   r5   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}   rp   reverser^   rC   rs   r3   r7   )r   r4   r5   rl   reversed_urls        r    r7   z ReversibleRuleRouter.reverse_url  s    4###94#D)194@@J 	( 	(D$+'788 (6t{6tCdCCC+''''tr"   r&   rx   )r)   r*   r+   r,   r   ry   r=   rk   r8   r   r7   __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 )rZ   zA routing rule.Nrp   r[   rs   ro   r4   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)rC   r8   r   rp   rs   ro   r4   )r   rp   rs   ro   r4   s        r    r=   zRule.__init__  sO    . fc"" 	+ #6**F.;C]]			r"   r5   c                       | j         j        | S r&   )rp   r   r   r5   s     r    r   zRule.reverse  s    #t|#T**r"   c           
      `    | j         j        d| j        d| j        d| j        d| j        d
S N(z, z	, kwargs=z, name=))r   r)   rp   rs   ro   r4   rO   s    r    __repr__zRule.__repr__  sA    N###LLLKKKIII
 	
r"   NN)r)   r*   r+   r,   r   r   r   r8   r=   r   r   r1   r"   r    rZ   rZ     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    rq   zMatcher.match  s     "###r"   r5   c                     dS )zEReconstructs full url from matcher instance and additional arguments.Nr1   r   s     r    r   zMatcher.reverse  s    tr"   N)r)   r*   r+   r,   r   r-   r   r   r8   r   rq   r   r1   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&   r1   r   s     r    rq   zAnyMatches.match  s    	r"   N)r)   r*   r+   r,   r   r-   r   r   r8   r   rq   r1   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$)rC   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   rq   	host_namer   s     r    rq   zHostMatches.match  s(    ""7#455 	Itr"   )r)   r*   r+   r,   r   r8   r   r=   r   r-   r   r   r   rq   r1   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   rq   r   default_hostr   s     r    rq   zDefaultHostMatches.match   s8    go-- &&t'7'DEE 	tr"   )r)   r*   r+   r,   r   r   r=   r   r-   r   r   r8   rq   r1   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 )ri   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)rC   r
   r   r   r   regexrh   
groupindexgroupspattern_find_groups_path_group_count)r   r   s     r    r=   zPathMatches.__init__+  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                 ^   | j                             |j                  }|d S | j         j        si S g }i }| j         j        r>t          d |                                                                D                       }nd |                                D             }t          ||          S )Nc              3   X   K   | ]%\  }}t          |          t          |          fV  &d S r&   )r8   _unquote_or_none).0kvs      r    	<genexpr>z$PathMatches.match.<locals>.<genexpr>I  sK        281aQ)!,,-     r"   c                 ,    g | ]}t          |          S r1   )r   )r   ss     r    
<listcomp>z%PathMatches.match.<locals>.<listcomp>M  s!    EEE)!,,EEEr"   )	path_argspath_kwargs)r   rq   rG   r   r   dict	groupdictitems)r   r   rq   r   r   s        r    rq   zPathMatches.match:  s    
  ..=4z  	I	 :  	F  <AOO<M<M<S<S<U<U    KK FEellnnEEEIi[AAAAr"   r5   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   rh   r   rC   r   rU   r8   rj   r   r   rf   )r   r5   converted_argsas       r    r   zPathMatches.reverseQ  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).
        ^re   Nr   r   r   r   r   z%s )r   r   
startswithr   r   countsplitindexr   r   rj   join)r   r   piecesfragment	paren_locunescaped_fragments         r    r   zPathMatches._find_groups`  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   r8   r   r=   r   r-   r   r   r   rq   r   r   intr   r1   r"   r    ri   ri   (  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"   ri   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   r4   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)ri   r~   r=   r   rs   handler_classr   )r   r   r   r   r4   rp   r   s         r    r=   zURLSpec.__init__  sN    0 g&&'64888]
![r"   c           
      j    | j         j        d| j        j        d| j        d| j        d| j        d
S r   )r   r)   r   r   r   r   r4   rO   s    r    r   zURLSpec.__repr__  sF    N###JKKKIII
 	
r"   r   )r)   r*   r+   r,   r   r8   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&   r1   r   s    r    r   r         Dr"   c                     d S r&   r1   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   rv   r   r3   r.   r'   rH   r8   ry   r]   r{   r/   rZ   r[   r   r   r   ri   r   rU   r   r1   r"   r    <module>r      s3  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 X X X X X X X X X X X X X X X X X X X X X X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.
 .
 .
 .
 .
6 .
 .
 .
b    f   (           '   $       "^2 ^2 ^2 ^2 ^2' ^2 ^2 ^2B.
 .
 .
 .
 .
d .
 .
 .
b 
	 	 	 	 	 
	 
	 	 	 
		6 	6(5/ 	6 	6 	6 	6 	6 	6r"   