o
    Qœ_úa  ã                   @   s  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„ dejƒZG dd„ deƒZG dd„ dej ƒZ!G d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„ deƒZ%G dd„ dee%ƒZ&G dd„ de'ƒZ(G dd„ de'ƒZ)G dd„ de)ƒZ*G dd„ de)ƒZ+G dd„ de)ƒZ,G d d!„ d!e)ƒZ-G d"d#„ d#e(ƒZ.ed$e#d%e/fd&d'„ƒZ0ed*d(d'„ƒZ0d$ee# d%ee/ fd)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                   @   sH   e Zd ZdZdejdedeej fdd„Z	de
dejdejfd	d
„ZdS )ÚRouterzAbstract router interface.ÚrequestÚkwargsÚreturnc                 K   ó   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   © r   ú1/usr/lib/python3/dist-packages/tornado/routing.pyÚfind_handlerÁ   s   zRouter.find_handlerÚserver_connÚrequest_connc                 C   s   t | ||ƒS ©N)Ú_RoutingDelegate)r   r!   r"   r   r   r   Ústart_requestÏ   s   zRouter.start_requestN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   ÚHTTPServerRequestr   r   ÚHTTPMessageDelegater    ÚobjectÚHTTPConnectionr%   r   r   r   r   r   ¾   s     ÿÿ
þÿÿþr   c                   @   s*   e Zd ZdZdededee fdd„ZdS )ÚReversibleRouterzxAbstract router interface for routers that can handle named routes
    and support reversing them to original urls.
    ÚnameÚargsr   c                 G   r   )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   r/   r0   r   r   r   Úreverse_urlÚ   s   zReversibleRouter.reverse_urlN)r&   r'   r(   r)   Ústrr   r   r1   r   r   r   r   r.   Õ   s    r.   c                   @   s‚   e Zd Zdededejddfdd„Zdeej	ej
f d	ejdeed  fd
d„Zdedeed  fdd„Zddd„Zddd„ZdS )r$   Úrouterr!   r"   r   Nc                 C   s   || _ || _d | _|| _d S r#   )r!   r"   Údelegater3   )r   r3   r!   r"   r   r   r   Ú__init__æ   s   
z_RoutingDelegate.__init__Ú
start_lineÚheadersc                 C   sj   t |tjƒsJ ‚tj| j| j||d�}| j |¡| _| jd u r.t	 
d|j|j¡ t| jƒ| _| j ||¡S )N)Ú
connectionÚserver_connectionr6   r7   z$Delegate for %s %s request not found)Ú
isinstancer   ÚRequestStartLiner*   r"   r!   r3   r    r4   r   ÚdebugÚmethodÚpathÚ_DefaultMessageDelegateÚheaders_received)r   r6   r7   r   r   r   r   r@   î   s    ü
ýz!_RoutingDelegate.headers_receivedÚchunkc                 C   s   | j d usJ ‚| j  |¡S r#   )r4   Údata_received)r   rA   r   r   r   rB     s   z_RoutingDelegate.data_receivedc                 C   ó   | j d usJ ‚| j  ¡  d S r#   )r4   Úfinish©r   r   r   r   rD   
  ó   z_RoutingDelegate.finishc                 C   rC   r#   )r4   Úon_connection_closerE   r   r   r   rG     rF   z$_RoutingDelegate.on_connection_close©r   N)r&   r'   r(   r   r,   r   r-   r5   r   r;   ÚResponseStartLineÚHTTPHeadersr   r   r@   ÚbytesrB   rD   rG   r   r   r   r   r$   å   s(    ÿÿÿ
þþý

ü
r$   c                   @   s*   e Zd Zdejddfdd„Zddd„ZdS )	r?   r8   r   Nc                 C   s
   || _ d S r#   )r8   )r   r8   r   r   r   r5     s   
