Mercurial > genshi > mirror
changeset 770:c290dc5a6813 stable-0.5.x
Ported [894] and [895] back to 0.5.x branch.
author | cmlenz |
---|---|
date | Tue, 01 Jul 2008 10:42:57 +0000 |
parents | f7682ced2777 |
children | 6aa9b14c68eb |
files | ChangeLog doc/plugin.txt genshi/__init__.py genshi/template/loader.py genshi/template/plugin.py genshi/template/tests/loader.py |
diffstat | 6 files changed, 88 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,9 @@ not directly a string, but rather something like an instance of the `LazyProxy` class in Babel (ticket #145). * Fix problem with match templates incorrectly being applied multiple times. + * Includes from templates loaded via an absolute path now include the correct + file in nested directories as long if no search path has been configured + (ticket #240). Version 0.5
--- a/doc/plugin.txt +++ b/doc/plugin.txt @@ -22,12 +22,11 @@ Introduction ============ -Most Python web frameworks (with the notable exception of Django_) support -a variety of different templating engines through the `Template Engine Plugin -API`_, which was first developed by the Buffet_ and TurboGears_ projects. +Some Python web frameworks support a variety of different templating engines +through the `Template Engine Plugin API`_, which was first developed by the +Buffet_ and TurboGears_ projects. .. _`Template Engine Plugin API`: http://docs.turbogears.org/1.0/TemplatePlugins -.. _`Django`: http://www.djangoproject.com/ .. _`Buffet`: http://projects.dowski.com/projects/buffet .. _`TurboGears`: http://www.turbogears.org/ @@ -72,8 +71,31 @@ format when you want to produce an Atom feed or other XML content. +Template Paths +-------------- + +How you specify template paths depends on whether you have a `search path`_ set +up or not. The search path is a list of directories that Genshi should load +templates from. Now when you request a template using a relative path such as +``mytmpl.html`` or ``foo/mytmpl.html``, Genshi will look for that file in the +directories on the search path. + +For mostly historical reasons, the Genshi template engine plugin uses a +different approach when you **haven't** configured the template search path: +you now load templates using *dotted notation*, for example ``mytmpl`` or +``foo.mytmpl``. Note how you've lost the ability to explicitly specify the +file extension: you now have to use ``.html`` for markup templates, and +``.txt`` for text templates. + +Using the search path is recommended for a number of reasons: First, it's +the native Genshi model and is thus more robust and better supported. +Second, a search path gives you much more flexibility for organizing your +application templates. And as noted above, you aren't forced to use hardcoded +filename extensions for your template files. + + Extra Implicit Objects -====================== +---------------------- The "genshi-markup" template engine plugin adds some extra functions that are made available to all templates implicitly, namely: @@ -230,6 +252,8 @@ In the version of Genshi, the default is to use the old syntax for backwards-compatibility, but that will change in a future release. +.. _`search path`: + ``genshi.search_path`` ---------------------- A colon-separated list of file-system path names that the template loader should
--- a/genshi/__init__.py +++ b/genshi/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2006-2007 Edgewall Software +# Copyright (C) 2006-2008 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which @@ -21,9 +21,13 @@ __docformat__ = 'restructuredtext en' try: - __version__ = __import__('pkg_resources').get_distribution('Genshi').version + from pkg_resources import get_distribution, ResolutionError + try: + __version__ = get_distribution('Genshi').version + except ResolutionError: + __version__ = None # unknown except ImportError: - pass + __version__ = None # unknown from genshi.core import * from genshi.input import ParseError, XML, HTML
--- a/genshi/template/loader.py +++ b/genshi/template/loader.py @@ -163,8 +163,14 @@ """ if cls is None: cls = self.default_class - if relative_to and not os.path.isabs(relative_to): + search_path = self.search_path + + # Make the filename relative to the template file its being loaded + # from, but only if that file is specified as a relative path, or no + # search path has been set up + if relative_to and (not search_path or not os.path.isabs(relative_to)): filename = os.path.join(os.path.dirname(relative_to), filename) + filename = os.path.normpath(filename) cachekey = filename @@ -181,7 +187,6 @@ except (KeyError, OSError): pass - search_path = self.search_path isabs = False if os.path.isabs(filename):
--- a/genshi/template/plugin.py +++ b/genshi/template/plugin.py @@ -16,8 +16,6 @@ CherryPy/Buffet. """ -from pkg_resources import resource_filename - from genshi.input import ET, HTML, XML from genshi.output import DocType from genshi.template.base import Template @@ -91,6 +89,7 @@ if self.use_package_naming: divider = templatename.rfind('.') if divider >= 0: + from pkg_resources import resource_filename package = templatename[:divider] basename = templatename[divider + 1:] + self.extension templatename = resource_filename(package, basename)
--- a/genshi/template/tests/loader.py +++ b/genshi/template/tests/loader.py @@ -261,6 +261,47 @@ </html>""", tmpl1.generate().render()) assert 'tmpl2.html' in loader._cache + def test_abspath_include_caching_without_search_path(self): + file1 = open(os.path.join(self.dirname, 'tmpl1.html'), 'w') + try: + file1.write("""<html xmlns:xi="http://www.w3.org/2001/XInclude"> + <xi:include href="tmpl2.html" /> + </html>""") + finally: + file1.close() + + file2 = open(os.path.join(self.dirname, 'tmpl2.html'), 'w') + try: + file2.write("""<div>Included</div>""") + finally: + file2.close() + + os.mkdir(os.path.join(self.dirname, 'sub')) + file3 = open(os.path.join(self.dirname, 'sub', 'tmpl1.html'), 'w') + try: + file3.write("""<html xmlns:xi="http://www.w3.org/2001/XInclude"> + <xi:include href="tmpl2.html" /> + </html>""") + finally: + file3.close() + + file4 = open(os.path.join(self.dirname, 'sub', 'tmpl2.html'), 'w') + try: + file4.write("""<div>Included from sub</div>""") + finally: + file4.close() + + loader = TemplateLoader() + tmpl1 = loader.load(os.path.join(self.dirname, 'tmpl1.html')) + self.assertEqual("""<html> + <div>Included</div> + </html>""", tmpl1.generate().render()) + tmpl2 = loader.load(os.path.join(self.dirname, 'sub', 'tmpl1.html')) + self.assertEqual("""<html> + <div>Included from sub</div> + </html>""", tmpl2.generate().render()) + assert 'tmpl2.html' not in loader._cache + def test_load_with_default_encoding(self): f = open(os.path.join(self.dirname, 'tmpl.html'), 'w') try: