<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang=""> <head> <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>django.template.base — Django 1.11.20 documentation</title> <link rel="stylesheet" href="../../../_static/default.css" type="text/css" /> <link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" /> <script type="text/javascript" id="documentation_options" data-url_root="../../../" src="../../../_static/documentation_options.js"></script> <script type="text/javascript" src="../../../_static/jquery.js"></script> <script type="text/javascript" src="../../../_static/underscore.js"></script> <script type="text/javascript" src="../../../_static/doctools.js"></script> <script type="text/javascript" src="../../../_static/language_data.js"></script> <link rel="index" title="Index" href="../../../genindex.html" /> <link rel="search" title="Search" href="../../../search.html" /> <script type="text/javascript" src="../../../templatebuiltins.js"></script> <script type="text/javascript"> (function($) { if (!django_template_builtins) { // templatebuiltins.js missing, do nothing. return; } $(document).ready(function() { // Hyperlink Django template tags and filters var base = "../../../ref/templates/builtins.html"; if (base == "#") { // Special case for builtins.html itself base = ""; } // Tags are keywords, class '.k' $("div.highlight\\-html\\+django span.k").each(function(i, elem) { var tagname = $(elem).text(); if ($.inArray(tagname, django_template_builtins.ttags) != -1) { var fragment = tagname.replace(/_/, '-'); $(elem).html("<a href='" + base + "#" + fragment + "'>" + tagname + "</a>"); } }); // Filters are functions, class '.nf' $("div.highlight\\-html\\+django span.nf").each(function(i, elem) { var filtername = $(elem).text(); if ($.inArray(filtername, django_template_builtins.tfilters) != -1) { var fragment = filtername.replace(/_/, '-'); $(elem).html("<a href='" + base + "#" + fragment + "'>" + filtername + "</a>"); } }); }); })(jQuery); </script> </head><body> <div class="document"> <div id="custom-doc" class="yui-t6"> <div id="hd"> <h1><a href="../../../index.html">Django 1.11.20 documentation</a></h1> <div id="global-nav"> <a title="Home page" href="../../../index.html">Home</a> | <a title="Table of contents" href="../../../contents.html">Table of contents</a> | <a title="Global index" href="../../../genindex.html">Index</a> | <a title="Module index" href="../../../py-modindex.html">Modules</a> </div> <div class="nav"> <a href="../../index.html" title="Module code" accesskey="U">up</a></div> </div> <div id="bd"> <div id="yui-main"> <div class="yui-b"> <div class="yui-g" id="_modules-django-template-base"> <h1>Source code for django.template.base</h1><div class="highlight"><pre> <span></span><span class="sd">"""</span> <span class="sd">This is the Django template system.</span> <span class="sd">How it works:</span> <span class="sd">The Lexer.tokenize() function converts a template string (i.e., a string containing</span> <span class="sd">markup with custom template tags) to tokens, which can be either plain text</span> <span class="sd">(TOKEN_TEXT), variables (TOKEN_VAR) or block statements (TOKEN_BLOCK).</span> <span class="sd">The Parser() class takes a list of tokens in its constructor, and its parse()</span> <span class="sd">method returns a compiled template -- which is, under the hood, a list of</span> <span class="sd">Node objects.</span> <span class="sd">Each Node is responsible for creating some sort of output -- e.g. simple text</span> <span class="sd">(TextNode), variable values in a given context (VariableNode), results of basic</span> <span class="sd">logic (IfNode), results of looping (ForNode), or anything else. The core Node</span> <span class="sd">types are TextNode, VariableNode, IfNode and ForNode, but plugin modules can</span> <span class="sd">define their own custom node types.</span> <span class="sd">Each Node has a render() method, which takes a Context and returns a string of</span> <span class="sd">the rendered node. For example, the render() method of a Variable Node returns</span> <span class="sd">the variable's value as a string. The render() method of a ForNode returns the</span> <span class="sd">rendered output of whatever was inside the loop, recursively.</span> <span class="sd">The Template class is a convenient wrapper that takes care of template</span> <span class="sd">compilation and rendering.</span> <span class="sd">Usage:</span> <span class="sd">The only thing you should ever use directly in this file is the Template class.</span> <span class="sd">Create a compiled template object with a template_string, then call render()</span> <span class="sd">with a context. In the compilation stage, the TemplateSyntaxError exception</span> <span class="sd">will be raised if the template doesn't have proper syntax.</span> <span class="sd">Sample code:</span> <span class="sd">>>> from django import template</span> <span class="sd">>>> s = '<html>{% if test %}<h1>{{ varvalue }}</h1>{% endif %}</html>'</span> <span class="sd">>>> t = template.Template(s)</span> <span class="sd">(t is now a compiled template, and its render() method can be called multiple</span> <span class="sd">times with multiple contexts)</span> <span class="sd">>>> c = template.Context({'test':True, 'varvalue': 'Hello'})</span> <span class="sd">>>> t.render(c)</span> <span class="sd">'<html><h1>Hello</h1></html>'</span> <span class="sd">>>> c = template.Context({'test':False, 'varvalue': 'Hello'})</span> <span class="sd">>>> t.render(c)</span> <span class="sd">'<html></html>'</span> <span class="sd">"""</span> <span class="kn">from</span> <span class="nn">__future__</span> <span class="k">import</span> <span class="n">unicode_literals</span> <span class="kn">import</span> <span class="nn">inspect</span> <span class="kn">import</span> <span class="nn">logging</span> <span class="kn">import</span> <span class="nn">re</span> <span class="kn">import</span> <span class="nn">warnings</span> <span class="kn">from</span> <span class="nn">django.template.context</span> <span class="k">import</span> <span class="p">(</span> <span class="c1"># NOQA: imported for backwards compatibility</span> <span class="n">BaseContext</span><span class="p">,</span> <span class="n">Context</span><span class="p">,</span> <span class="n">ContextPopException</span><span class="p">,</span> <span class="n">RequestContext</span><span class="p">,</span> <span class="p">)</span> <span class="kn">from</span> <span class="nn">django.utils</span> <span class="k">import</span> <span class="n">six</span> <span class="kn">from</span> <span class="nn">django.utils.deprecation</span> <span class="k">import</span> <span class="p">(</span> <span class="n">DeprecationInstanceCheck</span><span class="p">,</span> <span class="n">RemovedInDjango20Warning</span><span class="p">,</span> <span class="p">)</span> <span class="kn">from</span> <span class="nn">django.utils.encoding</span> <span class="k">import</span> <span class="p">(</span> <span class="n">force_str</span><span class="p">,</span> <span class="n">force_text</span><span class="p">,</span> <span class="n">python_2_unicode_compatible</span><span class="p">,</span> <span class="p">)</span> <span class="kn">from</span> <span class="nn">django.utils.formats</span> <span class="k">import</span> <span class="n">localize</span> <span class="kn">from</span> <span class="nn">django.utils.html</span> <span class="k">import</span> <span class="n">conditional_escape</span><span class="p">,</span> <span class="n">escape</span> <span class="kn">from</span> <span class="nn">django.utils.inspect</span> <span class="k">import</span> <span class="n">getargspec</span> <span class="kn">from</span> <span class="nn">django.utils.safestring</span> <span class="k">import</span> <span class="p">(</span> <span class="n">EscapeData</span><span class="p">,</span> <span class="n">SafeData</span><span class="p">,</span> <span class="n">mark_for_escaping</span><span class="p">,</span> <span class="n">mark_safe</span><span class="p">,</span> <span class="p">)</span> <span class="kn">from</span> <span class="nn">django.utils.text</span> <span class="k">import</span> <span class="p">(</span> <span class="n">get_text_list</span><span class="p">,</span> <span class="n">smart_split</span><span class="p">,</span> <span class="n">unescape_string_literal</span><span class="p">,</span> <span class="p">)</span> <span class="kn">from</span> <span class="nn">django.utils.timezone</span> <span class="k">import</span> <span class="n">template_localtime</span> <span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="k">import</span> <span class="n">pgettext_lazy</span><span class="p">,</span> <span class="n">ugettext_lazy</span> <span class="kn">from</span> <span class="nn">.exceptions</span> <span class="k">import</span> <span class="n">TemplateSyntaxError</span> <span class="n">TOKEN_TEXT</span> <span class="o">=</span> <span class="mi">0</span> <span class="n">TOKEN_VAR</span> <span class="o">=</span> <span class="mi">1</span> <span class="n">TOKEN_BLOCK</span> <span class="o">=</span> <span class="mi">2</span> <span class="n">TOKEN_COMMENT</span> <span class="o">=</span> <span class="mi">3</span> <span class="n">TOKEN_MAPPING</span> <span class="o">=</span> <span class="p">{</span> <span class="n">TOKEN_TEXT</span><span class="p">:</span> <span class="s1">'Text'</span><span class="p">,</span> <span class="n">TOKEN_VAR</span><span class="p">:</span> <span class="s1">'Var'</span><span class="p">,</span> <span class="n">TOKEN_BLOCK</span><span class="p">:</span> <span class="s1">'Block'</span><span class="p">,</span> <span class="n">TOKEN_COMMENT</span><span class="p">:</span> <span class="s1">'Comment'</span><span class="p">,</span> <span class="p">}</span> <span class="c1"># template syntax constants</span> <span class="n">FILTER_SEPARATOR</span> <span class="o">=</span> <span class="s1">'|'</span> <span class="n">FILTER_ARGUMENT_SEPARATOR</span> <span class="o">=</span> <span class="s1">':'</span> <span class="n">VARIABLE_ATTRIBUTE_SEPARATOR</span> <span class="o">=</span> <span class="s1">'.'</span> <span class="n">BLOCK_TAG_START</span> <span class="o">=</span> <span class="s1">'{%'</span> <span class="n">BLOCK_TAG_END</span> <span class="o">=</span> <span class="s1">'%}'</span> <span class="n">VARIABLE_TAG_START</span> <span class="o">=</span> <span class="s1">'{{'</span> <span class="n">VARIABLE_TAG_END</span> <span class="o">=</span> <span class="s1">'}}'</span> <span class="n">COMMENT_TAG_START</span> <span class="o">=</span> <span class="s1">'{#'</span> <span class="n">COMMENT_TAG_END</span> <span class="o">=</span> <span class="s1">'#}'</span> <span class="n">TRANSLATOR_COMMENT_MARK</span> <span class="o">=</span> <span class="s1">'Translators'</span> <span class="n">SINGLE_BRACE_START</span> <span class="o">=</span> <span class="s1">'{'</span> <span class="n">SINGLE_BRACE_END</span> <span class="o">=</span> <span class="s1">'}'</span> <span class="c1"># what to report as the origin for templates that come from non-loader sources</span> <span class="c1"># (e.g. strings)</span> <span class="n">UNKNOWN_SOURCE</span> <span class="o">=</span> <span class="s1">'<unknown source>'</span> <span class="c1"># match a variable or block tag and capture the entire tag, including start/end</span> <span class="c1"># delimiters</span> <span class="n">tag_re</span> <span class="o">=</span> <span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s1">'(</span><span class="si">%s</span><span class="s1">.*?</span><span class="si">%s</span><span class="s1">|</span><span class="si">%s</span><span class="s1">.*?</span><span class="si">%s</span><span class="s1">|</span><span class="si">%s</span><span class="s1">.*?</span><span class="si">%s</span><span class="s1">)'</span> <span class="o">%</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">BLOCK_TAG_START</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">BLOCK_TAG_END</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_TAG_START</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_TAG_END</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">COMMENT_TAG_START</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">COMMENT_TAG_END</span><span class="p">))))</span> <span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s1">'django.template'</span><span class="p">)</span> <span class="k">class</span> <span class="nc">TemplateEncodingError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span> <span class="k">pass</span> <span class="nd">@python_2_unicode_compatible</span> <span class="k">class</span> <span class="nc">VariableDoesNotExist</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span> <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">msg</span><span class="p">,</span> <span class="n">params</span><span class="o">=</span><span class="p">()):</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">=</span> <span class="n">msg</span> <span class="bp">self</span><span class="o">.</span><span class="n">params</span> <span class="o">=</span> <span class="n">params</span> <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">%</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">force_text</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="s1">'replace'</span><span class="p">)</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">params</span><span class="p">)</span> <div class="viewcode-block" id="Origin"><a class="viewcode-back" href="../../../ref/templates/api.html#django.template.Origin">[docs]</a><span class="k">class</span> <span class="nc">Origin</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <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">name</span><span class="p">,</span> <span class="n">template_name</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">loader</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span> <span class="bp">self</span><span class="o">.</span><span class="n">template_name</span> <span class="o">=</span> <span class="n">template_name</span> <span class="bp">self</span><span class="o">.</span><span class="n">loader</span> <span class="o">=</span> <span class="n">loader</span> <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <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> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">Origin</span><span class="p">):</span> <span class="k">return</span> <span class="kc">False</span> <span class="k">return</span> <span class="p">(</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="n">other</span><span class="o">.</span><span class="n">name</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">loader</span> <span class="o">==</span> <span class="n">other</span><span class="o">.</span><span class="n">loader</span> <span class="p">)</span> <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> <span class="k">return</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="fm">__eq__</span><span class="p">(</span><span class="n">other</span><span class="p">)</span> <span class="nd">@property</span> <span class="k">def</span> <span class="nf">loader_name</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">loader</span><span class="p">:</span> <span class="k">return</span> <span class="s1">'</span><span class="si">%s</span><span class="s1">.</span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span> <span class="bp">self</span><span class="o">.</span><span class="n">loader</span><span class="o">.</span><span class="vm">__module__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">loader</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="p">)</span></div> <span class="k">class</span> <span class="nc">StringOrigin</span><span class="p">(</span><span class="n">six</span><span class="o">.</span><span class="n">with_metaclass</span><span class="p">(</span><span class="n">DeprecationInstanceCheck</span><span class="p">,</span> <span class="n">Origin</span><span class="p">)):</span> <span class="n">alternative</span> <span class="o">=</span> <span class="s1">'django.template.Origin'</span> <span class="n">deprecation_warning</span> <span class="o">=</span> <span class="n">RemovedInDjango20Warning</span> <div class="viewcode-block" id="Template"><a class="viewcode-back" href="../../../ref/templates/api.html#django.template.Template">[docs]</a><span class="k">class</span> <span class="nc">Template</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <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">template_string</span><span class="p">,</span> <span class="n">origin</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">engine</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> <span class="k">try</span><span class="p">:</span> <span class="n">template_string</span> <span class="o">=</span> <span class="n">force_text</span><span class="p">(</span><span class="n">template_string</span><span class="p">)</span> <span class="k">except</span> <span class="ne">UnicodeDecodeError</span><span class="p">:</span> <span class="k">raise</span> <span class="n">TemplateEncodingError</span><span class="p">(</span><span class="s2">"Templates can only be constructed "</span> <span class="s2">"from unicode or UTF-8 strings."</span><span class="p">)</span> <span class="c1"># If Template is instantiated directly rather than from an Engine and</span> <span class="c1"># exactly one Django template engine is configured, use that engine.</span> <span class="c1"># This is required to preserve backwards-compatibility for direct use</span> <span class="c1"># e.g. Template('...').render(Context({...}))</span> <span class="k">if</span> <span class="n">engine</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span> <span class="kn">from</span> <span class="nn">.engine</span> <span class="k">import</span> <span class="n">Engine</span> <span class="n">engine</span> <span class="o">=</span> <span class="n">Engine</span><span class="o">.</span><span class="n">get_default</span><span class="p">()</span> <span class="k">if</span> <span class="n">origin</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span> <span class="n">origin</span> <span class="o">=</span> <span class="n">Origin</span><span class="p">(</span><span class="n">UNKNOWN_SOURCE</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span> <span class="bp">self</span><span class="o">.</span><span class="n">origin</span> <span class="o">=</span> <span class="n">origin</span> <span class="bp">self</span><span class="o">.</span><span class="n">engine</span> <span class="o">=</span> <span class="n">engine</span> <span class="bp">self</span><span class="o">.</span><span class="n">source</span> <span class="o">=</span> <span class="n">template_string</span> <span class="bp">self</span><span class="o">.</span><span class="n">nodelist</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">compile_nodelist</span><span class="p">()</span> <span class="k">def</span> <span class="nf">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">nodelist</span><span class="p">:</span> <span class="k">for</span> <span class="n">subnode</span> <span class="ow">in</span> <span class="n">node</span><span class="p">:</span> <span class="k">yield</span> <span class="n">subnode</span> <span class="k">def</span> <span class="nf">_render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">nodelist</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="n">context</span><span class="p">)</span> <div class="viewcode-block" id="Template.render"><a class="viewcode-back" href="../../../ref/templates/api.html#django.template.Template.render">[docs]</a> <span class="k">def</span> <span class="nf">render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span> <span class="s2">"Display stage -- can be called many times"</span> <span class="k">with</span> <span class="n">context</span><span class="o">.</span><span class="n">render_context</span><span class="o">.</span><span class="n">push_state</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">if</span> <span class="n">context</span><span class="o">.</span><span class="n">template</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span> <span class="k">with</span> <span class="n">context</span><span class="o">.</span><span class="n">bind_template</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">context</span><span class="o">.</span><span class="n">template_name</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_render</span><span class="p">(</span><span class="n">context</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_render</span><span class="p">(</span><span class="n">context</span><span class="p">)</span></div> <span class="k">def</span> <span class="nf">compile_nodelist</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Parse and compile the template source into a nodelist. If debug</span> <span class="sd"> is True and an exception occurs during parsing, the exception is</span> <span class="sd"> is annotated with contextual line information where it occurred in the</span> <span class="sd"> template source.</span> <span class="sd"> """</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">debug</span><span class="p">:</span> <span class="n">lexer</span> <span class="o">=</span> <span class="n">DebugLexer</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">lexer</span> <span class="o">=</span> <span class="n">Lexer</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">)</span> <span class="n">tokens</span> <span class="o">=</span> <span class="n">lexer</span><span class="o">.</span><span class="n">tokenize</span><span class="p">()</span> <span class="n">parser</span> <span class="o">=</span> <span class="n">Parser</span><span class="p">(</span> <span class="n">tokens</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">template_libraries</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">template_builtins</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">origin</span><span class="p">,</span> <span class="p">)</span> <span class="k">try</span><span class="p">:</span> <span class="k">return</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse</span><span class="p">()</span> <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">debug</span><span class="p">:</span> <span class="n">e</span><span class="o">.</span><span class="n">template_debug</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_exception_info</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">token</span><span class="p">)</span> <span class="k">raise</span> <span class="k">def</span> <span class="nf">get_exception_info</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exception</span><span class="p">,</span> <span class="n">token</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Return a dictionary containing contextual line information of where</span> <span class="sd"> the exception occurred in the template. The following information is</span> <span class="sd"> provided:</span> <span class="sd"> message</span> <span class="sd"> The message of the exception raised.</span> <span class="sd"> source_lines</span> <span class="sd"> The lines before, after, and including the line the exception</span> <span class="sd"> occurred on.</span> <span class="sd"> line</span> <span class="sd"> The line number the exception occurred on.</span> <span class="sd"> before, during, after</span> <span class="sd"> The line the exception occurred on split into three parts:</span> <span class="sd"> 1. The content before the token that raised the error.</span> <span class="sd"> 2. The token that raised the error.</span> <span class="sd"> 3. The content after the token that raised the error.</span> <span class="sd"> total</span> <span class="sd"> The number of lines in source_lines.</span> <span class="sd"> top</span> <span class="sd"> The line number where source_lines starts.</span> <span class="sd"> bottom</span> <span class="sd"> The line number where source_lines ends.</span> <span class="sd"> start</span> <span class="sd"> The start position of the token in the template source.</span> <span class="sd"> end</span> <span class="sd"> The end position of the token in the template source.</span> <span class="sd"> """</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="o">=</span> <span class="n">token</span><span class="o">.</span><span class="n">position</span> <span class="n">context_lines</span> <span class="o">=</span> <span class="mi">10</span> <span class="n">line</span> <span class="o">=</span> <span class="mi">0</span> <span class="n">upto</span> <span class="o">=</span> <span class="mi">0</span> <span class="n">source_lines</span> <span class="o">=</span> <span class="p">[]</span> <span class="n">before</span> <span class="o">=</span> <span class="n">during</span> <span class="o">=</span> <span class="n">after</span> <span class="o">=</span> <span class="s2">""</span> <span class="k">for</span> <span class="n">num</span><span class="p">,</span> <span class="nb">next</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">linebreak_iter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">)):</span> <span class="k">if</span> <span class="n">start</span> <span class="o">>=</span> <span class="n">upto</span> <span class="ow">and</span> <span class="n">end</span> <span class="o"><=</span> <span class="nb">next</span><span class="p">:</span> <span class="n">line</span> <span class="o">=</span> <span class="n">num</span> <span class="n">before</span> <span class="o">=</span> <span class="n">escape</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">[</span><span class="n">upto</span><span class="p">:</span><span class="n">start</span><span class="p">])</span> <span class="n">during</span> <span class="o">=</span> <span class="n">escape</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">[</span><span class="n">start</span><span class="p">:</span><span class="n">end</span><span class="p">])</span> <span class="n">after</span> <span class="o">=</span> <span class="n">escape</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">[</span><span class="n">end</span><span class="p">:</span><span class="nb">next</span><span class="p">])</span> <span class="n">source_lines</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">num</span><span class="p">,</span> <span class="n">escape</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">[</span><span class="n">upto</span><span class="p">:</span><span class="nb">next</span><span class="p">])))</span> <span class="n">upto</span> <span class="o">=</span> <span class="nb">next</span> <span class="n">total</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">source_lines</span><span class="p">)</span> <span class="n">top</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">line</span> <span class="o">-</span> <span class="n">context_lines</span><span class="p">)</span> <span class="n">bottom</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">total</span><span class="p">,</span> <span class="n">line</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">+</span> <span class="n">context_lines</span><span class="p">)</span> <span class="c1"># In some rare cases exc_value.args can be empty or an invalid</span> <span class="c1"># unicode string.</span> <span class="k">try</span><span class="p">:</span> <span class="n">message</span> <span class="o">=</span> <span class="n">force_text</span><span class="p">(</span><span class="n">exception</span><span class="o">.</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="k">except</span> <span class="p">(</span><span class="ne">IndexError</span><span class="p">,</span> <span class="ne">UnicodeDecodeError</span><span class="p">):</span> <span class="n">message</span> <span class="o">=</span> <span class="s1">'(Could not get exception message)'</span> <span class="k">return</span> <span class="p">{</span> <span class="s1">'message'</span><span class="p">:</span> <span class="n">message</span><span class="p">,</span> <span class="s1">'source_lines'</span><span class="p">:</span> <span class="n">source_lines</span><span class="p">[</span><span class="n">top</span><span class="p">:</span><span class="n">bottom</span><span class="p">],</span> <span class="s1">'before'</span><span class="p">:</span> <span class="n">before</span><span class="p">,</span> <span class="s1">'during'</span><span class="p">:</span> <span class="n">during</span><span class="p">,</span> <span class="s1">'after'</span><span class="p">:</span> <span class="n">after</span><span class="p">,</span> <span class="s1">'top'</span><span class="p">:</span> <span class="n">top</span><span class="p">,</span> <span class="s1">'bottom'</span><span class="p">:</span> <span class="n">bottom</span><span class="p">,</span> <span class="s1">'total'</span><span class="p">:</span> <span class="n">total</span><span class="p">,</span> <span class="s1">'line'</span><span class="p">:</span> <span class="n">line</span><span class="p">,</span> <span class="s1">'name'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">origin</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="s1">'start'</span><span class="p">:</span> <span class="n">start</span><span class="p">,</span> <span class="s1">'end'</span><span class="p">:</span> <span class="n">end</span><span class="p">,</span> <span class="p">}</span></div> <span class="k">def</span> <span class="nf">linebreak_iter</span><span class="p">(</span><span class="n">template_source</span><span class="p">):</span> <span class="k">yield</span> <span class="mi">0</span> <span class="n">p</span> <span class="o">=</span> <span class="n">template_source</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="p">)</span> <span class="k">while</span> <span class="n">p</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">:</span> <span class="k">yield</span> <span class="n">p</span> <span class="o">+</span> <span class="mi">1</span> <span class="n">p</span> <span class="o">=</span> <span class="n">template_source</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="p">,</span> <span class="n">p</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="k">yield</span> <span class="nb">len</span><span class="p">(</span><span class="n">template_source</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span> <span class="k">class</span> <span class="nc">Token</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <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">token_type</span><span class="p">,</span> <span class="n">contents</span><span class="p">,</span> <span class="n">position</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">lineno</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> A token representing a string from the template.</span> <span class="sd"> token_type</span> <span class="sd"> One of TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK, or TOKEN_COMMENT.</span> <span class="sd"> contents</span> <span class="sd"> The token source string.</span> <span class="sd"> position</span> <span class="sd"> An optional tuple containing the start and end index of the token</span> <span class="sd"> in the template source. This is used for traceback information</span> <span class="sd"> when debug is on.</span> <span class="sd"> lineno</span> <span class="sd"> The line number the token appears on in the template source.</span> <span class="sd"> This is used for traceback information and gettext files.</span> <span class="sd"> """</span> <span class="bp">self</span><span class="o">.</span><span class="n">token_type</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">contents</span> <span class="o">=</span> <span class="n">token_type</span><span class="p">,</span> <span class="n">contents</span> <span class="bp">self</span><span class="o">.</span><span class="n">lineno</span> <span class="o">=</span> <span class="n">lineno</span> <span class="bp">self</span><span class="o">.</span><span class="n">position</span> <span class="o">=</span> <span class="n">position</span> <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">token_name</span> <span class="o">=</span> <span class="n">TOKEN_MAPPING</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">token_type</span><span class="p">]</span> <span class="k">return</span> <span class="p">(</span><span class="s1">'<</span><span class="si">%s</span><span class="s1"> token: "</span><span class="si">%s</span><span class="s1">...">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">token_name</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">[:</span><span class="mi">20</span><span class="p">]</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="p">,</span> <span class="s1">''</span><span class="p">)))</span> <span class="k">def</span> <span class="nf">split_contents</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">split</span> <span class="o">=</span> <span class="p">[]</span> <span class="n">bits</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">smart_split</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">))</span> <span class="k">for</span> <span class="n">bit</span> <span class="ow">in</span> <span class="n">bits</span><span class="p">:</span> <span class="c1"># Handle translation-marked template pieces</span> <span class="k">if</span> <span class="n">bit</span><span class="o">.</span><span class="n">startswith</span><span class="p">((</span><span class="s1">'_("'</span><span class="p">,</span> <span class="s2">"_('"</span><span class="p">)):</span> <span class="n">sentinel</span> <span class="o">=</span> <span class="n">bit</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="s1">')'</span> <span class="n">trans_bit</span> <span class="o">=</span> <span class="p">[</span><span class="n">bit</span><span class="p">]</span> <span class="k">while</span> <span class="ow">not</span> <span class="n">bit</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="n">sentinel</span><span class="p">):</span> <span class="n">bit</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="n">bits</span><span class="p">)</span> <span class="n">trans_bit</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">bit</span><span class="p">)</span> <span class="n">bit</span> <span class="o">=</span> <span class="s1">' '</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">trans_bit</span><span class="p">)</span> <span class="n">split</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">bit</span><span class="p">)</span> <span class="k">return</span> <span class="n">split</span> <span class="k">class</span> <span class="nc">Lexer</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <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">template_string</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">template_string</span> <span class="o">=</span> <span class="n">template_string</span> <span class="bp">self</span><span class="o">.</span><span class="n">verbatim</span> <span class="o">=</span> <span class="kc">False</span> <span class="k">def</span> <span class="nf">tokenize</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Return a list of tokens from a given template_string.</span> <span class="sd"> """</span> <span class="n">in_tag</span> <span class="o">=</span> <span class="kc">False</span> <span class="n">lineno</span> <span class="o">=</span> <span class="mi">1</span> <span class="n">result</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">bit</span> <span class="ow">in</span> <span class="n">tag_re</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">template_string</span><span class="p">):</span> <span class="k">if</span> <span class="n">bit</span><span class="p">:</span> <span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">create_token</span><span class="p">(</span><span class="n">bit</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="n">lineno</span><span class="p">,</span> <span class="n">in_tag</span><span class="p">))</span> <span class="n">in_tag</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">in_tag</span> <span class="n">lineno</span> <span class="o">+=</span> <span class="n">bit</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="p">)</span> <span class="k">return</span> <span class="n">result</span> <span class="k">def</span> <span class="nf">create_token</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">token_string</span><span class="p">,</span> <span class="n">position</span><span class="p">,</span> <span class="n">lineno</span><span class="p">,</span> <span class="n">in_tag</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Convert the given token string into a new Token object and return it.</span> <span class="sd"> If in_tag is True, we are processing something that matched a tag,</span> <span class="sd"> otherwise it should be treated as a literal string.</span> <span class="sd"> """</span> <span class="k">if</span> <span class="n">in_tag</span> <span class="ow">and</span> <span class="n">token_string</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">BLOCK_TAG_START</span><span class="p">):</span> <span class="c1"># The [2:-2] ranges below strip off *_TAG_START and *_TAG_END.</span> <span class="c1"># We could do len(BLOCK_TAG_START) to be more "correct", but we've</span> <span class="c1"># hard-coded the 2s here for performance. And it's not like</span> <span class="c1"># the TAG_START values are going to change anytime, anyway.</span> <span class="n">block_content</span> <span class="o">=</span> <span class="n">token_string</span><span class="p">[</span><span class="mi">2</span><span class="p">:</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">verbatim</span> <span class="ow">and</span> <span class="n">block_content</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">verbatim</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">verbatim</span> <span class="o">=</span> <span class="kc">False</span> <span class="k">if</span> <span class="n">in_tag</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">verbatim</span><span class="p">:</span> <span class="k">if</span> <span class="n">token_string</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">VARIABLE_TAG_START</span><span class="p">):</span> <span class="n">token</span> <span class="o">=</span> <span class="n">Token</span><span class="p">(</span><span class="n">TOKEN_VAR</span><span class="p">,</span> <span class="n">token_string</span><span class="p">[</span><span class="mi">2</span><span class="p">:</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">(),</span> <span class="n">position</span><span class="p">,</span> <span class="n">lineno</span><span class="p">)</span> <span class="k">elif</span> <span class="n">token_string</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">BLOCK_TAG_START</span><span class="p">):</span> <span class="k">if</span> <span class="n">block_content</span><span class="p">[:</span><span class="mi">9</span><span class="p">]</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">'verbatim'</span><span class="p">,</span> <span class="s1">'verbatim '</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">verbatim</span> <span class="o">=</span> <span class="s1">'end</span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="n">block_content</span> <span class="n">token</span> <span class="o">=</span> <span class="n">Token</span><span class="p">(</span><span class="n">TOKEN_BLOCK</span><span class="p">,</span> <span class="n">block_content</span><span class="p">,</span> <span class="n">position</span><span class="p">,</span> <span class="n">lineno</span><span class="p">)</span> <span class="k">elif</span> <span class="n">token_string</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">COMMENT_TAG_START</span><span class="p">):</span> <span class="n">content</span> <span class="o">=</span> <span class="s1">''</span> <span class="k">if</span> <span class="n">token_string</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">TRANSLATOR_COMMENT_MARK</span><span class="p">):</span> <span class="n">content</span> <span class="o">=</span> <span class="n">token_string</span><span class="p">[</span><span class="mi">2</span><span class="p">:</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="n">token</span> <span class="o">=</span> <span class="n">Token</span><span class="p">(</span><span class="n">TOKEN_COMMENT</span><span class="p">,</span> <span class="n">content</span><span class="p">,</span> <span class="n">position</span><span class="p">,</span> <span class="n">lineno</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">token</span> <span class="o">=</span> <span class="n">Token</span><span class="p">(</span><span class="n">TOKEN_TEXT</span><span class="p">,</span> <span class="n">token_string</span><span class="p">,</span> <span class="n">position</span><span class="p">,</span> <span class="n">lineno</span><span class="p">)</span> <span class="k">return</span> <span class="n">token</span> <span class="k">class</span> <span class="nc">DebugLexer</span><span class="p">(</span><span class="n">Lexer</span><span class="p">):</span> <span class="k">def</span> <span class="nf">tokenize</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Split a template string into tokens and annotates each token with its</span> <span class="sd"> start and end position in the source. This is slower than the default</span> <span class="sd"> lexer so we only use it when debug is True.</span> <span class="sd"> """</span> <span class="n">lineno</span> <span class="o">=</span> <span class="mi">1</span> <span class="n">result</span> <span class="o">=</span> <span class="p">[]</span> <span class="n">upto</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">tag_re</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">template_string</span><span class="p">):</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">span</span><span class="p">()</span> <span class="k">if</span> <span class="n">start</span> <span class="o">></span> <span class="n">upto</span><span class="p">:</span> <span class="n">token_string</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">template_string</span><span class="p">[</span><span class="n">upto</span><span class="p">:</span><span class="n">start</span><span class="p">]</span> <span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">create_token</span><span class="p">(</span><span class="n">token_string</span><span class="p">,</span> <span class="p">(</span><span class="n">upto</span><span class="p">,</span> <span class="n">start</span><span class="p">),</span> <span class="n">lineno</span><span class="p">,</span> <span class="n">in_tag</span><span class="o">=</span><span class="kc">False</span><span class="p">))</span> <span class="n">lineno</span> <span class="o">+=</span> <span class="n">token_string</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="p">)</span> <span class="n">upto</span> <span class="o">=</span> <span class="n">start</span> <span class="n">token_string</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">template_string</span><span class="p">[</span><span class="n">start</span><span class="p">:</span><span class="n">end</span><span class="p">]</span> <span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">create_token</span><span class="p">(</span><span class="n">token_string</span><span class="p">,</span> <span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">),</span> <span class="n">lineno</span><span class="p">,</span> <span class="n">in_tag</span><span class="o">=</span><span class="kc">True</span><span class="p">))</span> <span class="n">lineno</span> <span class="o">+=</span> <span class="n">token_string</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="p">)</span> <span class="n">upto</span> <span class="o">=</span> <span class="n">end</span> <span class="n">last_bit</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">template_string</span><span class="p">[</span><span class="n">upto</span><span class="p">:]</span> <span class="k">if</span> <span class="n">last_bit</span><span class="p">:</span> <span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">create_token</span><span class="p">(</span><span class="n">last_bit</span><span class="p">,</span> <span class="p">(</span><span class="n">upto</span><span class="p">,</span> <span class="n">upto</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="n">last_bit</span><span class="p">)),</span> <span class="n">lineno</span><span class="p">,</span> <span class="n">in_tag</span><span class="o">=</span><span class="kc">False</span><span class="p">))</span> <span class="k">return</span> <span class="n">result</span> <span class="k">class</span> <span class="nc">Parser</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <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">tokens</span><span class="p">,</span> <span class="n">libraries</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">builtins</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">origin</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">tokens</span> <span class="o">=</span> <span class="n">tokens</span> <span class="bp">self</span><span class="o">.</span><span class="n">tags</span> <span class="o">=</span> <span class="p">{}</span> <span class="bp">self</span><span class="o">.</span><span class="n">filters</span> <span class="o">=</span> <span class="p">{}</span> <span class="bp">self</span><span class="o">.</span><span class="n">command_stack</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">if</span> <span class="n">libraries</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span> <span class="n">libraries</span> <span class="o">=</span> <span class="p">{}</span> <span class="k">if</span> <span class="n">builtins</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span> <span class="n">builtins</span> <span class="o">=</span> <span class="p">[]</span> <span class="bp">self</span><span class="o">.</span><span class="n">libraries</span> <span class="o">=</span> <span class="n">libraries</span> <span class="k">for</span> <span class="n">builtin</span> <span class="ow">in</span> <span class="n">builtins</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">add_library</span><span class="p">(</span><span class="n">builtin</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">origin</span> <span class="o">=</span> <span class="n">origin</span> <span class="k">def</span> <span class="nf">parse</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">parse_until</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Iterate through the parser tokens and compiles each one into a node.</span> <span class="sd"> If parse_until is provided, parsing will stop once one of the</span> <span class="sd"> specified tokens has been reached. This is formatted as a list of</span> <span class="sd"> tokens, e.g. ['elif', 'else', 'endif']. If no matching token is</span> <span class="sd"> reached, raise an exception with the unclosed block tag details.</span> <span class="sd"> """</span> <span class="k">if</span> <span class="n">parse_until</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span> <span class="n">parse_until</span> <span class="o">=</span> <span class="p">[]</span> <span class="n">nodelist</span> <span class="o">=</span> <span class="n">NodeList</span><span class="p">()</span> <span class="k">while</span> <span class="bp">self</span><span class="o">.</span><span class="n">tokens</span><span class="p">:</span> <span class="n">token</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">next_token</span><span class="p">()</span> <span class="c1"># Use the raw values here for TOKEN_* for a tiny performance boost.</span> <span class="k">if</span> <span class="n">token</span><span class="o">.</span><span class="n">token_type</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span> <span class="c1"># TOKEN_TEXT</span> <span class="bp">self</span><span class="o">.</span><span class="n">extend_nodelist</span><span class="p">(</span><span class="n">nodelist</span><span class="p">,</span> <span class="n">TextNode</span><span class="p">(</span><span class="n">token</span><span class="o">.</span><span class="n">contents</span><span class="p">),</span> <span class="n">token</span><span class="p">)</span> <span class="k">elif</span> <span class="n">token</span><span class="o">.</span><span class="n">token_type</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span> <span class="c1"># TOKEN_VAR</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">token</span><span class="o">.</span><span class="n">contents</span><span class="p">:</span> <span class="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">token</span><span class="p">,</span> <span class="s1">'Empty variable tag on line </span><span class="si">%d</span><span class="s1">'</span> <span class="o">%</span> <span class="n">token</span><span class="o">.</span><span class="n">lineno</span><span class="p">)</span> <span class="k">try</span><span class="p">:</span> <span class="n">filter_expression</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">compile_filter</span><span class="p">(</span><span class="n">token</span><span class="o">.</span><span class="n">contents</span><span class="p">)</span> <span class="k">except</span> <span class="n">TemplateSyntaxError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> <span class="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">token</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span> <span class="n">var_node</span> <span class="o">=</span> <span class="n">VariableNode</span><span class="p">(</span><span class="n">filter_expression</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">extend_nodelist</span><span class="p">(</span><span class="n">nodelist</span><span class="p">,</span> <span class="n">var_node</span><span class="p">,</span> <span class="n">token</span><span class="p">)</span> <span class="k">elif</span> <span class="n">token</span><span class="o">.</span><span class="n">token_type</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span> <span class="c1"># TOKEN_BLOCK</span> <span class="k">try</span><span class="p">:</span> <span class="n">command</span> <span class="o">=</span> <span class="n">token</span><span class="o">.</span><span class="n">contents</span><span class="o">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span> <span class="k">except</span> <span class="ne">IndexError</span><span class="p">:</span> <span class="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">token</span><span class="p">,</span> <span class="s1">'Empty block tag on line </span><span class="si">%d</span><span class="s1">'</span> <span class="o">%</span> <span class="n">token</span><span class="o">.</span><span class="n">lineno</span><span class="p">)</span> <span class="k">if</span> <span class="n">command</span> <span class="ow">in</span> <span class="n">parse_until</span><span class="p">:</span> <span class="c1"># A matching token has been reached. Return control to</span> <span class="c1"># the caller. Put the token back on the token list so the</span> <span class="c1"># caller knows where it terminated.</span> <span class="bp">self</span><span class="o">.</span><span class="n">prepend_token</span><span class="p">(</span><span class="n">token</span><span class="p">)</span> <span class="k">return</span> <span class="n">nodelist</span> <span class="c1"># Add the token to the command stack. This is used for error</span> <span class="c1"># messages if further parsing fails due to an unclosed block</span> <span class="c1"># tag.</span> <span class="bp">self</span><span class="o">.</span><span class="n">command_stack</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">command</span><span class="p">,</span> <span class="n">token</span><span class="p">))</span> <span class="c1"># Get the tag callback function from the ones registered with</span> <span class="c1"># the parser.</span> <span class="k">try</span><span class="p">:</span> <span class="n">compile_func</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="p">[</span><span class="n">command</span><span class="p">]</span> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">invalid_block_tag</span><span class="p">(</span><span class="n">token</span><span class="p">,</span> <span class="n">command</span><span class="p">,</span> <span class="n">parse_until</span><span class="p">)</span> <span class="c1"># Compile the callback into a node object and add it to</span> <span class="c1"># the node list.</span> <span class="k">try</span><span class="p">:</span> <span class="n">compiled_result</span> <span class="o">=</span> <span class="n">compile_func</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">token</span><span class="p">)</span> <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> <span class="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">token</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">extend_nodelist</span><span class="p">(</span><span class="n">nodelist</span><span class="p">,</span> <span class="n">compiled_result</span><span class="p">,</span> <span class="n">token</span><span class="p">)</span> <span class="c1"># Compile success. Remove the token from the command stack.</span> <span class="bp">self</span><span class="o">.</span><span class="n">command_stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span> <span class="k">if</span> <span class="n">parse_until</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">unclosed_block_tag</span><span class="p">(</span><span class="n">parse_until</span><span class="p">)</span> <span class="k">return</span> <span class="n">nodelist</span> <span class="k">def</span> <span class="nf">skip_past</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">endtag</span><span class="p">):</span> <span class="k">while</span> <span class="bp">self</span><span class="o">.</span><span class="n">tokens</span><span class="p">:</span> <span class="n">token</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">next_token</span><span class="p">()</span> <span class="k">if</span> <span class="n">token</span><span class="o">.</span><span class="n">token_type</span> <span class="o">==</span> <span class="n">TOKEN_BLOCK</span> <span class="ow">and</span> <span class="n">token</span><span class="o">.</span><span class="n">contents</span> <span class="o">==</span> <span class="n">endtag</span><span class="p">:</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">unclosed_block_tag</span><span class="p">([</span><span class="n">endtag</span><span class="p">])</span> <span class="k">def</span> <span class="nf">extend_nodelist</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nodelist</span><span class="p">,</span> <span class="n">node</span><span class="p">,</span> <span class="n">token</span><span class="p">):</span> <span class="c1"># Check that non-text nodes don't appear before an extends tag.</span> <span class="k">if</span> <span class="n">node</span><span class="o">.</span><span class="n">must_be_first</span> <span class="ow">and</span> <span class="n">nodelist</span><span class="o">.</span><span class="n">contains_nontext</span><span class="p">:</span> <span class="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">(</span> <span class="n">token</span><span class="p">,</span> <span class="s1">'</span><span class="si">%r</span><span class="s1"> must be the first tag in the template.'</span> <span class="o">%</span> <span class="n">node</span><span class="p">,</span> <span class="p">)</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">nodelist</span><span class="p">,</span> <span class="n">NodeList</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">TextNode</span><span class="p">):</span> <span class="n">nodelist</span><span class="o">.</span><span class="n">contains_nontext</span> <span class="o">=</span> <span class="kc">True</span> <span class="c1"># Set origin and token here since we can't modify the node __init__()</span> <span class="c1"># method.</span> <span class="n">node</span><span class="o">.</span><span class="n">token</span> <span class="o">=</span> <span class="n">token</span> <span class="n">node</span><span class="o">.</span><span class="n">origin</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">origin</span> <span class="n">nodelist</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">node</span><span class="p">)</span> <span class="k">def</span> <span class="nf">error</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">token</span><span class="p">,</span> <span class="n">e</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Return an exception annotated with the originating token. Since the</span> <span class="sd"> parser can be called recursively, check if a token is already set. This</span> <span class="sd"> ensures the innermost token is highlighted if an exception occurs,</span> <span class="sd"> e.g. a compile error within the body of an if statement.</span> <span class="sd"> """</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="ne">Exception</span><span class="p">):</span> <span class="n">e</span> <span class="o">=</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="n">e</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="s1">'token'</span><span class="p">):</span> <span class="n">e</span><span class="o">.</span><span class="n">token</span> <span class="o">=</span> <span class="n">token</span> <span class="k">return</span> <span class="n">e</span> <span class="k">def</span> <span class="nf">invalid_block_tag</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">token</span><span class="p">,</span> <span class="n">command</span><span class="p">,</span> <span class="n">parse_until</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> <span class="k">if</span> <span class="n">parse_until</span><span class="p">:</span> <span class="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">(</span> <span class="n">token</span><span class="p">,</span> <span class="s2">"Invalid block tag on line </span><span class="si">%d</span><span class="s2">: '</span><span class="si">%s</span><span class="s2">', expected </span><span class="si">%s</span><span class="s2">. Did you "</span> <span class="s2">"forget to register or load this tag?"</span> <span class="o">%</span> <span class="p">(</span> <span class="n">token</span><span class="o">.</span><span class="n">lineno</span><span class="p">,</span> <span class="n">command</span><span class="p">,</span> <span class="n">get_text_list</span><span class="p">([</span><span class="s2">"'</span><span class="si">%s</span><span class="s2">'"</span> <span class="o">%</span> <span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">parse_until</span><span class="p">],</span> <span class="s1">'or'</span><span class="p">),</span> <span class="p">),</span> <span class="p">)</span> <span class="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">(</span> <span class="n">token</span><span class="p">,</span> <span class="s2">"Invalid block tag on line </span><span class="si">%d</span><span class="s2">: '</span><span class="si">%s</span><span class="s2">'. Did you forget to register "</span> <span class="s2">"or load this tag?"</span> <span class="o">%</span> <span class="p">(</span><span class="n">token</span><span class="o">.</span><span class="n">lineno</span><span class="p">,</span> <span class="n">command</span><span class="p">)</span> <span class="p">)</span> <span class="k">def</span> <span class="nf">unclosed_block_tag</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">parse_until</span><span class="p">):</span> <span class="n">command</span><span class="p">,</span> <span class="n">token</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">command_stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span> <span class="n">msg</span> <span class="o">=</span> <span class="s2">"Unclosed tag on line </span><span class="si">%d</span><span class="s2">: '</span><span class="si">%s</span><span class="s2">'. Looking for one of: </span><span class="si">%s</span><span class="s2">."</span> <span class="o">%</span> <span class="p">(</span> <span class="n">token</span><span class="o">.</span><span class="n">lineno</span><span class="p">,</span> <span class="n">command</span><span class="p">,</span> <span class="s1">', '</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">parse_until</span><span class="p">),</span> <span class="p">)</span> <span class="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">token</span><span class="p">,</span> <span class="n">msg</span><span class="p">)</span> <span class="k">def</span> <span class="nf">next_token</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">tokens</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="k">def</span> <span class="nf">prepend_token</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">token</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">tokens</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">token</span><span class="p">)</span> <span class="k">def</span> <span class="nf">delete_first_token</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">tokens</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">def</span> <span class="nf">add_library</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">lib</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">lib</span><span class="o">.</span><span class="n">tags</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">filters</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">lib</span><span class="o">.</span><span class="n">filters</span><span class="p">)</span> <span class="k">def</span> <span class="nf">compile_filter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">token</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Convenient wrapper for FilterExpression</span> <span class="sd"> """</span> <span class="k">return</span> <span class="n">FilterExpression</span><span class="p">(</span><span class="n">token</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span> <span class="k">def</span> <span class="nf">find_filter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filter_name</span><span class="p">):</span> <span class="k">if</span> <span class="n">filter_name</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">filters</span><span class="p">:</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">filters</span><span class="p">[</span><span class="n">filter_name</span><span class="p">]</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="s2">"Invalid filter: '</span><span class="si">%s</span><span class="s2">'"</span> <span class="o">%</span> <span class="n">filter_name</span><span class="p">)</span> <span class="c1"># This only matches constant *strings* (things in quotes or marked for</span> <span class="c1"># translation). Numbers are treated as variables for implementation reasons</span> <span class="c1"># (so that they retain their type when passed to filters).</span> <span class="n">constant_string</span> <span class="o">=</span> <span class="sa">r</span><span class="s2">"""</span> <span class="s2">(?:</span><span class="si">%(i18n_open)s%(strdq)s%(i18n_close)s</span><span class="s2">|</span> <span class="si">%(i18n_open)s%(strsq)s%(i18n_close)s</span><span class="s2">|</span> <span class="si">%(strdq)s</span><span class="s2">|</span> <span class="si">%(strsq)s</span><span class="s2">)</span> <span class="s2">"""</span> <span class="o">%</span> <span class="p">{</span> <span class="s1">'strdq'</span><span class="p">:</span> <span class="sa">r</span><span class="s1">'"[^"</span><span class="se">\\</span><span class="s1">]*(?:</span><span class="se">\\</span><span class="s1">.[^"</span><span class="se">\\</span><span class="s1">]*)*"'</span><span class="p">,</span> <span class="c1"># double-quoted string</span> <span class="s1">'strsq'</span><span class="p">:</span> <span class="sa">r</span><span class="s2">"'[^'</span><span class="se">\\</span><span class="s2">]*(?:</span><span class="se">\\</span><span class="s2">.[^'</span><span class="se">\\</span><span class="s2">]*)*'"</span><span class="p">,</span> <span class="c1"># single-quoted string</span> <span class="s1">'i18n_open'</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="s2">"_("</span><span class="p">),</span> <span class="s1">'i18n_close'</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="s2">")"</span><span class="p">),</span> <span class="p">}</span> <span class="n">constant_string</span> <span class="o">=</span> <span class="n">constant_string</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="s2">""</span><span class="p">)</span> <span class="n">filter_raw_string</span> <span class="o">=</span> <span class="sa">r</span><span class="s2">"""</span> <span class="s2">^(?P<constant></span><span class="si">%(constant)s</span><span class="s2">)|</span> <span class="s2">^(?P<var>[</span><span class="si">%(var_chars)s</span><span class="s2">]+|</span><span class="si">%(num)s</span><span class="s2">)|</span> <span class="s2"> (?:\s*</span><span class="si">%(filter_sep)s</span><span class="s2">\s*</span> <span class="s2"> (?P<filter_name>\w+)</span> <span class="s2"> (?:</span><span class="si">%(arg_sep)s</span><span class="s2"></span> <span class="s2"> (?:</span> <span class="s2"> (?P<constant_arg></span><span class="si">%(constant)s</span><span class="s2">)|</span> <span class="s2"> (?P<var_arg>[</span><span class="si">%(var_chars)s</span><span class="s2">]+|</span><span class="si">%(num)s</span><span class="s2">)</span> <span class="s2"> )</span> <span class="s2"> )?</span> <span class="s2"> )"""</span> <span class="o">%</span> <span class="p">{</span> <span class="s1">'constant'</span><span class="p">:</span> <span class="n">constant_string</span><span class="p">,</span> <span class="s1">'num'</span><span class="p">:</span> <span class="sa">r</span><span class="s1">'[-+\.]?\d[\d\.e]*'</span><span class="p">,</span> <span class="s1">'var_chars'</span><span class="p">:</span> <span class="sa">r</span><span class="s1">'\w\.'</span><span class="p">,</span> <span class="s1">'filter_sep'</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">FILTER_SEPARATOR</span><span class="p">),</span> <span class="s1">'arg_sep'</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">FILTER_ARGUMENT_SEPARATOR</span><span class="p">),</span> <span class="p">}</span> <span class="n">filter_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="n">filter_raw_string</span><span class="p">,</span> <span class="n">re</span><span class="o">.</span><span class="n">UNICODE</span> <span class="o">|</span> <span class="n">re</span><span class="o">.</span><span class="n">VERBOSE</span><span class="p">)</span> <span class="k">class</span> <span class="nc">FilterExpression</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Parses a variable token and its optional filters (all as a single string),</span> <span class="sd"> and return a list of tuples of the filter name and arguments.</span> <span class="sd"> Sample::</span> <span class="sd"> >>> token = 'variable|default:"Default value"|date:"Y-m-d"'</span> <span class="sd"> >>> p = Parser('')</span> <span class="sd"> >>> fe = FilterExpression(token, p)</span> <span class="sd"> >>> len(fe.filters)</span> <span class="sd"> 2</span> <span class="sd"> >>> fe.var</span> <span class="sd"> <Variable: 'variable'></span> <span class="sd"> """</span> <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">token</span><span class="p">,</span> <span class="n">parser</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">token</span> <span class="o">=</span> <span class="n">token</span> <span class="n">matches</span> <span class="o">=</span> <span class="n">filter_re</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">token</span><span class="p">)</span> <span class="n">var_obj</span> <span class="o">=</span> <span class="kc">None</span> <span class="n">filters</span> <span class="o">=</span> <span class="p">[]</span> <span class="n">upto</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">matches</span><span class="p">:</span> <span class="n">start</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">start</span><span class="p">()</span> <span class="k">if</span> <span class="n">upto</span> <span class="o">!=</span> <span class="n">start</span><span class="p">:</span> <span class="k">raise</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="s2">"Could not parse some characters: "</span> <span class="s2">"</span><span class="si">%s</span><span class="s2">|</span><span class="si">%s</span><span class="s2">|</span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">token</span><span class="p">[:</span><span class="n">upto</span><span class="p">],</span> <span class="n">token</span><span class="p">[</span><span class="n">upto</span><span class="p">:</span><span class="n">start</span><span class="p">],</span> <span class="n">token</span><span class="p">[</span><span class="n">start</span><span class="p">:]))</span> <span class="k">if</span> <span class="n">var_obj</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span> <span class="n">var</span><span class="p">,</span> <span class="n">constant</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s2">"var"</span><span class="p">,</span> <span class="s2">"constant"</span><span class="p">)</span> <span class="k">if</span> <span class="n">constant</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="n">var_obj</span> <span class="o">=</span> <span class="n">Variable</span><span class="p">(</span><span class="n">constant</span><span class="p">)</span><span class="o">.</span><span class="n">resolve</span><span class="p">({})</span> <span class="k">except</span> <span class="n">VariableDoesNotExist</span><span class="p">:</span> <span class="n">var_obj</span> <span class="o">=</span> <span class="kc">None</span> <span class="k">elif</span> <span class="n">var</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span> <span class="k">raise</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="s2">"Could not find variable at "</span> <span class="s2">"start of </span><span class="si">%s</span><span class="s2">."</span> <span class="o">%</span> <span class="n">token</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">var_obj</span> <span class="o">=</span> <span class="n">Variable</span><span class="p">(</span><span class="n">var</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">filter_name</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s2">"filter_name"</span><span class="p">)</span> <span class="n">args</span> <span class="o">=</span> <span class="p">[]</span> <span class="n">constant_arg</span><span class="p">,</span> <span class="n">var_arg</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s2">"constant_arg"</span><span class="p">,</span> <span class="s2">"var_arg"</span><span class="p">)</span> <span class="k">if</span> <span class="n">constant_arg</span><span class="p">:</span> <span class="n">args</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><span class="n">constant_arg</span><span class="p">)</span><span class="o">.</span><span class="n">resolve</span><span class="p">({})))</span> <span class="k">elif</span> <span class="n">var_arg</span><span class="p">:</span> <span class="n">args</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><span class="n">var_arg</span><span class="p">)))</span> <span class="n">filter_func</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">find_filter</span><span class="p">(</span><span class="n">filter_name</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">args_check</span><span class="p">(</span><span class="n">filter_name</span><span class="p">,</span> <span class="n">filter_func</span><span class="p">,</span> <span class="n">args</span><span class="p">)</span> <span class="n">filters</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">filter_func</span><span class="p">,</span> <span class="n">args</span><span class="p">))</span> <span class="n">upto</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">end</span><span class="p">()</span> <span class="k">if</span> <span class="n">upto</span> <span class="o">!=</span> <span class="nb">len</span><span class="p">(</span><span class="n">token</span><span class="p">):</span> <span class="k">raise</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="s2">"Could not parse the remainder: '</span><span class="si">%s</span><span class="s2">' "</span> <span class="s2">"from '</span><span class="si">%s</span><span class="s2">'"</span> <span class="o">%</span> <span class="p">(</span><span class="n">token</span><span class="p">[</span><span class="n">upto</span><span class="p">:],</span> <span class="n">token</span><span class="p">))</span> <span class="bp">self</span><span class="o">.</span><span class="n">filters</span> <span class="o">=</span> <span class="n">filters</span> <span class="bp">self</span><span class="o">.</span><span class="n">var</span> <span class="o">=</span> <span class="n">var_obj</span> <span class="k">def</span> <span class="nf">resolve</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">,</span> <span class="n">ignore_failures</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">var</span><span class="p">,</span> <span class="n">Variable</span><span class="p">):</span> <span class="k">try</span><span class="p">:</span> <span class="n">obj</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">var</span><span class="o">.</span><span class="n">resolve</span><span class="p">(</span><span class="n">context</span><span class="p">)</span> <span class="k">except</span> <span class="n">VariableDoesNotExist</span><span class="p">:</span> <span class="k">if</span> <span class="n">ignore_failures</span><span class="p">:</span> <span class="n">obj</span> <span class="o">=</span> <span class="kc">None</span> <span class="k">else</span><span class="p">:</span> <span class="n">string_if_invalid</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">string_if_invalid</span> <span class="k">if</span> <span class="n">string_if_invalid</span><span class="p">:</span> <span class="k">if</span> <span class="s1">'</span><span class="si">%s</span><span class="s1">'</span> <span class="ow">in</span> <span class="n">string_if_invalid</span><span class="p">:</span> <span class="k">return</span> <span class="n">string_if_invalid</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">var</span> <span class="k">else</span><span class="p">:</span> <span class="k">return</span> <span class="n">string_if_invalid</span> <span class="k">else</span><span class="p">:</span> <span class="n">obj</span> <span class="o">=</span> <span class="n">string_if_invalid</span> <span class="k">else</span><span class="p">:</span> <span class="n">obj</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">var</span> <span class="n">escape_isnt_last_filter</span> <span class="o">=</span> <span class="kc">True</span> <span class="k">for</span> <span class="n">func</span><span class="p">,</span> <span class="n">args</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">filters</span><span class="p">:</span> <span class="n">arg_vals</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">lookup</span><span class="p">,</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">lookup</span><span class="p">:</span> <span class="n">arg_vals</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">mark_safe</span><span class="p">(</span><span class="n">arg</span><span class="p">))</span> <span class="k">else</span><span class="p">:</span> <span class="n">arg_vals</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">arg</span><span class="o">.</span><span class="n">resolve</span><span class="p">(</span><span class="n">context</span><span class="p">))</span> <span class="k">if</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="s1">'expects_localtime'</span><span class="p">,</span> <span class="kc">False</span><span class="p">):</span> <span class="n">obj</span> <span class="o">=</span> <span class="n">template_localtime</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">context</span><span class="o">.</span><span class="n">use_tz</span><span class="p">)</span> <span class="k">if</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="s1">'needs_autoescape'</span><span class="p">,</span> <span class="kc">False</span><span class="p">):</span> <span class="n">new_obj</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">autoescape</span><span class="o">=</span><span class="n">context</span><span class="o">.</span><span class="n">autoescape</span><span class="p">,</span> <span class="o">*</span><span class="n">arg_vals</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">new_obj</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="o">*</span><span class="n">arg_vals</span><span class="p">)</span> <span class="k">if</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="s1">'is_safe'</span><span class="p">,</span> <span class="kc">False</span><span class="p">)</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">SafeData</span><span class="p">):</span> <span class="n">obj</span> <span class="o">=</span> <span class="n">mark_safe</span><span class="p">(</span><span class="n">new_obj</span><span class="p">)</span> <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">EscapeData</span><span class="p">):</span> <span class="k">with</span> <span class="n">warnings</span><span class="o">.</span><span class="n">catch_warnings</span><span class="p">():</span> <span class="c1"># Ignore mark_for_escaping deprecation as this will be</span> <span class="c1"># removed in Django 2.0.</span> <span class="n">warnings</span><span class="o">.</span><span class="n">simplefilter</span><span class="p">(</span><span class="s1">'ignore'</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="n">RemovedInDjango20Warning</span><span class="p">)</span> <span class="n">obj</span> <span class="o">=</span> <span class="n">mark_for_escaping</span><span class="p">(</span><span class="n">new_obj</span><span class="p">)</span> <span class="n">escape_isnt_last_filter</span> <span class="o">=</span> <span class="kc">False</span> <span class="k">else</span><span class="p">:</span> <span class="n">obj</span> <span class="o">=</span> <span class="n">new_obj</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">escape_isnt_last_filter</span><span class="p">:</span> <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span> <span class="s2">"escape isn't the last filter in </span><span class="si">%s</span><span class="s2"> and will be applied "</span> <span class="s2">"immediately in Django 2.0 so the output may change."</span> <span class="o">%</span> <span class="p">[</span><span class="n">func</span><span class="o">.</span><span class="vm">__name__</span> <span class="k">for</span> <span class="n">func</span><span class="p">,</span> <span class="n">_</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">filters</span><span class="p">],</span> <span class="n">RemovedInDjango20Warning</span><span class="p">,</span> <span class="n">stacklevel</span><span class="o">=</span><span class="mi">2</span> <span class="p">)</span> <span class="k">return</span> <span class="n">obj</span> <span class="k">def</span> <span class="nf">args_check</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">func</span><span class="p">,</span> <span class="n">provided</span><span class="p">):</span> <span class="n">provided</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">provided</span><span class="p">)</span> <span class="c1"># First argument, filter input, is implied.</span> <span class="n">plen</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">provided</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span> <span class="c1"># Check to see if a decorator is providing the real function.</span> <span class="n">func</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="s1">'_decorated_function'</span><span class="p">,</span> <span class="n">func</span><span class="p">)</span> <span class="n">args</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">defaults</span> <span class="o">=</span> <span class="n">getargspec</span><span class="p">(</span><span class="n">func</span><span class="p">)</span> <span class="n">alen</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">args</span><span class="p">)</span> <span class="n">dlen</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">defaults</span> <span class="ow">or</span> <span class="p">[])</span> <span class="c1"># Not enough OR Too many</span> <span class="k">if</span> <span class="n">plen</span> <span class="o"><</span> <span class="p">(</span><span class="n">alen</span> <span class="o">-</span> <span class="n">dlen</span><span class="p">)</span> <span class="ow">or</span> <span class="n">plen</span> <span class="o">></span> <span class="n">alen</span><span class="p">:</span> <span class="k">raise</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="s2">"</span><span class="si">%s</span><span class="s2"> requires </span><span class="si">%d</span><span class="s2"> arguments, </span><span class="si">%d</span><span class="s2"> provided"</span> <span class="o">%</span> <span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">alen</span> <span class="o">-</span> <span class="n">dlen</span><span class="p">,</span> <span class="n">plen</span><span class="p">))</span> <span class="k">return</span> <span class="kc">True</span> <span class="n">args_check</span> <span class="o">=</span> <span class="nb">staticmethod</span><span class="p">(</span><span class="n">args_check</span><span class="p">)</span> <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">token</span> <span class="k">class</span> <span class="nc">Variable</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> A template variable, resolvable against a given context. The variable may</span> <span class="sd"> be a hard-coded string (if it begins and ends with single or double quote</span> <span class="sd"> marks)::</span> <span class="sd"> >>> c = {'article': {'section':'News'}}</span> <span class="sd"> >>> Variable('article.section').resolve(c)</span> <span class="sd"> 'News'</span> <span class="sd"> >>> Variable('article').resolve(c)</span> <span class="sd"> {'section': 'News'}</span> <span class="sd"> >>> class AClass: pass</span> <span class="sd"> >>> c = AClass()</span> <span class="sd"> >>> c.article = AClass()</span> <span class="sd"> >>> c.article.section = 'News'</span> <span class="sd"> (The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.')</span> <span class="sd"> """</span> <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">var</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">var</span> <span class="o">=</span> <span class="n">var</span> <span class="bp">self</span><span class="o">.</span><span class="n">literal</span> <span class="o">=</span> <span class="kc">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">lookups</span> <span class="o">=</span> <span class="kc">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">translate</span> <span class="o">=</span> <span class="kc">False</span> <span class="bp">self</span><span class="o">.</span><span class="n">message_context</span> <span class="o">=</span> <span class="kc">None</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">var</span><span class="p">,</span> <span class="n">six</span><span class="o">.</span><span class="n">string_types</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span> <span class="s2">"Variable must be a string or number, got </span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="nb">type</span><span class="p">(</span><span class="n">var</span><span class="p">))</span> <span class="k">try</span><span class="p">:</span> <span class="c1"># First try to treat this variable as a number.</span> <span class="c1">#</span> <span class="c1"># Note that this could cause an OverflowError here that we're not</span> <span class="c1"># catching. Since this should only happen at compile time, that's</span> <span class="c1"># probably OK.</span> <span class="bp">self</span><span class="o">.</span><span class="n">literal</span> <span class="o">=</span> <span class="nb">float</span><span class="p">(</span><span class="n">var</span><span class="p">)</span> <span class="c1"># So it's a float... is it an int? If the original value contained a</span> <span class="c1"># dot or an "e" then it was a float, not an int.</span> <span class="k">if</span> <span class="s1">'.'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">var</span> <span class="ow">and</span> <span class="s1">'e'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">var</span><span class="o">.</span><span class="n">lower</span><span class="p">():</span> <span class="bp">self</span><span class="o">.</span><span class="n">literal</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">literal</span><span class="p">)</span> <span class="c1"># "2." is invalid</span> <span class="k">if</span> <span class="n">var</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s1">'.'</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">ValueError</span> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="c1"># A ValueError means that the variable isn't a number.</span> <span class="k">if</span> <span class="n">var</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">'_('</span><span class="p">)</span> <span class="ow">and</span> <span class="n">var</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s1">')'</span><span class="p">):</span> <span class="c1"># The result of the lookup should be translated at rendering</span> <span class="c1"># time.</span> <span class="bp">self</span><span class="o">.</span><span class="n">translate</span> <span class="o">=</span> <span class="kc">True</span> <span class="n">var</span> <span class="o">=</span> <span class="n">var</span><span class="p">[</span><span class="mi">2</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="c1"># If it's wrapped with quotes (single or double), then</span> <span class="c1"># we're also dealing with a literal.</span> <span class="k">try</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">literal</span> <span class="o">=</span> <span class="n">mark_safe</span><span class="p">(</span><span class="n">unescape_string_literal</span><span class="p">(</span><span class="n">var</span><span class="p">))</span> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="c1"># Otherwise we'll set self.lookups so that resolve() knows we're</span> <span class="c1"># dealing with a bonafide variable</span> <span class="k">if</span> <span class="n">var</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">VARIABLE_ATTRIBUTE_SEPARATOR</span> <span class="o">+</span> <span class="s1">'_'</span><span class="p">)</span> <span class="o">></span> <span class="o">-</span><span class="mi">1</span> <span class="ow">or</span> <span class="n">var</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'_'</span><span class="p">:</span> <span class="k">raise</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="s2">"Variables and attributes may "</span> <span class="s2">"not begin with underscores: '</span><span class="si">%s</span><span class="s2">'"</span> <span class="o">%</span> <span class="n">var</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">lookups</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">var</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">VARIABLE_ATTRIBUTE_SEPARATOR</span><span class="p">))</span> <span class="k">def</span> <span class="nf">resolve</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span> <span class="sd">"""Resolve this variable against a given context."""</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">lookups</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span> <span class="c1"># We're dealing with a variable that needs to be resolved</span> <span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_resolve_lookup</span><span class="p">(</span><span class="n">context</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="c1"># We're dealing with a literal, so it's already been "resolved"</span> <span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">literal</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">translate</span><span class="p">:</span> <span class="n">is_safe</span> <span class="o">=</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">SafeData</span><span class="p">)</span> <span class="n">msgid</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'%'</span><span class="p">,</span> <span class="s1">'</span><span class="si">%%</span><span class="s1">'</span><span class="p">)</span> <span class="n">msgid</span> <span class="o">=</span> <span class="n">mark_safe</span><span class="p">(</span><span class="n">msgid</span><span class="p">)</span> <span class="k">if</span> <span class="n">is_safe</span> <span class="k">else</span> <span class="n">msgid</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">message_context</span><span class="p">:</span> <span class="k">return</span> <span class="n">pgettext_lazy</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">message_context</span><span class="p">,</span> <span class="n">msgid</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="k">return</span> <span class="n">ugettext_lazy</span><span class="p">(</span><span class="n">msgid</span><span class="p">)</span> <span class="k">return</span> <span class="n">value</span> <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="s2">"<</span><span class="si">%s</span><span class="s2">: </span><span class="si">%r</span><span class="s2">>"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">var</span><span class="p">)</span> <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">var</span> <span class="k">def</span> <span class="nf">_resolve_lookup</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Performs resolution of a real variable (i.e. not a literal) against the</span> <span class="sd"> given context.</span> <span class="sd"> As indicated by the method's name, this method is an implementation</span> <span class="sd"> detail and shouldn't be called by external code. Use Variable.resolve()</span> <span class="sd"> instead.</span> <span class="sd"> """</span> <span class="n">current</span> <span class="o">=</span> <span class="n">context</span> <span class="k">try</span><span class="p">:</span> <span class="c1"># catch-all for silent variable failures</span> <span class="k">for</span> <span class="n">bit</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">lookups</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="c1"># dictionary lookup</span> <span class="n">current</span> <span class="o">=</span> <span class="n">current</span><span class="p">[</span><span class="n">bit</span><span class="p">]</span> <span class="c1"># ValueError/IndexError are for numpy.array lookup on</span> <span class="c1"># numpy < 1.9 and 1.9+ respectively</span> <span class="k">except</span> <span class="p">(</span><span class="ne">TypeError</span><span class="p">,</span> <span class="ne">AttributeError</span><span class="p">,</span> <span class="ne">KeyError</span><span class="p">,</span> <span class="ne">ValueError</span><span class="p">,</span> <span class="ne">IndexError</span><span class="p">):</span> <span class="k">try</span><span class="p">:</span> <span class="c1"># attribute lookup</span> <span class="c1"># Don't return class attributes if the class is the context:</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">current</span><span class="p">,</span> <span class="n">BaseContext</span><span class="p">)</span> <span class="ow">and</span> <span class="nb">getattr</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="n">current</span><span class="p">),</span> <span class="n">bit</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">AttributeError</span> <span class="n">current</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">current</span><span class="p">,</span> <span class="n">bit</span><span class="p">)</span> <span class="k">except</span> <span class="p">(</span><span class="ne">TypeError</span><span class="p">,</span> <span class="ne">AttributeError</span><span class="p">):</span> <span class="c1"># Reraise if the exception was raised by a @property</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">current</span><span class="p">,</span> <span class="n">BaseContext</span><span class="p">)</span> <span class="ow">and</span> <span class="n">bit</span> <span class="ow">in</span> <span class="nb">dir</span><span class="p">(</span><span class="n">current</span><span class="p">):</span> <span class="k">raise</span> <span class="k">try</span><span class="p">:</span> <span class="c1"># list-index lookup</span> <span class="n">current</span> <span class="o">=</span> <span class="n">current</span><span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">bit</span><span class="p">)]</span> <span class="k">except</span> <span class="p">(</span><span class="ne">IndexError</span><span class="p">,</span> <span class="c1"># list index out of range</span> <span class="ne">ValueError</span><span class="p">,</span> <span class="c1"># invalid literal for int()</span> <span class="ne">KeyError</span><span class="p">,</span> <span class="c1"># current is a dict without `int(bit)` key</span> <span class="ne">TypeError</span><span class="p">):</span> <span class="c1"># unsubscriptable object</span> <span class="k">raise</span> <span class="n">VariableDoesNotExist</span><span class="p">(</span><span class="s2">"Failed lookup for key "</span> <span class="s2">"[</span><span class="si">%s</span><span class="s2">] in </span><span class="si">%r</span><span class="s2">"</span><span class="p">,</span> <span class="p">(</span><span class="n">bit</span><span class="p">,</span> <span class="n">current</span><span class="p">))</span> <span class="c1"># missing attribute</span> <span class="k">if</span> <span class="n">callable</span><span class="p">(</span><span class="n">current</span><span class="p">):</span> <span class="k">if</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">current</span><span class="p">,</span> <span class="s1">'do_not_call_in_templates'</span><span class="p">,</span> <span class="kc">False</span><span class="p">):</span> <span class="k">pass</span> <span class="k">elif</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">current</span><span class="p">,</span> <span class="s1">'alters_data'</span><span class="p">,</span> <span class="kc">False</span><span class="p">):</span> <span class="n">current</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">string_if_invalid</span> <span class="k">else</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="c1"># method call (assuming no args required)</span> <span class="n">current</span> <span class="o">=</span> <span class="n">current</span><span class="p">()</span> <span class="k">except</span> <span class="ne">TypeError</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="n">inspect</span><span class="o">.</span><span class="n">getcallargs</span><span class="p">(</span><span class="n">current</span><span class="p">)</span> <span class="k">except</span> <span class="ne">TypeError</span><span class="p">:</span> <span class="c1"># arguments *were* required</span> <span class="n">current</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">string_if_invalid</span> <span class="c1"># invalid method call</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> <span class="n">template_name</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="s1">'template_name'</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span> <span class="ow">or</span> <span class="s1">'unknown'</span> <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span> <span class="s2">"Exception while resolving variable '</span><span class="si">%s</span><span class="s2">' in template '</span><span class="si">%s</span><span class="s2">'."</span><span class="p">,</span> <span class="n">bit</span><span class="p">,</span> <span class="n">template_name</span><span class="p">,</span> <span class="n">exc_info</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="p">)</span> <span class="k">if</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="s1">'silent_variable_failure'</span><span class="p">,</span> <span class="kc">False</span><span class="p">):</span> <span class="n">current</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">string_if_invalid</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="k">return</span> <span class="n">current</span> <span class="k">class</span> <span class="nc">Node</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="c1"># Set this to True for nodes that must be first in the template (although</span> <span class="c1"># they can be preceded by text nodes.</span> <span class="n">must_be_first</span> <span class="o">=</span> <span class="kc">False</span> <span class="n">child_nodelists</span> <span class="o">=</span> <span class="p">(</span><span class="s1">'nodelist'</span><span class="p">,)</span> <span class="n">token</span> <span class="o">=</span> <span class="kc">None</span> <span class="k">def</span> <span class="nf">render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Return the node rendered as a string.</span> <span class="sd"> """</span> <span class="k">pass</span> <span class="k">def</span> <span class="nf">render_annotated</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Render the node. If debug is True and an exception occurs during</span> <span class="sd"> rendering, the exception is annotated with contextual line information</span> <span class="sd"> where it occurred in the template. For internal usage this method is</span> <span class="sd"> preferred over using the render method directly.</span> <span class="sd"> """</span> <span class="k">try</span><span class="p">:</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="n">context</span><span class="p">)</span> <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> <span class="k">if</span> <span class="n">context</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">debug</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="s1">'template_debug'</span><span class="p">):</span> <span class="n">e</span><span class="o">.</span><span class="n">template_debug</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">render_context</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">get_exception_info</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">token</span><span class="p">)</span> <span class="k">raise</span> <span class="k">def</span> <span class="nf">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">yield</span> <span class="bp">self</span> <span class="k">def</span> <span class="nf">get_nodes_by_type</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nodetype</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Return a list of all nodes (within this node and its nodelist)</span> <span class="sd"> of the given type</span> <span class="sd"> """</span> <span class="n">nodes</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nodetype</span><span class="p">):</span> <span class="n">nodes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="k">for</span> <span class="n">attr</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">child_nodelists</span><span class="p">:</span> <span class="n">nodelist</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">attr</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span> <span class="k">if</span> <span class="n">nodelist</span><span class="p">:</span> <span class="n">nodes</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">nodelist</span><span class="o">.</span><span class="n">get_nodes_by_type</span><span class="p">(</span><span class="n">nodetype</span><span class="p">))</span> <span class="k">return</span> <span class="n">nodes</span> <span class="k">class</span> <span class="nc">NodeList</span><span class="p">(</span><span class="nb">list</span><span class="p">):</span> <span class="c1"># Set to True the first time a non-TextNode is inserted by</span> <span class="c1"># extend_nodelist().</span> <span class="n">contains_nontext</span> <span class="o">=</span> <span class="kc">False</span> <span class="k">def</span> <span class="nf">render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span> <span class="n">bits</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">:</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">Node</span><span class="p">):</span> <span class="n">bit</span> <span class="o">=</span> <span class="n">node</span><span class="o">.</span><span class="n">render_annotated</span><span class="p">(</span><span class="n">context</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">bit</span> <span class="o">=</span> <span class="n">node</span> <span class="n">bits</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">force_text</span><span class="p">(</span><span class="n">bit</span><span class="p">))</span> <span class="k">return</span> <span class="n">mark_safe</span><span class="p">(</span><span class="s1">''</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">bits</span><span class="p">))</span> <span class="k">def</span> <span class="nf">get_nodes_by_type</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nodetype</span><span class="p">):</span> <span class="s2">"Return a list of all nodes of the given type"</span> <span class="n">nodes</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">:</span> <span class="n">nodes</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">node</span><span class="o">.</span><span class="n">get_nodes_by_type</span><span class="p">(</span><span class="n">nodetype</span><span class="p">))</span> <span class="k">return</span> <span class="n">nodes</span> <span class="k">class</span> <span class="nc">TextNode</span><span class="p">(</span><span class="n">Node</span><span class="p">):</span> <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">s</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">s</span> <span class="o">=</span> <span class="n">s</span> <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">rep</span> <span class="o">=</span> <span class="s2">"<</span><span class="si">%s</span><span class="s2">: </span><span class="si">%r</span><span class="s2">>"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">s</span><span class="p">[:</span><span class="mi">25</span><span class="p">])</span> <span class="k">return</span> <span class="n">force_str</span><span class="p">(</span><span class="n">rep</span><span class="p">,</span> <span class="s1">'ascii'</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="s1">'replace'</span><span class="p">)</span> <span class="k">def</span> <span class="nf">render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">s</span> <span class="k">def</span> <span class="nf">render_value_in_context</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Converts any value to a string to become part of a rendered template. This</span> <span class="sd"> means escaping, if required, and conversion to a unicode object. If value</span> <span class="sd"> is a string, it is expected to have already been translated.</span> <span class="sd"> """</span> <span class="n">value</span> <span class="o">=</span> <span class="n">template_localtime</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">use_tz</span><span class="o">=</span><span class="n">context</span><span class="o">.</span><span class="n">use_tz</span><span class="p">)</span> <span class="n">value</span> <span class="o">=</span> <span class="n">localize</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">use_l10n</span><span class="o">=</span><span class="n">context</span><span class="o">.</span><span class="n">use_l10n</span><span class="p">)</span> <span class="n">value</span> <span class="o">=</span> <span class="n">force_text</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="k">if</span> <span class="n">context</span><span class="o">.</span><span class="n">autoescape</span> <span class="ow">or</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">EscapeData</span><span class="p">):</span> <span class="k">return</span> <span class="n">conditional_escape</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="k">return</span> <span class="n">value</span> <span class="k">class</span> <span class="nc">VariableNode</span><span class="p">(</span><span class="n">Node</span><span class="p">):</span> <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">filter_expression</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">filter_expression</span> <span class="o">=</span> <span class="n">filter_expression</span> <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="s2">"<Variable Node: </span><span class="si">%s</span><span class="s2">>"</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">filter_expression</span> <span class="k">def</span> <span class="nf">render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span> <span class="k">try</span><span class="p">:</span> <span class="n">output</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">filter_expression</span><span class="o">.</span><span class="n">resolve</span><span class="p">(</span><span class="n">context</span><span class="p">)</span> <span class="k">except</span> <span class="ne">UnicodeDecodeError</span><span class="p">:</span> <span class="c1"># Unicode conversion can fail sometimes for reasons out of our</span> <span class="c1"># control (e.g. exception rendering). In that case, we fail</span> <span class="c1"># quietly.</span> <span class="k">return</span> <span class="s1">''</span> <span class="k">return</span> <span class="n">render_value_in_context</span><span class="p">(</span><span class="n">output</span><span class="p">,</span> <span class="n">context</span><span class="p">)</span> <span class="c1"># Regex for token keyword arguments</span> <span class="n">kwarg_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="sa">r</span><span class="s2">"(?:(\w+)=)?(.+)"</span><span class="p">)</span> <span class="k">def</span> <span class="nf">token_kwargs</span><span class="p">(</span><span class="n">bits</span><span class="p">,</span> <span class="n">parser</span><span class="p">,</span> <span class="n">support_legacy</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> A utility method for parsing token keyword arguments.</span> <span class="sd"> :param bits: A list containing remainder of the token (split by spaces)</span> <span class="sd"> that is to be checked for arguments. Valid arguments will be removed</span> <span class="sd"> from this list.</span> <span class="sd"> :param support_legacy: If set to true ``True``, the legacy format</span> <span class="sd"> ``1 as foo`` will be accepted. Otherwise, only the standard ``foo=1``</span> <span class="sd"> format is allowed.</span> <span class="sd"> :returns: A dictionary of the arguments retrieved from the ``bits`` token</span> <span class="sd"> list.</span> <span class="sd"> There is no requirement for all remaining token ``bits`` to be keyword</span> <span class="sd"> arguments, so the dictionary will be returned as soon as an invalid</span> <span class="sd"> argument format is reached.</span> <span class="sd"> """</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">bits</span><span class="p">:</span> <span class="k">return</span> <span class="p">{}</span> <span class="n">match</span> <span class="o">=</span> <span class="n">kwarg_re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">bits</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="n">kwarg_format</span> <span class="o">=</span> <span class="n">match</span> <span class="ow">and</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="k">if</span> <span class="ow">not</span> <span class="n">kwarg_format</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">support_legacy</span><span class="p">:</span> <span class="k">return</span> <span class="p">{}</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">bits</span><span class="p">)</span> <span class="o"><</span> <span class="mi">3</span> <span class="ow">or</span> <span class="n">bits</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">'as'</span><span class="p">:</span> <span class="k">return</span> <span class="p">{}</span> <span class="n">kwargs</span> <span class="o">=</span> <span class="p">{}</span> <span class="k">while</span> <span class="n">bits</span><span class="p">:</span> <span class="k">if</span> <span class="n">kwarg_format</span><span class="p">:</span> <span class="n">match</span> <span class="o">=</span> <span class="n">kwarg_re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">bits</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">match</span> <span class="ow">or</span> <span class="ow">not</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="k">return</span> <span class="n">kwargs</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">groups</span><span class="p">()</span> <span class="k">del</span> <span class="n">bits</span><span class="p">[:</span><span class="mi">1</span><span class="p">]</span> <span class="k">else</span><span class="p">:</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">bits</span><span class="p">)</span> <span class="o"><</span> <span class="mi">3</span> <span class="ow">or</span> <span class="n">bits</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">'as'</span><span class="p">:</span> <span class="k">return</span> <span class="n">kwargs</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="o">=</span> <span class="n">bits</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">bits</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">del</span> <span class="n">bits</span><span class="p">[:</span><span class="mi">3</span><span class="p">]</span> <span class="n">kwargs</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">compile_filter</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="k">if</span> <span class="n">bits</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">kwarg_format</span><span class="p">:</span> <span class="k">if</span> <span class="n">bits</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">'and'</span><span class="p">:</span> <span class="k">return</span> <span class="n">kwargs</span> <span class="k">del</span> <span class="n">bits</span><span class="p">[:</span><span class="mi">1</span><span class="p">]</span> <span class="k">return</span> <span class="n">kwargs</span> </pre></div> </div> </div> </div> <div class="yui-b" id="sidebar"> <div class="sphinxsidebar" role="navigation" aria-label="main navigation"> <div class="sphinxsidebarwrapper"> <div id="searchbox" style="display: none" role="search"> <h3>Quick search</h3> <div class="searchformwrapper"> <form class="search" action="../../../search.html" method="get"> <input type="text" name="q" /> <input type="submit" value="Go" /> <input type="hidden" name="check_keywords" value="yes" /> <input type="hidden" name="area" value="default" /> </form> </div> </div> <script type="text/javascript">$('#searchbox').show(0);</script> </div> </div> <h3>Last update:</h3> <p class="topless">Feb 11, 2019</p> </div> </div> <div id="ft"> <div class="nav"> <a href="../../index.html" title="Module code" accesskey="U">up</a></div> </div> </div> <div class="clearer"></div> </div> </body> </html>