z _DefaultMessageDelegate.__init__c                 C   s*   | j  t ddd¡t ¡ ¡ | j  ¡  d S )NzHTTP/1.1i”  z	Not Found)r8   Úwrite_headersr   rI   rJ   rD   rE   r   r   r   rD     s
   þz_DefaultMessageDelegate.finishrH   )r&   r'   r(   r   r-   r5   rD   r   r   r   r   r?     s    r?   ÚRuleÚMatcherc                	   @   s„   e Zd ZdZddee ddfdd„Zdeddfdd„Zddd„Zde	j
dedee	j fdd„Zdede	j
dedee	j fdd„ZdS )Ú
RuleRouterz!Rule-based router implementation.NÚrulesr   c                 C   s   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)rP   Ú	add_rules©r   rP   r   r   r   r5   /  s   ÿzRuleRouter.__init__c                 C   sv   |D ]6}t |ttfƒr/t|ƒdv sJ ‚t |d tƒr+tt|d ƒg|dd… ¢R Ž }nt|Ž }| j |  	|¡¡ qdS )z£Appends new rules to the router.

        :arg rules: a list of Rule instances (or tuples of arguments, which are
            passed to Rule constructor).
        )é   é   é   r   é   N)
r:   ÚtupleÚlistÚlenr	   rM   ÚPathMatchesrP   ÚappendÚprocess_rule)r   rP   Úruler   r   r   rQ   N  s   "øzRuleRouter.add_rulesr]   rM   c                 C   s   |S )z¯Override this method for additional preprocessing of each rule.

        :arg Rule rule: a rule to be processed.
        :returns: the same or modified Rule instance.
        r   ©r   r]   r   r   r   r\   ^  s   zRuleRouter.process_ruler   r   c                 K   sZ   | j D ]'}|j |¡}|d ur*|jr|j|d< | j|j|fi |¤Ž}|d ur*|  S qd S )NÚtarget_kwargs)rP   ÚmatcherÚmatchr_   Úget_target_delegateÚtarget)r   r   r   r]   Útarget_paramsr4   r   r   r   r    f  s   

ÿÿ€zRuleRouter.find_handlerrc   rd   c                 K   sx   t |tƒr|j|fi |¤ŽS t |tjƒr#|jdusJ ‚| |j|j¡S t|ƒr:|jdus.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)r:   r   r    r   ÚHTTPServerConnectionDelegater8   r%   r9   Úcallabler   r   )r   rc   r   rd   r   r   r   rb   x  s   
ÿzRuleRouter.get_target_delegater#   ©r]   rM   r   rM   )r&   r'   r(   r)   r   Ú	_RuleListr5   rQ   r\   r   r*   r   r+   r    rb   r   r   r   r   rO   ,  s*    
ÿÿ
þÿÿÿþrO   c                       sX   e Zd ZdZddee ddf‡ fdd„Zd‡ fd	d
„Zdede	dee fdd„Z
‡  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`).
    NrP   r   c                    s   i | _ tƒ  |¡ d S r#   )Únamed_rulesÚsuperr5   rR   ©Ú	__class__r   r   r5   œ  s   zReversibleRuleRouter.__init__r]   rM   c                    s<   t ƒ  |¡}|jr|j| jv rt d|j¡ || j|j< |S )Nz4Multiple handlers named %s; replacing previous value)rk   r\   r/   rj   r   Úwarningr^   rl   r   r   r\      s   ÿz!ReversibleRuleRouter.process_ruler/   r0   c                 G   s\   || j v r| j | jj|Ž S | jD ]}t|jtƒr+|jj|g|¢R Ž }|d ur+|  S qd S r#   )rj   r`   ÚreverserP   r:   rc   r.   r1   )r   r/   r0   r]   Úreversed_urlr   r   r   r1   ¬  s   

€z ReversibleRuleRouter.reverse_urlr#   rg   )r&   r'   r(   r)   r   rh   r5   r\   r2   r   r1   Ú__classcell__r   r   rl   r   ri   ”  s
    "ri   c                   @   sh   e Zd ZdZ		ddddedeeeef  dee ddf
