From 825e522fb5618d0fcfab0ed0d752332a35e20b94 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Fri, 16 Nov 2007 16:16:23 +0100 Subject: [PATCH] some more doc changes in jinja for the upcoming release --HG-- branch : trunk --- .hgignore | 6 +++ CHANGES | 9 +++- docs/src/debugging.txt | 19 ++++--- docs/src/designerdoc.txt | 8 +++ docs/src/devrecipies.txt | 12 +++++ docs/src/escaping.txt | 4 +- docs/src/frameworks.txt | 109 +++++++++++++++++++++++++++++++++++++- docs/src/installation.txt | 18 ++++++- docs/src/scopes.txt | 5 +- jinja/datastructure.py | 2 +- setup.py | 8 +-- tests/test_security.py | 16 ++++++ 12 files changed, 196 insertions(+), 20 deletions(-) create mode 100644 .hgignore diff --git a/.hgignore b/.hgignore new file mode 100644 index 0000000..bfd0c2a --- /dev/null +++ b/.hgignore @@ -0,0 +1,6 @@ +^instance$ +^instance/ +^jinja/.*\.so$ +^(build|dist|Jinja\.egg-info)/ +\.py[co]$ +\.DS_Store$ diff --git a/CHANGES b/CHANGES index 2a0a953..632b902 100644 --- a/CHANGES +++ b/CHANGES @@ -3,7 +3,14 @@ Jinja Changelog Version 1.2 ----------- -(codename to be selected, release date unknown) +(codename to be hatsuyuki, released Nov 17th 2007) + +.. admonition:: Backwards Incompatible Changes + + - `call` is a keyword now + - the internal parser AST changed + - `extends` must be the first tag in a template + - the tuple literal yields tuples now, instead of lists. - environments now have a `translator_factory` parameter that allows to change the translator without subclassing the environment. diff --git a/docs/src/debugging.txt b/docs/src/debugging.txt index a67f989..e8f432a 100644 --- a/docs/src/debugging.txt +++ b/docs/src/debugging.txt @@ -8,20 +8,25 @@ does not support the `__loader__` hook which is used by Jinja to provide templates. Although the import system was implemented three Python versions ago the default traceback system still doesn't support it. -However most of the extended web development traceback module support it: +However most of the extended web development traceback modules have support +for `__loader__`. Either directly or via the linecache module: -- `Colubrid Debugging Middleware`_ +- `Werkzeug Debugging Middleware`_ +- `Django`_ - `cgitb`_ - `EvalException`_ -Note that the django traceback module currently does not provide this. `A -ticket`_ was filed already so there is hope that this will be fixed. - To enable debugging you have to use one of those debugging systems or implement your own one with support for `__loader__`. +The python implementation of the jinja debugger can only translate the first +exception in a traceback which can lead to problematic results. If you have +the extended debugger c extension compiled (default on unix systems but only +available on Windows if you have a VisualStudio 2003 installation) all frames +in the traceback will point to the correct linenumbers of the templates. + -.. _Colubrid Debugging Middleware: http://trac.pocoo.org/repos/colubrid/trunk/colubrid/debug.py +.. _Werkzeug Debugging Middleware: http://werkzeug.pocoo.org/ +.. _Django: http://www.djangoproject.com/ .. _cgitb: http://docs.python.org/lib/module-cgitb.html .. _EvalException: http://pythonpaste.org/module-paste.evalexception.html -.. _A ticket: http://code.djangoproject.com/ticket/3734 diff --git a/docs/src/designerdoc.txt b/docs/src/designerdoc.txt index 1ca741d..978565a 100644 --- a/docs/src/designerdoc.txt +++ b/docs/src/designerdoc.txt @@ -223,6 +223,14 @@ table shows which syntax elements are supported: ``undefined`` special Jinja undefined singleton. ======================= =================================================== +.. admonition:: Common Pitfalls + + Keep in mind that Jinja literals, keywords and functions are all lowercase. + If you're used to Python you probably tried to write `True` which evaluates + to undefined because it simply does not exist. The correct name for the + true value is just `true` (lowercase). + + Operators ========= diff --git a/docs/src/devrecipies.txt b/docs/src/devrecipies.txt index f0ec3c8..dfa2043 100644 --- a/docs/src/devrecipies.txt +++ b/docs/src/devrecipies.txt @@ -38,6 +38,7 @@ You can use it now like this: In the template you can now access the local variables `seq` and `foo`. + Using Django Filters with Jinja =============================== @@ -75,10 +76,18 @@ And use it: Also keep in mind that Jinja knows about keywords, thus you cannot have a filter that is called `pluralize` for example. +Such a conversion function is also part of the djangosupport module which was +introduced in Jinja 1.2. It's explained on the `Framework Integration`_ page. + Using Jinja in Django ===================== +.. admonition:: Note + + This section is more or less obsolete as of Jinja 1.2 which provides a + djangosupport module, covered on the `Framework Integration`_ page. + This snippet was contributed by Bryan McLemore. It provides a `render_to_response` function similar to the one shipped with django just that it uses Jinja for rendering. It applies the context processors on the context and consumes a @@ -125,3 +134,6 @@ environment class: Because Django uses gettext internally we can create just assign the ngettext and gettext functions directly to the translator class. + + +.. _Framework Integration: frameworks.txt diff --git a/docs/src/escaping.txt b/docs/src/escaping.txt index ab7e8d6..73c0d93 100644 --- a/docs/src/escaping.txt +++ b/docs/src/escaping.txt @@ -40,8 +40,8 @@ processing). Starting with `Jinja 1.1` you can also handle some whitespace rules in the template. If you put an minus sign (`-`) to the start or end of an block -(for example a `for` tag) or a comment, variable element you can remove -the whitespaces after that block or before that block: +(for example a `for` tag), a comment or variable element you can remove +the whitespaces after or before that block: .. sourcecode:: jinja diff --git a/docs/src/frameworks.txt b/docs/src/frameworks.txt index 930b001..88aafea 100644 --- a/docs/src/frameworks.txt +++ b/docs/src/frameworks.txt @@ -15,6 +15,7 @@ called `General Template Interface`_ which isn't implemented by any existing framework so far. This specification however tries to solve the problems that exist in Buffet. + Buffet ====== @@ -108,6 +109,7 @@ a folder in the ``yourapplication`` python package. The `downloads` action uses the pylons specific leading foreslash notation. + General Template Interface ========================== @@ -121,7 +123,112 @@ Django Using Jinja in django is straightforward because django has a pretty low level response interface. Just have a look at the `developer recipies`_, -there are some examples for django. +there are some examples for django. Starting with Jinja 1.2 there is also +a contrib module that simplifies using Jinja in an unicode enabled django. + +Quickstart +---------- + +To get started execute the following code at the bottom of your settings.py +or in some general application file such as urls.py or a central module. The +only thing that matters is that it's executed right *after* the settings +were set up and *before* `django.contrib.jinja` is imported:: + + from jinja.contrib import djangosupport + djangosupport.configure() + +What this does is setting up a Jinja environment for this django instance +with loaders for `TEMPLATE_DIRS` etc. It also converts a couple of default +django filters such as `date` and `timesince` which are not available in +Jinja per default. If you want to change the list you can provide others +by passing a list with filter import names as `convert_filters` keyword +argument. + +All other keyword arguments are forwarded to the environment. If you want +to provide a loader yourself pass it a loader keyword argument. + +Rendering Templates +------------------- + +To render a template you can use the functions `render_to_string` or +`render_to_response` from the `django.contrib.jinja` module:: + + from django.contrib.jinja import render_to_response + resp = render_to_response('Hello {{ username }}!', { + 'username': req.session['username'] + }, req) + +`render_to_string` and `render_to_response` take at least the name of +the template as argument, then the optional dict which will become the +context. If you also provide a request object as third argument the +context processors will be applied. + +`render_to_response` also takes a forth parameter which can be the +content type which defaults to `DEFAULT_CONTENT_TYPE`. + +Converting Filters +------------------ + +One of the useful objects provided by `django.contrib.jinja` is the +`register` object which can be used to register filters, tests and +global objects. You can also convert any filter django provides in +a Jinja filter using `convert_django_filter`:: + + from django.contrib.jinja import register, convert_django_filter + from django.template.defaultfilters import floatformat + + register.filter(convert_django_filter(floatformat), 'floatformat') + +Available methods on the `register` object: + +``object (obj[, name])`` + Register a new global as name or with the object's name. + Returns the function object unchanged so that you can use + it as decorator if no name is provided. + +``filter (func[, name])`` + Register a function as filter with the name provided or + the object's name as filtername. + Returns the function object unchanged so that you can use + it as decorator if no name is provided. + +``test (func[, name])`` + Register a function as test with the name provided or the + object's name as testname. + Returns the function object unchanged so that you can use + it as decorator if no name is provided. + +``context_inclusion (func, template[, name])`` + Register a function with a name provided or the func object's + name in the global namespace that acts as subrender function. + + func is called with the callers context as dict and the + arguments and keywords argument of the inclusion function. + The function should then process the context and return a + new context or the same context object. Afterwards the + template is rendered with this context. + + Example:: + + def add_author(context, author=None): + if author is not None: + author = Author.objects.get(name=author) + context['author'] = author + return context + + register.context_inclusion(add_author, 'author_details.html', + 'render_author_details') + + You can use it in the template like this then:: + + {{ render_author_details('John Doe') }} + +``clean_inclusion (func, template[, name[, run_processors]]) `` + Works like `context_inclusion` but doesn't use the calles + context but an empty context. If `run_processors` is `True` + it will lookup the context for a `request` object and pass + it to the render function to apply context processors. + .. _Pylons: http://www.pylonshq.com/ diff --git a/docs/src/installation.txt b/docs/src/installation.txt index 5b48a07..8f7cbad 100644 --- a/docs/src/installation.txt +++ b/docs/src/installation.txt @@ -4,6 +4,7 @@ Installation Jinja requires at least Python 2.3 to work correctly. + Installing a released version ============================= @@ -30,6 +31,7 @@ internet connection. This will install Jinja into your Python installation's site-packages directory. + Installing the development version ================================== @@ -42,7 +44,8 @@ If you want to play around with the code 4. ``ln -s jinja /usr/lib/python2.X/site-packages`` As an alternative to steps 4 you can also do ``python setup.py develop`` -which will install the package via setuptools in development mode. +which will install the package via setuptools in development mode. This also +has the advantage that the c extensions are compiled. If you just want the latest features and use them ------------------------------------------------- @@ -55,6 +58,19 @@ This will install a Jinja egg containing the latest Subversion trunk code in your Python installation's site-packages directory. Every time the command is run, the sources are updated from Subversion. + +Windows Installation Information +================================ + +On windows computers without Visual Studio 2003 Jinja is unable to compile the +C extensions. This is usually not a problem because there is a fallback for +native Python implementations of those C libraries. However under certain +conditions the installation may fail with an error message. In that case try +to disable the extensions by passing the following parameters to setup.py:: + + python setup.py install --without-speedups --without-extended-debugger + + Documentation ============= diff --git a/docs/src/scopes.txt b/docs/src/scopes.txt index baf8c69..8dd1e43 100644 --- a/docs/src/scopes.txt +++ b/docs/src/scopes.txt @@ -182,6 +182,5 @@ it. There is however a way to override a variable from an outer scope using the After the iteration `last_item` will point to the item of the last iteration. -If `last_item` was not defined in the outer scope it wouldn't exist now because -in that situation `set`, even with a postfixed bang just behaves like setting a -scope variable. +If `last_item` was not defined in the outer scope it would be defined in the +outermost scope. diff --git a/jinja/datastructure.py b/jinja/datastructure.py index 8e07a03..eb213d4 100644 --- a/jinja/datastructure.py +++ b/jinja/datastructure.py @@ -274,7 +274,7 @@ class Context(BaseContext): if name in layer: layer[name] = value return - self.current[name] = value + self.initial[name] = value def translate_func(self): """ diff --git a/setup.py b/setup.py index a7086c2..772e1ea 100644 --- a/setup.py +++ b/setup.py @@ -90,15 +90,15 @@ setup( features={ 'speedups': Feature( 'optional C-speed enhancements', - standard = True, - ext_modules = [ + standard=True, + ext_modules=[ Extension('jinja._speedups', ['jinja/_speedups.c']) ] ), 'extended-debugger': Feature( 'extended debugger', - standard = True, - ext_modules = [ + standard=True, + ext_modules=[ Extension('jinja._debugger', ['jinja/_debugger.c']) ] ) diff --git a/tests/test_security.py b/tests/test_security.py index 78a1e0a..a0faf18 100644 --- a/tests/test_security.py +++ b/tests/test_security.py @@ -6,6 +6,14 @@ :copyright: 2007 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ +from jinja import Environment + + +NONLOCALSET = '''\ +{% for item in range(10) %} + {%- set outer = item! -%} +{% endfor -%} +{{ outer }}''' class PrivateStuff(object): @@ -49,3 +57,11 @@ Traceback (most recent call last): ... TemplateSyntaxError: cannot assign to expression (line 1) ''' + + +def test_nonlocal_set(): + env = Environment() + env.globals['outer'] = 42 + tmpl = env.from_string(NONLOCALSET) + assert tmpl.render() == '9' + assert env.globals['outer'] == 42 -- 2.26.2