routing.html 205 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  2. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  3. <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
  4. <head>
  5. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  6. <title>werkzeug.routing &#8212; proxypool documentation</title>
  7. <link rel="stylesheet" href="../../_static/alabaster.css" type="text/css" />
  8. <link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
  9. <script type="text/javascript">
  10. var DOCUMENTATION_OPTIONS = {
  11. URL_ROOT: '../../',
  12. VERSION: '',
  13. COLLAPSE_INDEX: false,
  14. FILE_SUFFIX: '.html',
  15. HAS_SOURCE: true
  16. };
  17. </script>
  18. <script type="text/javascript" src="../../_static/jquery.js"></script>
  19. <script type="text/javascript" src="../../_static/underscore.js"></script>
  20. <script type="text/javascript" src="../../_static/doctools.js"></script>
  21. <link rel="index" title="Index" href="../../genindex.html" />
  22. <link rel="search" title="Search" href="../../search.html" />
  23. <link rel="top" title="proxypool documentation" href="../../index.html" />
  24. <link rel="up" title="Module code" href="../index.html" />
  25. <link rel="stylesheet" href="../../_static/custom.css" type="text/css" />
  26. <meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
  27. </head>
  28. <body role="document">
  29. <div class="document">
  30. <div class="documentwrapper">
  31. <div class="bodywrapper">
  32. <div class="body" role="main">
  33. <h1>Source code for werkzeug.routing</h1><div class="highlight"><pre>
  34. <span></span><span class="c1"># -*- coding: utf-8 -*-</span>
  35. <span class="sd">&quot;&quot;&quot;</span>
  36. <span class="sd"> werkzeug.routing</span>
  37. <span class="sd"> ~~~~~~~~~~~~~~~~</span>
  38. <span class="sd"> When it comes to combining multiple controller or view functions (however</span>
  39. <span class="sd"> you want to call them) you need a dispatcher. A simple way would be</span>
  40. <span class="sd"> applying regular expression tests on the ``PATH_INFO`` and calling</span>
  41. <span class="sd"> registered callback functions that return the value then.</span>
  42. <span class="sd"> This module implements a much more powerful system than simple regular</span>
  43. <span class="sd"> expression matching because it can also convert values in the URLs and</span>
  44. <span class="sd"> build URLs.</span>
  45. <span class="sd"> Here a simple example that creates an URL map for an application with</span>
  46. <span class="sd"> two subdomains (www and kb) and some URL rules:</span>
  47. <span class="sd"> &gt;&gt;&gt; m = Map([</span>
  48. <span class="sd"> ... # Static URLs</span>
  49. <span class="sd"> ... Rule(&#39;/&#39;, endpoint=&#39;static/index&#39;),</span>
  50. <span class="sd"> ... Rule(&#39;/about&#39;, endpoint=&#39;static/about&#39;),</span>
  51. <span class="sd"> ... Rule(&#39;/help&#39;, endpoint=&#39;static/help&#39;),</span>
  52. <span class="sd"> ... # Knowledge Base</span>
  53. <span class="sd"> ... Subdomain(&#39;kb&#39;, [</span>
  54. <span class="sd"> ... Rule(&#39;/&#39;, endpoint=&#39;kb/index&#39;),</span>
  55. <span class="sd"> ... Rule(&#39;/browse/&#39;, endpoint=&#39;kb/browse&#39;),</span>
  56. <span class="sd"> ... Rule(&#39;/browse/&lt;int:id&gt;/&#39;, endpoint=&#39;kb/browse&#39;),</span>
  57. <span class="sd"> ... Rule(&#39;/browse/&lt;int:id&gt;/&lt;int:page&gt;&#39;, endpoint=&#39;kb/browse&#39;)</span>
  58. <span class="sd"> ... ])</span>
  59. <span class="sd"> ... ], default_subdomain=&#39;www&#39;)</span>
  60. <span class="sd"> If the application doesn&#39;t use subdomains it&#39;s perfectly fine to not set</span>
  61. <span class="sd"> the default subdomain and not use the `Subdomain` rule factory. The endpoint</span>
  62. <span class="sd"> in the rules can be anything, for example import paths or unique</span>
  63. <span class="sd"> identifiers. The WSGI application can use those endpoints to get the</span>
  64. <span class="sd"> handler for that URL. It doesn&#39;t have to be a string at all but it&#39;s</span>
  65. <span class="sd"> recommended.</span>
  66. <span class="sd"> Now it&#39;s possible to create a URL adapter for one of the subdomains and</span>
  67. <span class="sd"> build URLs:</span>
  68. <span class="sd"> &gt;&gt;&gt; c = m.bind(&#39;example.com&#39;)</span>
  69. <span class="sd"> &gt;&gt;&gt; c.build(&quot;kb/browse&quot;, dict(id=42))</span>
  70. <span class="sd"> &#39;http://kb.example.com/browse/42/&#39;</span>
  71. <span class="sd"> &gt;&gt;&gt; c.build(&quot;kb/browse&quot;, dict())</span>
  72. <span class="sd"> &#39;http://kb.example.com/browse/&#39;</span>
  73. <span class="sd"> &gt;&gt;&gt; c.build(&quot;kb/browse&quot;, dict(id=42, page=3))</span>
  74. <span class="sd"> &#39;http://kb.example.com/browse/42/3&#39;</span>
  75. <span class="sd"> &gt;&gt;&gt; c.build(&quot;static/about&quot;)</span>
  76. <span class="sd"> &#39;/about&#39;</span>
  77. <span class="sd"> &gt;&gt;&gt; c.build(&quot;static/index&quot;, force_external=True)</span>
  78. <span class="sd"> &#39;http://www.example.com/&#39;</span>
  79. <span class="sd"> &gt;&gt;&gt; c = m.bind(&#39;example.com&#39;, subdomain=&#39;kb&#39;)</span>
  80. <span class="sd"> &gt;&gt;&gt; c.build(&quot;static/about&quot;)</span>
  81. <span class="sd"> &#39;http://www.example.com/about&#39;</span>
  82. <span class="sd"> The first argument to bind is the server name *without* the subdomain.</span>
  83. <span class="sd"> Per default it will assume that the script is mounted on the root, but</span>
  84. <span class="sd"> often that&#39;s not the case so you can provide the real mount point as</span>
  85. <span class="sd"> second argument:</span>
  86. <span class="sd"> &gt;&gt;&gt; c = m.bind(&#39;example.com&#39;, &#39;/applications/example&#39;)</span>
  87. <span class="sd"> The third argument can be the subdomain, if not given the default</span>
  88. <span class="sd"> subdomain is used. For more details about binding have a look at the</span>
  89. <span class="sd"> documentation of the `MapAdapter`.</span>
  90. <span class="sd"> And here is how you can match URLs:</span>
  91. <span class="sd"> &gt;&gt;&gt; c = m.bind(&#39;example.com&#39;)</span>
  92. <span class="sd"> &gt;&gt;&gt; c.match(&quot;/&quot;)</span>
  93. <span class="sd"> (&#39;static/index&#39;, {})</span>
  94. <span class="sd"> &gt;&gt;&gt; c.match(&quot;/about&quot;)</span>
  95. <span class="sd"> (&#39;static/about&#39;, {})</span>
  96. <span class="sd"> &gt;&gt;&gt; c = m.bind(&#39;example.com&#39;, &#39;/&#39;, &#39;kb&#39;)</span>
  97. <span class="sd"> &gt;&gt;&gt; c.match(&quot;/&quot;)</span>
  98. <span class="sd"> (&#39;kb/index&#39;, {})</span>
  99. <span class="sd"> &gt;&gt;&gt; c.match(&quot;/browse/42/23&quot;)</span>
  100. <span class="sd"> (&#39;kb/browse&#39;, {&#39;id&#39;: 42, &#39;page&#39;: 23})</span>
  101. <span class="sd"> If matching fails you get a `NotFound` exception, if the rule thinks</span>
  102. <span class="sd"> it&#39;s a good idea to redirect (for example because the URL was defined</span>
  103. <span class="sd"> to have a slash at the end but the request was missing that slash) it</span>
  104. <span class="sd"> will raise a `RequestRedirect` exception. Both are subclasses of the</span>
  105. <span class="sd"> `HTTPException` so you can use those errors as responses in the</span>
  106. <span class="sd"> application.</span>
  107. <span class="sd"> If matching succeeded but the URL rule was incompatible to the given</span>
  108. <span class="sd"> method (for example there were only rules for `GET` and `HEAD` and</span>
  109. <span class="sd"> routing system tried to match a `POST` request) a `MethodNotAllowed`</span>
  110. <span class="sd"> method is raised.</span>
  111. <span class="sd"> :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details.</span>
  112. <span class="sd"> :license: BSD, see LICENSE for more details.</span>
  113. <span class="sd">&quot;&quot;&quot;</span>
  114. <span class="kn">import</span> <span class="nn">difflib</span>
  115. <span class="kn">import</span> <span class="nn">re</span>
  116. <span class="kn">import</span> <span class="nn">uuid</span>
  117. <span class="kn">import</span> <span class="nn">posixpath</span>
  118. <span class="kn">from</span> <span class="nn">pprint</span> <span class="k">import</span> <span class="n">pformat</span>
  119. <span class="kn">from</span> <span class="nn">threading</span> <span class="k">import</span> <span class="n">Lock</span>
  120. <span class="kn">from</span> <span class="nn">werkzeug.urls</span> <span class="k">import</span> <span class="n">url_encode</span><span class="p">,</span> <span class="n">url_quote</span><span class="p">,</span> <span class="n">url_join</span>
  121. <span class="kn">from</span> <span class="nn">werkzeug.utils</span> <span class="k">import</span> <span class="n">redirect</span><span class="p">,</span> <span class="n">format_string</span>
  122. <span class="kn">from</span> <span class="nn">werkzeug.exceptions</span> <span class="k">import</span> <span class="n">HTTPException</span><span class="p">,</span> <span class="n">NotFound</span><span class="p">,</span> <span class="n">MethodNotAllowed</span><span class="p">,</span> \
  123. <span class="n">BadHost</span>
  124. <span class="kn">from</span> <span class="nn">werkzeug._internal</span> <span class="k">import</span> <span class="n">_get_environ</span><span class="p">,</span> <span class="n">_encode_idna</span>
  125. <span class="kn">from</span> <span class="nn">werkzeug._compat</span> <span class="k">import</span> <span class="n">itervalues</span><span class="p">,</span> <span class="n">iteritems</span><span class="p">,</span> <span class="n">to_unicode</span><span class="p">,</span> <span class="n">to_bytes</span><span class="p">,</span> \
  126. <span class="n">text_type</span><span class="p">,</span> <span class="n">string_types</span><span class="p">,</span> <span class="n">native_string_result</span><span class="p">,</span> \
  127. <span class="n">implements_to_string</span><span class="p">,</span> <span class="n">wsgi_decoding_dance</span>
  128. <span class="kn">from</span> <span class="nn">werkzeug.datastructures</span> <span class="k">import</span> <span class="n">ImmutableDict</span><span class="p">,</span> <span class="n">MultiDict</span>
  129. <span class="n">_rule_re</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s1">r&#39;&#39;&#39;</span>
  130. <span class="s1"> (?P&lt;static&gt;[^&lt;]*) # static rule data</span>
  131. <span class="s1"> &lt;</span>
  132. <span class="s1"> (?:</span>
  133. <span class="s1"> (?P&lt;converter&gt;[a-zA-Z_][a-zA-Z0-9_]*) # converter name</span>
  134. <span class="s1"> (?:\((?P&lt;args&gt;.*?)\))? # converter arguments</span>
  135. <span class="s1"> \: # variable delimiter</span>
  136. <span class="s1"> )?</span>
  137. <span class="s1"> (?P&lt;variable&gt;[a-zA-Z_][a-zA-Z0-9_]*) # variable name</span>
  138. <span class="s1"> &gt;</span>
  139. <span class="s1">&#39;&#39;&#39;</span><span class="p">,</span> <span class="n">re</span><span class="o">.</span><span class="n">VERBOSE</span><span class="p">)</span>
  140. <span class="n">_simple_rule_re</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s1">r&#39;&lt;([^&gt;]+)&gt;&#39;</span><span class="p">)</span>
  141. <span class="n">_converter_args_re</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s1">r&#39;&#39;&#39;</span>
  142. <span class="s1"> ((?P&lt;name&gt;\w+)\s*=\s*)?</span>
  143. <span class="s1"> (?P&lt;value&gt;</span>
  144. <span class="s1"> True|False|</span>
  145. <span class="s1"> \d+.\d+|</span>
  146. <span class="s1"> \d+.|</span>
  147. <span class="s1"> \d+|</span>
  148. <span class="s1"> \w+|</span>
  149. <span class="s1"> [urUR]?(?P&lt;stringval&gt;&quot;[^&quot;]*?&quot;|&#39;[^&#39;]*&#39;)</span>
  150. <span class="s1"> )\s*,</span>
  151. <span class="s1">&#39;&#39;&#39;</span><span class="p">,</span> <span class="n">re</span><span class="o">.</span><span class="n">VERBOSE</span> <span class="o">|</span> <span class="n">re</span><span class="o">.</span><span class="n">UNICODE</span><span class="p">)</span>
  152. <span class="n">_PYTHON_CONSTANTS</span> <span class="o">=</span> <span class="p">{</span>
  153. <span class="s1">&#39;None&#39;</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
  154. <span class="s1">&#39;True&#39;</span><span class="p">:</span> <span class="kc">True</span><span class="p">,</span>
  155. <span class="s1">&#39;False&#39;</span><span class="p">:</span> <span class="kc">False</span>
  156. <span class="p">}</span>
  157. <span class="k">def</span> <span class="nf">_pythonize</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
  158. <span class="k">if</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">_PYTHON_CONSTANTS</span><span class="p">:</span>
  159. <span class="k">return</span> <span class="n">_PYTHON_CONSTANTS</span><span class="p">[</span><span class="n">value</span><span class="p">]</span>
  160. <span class="k">for</span> <span class="n">convert</span> <span class="ow">in</span> <span class="nb">int</span><span class="p">,</span> <span class="nb">float</span><span class="p">:</span>
  161. <span class="k">try</span><span class="p">:</span>
  162. <span class="k">return</span> <span class="n">convert</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
  163. <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
  164. <span class="k">pass</span>
  165. <span class="k">if</span> <span class="n">value</span><span class="p">[:</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">value</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">:]</span> <span class="ow">and</span> <span class="n">value</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="s1">&#39;&quot;</span><span class="se">\&#39;</span><span class="s1">&#39;</span><span class="p">:</span>
  166. <span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
  167. <span class="k">return</span> <span class="n">text_type</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
  168. <span class="k">def</span> <span class="nf">parse_converter_args</span><span class="p">(</span><span class="n">argstr</span><span class="p">):</span>
  169. <span class="n">argstr</span> <span class="o">+=</span> <span class="s1">&#39;,&#39;</span>
  170. <span class="n">args</span> <span class="o">=</span> <span class="p">[]</span>
  171. <span class="n">kwargs</span> <span class="o">=</span> <span class="p">{}</span>
  172. <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">_converter_args_re</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">argstr</span><span class="p">):</span>
  173. <span class="n">value</span> <span class="o">=</span> <span class="n">item</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s1">&#39;stringval&#39;</span><span class="p">)</span>
  174. <span class="k">if</span> <span class="n">value</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
  175. <span class="n">value</span> <span class="o">=</span> <span class="n">item</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s1">&#39;value&#39;</span><span class="p">)</span>
  176. <span class="n">value</span> <span class="o">=</span> <span class="n">_pythonize</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
  177. <span class="k">if</span> <span class="ow">not</span> <span class="n">item</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">):</span>
  178. <span class="n">args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
  179. <span class="k">else</span><span class="p">:</span>
  180. <span class="n">name</span> <span class="o">=</span> <span class="n">item</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">)</span>
  181. <span class="n">kwargs</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
  182. <span class="k">return</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">args</span><span class="p">),</span> <span class="n">kwargs</span>
  183. <span class="k">def</span> <span class="nf">parse_rule</span><span class="p">(</span><span class="n">rule</span><span class="p">):</span>
  184. <span class="sd">&quot;&quot;&quot;Parse a rule and return it as generator. Each iteration yields tuples</span>
  185. <span class="sd"> in the form ``(converter, arguments, variable)``. If the converter is</span>
  186. <span class="sd"> `None` it&#39;s a static url part, otherwise it&#39;s a dynamic one.</span>
  187. <span class="sd"> :internal:</span>
  188. <span class="sd"> &quot;&quot;&quot;</span>
  189. <span class="n">pos</span> <span class="o">=</span> <span class="mi">0</span>
  190. <span class="n">end</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">rule</span><span class="p">)</span>
  191. <span class="n">do_match</span> <span class="o">=</span> <span class="n">_rule_re</span><span class="o">.</span><span class="n">match</span>
  192. <span class="n">used_names</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
  193. <span class="k">while</span> <span class="n">pos</span> <span class="o">&lt;</span> <span class="n">end</span><span class="p">:</span>
  194. <span class="n">m</span> <span class="o">=</span> <span class="n">do_match</span><span class="p">(</span><span class="n">rule</span><span class="p">,</span> <span class="n">pos</span><span class="p">)</span>
  195. <span class="k">if</span> <span class="n">m</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
  196. <span class="k">break</span>
  197. <span class="n">data</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">groupdict</span><span class="p">()</span>
  198. <span class="k">if</span> <span class="n">data</span><span class="p">[</span><span class="s1">&#39;static&#39;</span><span class="p">]:</span>
  199. <span class="k">yield</span> <span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="n">data</span><span class="p">[</span><span class="s1">&#39;static&#39;</span><span class="p">]</span>
  200. <span class="n">variable</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="s1">&#39;variable&#39;</span><span class="p">]</span>
  201. <span class="n">converter</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="s1">&#39;converter&#39;</span><span class="p">]</span> <span class="ow">or</span> <span class="s1">&#39;default&#39;</span>
  202. <span class="k">if</span> <span class="n">variable</span> <span class="ow">in</span> <span class="n">used_names</span><span class="p">:</span>
  203. <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s1">&#39;variable name </span><span class="si">%r</span><span class="s1"> used twice.&#39;</span> <span class="o">%</span> <span class="n">variable</span><span class="p">)</span>
  204. <span class="n">used_names</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">variable</span><span class="p">)</span>
  205. <span class="k">yield</span> <span class="n">converter</span><span class="p">,</span> <span class="n">data</span><span class="p">[</span><span class="s1">&#39;args&#39;</span><span class="p">]</span> <span class="ow">or</span> <span class="kc">None</span><span class="p">,</span> <span class="n">variable</span>
  206. <span class="n">pos</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">end</span><span class="p">()</span>
  207. <span class="k">if</span> <span class="n">pos</span> <span class="o">&lt;</span> <span class="n">end</span><span class="p">:</span>
  208. <span class="n">remaining</span> <span class="o">=</span> <span class="n">rule</span><span class="p">[</span><span class="n">pos</span><span class="p">:]</span>
  209. <span class="k">if</span> <span class="s1">&#39;&gt;&#39;</span> <span class="ow">in</span> <span class="n">remaining</span> <span class="ow">or</span> <span class="s1">&#39;&lt;&#39;</span> <span class="ow">in</span> <span class="n">remaining</span><span class="p">:</span>
  210. <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s1">&#39;malformed url rule: </span><span class="si">%r</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">rule</span><span class="p">)</span>
  211. <span class="k">yield</span> <span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="n">remaining</span>
  212. <span class="k">class</span> <span class="nc">RoutingException</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
  213. <span class="sd">&quot;&quot;&quot;Special exceptions that require the application to redirect, notifying</span>
  214. <span class="sd"> about missing urls, etc.</span>
  215. <span class="sd"> :internal:</span>
  216. <span class="sd"> &quot;&quot;&quot;</span>
  217. <span class="k">class</span> <span class="nc">RequestRedirect</span><span class="p">(</span><span class="n">HTTPException</span><span class="p">,</span> <span class="n">RoutingException</span><span class="p">):</span>
  218. <span class="sd">&quot;&quot;&quot;Raise if the map requests a redirect. This is for example the case if</span>
  219. <span class="sd"> `strict_slashes` are activated and an url that requires a trailing slash.</span>
  220. <span class="sd"> The attribute `new_url` contains the absolute destination url.</span>
  221. <span class="sd"> &quot;&quot;&quot;</span>
  222. <span class="n">code</span> <span class="o">=</span> <span class="mi">301</span>
  223. <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">new_url</span><span class="p">):</span>
  224. <span class="n">RoutingException</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">new_url</span><span class="p">)</span>
  225. <span class="bp">self</span><span class="o">.</span><span class="n">new_url</span> <span class="o">=</span> <span class="n">new_url</span>
  226. <span class="k">def</span> <span class="nf">get_response</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">):</span>
  227. <span class="k">return</span> <span class="n">redirect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">new_url</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">code</span><span class="p">)</span>
  228. <span class="k">class</span> <span class="nc">RequestSlash</span><span class="p">(</span><span class="n">RoutingException</span><span class="p">):</span>
  229. <span class="sd">&quot;&quot;&quot;Internal exception.&quot;&quot;&quot;</span>
  230. <span class="k">class</span> <span class="nc">RequestAliasRedirect</span><span class="p">(</span><span class="n">RoutingException</span><span class="p">):</span>
  231. <span class="sd">&quot;&quot;&quot;This rule is an alias and wants to redirect to the canonical URL.&quot;&quot;&quot;</span>
  232. <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">matched_values</span><span class="p">):</span>
  233. <span class="bp">self</span><span class="o">.</span><span class="n">matched_values</span> <span class="o">=</span> <span class="n">matched_values</span>
  234. <span class="k">class</span> <span class="nc">BuildError</span><span class="p">(</span><span class="n">RoutingException</span><span class="p">,</span> <span class="ne">LookupError</span><span class="p">):</span>
  235. <span class="sd">&quot;&quot;&quot;Raised if the build system cannot find a URL for an endpoint with the</span>
  236. <span class="sd"> values provided.</span>
  237. <span class="sd"> &quot;&quot;&quot;</span>
  238. <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="n">adapter</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
  239. <span class="ne">LookupError</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">,</span> <span class="n">method</span><span class="p">)</span>
  240. <span class="bp">self</span><span class="o">.</span><span class="n">endpoint</span> <span class="o">=</span> <span class="n">endpoint</span>
  241. <span class="bp">self</span><span class="o">.</span><span class="n">values</span> <span class="o">=</span> <span class="n">values</span>
  242. <span class="bp">self</span><span class="o">.</span><span class="n">method</span> <span class="o">=</span> <span class="n">method</span>
  243. <span class="bp">self</span><span class="o">.</span><span class="n">suggested</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">closest_rule</span><span class="p">(</span><span class="n">adapter</span><span class="p">)</span>
  244. <span class="k">def</span> <span class="nf">closest_rule</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">adapter</span><span class="p">):</span>
  245. <span class="k">def</span> <span class="nf">score_rule</span><span class="p">(</span><span class="n">rule</span><span class="p">):</span>
  246. <span class="k">return</span> <span class="nb">sum</span><span class="p">([</span>
  247. <span class="mf">0.98</span> <span class="o">*</span> <span class="n">difflib</span><span class="o">.</span><span class="n">SequenceMatcher</span><span class="p">(</span>
  248. <span class="kc">None</span><span class="p">,</span> <span class="n">rule</span><span class="o">.</span><span class="n">endpoint</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">endpoint</span>
  249. <span class="p">)</span><span class="o">.</span><span class="n">ratio</span><span class="p">(),</span>
  250. <span class="mf">0.01</span> <span class="o">*</span> <span class="nb">bool</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">values</span> <span class="ow">or</span> <span class="p">())</span><span class="o">.</span><span class="n">issubset</span><span class="p">(</span><span class="n">rule</span><span class="o">.</span><span class="n">arguments</span><span class="p">)),</span>
  251. <span class="mf">0.01</span> <span class="o">*</span> <span class="nb">bool</span><span class="p">(</span><span class="n">rule</span><span class="o">.</span><span class="n">methods</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">method</span> <span class="ow">in</span> <span class="n">rule</span><span class="o">.</span><span class="n">methods</span><span class="p">)</span>
  252. <span class="p">])</span>
  253. <span class="k">if</span> <span class="n">adapter</span> <span class="ow">and</span> <span class="n">adapter</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">_rules</span><span class="p">:</span>
  254. <span class="k">return</span> <span class="nb">max</span><span class="p">(</span><span class="n">adapter</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">_rules</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">score_rule</span><span class="p">)</span>
  255. <span class="k">else</span><span class="p">:</span>
  256. <span class="k">return</span> <span class="kc">None</span>
  257. <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
  258. <span class="n">message</span> <span class="o">=</span> <span class="p">[]</span>
  259. <span class="n">message</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;Could not build url for endpoint </span><span class="si">%r</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">endpoint</span><span class="p">)</span>
  260. <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">method</span><span class="p">:</span>
  261. <span class="n">message</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot; (</span><span class="si">%r</span><span class="s2">)&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">method</span><span class="p">)</span>
  262. <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">values</span><span class="p">:</span>
  263. <span class="n">message</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot; with values </span><span class="si">%r</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="nb">sorted</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">values</span><span class="o">.</span><span class="n">keys</span><span class="p">()))</span>
  264. <span class="n">message</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;.&quot;</span><span class="p">)</span>
  265. <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">suggested</span><span class="p">:</span>
  266. <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">endpoint</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">suggested</span><span class="o">.</span><span class="n">endpoint</span><span class="p">:</span>
  267. <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">method</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">method</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">suggested</span><span class="o">.</span><span class="n">methods</span><span class="p">:</span>
  268. <span class="n">message</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot; Did you mean to use methods </span><span class="si">%r</span><span class="s2">?&quot;</span> <span class="o">%</span> <span class="nb">sorted</span><span class="p">(</span>
  269. <span class="bp">self</span><span class="o">.</span><span class="n">suggested</span><span class="o">.</span><span class="n">methods</span>
  270. <span class="p">))</span>
  271. <span class="n">missing_values</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">suggested</span><span class="o">.</span><span class="n">arguments</span><span class="o">.</span><span class="n">union</span><span class="p">(</span>
  272. <span class="nb">set</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">suggested</span><span class="o">.</span><span class="n">defaults</span> <span class="ow">or</span> <span class="p">())</span>
  273. <span class="p">)</span> <span class="o">-</span> <span class="nb">set</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">values</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span>
  274. <span class="k">if</span> <span class="n">missing_values</span><span class="p">:</span>
  275. <span class="n">message</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
  276. <span class="s2">&quot; Did you forget to specify values </span><span class="si">%r</span><span class="s2">?&quot;</span> <span class="o">%</span>
  277. <span class="nb">sorted</span><span class="p">(</span><span class="n">missing_values</span><span class="p">)</span>
  278. <span class="p">)</span>
  279. <span class="k">else</span><span class="p">:</span>
  280. <span class="n">message</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
  281. <span class="s2">&quot; Did you mean </span><span class="si">%r</span><span class="s2"> instead?&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">suggested</span><span class="o">.</span><span class="n">endpoint</span>
  282. <span class="p">)</span>
  283. <span class="k">return</span> <span class="s2">&quot;&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
  284. <span class="k">class</span> <span class="nc">ValidationError</span><span class="p">(</span><span class="ne">ValueError</span><span class="p">):</span>
  285. <span class="sd">&quot;&quot;&quot;Validation error. If a rule converter raises this exception the rule</span>
  286. <span class="sd"> does not match the current URL and the next URL is tried.</span>
  287. <span class="sd"> &quot;&quot;&quot;</span>
  288. <span class="k">class</span> <span class="nc">RuleFactory</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
  289. <span class="sd">&quot;&quot;&quot;As soon as you have more complex URL setups it&#39;s a good idea to use rule</span>
  290. <span class="sd"> factories to avoid repetitive tasks. Some of them are builtin, others can</span>
  291. <span class="sd"> be added by subclassing `RuleFactory` and overriding `get_rules`.</span>
  292. <span class="sd"> &quot;&quot;&quot;</span>
  293. <span class="k">def</span> <span class="nf">get_rules</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">map</span><span class="p">):</span>
  294. <span class="sd">&quot;&quot;&quot;Subclasses of `RuleFactory` have to override this method and return</span>
  295. <span class="sd"> an iterable of rules.&quot;&quot;&quot;</span>
  296. <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">()</span>
  297. <span class="k">class</span> <span class="nc">Subdomain</span><span class="p">(</span><span class="n">RuleFactory</span><span class="p">):</span>
  298. <span class="sd">&quot;&quot;&quot;All URLs provided by this factory have the subdomain set to a</span>
  299. <span class="sd"> specific domain. For example if you want to use the subdomain for</span>
  300. <span class="sd"> the current language this can be a good setup::</span>
  301. <span class="sd"> url_map = Map([</span>
  302. <span class="sd"> Rule(&#39;/&#39;, endpoint=&#39;#select_language&#39;),</span>
  303. <span class="sd"> Subdomain(&#39;&lt;string(length=2):lang_code&gt;&#39;, [</span>
  304. <span class="sd"> Rule(&#39;/&#39;, endpoint=&#39;index&#39;),</span>
  305. <span class="sd"> Rule(&#39;/about&#39;, endpoint=&#39;about&#39;),</span>
  306. <span class="sd"> Rule(&#39;/help&#39;, endpoint=&#39;help&#39;)</span>
  307. <span class="sd"> ])</span>
  308. <span class="sd"> ])</span>
  309. <span class="sd"> All the rules except for the ``&#39;#select_language&#39;`` endpoint will now</span>
  310. <span class="sd"> listen on a two letter long subdomain that holds the language code</span>
  311. <span class="sd"> for the current request.</span>
  312. <span class="sd"> &quot;&quot;&quot;</span>
  313. <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">subdomain</span><span class="p">,</span> <span class="n">rules</span><span class="p">):</span>
  314. <span class="bp">self</span><span class="o">.</span><span class="n">subdomain</span> <span class="o">=</span> <span class="n">subdomain</span>
  315. <span class="bp">self</span><span class="o">.</span><span class="n">rules</span> <span class="o">=</span> <span class="n">rules</span>
  316. <span class="k">def</span> <span class="nf">get_rules</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">map</span><span class="p">):</span>
  317. <span class="k">for</span> <span class="n">rulefactory</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">rules</span><span class="p">:</span>
  318. <span class="k">for</span> <span class="n">rule</span> <span class="ow">in</span> <span class="n">rulefactory</span><span class="o">.</span><span class="n">get_rules</span><span class="p">(</span><span class="nb">map</span><span class="p">):</span>
  319. <span class="n">rule</span> <span class="o">=</span> <span class="n">rule</span><span class="o">.</span><span class="n">empty</span><span class="p">()</span>
  320. <span class="n">rule</span><span class="o">.</span><span class="n">subdomain</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">subdomain</span>
  321. <span class="k">yield</span> <span class="n">rule</span>
  322. <span class="k">class</span> <span class="nc">Submount</span><span class="p">(</span><span class="n">RuleFactory</span><span class="p">):</span>
  323. <span class="sd">&quot;&quot;&quot;Like `Subdomain` but prefixes the URL rule with a given string::</span>
  324. <span class="sd"> url_map = Map([</span>
  325. <span class="sd"> Rule(&#39;/&#39;, endpoint=&#39;index&#39;),</span>
  326. <span class="sd"> Submount(&#39;/blog&#39;, [</span>
  327. <span class="sd"> Rule(&#39;/&#39;, endpoint=&#39;blog/index&#39;),</span>
  328. <span class="sd"> Rule(&#39;/entry/&lt;entry_slug&gt;&#39;, endpoint=&#39;blog/show&#39;)</span>
  329. <span class="sd"> ])</span>
  330. <span class="sd"> ])</span>
  331. <span class="sd"> Now the rule ``&#39;blog/show&#39;`` matches ``/blog/entry/&lt;entry_slug&gt;``.</span>
  332. <span class="sd"> &quot;&quot;&quot;</span>
  333. <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="n">rules</span><span class="p">):</span>
  334. <span class="bp">self</span><span class="o">.</span><span class="n">path</span> <span class="o">=</span> <span class="n">path</span><span class="o">.</span><span class="n">rstrip</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">)</span>
  335. <span class="bp">self</span><span class="o">.</span><span class="n">rules</span> <span class="o">=</span> <span class="n">rules</span>
  336. <span class="k">def</span> <span class="nf">get_rules</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">map</span><span class="p">):</span>
  337. <span class="k">for</span> <span class="n">rulefactory</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">rules</span><span class="p">:</span>
  338. <span class="k">for</span> <span class="n">rule</span> <span class="ow">in</span> <span class="n">rulefactory</span><span class="o">.</span><span class="n">get_rules</span><span class="p">(</span><span class="nb">map</span><span class="p">):</span>
  339. <span class="n">rule</span> <span class="o">=</span> <span class="n">rule</span><span class="o">.</span><span class="n">empty</span><span class="p">()</span>
  340. <span class="n">rule</span><span class="o">.</span><span class="n">rule</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">path</span> <span class="o">+</span> <span class="n">rule</span><span class="o">.</span><span class="n">rule</span>
  341. <span class="k">yield</span> <span class="n">rule</span>
  342. <span class="k">class</span> <span class="nc">EndpointPrefix</span><span class="p">(</span><span class="n">RuleFactory</span><span class="p">):</span>
  343. <span class="sd">&quot;&quot;&quot;Prefixes all endpoints (which must be strings for this factory) with</span>
  344. <span class="sd"> another string. This can be useful for sub applications::</span>
  345. <span class="sd"> url_map = Map([</span>
  346. <span class="sd"> Rule(&#39;/&#39;, endpoint=&#39;index&#39;),</span>
  347. <span class="sd"> EndpointPrefix(&#39;blog/&#39;, [Submount(&#39;/blog&#39;, [</span>
  348. <span class="sd"> Rule(&#39;/&#39;, endpoint=&#39;index&#39;),</span>
  349. <span class="sd"> Rule(&#39;/entry/&lt;entry_slug&gt;&#39;, endpoint=&#39;show&#39;)</span>
  350. <span class="sd"> ])])</span>
  351. <span class="sd"> ])</span>
  352. <span class="sd"> &quot;&quot;&quot;</span>
  353. <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">prefix</span><span class="p">,</span> <span class="n">rules</span><span class="p">):</span>
  354. <span class="bp">self</span><span class="o">.</span><span class="n">prefix</span> <span class="o">=</span> <span class="n">prefix</span>
  355. <span class="bp">self</span><span class="o">.</span><span class="n">rules</span> <span class="o">=</span> <span class="n">rules</span>
  356. <span class="k">def</span> <span class="nf">get_rules</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">map</span><span class="p">):</span>
  357. <span class="k">for</span> <span class="n">rulefactory</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">rules</span><span class="p">:</span>
  358. <span class="k">for</span> <span class="n">rule</span> <span class="ow">in</span> <span class="n">rulefactory</span><span class="o">.</span><span class="n">get_rules</span><span class="p">(</span><span class="nb">map</span><span class="p">):</span>
  359. <span class="n">rule</span> <span class="o">=</span> <span class="n">rule</span><span class="o">.</span><span class="n">empty</span><span class="p">()</span>
  360. <span class="n">rule</span><span class="o">.</span><span class="n">endpoint</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">prefix</span> <span class="o">+</span> <span class="n">rule</span><span class="o">.</span><span class="n">endpoint</span>
  361. <span class="k">yield</span> <span class="n">rule</span>
  362. <span class="k">class</span> <span class="nc">RuleTemplate</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
  363. <span class="sd">&quot;&quot;&quot;Returns copies of the rules wrapped and expands string templates in</span>
  364. <span class="sd"> the endpoint, rule, defaults or subdomain sections.</span>
  365. <span class="sd"> Here a small example for such a rule template::</span>
  366. <span class="sd"> from werkzeug.routing import Map, Rule, RuleTemplate</span>
  367. <span class="sd"> resource = RuleTemplate([</span>
  368. <span class="sd"> Rule(&#39;/$name/&#39;, endpoint=&#39;$name.list&#39;),</span>
  369. <span class="sd"> Rule(&#39;/$name/&lt;int:id&gt;&#39;, endpoint=&#39;$name.show&#39;)</span>
  370. <span class="sd"> ])</span>
  371. <span class="sd"> url_map = Map([resource(name=&#39;user&#39;), resource(name=&#39;page&#39;)])</span>
  372. <span class="sd"> When a rule template is called the keyword arguments are used to</span>
  373. <span class="sd"> replace the placeholders in all the string parameters.</span>
  374. <span class="sd"> &quot;&quot;&quot;</span>
  375. <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">rules</span><span class="p">):</span>
  376. <span class="bp">self</span><span class="o">.</span><span class="n">rules</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">rules</span><span class="p">)</span>
  377. <span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
  378. <span class="k">return</span> <span class="n">RuleTemplateFactory</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">rules</span><span class="p">,</span> <span class="nb">dict</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">))</span>
  379. <span class="k">class</span> <span class="nc">RuleTemplateFactory</span><span class="p">(</span><span class="n">RuleFactory</span><span class="p">):</span>
  380. <span class="sd">&quot;&quot;&quot;A factory that fills in template variables into rules. Used by</span>
  381. <span class="sd"> `RuleTemplate` internally.</span>
  382. <span class="sd"> :internal:</span>
  383. <span class="sd"> &quot;&quot;&quot;</span>
  384. <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">rules</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span>
  385. <span class="bp">self</span><span class="o">.</span><span class="n">rules</span> <span class="o">=</span> <span class="n">rules</span>
  386. <span class="bp">self</span><span class="o">.</span><span class="n">context</span> <span class="o">=</span> <span class="n">context</span>
  387. <span class="k">def</span> <span class="nf">get_rules</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">map</span><span class="p">):</span>
  388. <span class="k">for</span> <span class="n">rulefactory</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">rules</span><span class="p">:</span>
  389. <span class="k">for</span> <span class="n">rule</span> <span class="ow">in</span> <span class="n">rulefactory</span><span class="o">.</span><span class="n">get_rules</span><span class="p">(</span><span class="nb">map</span><span class="p">):</span>
  390. <span class="n">new_defaults</span> <span class="o">=</span> <span class="n">subdomain</span> <span class="o">=</span> <span class="kc">None</span>
  391. <span class="k">if</span> <span class="n">rule</span><span class="o">.</span><span class="n">defaults</span><span class="p">:</span>
  392. <span class="n">new_defaults</span> <span class="o">=</span> <span class="p">{}</span>
  393. <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">iteritems</span><span class="p">(</span><span class="n">rule</span><span class="o">.</span><span class="n">defaults</span><span class="p">):</span>
  394. <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">string_types</span><span class="p">):</span>
  395. <span class="n">value</span> <span class="o">=</span> <span class="n">format_string</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">context</span><span class="p">)</span>
  396. <span class="n">new_defaults</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
  397. <span class="k">if</span> <span class="n">rule</span><span class="o">.</span><span class="n">subdomain</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
  398. <span class="n">subdomain</span> <span class="o">=</span> <span class="n">format_string</span><span class="p">(</span><span class="n">rule</span><span class="o">.</span><span class="n">subdomain</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">context</span><span class="p">)</span>
  399. <span class="n">new_endpoint</span> <span class="o">=</span> <span class="n">rule</span><span class="o">.</span><span class="n">endpoint</span>
  400. <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">new_endpoint</span><span class="p">,</span> <span class="n">string_types</span><span class="p">):</span>
  401. <span class="n">new_endpoint</span> <span class="o">=</span> <span class="n">format_string</span><span class="p">(</span><span class="n">new_endpoint</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">context</span><span class="p">)</span>
  402. <span class="k">yield</span> <span class="n">Rule</span><span class="p">(</span>
  403. <span class="n">format_string</span><span class="p">(</span><span class="n">rule</span><span class="o">.</span><span class="n">rule</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">context</span><span class="p">),</span>
  404. <span class="n">new_defaults</span><span class="p">,</span>
  405. <span class="n">subdomain</span><span class="p">,</span>
  406. <span class="n">rule</span><span class="o">.</span><span class="n">methods</span><span class="p">,</span>
  407. <span class="n">rule</span><span class="o">.</span><span class="n">build_only</span><span class="p">,</span>
  408. <span class="n">new_endpoint</span><span class="p">,</span>
  409. <span class="n">rule</span><span class="o">.</span><span class="n">strict_slashes</span>
  410. <span class="p">)</span>
  411. <span class="nd">@implements_to_string</span>
  412. <span class="k">class</span> <span class="nc">Rule</span><span class="p">(</span><span class="n">RuleFactory</span><span class="p">):</span>
  413. <span class="sd">&quot;&quot;&quot;A Rule represents one URL pattern. There are some options for `Rule`</span>
  414. <span class="sd"> that change the way it behaves and are passed to the `Rule` constructor.</span>
  415. <span class="sd"> Note that besides the rule-string all arguments *must* be keyword arguments</span>
  416. <span class="sd"> in order to not break the application on Werkzeug upgrades.</span>
  417. <span class="sd"> `string`</span>
  418. <span class="sd"> Rule strings basically are just normal URL paths with placeholders in</span>
  419. <span class="sd"> the format ``&lt;converter(arguments):name&gt;`` where the converter and the</span>
  420. <span class="sd"> arguments are optional. If no converter is defined the `default`</span>
  421. <span class="sd"> converter is used which means `string` in the normal configuration.</span>
  422. <span class="sd"> URL rules that end with a slash are branch URLs, others are leaves.</span>
  423. <span class="sd"> If you have `strict_slashes` enabled (which is the default), all</span>
  424. <span class="sd"> branch URLs that are matched without a trailing slash will trigger a</span>
  425. <span class="sd"> redirect to the same URL with the missing slash appended.</span>
  426. <span class="sd"> The converters are defined on the `Map`.</span>
  427. <span class="sd"> `endpoint`</span>
  428. <span class="sd"> The endpoint for this rule. This can be anything. A reference to a</span>
  429. <span class="sd"> function, a string, a number etc. The preferred way is using a string</span>
  430. <span class="sd"> because the endpoint is used for URL generation.</span>
  431. <span class="sd"> `defaults`</span>
  432. <span class="sd"> An optional dict with defaults for other rules with the same endpoint.</span>
  433. <span class="sd"> This is a bit tricky but useful if you want to have unique URLs::</span>
  434. <span class="sd"> url_map = Map([</span>
  435. <span class="sd"> Rule(&#39;/all/&#39;, defaults={&#39;page&#39;: 1}, endpoint=&#39;all_entries&#39;),</span>
  436. <span class="sd"> Rule(&#39;/all/page/&lt;int:page&gt;&#39;, endpoint=&#39;all_entries&#39;)</span>
  437. <span class="sd"> ])</span>
  438. <span class="sd"> If a user now visits ``http://example.com/all/page/1`` he will be</span>
  439. <span class="sd"> redirected to ``http://example.com/all/``. If `redirect_defaults` is</span>
  440. <span class="sd"> disabled on the `Map` instance this will only affect the URL</span>
  441. <span class="sd"> generation.</span>
  442. <span class="sd"> `subdomain`</span>
  443. <span class="sd"> The subdomain rule string for this rule. If not specified the rule</span>
  444. <span class="sd"> only matches for the `default_subdomain` of the map. If the map is</span>
  445. <span class="sd"> not bound to a subdomain this feature is disabled.</span>
  446. <span class="sd"> Can be useful if you want to have user profiles on different subdomains</span>
  447. <span class="sd"> and all subdomains are forwarded to your application::</span>
  448. <span class="sd"> url_map = Map([</span>
  449. <span class="sd"> Rule(&#39;/&#39;, subdomain=&#39;&lt;username&gt;&#39;, endpoint=&#39;user/homepage&#39;),</span>
  450. <span class="sd"> Rule(&#39;/stats&#39;, subdomain=&#39;&lt;username&gt;&#39;, endpoint=&#39;user/stats&#39;)</span>
  451. <span class="sd"> ])</span>
  452. <span class="sd"> `methods`</span>
  453. <span class="sd"> A sequence of http methods this rule applies to. If not specified, all</span>
  454. <span class="sd"> methods are allowed. For example this can be useful if you want different</span>
  455. <span class="sd"> endpoints for `POST` and `GET`. If methods are defined and the path</span>
  456. <span class="sd"> matches but the method matched against is not in this list or in the</span>
  457. <span class="sd"> list of another rule for that path the error raised is of the type</span>
  458. <span class="sd"> `MethodNotAllowed` rather than `NotFound`. If `GET` is present in the</span>
  459. <span class="sd"> list of methods and `HEAD` is not, `HEAD` is added automatically.</span>
  460. <span class="sd"> .. versionchanged:: 0.6.1</span>
  461. <span class="sd"> `HEAD` is now automatically added to the methods if `GET` is</span>
  462. <span class="sd"> present. The reason for this is that existing code often did not</span>
  463. <span class="sd"> work properly in servers not rewriting `HEAD` to `GET`</span>
  464. <span class="sd"> automatically and it was not documented how `HEAD` should be</span>
  465. <span class="sd"> treated. This was considered a bug in Werkzeug because of that.</span>
  466. <span class="sd"> `strict_slashes`</span>
  467. <span class="sd"> Override the `Map` setting for `strict_slashes` only for this rule. If</span>
  468. <span class="sd"> not specified the `Map` setting is used.</span>
  469. <span class="sd"> `build_only`</span>
  470. <span class="sd"> Set this to True and the rule will never match but will create a URL</span>
  471. <span class="sd"> that can be build. This is useful if you have resources on a subdomain</span>
  472. <span class="sd"> or folder that are not handled by the WSGI application (like static data)</span>
  473. <span class="sd"> `redirect_to`</span>
  474. <span class="sd"> If given this must be either a string or callable. In case of a</span>
  475. <span class="sd"> callable it&#39;s called with the url adapter that triggered the match and</span>
  476. <span class="sd"> the values of the URL as keyword arguments and has to return the target</span>
  477. <span class="sd"> for the redirect, otherwise it has to be a string with placeholders in</span>
  478. <span class="sd"> rule syntax::</span>
  479. <span class="sd"> def foo_with_slug(adapter, id):</span>
  480. <span class="sd"> # ask the database for the slug for the old id. this of</span>
  481. <span class="sd"> # course has nothing to do with werkzeug.</span>
  482. <span class="sd"> return &#39;foo/&#39; + Foo.get_slug_for_id(id)</span>
  483. <span class="sd"> url_map = Map([</span>
  484. <span class="sd"> Rule(&#39;/foo/&lt;slug&gt;&#39;, endpoint=&#39;foo&#39;),</span>
  485. <span class="sd"> Rule(&#39;/some/old/url/&lt;slug&gt;&#39;, redirect_to=&#39;foo/&lt;slug&gt;&#39;),</span>
  486. <span class="sd"> Rule(&#39;/other/old/url/&lt;int:id&gt;&#39;, redirect_to=foo_with_slug)</span>
  487. <span class="sd"> ])</span>
  488. <span class="sd"> When the rule is matched the routing system will raise a</span>
  489. <span class="sd"> `RequestRedirect` exception with the target for the redirect.</span>
  490. <span class="sd"> Keep in mind that the URL will be joined against the URL root of the</span>
  491. <span class="sd"> script so don&#39;t use a leading slash on the target URL unless you</span>
  492. <span class="sd"> really mean root of that domain.</span>
  493. <span class="sd"> `alias`</span>
  494. <span class="sd"> If enabled this rule serves as an alias for another rule with the same</span>
  495. <span class="sd"> endpoint and arguments.</span>
  496. <span class="sd"> `host`</span>
  497. <span class="sd"> If provided and the URL map has host matching enabled this can be</span>
  498. <span class="sd"> used to provide a match rule for the whole host. This also means</span>
  499. <span class="sd"> that the subdomain feature is disabled.</span>
  500. <span class="sd"> .. versionadded:: 0.7</span>
  501. <span class="sd"> The `alias` and `host` parameters were added.</span>
  502. <span class="sd"> &quot;&quot;&quot;</span>
  503. <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">string</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">subdomain</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
  504. <span class="n">build_only</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">endpoint</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">strict_slashes</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
  505. <span class="n">redirect_to</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">alias</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">host</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
  506. <span class="k">if</span> <span class="ow">not</span> <span class="n">string</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">):</span>
  507. <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s1">&#39;urls must start with a leading slash&#39;</span><span class="p">)</span>
  508. <span class="bp">self</span><span class="o">.</span><span class="n">rule</span> <span class="o">=</span> <span class="n">string</span>
  509. <span class="bp">self</span><span class="o">.</span><span class="n">is_leaf</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">string</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">)</span>
  510. <span class="bp">self</span><span class="o">.</span><span class="n">map</span> <span class="o">=</span> <span class="kc">None</span>
  511. <span class="bp">self</span><span class="o">.</span><span class="n">strict_slashes</span> <span class="o">=</span> <span class="n">strict_slashes</span>
  512. <span class="bp">self</span><span class="o">.</span><span class="n">subdomain</span> <span class="o">=</span> <span class="n">subdomain</span>
  513. <span class="bp">self</span><span class="o">.</span><span class="n">host</span> <span class="o">=</span> <span class="n">host</span>
  514. <span class="bp">self</span><span class="o">.</span><span class="n">defaults</span> <span class="o">=</span> <span class="n">defaults</span>
  515. <span class="bp">self</span><span class="o">.</span><span class="n">build_only</span> <span class="o">=</span> <span class="n">build_only</span>
  516. <span class="bp">self</span><span class="o">.</span><span class="n">alias</span> <span class="o">=</span> <span class="n">alias</span>
  517. <span class="k">if</span> <span class="n">methods</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
  518. <span class="bp">self</span><span class="o">.</span><span class="n">methods</span> <span class="o">=</span> <span class="kc">None</span>
  519. <span class="k">else</span><span class="p">:</span>
  520. <span class="bp">self</span><span class="o">.</span><span class="n">methods</span> <span class="o">=</span> <span class="nb">set</span><span class="p">([</span><span class="n">x</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">methods</span><span class="p">])</span>
  521. <span class="k">if</span> <span class="s1">&#39;HEAD&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">methods</span> <span class="ow">and</span> <span class="s1">&#39;GET&#39;</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">methods</span><span class="p">:</span>
  522. <span class="bp">self</span><span class="o">.</span><span class="n">methods</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s1">&#39;HEAD&#39;</span><span class="p">)</span>
  523. <span class="bp">self</span><span class="o">.</span><span class="n">endpoint</span> <span class="o">=</span> <span class="n">endpoint</span>
  524. <span class="bp">self</span><span class="o">.</span><span class="n">redirect_to</span> <span class="o">=</span> <span class="n">redirect_to</span>
  525. <span class="k">if</span> <span class="n">defaults</span><span class="p">:</span>
  526. <span class="bp">self</span><span class="o">.</span><span class="n">arguments</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">defaults</span><span class="p">))</span>
  527. <span class="k">else</span><span class="p">:</span>
  528. <span class="bp">self</span><span class="o">.</span><span class="n">arguments</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
  529. <span class="bp">self</span><span class="o">.</span><span class="n">_trace</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_converters</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_regex</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_weights</span> <span class="o">=</span> <span class="kc">None</span>
  530. <span class="k">def</span> <span class="nf">empty</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
  531. <span class="sd">&quot;&quot;&quot;</span>
  532. <span class="sd"> Return an unbound copy of this rule.</span>
  533. <span class="sd"> This can be useful if want to reuse an already bound URL for another</span>
  534. <span class="sd"> map. See ``get_empty_kwargs`` to override what keyword arguments are</span>
  535. <span class="sd"> provided to the new copy.</span>
  536. <span class="sd"> &quot;&quot;&quot;</span>
  537. <span class="k">return</span> <span class="nb">type</span><span class="p">(</span><span class="bp">self</span><span class="p">)(</span><span class="bp">self</span><span class="o">.</span><span class="n">rule</span><span class="p">,</span> <span class="o">**</span><span class="bp">self</span><span class="o">.</span><span class="n">get_empty_kwargs</span><span class="p">())</span>
  538. <span class="k">def</span> <span class="nf">get_empty_kwargs</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
  539. <span class="sd">&quot;&quot;&quot;</span>
  540. <span class="sd"> Provides kwargs for instantiating empty copy with empty()</span>
  541. <span class="sd"> Use this method to provide custom keyword arguments to the subclass of</span>
  542. <span class="sd"> ``Rule`` when calling ``some_rule.empty()``. Helpful when the subclass</span>
  543. <span class="sd"> has custom keyword arguments that are needed at instantiation.</span>
  544. <span class="sd"> Must return a ``dict`` that will be provided as kwargs to the new</span>
  545. <span class="sd"> instance of ``Rule``, following the initial ``self.rule`` value which</span>
  546. <span class="sd"> is always provided as the first, required positional argument.</span>
  547. <span class="sd"> &quot;&quot;&quot;</span>
  548. <span class="n">defaults</span> <span class="o">=</span> <span class="kc">None</span>
  549. <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">defaults</span><span class="p">:</span>
  550. <span class="n">defaults</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
  551. <span class="k">return</span> <span class="nb">dict</span><span class="p">(</span><span class="n">defaults</span><span class="o">=</span><span class="n">defaults</span><span class="p">,</span> <span class="n">subdomain</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">subdomain</span><span class="p">,</span>
  552. <span class="n">methods</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">methods</span><span class="p">,</span> <span class="n">build_only</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">build_only</span><span class="p">,</span>
  553. <span class="n">endpoint</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">strict_slashes</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">strict_slashes</span><span class="p">,</span>
  554. <span class="n">redirect_to</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">redirect_to</span><span class="p">,</span> <span class="n">alias</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">alias</span><span class="p">,</span>
  555. <span class="n">host</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">host</span><span class="p">)</span>
  556. <span class="k">def</span> <span class="nf">get_rules</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">map</span><span class="p">):</span>
  557. <span class="k">yield</span> <span class="bp">self</span>
  558. <span class="k">def</span> <span class="nf">refresh</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
  559. <span class="sd">&quot;&quot;&quot;Rebinds and refreshes the URL. Call this if you modified the</span>
  560. <span class="sd"> rule in place.</span>
  561. <span class="sd"> :internal:</span>
  562. <span class="sd"> &quot;&quot;&quot;</span>
  563. <span class="bp">self</span><span class="o">.</span><span class="n">bind</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="p">,</span> <span class="n">rebind</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
  564. <span class="k">def</span> <span class="nf">bind</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">map</span><span class="p">,</span> <span class="n">rebind</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
  565. <span class="sd">&quot;&quot;&quot;Bind the url to a map and create a regular expression based on</span>
  566. <span class="sd"> the information from the rule itself and the defaults from the map.</span>
  567. <span class="sd"> :internal:</span>
  568. <span class="sd"> &quot;&quot;&quot;</span>
  569. <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">map</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">rebind</span><span class="p">:</span>
  570. <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s1">&#39;url rule </span><span class="si">%r</span><span class="s1"> already bound to map </span><span class="si">%r</span><span class="s1">&#39;</span> <span class="o">%</span>
  571. <span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="p">))</span>
  572. <span class="bp">self</span><span class="o">.</span><span class="n">map</span> <span class="o">=</span> <span class="nb">map</span>
  573. <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">strict_slashes</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
  574. <span class="bp">self</span><span class="o">.</span><span class="n">strict_slashes</span> <span class="o">=</span> <span class="nb">map</span><span class="o">.</span><span class="n">strict_slashes</span>
  575. <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">subdomain</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
  576. <span class="bp">self</span><span class="o">.</span><span class="n">subdomain</span> <span class="o">=</span> <span class="nb">map</span><span class="o">.</span><span class="n">default_subdomain</span>
  577. <span class="bp">self</span><span class="o">.</span><span class="n">compile</span><span class="p">()</span>
  578. <span class="k">def</span> <span class="nf">get_converter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">variable_name</span><span class="p">,</span> <span class="n">converter_name</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">):</span>
  579. <span class="sd">&quot;&quot;&quot;Looks up the converter for the given parameter.</span>
  580. <span class="sd"> .. versionadded:: 0.9</span>
  581. <span class="sd"> &quot;&quot;&quot;</span>
  582. <span class="k">if</span> <span class="n">converter_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">converters</span><span class="p">:</span>
  583. <span class="k">raise</span> <span class="ne">LookupError</span><span class="p">(</span><span class="s1">&#39;the converter </span><span class="si">%r</span><span class="s1"> does not exist&#39;</span> <span class="o">%</span> <span class="n">converter_name</span><span class="p">)</span>
  584. <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">converters</span><span class="p">[</span><span class="n">converter_name</span><span class="p">](</span><span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
  585. <span class="k">def</span> <span class="nf">compile</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
  586. <span class="sd">&quot;&quot;&quot;Compiles the regular expression and stores it.&quot;&quot;&quot;</span>
  587. <span class="k">assert</span> <span class="bp">self</span><span class="o">.</span><span class="n">map</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">,</span> <span class="s1">&#39;rule not bound&#39;</span>
  588. <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">host_matching</span><span class="p">:</span>
  589. <span class="n">domain_rule</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">host</span> <span class="ow">or</span> <span class="s1">&#39;&#39;</span>
  590. <span class="k">else</span><span class="p">:</span>
  591. <span class="n">domain_rule</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">subdomain</span> <span class="ow">or</span> <span class="s1">&#39;&#39;</span>
  592. <span class="bp">self</span><span class="o">.</span><span class="n">_trace</span> <span class="o">=</span> <span class="p">[]</span>
  593. <span class="bp">self</span><span class="o">.</span><span class="n">_converters</span> <span class="o">=</span> <span class="p">{}</span>
  594. <span class="bp">self</span><span class="o">.</span><span class="n">_weights</span> <span class="o">=</span> <span class="p">[]</span>
  595. <span class="n">regex_parts</span> <span class="o">=</span> <span class="p">[]</span>
  596. <span class="k">def</span> <span class="nf">_build_regex</span><span class="p">(</span><span class="n">rule</span><span class="p">):</span>
  597. <span class="k">for</span> <span class="n">converter</span><span class="p">,</span> <span class="n">arguments</span><span class="p">,</span> <span class="n">variable</span> <span class="ow">in</span> <span class="n">parse_rule</span><span class="p">(</span><span class="n">rule</span><span class="p">):</span>
  598. <span class="k">if</span> <span class="n">converter</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
  599. <span class="n">regex_parts</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">escape</span><span class="p">(</span><span class="n">variable</span><span class="p">))</span>
  600. <span class="bp">self</span><span class="o">.</span><span class="n">_trace</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="kc">False</span><span class="p">,</span> <span class="n">variable</span><span class="p">))</span>
  601. <span class="k">for</span> <span class="n">part</span> <span class="ow">in</span> <span class="n">variable</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">):</span>
  602. <span class="k">if</span> <span class="n">part</span><span class="p">:</span>
  603. <span class="bp">self</span><span class="o">.</span><span class="n">_weights</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="nb">len</span><span class="p">(</span><span class="n">part</span><span class="p">)))</span>
  604. <span class="k">else</span><span class="p">:</span>
  605. <span class="k">if</span> <span class="n">arguments</span><span class="p">:</span>
  606. <span class="n">c_args</span><span class="p">,</span> <span class="n">c_kwargs</span> <span class="o">=</span> <span class="n">parse_converter_args</span><span class="p">(</span><span class="n">arguments</span><span class="p">)</span>
  607. <span class="k">else</span><span class="p">:</span>
  608. <span class="n">c_args</span> <span class="o">=</span> <span class="p">()</span>
  609. <span class="n">c_kwargs</span> <span class="o">=</span> <span class="p">{}</span>
  610. <span class="n">convobj</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_converter</span><span class="p">(</span>
  611. <span class="n">variable</span><span class="p">,</span> <span class="n">converter</span><span class="p">,</span> <span class="n">c_args</span><span class="p">,</span> <span class="n">c_kwargs</span><span class="p">)</span>
  612. <span class="n">regex_parts</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;(?P&lt;</span><span class="si">%s</span><span class="s1">&gt;</span><span class="si">%s</span><span class="s1">)&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">variable</span><span class="p">,</span> <span class="n">convobj</span><span class="o">.</span><span class="n">regex</span><span class="p">))</span>
  613. <span class="bp">self</span><span class="o">.</span><span class="n">_converters</span><span class="p">[</span><span class="n">variable</span><span class="p">]</span> <span class="o">=</span> <span class="n">convobj</span>
  614. <span class="bp">self</span><span class="o">.</span><span class="n">_trace</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="kc">True</span><span class="p">,</span> <span class="n">variable</span><span class="p">))</span>
  615. <span class="bp">self</span><span class="o">.</span><span class="n">_weights</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="mi">1</span><span class="p">,</span> <span class="n">convobj</span><span class="o">.</span><span class="n">weight</span><span class="p">))</span>
  616. <span class="bp">self</span><span class="o">.</span><span class="n">arguments</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">variable</span><span class="p">))</span>
  617. <span class="n">_build_regex</span><span class="p">(</span><span class="n">domain_rule</span><span class="p">)</span>
  618. <span class="n">regex_parts</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\\</span><span class="s1">|&#39;</span><span class="p">)</span>
  619. <span class="bp">self</span><span class="o">.</span><span class="n">_trace</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="kc">False</span><span class="p">,</span> <span class="s1">&#39;|&#39;</span><span class="p">))</span>
  620. <span class="n">_build_regex</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">is_leaf</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">rule</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">rule</span><span class="o">.</span><span class="n">rstrip</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">))</span>
  621. <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_leaf</span><span class="p">:</span>
  622. <span class="bp">self</span><span class="o">.</span><span class="n">_trace</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="kc">False</span><span class="p">,</span> <span class="s1">&#39;/&#39;</span><span class="p">))</span>
  623. <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">build_only</span><span class="p">:</span>
  624. <span class="k">return</span>
  625. <span class="n">regex</span> <span class="o">=</span> <span class="s1">r&#39;^</span><span class="si">%s%s</span><span class="s1">$&#39;</span> <span class="o">%</span> <span class="p">(</span>
  626. <span class="s1">u&#39;&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">regex_parts</span><span class="p">),</span>
  627. <span class="p">(</span><span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_leaf</span> <span class="ow">or</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">strict_slashes</span><span class="p">)</span> <span class="ow">and</span>
  628. <span class="s1">&#39;(?&lt;!/)(?P&lt;__suffix__&gt;/?)&#39;</span> <span class="ow">or</span> <span class="s1">&#39;&#39;</span>
  629. <span class="p">)</span>
  630. <span class="bp">self</span><span class="o">.</span><span class="n">_regex</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="n">regex</span><span class="p">,</span> <span class="n">re</span><span class="o">.</span><span class="n">UNICODE</span><span class="p">)</span>
  631. <span class="k">def</span> <span class="nf">match</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">):</span>
  632. <span class="sd">&quot;&quot;&quot;Check if the rule matches a given path. Path is a string in the</span>
  633. <span class="sd"> form ``&quot;subdomain|/path(method)&quot;`` and is assembled by the map. If</span>
  634. <span class="sd"> the map is doing host matching the subdomain part will be the host</span>
  635. <span class="sd"> instead.</span>
  636. <span class="sd"> If the rule matches a dict with the converted values is returned,</span>
  637. <span class="sd"> otherwise the return value is `None`.</span>
  638. <span class="sd"> :internal:</span>
  639. <span class="sd"> &quot;&quot;&quot;</span>
  640. <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">build_only</span><span class="p">:</span>
  641. <span class="n">m</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_regex</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
  642. <span class="k">if</span> <span class="n">m</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
  643. <span class="n">groups</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">groupdict</span><span class="p">()</span>
  644. <span class="c1"># we have a folder like part of the url without a trailing</span>
  645. <span class="c1"># slash and strict slashes enabled. raise an exception that</span>
  646. <span class="c1"># tells the map to redirect to the same url but with a</span>
  647. <span class="c1"># trailing slash</span>
  648. <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">strict_slashes</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_leaf</span> <span class="ow">and</span> \
  649. <span class="ow">not</span> <span class="n">groups</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s1">&#39;__suffix__&#39;</span><span class="p">):</span>
  650. <span class="k">raise</span> <span class="n">RequestSlash</span><span class="p">()</span>
  651. <span class="c1"># if we are not in strict slashes mode we have to remove</span>
  652. <span class="c1"># a __suffix__</span>
  653. <span class="k">elif</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">strict_slashes</span><span class="p">:</span>
  654. <span class="k">del</span> <span class="n">groups</span><span class="p">[</span><span class="s1">&#39;__suffix__&#39;</span><span class="p">]</span>
  655. <span class="n">result</span> <span class="o">=</span> <span class="p">{}</span>
  656. <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">iteritems</span><span class="p">(</span><span class="n">groups</span><span class="p">):</span>
  657. <span class="k">try</span><span class="p">:</span>
  658. <span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_converters</span><span class="p">[</span><span class="n">name</span><span class="p">]</span><span class="o">.</span><span class="n">to_python</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
  659. <span class="k">except</span> <span class="n">ValidationError</span><span class="p">:</span>
  660. <span class="k">return</span>
  661. <span class="n">result</span><span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">name</span><span class="p">)]</span> <span class="o">=</span> <span class="n">value</span>
  662. <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">defaults</span><span class="p">:</span>
  663. <span class="n">result</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
  664. <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">alias</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">redirect_defaults</span><span class="p">:</span>
  665. <span class="k">raise</span> <span class="n">RequestAliasRedirect</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
  666. <span class="k">return</span> <span class="n">result</span>
  667. <span class="k">def</span> <span class="nf">build</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">values</span><span class="p">,</span> <span class="n">append_unknown</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
  668. <span class="sd">&quot;&quot;&quot;Assembles the relative url for that rule and the subdomain.</span>
  669. <span class="sd"> If building doesn&#39;t work for some reasons `None` is returned.</span>
  670. <span class="sd"> :internal:</span>
  671. <span class="sd"> &quot;&quot;&quot;</span>
  672. <span class="n">tmp</span> <span class="o">=</span> <span class="p">[]</span>
  673. <span class="n">add</span> <span class="o">=</span> <span class="n">tmp</span><span class="o">.</span><span class="n">append</span>
  674. <span class="n">processed</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">arguments</span><span class="p">)</span>
  675. <span class="k">for</span> <span class="n">is_dynamic</span><span class="p">,</span> <span class="n">data</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_trace</span><span class="p">:</span>
  676. <span class="k">if</span> <span class="n">is_dynamic</span><span class="p">:</span>
  677. <span class="k">try</span><span class="p">:</span>
  678. <span class="n">add</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_converters</span><span class="p">[</span><span class="n">data</span><span class="p">]</span><span class="o">.</span><span class="n">to_url</span><span class="p">(</span><span class="n">values</span><span class="p">[</span><span class="n">data</span><span class="p">]))</span>
  679. <span class="k">except</span> <span class="n">ValidationError</span><span class="p">:</span>
  680. <span class="k">return</span>
  681. <span class="n">processed</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
  682. <span class="k">else</span><span class="p">:</span>
  683. <span class="n">add</span><span class="p">(</span><span class="n">url_quote</span><span class="p">(</span><span class="n">to_bytes</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">charset</span><span class="p">),</span> <span class="n">safe</span><span class="o">=</span><span class="s1">&#39;/:|+&#39;</span><span class="p">))</span>
  684. <span class="n">domain_part</span><span class="p">,</span> <span class="n">url</span> <span class="o">=</span> <span class="p">(</span><span class="s1">u&#39;&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">tmp</span><span class="p">))</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">u&#39;|&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
  685. <span class="k">if</span> <span class="n">append_unknown</span><span class="p">:</span>
  686. <span class="n">query_vars</span> <span class="o">=</span> <span class="n">MultiDict</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>
  687. <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">processed</span><span class="p">:</span>
  688. <span class="k">if</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">query_vars</span><span class="p">:</span>
  689. <span class="k">del</span> <span class="n">query_vars</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>
  690. <span class="k">if</span> <span class="n">query_vars</span><span class="p">:</span>
  691. <span class="n">url</span> <span class="o">+=</span> <span class="s1">u&#39;?&#39;</span> <span class="o">+</span> <span class="n">url_encode</span><span class="p">(</span><span class="n">query_vars</span><span class="p">,</span> <span class="n">charset</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">charset</span><span class="p">,</span>
  692. <span class="n">sort</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">sort_parameters</span><span class="p">,</span>
  693. <span class="n">key</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">sort_key</span><span class="p">)</span>
  694. <span class="k">return</span> <span class="n">domain_part</span><span class="p">,</span> <span class="n">url</span>
  695. <span class="k">def</span> <span class="nf">provides_defaults_for</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">rule</span><span class="p">):</span>
  696. <span class="sd">&quot;&quot;&quot;Check if this rule has defaults for a given rule.</span>
  697. <span class="sd"> :internal:</span>
  698. <span class="sd"> &quot;&quot;&quot;</span>
  699. <span class="k">return</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">build_only</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">defaults</span> <span class="ow">and</span> \
  700. <span class="bp">self</span><span class="o">.</span><span class="n">endpoint</span> <span class="o">==</span> <span class="n">rule</span><span class="o">.</span><span class="n">endpoint</span> <span class="ow">and</span> <span class="bp">self</span> <span class="o">!=</span> <span class="n">rule</span> <span class="ow">and</span> \
  701. <span class="bp">self</span><span class="o">.</span><span class="n">arguments</span> <span class="o">==</span> <span class="n">rule</span><span class="o">.</span><span class="n">arguments</span>
  702. <span class="k">def</span> <span class="nf">suitable_for</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">values</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
  703. <span class="sd">&quot;&quot;&quot;Check if the dict of values has enough data for url generation.</span>
  704. <span class="sd"> :internal:</span>
  705. <span class="sd"> &quot;&quot;&quot;</span>
  706. <span class="c1"># if a method was given explicitly and that method is not supported</span>
  707. <span class="c1"># by this rule, this rule is not suitable.</span>
  708. <span class="k">if</span> <span class="n">method</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">methods</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> \
  709. <span class="ow">and</span> <span class="n">method</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">methods</span><span class="p">:</span>
  710. <span class="k">return</span> <span class="kc">False</span>
  711. <span class="n">defaults</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">defaults</span> <span class="ow">or</span> <span class="p">()</span>
  712. <span class="c1"># all arguments required must be either in the defaults dict or</span>
  713. <span class="c1"># the value dictionary otherwise it&#39;s not suitable</span>
  714. <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">arguments</span><span class="p">:</span>
  715. <span class="k">if</span> <span class="n">key</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">defaults</span> <span class="ow">and</span> <span class="n">key</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">values</span><span class="p">:</span>
  716. <span class="k">return</span> <span class="kc">False</span>
  717. <span class="c1"># in case defaults are given we ensure taht either the value was</span>
  718. <span class="c1"># skipped or the value is the same as the default value.</span>
  719. <span class="k">if</span> <span class="n">defaults</span><span class="p">:</span>
  720. <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">iteritems</span><span class="p">(</span><span class="n">defaults</span><span class="p">):</span>
  721. <span class="k">if</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">values</span> <span class="ow">and</span> <span class="n">value</span> <span class="o">!=</span> <span class="n">values</span><span class="p">[</span><span class="n">key</span><span class="p">]:</span>
  722. <span class="k">return</span> <span class="kc">False</span>
  723. <span class="k">return</span> <span class="kc">True</span>
  724. <span class="k">def</span> <span class="nf">match_compare_key</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
  725. <span class="sd">&quot;&quot;&quot;The match compare key for sorting.</span>
  726. <span class="sd"> Current implementation:</span>
  727. <span class="sd"> 1. rules without any arguments come first for performance</span>
  728. <span class="sd"> reasons only as we expect them to match faster and some</span>
  729. <span class="sd"> common ones usually don&#39;t have any arguments (index pages etc.)</span>
  730. <span class="sd"> 2. The more complex rules come first so the second argument is the</span>
  731. <span class="sd"> negative length of the number of weights.</span>
  732. <span class="sd"> 3. lastly we order by the actual weights.</span>
  733. <span class="sd"> :internal:</span>
  734. <span class="sd"> &quot;&quot;&quot;</span>
  735. <span class="k">return</span> <span class="nb">bool</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">arguments</span><span class="p">),</span> <span class="o">-</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_weights</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">_weights</span>
  736. <span class="k">def</span> <span class="nf">build_compare_key</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
  737. <span class="sd">&quot;&quot;&quot;The build compare key for sorting.</span>
  738. <span class="sd"> :internal:</span>
  739. <span class="sd"> &quot;&quot;&quot;</span>
  740. <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">alias</span> <span class="ow">and</span> <span class="mi">1</span> <span class="ow">or</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">arguments</span><span class="p">),</span> \
  741. <span class="o">-</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">defaults</span> <span class="ow">or</span> <span class="p">())</span>
  742. <span class="k">def</span> <span class="nf">__eq__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
  743. <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__class__</span> <span class="ow">is</span> <span class="n">other</span><span class="o">.</span><span class="n">__class__</span> <span class="ow">and</span> \
  744. <span class="bp">self</span><span class="o">.</span><span class="n">_trace</span> <span class="o">==</span> <span class="n">other</span><span class="o">.</span><span class="n">_trace</span>
  745. <span class="k">def</span> <span class="nf">__ne__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
  746. <span class="k">return</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">__eq__</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
  747. <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
  748. <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">rule</span>
  749. <span class="nd">@native_string_result</span>
  750. <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
  751. <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">map</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
  752. <span class="k">return</span> <span class="s1">u&#39;&lt;</span><span class="si">%s</span><span class="s1"> (unbound)&gt;&#39;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__name__</span>
  753. <span class="n">tmp</span> <span class="o">=</span> <span class="p">[]</span>
  754. <span class="k">for</span> <span class="n">is_dynamic</span><span class="p">,</span> <span class="n">data</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_trace</span><span class="p">:</span>
  755. <span class="k">if</span> <span class="n">is_dynamic</span><span class="p">:</span>
  756. <span class="n">tmp</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">u&#39;&lt;</span><span class="si">%s</span><span class="s1">&gt;&#39;</span> <span class="o">%</span> <span class="n">data</span><span class="p">)</span>
  757. <span class="k">else</span><span class="p">:</span>
  758. <span class="n">tmp</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
  759. <span class="k">return</span> <span class="s1">u&#39;&lt;</span><span class="si">%s</span><span class="s1"> </span><span class="si">%s%s</span><span class="s1"> -&gt; </span><span class="si">%s</span><span class="s1">&gt;&#39;</span> <span class="o">%</span> <span class="p">(</span>
  760. <span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__name__</span><span class="p">,</span>
  761. <span class="nb">repr</span><span class="p">((</span><span class="s1">u&#39;&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">tmp</span><span class="p">))</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s1">u&#39;|&#39;</span><span class="p">))</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s1">u&#39;u&#39;</span><span class="p">),</span>
  762. <span class="bp">self</span><span class="o">.</span><span class="n">methods</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
  763. <span class="ow">and</span> <span class="s1">u&#39; (</span><span class="si">%s</span><span class="s1">)&#39;</span> <span class="o">%</span> <span class="s1">u&#39;, &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">methods</span><span class="p">)</span>
  764. <span class="ow">or</span> <span class="s1">u&#39;&#39;</span><span class="p">,</span>
  765. <span class="bp">self</span><span class="o">.</span><span class="n">endpoint</span>
  766. <span class="p">)</span>
  767. <span class="k">class</span> <span class="nc">BaseConverter</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
  768. <span class="sd">&quot;&quot;&quot;Base class for all converters.&quot;&quot;&quot;</span>
  769. <span class="n">regex</span> <span class="o">=</span> <span class="s1">&#39;[^/]+&#39;</span>
  770. <span class="n">weight</span> <span class="o">=</span> <span class="mi">100</span>
  771. <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">map</span><span class="p">):</span>
  772. <span class="bp">self</span><span class="o">.</span><span class="n">map</span> <span class="o">=</span> <span class="nb">map</span>
  773. <span class="k">def</span> <span class="nf">to_python</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
  774. <span class="k">return</span> <span class="n">value</span>
  775. <span class="k">def</span> <span class="nf">to_url</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
  776. <span class="k">return</span> <span class="n">url_quote</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">charset</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">charset</span><span class="p">)</span>
  777. <span class="k">class</span> <span class="nc">UnicodeConverter</span><span class="p">(</span><span class="n">BaseConverter</span><span class="p">):</span>
  778. <span class="sd">&quot;&quot;&quot;This converter is the default converter and accepts any string but</span>
  779. <span class="sd"> only one path segment. Thus the string can not include a slash.</span>
  780. <span class="sd"> This is the default validator.</span>
  781. <span class="sd"> Example::</span>
  782. <span class="sd"> Rule(&#39;/pages/&lt;page&gt;&#39;),</span>
  783. <span class="sd"> Rule(&#39;/&lt;string(length=2):lang_code&gt;&#39;)</span>
  784. <span class="sd"> :param map: the :class:`Map`.</span>
  785. <span class="sd"> :param minlength: the minimum length of the string. Must be greater</span>
  786. <span class="sd"> or equal 1.</span>
  787. <span class="sd"> :param maxlength: the maximum length of the string.</span>
  788. <span class="sd"> :param length: the exact length of the string.</span>
  789. <span class="sd"> &quot;&quot;&quot;</span>
  790. <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">map</span><span class="p">,</span> <span class="n">minlength</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">maxlength</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">length</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
  791. <span class="n">BaseConverter</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">map</span><span class="p">)</span>
  792. <span class="k">if</span> <span class="n">length</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
  793. <span class="n">length</span> <span class="o">=</span> <span class="s1">&#39;{</span><span class="si">%d</span><span class="s1">}&#39;</span> <span class="o">%</span> <span class="nb">int</span><span class="p">(</span><span class="n">length</span><span class="p">)</span>
  794. <span class="k">else</span><span class="p">:</span>
  795. <span class="k">if</span> <span class="n">maxlength</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
  796. <span class="n">maxlength</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span>
  797. <span class="k">else</span><span class="p">:</span>
  798. <span class="n">maxlength</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">maxlength</span><span class="p">)</span>
  799. <span class="n">length</span> <span class="o">=</span> <span class="s1">&#39;{</span><span class="si">%s</span><span class="s1">,</span><span class="si">%s</span><span class="s1">}&#39;</span> <span class="o">%</span> <span class="p">(</span>
  800. <span class="nb">int</span><span class="p">(</span><span class="n">minlength</span><span class="p">),</span>
  801. <span class="n">maxlength</span>
  802. <span class="p">)</span>
  803. <span class="bp">self</span><span class="o">.</span><span class="n">regex</span> <span class="o">=</span> <span class="s1">&#39;[^/]&#39;</span> <span class="o">+</span> <span class="n">length</span>
  804. <span class="k">class</span> <span class="nc">AnyConverter</span><span class="p">(</span><span class="n">BaseConverter</span><span class="p">):</span>
  805. <span class="sd">&quot;&quot;&quot;Matches one of the items provided. Items can either be Python</span>
  806. <span class="sd"> identifiers or strings::</span>
  807. <span class="sd"> Rule(&#39;/&lt;any(about, help, imprint, class, &quot;foo,bar&quot;):page_name&gt;&#39;)</span>
  808. <span class="sd"> :param map: the :class:`Map`.</span>
  809. <span class="sd"> :param items: this function accepts the possible items as positional</span>
  810. <span class="sd"> arguments.</span>
  811. <span class="sd"> &quot;&quot;&quot;</span>
  812. <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">map</span><span class="p">,</span> <span class="o">*</span><span class="n">items</span><span class="p">):</span>
  813. <span class="n">BaseConverter</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">map</span><span class="p">)</span>
  814. <span class="bp">self</span><span class="o">.</span><span class="n">regex</span> <span class="o">=</span> <span class="s1">&#39;(?:</span><span class="si">%s</span><span class="s1">)&#39;</span> <span class="o">%</span> <span class="s1">&#39;|&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="n">re</span><span class="o">.</span><span class="n">escape</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">items</span><span class="p">])</span>
  815. <span class="k">class</span> <span class="nc">PathConverter</span><span class="p">(</span><span class="n">BaseConverter</span><span class="p">):</span>
  816. <span class="sd">&quot;&quot;&quot;Like the default :class:`UnicodeConverter`, but it also matches</span>
  817. <span class="sd"> slashes. This is useful for wikis and similar applications::</span>
  818. <span class="sd"> Rule(&#39;/&lt;path:wikipage&gt;&#39;)</span>
  819. <span class="sd"> Rule(&#39;/&lt;path:wikipage&gt;/edit&#39;)</span>
  820. <span class="sd"> :param map: the :class:`Map`.</span>
  821. <span class="sd"> &quot;&quot;&quot;</span>
  822. <span class="n">regex</span> <span class="o">=</span> <span class="s1">&#39;[^/].*?&#39;</span>
  823. <span class="n">weight</span> <span class="o">=</span> <span class="mi">200</span>
  824. <span class="k">class</span> <span class="nc">NumberConverter</span><span class="p">(</span><span class="n">BaseConverter</span><span class="p">):</span>
  825. <span class="sd">&quot;&quot;&quot;Baseclass for `IntegerConverter` and `FloatConverter`.</span>
  826. <span class="sd"> :internal:</span>
  827. <span class="sd"> &quot;&quot;&quot;</span>
  828. <span class="n">weight</span> <span class="o">=</span> <span class="mi">50</span>
  829. <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">map</span><span class="p">,</span> <span class="n">fixed_digits</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="nb">min</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="nb">max</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
  830. <span class="n">BaseConverter</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">map</span><span class="p">)</span>
  831. <span class="bp">self</span><span class="o">.</span><span class="n">fixed_digits</span> <span class="o">=</span> <span class="n">fixed_digits</span>
  832. <span class="bp">self</span><span class="o">.</span><span class="n">min</span> <span class="o">=</span> <span class="nb">min</span>
  833. <span class="bp">self</span><span class="o">.</span><span class="n">max</span> <span class="o">=</span> <span class="nb">max</span>
  834. <span class="k">def</span> <span class="nf">to_python</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
  835. <span class="k">if</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">fixed_digits</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="o">!=</span> <span class="bp">self</span><span class="o">.</span><span class="n">fixed_digits</span><span class="p">):</span>
  836. <span class="k">raise</span> <span class="n">ValidationError</span><span class="p">()</span>
  837. <span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">num_convert</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
  838. <span class="k">if</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">min</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">value</span> <span class="o">&lt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">min</span><span class="p">)</span> <span class="ow">or</span> \
  839. <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">max</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">value</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">max</span><span class="p">):</span>
  840. <span class="k">raise</span> <span class="n">ValidationError</span><span class="p">()</span>
  841. <span class="k">return</span> <span class="n">value</span>
  842. <span class="k">def</span> <span class="nf">to_url</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
  843. <span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">num_convert</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
  844. <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">fixed_digits</span><span class="p">:</span>
  845. <span class="n">value</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;</span><span class="si">%%</span><span class="s1">0</span><span class="si">%s</span><span class="s1">d&#39;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">fixed_digits</span><span class="p">)</span> <span class="o">%</span> <span class="n">value</span>
  846. <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
  847. <span class="k">class</span> <span class="nc">IntegerConverter</span><span class="p">(</span><span class="n">NumberConverter</span><span class="p">):</span>
  848. <span class="sd">&quot;&quot;&quot;This converter only accepts integer values::</span>
  849. <span class="sd"> Rule(&#39;/page/&lt;int:page&gt;&#39;)</span>
  850. <span class="sd"> This converter does not support negative values.</span>
  851. <span class="sd"> :param map: the :class:`Map`.</span>
  852. <span class="sd"> :param fixed_digits: the number of fixed digits in the URL. If you set</span>
  853. <span class="sd"> this to ``4`` for example, the application will</span>
  854. <span class="sd"> only match if the url looks like ``/0001/``. The</span>
  855. <span class="sd"> default is variable length.</span>
  856. <span class="sd"> :param min: the minimal value.</span>
  857. <span class="sd"> :param max: the maximal value.</span>
  858. <span class="sd"> &quot;&quot;&quot;</span>
  859. <span class="n">regex</span> <span class="o">=</span> <span class="s1">r&#39;\d+&#39;</span>
  860. <span class="n">num_convert</span> <span class="o">=</span> <span class="nb">int</span>
  861. <span class="k">class</span> <span class="nc">FloatConverter</span><span class="p">(</span><span class="n">NumberConverter</span><span class="p">):</span>
  862. <span class="sd">&quot;&quot;&quot;This converter only accepts floating point values::</span>
  863. <span class="sd"> Rule(&#39;/probability/&lt;float:probability&gt;&#39;)</span>
  864. <span class="sd"> This converter does not support negative values.</span>
  865. <span class="sd"> :param map: the :class:`Map`.</span>
  866. <span class="sd"> :param min: the minimal value.</span>
  867. <span class="sd"> :param max: the maximal value.</span>
  868. <span class="sd"> &quot;&quot;&quot;</span>
  869. <span class="n">regex</span> <span class="o">=</span> <span class="s1">r&#39;\d+\.\d+&#39;</span>
  870. <span class="n">num_convert</span> <span class="o">=</span> <span class="nb">float</span>
  871. <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">map</span><span class="p">,</span> <span class="nb">min</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="nb">max</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
  872. <span class="n">NumberConverter</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">map</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">min</span><span class="p">,</span> <span class="nb">max</span><span class="p">)</span>
  873. <span class="k">class</span> <span class="nc">UUIDConverter</span><span class="p">(</span><span class="n">BaseConverter</span><span class="p">):</span>
  874. <span class="sd">&quot;&quot;&quot;This converter only accepts UUID strings::</span>
  875. <span class="sd"> Rule(&#39;/object/&lt;uuid:identifier&gt;&#39;)</span>
  876. <span class="sd"> .. versionadded:: 0.10</span>
  877. <span class="sd"> :param map: the :class:`Map`.</span>
  878. <span class="sd"> &quot;&quot;&quot;</span>
  879. <span class="n">regex</span> <span class="o">=</span> <span class="s1">r&#39;[A-Fa-f0-9]</span><span class="si">{8}</span><span class="s1">-[A-Fa-f0-9]</span><span class="si">{4}</span><span class="s1">-&#39;</span> \
  880. <span class="s1">r&#39;[A-Fa-f0-9]</span><span class="si">{4}</span><span class="s1">-[A-Fa-f0-9]</span><span class="si">{4}</span><span class="s1">-[A-Fa-f0-9]</span><span class="si">{12}</span><span class="s1">&#39;</span>
  881. <span class="k">def</span> <span class="nf">to_python</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
  882. <span class="k">return</span> <span class="n">uuid</span><span class="o">.</span><span class="n">UUID</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
  883. <span class="k">def</span> <span class="nf">to_url</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
  884. <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
  885. <span class="c1">#: the default converter mapping for the map.</span>
  886. <span class="n">DEFAULT_CONVERTERS</span> <span class="o">=</span> <span class="p">{</span>
  887. <span class="s1">&#39;default&#39;</span><span class="p">:</span> <span class="n">UnicodeConverter</span><span class="p">,</span>
  888. <span class="s1">&#39;string&#39;</span><span class="p">:</span> <span class="n">UnicodeConverter</span><span class="p">,</span>
  889. <span class="s1">&#39;any&#39;</span><span class="p">:</span> <span class="n">AnyConverter</span><span class="p">,</span>
  890. <span class="s1">&#39;path&#39;</span><span class="p">:</span> <span class="n">PathConverter</span><span class="p">,</span>
  891. <span class="s1">&#39;int&#39;</span><span class="p">:</span> <span class="n">IntegerConverter</span><span class="p">,</span>
  892. <span class="s1">&#39;float&#39;</span><span class="p">:</span> <span class="n">FloatConverter</span><span class="p">,</span>
  893. <span class="s1">&#39;uuid&#39;</span><span class="p">:</span> <span class="n">UUIDConverter</span><span class="p">,</span>
  894. <span class="p">}</span>
  895. <span class="k">class</span> <span class="nc">Map</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
  896. <span class="sd">&quot;&quot;&quot;The map class stores all the URL rules and some configuration</span>
  897. <span class="sd"> parameters. Some of the configuration values are only stored on the</span>
  898. <span class="sd"> `Map` instance since those affect all rules, others are just defaults</span>
  899. <span class="sd"> and can be overridden for each rule. Note that you have to specify all</span>
  900. <span class="sd"> arguments besides the `rules` as keyword arguments!</span>
  901. <span class="sd"> :param rules: sequence of url rules for this map.</span>
  902. <span class="sd"> :param default_subdomain: The default subdomain for rules without a</span>
  903. <span class="sd"> subdomain defined.</span>
  904. <span class="sd"> :param charset: charset of the url. defaults to ``&quot;utf-8&quot;``</span>
  905. <span class="sd"> :param strict_slashes: Take care of trailing slashes.</span>
  906. <span class="sd"> :param redirect_defaults: This will redirect to the default rule if it</span>
  907. <span class="sd"> wasn&#39;t visited that way. This helps creating</span>
  908. <span class="sd"> unique URLs.</span>
  909. <span class="sd"> :param converters: A dict of converters that adds additional converters</span>
  910. <span class="sd"> to the list of converters. If you redefine one</span>
  911. <span class="sd"> converter this will override the original one.</span>
  912. <span class="sd"> :param sort_parameters: If set to `True` the url parameters are sorted.</span>
  913. <span class="sd"> See `url_encode` for more details.</span>
  914. <span class="sd"> :param sort_key: The sort key function for `url_encode`.</span>
  915. <span class="sd"> :param encoding_errors: the error method to use for decoding</span>
  916. <span class="sd"> :param host_matching: if set to `True` it enables the host matching</span>
  917. <span class="sd"> feature and disables the subdomain one. If</span>
  918. <span class="sd"> enabled the `host` parameter to rules is used</span>
  919. <span class="sd"> instead of the `subdomain` one.</span>
  920. <span class="sd"> .. versionadded:: 0.5</span>
  921. <span class="sd"> `sort_parameters` and `sort_key` was added.</span>
  922. <span class="sd"> .. versionadded:: 0.7</span>
  923. <span class="sd"> `encoding_errors` and `host_matching` was added.</span>
  924. <span class="sd"> &quot;&quot;&quot;</span>
  925. <span class="c1">#: .. versionadded:: 0.6</span>
  926. <span class="c1">#: a dict of default converters to be used.</span>
  927. <span class="n">default_converters</span> <span class="o">=</span> <span class="n">ImmutableDict</span><span class="p">(</span><span class="n">DEFAULT_CONVERTERS</span><span class="p">)</span>
  928. <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">rules</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">default_subdomain</span><span class="o">=</span><span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="n">charset</span><span class="o">=</span><span class="s1">&#39;utf-8&#39;</span><span class="p">,</span>
  929. <span class="n">strict_slashes</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">redirect_defaults</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
  930. <span class="n">converters</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">sort_parameters</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">sort_key</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
  931. <span class="n">encoding_errors</span><span class="o">=</span><span class="s1">&#39;replace&#39;</span><span class="p">,</span> <span class="n">host_matching</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
  932. <span class="bp">self</span><span class="o">.</span><span class="n">_rules</span> <span class="o">=</span> <span class="p">[]</span>
  933. <span class="bp">self</span><span class="o">.</span><span class="n">_rules_by_endpoint</span> <span class="o">=</span> <span class="p">{}</span>
  934. <span class="bp">self</span><span class="o">.</span><span class="n">_remap</span> <span class="o">=</span> <span class="kc">True</span>
  935. <span class="bp">self</span><span class="o">.</span><span class="n">_remap_lock</span> <span class="o">=</span> <span class="n">Lock</span><span class="p">()</span>
  936. <span class="bp">self</span><span class="o">.</span><span class="n">default_subdomain</span> <span class="o">=</span> <span class="n">default_subdomain</span>
  937. <span class="bp">self</span><span class="o">.</span><span class="n">charset</span> <span class="o">=</span> <span class="n">charset</span>
  938. <span class="bp">self</span><span class="o">.</span><span class="n">encoding_errors</span> <span class="o">=</span> <span class="n">encoding_errors</span>
  939. <span class="bp">self</span><span class="o">.</span><span class="n">strict_slashes</span> <span class="o">=</span> <span class="n">strict_slashes</span>
  940. <span class="bp">self</span><span class="o">.</span><span class="n">redirect_defaults</span> <span class="o">=</span> <span class="n">redirect_defaults</span>
  941. <span class="bp">self</span><span class="o">.</span><span class="n">host_matching</span> <span class="o">=</span> <span class="n">host_matching</span>
  942. <span class="bp">self</span><span class="o">.</span><span class="n">converters</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">default_converters</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
  943. <span class="k">if</span> <span class="n">converters</span><span class="p">:</span>
  944. <span class="bp">self</span><span class="o">.</span><span class="n">converters</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">converters</span><span class="p">)</span>
  945. <span class="bp">self</span><span class="o">.</span><span class="n">sort_parameters</span> <span class="o">=</span> <span class="n">sort_parameters</span>
  946. <span class="bp">self</span><span class="o">.</span><span class="n">sort_key</span> <span class="o">=</span> <span class="n">sort_key</span>
  947. <span class="k">for</span> <span class="n">rulefactory</span> <span class="ow">in</span> <span class="n">rules</span> <span class="ow">or</span> <span class="p">():</span>
  948. <span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">rulefactory</span><span class="p">)</span>
  949. <span class="k">def</span> <span class="nf">is_endpoint_expecting</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">endpoint</span><span class="p">,</span> <span class="o">*</span><span class="n">arguments</span><span class="p">):</span>
  950. <span class="sd">&quot;&quot;&quot;Iterate over all rules and check if the endpoint expects</span>
  951. <span class="sd"> the arguments provided. This is for example useful if you have</span>
  952. <span class="sd"> some URLs that expect a language code and others that do not and</span>
  953. <span class="sd"> you want to wrap the builder a bit so that the current language</span>
  954. <span class="sd"> code is automatically added if not provided but endpoints expect</span>
  955. <span class="sd"> it.</span>
  956. <span class="sd"> :param endpoint: the endpoint to check.</span>
  957. <span class="sd"> :param arguments: this function accepts one or more arguments</span>
  958. <span class="sd"> as positional arguments. Each one of them is</span>
  959. <span class="sd"> checked.</span>
  960. <span class="sd"> &quot;&quot;&quot;</span>
  961. <span class="bp">self</span><span class="o">.</span><span class="n">update</span><span class="p">()</span>
  962. <span class="n">arguments</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="n">arguments</span><span class="p">)</span>
  963. <span class="k">for</span> <span class="n">rule</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_rules_by_endpoint</span><span class="p">[</span><span class="n">endpoint</span><span class="p">]:</span>
  964. <span class="k">if</span> <span class="n">arguments</span><span class="o">.</span><span class="n">issubset</span><span class="p">(</span><span class="n">rule</span><span class="o">.</span><span class="n">arguments</span><span class="p">):</span>
  965. <span class="k">return</span> <span class="kc">True</span>
  966. <span class="k">return</span> <span class="kc">False</span>
  967. <span class="k">def</span> <span class="nf">iter_rules</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">endpoint</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
  968. <span class="sd">&quot;&quot;&quot;Iterate over all rules or the rules of an endpoint.</span>
  969. <span class="sd"> :param endpoint: if provided only the rules for that endpoint</span>
  970. <span class="sd"> are returned.</span>
  971. <span class="sd"> :return: an iterator</span>
  972. <span class="sd"> &quot;&quot;&quot;</span>
  973. <span class="bp">self</span><span class="o">.</span><span class="n">update</span><span class="p">()</span>
  974. <span class="k">if</span> <span class="n">endpoint</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
  975. <span class="k">return</span> <span class="nb">iter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_rules_by_endpoint</span><span class="p">[</span><span class="n">endpoint</span><span class="p">])</span>
  976. <span class="k">return</span> <span class="nb">iter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_rules</span><span class="p">)</span>
  977. <span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">rulefactory</span><span class="p">):</span>
  978. <span class="sd">&quot;&quot;&quot;Add a new rule or factory to the map and bind it. Requires that the</span>
  979. <span class="sd"> rule is not bound to another map.</span>
  980. <span class="sd"> :param rulefactory: a :class:`Rule` or :class:`RuleFactory`</span>
  981. <span class="sd"> &quot;&quot;&quot;</span>
  982. <span class="k">for</span> <span class="n">rule</span> <span class="ow">in</span> <span class="n">rulefactory</span><span class="o">.</span><span class="n">get_rules</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
  983. <span class="n">rule</span><span class="o">.</span><span class="n">bind</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
  984. <span class="bp">self</span><span class="o">.</span><span class="n">_rules</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">rule</span><span class="p">)</span>
  985. <span class="bp">self</span><span class="o">.</span><span class="n">_rules_by_endpoint</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">rule</span><span class="o">.</span><span class="n">endpoint</span><span class="p">,</span> <span class="p">[])</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">rule</span><span class="p">)</span>
  986. <span class="bp">self</span><span class="o">.</span><span class="n">_remap</span> <span class="o">=</span> <span class="kc">True</span>
  987. <span class="k">def</span> <span class="nf">bind</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">server_name</span><span class="p">,</span> <span class="n">script_name</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">subdomain</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
  988. <span class="n">url_scheme</span><span class="o">=</span><span class="s1">&#39;http&#39;</span><span class="p">,</span> <span class="n">default_method</span><span class="o">=</span><span class="s1">&#39;GET&#39;</span><span class="p">,</span> <span class="n">path_info</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
  989. <span class="n">query_args</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
  990. <span class="sd">&quot;&quot;&quot;Return a new :class:`MapAdapter` with the details specified to the</span>
  991. <span class="sd"> call. Note that `script_name` will default to ``&#39;/&#39;`` if not further</span>
  992. <span class="sd"> specified or `None`. The `server_name` at least is a requirement</span>
  993. <span class="sd"> because the HTTP RFC requires absolute URLs for redirects and so all</span>
  994. <span class="sd"> redirect exceptions raised by Werkzeug will contain the full canonical</span>
  995. <span class="sd"> URL.</span>
  996. <span class="sd"> If no path_info is passed to :meth:`match` it will use the default path</span>
  997. <span class="sd"> info passed to bind. While this doesn&#39;t really make sense for</span>
  998. <span class="sd"> manual bind calls, it&#39;s useful if you bind a map to a WSGI</span>
  999. <span class="sd"> environment which already contains the path info.</span>
  1000. <span class="sd"> `subdomain` will default to the `default_subdomain` for this map if</span>
  1001. <span class="sd"> no defined. If there is no `default_subdomain` you cannot use the</span>
  1002. <span class="sd"> subdomain feature.</span>
  1003. <span class="sd"> .. versionadded:: 0.7</span>
  1004. <span class="sd"> `query_args` added</span>
  1005. <span class="sd"> .. versionadded:: 0.8</span>
  1006. <span class="sd"> `query_args` can now also be a string.</span>
  1007. <span class="sd"> &quot;&quot;&quot;</span>
  1008. <span class="n">server_name</span> <span class="o">=</span> <span class="n">server_name</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
  1009. <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">host_matching</span><span class="p">:</span>
  1010. <span class="k">if</span> <span class="n">subdomain</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
  1011. <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s1">&#39;host matching enabled and a &#39;</span>
  1012. <span class="s1">&#39;subdomain was provided&#39;</span><span class="p">)</span>
  1013. <span class="k">elif</span> <span class="n">subdomain</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
  1014. <span class="n">subdomain</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">default_subdomain</span>
  1015. <span class="k">if</span> <span class="n">script_name</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
  1016. <span class="n">script_name</span> <span class="o">=</span> <span class="s1">&#39;/&#39;</span>
  1017. <span class="k">try</span><span class="p">:</span>
  1018. <span class="n">server_name</span> <span class="o">=</span> <span class="n">_encode_idna</span><span class="p">(</span><span class="n">server_name</span><span class="p">)</span>
  1019. <span class="k">except</span> <span class="ne">UnicodeError</span><span class="p">:</span>
  1020. <span class="k">raise</span> <span class="n">BadHost</span><span class="p">()</span>
  1021. <span class="k">return</span> <span class="n">MapAdapter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">server_name</span><span class="p">,</span> <span class="n">script_name</span><span class="p">,</span> <span class="n">subdomain</span><span class="p">,</span>
  1022. <span class="n">url_scheme</span><span class="p">,</span> <span class="n">path_info</span><span class="p">,</span> <span class="n">default_method</span><span class="p">,</span> <span class="n">query_args</span><span class="p">)</span>
  1023. <span class="k">def</span> <span class="nf">bind_to_environ</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">,</span> <span class="n">server_name</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">subdomain</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
  1024. <span class="sd">&quot;&quot;&quot;Like :meth:`bind` but you can pass it an WSGI environment and it</span>
  1025. <span class="sd"> will fetch the information from that dictionary. Note that because of</span>
  1026. <span class="sd"> limitations in the protocol there is no way to get the current</span>
  1027. <span class="sd"> subdomain and real `server_name` from the environment. If you don&#39;t</span>
  1028. <span class="sd"> provide it, Werkzeug will use `SERVER_NAME` and `SERVER_PORT` (or</span>
  1029. <span class="sd"> `HTTP_HOST` if provided) as used `server_name` with disabled subdomain</span>
  1030. <span class="sd"> feature.</span>
  1031. <span class="sd"> If `subdomain` is `None` but an environment and a server name is</span>
  1032. <span class="sd"> provided it will calculate the current subdomain automatically.</span>
  1033. <span class="sd"> Example: `server_name` is ``&#39;example.com&#39;`` and the `SERVER_NAME`</span>
  1034. <span class="sd"> in the wsgi `environ` is ``&#39;staging.dev.example.com&#39;`` the calculated</span>
  1035. <span class="sd"> subdomain will be ``&#39;staging.dev&#39;``.</span>
  1036. <span class="sd"> If the object passed as environ has an environ attribute, the value of</span>
  1037. <span class="sd"> this attribute is used instead. This allows you to pass request</span>
  1038. <span class="sd"> objects. Additionally `PATH_INFO` added as a default of the</span>
  1039. <span class="sd"> :class:`MapAdapter` so that you don&#39;t have to pass the path info to</span>
  1040. <span class="sd"> the match method.</span>
  1041. <span class="sd"> .. versionchanged:: 0.5</span>
  1042. <span class="sd"> previously this method accepted a bogus `calculate_subdomain`</span>
  1043. <span class="sd"> parameter that did not have any effect. It was removed because</span>
  1044. <span class="sd"> of that.</span>
  1045. <span class="sd"> .. versionchanged:: 0.8</span>
  1046. <span class="sd"> This will no longer raise a ValueError when an unexpected server</span>
  1047. <span class="sd"> name was passed.</span>
  1048. <span class="sd"> :param environ: a WSGI environment.</span>
  1049. <span class="sd"> :param server_name: an optional server name hint (see above).</span>
  1050. <span class="sd"> :param subdomain: optionally the current subdomain (see above).</span>
  1051. <span class="sd"> &quot;&quot;&quot;</span>
  1052. <span class="n">environ</span> <span class="o">=</span> <span class="n">_get_environ</span><span class="p">(</span><span class="n">environ</span><span class="p">)</span>
  1053. <span class="k">if</span> <span class="s1">&#39;HTTP_HOST&#39;</span> <span class="ow">in</span> <span class="n">environ</span><span class="p">:</span>
  1054. <span class="n">wsgi_server_name</span> <span class="o">=</span> <span class="n">environ</span><span class="p">[</span><span class="s1">&#39;HTTP_HOST&#39;</span><span class="p">]</span>
  1055. <span class="k">if</span> <span class="n">environ</span><span class="p">[</span><span class="s1">&#39;wsgi.url_scheme&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="s1">&#39;http&#39;</span> \
  1056. <span class="ow">and</span> <span class="n">wsgi_server_name</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s1">&#39;:80&#39;</span><span class="p">):</span>
  1057. <span class="n">wsgi_server_name</span> <span class="o">=</span> <span class="n">wsgi_server_name</span><span class="p">[:</span><span class="o">-</span><span class="mi">3</span><span class="p">]</span>
  1058. <span class="k">elif</span> <span class="n">environ</span><span class="p">[</span><span class="s1">&#39;wsgi.url_scheme&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="s1">&#39;https&#39;</span> \
  1059. <span class="ow">and</span> <span class="n">wsgi_server_name</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s1">&#39;:443&#39;</span><span class="p">):</span>
  1060. <span class="n">wsgi_server_name</span> <span class="o">=</span> <span class="n">wsgi_server_name</span><span class="p">[:</span><span class="o">-</span><span class="mi">4</span><span class="p">]</span>
  1061. <span class="k">else</span><span class="p">:</span>
  1062. <span class="n">wsgi_server_name</span> <span class="o">=</span> <span class="n">environ</span><span class="p">[</span><span class="s1">&#39;SERVER_NAME&#39;</span><span class="p">]</span>
  1063. <span class="k">if</span> <span class="p">(</span><span class="n">environ</span><span class="p">[</span><span class="s1">&#39;wsgi.url_scheme&#39;</span><span class="p">],</span> <span class="n">environ</span><span class="p">[</span><span class="s1">&#39;SERVER_PORT&#39;</span><span class="p">])</span> <span class="ow">not</span> \
  1064. <span class="ow">in</span> <span class="p">((</span><span class="s1">&#39;https&#39;</span><span class="p">,</span> <span class="s1">&#39;443&#39;</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;http&#39;</span><span class="p">,</span> <span class="s1">&#39;80&#39;</span><span class="p">)):</span>
  1065. <span class="n">wsgi_server_name</span> <span class="o">+=</span> <span class="s1">&#39;:&#39;</span> <span class="o">+</span> <span class="n">environ</span><span class="p">[</span><span class="s1">&#39;SERVER_PORT&#39;</span><span class="p">]</span>
  1066. <span class="n">wsgi_server_name</span> <span class="o">=</span> <span class="n">wsgi_server_name</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
  1067. <span class="k">if</span> <span class="n">server_name</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
  1068. <span class="n">server_name</span> <span class="o">=</span> <span class="n">wsgi_server_name</span>
  1069. <span class="k">else</span><span class="p">:</span>
  1070. <span class="n">server_name</span> <span class="o">=</span> <span class="n">server_name</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
  1071. <span class="k">if</span> <span class="n">subdomain</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">host_matching</span><span class="p">:</span>
  1072. <span class="n">cur_server_name</span> <span class="o">=</span> <span class="n">wsgi_server_name</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;.&#39;</span><span class="p">)</span>
  1073. <span class="n">real_server_name</span> <span class="o">=</span> <span class="n">server_name</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;.&#39;</span><span class="p">)</span>
  1074. <span class="n">offset</span> <span class="o">=</span> <span class="o">-</span><span class="nb">len</span><span class="p">(</span><span class="n">real_server_name</span><span class="p">)</span>
  1075. <span class="k">if</span> <span class="n">cur_server_name</span><span class="p">[</span><span class="n">offset</span><span class="p">:]</span> <span class="o">!=</span> <span class="n">real_server_name</span><span class="p">:</span>
  1076. <span class="c1"># This can happen even with valid configs if the server was</span>
  1077. <span class="c1"># accesssed directly by IP address under some situations.</span>
  1078. <span class="c1"># Instead of raising an exception like in Werkzeug 0.7 or</span>
  1079. <span class="c1"># earlier we go by an invalid subdomain which will result</span>
  1080. <span class="c1"># in a 404 error on matching.</span>
  1081. <span class="n">subdomain</span> <span class="o">=</span> <span class="s1">&#39;&lt;invalid&gt;&#39;</span>
  1082. <span class="k">else</span><span class="p">:</span>
  1083. <span class="n">subdomain</span> <span class="o">=</span> <span class="s1">&#39;.&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">filter</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">cur_server_name</span><span class="p">[:</span><span class="n">offset</span><span class="p">]))</span>
  1084. <span class="k">def</span> <span class="nf">_get_wsgi_string</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
  1085. <span class="n">val</span> <span class="o">=</span> <span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
  1086. <span class="k">if</span> <span class="n">val</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
  1087. <span class="k">return</span> <span class="n">wsgi_decoding_dance</span><span class="p">(</span><span class="n">val</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">charset</span><span class="p">)</span>
  1088. <span class="n">script_name</span> <span class="o">=</span> <span class="n">_get_wsgi_string</span><span class="p">(</span><span class="s1">&#39;SCRIPT_NAME&#39;</span><span class="p">)</span>
  1089. <span class="n">path_info</span> <span class="o">=</span> <span class="n">_get_wsgi_string</span><span class="p">(</span><span class="s1">&#39;PATH_INFO&#39;</span><span class="p">)</span>
  1090. <span class="n">query_args</span> <span class="o">=</span> <span class="n">_get_wsgi_string</span><span class="p">(</span><span class="s1">&#39;QUERY_STRING&#39;</span><span class="p">)</span>
  1091. <span class="k">return</span> <span class="n">Map</span><span class="o">.</span><span class="n">bind</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">server_name</span><span class="p">,</span> <span class="n">script_name</span><span class="p">,</span>
  1092. <span class="n">subdomain</span><span class="p">,</span> <span class="n">environ</span><span class="p">[</span><span class="s1">&#39;wsgi.url_scheme&#39;</span><span class="p">],</span>
  1093. <span class="n">environ</span><span class="p">[</span><span class="s1">&#39;REQUEST_METHOD&#39;</span><span class="p">],</span> <span class="n">path_info</span><span class="p">,</span>
  1094. <span class="n">query_args</span><span class="o">=</span><span class="n">query_args</span><span class="p">)</span>
  1095. <span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
  1096. <span class="sd">&quot;&quot;&quot;Called before matching and building to keep the compiled rules</span>
  1097. <span class="sd"> in the correct order after things changed.</span>
  1098. <span class="sd"> &quot;&quot;&quot;</span>
  1099. <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_remap</span><span class="p">:</span>
  1100. <span class="k">return</span>
  1101. <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_remap_lock</span><span class="p">:</span>
  1102. <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_remap</span><span class="p">:</span>
  1103. <span class="k">return</span>
  1104. <span class="bp">self</span><span class="o">.</span><span class="n">_rules</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="o">.</span><span class="n">match_compare_key</span><span class="p">())</span>
  1105. <span class="k">for</span> <span class="n">rules</span> <span class="ow">in</span> <span class="n">itervalues</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_rules_by_endpoint</span><span class="p">):</span>
  1106. <span class="n">rules</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="o">.</span><span class="n">build_compare_key</span><span class="p">())</span>
  1107. <span class="bp">self</span><span class="o">.</span><span class="n">_remap</span> <span class="o">=</span> <span class="kc">False</span>
  1108. <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
  1109. <span class="n">rules</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">iter_rules</span><span class="p">()</span>
  1110. <span class="k">return</span> <span class="s1">&#39;</span><span class="si">%s</span><span class="s1">(</span><span class="si">%s</span><span class="s1">)&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__name__</span><span class="p">,</span> <span class="n">pformat</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="n">rules</span><span class="p">)))</span>
  1111. <span class="k">class</span> <span class="nc">MapAdapter</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
  1112. <span class="sd">&quot;&quot;&quot;Returned by :meth:`Map.bind` or :meth:`Map.bind_to_environ` and does</span>
  1113. <span class="sd"> the URL matching and building based on runtime information.</span>
  1114. <span class="sd"> &quot;&quot;&quot;</span>
  1115. <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">map</span><span class="p">,</span> <span class="n">server_name</span><span class="p">,</span> <span class="n">script_name</span><span class="p">,</span> <span class="n">subdomain</span><span class="p">,</span>
  1116. <span class="n">url_scheme</span><span class="p">,</span> <span class="n">path_info</span><span class="p">,</span> <span class="n">default_method</span><span class="p">,</span> <span class="n">query_args</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
  1117. <span class="bp">self</span><span class="o">.</span><span class="n">map</span> <span class="o">=</span> <span class="nb">map</span>
  1118. <span class="bp">self</span><span class="o">.</span><span class="n">server_name</span> <span class="o">=</span> <span class="n">to_unicode</span><span class="p">(</span><span class="n">server_name</span><span class="p">)</span>
  1119. <span class="n">script_name</span> <span class="o">=</span> <span class="n">to_unicode</span><span class="p">(</span><span class="n">script_name</span><span class="p">)</span>
  1120. <span class="k">if</span> <span class="ow">not</span> <span class="n">script_name</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s1">u&#39;/&#39;</span><span class="p">):</span>
  1121. <span class="n">script_name</span> <span class="o">+=</span> <span class="s1">u&#39;/&#39;</span>
  1122. <span class="bp">self</span><span class="o">.</span><span class="n">script_name</span> <span class="o">=</span> <span class="n">script_name</span>
  1123. <span class="bp">self</span><span class="o">.</span><span class="n">subdomain</span> <span class="o">=</span> <span class="n">to_unicode</span><span class="p">(</span><span class="n">subdomain</span><span class="p">)</span>
  1124. <span class="bp">self</span><span class="o">.</span><span class="n">url_scheme</span> <span class="o">=</span> <span class="n">to_unicode</span><span class="p">(</span><span class="n">url_scheme</span><span class="p">)</span>
  1125. <span class="bp">self</span><span class="o">.</span><span class="n">path_info</span> <span class="o">=</span> <span class="n">to_unicode</span><span class="p">(</span><span class="n">path_info</span><span class="p">)</span>
  1126. <span class="bp">self</span><span class="o">.</span><span class="n">default_method</span> <span class="o">=</span> <span class="n">to_unicode</span><span class="p">(</span><span class="n">default_method</span><span class="p">)</span>
  1127. <span class="bp">self</span><span class="o">.</span><span class="n">query_args</span> <span class="o">=</span> <span class="n">query_args</span>
  1128. <span class="k">def</span> <span class="nf">dispatch</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">view_func</span><span class="p">,</span> <span class="n">path_info</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
  1129. <span class="n">catch_http_exceptions</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
  1130. <span class="sd">&quot;&quot;&quot;Does the complete dispatching process. `view_func` is called with</span>
  1131. <span class="sd"> the endpoint and a dict with the values for the view. It should</span>
  1132. <span class="sd"> look up the view function, call it, and return a response object</span>
  1133. <span class="sd"> or WSGI application. http exceptions are not caught by default</span>
  1134. <span class="sd"> so that applications can display nicer error messages by just</span>
  1135. <span class="sd"> catching them by hand. If you want to stick with the default</span>
  1136. <span class="sd"> error messages you can pass it ``catch_http_exceptions=True`` and</span>
  1137. <span class="sd"> it will catch the http exceptions.</span>
  1138. <span class="sd"> Here a small example for the dispatch usage::</span>
  1139. <span class="sd"> from werkzeug.wrappers import Request, Response</span>
  1140. <span class="sd"> from werkzeug.wsgi import responder</span>
  1141. <span class="sd"> from werkzeug.routing import Map, Rule</span>
  1142. <span class="sd"> def on_index(request):</span>
  1143. <span class="sd"> return Response(&#39;Hello from the index&#39;)</span>
  1144. <span class="sd"> url_map = Map([Rule(&#39;/&#39;, endpoint=&#39;index&#39;)])</span>
  1145. <span class="sd"> views = {&#39;index&#39;: on_index}</span>
  1146. <span class="sd"> @responder</span>
  1147. <span class="sd"> def application(environ, start_response):</span>
  1148. <span class="sd"> request = Request(environ)</span>
  1149. <span class="sd"> urls = url_map.bind_to_environ(environ)</span>
  1150. <span class="sd"> return urls.dispatch(lambda e, v: views[e](request, **v),</span>
  1151. <span class="sd"> catch_http_exceptions=True)</span>
  1152. <span class="sd"> Keep in mind that this method might return exception objects, too, so</span>
  1153. <span class="sd"> use :class:`Response.force_type` to get a response object.</span>
  1154. <span class="sd"> :param view_func: a function that is called with the endpoint as</span>
  1155. <span class="sd"> first argument and the value dict as second. Has</span>
  1156. <span class="sd"> to dispatch to the actual view function with this</span>
  1157. <span class="sd"> information. (see above)</span>
  1158. <span class="sd"> :param path_info: the path info to use for matching. Overrides the</span>
  1159. <span class="sd"> path info specified on binding.</span>
  1160. <span class="sd"> :param method: the HTTP method used for matching. Overrides the</span>
  1161. <span class="sd"> method specified on binding.</span>
  1162. <span class="sd"> :param catch_http_exceptions: set to `True` to catch any of the</span>
  1163. <span class="sd"> werkzeug :class:`HTTPException`\s.</span>
  1164. <span class="sd"> &quot;&quot;&quot;</span>
  1165. <span class="k">try</span><span class="p">:</span>
  1166. <span class="k">try</span><span class="p">:</span>
  1167. <span class="n">endpoint</span><span class="p">,</span> <span class="n">args</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">path_info</span><span class="p">,</span> <span class="n">method</span><span class="p">)</span>
  1168. <span class="k">except</span> <span class="n">RequestRedirect</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
  1169. <span class="k">return</span> <span class="n">e</span>
  1170. <span class="k">return</span> <span class="n">view_func</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">args</span><span class="p">)</span>
  1171. <span class="k">except</span> <span class="n">HTTPException</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
  1172. <span class="k">if</span> <span class="n">catch_http_exceptions</span><span class="p">:</span>
  1173. <span class="k">return</span> <span class="n">e</span>
  1174. <span class="k">raise</span>
  1175. <span class="k">def</span> <span class="nf">match</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path_info</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">return_rule</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
  1176. <span class="n">query_args</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
  1177. <span class="sd">&quot;&quot;&quot;The usage is simple: you just pass the match method the current</span>
  1178. <span class="sd"> path info as well as the method (which defaults to `GET`). The</span>
  1179. <span class="sd"> following things can then happen:</span>
  1180. <span class="sd"> - you receive a `NotFound` exception that indicates that no URL is</span>
  1181. <span class="sd"> matching. A `NotFound` exception is also a WSGI application you</span>
  1182. <span class="sd"> can call to get a default page not found page (happens to be the</span>
  1183. <span class="sd"> same object as `werkzeug.exceptions.NotFound`)</span>
  1184. <span class="sd"> - you receive a `MethodNotAllowed` exception that indicates that there</span>
  1185. <span class="sd"> is a match for this URL but not for the current request method.</span>
  1186. <span class="sd"> This is useful for RESTful applications.</span>
  1187. <span class="sd"> - you receive a `RequestRedirect` exception with a `new_url`</span>
  1188. <span class="sd"> attribute. This exception is used to notify you about a request</span>
  1189. <span class="sd"> Werkzeug requests from your WSGI application. This is for example the</span>
  1190. <span class="sd"> case if you request ``/foo`` although the correct URL is ``/foo/``</span>
  1191. <span class="sd"> You can use the `RequestRedirect` instance as response-like object</span>
  1192. <span class="sd"> similar to all other subclasses of `HTTPException`.</span>
  1193. <span class="sd"> - you get a tuple in the form ``(endpoint, arguments)`` if there is</span>
  1194. <span class="sd"> a match (unless `return_rule` is True, in which case you get a tuple</span>
  1195. <span class="sd"> in the form ``(rule, arguments)``)</span>
  1196. <span class="sd"> If the path info is not passed to the match method the default path</span>
  1197. <span class="sd"> info of the map is used (defaults to the root URL if not defined</span>
  1198. <span class="sd"> explicitly).</span>
  1199. <span class="sd"> All of the exceptions raised are subclasses of `HTTPException` so they</span>
  1200. <span class="sd"> can be used as WSGI responses. The will all render generic error or</span>
  1201. <span class="sd"> redirect pages.</span>
  1202. <span class="sd"> Here is a small example for matching:</span>
  1203. <span class="sd"> &gt;&gt;&gt; m = Map([</span>
  1204. <span class="sd"> ... Rule(&#39;/&#39;, endpoint=&#39;index&#39;),</span>
  1205. <span class="sd"> ... Rule(&#39;/downloads/&#39;, endpoint=&#39;downloads/index&#39;),</span>
  1206. <span class="sd"> ... Rule(&#39;/downloads/&lt;int:id&gt;&#39;, endpoint=&#39;downloads/show&#39;)</span>
  1207. <span class="sd"> ... ])</span>
  1208. <span class="sd"> &gt;&gt;&gt; urls = m.bind(&quot;example.com&quot;, &quot;/&quot;)</span>
  1209. <span class="sd"> &gt;&gt;&gt; urls.match(&quot;/&quot;, &quot;GET&quot;)</span>
  1210. <span class="sd"> (&#39;index&#39;, {})</span>
  1211. <span class="sd"> &gt;&gt;&gt; urls.match(&quot;/downloads/42&quot;)</span>
  1212. <span class="sd"> (&#39;downloads/show&#39;, {&#39;id&#39;: 42})</span>
  1213. <span class="sd"> And here is what happens on redirect and missing URLs:</span>
  1214. <span class="sd"> &gt;&gt;&gt; urls.match(&quot;/downloads&quot;)</span>
  1215. <span class="sd"> Traceback (most recent call last):</span>
  1216. <span class="sd"> ...</span>
  1217. <span class="sd"> RequestRedirect: http://example.com/downloads/</span>
  1218. <span class="sd"> &gt;&gt;&gt; urls.match(&quot;/missing&quot;)</span>
  1219. <span class="sd"> Traceback (most recent call last):</span>
  1220. <span class="sd"> ...</span>
  1221. <span class="sd"> NotFound: 404 Not Found</span>
  1222. <span class="sd"> :param path_info: the path info to use for matching. Overrides the</span>
  1223. <span class="sd"> path info specified on binding.</span>
  1224. <span class="sd"> :param method: the HTTP method used for matching. Overrides the</span>
  1225. <span class="sd"> method specified on binding.</span>
  1226. <span class="sd"> :param return_rule: return the rule that matched instead of just the</span>
  1227. <span class="sd"> endpoint (defaults to `False`).</span>
  1228. <span class="sd"> :param query_args: optional query arguments that are used for</span>
  1229. <span class="sd"> automatic redirects as string or dictionary. It&#39;s</span>
  1230. <span class="sd"> currently not possible to use the query arguments</span>
  1231. <span class="sd"> for URL matching.</span>
  1232. <span class="sd"> .. versionadded:: 0.6</span>
  1233. <span class="sd"> `return_rule` was added.</span>
  1234. <span class="sd"> .. versionadded:: 0.7</span>
  1235. <span class="sd"> `query_args` was added.</span>
  1236. <span class="sd"> .. versionchanged:: 0.8</span>
  1237. <span class="sd"> `query_args` can now also be a string.</span>
  1238. <span class="sd"> &quot;&quot;&quot;</span>
  1239. <span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">update</span><span class="p">()</span>
  1240. <span class="k">if</span> <span class="n">path_info</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
  1241. <span class="n">path_info</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">path_info</span>
  1242. <span class="k">else</span><span class="p">:</span>
  1243. <span class="n">path_info</span> <span class="o">=</span> <span class="n">to_unicode</span><span class="p">(</span><span class="n">path_info</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">charset</span><span class="p">)</span>
  1244. <span class="k">if</span> <span class="n">query_args</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
  1245. <span class="n">query_args</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">query_args</span>
  1246. <span class="n">method</span> <span class="o">=</span> <span class="p">(</span><span class="n">method</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">default_method</span><span class="p">)</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span>
  1247. <span class="n">path</span> <span class="o">=</span> <span class="s1">u&#39;</span><span class="si">%s</span><span class="s1">|</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span>
  1248. <span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">host_matching</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">server_name</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">subdomain</span><span class="p">,</span>
  1249. <span class="n">path_info</span> <span class="ow">and</span> <span class="s1">&#39;/</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">path_info</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">)</span>
  1250. <span class="p">)</span>
  1251. <span class="n">have_match_for</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
  1252. <span class="k">for</span> <span class="n">rule</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">_rules</span><span class="p">:</span>
  1253. <span class="k">try</span><span class="p">:</span>
  1254. <span class="n">rv</span> <span class="o">=</span> <span class="n">rule</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
  1255. <span class="k">except</span> <span class="n">RequestSlash</span><span class="p">:</span>
  1256. <span class="k">raise</span> <span class="n">RequestRedirect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">make_redirect_url</span><span class="p">(</span>
  1257. <span class="n">url_quote</span><span class="p">(</span><span class="n">path_info</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">charset</span><span class="p">,</span>
  1258. <span class="n">safe</span><span class="o">=</span><span class="s1">&#39;/:|+&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="n">query_args</span><span class="p">))</span>
  1259. <span class="k">except</span> <span class="n">RequestAliasRedirect</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
  1260. <span class="k">raise</span> <span class="n">RequestRedirect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">make_alias_redirect_url</span><span class="p">(</span>
  1261. <span class="n">path</span><span class="p">,</span> <span class="n">rule</span><span class="o">.</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">matched_values</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="n">query_args</span><span class="p">))</span>
  1262. <span class="k">if</span> <span class="n">rv</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
  1263. <span class="k">continue</span>
  1264. <span class="k">if</span> <span class="n">rule</span><span class="o">.</span><span class="n">methods</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">method</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">rule</span><span class="o">.</span><span class="n">methods</span><span class="p">:</span>
  1265. <span class="n">have_match_for</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">rule</span><span class="o">.</span><span class="n">methods</span><span class="p">)</span>
  1266. <span class="k">continue</span>
  1267. <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">redirect_defaults</span><span class="p">:</span>
  1268. <span class="n">redirect_url</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_default_redirect</span><span class="p">(</span><span class="n">rule</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="n">rv</span><span class="p">,</span>
  1269. <span class="n">query_args</span><span class="p">)</span>
  1270. <span class="k">if</span> <span class="n">redirect_url</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
  1271. <span class="k">raise</span> <span class="n">RequestRedirect</span><span class="p">(</span><span class="n">redirect_url</span><span class="p">)</span>
  1272. <span class="k">if</span> <span class="n">rule</span><span class="o">.</span><span class="n">redirect_to</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
  1273. <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">rule</span><span class="o">.</span><span class="n">redirect_to</span><span class="p">,</span> <span class="n">string_types</span><span class="p">):</span>
  1274. <span class="k">def</span> <span class="nf">_handle_match</span><span class="p">(</span><span class="n">match</span><span class="p">):</span>
  1275. <span class="n">value</span> <span class="o">=</span> <span class="n">rv</span><span class="p">[</span><span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">)]</span>
  1276. <span class="k">return</span> <span class="n">rule</span><span class="o">.</span><span class="n">_converters</span><span class="p">[</span><span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">)]</span><span class="o">.</span><span class="n">to_url</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
  1277. <span class="n">redirect_url</span> <span class="o">=</span> <span class="n">_simple_rule_re</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="n">_handle_match</span><span class="p">,</span>
  1278. <span class="n">rule</span><span class="o">.</span><span class="n">redirect_to</span><span class="p">)</span>
  1279. <span class="k">else</span><span class="p">:</span>
  1280. <span class="n">redirect_url</span> <span class="o">=</span> <span class="n">rule</span><span class="o">.</span><span class="n">redirect_to</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">rv</span><span class="p">)</span>
  1281. <span class="k">raise</span> <span class="n">RequestRedirect</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">url_join</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">%s</span><span class="s1">://</span><span class="si">%s%s%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span>
  1282. <span class="bp">self</span><span class="o">.</span><span class="n">url_scheme</span> <span class="ow">or</span> <span class="s1">&#39;http&#39;</span><span class="p">,</span>
  1283. <span class="bp">self</span><span class="o">.</span><span class="n">subdomain</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">subdomain</span> <span class="o">+</span> <span class="s1">&#39;.&#39;</span> <span class="ow">or</span> <span class="s1">&#39;&#39;</span><span class="p">,</span>
  1284. <span class="bp">self</span><span class="o">.</span><span class="n">server_name</span><span class="p">,</span>
  1285. <span class="bp">self</span><span class="o">.</span><span class="n">script_name</span>
  1286. <span class="p">),</span> <span class="n">redirect_url</span><span class="p">)))</span>
  1287. <span class="k">if</span> <span class="n">return_rule</span><span class="p">:</span>
  1288. <span class="k">return</span> <span class="n">rule</span><span class="p">,</span> <span class="n">rv</span>
  1289. <span class="k">else</span><span class="p">:</span>
  1290. <span class="k">return</span> <span class="n">rule</span><span class="o">.</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">rv</span>
  1291. <span class="k">if</span> <span class="n">have_match_for</span><span class="p">:</span>
  1292. <span class="k">raise</span> <span class="n">MethodNotAllowed</span><span class="p">(</span><span class="n">valid_methods</span><span class="o">=</span><span class="nb">list</span><span class="p">(</span><span class="n">have_match_for</span><span class="p">))</span>
  1293. <span class="k">raise</span> <span class="n">NotFound</span><span class="p">()</span>
  1294. <span class="k">def</span> <span class="nf">test</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path_info</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
  1295. <span class="sd">&quot;&quot;&quot;Test if a rule would match. Works like `match` but returns `True`</span>
  1296. <span class="sd"> if the URL matches, or `False` if it does not exist.</span>
  1297. <span class="sd"> :param path_info: the path info to use for matching. Overrides the</span>
  1298. <span class="sd"> path info specified on binding.</span>
  1299. <span class="sd"> :param method: the HTTP method used for matching. Overrides the</span>
  1300. <span class="sd"> method specified on binding.</span>
  1301. <span class="sd"> &quot;&quot;&quot;</span>
  1302. <span class="k">try</span><span class="p">:</span>
  1303. <span class="bp">self</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">path_info</span><span class="p">,</span> <span class="n">method</span><span class="p">)</span>
  1304. <span class="k">except</span> <span class="n">RequestRedirect</span><span class="p">:</span>
  1305. <span class="k">pass</span>
  1306. <span class="k">except</span> <span class="n">HTTPException</span><span class="p">:</span>
  1307. <span class="k">return</span> <span class="kc">False</span>
  1308. <span class="k">return</span> <span class="kc">True</span>
  1309. <span class="k">def</span> <span class="nf">allowed_methods</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path_info</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
  1310. <span class="sd">&quot;&quot;&quot;Returns the valid methods that match for a given path.</span>
  1311. <span class="sd"> .. versionadded:: 0.7</span>
  1312. <span class="sd"> &quot;&quot;&quot;</span>
  1313. <span class="k">try</span><span class="p">:</span>
  1314. <span class="bp">self</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">path_info</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s1">&#39;--&#39;</span><span class="p">)</span>
  1315. <span class="k">except</span> <span class="n">MethodNotAllowed</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
  1316. <span class="k">return</span> <span class="n">e</span><span class="o">.</span><span class="n">valid_methods</span>
  1317. <span class="k">except</span> <span class="n">HTTPException</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
  1318. <span class="k">pass</span>
  1319. <span class="k">return</span> <span class="p">[]</span>
  1320. <span class="k">def</span> <span class="nf">get_host</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">domain_part</span><span class="p">):</span>
  1321. <span class="sd">&quot;&quot;&quot;Figures out the full host name for the given domain part. The</span>
  1322. <span class="sd"> domain part is a subdomain in case host matching is disabled or</span>
  1323. <span class="sd"> a full host name.</span>
  1324. <span class="sd"> &quot;&quot;&quot;</span>
  1325. <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">host_matching</span><span class="p">:</span>
  1326. <span class="k">if</span> <span class="n">domain_part</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
  1327. <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">server_name</span>
  1328. <span class="k">return</span> <span class="n">to_unicode</span><span class="p">(</span><span class="n">domain_part</span><span class="p">,</span> <span class="s1">&#39;ascii&#39;</span><span class="p">)</span>
  1329. <span class="n">subdomain</span> <span class="o">=</span> <span class="n">domain_part</span>
  1330. <span class="k">if</span> <span class="n">subdomain</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
  1331. <span class="n">subdomain</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">subdomain</span>
  1332. <span class="k">else</span><span class="p">:</span>
  1333. <span class="n">subdomain</span> <span class="o">=</span> <span class="n">to_unicode</span><span class="p">(</span><span class="n">subdomain</span><span class="p">,</span> <span class="s1">&#39;ascii&#39;</span><span class="p">)</span>
  1334. <span class="k">return</span> <span class="p">(</span><span class="n">subdomain</span> <span class="ow">and</span> <span class="n">subdomain</span> <span class="o">+</span> <span class="s1">u&#39;.&#39;</span> <span class="ow">or</span> <span class="s1">u&#39;&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">server_name</span>
  1335. <span class="k">def</span> <span class="nf">get_default_redirect</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">rule</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="n">values</span><span class="p">,</span> <span class="n">query_args</span><span class="p">):</span>
  1336. <span class="sd">&quot;&quot;&quot;A helper that returns the URL to redirect to if it finds one.</span>
  1337. <span class="sd"> This is used for default redirecting only.</span>
  1338. <span class="sd"> :internal:</span>
  1339. <span class="sd"> &quot;&quot;&quot;</span>
  1340. <span class="k">assert</span> <span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">redirect_defaults</span>
  1341. <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">_rules_by_endpoint</span><span class="p">[</span><span class="n">rule</span><span class="o">.</span><span class="n">endpoint</span><span class="p">]:</span>
  1342. <span class="c1"># every rule that comes after this one, including ourself</span>
  1343. <span class="c1"># has a lower priority for the defaults. We order the ones</span>
  1344. <span class="c1"># with the highest priority up for building.</span>
  1345. <span class="k">if</span> <span class="n">r</span> <span class="ow">is</span> <span class="n">rule</span><span class="p">:</span>
  1346. <span class="k">break</span>
  1347. <span class="k">if</span> <span class="n">r</span><span class="o">.</span><span class="n">provides_defaults_for</span><span class="p">(</span><span class="n">rule</span><span class="p">)</span> <span class="ow">and</span> \
  1348. <span class="n">r</span><span class="o">.</span><span class="n">suitable_for</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="n">method</span><span class="p">):</span>
  1349. <span class="n">values</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
  1350. <span class="n">domain_part</span><span class="p">,</span> <span class="n">path</span> <span class="o">=</span> <span class="n">r</span><span class="o">.</span><span class="n">build</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>
  1351. <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">make_redirect_url</span><span class="p">(</span>
  1352. <span class="n">path</span><span class="p">,</span> <span class="n">query_args</span><span class="p">,</span> <span class="n">domain_part</span><span class="o">=</span><span class="n">domain_part</span><span class="p">)</span>
  1353. <span class="k">def</span> <span class="nf">encode_query_args</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">query_args</span><span class="p">):</span>
  1354. <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">query_args</span><span class="p">,</span> <span class="n">string_types</span><span class="p">):</span>
  1355. <span class="n">query_args</span> <span class="o">=</span> <span class="n">url_encode</span><span class="p">(</span><span class="n">query_args</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">charset</span><span class="p">)</span>
  1356. <span class="k">return</span> <span class="n">query_args</span>
  1357. <span class="k">def</span> <span class="nf">make_redirect_url</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path_info</span><span class="p">,</span> <span class="n">query_args</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">domain_part</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
  1358. <span class="sd">&quot;&quot;&quot;Creates a redirect URL.</span>
  1359. <span class="sd"> :internal:</span>
  1360. <span class="sd"> &quot;&quot;&quot;</span>
  1361. <span class="n">suffix</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span>
  1362. <span class="k">if</span> <span class="n">query_args</span><span class="p">:</span>
  1363. <span class="n">suffix</span> <span class="o">=</span> <span class="s1">&#39;?&#39;</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">encode_query_args</span><span class="p">(</span><span class="n">query_args</span><span class="p">)</span>
  1364. <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">%s</span><span class="s1">://</span><span class="si">%s</span><span class="s1">/</span><span class="si">%s%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span>
  1365. <span class="bp">self</span><span class="o">.</span><span class="n">url_scheme</span> <span class="ow">or</span> <span class="s1">&#39;http&#39;</span><span class="p">,</span>
  1366. <span class="bp">self</span><span class="o">.</span><span class="n">get_host</span><span class="p">(</span><span class="n">domain_part</span><span class="p">),</span>
  1367. <span class="n">posixpath</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">script_name</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">),</span>
  1368. <span class="n">path_info</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">)),</span>
  1369. <span class="n">suffix</span>
  1370. <span class="p">))</span>
  1371. <span class="k">def</span> <span class="nf">make_alias_redirect_url</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="n">query_args</span><span class="p">):</span>
  1372. <span class="sd">&quot;&quot;&quot;Internally called to make an alias redirect URL.&quot;&quot;&quot;</span>
  1373. <span class="n">url</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">build</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="n">append_unknown</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
  1374. <span class="n">force_external</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
  1375. <span class="k">if</span> <span class="n">query_args</span><span class="p">:</span>
  1376. <span class="n">url</span> <span class="o">+=</span> <span class="s1">&#39;?&#39;</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">encode_query_args</span><span class="p">(</span><span class="n">query_args</span><span class="p">)</span>
  1377. <span class="k">assert</span> <span class="n">url</span> <span class="o">!=</span> <span class="n">path</span><span class="p">,</span> <span class="s1">&#39;detected invalid alias setting. No canonical &#39;</span> \
  1378. <span class="s1">&#39;URL found&#39;</span>
  1379. <span class="k">return</span> <span class="n">url</span>
  1380. <span class="k">def</span> <span class="nf">_partial_build</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="n">append_unknown</span><span class="p">):</span>
  1381. <span class="sd">&quot;&quot;&quot;Helper for :meth:`build`. Returns subdomain and path for the</span>
  1382. <span class="sd"> rule that accepts this endpoint, values and method.</span>
  1383. <span class="sd"> :internal:</span>
  1384. <span class="sd"> &quot;&quot;&quot;</span>
  1385. <span class="c1"># in case the method is none, try with the default method first</span>
  1386. <span class="k">if</span> <span class="n">method</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
  1387. <span class="n">rv</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_partial_build</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">default_method</span><span class="p">,</span>
  1388. <span class="n">append_unknown</span><span class="p">)</span>
  1389. <span class="k">if</span> <span class="n">rv</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
  1390. <span class="k">return</span> <span class="n">rv</span>
  1391. <span class="c1"># default method did not match or a specific method is passed,</span>
  1392. <span class="c1"># check all and go with first result.</span>
  1393. <span class="k">for</span> <span class="n">rule</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">_rules_by_endpoint</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="p">()):</span>
  1394. <span class="k">if</span> <span class="n">rule</span><span class="o">.</span><span class="n">suitable_for</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="n">method</span><span class="p">):</span>
  1395. <span class="n">rv</span> <span class="o">=</span> <span class="n">rule</span><span class="o">.</span><span class="n">build</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="n">append_unknown</span><span class="p">)</span>
  1396. <span class="k">if</span> <span class="n">rv</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
  1397. <span class="k">return</span> <span class="n">rv</span>
  1398. <span class="k">def</span> <span class="nf">build</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">force_external</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
  1399. <span class="n">append_unknown</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
  1400. <span class="sd">&quot;&quot;&quot;Building URLs works pretty much the other way round. Instead of</span>
  1401. <span class="sd"> `match` you call `build` and pass it the endpoint and a dict of</span>
  1402. <span class="sd"> arguments for the placeholders.</span>
  1403. <span class="sd"> The `build` function also accepts an argument called `force_external`</span>
  1404. <span class="sd"> which, if you set it to `True` will force external URLs. Per default</span>
  1405. <span class="sd"> external URLs (include the server name) will only be used if the</span>
  1406. <span class="sd"> target URL is on a different subdomain.</span>
  1407. <span class="sd"> &gt;&gt;&gt; m = Map([</span>
  1408. <span class="sd"> ... Rule(&#39;/&#39;, endpoint=&#39;index&#39;),</span>
  1409. <span class="sd"> ... Rule(&#39;/downloads/&#39;, endpoint=&#39;downloads/index&#39;),</span>
  1410. <span class="sd"> ... Rule(&#39;/downloads/&lt;int:id&gt;&#39;, endpoint=&#39;downloads/show&#39;)</span>
  1411. <span class="sd"> ... ])</span>
  1412. <span class="sd"> &gt;&gt;&gt; urls = m.bind(&quot;example.com&quot;, &quot;/&quot;)</span>
  1413. <span class="sd"> &gt;&gt;&gt; urls.build(&quot;index&quot;, {})</span>
  1414. <span class="sd"> &#39;/&#39;</span>
  1415. <span class="sd"> &gt;&gt;&gt; urls.build(&quot;downloads/show&quot;, {&#39;id&#39;: 42})</span>
  1416. <span class="sd"> &#39;/downloads/42&#39;</span>
  1417. <span class="sd"> &gt;&gt;&gt; urls.build(&quot;downloads/show&quot;, {&#39;id&#39;: 42}, force_external=True)</span>
  1418. <span class="sd"> &#39;http://example.com/downloads/42&#39;</span>
  1419. <span class="sd"> Because URLs cannot contain non ASCII data you will always get</span>
  1420. <span class="sd"> bytestrings back. Non ASCII characters are urlencoded with the</span>
  1421. <span class="sd"> charset defined on the map instance.</span>
  1422. <span class="sd"> Additional values are converted to unicode and appended to the URL as</span>
  1423. <span class="sd"> URL querystring parameters:</span>
  1424. <span class="sd"> &gt;&gt;&gt; urls.build(&quot;index&quot;, {&#39;q&#39;: &#39;My Searchstring&#39;})</span>
  1425. <span class="sd"> &#39;/?q=My+Searchstring&#39;</span>
  1426. <span class="sd"> When processing those additional values, lists are furthermore</span>
  1427. <span class="sd"> interpreted as multiple values (as per</span>
  1428. <span class="sd"> :py:class:`werkzeug.datastructures.MultiDict`):</span>
  1429. <span class="sd"> &gt;&gt;&gt; urls.build(&quot;index&quot;, {&#39;q&#39;: [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;]})</span>
  1430. <span class="sd"> &#39;/?q=a&amp;q=b&amp;q=c&#39;</span>
  1431. <span class="sd"> If a rule does not exist when building a `BuildError` exception is</span>
  1432. <span class="sd"> raised.</span>
  1433. <span class="sd"> The build method accepts an argument called `method` which allows you</span>
  1434. <span class="sd"> to specify the method you want to have an URL built for if you have</span>
  1435. <span class="sd"> different methods for the same endpoint specified.</span>
  1436. <span class="sd"> .. versionadded:: 0.6</span>
  1437. <span class="sd"> the `append_unknown` parameter was added.</span>
  1438. <span class="sd"> :param endpoint: the endpoint of the URL to build.</span>
  1439. <span class="sd"> :param values: the values for the URL to build. Unhandled values are</span>
  1440. <span class="sd"> appended to the URL as query parameters.</span>
  1441. <span class="sd"> :param method: the HTTP method for the rule if there are different</span>
  1442. <span class="sd"> URLs for different methods on the same endpoint.</span>
  1443. <span class="sd"> :param force_external: enforce full canonical external URLs. If the URL</span>
  1444. <span class="sd"> scheme is not provided, this will generate</span>
  1445. <span class="sd"> a protocol-relative URL.</span>
  1446. <span class="sd"> :param append_unknown: unknown parameters are appended to the generated</span>
  1447. <span class="sd"> URL as query string argument. Disable this</span>
  1448. <span class="sd"> if you want the builder to ignore those.</span>
  1449. <span class="sd"> &quot;&quot;&quot;</span>
  1450. <span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">update</span><span class="p">()</span>
  1451. <span class="k">if</span> <span class="n">values</span><span class="p">:</span>
  1452. <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="n">MultiDict</span><span class="p">):</span>
  1453. <span class="n">valueiter</span> <span class="o">=</span> <span class="n">iteritems</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="n">multi</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
  1454. <span class="k">else</span><span class="p">:</span>
  1455. <span class="n">valueiter</span> <span class="o">=</span> <span class="n">iteritems</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>
  1456. <span class="n">values</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">((</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">valueiter</span> <span class="k">if</span> <span class="n">v</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">)</span>
  1457. <span class="k">else</span><span class="p">:</span>
  1458. <span class="n">values</span> <span class="o">=</span> <span class="p">{}</span>
  1459. <span class="n">rv</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_partial_build</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="n">append_unknown</span><span class="p">)</span>
  1460. <span class="k">if</span> <span class="n">rv</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
  1461. <span class="k">raise</span> <span class="n">BuildError</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span>
  1462. <span class="n">domain_part</span><span class="p">,</span> <span class="n">path</span> <span class="o">=</span> <span class="n">rv</span>
  1463. <span class="n">host</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_host</span><span class="p">(</span><span class="n">domain_part</span><span class="p">)</span>
  1464. <span class="c1"># shortcut this.</span>
  1465. <span class="k">if</span> <span class="ow">not</span> <span class="n">force_external</span> <span class="ow">and</span> <span class="p">(</span>
  1466. <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">host_matching</span> <span class="ow">and</span> <span class="n">host</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">server_name</span><span class="p">)</span> <span class="ow">or</span>
  1467. <span class="p">(</span><span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">host_matching</span> <span class="ow">and</span> <span class="n">domain_part</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">subdomain</span><span class="p">)</span>
  1468. <span class="p">):</span>
  1469. <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="n">url_join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">script_name</span><span class="p">,</span> <span class="s1">&#39;./&#39;</span> <span class="o">+</span> <span class="n">path</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">)))</span>
  1470. <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">%s</span><span class="s1">//</span><span class="si">%s%s</span><span class="s1">/</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span>
  1471. <span class="bp">self</span><span class="o">.</span><span class="n">url_scheme</span> <span class="o">+</span> <span class="s1">&#39;:&#39;</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">url_scheme</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span><span class="p">,</span>
  1472. <span class="n">host</span><span class="p">,</span>
  1473. <span class="bp">self</span><span class="o">.</span><span class="n">script_name</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span>
  1474. <span class="n">path</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">)</span>
  1475. <span class="p">))</span>
  1476. </pre></div>
  1477. </div>
  1478. </div>
  1479. </div>
  1480. <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
  1481. <div class="sphinxsidebarwrapper"><div class="relations">
  1482. <h3>Related Topics</h3>
  1483. <ul>
  1484. <li><a href="../../index.html">Documentation overview</a><ul>
  1485. <li><a href="../index.html">Module code</a><ul>
  1486. </ul></li>
  1487. </ul></li>
  1488. </ul>
  1489. </div>
  1490. <div id="searchbox" style="display: none" role="search">
  1491. <h3>Quick search</h3>
  1492. <form class="search" action="../../search.html" method="get">
  1493. <div><input type="text" name="q" /></div>
  1494. <div><input type="submit" value="Go" /></div>
  1495. <input type="hidden" name="check_keywords" value="yes" />
  1496. <input type="hidden" name="area" value="default" />
  1497. </form>
  1498. </div>
  1499. <script type="text/javascript">$('#searchbox').show(0);</script>
  1500. </div>
  1501. </div>
  1502. <div class="clearer"></div>
  1503. </div>
  1504. <div class="footer">
  1505. &copy;2016, Author.
  1506. |
  1507. Powered by <a href="http://sphinx-doc.org/">Sphinx 1.4.8</a>
  1508. &amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.9</a>
  1509. </div>
  1510. </body>
  1511. </html>