d	d
„Zdedee fdd„Z	defdd„Z
dS )rM   zA routing rule.Nr`   rN   rc   r_   r/   r   c                 C   s6   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)r:   r2   r
   r`   rc   r_   r/   )r   r`   rc   r_   r/   r   r   r   r5   ¼  s   

zRule.__init__r0   c                 G   s   | j j|Ž S r#   )r`   ro   ©r   r0   r   r   r   ro   Ý  s   zRule.reversec                 C   s   d| j j| j| j| j| jf S ©Nz%s(%r, %s, kwargs=%r, name=%r))rm   r&   r`   rc   r_   r/   rE   r   r   r   Ú__repr__à  s   ûzRule.__repr__©NN)r&   r'   r(   r)   r   r   r   r2   r5   ro   rt   r   r   r   r   rM   ¹  s"    ûþýüû
ú!c                   @   sF   e Zd ZdZdejdeeee	f  fdd„Z
de	dee fdd„Zd	S )
rN   z*Represents a matcher for request features.r   r   c                 C   r   )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   r   r   r   ra   í  s   
zMatcher.matchr0   c                 G   s   dS )zEReconstructs full url from matcher instance and additional arguments.Nr   rr   r   r   r   ro   ù  ó   zMatcher.reverseN)r&   r'   r(   r)   r   r*   r   r   r2   r   ra   ro   r   r   r   r   rN   ê  s     c                   @   s0   e Zd ZdZdejdeeee	f  fdd„Z
dS )Ú
AnyMatcheszMatches any request.r   r   c                 C   s   i S r#   r   rv   r   r   r   ra     s   zAnyMatches.matchN)r&   r'   r(   r)   r   r*   r   r   r2   r   ra   r   r   r   r   rx   þ  s    $rx   c                   @   sJ   e Zd ZdZdeeef ddfdd„Zdej	de
eeef  fdd	„ZdS )
ÚHostMatchesz@Matches requests from hosts specified by ``host_pattern`` regex.Úhost_patternr   Nc                 C   s6   t |tƒr| d¡s|d7 }t |¡| _d S || _d S )Nú$)r:   r	   ÚendswithÚreÚcompilerz   )r   rz   r   r   r   r5     s
   


zHostMatches.__init__r   c                 C   s   | j  |j¡r	i S d S r#   )rz   ra   Ú	host_namerv   r   r   r   ra     s   zHostMatches.match)r&   r'   r(   r)   r   r2   r   r5   r   r*   r   r   r   ra   r   r   r   r   ry     s    $ry   c                   @   sF   e Zd ZdZdededdfdd„Zdejde	e
eef  fd	d
„ZdS )ÚDefaultHostMatcheszŒMatches requests from host that is equal to application's default_host.
    Always returns no match if ``X-Real-Ip`` header is present.
    Úapplicationrz   r   Nc                 C   s   || _ || _d S r#   )r�   rz   )r   r�   rz   r   r   r   r5     s   
zDefaultHostMatches.__init__r   c                 C   s"   d|j vr| j | jj¡ri S d S )Nz	X-Real-Ip)r7   rz   ra   r�   Údefault_hostrv   r   r   r   ra      s   
zDefaultHostMatches.match)r&   r'   r(   r)   r   r   r5   r   r*   r   r   r2   ra   r   r   r   r   r€     s    $r€   c                   @   s~   e Zd ZdZdeeef ddfdd„Zdej	de
eeef  fdd	„Zd
ede
e fdd„Zdee
e e
e f fdd„ZdS )rZ   z@Matches requests with paths specified by ``path_pattern`` regex.Úpath_patternr   Nc                 C   sl   t |tƒr| d¡s|d7 }t |¡| _n|| _t| jjƒd| jjfv s,J d| jj	 ƒ‚|  
¡ \| _| _d S )Nr{   r   zDgroups in url regexes must either be all named or all positional: %r)r:   r	   r|   r}   r~   ÚregexrY   Ú
groupindexÚgroupsÚpatternÚ_find_groupsÚ_pathÚ_group_count)r   rƒ   r   r   r   r5   +  s   

ÿÿzPathMatches.__init__r   c                 C   sp   | j  |j¡}|d u rd S | j jsi S g }i }| j jr)tdd„ | ¡  ¡ D ƒƒ}n	dd„ | ¡ D ƒ}t||d�S )Nc                 s   s$   � | ]\}}t |ƒt|ƒfV  qd S r#   )r2   Ú_unquote_or_none)Ú.0ÚkÚvr   r   r   Ú	<genexpr>I  s   € 
ÿz$PathMatches.match.<locals>.<genexpr>c                 S   s   g | ]}t |ƒ‘qS r   )r‹   )rŒ   Úsr   r   r   Ú
<listcomp>M  s    z%PathMatches.match.<locals>.<listcomp>)Ú	path_argsÚpath_kwargs)r„   ra   r>   r†   r…   ÚdictÚ	groupdictÚitems)r   r   ra   r’   r“   r   r   r   ra   :  s   

ÿzPathMatches.matchr0   c                 G   s†   | j d u rtd| jj ƒ‚t|ƒ| jksJ dƒ‚t|ƒs| j S g }|D ]}t|ttfƒs0t	|ƒ}| 
tt|ƒdd�¡ q#| j t|ƒ S )NzCannot reverse url regex z&required number of arguments not foundF)Úplus)r‰   Ú
ValueErrorr„   r‡   rY   rŠ   r:   r   rK   r2   r[   r   r   rW   )r   r0   Úconverted_argsÚar   r   r   ro   Q  s   
ÿzPathMatches.reversec              	   C   sø   | j j}| d¡r|dd… }| d¡r|dd… }| j j| d¡kr%dS g }| d¡D ]F}d|v r[| d¡}|d	krZzt||d d… ƒ}W n t	yR   Y  dS w | 
d
| ¡ q,zt|ƒ}W n t	yl   Y  dS w | 
|¡ q,d |¡| j jfS )z¶Returns 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).
        ú^rV   Nr{   éÿÿÿÿú(ru   ú)r   z%sÚ )r„   r‡   Ú
startswithr|   r†   ÚcountÚsplitÚindexr   r˜   r[   Újoin)r   r‡   ÚpiecesÚfragmentÚ	paren_locÚunescaped_fragmentr   r   r   rˆ   `  s4   


