From: Armin Ronacher Date: Sat, 3 Mar 2007 20:58:44 +0000 (+0100) Subject: [svn] fixed loop context bug, added new jinja webpage X-Git-Tag: 2.0rc1~473 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=0a1742e272a4e18c0fa688ec2513880abeb9e011;p=jinja2.git [svn] fixed loop context bug, added new jinja webpage --HG-- branch : trunk --- diff --git a/jinja/__init__.py b/jinja/__init__.py index ceaf5f5..9ee395a 100644 --- a/jinja/__init__.py +++ b/jinja/__init__.py @@ -8,3 +8,6 @@ """ from jinja.environment import Environment from jinja.loaders import * + + +from_string = Environment().from_string diff --git a/jinja/datastructure.py b/jinja/datastructure.py index 7a69ec5..22f5fbc 100644 --- a/jinja/datastructure.py +++ b/jinja/datastructure.py @@ -66,6 +66,9 @@ class UndefinedType(object): def __float__(self): return 1 + def __call__(self, *args, **kwargs): + return self + Undefined = UndefinedType() @@ -214,6 +217,9 @@ class LoopContext(object): return self.loop_function(seq) return Undefined + def __repr__(self): + return str(self._stack) + class CycleContext(object): """ @@ -263,7 +269,7 @@ class TokenStream(object): return True eos = property(lambda x: not x.__nonzero__(), doc=__nonzero__.__doc__) - + def next(self): """Return the next token from the stream.""" if self._pushed: diff --git a/jinja/environment.py b/jinja/environment.py index 701c4d2..124ee47 100644 --- a/jinja/environment.py +++ b/jinja/environment.py @@ -133,15 +133,14 @@ class Environment(object): """ Get the attribute name from obj. """ - if name in obj: + try: return obj[name] - elif hasattr(obj, name): - rv = getattr(obj, name) - r = getattr(obj, 'jinja_allowed_attributes', None) - if r is not None: - if name not in r: + except (TypeError, KeyError, IndexError): + if hasattr(obj, name): + r = getattr(obj, 'jinja_allowed_attributes', None) + if r is not None and name not in r: raise SecurityException('unsafe attributed %r accessed' % name) - return rv + return getattr(obj, name) return Undefined def call_function(self, f, args, kwargs, dyn_args, dyn_kwargs): diff --git a/jinja/parser.py b/jinja/parser.py index 0c4dcb1..af77022 100644 --- a/jinja/parser.py +++ b/jinja/parser.py @@ -26,6 +26,7 @@ end_of_if = lambda p, t, d: t == 'name' and d == 'endif' end_of_filter = lambda p, t, d: t == 'name' and d == 'endfilter' end_of_macro = lambda p, t, d: t == 'name' and d == 'endmacro' end_of_block_tag = lambda p, t, d: t == 'name' and d == 'endblock' +end_of_raw = lambda p, t, d: t == 'name' and d == 'endraw' class Parser(object): diff --git a/www/documentation.html b/www/documentation.html new file mode 100644 index 0000000..2edeb79 --- /dev/null +++ b/www/documentation.html @@ -0,0 +1,36 @@ + + + + Documentation | Jinja Template Engine + + + + + + + + +
+
+

Documentation

+

+ You can browse the documentation either online or download it: +

+
+

+ show template source +

+
+ + + \ No newline at end of file diff --git a/www/documentation.tmpl b/www/documentation.tmpl new file mode 100644 index 0000000..2e6fa97 --- /dev/null +++ b/www/documentation.tmpl @@ -0,0 +1,8 @@ +<% extends 'layout/base.tmpl' %> +<% block title %>Documentation<% endblock %> +<% block content %> +

Documentation

+

+ You can browse the documentation either online or download it: +

+<% endblock %> diff --git a/www/download.html b/www/download.html new file mode 100644 index 0000000..996fb38 --- /dev/null +++ b/www/download.html @@ -0,0 +1,52 @@ + + + + Download | Jinja Template Engine + + + + + + + + +
+
+

Download

+

+ If you want to install the release with + easy_install, + you can do it using this command: +

+
easy_install Pygments
+

