;iddlmZddlZddlZddlmZddlmZddl m Z ddl m Z ddl m Z dd l mZdd l mZdd lmZdd lmZdd lmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm!Z!ddlm"Z"ddlm#Z#ddl$m%Z%ddl&m'Z'ddl&m(Z(ej)rddl*m+Z+ddl*m,Z,dd l-m.Z.dd!lm/Z/dd"l&m0Z0Gd#d$Z1Gd%d&Z2dS)') annotationsN)pformat)Lock)quote)urljoin) urlunsplit) _get_environ)_wsgi_decoding_dance) ImmutableDict) MultiDict)BadHost) HTTPException)MethodNotAllowed)NotFound) _urlencode)get_host)DEFAULT_CONVERTERS) BuildError)NoMatch)RequestAliasRedirect) RequestPath)RequestRedirect)WebsocketMismatch)StateMachineMatcher)_simple_rule_re)Rule)WSGIApplication)WSGIEnvironment)Request) BaseConverter) RuleFactoryceZdZdZeeZeZ d8d9dZ e d:dZ e j d;dZ dd?d"Zd@d%Z dAdBd2Z dCdDd5ZdEd6ZdFd7ZdS)GMapaThe map class stores all the URL rules and some configuration parameters. Some of the configuration values are only stored on the `Map` instance since those affect all rules, others are just defaults and can be overridden for each rule. Note that you have to specify all arguments besides the `rules` as keyword arguments! :param rules: sequence of url rules for this map. :param default_subdomain: The default subdomain for rules without a subdomain defined. :param strict_slashes: If a rule ends with a slash but the matched URL does not, redirect to the URL with a trailing slash. :param merge_slashes: Merge consecutive slashes when matching or building URLs. Matches will redirect to the normalized URL. Slashes in variable parts are not merged. :param redirect_defaults: This will redirect to the default rule if it wasn't visited that way. This helps creating unique URLs. :param converters: A dict of converters that adds additional converters to the list of converters. If you redefine one converter this will override the original one. :param sort_parameters: If set to `True` the url parameters are sorted. See `url_encode` for more details. :param sort_key: The sort key function for `url_encode`. :param host_matching: if set to `True` it enables the host matching feature and disables the subdomain one. If enabled the `host` parameter to rules is used instead of the `subdomain` one. .. versionchanged:: 3.0 The ``charset`` and ``encoding_errors`` parameters were removed. .. versionchanged:: 1.0 If ``url_scheme`` is ``ws`` or ``wss``, only WebSocket rules will match. .. versionchanged:: 1.0 The ``merge_slashes`` parameter was added. .. versionchanged:: 0.7 The ``encoding_errors`` and ``host_matching`` parameters were added. .. versionchanged:: 0.5 The ``sort_parameters`` and ``sort_key`` paramters were added. NTFrulest.Iterable[RuleFactory] | Nonedefault_subdomainstrstrict_slashesbool merge_slashesredirect_defaults converters*t.Mapping[str, type[BaseConverter]] | Nonesort_parameterssort_key!t.Callable[[t.Any], t.Any] | None host_matchingreturnNonec |t||_i|_d|_||_||_||_||_| |_ |j |_ |r|j |||_||_|pdD]} || dS)NT)r_matcher_rules_by_endpoint_remap lock_class _remap_lockr)r+r.r4default_converterscopyr/updater1r2add) selfr'r)r+r-r.r/r1r2r4 rulefactorys HC:\PYTHON\MyICR_Workspace\venv\Lib\site-packages\werkzeug/routing/map.py__init__z Map.__init__^s,M:: ;= ??,,!2,!2*16688  / O " ": . . ..   ;B " "K HH[ ! ! ! ! " "c|jjSNr9r-rBs rDr-zMap.merge_slashes~s }**rFvaluec||j_dSrHrI)rBrKs rDr-zMap.merge_slashess&+ ###rFendpointt.Any argumentsc|t|}|j|D]}||jrdS dS)aQIterate over all rules and check if the endpoint expects the arguments provided. This is for example useful if you have some URLs that expect a language code and others that do not and you want to wrap the builder a bit so that the current language code is automatically added if not provided but endpoints expect it. :param endpoint: the endpoint to check. :param arguments: this function accepts one or more arguments as positional arguments. Each one of them is checked. TF)r@setr:issubsetrO)rBrMrO arguments_setrules rDis_endpoint_expectingzMap.is_endpoint_expectings\ I +H5  D%%dn55 tt urF list[Rule]cHd|jDS)Ncg|] }|D]}| Sr8r8).0r'rTs rD zMap._rules..s%UUUuUUtUUUUrF)r:valuesrJs rD_rulesz Map._ruless%UU$"9"@"@"B"BUUUUrF t.Any | Nonet.Iterator[Rule]c||t|j|St|jS)zIterate over all rules or the rules of an endpoint. :param endpoint: if provided only the rules for that endpoint are returned. :return: an iterator )r@iterr:r\)rBrMs rD iter_ruleszMap.iter_ruless=  /9:: :DK   rFrCr#c||D]k}|||js|j||j|jg|ld|_ dS)zAdd a new rule or factory to the map and bind it. Requires that the rule is not bound to another map. :param rulefactory: a :class:`Rule` or :class:`RuleFactory` TN) get_rulesbind build_onlyr9rAr: setdefaultrMappendr;)rBrCrTs rDrAzMap.adds  ))$// O OD IIdOOO? ( !!$'''  # . .t}b A A H H N N N N rFhttpGET server_name script_name str | None subdomain url_schemedefault_method path_info query_args"t.Mapping[str, t.Any] | str | None MapAdapterc ~|}|jr|tdn ||j}|d}|d}|d\}}} |dd}n!#t$r} t| d} ~ wwxYwt|||| ||||||S)aReturn a new :class:`MapAdapter` with the details specified to the call. Note that `script_name` will default to ``'/'`` if not further specified or `None`. The `server_name` at least is a requirement because the HTTP RFC requires absolute URLs for redirects and so all redirect exceptions raised by Werkzeug will contain the full canonical URL. If no path_info is passed to :meth:`match` it will use the default path info passed to bind. While this doesn't really make sense for manual bind calls, it's useful if you bind a map to a WSGI environment which already contains the path info. `subdomain` will default to the `default_subdomain` for this map if no defined. If there is no `default_subdomain` you cannot use the subdomain feature. .. versionchanged:: 1.0 If ``url_scheme`` is ``ws`` or ``wss``, only WebSocket rules will match. .. versionchanged:: 0.15 ``path_info`` defaults to ``'/'`` if ``None``. .. versionchanged:: 0.8 ``query_args`` can be a string. .. versionchanged:: 0.7 Added ``query_args``. Nz2host matching enabled and a subdomain was provided/:idnaascii) lowerr4 RuntimeErrorr) partitionencodedecode UnicodeErrorrrs) rBrjrkrmrnrorprqport_sepportes rDrdzMap.binds N"''))   /$"#WXXX%  .I  K  I'2&;&;C&@&@# Xt #%,,V44;;GDDKK # # #)) " #  ,H ,d , ,         s(B B  BB environWSGIEnvironment | Requestc t|t}d}tddddD}|r6dddkr |dkrd nd }||}n[|}|d vr |d r |d d}n#|dvr|dr |d d}||js|d}|d}t| } || d |krtj d|d|dd}n+d td |d | }d"fd } | d} | d} | d} t||| ||d | | !S)#aLike :meth:`bind` but you can pass it an WSGI environment and it will fetch the information from that dictionary. Note that because of limitations in the protocol there is no way to get the current subdomain and real `server_name` from the environment. If you don't provide it, Werkzeug will use `SERVER_NAME` and `SERVER_PORT` (or `HTTP_HOST` if provided) as used `server_name` with disabled subdomain feature. If `subdomain` is `None` but an environment and a server name is provided it will calculate the current subdomain automatically. Example: `server_name` is ``'example.com'`` and the `SERVER_NAME` in the wsgi `environ` is ``'staging.dev.example.com'`` the calculated subdomain will be ``'staging.dev'``. If the object passed as environ has an environ attribute, the value of this attribute is used instead. This allows you to pass request objects. Additionally `PATH_INFO` added as a default of the :class:`MapAdapter` so that you don't have to pass the path info to the match method. .. versionchanged:: 1.0.0 If the passed server name specifies port 443, it will match if the incoming scheme is ``https`` without a port. .. versionchanged:: 1.0.0 A warning is shown when the passed server name does not match the incoming WSGI server name. .. versionchanged:: 0.8 This will no longer raise a ValueError when an unexpected server name was passed. .. versionchanged:: 0.5 previously this method accepted a bogus `calculate_subdomain` parameter that did not have any effect. It was removed because of that. :param environ: a WSGI environment. :param server_name: an optional server name hint (see above). :param subdomain: optionally the current subdomain (see above). zwsgi.url_schemec3FK|]}|dkVdS)upgradeN)strip)rYvs rD z&Map.bind_to_environ...sC   GGII "      rFHTTP_CONNECTIONr&, HTTP_UPGRADE websockethttpswsswsN>rrhz:80>rrz:443.zCurrent server name z& doesn't match configured server name r ) stacklevelz namer*r5rlcT|}|t|SdSrH)getr )rvalenvs rD_get_wsgi_stringz-Map.bind_to_environ.._get_wsgi_stringUs*''$--C+C0004rF SCRIPT_NAME PATH_INFO QUERY_STRINGREQUEST_METHOD)rq)rr*r5rl)r rryanyrsplitendswithr4lenwarningswarnjoinfilterr%rd)rBrrjrmwsgi_server_nameschemercur_server_namereal_server_nameoffsetrrkrprqrs @rDbind_to_environzMap.bind_to_environs^7###C==..00&'  WW.3399;;AA#FF       :sww~r2288::kII$//UUTF  *KK%++--K''K,@,@,G,G')#2#. +++ 0D0DV0L0L+)#2#.  T%7 .44S99O*0055 *+++Fvww'+;;;  4+;44$/44  ( HHVD/'6'2J%K%KLL        '&}55 $$[11 %%n55 xx       ! !   rFc(|jsdS|j5|js ddddS|j|jD]}|dd|_ddddS#1swxYwYdS)zzCalled before matching and building to keep the compiled rules in the correct order after things changed. Nc*|SrH)build_compare_key)xs rDzMap.update..vs)<)<)>)>rF)keyF)r;r=r9r@r:r[sortrBr's rDr@z Map.updateis {  F    ;          M " " "07799 @ @ >> ????DK                  s BABB B c|}t|jdtt |dS)N())ratype__name__rlistrs rD__repr__z Map.__repr__ys?!!t**%??U (<(<????rF) Nr&TTTNFNF)r'r(r)r*r+r,r-r,r.r,r/r0r1r,r2r3r4r,r5r6)r5r,)rKr,r5r6)rMrNrOr*r5r,)r5rVrH)rMr]r5r^)rCr#r5r6)NNrhriNN)rjr*rkrlrmrlrnr*ror*rprlrqrrr5rsNN)rrrjrlrmrlr5rs)r5r6)r5r*)r __module__ __qualname____doc__r rr>rr<rEpropertyr-setterrUr\rarArdrr@rr8rFrDr%r%)s**Z''9:: J15!##""&AE %6:#"""""@+++X+,,,,(VVVXV ! ! ! ! !     #' $ # $9=C C C C C P#' $ k k k k k Z    @@@@@@rFr%ceZdZdZ d=d>dZ d?d@dZej dAdBdZej dCdDd"Z dAdEd$ZdFdGd%Z d=dHd'Z dId)Z dJd/Z dKd0Z dFdLd1ZdMd6ZdNd9Z dOdPd<ZdS)QrszReturned by :meth:`Map.bind` or :meth:`Map.bind_to_environ` and does the URL matching and building based on runtime information. Nmapr%rjr*rkrmrlrnrprorqrrc ||_||_|ds|dz }||_||_||_||_||_||_|jdv|_ dS)Nru>rr) rrjrrkrmrnrprorqr) rBrrjrkrmrnrprorqs rDrEzMapAdapter.__init__sq&##C((  3 K&"$",$M9rFF view_func9t.Callable[[str, t.Mapping[str, t.Any]], WSGIApplication]methodcatch_http_exceptionsr,r5rc |||\}}n#t$r }|cYd}~Sd}~wwxYw|||S#t$r}|r|cYd}~Sd}~wwxYw)a3Does the complete dispatching process. `view_func` is called with the endpoint and a dict with the values for the view. It should look up the view function, call it, and return a response object or WSGI application. http exceptions are not caught by default so that applications can display nicer error messages by just catching them by hand. If you want to stick with the default error messages you can pass it ``catch_http_exceptions=True`` and it will catch the http exceptions. Here a small example for the dispatch usage:: from werkzeug.wrappers import Request, Response from werkzeug.wsgi import responder from werkzeug.routing import Map, Rule def on_index(request): return Response('Hello from the index') url_map = Map([Rule('/', endpoint='index')]) views = {'index': on_index} @responder def application(environ, start_response): request = Request(environ) urls = url_map.bind_to_environ(environ) return urls.dispatch(lambda e, v: views[e](request, **v), catch_http_exceptions=True) Keep in mind that this method might return exception objects, too, so use :class:`Response.force_type` to get a response object. :param view_func: a function that is called with the endpoint as first argument and the value dict as second. Has to dispatch to the actual view function with this information. (see above) :param path_info: the path info to use for matching. Overrides the path info specified on binding. :param method: the HTTP method used for matching. Overrides the method specified on binding. :param catch_http_exceptions: set to `True` to catch any of the werkzeug :class:`HTTPException`\s. Nmatchrr)rBrrprrrMargsrs rDdispatchzMapAdapter.dispatchsb  !%Iv!>!>$$"    9Xt,, ,   $   sAA 3.3A3A A AAAA return_rulet.Literal[False]r bool | None#tuple[t.Any, t.Mapping[str, t.Any]]cdSrHr8rBrprrrqrs rDrzMapAdapter.matchs /2crFTt.Literal[True]"tuple[Rule, t.Mapping[str, t.Any]]cdSrHr8rs rDrzMapAdapter.matchs .1SrF*tuple[t.Any | Rule, t.Mapping[str, t.Any]]c |j||j}| |jpi}|p|j}||j}|j}|jjs|j |j }|rd| dnd} |jj ||||}|\|jj r)|||} | t| jt#jt$r"dfd } t'j| j} nj|fi} |j r|j d |j} n|j} tt+|jpd d | |j| |rfSjfS#t2$r?} t5| jd } t|| |dd} ~ wt8$r;} t||d|| j| j||dd} ~ wt>$rT} | j r#tCtE| j d| j#rtIdtKdd} ~ wwxYw)aThe usage is simple: you just pass the match method the current path info as well as the method (which defaults to `GET`). The following things can then happen: - you receive a `NotFound` exception that indicates that no URL is matching. A `NotFound` exception is also a WSGI application you can call to get a default page not found page (happens to be the same object as `werkzeug.exceptions.NotFound`) - you receive a `MethodNotAllowed` exception that indicates that there is a match for this URL but not for the current request method. This is useful for RESTful applications. - you receive a `RequestRedirect` exception with a `new_url` attribute. This exception is used to notify you about a request Werkzeug requests from your WSGI application. This is for example the case if you request ``/foo`` although the correct URL is ``/foo/`` You can use the `RequestRedirect` instance as response-like object similar to all other subclasses of `HTTPException`. - you receive a ``WebsocketMismatch`` exception if the only match is a WebSocket rule but the bind is an HTTP request, or if the match is an HTTP rule but the bind is a WebSocket request. - you get a tuple in the form ``(endpoint, arguments)`` if there is a match (unless `return_rule` is True, in which case you get a tuple in the form ``(rule, arguments)``) If the path info is not passed to the match method the default path info of the map is used (defaults to the root URL if not defined explicitly). All of the exceptions raised are subclasses of `HTTPException` so they can be used as WSGI responses. They will all render generic error or redirect pages. Here is a small example for matching: >>> m = Map([ ... Rule('/', endpoint='index'), ... Rule('/downloads/', endpoint='downloads/index'), ... Rule('/downloads/', endpoint='downloads/show') ... ]) >>> urls = m.bind("example.com", "/") >>> urls.match("/", "GET") ('index', {}) >>> urls.match("/downloads/42") ('downloads/show', {'id': 42}) And here is what happens on redirect and missing URLs: >>> urls.match("/downloads") Traceback (most recent call last): ... RequestRedirect: http://example.com/downloads/ >>> urls.match("/missing") Traceback (most recent call last): ... NotFound: 404 Not Found :param path_info: the path info to use for matching. Overrides the path info specified on binding. :param method: the HTTP method used for matching. Overrides the method specified on binding. :param return_rule: return the rule that matched instead of just the endpoint (defaults to `False`). :param query_args: optional query arguments that are used for automatic redirects as string or dictionary. It's currently not possible to use the query arguments for URL matching. :param websocket: Match WebSocket instead of HTTP requests. A websocket request has a ``ws`` or ``wss`` :attr:`url_scheme`. This overrides that detection. .. versionadded:: 1.0 Added ``websocket``. .. versionchanged:: 0.8 ``query_args`` can be a string. .. versionadded:: 0.7 Added ``query_args``. .. versionadded:: 0.6 Added ``return_rule``. Nrur&r t.Match[str]r5r*c|d}j|d|S)Nr)group _convertersto_url)rrKrTrvs rD _handle_matchz'MapAdapter.match.._handle_matchs= "5;;q>> 2#/ A?FFuMMMrFrrhz://z!$&'()*+,/:;=@)safe|) valid_methods)rrr5r*)&rr@rprqroupperrrjr4rmlstripr9rr.get_default_redirectr redirect_to isinstancer*rsubrrnrkrMrrmake_redirect_urlrmake_alias_redirect_urlmatched_valuesrhave_match_forrrwebsocket_mismatchrr)rBrprrrqr domain_part path_partresult redirect_urlrnetlocrnew_pathrTrs @@rDrzMapAdapter.matchsD~   I  .BJ/D/6688  I& x% )$.*D.K3<D/ ((--///" < )X&,,[)VYWWF4HD"x) 8#88vr:VV +),777+d.44@NNNNNNN$3#6}dFV#W#WLL#34#3D#?#?B#?#?L>. $CC1ACCFF!-F%?4fSSSAQSS$ )Rx}b((u   Q[/?@@@H!&&x<< $   !,,"00Y00J$   ' ' ' W&T!:J5K5KLLLRVV# 4'))t3**$ & 's1"F J(:G"" J/6H%% J2AJJcn |||n#t$rYnt$rYdSwxYwdS)aTest if a rule would match. Works like `match` but returns `True` if the URL matches, or `False` if it does not exist. :param path_info: the path info to use for matching. Overrides the path info specified on binding. :param method: the HTTP method used for matching. Overrides the method specified on binding. FTr)rBrprs rDtestzMapAdapter.tests\  JJy& ) ) ) )    D   55 ts 2 22t.Iterable[str]c ||dn)#t$r}|jcYd}~Sd}~wt$rYnwxYwgS)z^Returns the valid methods that match for a given path. .. versionadded:: 0.7 z--)rN)rrrr)rBrprs rDallowed_methodszMapAdapter.allowed_methodssr   JJyJ . . . . # # #? " " " " " "    D  s A0A AArcr|jjr ||jS|S||j}n|}|r |d|jS|jS)zFigures out the full host name for the given domain part. The domain part is a subdomain in case host matching is disabled or a full host name. Nr)rr4rjrm)rBrrms rDrzMapAdapter.get_hostsb 8 ! "''   II#I  $44$"244 4# #rFrTrr[t.MutableMapping[str, t.Any]t.Mapping[str, t.Any] | strcP|jjsJ|jj|jD]}||urnx||rb|||rL||j||\}}| |||cSdS)zA helper that returns the URL to redirect to if it finds one. This is used for default redirecting only. :internal: )rN) rr.r:rMprovides_defaults_for suitable_forr@defaultsbuildr)rBrTrr[rqrrpaths rDrzMapAdapter.get_default_redirectsx)))),T]; Y YADyy&&t,, Y1O1O Y aj)))$%GGFOO! T--dJK-XXXXXtrFcNt|tst|S|SrH)rr*r)rBrqs rDencode_query_argszMapAdapter.encode_query_argss(*c** *j)) )rFc0||j}|r||}nd}|jpd}||}d|jd|df}t||||dfS)z4Creates a redirect URL. :internal: Nrhru) rqrrnrrrkrrr)rBrprqr query_strrhostrs rDrzMapAdapter.make_redirect_urls  J  ..z::III*F}}[))xx)//44i6F6Fs6K6KLMM64y$?@@@rFrrMrNt.Mapping[str, t.Any]c||||dd}|r|d||z }||ks Jd|S)z0Internally called to make an alias redirect URL.FT)append_unknownforce_external?z6detected invalid alias setting. No canonical URL found)rr)rBrrMr[rrqurls rDrz"MapAdapter.make_alias_redirect_urlskjj ffU4    < ;t--j99;; ;Cd{{{T{{{ rFr tuple[str, str, bool] | Nonecr|!||||j|}||Sd}|jj|dD]p}|||rX|||}|@|d|d|jf}|jjr|d|j kr|cS||}l|cSq|S)zHelper for :meth:`build`. Returns subdomain and path for the rule that accepts this endpoint, values and method. :internal: Nr8rr) _partial_buildrorr:rrrrr4rj) rBrMr[rr r first_matchrTbuild_rvs rDrzMapAdapter._partial_builds >$$&$"5~B~  H/33HbAA " "D  00 "::fn=='"1+x{DNCBx-"a5D$444#%III(0*,K! rFt.Mapping[str, t.Any] | Noner c|j|rYt|tr%dt|D}n!d|D}ni}|||||}|t|||||\}} } ||} ||j }|dv} | r d}| rdnd}n|r| rdnd }|s`|jj r | |j ks|jj s=||j kr2|j d d | d S|r|d nd } | d | |j ddd | d S)a; Building URLs works pretty much the other way round. Instead of `match` you call `build` and pass it the endpoint and a dict of arguments for the placeholders. The `build` function also accepts an argument called `force_external` which, if you set it to `True` will force external URLs. Per default external URLs (include the server name) will only be used if the target URL is on a different subdomain. >>> m = Map([ ... Rule('/', endpoint='index'), ... Rule('/downloads/', endpoint='downloads/index'), ... Rule('/downloads/', endpoint='downloads/show') ... ]) >>> urls = m.bind("example.com", "/") >>> urls.build("index", {}) '/' >>> urls.build("downloads/show", {'id': 42}) '/downloads/42' >>> urls.build("downloads/show", {'id': 42}, force_external=True) 'http://example.com/downloads/42' Because URLs cannot contain non ASCII data you will always get bytes back. Non ASCII characters are urlencoded with the charset defined on the map instance. Additional values are converted to strings and appended to the URL as URL querystring parameters: >>> urls.build("index", {'q': 'My Searchstring'}) '/?q=My+Searchstring' When processing those additional values, lists are furthermore interpreted as multiple values (as per :py:class:`werkzeug.datastructures.MultiDict`): >>> urls.build("index", {'q': ['a', 'b', 'c']}) '/?q=a&q=b&q=c' Passing a ``MultiDict`` will also add multiple values: >>> urls.build("index", MultiDict((('p', 'z'), ('q', 'a'), ('q', 'b')))) '/?p=z&q=a&q=b' If a rule does not exist when building a `BuildError` exception is raised. The build method accepts an argument called `method` which allows you to specify the method you want to have an URL built for if you have different methods for the same endpoint specified. :param endpoint: the endpoint of the URL to build. :param values: the values for the URL to build. Unhandled values are appended to the URL as query parameters. :param method: the HTTP method for the rule if there are different URLs for different methods on the same endpoint. :param force_external: enforce full canonical external URLs. If the URL scheme is not provided, this will generate a protocol-relative URL. :param append_unknown: unknown parameters are appended to the generated URL as query string argument. Disable this if you want the builder to ignore those. :param url_scheme: Scheme to use in place of the bound :attr:`url_scheme`. .. versionchanged:: 2.0 Added the ``url_scheme`` parameter. .. versionadded:: 0.6 Added the ``append_unknown`` parameter. cvi|]6\}}t|dk|t|dkr|dn|7S)rr)rrYkrs rD z$MapAdapter.build..sK11vv{{A! !"{{rFci|] \}}||| SrHr8rs rDrz$MapAdapter.build..sKKK41aQ]!Q]]]rFN>rrTrrrrhrurvr&z//)rr@rr dictitemsrrrrnr4rjrmrkrstripr)rBrMr[rr r rnrrrrrsecurers rDrzMapAdapter.build<s`   &),, L $ 6 2 2 LK6<<>>KKKF  66> J J :Xvvt<< <')$ T9}}[))  J //  7!N"(2dJJ  7$*6J H X # H(,0@(@(@H*)A/:dn/L/L&--c22GGT[[5E5EGG G%/7J!!!!RLLDL$"23B3"7LL$++c:J:JLLLrFrH)rr%rjr*rkr*rmrlrnr*rpr*ror*rqrr)NNF) rrrprlrrlrr,r5r)NNFNN) rprlrrlrrrqrrrrr5r)NNTNN) rprlrrlrrrqrrrrr5r) rprlrrlrr,rqrrrrr5rr)rprlrrlr5r,)rprlr5r)rrlr5r*) rTrrr*r[rrqrr5rl)rqrr5r*)rpr*rqrrrrlr5r*) rr*rMrNr[rrr*rqrr5r*) rMrNr[rrrlr r,r5r)NNFTN)rMrNr[rrrlr r,r r,rnrlr5r*)rrrrrErtoverloadrrrrrrrrrrr8rFrDrsrs~s:>:::::8!%!&+ :::::xZ!%!(-9=!% 2222Z2Z!%!'+9=!% 1111Z1!%!!9=!% l)l)l)l)l)\"     $$$$*2:>"& AAAAA."''''X04!$#!%{M{M{M{M{M{M{MrFrs)3 __future__rtypingrrpprintr threadingr urllib.parserrr _internalr r datastructuresr r exceptionsrrrrurlsrwsgirr/rrrrrrrmatcherrr'rr TYPE_CHECKING_typeshed.wsgirr wrappers.requestr!r"r#r%rsr8rFrDr/s"""""" ######$$$$$$,,,,,,******&&&&&& &&&&&&))))))!!!!!!******"""""",,,,,,######''''''))))))((((((""""""?#............******))))))""""""R@R@R@R@R@R@R@R@j yMyMyMyMyMyMyMyMyMyMrF