ý€ýzPathMatches._find_groups)r&   r'   r(   r)   r   r2   r   r5   r   r*   r   r   r   ra   ro   r   Úintrˆ   r   r   r   r   rZ   (  s     "rZ   c                       sb   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d	„Z
defd
d„Z‡  ZS )ÚURLSpeczÍSpecifies 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   r/   r   c                    s4   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)rZ   rk   r5   r„   rc   Úhandler_classr   )r   r‡   r«   r   r/   r`   rl   r   r   r5   ‘  s
   
zURLSpec.__init__c                 C   s    d| j j| jj| j| j| jf S rs   )rm   r&   r„   r‡   r¬   r   r/   rE   r   r   r   rt   °  s   ûzURLSpec.__repr__ru   )r&   r'   r(   r)   r   r2   r   r   r   r   r5   rt   rq   r   r   rl   r   rª   ‰  s     û
þýüûúrª   r�   r   c                 C   ó   d S r#   r   ©r�   r   r   r   r‹   º  rw   r‹   c                 C   r­   r#   r   r®   r   r   r   r‹   ¿  rw   c                 C   s   | du r| S t | ddd�S )z¹None-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®   r   r   r   r‹   Ä  s   )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   re   r   r.   r+   r$   r?   r2   rh   rO   ri   r,   rM   rN   rx   ry   r€   rZ   rª   rK   r‹   r   r   r   r   Ú<module>   sL    $,.üÿÿh%1a1