+ You can also get the development source from subversion using this command: +

+
svn co http://trac.pocoo.org/repos/jinja/trunk jinja
+

+ Installing the current subversion trunk as a Python egg is done with: +

+
easy_install Jinja==dev
+

+ Development takes place at the Pocoo trac, + you can browse the source online + here. +

+
+

+ show template source +

+
+ + + \ No newline at end of file diff --git a/www/download.tmpl b/www/download.tmpl new file mode 100644 index 0000000..53aac92 --- /dev/null +++ b/www/download.tmpl @@ -0,0 +1,24 @@ +<% extends 'layout/base.tmpl' %> +<% block title %>Download<% endblock %> +<% block content %> +

Download

+

+ If you want to install the release with + easy_install, + you can do it using this command: +

+
easy_install Pygments
+

+ You can also get the development source from subversion using this command: +

+
svn co http://trac.pocoo.org/repos/jinja/trunk jinja
+

+ Installing the current subversion trunk as a Python egg is done with: +

+
easy_install Jinja==dev
+

+ Development takes place at the Pocoo trac, + you can browse the source online + here. +

+<% endblock %> diff --git a/www/faq.html b/www/faq.html new file mode 100644 index 0000000..7d0cadc --- /dev/null +++ b/www/faq.html @@ -0,0 +1,72 @@ + + + + FAQ | Jinja Template Engine + + + + + + + + +
+
+

Frequently Asked Questions

+

+ Here a list of frequently asked questions. +

+

Why the Name?

+

+ The name Jinja was chosen because it's the name of a Japanese temple and + temple and template share a similar pronunciation. +

+

How fast is it?

+

+ I really hate benchmarks especially since they don't reflect much. The + performance of a template depends on many factors and you would have to + benchmark different engines in differen situations. However Jinja isn't + slow. The benchmarks from the testsuite show that Jinja is about twice + as fast as Django templates and about three times as slow as + mako. That's not bad for a + sandboxed template engine that has to sanitize template input on the fly. + If you really need the best performance of a template engine consider + using mako. +

+

What happened to Jinja < 1?

+

+ Before Jinja 1 there was a template engine too with the same name. Beside + the name and the same maintainer those two projects don't share a single + line of code. If you have an application using Jinja < 1 you should try + to make it Jinja 1 compatible. If that's not possible, the old project is + still available as + 0.9-maint + in the Jinja subversion repository. +

+

Why should I use Jinja?

+

+ There are dozens of template engines for Python, many of them try to + achieve different things. If you are looking for a XML based template + engine have a look at genshi, + if you want a bleezing fast template engine with the full range of + python constructs have a look at mako. If you want sandboxed templates + you probably want to check out Jinja. +

+
+

+ show template source +

+
+ + + \ No newline at end of file diff --git a/www/faq.tmpl b/www/faq.tmpl new file mode 100644 index 0000000..55eb8a3 --- /dev/null +++ b/www/faq.tmpl @@ -0,0 +1,44 @@ +<% extends 'layout/base.tmpl' %> +<% block title %>FAQ<% endblock %> +<% block content %> +

Frequently Asked Questions

+

+ Here a list of frequently asked questions. +

+

Why the Name?

+

+ The name Jinja was chosen because it's the name of a Japanese temple and + temple and template share a similar pronunciation. +

+

How fast is it?

+

+ I really hate benchmarks especially since they don't reflect much. The + performance of a template depends on many factors and you would have to + benchmark different engines in differen situations. However Jinja isn't + slow. The benchmarks from the testsuite show that Jinja is about twice + as fast as Django templates and about three times as slow as + mako. That's not bad for a + sandboxed template engine that has to sanitize template input on the fly. + If you really need the best performance of a template engine consider + using mako. +

+

What happened to Jinja < 1?

+

+ Before Jinja 1 there was a template engine too with the same name. Beside + the name and the same maintainer those two projects don't share a single + line of code. If you have an application using Jinja < 1 you should try + to make it Jinja 1 compatible. If that's not possible, the old project is + still available as + 0.9-maint + in the Jinja subversion repository. +

+

Why should I use Jinja?

+

