From 2894f22c38cd64188648ba715c4f61e202d36913 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Mon, 19 Mar 2007 22:39:55 +0100 Subject: [PATCH] [svn] removed template plugin (buffet == broken) and added support for unused python keywords --HG-- branch : trunk --- docs/src/frameworks.txt | 60 ++--------------------------------- jinja/filters.py | 2 -- jinja/lexer.py | 21 ++++++++++++- jinja/loaders.py | 13 ++++---- jinja/nodes.py | 3 +- jinja/parser.py | 13 +++++++- jinja/plugin.py | 70 ----------------------------------------- setup.py | 6 +--- 8 files changed, 43 insertions(+), 145 deletions(-) delete mode 100644 jinja/plugin.py diff --git a/docs/src/frameworks.txt b/docs/src/frameworks.txt index 2cea2c9..6d576db 100644 --- a/docs/src/frameworks.txt +++ b/docs/src/frameworks.txt @@ -2,60 +2,6 @@ Framework Integration ===================== -Jinja registers itself in the buffet template plugin system. If your framework -supports buffet (currently `TurboGears`_ and `pylons`_) you can add it very -easily. - -Pylons ------- - -Edit ``yourproject/config/middleware.py`` and add the following lines to -`config.init_app...`: - -.. sourcecode:: python - - from jinja import Environment, FileSystemLoader - - config.add_template_engine('jinja', { - 'jinja.environment': Environment(loader=FileSystemLoader('path/to/templates')) - }) - -To make Jinja the default template engine change the `init_app` call to -something like this: - -.. sourcecode:: python - - config.init_app(global_conf, app_conf, package='yourproject', - template_engine='jinja') - -If you load templates using dotted notation the ``'.html'`` to the filename. -You can override this using ``jinja.exception``. eg: - -.. sourcecode:: python - - config.add_template_engine('jinja', { - 'jinja.environment': ..., - 'jinja.extension': 'tmpl' - }) - -Note that you have to use a trailing slash to load templates if you want to -specify the extension. Otherwise use the dotted notation: - -.. sourcecode:: python - - render_template('/index.html') - render_template('index') - - render_template('/modules/userlist.html') - render_template('modules.userlist') - - -TurboGears ----------- - -The TurboGears template plugin interface is broken by design and -there is currently no way to embed Jinja templates in TurboGears. - - -.. _TurboGears: http://www.turbogears.org/ -.. _pylons: http://www.pylonshq.com/ +Because the buffet template interface does not support more complex usage +cases there is currently no built in framework support. This however will +hopefully change before the Jinja release. diff --git a/jinja/filters.py b/jinja/filters.py index 481f9f5..be32113 100644 --- a/jinja/filters.py +++ b/jinja/filters.py @@ -404,8 +404,6 @@ do_indent = stringfilter(do_indent) def do_truncate(s, length=255, killwords=False, end='...'): """ - {{ s|truncate[ length[ killwords[ end]]] }} - Return a truncated copy of the string. The length is specified with the first parameter which defaults to ``255``. If the second parameter is ``true`` the filter will cut the text at length. Otherwise diff --git a/jinja/lexer.py b/jinja/lexer.py index 13ca67a..2793c50 100644 --- a/jinja/lexer.py +++ b/jinja/lexer.py @@ -10,6 +10,11 @@ import re from jinja.datastructure import TokenStream from jinja.exceptions import TemplateSyntaxError +try: + set +except NameError: + from sets import Set as set + # static regular expressions whitespace_re = re.compile(r'\s+(?m)') @@ -29,6 +34,13 @@ operator_re = re.compile('(%s)' % '|'.join( ur'or\b', ur'and\b', ur'not\b', ur'in\b', ur'is' ])) +# set of names that are keywords in python but not in jinja. the lexer +# appends three trailing underscores, the parser removes them again later +escaped_names = set(['with', 'as', 'import', 'from', 'class', 'def', + 'try', 'except', 'exec', 'global', 'assert', + 'break', 'continue', 'lambda', 'return', 'raise', + 'yield', 'while', 'pass', 'finally']) + class Failure(object): """ @@ -104,8 +116,15 @@ class Lexer(object): tuples. Wrap the generator returned by this function in a `TokenStream` to get real token instances and be able to push tokens back to the stream. That's for example done by the parser. + + Additionally some names like "class" are escaped """ - return TokenStream(self.tokeniter(source)) + def filter(): + for lineno, token, value in self.tokeniter(source): + if token == 'name' and value in escaped_names: + value += '___' + yield lineno, token, value + return TokenStream(filter()) def tokeniter(self, source): """ diff --git a/jinja/loaders.py b/jinja/loaders.py index fe40aa8..76d476d 100644 --- a/jinja/loaders.py +++ b/jinja/loaders.py @@ -308,17 +308,16 @@ class PackageLoader(CachedLoaderMixin, BaseLoader): self.package_path = package_path # if we have an loader we probably retrieved it from an egg # file. In that case don't use the auto_reload! - if auto_reload: - package = __import__(package_name, '', '', ['']) - if package.__loader__ is not None: - auto_reload = False + if auto_reload and getattr(__import__(package_name, '', '', ['']), + '__loader__', None) is not None: + auto_reload = False CachedLoaderMixin.__init__(self, use_memcache, memcache_size, cache_folder, auto_reload) def get_source(self, environment, name, parent): name = '/'.join([self.package_path] + [p for p in name.split('/') - if p and p[0] != '.']) - if not resource_exists(self.package, name): + if p != '..']) + if not resource_exists(self.package_name, name): raise TemplateNotFound(name) contents = resource_string(self.package_name, name) return contents.decode(environment.template_charset) @@ -326,7 +325,7 @@ class PackageLoader(CachedLoaderMixin, BaseLoader): def check_source_changed(self, environment, name): name = '/'.join([self.package_path] + [p for p in name.split('/') if p and p[0] != '.']) - return path.getmtime(resource_filename(name)) + return path.getmtime(resource_filename(self.package_name, name)) class DictLoader(BaseLoader): diff --git a/jinja/nodes.py b/jinja/nodes.py index a4fa2a2..b3ef5f5 100644 --- a/jinja/nodes.py +++ b/jinja/nodes.py @@ -9,7 +9,6 @@ :license: BSD, see LICENSE for more details. """ from compiler import ast -from compiler.misc import set_filename def inc_lineno(offset, tree): @@ -94,7 +93,7 @@ class Template(NodeList): body = (body,) NodeList.__init__(self, 1, body) self.extends = extends - set_filename(filename, self) + self.filename = filename def get_items(self): if self.extends is not None: diff --git a/jinja/parser.py b/jinja/parser.py index c5d4e1b..11d031f 100644 --- a/jinja/parser.py +++ b/jinja/parser.py @@ -12,6 +12,7 @@ import re from compiler import ast, parse from compiler.misc import set_filename from jinja import nodes +from jinja.lexer import escaped_names from jinja.datastructure import TokenStream from jinja.exceptions import TemplateSyntaxError try: @@ -396,9 +397,19 @@ class Parser(object): def parse(self): """ - Parse the template and return a Template node. + Parse the template and return a Template node. Also unescape the + names escaped by the lexer (unused python keywords) and set the + filename attributes for all nodes in the tree. """ body = self.subparse(None) + todo = [body] + while todo: + node = todo.pop() + if node.__class__ in (ast.AssName, ast.Name) and \ + node.name.endswith('___') and node.name[:-3] in escaped_names: + node.name = node.name[:-3] + node.filename = self.filename + todo.extend(node.getChildNodes()) return nodes.Template(self.filename, body, self.extends) def subparse(self, test, drop_needle=False): diff --git a/jinja/plugin.py b/jinja/plugin.py deleted file mode 100644 index 7c6b4bc..0000000 --- a/jinja/plugin.py +++ /dev/null @@ -1,70 +0,0 @@ -# -*- coding: utf-8 -*- -""" - jinja.plugin - ~~~~~~~~~~~~ - - This module proides a bridge to buffed so that you can use Jinja - in pylons. Note that this doesn't work with turbogears because their - buffet implementation is broken. - - :copyright: 2007 by Armin Ronacher. - :license: BSD, see LICENSE for more details. -""" - -from jinja import Environment - - -class ConfigurationError(ValueError): - """ - Raised if an configuration error occoured. - """ - - -class JinjaPlugin(object): - """ - Implementation of the Plugin API - """ - extension = 'html' - - def __init__(self, extra_vars_func=None, options=None): - self.get_extra_vars = extra_vars_func - options = options or {} - if 'jinja.environment' in options: - self.environment = options['jinja.environment'] - elif 'jinja.init_callback' in options: - name = options['jinja.init_callback'] - p = name.rsplit('.', 1) - func = getattr(__import__(p[0], '', '', ['']), p[1]) - self.environment = func(options) - else: - raise ConfigurationError('no jinja environment defined') - if 'jinja.extension' in options: - self.extension = options['jinja.extension'] - - def load_template(self, templatename, template_string=None): - """ - Find a template specified in python 'dot' notation, or load one from - a string. - """ - if template_string is not None: - return self.environment.from_string(template_string) - - # Translate TG dot notation to normal / template path - if templatename.startswith('/'): - templatename = templatename[1:] - else: - templatename = templatename.replace('.', '/') + '.' + self.extension - - return self.environment.get_template(templatename) - - def render(self, info, format='html', fragment=False, template=None): - """ - Render a template. - """ - if isinstance(template, basestring): - template = self.load_template(template) - - if self.get_extra_vars: - info.update(self.get_extra_vars()) - - return template.render(**info) diff --git a/setup.py b/setup.py index 503dee4..c296c1f 100644 --- a/setup.py +++ b/setup.py @@ -30,9 +30,5 @@ setup( ], keywords = ['python.templating.engines'], packages = ['jinja', 'jinja.translators'], - extras_require = {'plugin': ['setuptools>=0.6a2']}, - entry_points=''' - [python.templating.engines] - jinja = jinja.plugin:JinjaPlugin[plugin] - ''' + extras_require = {'plugin': ['setuptools>=0.6a2']} ) -- 2.26.2