changeset 876:52d7d6b7b6c1

Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
author cmlenz
date Thu, 15 Apr 2010 21:07:15 +0000
parents b8ac236f0254
children 8747234921b6
files genshi/template/base.py genshi/template/loader.py genshi/template/markup.py genshi/template/tests/loader.py
diffstat 4 files changed, 71 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/genshi/template/base.py
+++ b/genshi/template/base.py
@@ -395,6 +395,7 @@
         self.lookup = lookup
         self.allow_exec = allow_exec
         self._init_filters()
+        self._init_loader()
         self._prepared = False
 
         if isinstance(source, basestring):
@@ -419,9 +420,21 @@
         return '<%s "%s">' % (type(self).__name__, self.filename)
 
     def _init_filters(self):
-        self.filters = [self._flatten]
-        if self.loader:
-            self.filters.append(self._include)
+        self.filters = [self._flatten, self._include]
+
+    def _init_loader(self):
+        if self.loader is None:
+            from genshi.template.loader import TemplateLoader
+            if self.filename:
+                if self.filepath != self.filename:
+                    basedir = os.path.normpath(self.filepath)[:-len(
+                        os.path.normpath(self.filename))
+                    ]
+                else:
+                    basedir = os.path.dirname(self.filename)
+            else:
+                basedir = '.'
+            self.loader = TemplateLoader([os.path.abspath(basedir)])
 
     @property
     def stream(self):
--- a/genshi/template/loader.py
+++ b/genshi/template/loader.py
@@ -131,6 +131,15 @@
         self._uptodate = {}
         self._lock = threading.RLock()
 
+    def __getstate__(self):
+        state = self.__dict__.copy()
+        state['_lock'] = None
+        return state
+
+    def __setstate__(self, state):
+        self.__dict__ = state
+        self._lock = threading.RLock()
+
     def load(self, filename, relative_to=None, cls=None, encoding=None):
         """Load the template with the given name.
         
--- a/genshi/template/markup.py
+++ b/genshi/template/markup.py
@@ -70,11 +70,8 @@
     def _init_filters(self):
         Template._init_filters(self)
         # Make sure the include filter comes after the match filter
-        if self.loader:
-            self.filters.remove(self._include)
-        self.filters += [self._match]
-        if self.loader:
-            self.filters.append(self._include)
+        self.filters.remove(self._include)
+        self.filters += [self._match, self._include]
 
     def _parse(self, source, encoding):
         if not isinstance(source, Stream):
--- a/genshi/template/tests/loader.py
+++ b/genshi/template/tests/loader.py
@@ -153,6 +153,50 @@
               <div>Included</div>
             </html>""", tmpl.generate().render(encoding=None))
 
+    def test_relative_include_without_loader(self):
+        file1 = open(os.path.join(self.dirname, 'tmpl1.html'), 'w')
+        try:
+            file1.write("""<div>Included</div>""")
+        finally:
+            file1.close()
+
+        file2 = open(os.path.join(self.dirname, 'tmpl2.html'), 'w')
+        try:
+            file2.write("""<html xmlns:xi="http://www.w3.org/2001/XInclude">
+              <xi:include href="tmpl1.html" />
+            </html>""")
+        finally:
+            file2.close()
+
+        tmpl = MarkupTemplate("""<html xmlns:xi="http://www.w3.org/2001/XInclude">
+              <xi:include href="tmpl1.html" />
+            </html>""", os.path.join(self.dirname, 'tmpl2.html'), 'tmpl2.html')
+        self.assertEqual("""<html>
+              <div>Included</div>
+            </html>""", tmpl.generate().render(encoding=None))
+
+    def test_relative_include_without_loader_relative(self):
+        file1 = open(os.path.join(self.dirname, 'tmpl1.html'), 'w')
+        try:
+            file1.write("""<div>Included</div>""")
+        finally:
+            file1.close()
+
+        file2 = open(os.path.join(self.dirname, 'tmpl2.html'), 'w')
+        try:
+            file2.write("""<html xmlns:xi="http://www.w3.org/2001/XInclude">
+              <xi:include href="tmpl1.html" />
+            </html>""")
+        finally:
+            file2.close()
+
+        tmpl = MarkupTemplate("""<html xmlns:xi="http://www.w3.org/2001/XInclude">
+              <xi:include href="tmpl1.html" />
+            </html>""", filename=os.path.join(self.dirname, 'tmpl2.html'))
+        self.assertEqual("""<html>
+              <div>Included</div>
+            </html>""", tmpl.generate().render(encoding=None))
+
     def test_relative_include_without_search_path_nested(self):
         file1 = open(os.path.join(self.dirname, 'tmpl1.html'), 'w')
         try:
Copyright (C) 2012-2017 Edgewall Software