+ There are dozens of template engines for Python, many of them try to + achieve different things. If you are looking for a XML based template + engine have a look at genshi, + if you want a bleezing fast template engine with the full range of + python constructs have a look at mako. If you want sandboxed templates + you probably want to check out Jinja. +

+<% endblock %> diff --git a/www/generate.py b/www/generate.py new file mode 100755 index 0000000..f8111f3 --- /dev/null +++ b/www/generate.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +""" + jinja webpage generator + ~~~~~~~~~~~~~~~~~~~~~~~ +""" +import os +from codecs import open +from jinja import Environment, FileSystemLoader +from jinja.filters import stringfilter +from pygments import highlight +from pygments.lexers import get_lexer_by_name +from pygments.formatters import HtmlFormatter + + +formatter = HtmlFormatter(cssclass='syntax', encoding=None, style='pastie') + +env = Environment('<%', '%>', '<%=', '%>', loader=FileSystemLoader('.'), trim_blocks=True) +env.filters['pygmentize'] = stringfilter(lambda v, l: + highlight(v.strip(), get_lexer_by_name(l), formatter)) + + +def get_files(folder): + for fn in os.listdir(folder): + fn = os.path.join(folder, fn) + if os.path.isdir(fn): + for item in get_files(fn): + yield item + elif fn.endswith('.tmpl'): + yield fn + + +for filename in get_files('.'): + root = './' + ''.join(['../' for _ in os.path.dirname(filename). + split(os.path.sep)[1:]]) + + t = env.get_template(filename) + f = open(filename[:-5] + '.html', 'w', 'utf-8') + f.write(t.render( + file_id=filename[2:-5], + root=root + )) + f.close() + +f = file('static/pygments.css', 'w') +f.write(formatter.get_style_defs('.syntax')) +f.close() diff --git a/www/index.html b/www/index.html new file mode 100644 index 0000000..8615465 --- /dev/null +++ b/www/index.html @@ -0,0 +1,92 @@ + + + + Index | Jinja Template Engine + + + + + + + + +
+
+

Jinja Templates

+

+ Jinja is a + sandboxed + template engine written in pure Python. It + provides a Django-like non-XML syntax + and compiles templates into executable python code. It's basically a combination + of Django templates and python code. +

+

Nutshell

+
{% extends 'base.html' %}
+{% block title %}Memberlist{% endblock %}
+{% block content %}
+  <ul>
+  {% for user in users %}
+    <li><a href="{{ user.url|e }}">{{ user.username|e }}</a></li>
+  {% endfor %}
+  </ul>
+{% endblock %}
+
+

Philosphy

+

+ Application logic is for the controller but don't try to make the live for the + template designer too hard by giving him too less functionality. +

+

Features

+
    +
  • Simple API. For basic usage just one function is needed: +
    from jinja import from_string
    +print from_string('Hello {{ data }}!').render(data='World')
    +
    +
  • +
  • Sandboxed. The whole engine is completely sandboxed. A + template designer won't be able to modify application data or execute + dangerous code.
  • +
  • Python expressions. You can use nearly every python + expression. Not supported are the binary operators and list comprehensions / + generator expressions.
  • +
  • Inheritance. Jinja uses the same concept for inheritance + Django uses. It's very powerful and easy to understand.
  • +
  • Macros. Jinja provides so called macros that allow you to + put often used template snippets into callable blocks: +
    {% macro dialog title, text %}
    +  <div class="dialog">
    +    <h2 class="title">{{ title }}</h2>
    +    <div class="text">{{ text }}</div>
    +  </div>
    +{% endmacro %}
    +
    +You can then use this block by calling it: +
    {{ dialog('Notification', 'Here the text for the macro.') }}
    +
    +
  • +
  • Designer friendly. Jinja simplifies many things for a + template designer. Loops can be used in a recursive way, filters are + available to format values, loops know about their iteration etc.
  • +
  • Dynamic Syntax. You don't like the Django block syntax? + You can override the syntax elements on environment initialisation. It's + no problem to use ASP/PHP/Ruby syntax, html comments for blocks etc.
  • +
+
+

+ show template source +

+
+ + + \ No newline at end of file diff --git a/www/index.tmpl b/www/index.tmpl new file mode 100644 index 0000000..6e7d4fe --- /dev/null +++ b/www/index.tmpl @@ -0,0 +1,65 @@ +<% extends 'layout/base.tmpl' %> +<% block title %>Index<% endblock %> +<% block content %> +

Jinja Templates

+

+ Jinja is a + sandboxed + template engine written in pure Python. It + provides a Django-like non-XML syntax + and compiles templates into executable python code. It's basically a combination + of Django templates and python code. +

+

Nutshell

+ <% filter pygmentize('html+jinja') %> +{% extends 'base.html' %} +{% block title %}Memberlist{% endblock %} +{% block content %} + +{% endblock %} +<% endfilter %> +

Philosphy

+

+ Application logic is for the controller but don't try to make the live for the + template designer too hard by giving him too less functionality. +

+

Features

+ +<% endblock %> diff --git a/www/layout/base.html b/www/layout/base.html new file mode 100644 index 0000000..c4fbe16 --- /dev/null +++ b/www/layout/base.html @@ -0,0 +1,32 @@ + + + + Untitled | Jinja Template Engine + + + + + + + + +
+
+
+

+ show template source +

+
+ + + \ No newline at end of file diff --git a/www/layout/base.tmpl b/www/layout/base.tmpl new file mode 100644 index 0000000..8f6d8c5 --- /dev/null +++ b/www/layout/base.tmpl @@ -0,0 +1,54 @@ +<% set navigation = [ + ('index', 'Index'), + ('faq', 'FAQ'), + ('documentation', 'Documentation'), + ('download', 'Download') +] %> +<% block code %><% endblock %> + + + + <% block title %>Untitled<% endblock %> | Jinja Template Engine + + + + + + + + + <% if trace %> +
+ <% for href, caption in trace %> + <% if loop.last %> + <%= caption %> + <% else %> + <%= caption %> » + <% endif %> + <% endfor %> +
+ <% endif %> +
+
+ <% block content %><% endblock %> +
+

+ show template source +

