<!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="Content-Type" content="text/html; charset=utf-8" /> <title>django.template.base — Django 1.8.19 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"> var DOCUMENTATION_OPTIONS = { URL_ROOT: '../../../', VERSION: '1.8.19', COLLAPSE_INDEX: false, FILE_SUFFIX: '.html', HAS_SOURCE: true }; </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> <link rel="index" title="Index" href="../../../genindex.html" /> <link rel="search" title="Search" href="../../../search.html" /> <link rel="top" title="Django 1.8.19 documentation" href="../../../contents.html" /> <link rel="up" title="django" href="../../django.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 role="document"> <div class="document"> <div id="custom-doc" class="yui-t6"> <div id="hd"> <h1><a href="../../../index.html">Django 1.8.19 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 = u'<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">u'<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">u'<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">re</span> <span class="kn">import</span> <span class="nn">warnings</span> <span class="kn">from</span> <span class="nn">functools</span> <span class="k">import</span> <span class="n">partial</span> <span class="kn">from</span> <span class="nn">importlib</span> <span class="k">import</span> <span class="n">import_module</span> <span class="kn">from</span> <span class="nn">django.apps</span> <span class="k">import</span> <span class="n">apps</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">lru_cache</span><span class="p">,</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="n">RemovedInDjango110Warning</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="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.itercompat</span> <span class="k">import</span> <span class="n">is_iterable</span> <span class="kn">from</span> <span class="nn">django.utils.module_loading</span> <span class="k">import</span> <span class="n">module_has_submodule</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="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="n">ALLOWED_VARIABLE_CHARS</span> <span class="o">=</span> <span class="p">(</span><span class="s1">'abcdefghijklmnopqrstuvwxyz'</span> <span class="s1">'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.'</span><span class="p">)</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="c1"># global dictionary of libraries that have been loaded using get_library</span> <span class="n">libraries</span> <span class="o">=</span> <span class="p">{}</span> <span class="c1"># global list of libraries to load by default for a new parser</span> <span class="n">builtins</span> <span class="o">=</span> <span class="p">[]</span> <div class="viewcode-block" id="TemplateSyntaxError"><a class="viewcode-back" href="../../../topics/templates.html#django.template.TemplateSyntaxError">[docs]</a><span class="k">class</span> <span class="nc">TemplateSyntaxError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span> <span class="k">pass</span></div> <div class="viewcode-block" id="TemplateDoesNotExist"><a class="viewcode-back" href="../../../topics/templates.html#django.template.TemplateDoesNotExist">[docs]</a><span class="k">class</span> <span class="nc">TemplateDoesNotExist</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span> <span class="k">pass</span></div> <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> <span class="k">class</span> <span class="nc">InvalidTemplateLibrary</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span> <span class="k">pass</span> <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="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span> <span class="k">def</span> <span class="nf">reload</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s1">'subclasses of Origin must provide a reload() method'</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">name</span> <div class="viewcode-block" id="StringOrigin"><a class="viewcode-back" href="../../../ref/templates/api.html#django.template.StringOrigin">[docs]</a><span class="k">class</span> <span class="nc">StringOrigin</span><span class="p">(</span><span class="n">Origin</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">source</span><span class="p">):</span> <span class="nb">super</span><span class="p">(</span><span class="n">StringOrigin</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</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">source</span> <span class="o">=</span> <span class="n">source</span> <span class="k">def</span> <span class="nf">reload</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">source</span></div> <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">engine</span><span class="o">.</span><span class="n">debug</span> <span class="ow">and</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">StringOrigin</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">nodelist</span> <span class="o">=</span> <span class="n">engine</span><span class="o">.</span><span class="n">compile_string</span><span class="p">(</span><span class="n">template_string</span><span class="p">,</span> <span class="n">origin</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="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="n">context</span><span class="o">.</span><span class="n">render_context</span><span class="o">.</span><span class="n">push</span><span class="p">()</span> <span class="k">try</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="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> <span class="k">finally</span><span class="p">:</span> <span class="n">context</span><span class="o">.</span><span class="n">render_context</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span></div></div> <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="c1"># token_type must be TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK or</span> <span class="c1"># TOKEN_COMMENT.</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="kc">None</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="ow">or</span> <span class="n">bit</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"_('"</span><span class="p">):</span> <span class="n">sentinal</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">sentinal</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="n">origin</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">origin</span> <span class="o">=</span> <span class="n">origin</span> <span class="bp">self</span><span class="o">.</span><span class="n">lineno</span> <span class="o">=</span> <span class="mi">1</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">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="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="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">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="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="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="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">token</span><span class="o">.</span><span class="n">lineno</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">lineno</span> <span class="bp">self</span><span class="o">.</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="k">return</span> <span class="n">token</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="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="k">for</span> <span class="n">lib</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">lib</span><span class="p">)</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="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="bp">self</span><span class="o">.</span><span class="n">create_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="bp">self</span><span class="o">.</span><span class="n">empty_variable</span><span class="p">(</span><span class="n">token</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">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">compile_filter_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="k">raise</span> <span class="n">var_node</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">create_variable_node</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="bp">self</span><span class="o">.</span><span class="n">empty_block_tag</span><span class="p">(</span><span class="n">token</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"># put token back on token list so calling</span> <span class="c1"># code knows why 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"># execute callback function for this tag and append</span> <span class="c1"># resulting node</span> <span class="bp">self</span><span class="o">.</span><span class="n">enter_command</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="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="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="n">TemplateSyntaxError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">compile_function_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="k">raise</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="bp">self</span><span class="o">.</span><span class="n">exit_command</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">create_variable_node</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="k">return</span> <span class="n">VariableNode</span><span class="p">(</span><span class="n">filter_expression</span><span class="p">)</span> <span class="k">def</span> <span class="nf">create_nodelist</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="n">NodeList</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="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="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="k">if</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="ne">AttributeError</span> <span class="k">except</span> <span class="ne">AttributeError</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">%r</span><span class="s2"> must be the first tag "</span> <span class="s2">"in the template."</span> <span class="o">%</span> <span class="n">node</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="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">enter_command</span><span class="p">(</span><span class="bp">self</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="k">pass</span> <span class="k">def</span> <span class="nf">exit_command</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">pass</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">msg</span><span class="p">):</span> <span class="k">return</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> <span class="k">def</span> <span class="nf">empty_variable</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">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">"Empty variable tag"</span><span class="p">)</span> <span class="k">def</span> <span class="nf">empty_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="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">"Empty block tag"</span><span class="p">)</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: '</span><span class="si">%s</span><span class="s2">', expected </span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</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="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: '</span><span class="si">%s</span><span class="s2">'"</span> <span class="o">%</span> <span class="n">command</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="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="s2">"Unclosed tags: </span><span class="si">%s</span><span class="s2"> "</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">parse_until</span><span class="p">))</span> <span class="k">def</span> <span class="nf">compile_filter_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="k">pass</span> <span class="k">def</span> <span class="nf">compile_function_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="k">pass</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="k">class</span> <span class="nc">TokenParser</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Subclass this and implement the top() method to parse a template line.</span> <span class="sd"> When instantiating the parser, pass in the line from the Django template</span> <span class="sd"> parser.</span> <span class="sd"> The parser's "tagname" instance-variable stores the name of the tag that</span> <span class="sd"> the filter was called with.</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">subject</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">subject</span> <span class="o">=</span> <span class="n">subject</span> <span class="bp">self</span><span class="o">.</span><span class="n">pointer</span> <span class="o">=</span> <span class="mi">0</span> <span class="bp">self</span><span class="o">.</span><span class="n">backout</span> <span class="o">=</span> <span class="p">[]</span> <span class="bp">self</span><span class="o">.</span><span class="n">tagname</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">tag</span><span class="p">()</span> <span class="k">def</span> <span class="nf">top</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Overload this method to do the actual parsing and return the result.</span> <span class="sd"> """</span> <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s1">'subclasses of Tokenparser must provide a top() method'</span><span class="p">)</span> <span class="k">def</span> <span class="nf">more</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Returns True if there is more stuff in the tag.</span> <span class="sd"> """</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">pointer</span> <span class="o"><</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">subject</span><span class="p">)</span> <span class="k">def</span> <span class="nf">back</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Undoes the last microparser. Use this for lookahead and backtracking.</span> <span class="sd"> """</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">backout</span><span class="p">):</span> <span class="k">raise</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="s2">"back called without some previous "</span> <span class="s2">"parsing"</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">pointer</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">backout</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span> <span class="k">def</span> <span class="nf">tag</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> A microparser that just returns the next tag from the line.</span> <span class="sd"> """</span> <span class="n">subject</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">subject</span> <span class="n">i</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">pointer</span> <span class="k">if</span> <span class="n">i</span> <span class="o">>=</span> <span class="nb">len</span><span class="p">(</span><span class="n">subject</span><span class="p">):</span> <span class="k">raise</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="s2">"expected another tag, found "</span> <span class="s2">"end of string: </span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="n">subject</span><span class="p">)</span> <span class="n">p</span> <span class="o">=</span> <span class="n">i</span> <span class="k">while</span> <span class="n">i</span> <span class="o"><</span> <span class="nb">len</span><span class="p">(</span><span class="n">subject</span><span class="p">)</span> <span class="ow">and</span> <span class="n">subject</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">' '</span><span class="p">,</span> <span class="s1">'</span><span class="se">\t</span><span class="s1">'</span><span class="p">):</span> <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span> <span class="n">s</span> <span class="o">=</span> <span class="n">subject</span><span class="p">[</span><span class="n">p</span><span class="p">:</span><span class="n">i</span><span class="p">]</span> <span class="k">while</span> <span class="n">i</span> <span class="o"><</span> <span class="nb">len</span><span class="p">(</span><span class="n">subject</span><span class="p">)</span> <span class="ow">and</span> <span class="n">subject</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">' '</span><span class="p">,</span> <span class="s1">'</span><span class="se">\t</span><span class="s1">'</span><span class="p">):</span> <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span> <span class="bp">self</span><span class="o">.</span><span class="n">backout</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">pointer</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">pointer</span> <span class="o">=</span> <span class="n">i</span> <span class="k">return</span> <span class="n">s</span> <span class="k">def</span> <span class="nf">value</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> A microparser that parses for a value: some string constant or</span> <span class="sd"> variable name.</span> <span class="sd"> """</span> <span class="n">subject</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">subject</span> <span class="n">i</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">pointer</span> <span class="k">def</span> <span class="nf">next_space_index</span><span class="p">(</span><span class="n">subject</span><span class="p">,</span> <span class="n">i</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Increment pointer until a real space (i.e. a space not within</span> <span class="sd"> quotes) is encountered</span> <span class="sd"> """</span> <span class="k">while</span> <span class="n">i</span> <span class="o"><</span> <span class="nb">len</span><span class="p">(</span><span class="n">subject</span><span class="p">)</span> <span class="ow">and</span> <span class="n">subject</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">' '</span><span class="p">,</span> <span class="s1">'</span><span class="se">\t</span><span class="s1">'</span><span class="p">):</span> <span class="k">if</span> <span class="n">subject</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">'"'</span><span class="p">,</span> <span class="s2">"'"</span><span class="p">):</span> <span class="n">c</span> <span class="o">=</span> <span class="n">subject</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">while</span> <span class="n">i</span> <span class="o"><</span> <span class="nb">len</span><span class="p">(</span><span class="n">subject</span><span class="p">)</span> <span class="ow">and</span> <span class="n">subject</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">c</span><span class="p">:</span> <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">i</span> <span class="o">>=</span> <span class="nb">len</span><span class="p">(</span><span class="n">subject</span><span class="p">):</span> <span class="k">raise</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="s2">"Searching for value. "</span> <span class="s2">"Unexpected end of string in column </span><span class="si">%d</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">i</span><span class="p">,</span> <span class="n">subject</span><span class="p">))</span> <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">return</span> <span class="n">i</span> <span class="k">if</span> <span class="n">i</span> <span class="o">>=</span> <span class="nb">len</span><span class="p">(</span><span class="n">subject</span><span class="p">):</span> <span class="k">raise</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="s2">"Searching for value. Expected another "</span> <span class="s2">"value but found end of string: </span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="n">subject</span><span class="p">)</span> <span class="k">if</span> <span class="n">subject</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">'"'</span><span class="p">,</span> <span class="s2">"'"</span><span class="p">):</span> <span class="n">p</span> <span class="o">=</span> <span class="n">i</span> <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">while</span> <span class="n">i</span> <span class="o"><</span> <span class="nb">len</span><span class="p">(</span><span class="n">subject</span><span class="p">)</span> <span class="ow">and</span> <span class="n">subject</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">subject</span><span class="p">[</span><span class="n">p</span><span class="p">]:</span> <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">i</span> <span class="o">>=</span> <span class="nb">len</span><span class="p">(</span><span class="n">subject</span><span class="p">):</span> <span class="k">raise</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="s2">"Searching for value. Unexpected "</span> <span class="s2">"end of string in column </span><span class="si">%d</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">i</span><span class="p">,</span> <span class="n">subject</span><span class="p">))</span> <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span> <span class="c1"># Continue parsing until next "real" space,</span> <span class="c1"># so that filters are also included</span> <span class="n">i</span> <span class="o">=</span> <span class="n">next_space_index</span><span class="p">(</span><span class="n">subject</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span> <span class="n">res</span> <span class="o">=</span> <span class="n">subject</span><span class="p">[</span><span class="n">p</span><span class="p">:</span><span class="n">i</span><span class="p">]</span> <span class="k">while</span> <span class="n">i</span> <span class="o"><</span> <span class="nb">len</span><span class="p">(</span><span class="n">subject</span><span class="p">)</span> <span class="ow">and</span> <span class="n">subject</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">' '</span><span class="p">,</span> <span class="s1">'</span><span class="se">\t</span><span class="s1">'</span><span class="p">):</span> <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span> <span class="bp">self</span><span class="o">.</span><span class="n">backout</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">pointer</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">pointer</span> <span class="o">=</span> <span class="n">i</span> <span class="k">return</span> <span class="n">res</span> <span class="k">else</span><span class="p">:</span> <span class="n">p</span> <span class="o">=</span> <span class="n">i</span> <span class="n">i</span> <span class="o">=</span> <span class="n">next_space_index</span><span class="p">(</span><span class="n">subject</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span> <span class="n">s</span> <span class="o">=</span> <span class="n">subject</span><span class="p">[</span><span class="n">p</span><span class="p">:</span><span class="n">i</span><span class="p">]</span> <span class="k">while</span> <span class="n">i</span> <span class="o"><</span> <span class="nb">len</span><span class="p">(</span><span class="n">subject</span><span class="p">)</span> <span class="ow">and</span> <span class="n">subject</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">' '</span><span class="p">,</span> <span class="s1">'</span><span class="se">\t</span><span class="s1">'</span><span class="p">):</span> <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span> <span class="bp">self</span><span class="o">.</span><span class="n">backout</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">pointer</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">pointer</span> <span class="o">=</span> <span class="n">i</span> <span class="k">return</span> <span class="n">s</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="s2">r"""</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="s1">r'"[^"</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="s2">r"'[^'</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="s2">r"""</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="s1">r'[-+\.]?\d[\d\.e]*'</span><span class="p">,</span> <span class="s1">'var_chars'</span><span class="p">:</span> <span class="s2">"\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="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="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="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">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">def</span> <span class="nf">resolve_variable</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Returns the resolved variable, which may contain attribute syntax, within</span> <span class="sd"> the given context.</span> <span class="sd"> Deprecated; use the Variable class instead.</span> <span class="sd"> """</span> <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s2">"resolve_variable() is deprecated. Use django.template."</span> <span class="s2">"Variable(path).resolve(context) instead"</span><span class="p">,</span> <span class="n">RemovedInDjango110Warning</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">Variable</span><span class="p">(</span><span class="n">path</span><span class="p">)</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">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':u'News'}}</span> <span class="sd"> >>> Variable('article.section').resolve(c)</span> <span class="sd"> u'News'</span> <span class="sd"> >>> Variable('article').resolve(c)</span> <span class="sd"> {'section': u'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 = u'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="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">value</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">value</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="n">__class__</span><span class="o">.</span><span class="n">__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="k">as</span> <span class="n">e</span><span class="p">:</span> <span class="c1"># Reraise an AttributeError raised by a @property</span> <span class="k">if</span> <span class="p">(</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="ne">AttributeError</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">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="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="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">__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="bp">self</span><span class="o">.</span><span class="n">render_node</span><span class="p">(</span><span class="n">node</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">def</span> <span class="nf">render_node</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">node</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span> <span class="k">return</span> <span class="n">node</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">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="k">return</span> <span class="n">force_str</span><span class="p">(</span><span class="s2">"<Text 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">s</span><span class="p">[:</span><span class="mi">25</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="p">((</span><span class="n">context</span><span class="o">.</span><span class="n">autoescape</span> <span class="ow">and</span> <span class="ow">not</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="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="s2">r"(?:(\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> <span class="k">def</span> <span class="nf">parse_bits</span><span class="p">(</span><span class="n">parser</span><span class="p">,</span> <span class="n">bits</span><span class="p">,</span> <span class="n">params</span><span class="p">,</span> <span class="n">varargs</span><span class="p">,</span> <span class="n">varkw</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">takes_context</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Parses bits for template tag helpers (simple_tag, include_tag and</span> <span class="sd"> assignment_tag), in particular by detecting syntax errors and by</span> <span class="sd"> extracting positional and keyword arguments.</span> <span class="sd"> """</span> <span class="k">if</span> <span class="n">takes_context</span><span class="p">:</span> <span class="k">if</span> <span class="n">params</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'context'</span><span class="p">:</span> <span class="n">params</span> <span class="o">=</span> <span class="n">params</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">raise</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span> <span class="s2">"'</span><span class="si">%s</span><span class="s2">' is decorated with takes_context=True so it must "</span> <span class="s2">"have a first argument of 'context'"</span> <span class="o">%</span> <span class="n">name</span><span class="p">)</span> <span class="n">args</span> <span class="o">=</span> <span class="p">[]</span> <span class="n">kwargs</span> <span class="o">=</span> <span class="p">{}</span> <span class="n">unhandled_params</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">params</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"># First we try to extract a potential kwarg from the bit</span> <span class="n">kwarg</span> <span class="o">=</span> <span class="n">token_kwargs</span><span class="p">([</span><span class="n">bit</span><span class="p">],</span> <span class="n">parser</span><span class="p">)</span> <span class="k">if</span> <span class="n">kwarg</span><span class="p">:</span> <span class="c1"># The kwarg was successfully extracted</span> <span class="n">param</span><span class="p">,</span> <span class="n">value</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">six</span><span class="o">.</span><span class="n">iteritems</span><span class="p">(</span><span class="n">kwarg</span><span class="p">))[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="n">param</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">params</span> <span class="ow">and</span> <span class="n">varkw</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span> <span class="c1"># An unexpected keyword argument was supplied</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">' received unexpected keyword argument '</span><span class="si">%s</span><span class="s2">'"</span> <span class="o">%</span> <span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">param</span><span class="p">))</span> <span class="k">elif</span> <span class="n">param</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="p">:</span> <span class="c1"># The keyword argument has already been supplied once</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">' received multiple values for keyword argument '</span><span class="si">%s</span><span class="s2">'"</span> <span class="o">%</span> <span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">param</span><span class="p">))</span> <span class="k">else</span><span class="p">:</span> <span class="c1"># All good, record the keyword argument</span> <span class="n">kwargs</span><span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">param</span><span class="p">)]</span> <span class="o">=</span> <span class="n">value</span> <span class="k">if</span> <span class="n">param</span> <span class="ow">in</span> <span class="n">unhandled_params</span><span class="p">:</span> <span class="c1"># If using the keyword syntax for a positional arg, then</span> <span class="c1"># consume it.</span> <span class="n">unhandled_params</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">param</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="k">if</span> <span class="n">kwargs</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">' received some positional argument(s) after some "</span> <span class="s2">"keyword argument(s)"</span> <span class="o">%</span> <span class="n">name</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="c1"># Record the positional argument</span> <span class="n">args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">parser</span><span class="o">.</span><span class="n">compile_filter</span><span class="p">(</span><span class="n">bit</span><span class="p">))</span> <span class="k">try</span><span class="p">:</span> <span class="c1"># Consume from the list of expected positional arguments</span> <span class="n">unhandled_params</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">except</span> <span class="ne">IndexError</span><span class="p">:</span> <span class="k">if</span> <span class="n">varargs</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">"'</span><span class="si">%s</span><span class="s2">' received too many positional arguments"</span> <span class="o">%</span> <span class="n">name</span><span class="p">)</span> <span class="k">if</span> <span class="n">defaults</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span> <span class="c1"># Consider the last n params handled, where n is the</span> <span class="c1"># number of defaults.</span> <span class="n">unhandled_params</span> <span class="o">=</span> <span class="n">unhandled_params</span><span class="p">[:</span><span class="o">-</span><span class="nb">len</span><span class="p">(</span><span class="n">defaults</span><span class="p">)]</span> <span class="k">if</span> <span class="n">unhandled_params</span><span class="p">:</span> <span class="c1"># Some positional arguments were not supplied</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">' did not receive value(s) for the argument(s): </span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="s2">", "</span><span class="o">.</span><span class="n">join</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">unhandled_params</span><span class="p">)))</span> <span class="k">return</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span> <span class="k">def</span> <span class="nf">generic_tag_compiler</span><span class="p">(</span><span class="n">parser</span><span class="p">,</span> <span class="n">token</span><span class="p">,</span> <span class="n">params</span><span class="p">,</span> <span class="n">varargs</span><span class="p">,</span> <span class="n">varkw</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">takes_context</span><span class="p">,</span> <span class="n">node_class</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Returns a template.Node subclass.</span> <span class="sd"> """</span> <span class="n">bits</span> <span class="o">=</span> <span class="n">token</span><span class="o">.</span><span class="n">split_contents</span><span class="p">()[</span><span class="mi">1</span><span class="p">:]</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span> <span class="o">=</span> <span class="n">parse_bits</span><span class="p">(</span><span class="n">parser</span><span class="p">,</span> <span class="n">bits</span><span class="p">,</span> <span class="n">params</span><span class="p">,</span> <span class="n">varargs</span><span class="p">,</span> <span class="n">varkw</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">takes_context</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span> <span class="k">return</span> <span class="n">node_class</span><span class="p">(</span><span class="n">takes_context</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">)</span> <span class="k">class</span> <span class="nc">TagHelperNode</span><span class="p">(</span><span class="n">Node</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Base class for tag helper nodes such as SimpleNode, InclusionNode and</span> <span class="sd"> AssignmentNode. Manages the positional and keyword arguments to be passed</span> <span class="sd"> to the decorated function.</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">takes_context</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">takes_context</span> <span class="o">=</span> <span class="n">takes_context</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span> <span class="o">=</span> <span class="n">args</span> <span class="bp">self</span><span class="o">.</span><span class="n">kwargs</span> <span class="o">=</span> <span class="n">kwargs</span> <span class="k">def</span> <span class="nf">get_resolved_arguments</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">resolved_args</span> <span class="o">=</span> <span class="p">[</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">for</span> <span class="n">var</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">]</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">takes_context</span><span class="p">:</span> <span class="n">resolved_args</span> <span class="o">=</span> <span class="p">[</span><span class="n">context</span><span class="p">]</span> <span class="o">+</span> <span class="n">resolved_args</span> <span class="n">resolved_kwargs</span> <span class="o">=</span> <span class="p">{</span><span class="n">k</span><span class="p">:</span> <span class="n">v</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">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">kwargs</span><span class="o">.</span><span class="n">items</span><span class="p">()}</span> <span class="k">return</span> <span class="n">resolved_args</span><span class="p">,</span> <span class="n">resolved_kwargs</span> <span class="k">class</span> <span class="nc">Library</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="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">tags</span> <span class="o">=</span> <span class="p">{}</span> <span class="k">def</span> <span class="nf">tag</span><span class="p">(</span><span class="bp">self</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">compile_function</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> <span class="k">if</span> <span class="n">name</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">compile_function</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span> <span class="c1"># @register.tag()</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">tag_function</span> <span class="k">elif</span> <span class="n">name</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">compile_function</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span> <span class="k">if</span> <span class="n">callable</span><span class="p">(</span><span class="n">name</span><span class="p">):</span> <span class="c1"># @register.tag</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">tag_function</span><span class="p">(</span><span class="n">name</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="c1"># @register.tag('somename') or @register.tag(name='somename')</span> <span class="k">def</span> <span class="nf">dec</span><span class="p">(</span><span class="n">func</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">tag</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="k">return</span> <span class="n">dec</span> <span class="k">elif</span> <span class="n">name</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">compile_function</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span> <span class="c1"># register.tag('somename', somefunc)</span> <span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">compile_function</span> <span class="k">return</span> <span class="n">compile_function</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="n">InvalidTemplateLibrary</span><span class="p">(</span><span class="s2">"Unsupported arguments to "</span> <span class="s2">"Library.tag: (</span><span class="si">%r</span><span class="s2">, </span><span class="si">%r</span><span class="s2">)"</span><span class="p">,</span> <span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">compile_function</span><span class="p">))</span> <span class="k">def</span> <span class="nf">tag_function</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">func</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="p">[</span><span class="nb">getattr</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="s2">"_decorated_function"</span><span class="p">,</span> <span class="n">func</span><span class="p">)</span><span class="o">.</span><span class="n">__name__</span><span class="p">]</span> <span class="o">=</span> <span class="n">func</span> <span class="k">return</span> <span class="n">func</span> <span class="k">def</span> <span class="nf">filter</span><span class="p">(</span><span class="bp">self</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">filter_func</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">**</span><span class="n">flags</span><span class="p">):</span> <span class="k">if</span> <span class="n">name</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">filter_func</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span> <span class="c1"># @register.filter()</span> <span class="k">def</span> <span class="nf">dec</span><span class="p">(</span><span class="n">func</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">filter_function</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="o">**</span><span class="n">flags</span><span class="p">)</span> <span class="k">return</span> <span class="n">dec</span> <span class="k">elif</span> <span class="n">name</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">filter_func</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span> <span class="k">if</span> <span class="n">callable</span><span class="p">(</span><span class="n">name</span><span class="p">):</span> <span class="c1"># @register.filter</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">filter_function</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="o">**</span><span class="n">flags</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="c1"># @register.filter('somename') or @register.filter(name='somename')</span> <span class="k">def</span> <span class="nf">dec</span><span class="p">(</span><span class="n">func</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">filter</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="o">**</span><span class="n">flags</span><span class="p">)</span> <span class="k">return</span> <span class="n">dec</span> <span class="k">elif</span> <span class="n">name</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">filter_func</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span> <span class="c1"># register.filter('somename', somefunc)</span> <span class="bp">self</span><span class="o">.</span><span class="n">filters</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">filter_func</span> <span class="k">for</span> <span class="n">attr</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">'expects_localtime'</span><span class="p">,</span> <span class="s1">'is_safe'</span><span class="p">,</span> <span class="s1">'needs_autoescape'</span><span class="p">):</span> <span class="k">if</span> <span class="n">attr</span> <span class="ow">in</span> <span class="n">flags</span><span class="p">:</span> <span class="n">value</span> <span class="o">=</span> <span class="n">flags</span><span class="p">[</span><span class="n">attr</span><span class="p">]</span> <span class="c1"># set the flag on the filter for FilterExpression.resolve</span> <span class="nb">setattr</span><span class="p">(</span><span class="n">filter_func</span><span class="p">,</span> <span class="n">attr</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span> <span class="c1"># set the flag on the innermost decorated function</span> <span class="c1"># for decorators that need it e.g. stringfilter</span> <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">filter_func</span><span class="p">,</span> <span class="s2">"_decorated_function"</span><span class="p">):</span> <span class="nb">setattr</span><span class="p">(</span><span class="n">filter_func</span><span class="o">.</span><span class="n">_decorated_function</span><span class="p">,</span> <span class="n">attr</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span> <span class="n">filter_func</span><span class="o">.</span><span class="n">_filter_name</span> <span class="o">=</span> <span class="n">name</span> <span class="k">return</span> <span class="n">filter_func</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="n">InvalidTemplateLibrary</span><span class="p">(</span><span class="s2">"Unsupported arguments to "</span> <span class="s2">"Library.filter: (</span><span class="si">%r</span><span class="s2">, </span><span class="si">%r</span><span class="s2">)"</span><span class="p">,</span> <span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">filter_func</span><span class="p">))</span> <span class="k">def</span> <span class="nf">filter_function</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">func</span><span class="p">,</span> <span class="o">**</span><span class="n">flags</span><span class="p">):</span> <span class="n">name</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="s2">"_decorated_function"</span><span class="p">,</span> <span class="n">func</span><span class="p">)</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">filter</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="o">**</span><span class="n">flags</span><span class="p">)</span> <span class="k">def</span> <span class="nf">simple_tag</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">func</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">takes_context</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="k">def</span> <span class="nf">dec</span><span class="p">(</span><span class="n">func</span><span class="p">):</span> <span class="n">params</span><span class="p">,</span> <span class="n">varargs</span><span class="p">,</span> <span class="n">varkw</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="k">class</span> <span class="nc">SimpleNode</span><span class="p">(</span><span class="n">TagHelperNode</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="n">resolved_args</span><span class="p">,</span> <span class="n">resolved_kwargs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resolved_arguments</span><span class="p">(</span><span class="n">context</span><span class="p">)</span> <span class="k">return</span> <span class="n">func</span><span class="p">(</span><span class="o">*</span><span class="n">resolved_args</span><span class="p">,</span> <span class="o">**</span><span class="n">resolved_kwargs</span><span class="p">)</span> <span class="n">function_name</span> <span class="o">=</span> <span class="p">(</span><span class="n">name</span> <span class="ow">or</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="o">.</span><span class="n">__name__</span><span class="p">)</span> <span class="n">compile_func</span> <span class="o">=</span> <span class="n">partial</span><span class="p">(</span><span class="n">generic_tag_compiler</span><span class="p">,</span> <span class="n">params</span><span class="o">=</span><span class="n">params</span><span class="p">,</span> <span class="n">varargs</span><span class="o">=</span><span class="n">varargs</span><span class="p">,</span> <span class="n">varkw</span><span class="o">=</span><span class="n">varkw</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="n">defaults</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">function_name</span><span class="p">,</span> <span class="n">takes_context</span><span class="o">=</span><span class="n">takes_context</span><span class="p">,</span> <span class="n">node_class</span><span class="o">=</span><span class="n">SimpleNode</span><span class="p">)</span> <span class="n">compile_func</span><span class="o">.</span><span class="n">__doc__</span> <span class="o">=</span> <span class="n">func</span><span class="o">.</span><span class="n">__doc__</span> <span class="bp">self</span><span class="o">.</span><span class="n">tag</span><span class="p">(</span><span class="n">function_name</span><span class="p">,</span> <span class="n">compile_func</span><span class="p">)</span> <span class="k">return</span> <span class="n">func</span> <span class="k">if</span> <span class="n">func</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span> <span class="c1"># @register.simple_tag(...)</span> <span class="k">return</span> <span class="n">dec</span> <span class="k">elif</span> <span class="n">callable</span><span class="p">(</span><span class="n">func</span><span class="p">):</span> <span class="c1"># @register.simple_tag</span> <span class="k">return</span> <span class="n">dec</span><span class="p">(</span><span class="n">func</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 arguments provided to simple_tag"</span><span class="p">)</span> <span class="k">def</span> <span class="nf">assignment_tag</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">func</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">takes_context</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="k">def</span> <span class="nf">dec</span><span class="p">(</span><span class="n">func</span><span class="p">):</span> <span class="n">params</span><span class="p">,</span> <span class="n">varargs</span><span class="p">,</span> <span class="n">varkw</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="k">class</span> <span class="nc">AssignmentNode</span><span class="p">(</span><span class="n">TagHelperNode</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">takes_context</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">,</span> <span class="n">target_var</span><span class="p">):</span> <span class="nb">super</span><span class="p">(</span><span class="n">AssignmentNode</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">takes_context</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">target_var</span> <span class="o">=</span> <span class="n">target_var</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">resolved_args</span><span class="p">,</span> <span class="n">resolved_kwargs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resolved_arguments</span><span class="p">(</span><span class="n">context</span><span class="p">)</span> <span class="n">context</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">target_var</span><span class="p">]</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="o">*</span><span class="n">resolved_args</span><span class="p">,</span> <span class="o">**</span><span class="n">resolved_kwargs</span><span class="p">)</span> <span class="k">return</span> <span class="s1">''</span> <span class="n">function_name</span> <span class="o">=</span> <span class="p">(</span><span class="n">name</span> <span class="ow">or</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="o">.</span><span class="n">__name__</span><span class="p">)</span> <span class="k">def</span> <span class="nf">compile_func</span><span class="p">(</span><span class="n">parser</span><span class="p">,</span> <span class="n">token</span><span class="p">):</span> <span class="n">bits</span> <span class="o">=</span> <span class="n">token</span><span class="o">.</span><span class="n">split_contents</span><span class="p">()[</span><span class="mi">1</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">2</span> <span class="ow">or</span> <span class="n">bits</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">'as'</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">' tag takes at least 2 arguments and the "</span> <span class="s2">"second last argument must be 'as'"</span> <span class="o">%</span> <span class="n">function_name</span><span class="p">)</span> <span class="n">target_var</span> <span class="o">=</span> <span class="n">bits</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="n">bits</span> <span class="o">=</span> <span class="n">bits</span><span class="p">[:</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span> <span class="o">=</span> <span class="n">parse_bits</span><span class="p">(</span><span class="n">parser</span><span class="p">,</span> <span class="n">bits</span><span class="p">,</span> <span class="n">params</span><span class="p">,</span> <span class="n">varargs</span><span class="p">,</span> <span class="n">varkw</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">takes_context</span><span class="p">,</span> <span class="n">function_name</span><span class="p">)</span> <span class="k">return</span> <span class="n">AssignmentNode</span><span class="p">(</span><span class="n">takes_context</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">,</span> <span class="n">target_var</span><span class="p">)</span> <span class="n">compile_func</span><span class="o">.</span><span class="n">__doc__</span> <span class="o">=</span> <span class="n">func</span><span class="o">.</span><span class="n">__doc__</span> <span class="bp">self</span><span class="o">.</span><span class="n">tag</span><span class="p">(</span><span class="n">function_name</span><span class="p">,</span> <span class="n">compile_func</span><span class="p">)</span> <span class="k">return</span> <span class="n">func</span> <span class="k">if</span> <span class="n">func</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span> <span class="c1"># @register.assignment_tag(...)</span> <span class="k">return</span> <span class="n">dec</span> <span class="k">elif</span> <span class="n">callable</span><span class="p">(</span><span class="n">func</span><span class="p">):</span> <span class="c1"># @register.assignment_tag</span> <span class="k">return</span> <span class="n">dec</span><span class="p">(</span><span class="n">func</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 arguments provided to assignment_tag"</span><span class="p">)</span> <span class="k">def</span> <span class="nf">inclusion_tag</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">file_name</span><span class="p">,</span> <span class="n">takes_context</span><span class="o">=</span><span class="kc">False</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="k">def</span> <span class="nf">dec</span><span class="p">(</span><span class="n">func</span><span class="p">):</span> <span class="n">params</span><span class="p">,</span> <span class="n">varargs</span><span class="p">,</span> <span class="n">varkw</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="k">class</span> <span class="nc">InclusionNode</span><span class="p">(</span><span class="n">TagHelperNode</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="sd">"""</span> <span class="sd"> Renders the specified template and context. Caches the</span> <span class="sd"> template object in render_context to avoid reparsing and</span> <span class="sd"> loading when used in a for loop.</span> <span class="sd"> """</span> <span class="n">resolved_args</span><span class="p">,</span> <span class="n">resolved_kwargs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resolved_arguments</span><span class="p">(</span><span class="n">context</span><span class="p">)</span> <span class="n">_dict</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="o">*</span><span class="n">resolved_args</span><span class="p">,</span> <span class="o">**</span><span class="n">resolved_kwargs</span><span class="p">)</span> <span class="n">t</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">get</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="k">if</span> <span class="n">t</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">file_name</span><span class="p">,</span> <span class="n">Template</span><span class="p">):</span> <span class="n">t</span> <span class="o">=</span> <span class="n">file_name</span> <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="nb">getattr</span><span class="p">(</span><span class="n">file_name</span><span class="p">,</span> <span class="s1">'template'</span><span class="p">,</span> <span class="kc">None</span><span class="p">),</span> <span class="n">Template</span><span class="p">):</span> <span class="n">t</span> <span class="o">=</span> <span class="n">file_name</span><span class="o">.</span><span class="n">template</span> <span class="k">elif</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">file_name</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="ow">and</span> <span class="n">is_iterable</span><span class="p">(</span><span class="n">file_name</span><span class="p">):</span> <span class="n">t</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">select_template</span><span class="p">(</span><span class="n">file_name</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">t</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">get_template</span><span class="p">(</span><span class="n">file_name</span><span class="p">)</span> <span class="n">context</span><span class="o">.</span><span class="n">render_context</span><span class="p">[</span><span class="bp">self</span><span class="p">]</span> <span class="o">=</span> <span class="n">t</span> <span class="n">new_context</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">_dict</span><span class="p">)</span> <span class="c1"># Copy across the CSRF token, if present, because</span> <span class="c1"># inclusion tags are often used for forms, and we need</span> <span class="c1"># instructions for using CSRF protection to be as simple</span> <span class="c1"># as possible.</span> <span class="n">csrf_token</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'csrf_token'</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span> <span class="k">if</span> <span class="n">csrf_token</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span> <span class="n">new_context</span><span class="p">[</span><span class="s1">'csrf_token'</span><span class="p">]</span> <span class="o">=</span> <span class="n">csrf_token</span> <span class="k">return</span> <span class="n">t</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="n">new_context</span><span class="p">)</span> <span class="n">function_name</span> <span class="o">=</span> <span class="p">(</span><span class="n">name</span> <span class="ow">or</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="o">.</span><span class="n">__name__</span><span class="p">)</span> <span class="n">compile_func</span> <span class="o">=</span> <span class="n">partial</span><span class="p">(</span><span class="n">generic_tag_compiler</span><span class="p">,</span> <span class="n">params</span><span class="o">=</span><span class="n">params</span><span class="p">,</span> <span class="n">varargs</span><span class="o">=</span><span class="n">varargs</span><span class="p">,</span> <span class="n">varkw</span><span class="o">=</span><span class="n">varkw</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="n">defaults</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">function_name</span><span class="p">,</span> <span class="n">takes_context</span><span class="o">=</span><span class="n">takes_context</span><span class="p">,</span> <span class="n">node_class</span><span class="o">=</span><span class="n">InclusionNode</span><span class="p">)</span> <span class="n">compile_func</span><span class="o">.</span><span class="n">__doc__</span> <span class="o">=</span> <span class="n">func</span><span class="o">.</span><span class="n">__doc__</span> <span class="bp">self</span><span class="o">.</span><span class="n">tag</span><span class="p">(</span><span class="n">function_name</span><span class="p">,</span> <span class="n">compile_func</span><span class="p">)</span> <span class="k">return</span> <span class="n">func</span> <span class="k">return</span> <span class="n">dec</span> <span class="k">def</span> <span class="nf">is_library_missing</span><span class="p">(</span><span class="n">name</span><span class="p">):</span> <span class="sd">"""Check if library that failed to load cannot be found under any</span> <span class="sd"> templatetags directory or does exist but fails to import.</span> <span class="sd"> Non-existing condition is checked recursively for each subpackage in cases</span> <span class="sd"> like <appdir>/templatetags/subpackage/package/module.py.</span> <span class="sd"> """</span> <span class="c1"># Don't bother to check if '.' is in name since any name will be prefixed</span> <span class="c1"># with some template root.</span> <span class="n">path</span><span class="p">,</span> <span class="n">module</span> <span class="o">=</span> <span class="n">name</span><span class="o">.</span><span class="n">rsplit</span><span class="p">(</span><span class="s1">'.'</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">try</span><span class="p">:</span> <span class="n">package</span> <span class="o">=</span> <span class="n">import_module</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="k">return</span> <span class="ow">not</span> <span class="n">module_has_submodule</span><span class="p">(</span><span class="n">package</span><span class="p">,</span> <span class="n">module</span><span class="p">)</span> <span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span> <span class="k">return</span> <span class="n">is_library_missing</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="k">def</span> <span class="nf">import_library</span><span class="p">(</span><span class="n">taglib_module</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Load a template tag library module.</span> <span class="sd"> Verifies that the library contains a 'register' attribute, and</span> <span class="sd"> returns that attribute as the representation of the library</span> <span class="sd"> """</span> <span class="k">try</span><span class="p">:</span> <span class="n">mod</span> <span class="o">=</span> <span class="n">import_module</span><span class="p">(</span><span class="n">taglib_module</span><span class="p">)</span> <span class="k">except</span> <span class="ne">ImportError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> <span class="c1"># If the ImportError is because the taglib submodule does not exist,</span> <span class="c1"># that's not an error that should be raised. If the submodule exists</span> <span class="c1"># and raised an ImportError on the attempt to load it, that we want</span> <span class="c1"># to raise.</span> <span class="k">if</span> <span class="n">is_library_missing</span><span class="p">(</span><span class="n">taglib_module</span><span class="p">):</span> <span class="k">return</span> <span class="kc">None</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="n">InvalidTemplateLibrary</span><span class="p">(</span><span class="s2">"ImportError raised loading </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">taglib_module</span><span class="p">,</span> <span class="n">e</span><span class="p">))</span> <span class="k">try</span><span class="p">:</span> <span class="k">return</span> <span class="n">mod</span><span class="o">.</span><span class="n">register</span> <span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span> <span class="k">raise</span> <span class="n">InvalidTemplateLibrary</span><span class="p">(</span><span class="s2">"Template library </span><span class="si">%s</span><span class="s2"> does not have "</span> <span class="s2">"a variable named 'register'"</span> <span class="o">%</span> <span class="n">taglib_module</span><span class="p">)</span> <span class="nd">@lru_cache</span><span class="o">.</span><span class="n">lru_cache</span><span class="p">()</span> <span class="k">def</span> <span class="nf">get_templatetags_modules</span><span class="p">():</span> <span class="sd">"""</span> <span class="sd"> Return the list of all available template tag modules.</span> <span class="sd"> Caches the result for faster access.</span> <span class="sd"> """</span> <span class="n">templatetags_modules_candidates</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'django.templatetags'</span><span class="p">]</span> <span class="n">templatetags_modules_candidates</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span> <span class="s1">'</span><span class="si">%s</span><span class="s1">.templatetags'</span> <span class="o">%</span> <span class="n">app_config</span><span class="o">.</span><span class="n">name</span> <span class="k">for</span> <span class="n">app_config</span> <span class="ow">in</span> <span class="n">apps</span><span class="o">.</span><span class="n">get_app_configs</span><span class="p">())</span> <span class="n">templatetags_modules</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">templatetag_module</span> <span class="ow">in</span> <span class="n">templatetags_modules_candidates</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="n">import_module</span><span class="p">(</span><span class="n">templatetag_module</span><span class="p">)</span> <span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span> <span class="k">continue</span> <span class="k">else</span><span class="p">:</span> <span class="n">templatetags_modules</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">templatetag_module</span><span class="p">)</span> <span class="k">return</span> <span class="n">templatetags_modules</span> <span class="k">def</span> <span class="nf">get_library</span><span class="p">(</span><span class="n">library_name</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Load the template library module with the given name.</span> <span class="sd"> If library is not already loaded loop over all templatetags modules</span> <span class="sd"> to locate it.</span> <span class="sd"> {% load somelib %} and {% load someotherlib %} loops twice.</span> <span class="sd"> Subsequent loads eg. {% load somelib %} in the same process will grab</span> <span class="sd"> the cached module from libraries.</span> <span class="sd"> """</span> <span class="n">lib</span> <span class="o">=</span> <span class="n">libraries</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">library_name</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">lib</span><span class="p">:</span> <span class="n">templatetags_modules</span> <span class="o">=</span> <span class="n">get_templatetags_modules</span><span class="p">()</span> <span class="n">tried_modules</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">module</span> <span class="ow">in</span> <span class="n">templatetags_modules</span><span class="p">:</span> <span class="n">taglib_module</span> <span class="o">=</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">module</span><span class="p">,</span> <span class="n">library_name</span><span class="p">)</span> <span class="n">tried_modules</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">taglib_module</span><span class="p">)</span> <span class="n">lib</span> <span class="o">=</span> <span class="n">import_library</span><span class="p">(</span><span class="n">taglib_module</span><span class="p">)</span> <span class="k">if</span> <span class="n">lib</span><span class="p">:</span> <span class="n">libraries</span><span class="p">[</span><span class="n">library_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">lib</span> <span class="k">break</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">lib</span><span class="p">:</span> <span class="k">raise</span> <span class="n">InvalidTemplateLibrary</span><span class="p">(</span><span class="s2">"Template library </span><span class="si">%s</span><span class="s2"> not found, "</span> <span class="s2">"tried </span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">library_name</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">tried_modules</span><span class="p">)))</span> <span class="k">return</span> <span class="n">lib</span> <span class="k">def</span> <span class="nf">add_to_builtins</span><span class="p">(</span><span class="n">module</span><span class="p">):</span> <span class="n">builtins</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">import_library</span><span class="p">(</span><span class="n">module</span><span class="p">))</span> <span class="n">add_to_builtins</span><span class="p">(</span><span class="s1">'django.template.defaulttags'</span><span class="p">)</span> <span class="n">add_to_builtins</span><span class="p">(</span><span class="s1">'django.template.defaultfilters'</span><span class="p">)</span> <span class="n">add_to_builtins</span><span class="p">(</span><span class="s1">'django.template.loader_tags'</span><span class="p">)</span> </pre></div> </div> </div> </div> <div class="yui-b" id="sidebar"> <div class="sphinxsidebar" role="navigation" aria-label="main navigation"> <div class="sphinxsidebarwrapper"> <h3>Browse</h3> <ul> </ul> <h3>You are here:</h3> <ul> <li> <a href="../../../index.html">Django 1.8.19 documentation</a> <ul><li><a href="../../index.html">Module code</a> <ul><li><a href="../../django.html">django</a> <ul><li>django.template.base</li></ul> </li></ul></li></ul> </li> </ul> <div id="searchbox" style="display: none" role="search"> <h3>Quick search</h3> <form class="search" action="../../../search.html" method="get"> <div><input type="text" name="q" /></div> <div><input type="submit" value="Go" /></div> <input type="hidden" name="check_keywords" value="yes" /> <input type="hidden" name="area" value="default" /> </form> </div> <script type="text/javascript">$('#searchbox').show(0);</script> </div> </div> <h3>Last update:</h3> <p class="topless">Jan 06, 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>