+
+ + + diff --git a/www/static/jinjabanner.png b/www/static/jinjabanner.png new file mode 100644 index 0000000..c672118 Binary files /dev/null and b/www/static/jinjabanner.png differ diff --git a/www/static/jinjalogo.png b/www/static/jinjalogo.png new file mode 100644 index 0000000..17d6dc3 Binary files /dev/null and b/www/static/jinjalogo.png differ diff --git a/www/static/pygments.css b/www/static/pygments.css new file mode 100644 index 0000000..1f1c6d6 --- /dev/null +++ b/www/static/pygments.css @@ -0,0 +1,58 @@ +.syntax { background: #ffffff; } +.syntax .c { color: #888888 } /* Comment */ +.syntax .err { color: #a61717; background-color: #e3d2d2 } /* Error */ +.syntax .k { color: #008800; font-weight: bold } /* Keyword */ +.syntax .cm { color: #888888 } /* Comment.Multiline */ +.syntax .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ +.syntax .c1 { color: #888888 } /* Comment.Single */ +.syntax .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ +.syntax .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ +.syntax .ge { font-style: italic } /* Generic.Emph */ +.syntax .gr { color: #aa0000 } /* Generic.Error */ +.syntax .gh { color: #999999 } /* Generic.Heading */ +.syntax .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ +.syntax .go { color: #888888 } /* Generic.Output */ +.syntax .gp { color: #555555 } /* Generic.Prompt */ +.syntax .gs { font-weight: bold } /* Generic.Strong */ +.syntax .gu { color: #aaaaaa } /* Generic.Subheading */ +.syntax .gt { color: #aa0000 } /* Generic.Traceback */ +.syntax .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ +.syntax .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ +.syntax .kp { color: #008800 } /* Keyword.Pseudo */ +.syntax .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ +.syntax .kt { color: #888888; font-weight: bold } /* Keyword.Type */ +.syntax .m { color: #0000DD; font-weight: bold } /* Literal.Number */ +.syntax .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ +.syntax .na { color: #336699 } /* Name.Attribute */ +.syntax .nb { color: #003388 } /* Name.Builtin */ +.syntax .nc { color: #bb0066; font-weight: bold } /* Name.Class */ +.syntax .no { color: #003366; font-weight: bold } /* Name.Constant */ +.syntax .nd { color: #555555 } /* Name.Decorator */ +.syntax .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ +.syntax .nf { color: #0066bb; font-weight: bold } /* Name.Function */ +.syntax .nl { color: #336699; font-style: italic } /* Name.Label */ +.syntax .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ +.syntax .py { color: #336699; font-weight: bold } /* Name.Property */ +.syntax .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ +.syntax .nv { color: #336699 } /* Name.Variable */ +.syntax .ow { color: #008800 } /* Operator.Word */ +.syntax .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ +.syntax .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ +.syntax .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ +.syntax .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ +.syntax .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ +.syntax .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ +.syntax .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ +.syntax .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ +.syntax .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ +.syntax .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ +.syntax .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ +.syntax .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ +.syntax .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ +.syntax .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ +.syntax .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ +.syntax .bp { color: #003388 } /* Name.Builtin.Pseudo */ +.syntax .vc { color: #336699 } /* Name.Variable.Class */ +.syntax .vg { color: #dd7700 } /* Name.Variable.Global */ +.syntax .vi { color: #3333bb } /* Name.Variable.Instance */ +.syntax .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/www/static/style.css b/www/static/style.css new file mode 100644 index 0000000..1e89fa3 --- /dev/null +++ b/www/static/style.css @@ -0,0 +1,137 @@ +/** + * Jinja Webpage Design + */ + +body { + background-color: #333; + margin: 0; + padding: 0; + font-family: 'Georgia', serif; + font-size: 15px; + color: #111; +} + +p, li, dd, dt, blockquote { + color: #333; +} + +p { + line-height: 150%; + margin-bottom: 0; + margin-top: 10px; + text-align: justify; +} + +hr { + border-top: 1px solid #ccc; + border-bottom: 0; + border-right: 0; + border-left: 0; + margin-bottom: 10px; + margin-top: 20px; +} + +a { + color: #b41717; +} + +a:hover { + color: #444; +} + +pre { + background-color: #f9f9f9; + border-top: 1px solid #ccc; + border-bottom: 1px solid #ccc; + padding: 5px; + font-size: 13px; + font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace; +} + +#content { + background-color: white; + background-image: url(watermark.png); + padding: 10px; + margin: 25px 25px 0 25px; + border: 4px solid #ddd; + border-bottom: none; +} + +#footer { + margin: 0 25px 25px 25px; + border-bottom: 4px solid #ddd; + background-color: #fff; + text-align: right; + padding: 0 10px 5px 0; +} + +#contentwrapper { + max-width: 700px; + padding: 0 10px 0 20px; +} + +#header { + height: 80px; + background-color: #eee; + background-image: url(jinjabanner.png); + background-repeat: no-repeat; + border-bottom: 4px solid #ccc; +} + +#header h1 { + display: none +} + +#navigation { + background-color: #fff; + border: 1px solid #ccc; + border-right: none; + margin: 50px 29px 10px 10px; + padding: 0; + float: right; + list-style: none; + font-weight: bold; +} + +#navigation li a { + display: block; + text-decoration: none; + padding: 5px 10px 5px 10px; + color: #333; +} + +#navigation li a:hover { + color: #fff; + background-color: #444; +} + +#navigation li.active { + padding: 5px 10px 5px 10px; + background-color: #b41717; + color: white; +} + +#navigation li a:focus { + outline: none; + background-color: #222; + color: #fff; +} + +#contentwrapper h1 { + color: #b41717; + font-size: 26px; + margin: 20px 0 0 -5px; +} + +#contentwrapper h2 { + color: #444; + font-size: 20px; + margin: 20px 0 0 0; +} + +#meta { + clear: both; + text-align: right; + color: #888; + font-size: 13px; +} diff --git a/www/static/watermark.png b/www/static/watermark.png new file mode 100644 index 0000000..297d899 Binary files /dev/null and b/www/static/watermark.png differ