[Checkins] SVN: z3c.jbot/ Initial import.

Malthe Borch mborch at gmail.com
Tue Nov 27 18:17:59 EST 2007


Log message for revision 81997:
  Initial import.

Changed:
  A   z3c.jbot/
  A   z3c.jbot/branches/
  A   z3c.jbot/tags/
  A   z3c.jbot/trunk/
  A   z3c.jbot/trunk/README.txt
  A   z3c.jbot/trunk/setup.py
  A   z3c.jbot/trunk/z3c/
  A   z3c.jbot/trunk/z3c/__init__.py
  A   z3c.jbot/trunk/z3c/jbot/
  A   z3c.jbot/trunk/z3c/jbot/Five.txt
  A   z3c.jbot/trunk/z3c/jbot/README.txt
  A   z3c.jbot/trunk/z3c/jbot/__init__.py
  A   z3c.jbot/trunk/z3c/jbot/manager.py
  A   z3c.jbot/trunk/z3c/jbot/meta.zcml
  A   z3c.jbot/trunk/z3c/jbot/metaconfigure.py
  A   z3c.jbot/trunk/z3c/jbot/metadirectives.py
  A   z3c.jbot/trunk/z3c/jbot/tests/
  A   z3c.jbot/trunk/z3c/jbot/tests/__init__.py
  A   z3c.jbot/trunk/z3c/jbot/tests/templates/
  A   z3c.jbot/trunk/z3c/jbot/tests/templates/example.pt
  A   z3c.jbot/trunk/z3c/jbot/tests/templates/z3c.jbot.tests.templates.example.pt
  A   z3c.jbot/trunk/z3c/jbot/tests/test_doctests.py

-=-
Added: z3c.jbot/trunk/README.txt
===================================================================
--- z3c.jbot/trunk/README.txt	                        (rev 0)
+++ z3c.jbot/trunk/README.txt	2007-11-27 23:17:59 UTC (rev 81997)
@@ -0,0 +1,36 @@
+Overview
+--------
+
+The z3c.jbot (or "Just a bunch of templates") package allows drop-in
+page template overrides.
+
+It works by giving page templates a canonical filename which you can
+use to provide a replacement in your own package. Simply register a
+template overrides directory and give your new template the canonical
+filename.
+
+Canonical filename
+------------------
+
+The canonical filename is defined as the path relative to the package
+within which the template is located with directory separators
+replaced with dots.
+
+Example:
+
+  Suppose you want to override: /plone/app/layout/viewlets/logo.pt
+  You would use the filename:   plone.app.layout.viewlets.logo.pt
+
+Registering a on overrides directory
+------------------------------------
+
+In python:
+
+  >>> from z3c.jbot.manager import getGlobalTemplateManager
+  >>> getGlobalTemplateManager().registerDirectory(directory)
+
+In ZCML:
+
+  <include package="z3c.jbot" file="meta.zcml" />
+  <browser:templateOverrides directory="<directory>" />
+  

Added: z3c.jbot/trunk/setup.py
===================================================================
--- z3c.jbot/trunk/setup.py	                        (rev 0)
+++ z3c.jbot/trunk/setup.py	2007-11-27 23:17:59 UTC (rev 81997)
@@ -0,0 +1,32 @@
+from setuptools import setup, find_packages
+import sys, os
+
+version = '0.1'
+
+setup(name='z3c.jbot',
+      version=version,
+      description="Drop-in template overrides.",
+      long_description=open("README.txt").read(),
+      classifiers=[
+        "Framework :: Zope2",
+        "Framework :: Zope3",
+        "Programming Language :: Python",
+        "Topic :: Software Development :: Libraries :: Python Modules",
+        ],
+      keywords='page template override',
+      author='Malthe Borch',
+      author_email='mborch at gmail.com',
+      url='',
+      license='ZPL',
+      packages=find_packages(exclude=['ez_setup']),
+      namespace_packages=['z3c'],
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+          'setuptools',
+          # -*- Extra requirements: -*-
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )

Added: z3c.jbot/trunk/z3c/__init__.py
===================================================================
--- z3c.jbot/trunk/z3c/__init__.py	                        (rev 0)
+++ z3c.jbot/trunk/z3c/__init__.py	2007-11-27 23:17:59 UTC (rev 81997)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

Added: z3c.jbot/trunk/z3c/jbot/Five.txt
===================================================================
--- z3c.jbot/trunk/z3c/jbot/Five.txt	                        (rev 0)
+++ z3c.jbot/trunk/z3c/jbot/Five.txt	2007-11-27 23:17:59 UTC (rev 81997)
@@ -0,0 +1,37 @@
+Five compatibility tests
+========================
+
+Let's instantiate a Five page template.
+
+  >>> from Products.Five.browser.pagetemplatefile import ZopeTwoPageTemplateFile
+
+  >>> import z3c.jbot.tests
+  >>> directory = z3c.jbot.tests.__path__[0] + "/templates"
+
+To play nicely we'll put the template inside a view.
+  
+  >>> from Products.Five.browser import BrowserView
+  >>> class MockView(BrowserView):
+  ...     template = ZopeTwoPageTemplateFile("example.pt", _prefix=directory)
+
+Let's instantiate the view with a test request.
+  
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest("en")  
+  >>> view = MockView(None, request)
+
+Verify that the original template is rendered.
+  
+  >>> view.template()
+  u'This is an example page template.\n'
+
+Register template overrides directory.
+  
+  >>> import z3c.jbot.manager
+  >>> manager = z3c.jbot.manager.getGlobalTemplateManager()
+  >>> manager.registerDirectory(directory)
+
+Verify that the override is rendered.
+  
+  >>> view.template()
+  u'This template will override the example template.\n'

Added: z3c.jbot/trunk/z3c/jbot/README.txt
===================================================================
--- z3c.jbot/trunk/z3c/jbot/README.txt	                        (rev 0)
+++ z3c.jbot/trunk/z3c/jbot/README.txt	2007-11-27 23:17:59 UTC (rev 81997)
@@ -0,0 +1,89 @@
+z3c.jbot
+========
+
+The z3c.jbot (or "Just a bunch of templates") package allows drop-in
+page template overrides.
+
+Registration
+------------
+
+Let's instantiate a page template
+
+  >>> from zope.pagetemplate.pagetemplatefile import PageTemplateFile
+  >>> template = PageTemplateFile("tests/templates/example.pt")
+  
+A call to the template will render it.
+
+  >>> template()
+  u'This is an example page template.\n'
+
+Providing a template override
+-----------------------------
+
+We use the global template manager to register and unregister new
+template override directories.
+
+If we register the directory where it's placed with the global template
+manager, it will be used when rendering this template object instead
+of the original filename.
+
+  >>> import z3c.jbot.tests
+  >>> directory = z3c.jbot.tests.__path__[0]
+
+  >>> import z3c.jbot.manager
+  >>> manager = z3c.jbot.manager.getGlobalTemplateManager()
+  >>> manager.registerDirectory("%s/templates" % directory)
+
+Verify that we've registered the contents of the directory:
+
+  >>> manager.paths
+  {'z3c.jbot.tests.templates.example.pt': '.../z3c.jbot.tests.templates.example.pt',
+   'example.pt': '.../example.pt'}
+  
+Notice that the file "z3c.jbot.tests.templates.example.pt" is the
+dotted name for the original example page template file.
+
+We should now see that the new filename will be used for rendering:
+
+  >>> template()
+  u'This template will override the example template.\n'
+
+Before we proceed we'll clean up.
+
+  >>> manager.unregisterDirectory("%s/templates" % directory)
+
+The template does indeed render the original template.
+  
+  >>> template()
+  u'This is an example page template.\n'
+
+Upon rendering, the global template manager will have reverted the
+template filename to the original.
+
+  >>> template.filename
+  '.../z3c.jbot/z3c/jbot/tests/templates/example.pt'
+
+Configuring template override directories in ZCML
+-------------------------------------------------
+
+First we load the metadirectives of the package. This will allow us
+to register template overrides directories in configuration files.
+
+  >>> from cStringIO import StringIO
+  >>> from zope.configuration import xmlconfig
+  >>> xmlconfig.XMLConfig('meta.zcml', z3c.jbot)()
+
+Let's try registering the directory again.
+
+  >>> xmlconfig.xmlconfig(StringIO("""
+  ... <configure xmlns="http://namespaces.zope.org/browser">
+  ... <templateOverrides directory="%s/templates" />
+  ... </configure>
+  ... """ % directory))
+
+Once again, the override will be in effect.
+  
+  >>> template()
+  u'This template will override the example template.\n'
+
+  >>> manager.unregisterDirectory("%s/templates" % directory)

Added: z3c.jbot/trunk/z3c/jbot/__init__.py
===================================================================
--- z3c.jbot/trunk/z3c/jbot/__init__.py	                        (rev 0)
+++ z3c.jbot/trunk/z3c/jbot/__init__.py	2007-11-27 23:17:59 UTC (rev 81997)
@@ -0,0 +1,10 @@
+import manager
+from zope.pagetemplate.pagetemplatefile import PageTemplate
+
+# add registration hook to ``zope.app.pagetemplate``
+pt_render = PageTemplate.pt_render
+def patched_pt_render(self, *args, **kwargs):
+    manager.getGlobalTemplateManager().registerTemplate(self)
+    return pt_render(self, *args, **kwargs)
+
+PageTemplate.pt_render = patched_pt_render

Added: z3c.jbot/trunk/z3c/jbot/manager.py
===================================================================
--- z3c.jbot/trunk/z3c/jbot/manager.py	                        (rev 0)
+++ z3c.jbot/trunk/z3c/jbot/manager.py	2007-11-27 23:17:59 UTC (rev 81997)
@@ -0,0 +1,71 @@
+import sys
+import os.path
+
+def root_length(a, b):
+    if b.startswith(a):
+        return len(a)
+    else:
+        return 0
+
+def find_package(path):
+    # find out in which package this file is located
+    syspaths = sys.path
+    syspaths.sort(key=lambda syspath: root_length(syspath, path),
+                  reverse=True)
+        
+    path = path[len(syspaths[0]):]
+
+    # convert path to dotted filename
+    if path.startswith(os.path.sep):
+        path = path[1:]
+
+    return path
+    
+class GlobalTemplateManager(object):
+    def __init__(self):
+        self.templates = {}
+        self.paths = {}
+        
+    def registerDirectory(self, directory):
+        for filename in os.listdir(directory):
+            if filename.endswith('.pt'):
+                self.paths[filename] = "%s/%s" % (directory, filename)
+
+    def unregisterDirectory(self, directory):
+        for filename in os.listdir(directory):
+            if filename in self.paths:
+                del self.paths[filename]
+        
+    def registerTemplate(self, template):
+        # only register templates that have a filename attribute
+        if not hasattr(template, 'filename'):
+            return
+        
+        # assert that template is not already registered
+        filename = self.templates.get(template)
+        if self.paths.get(filename) == template.filename:
+            return
+
+        if filename and filename not in self.paths:
+            # template file has been unregistered; restore
+            # original template
+            template.filename = template._filename
+            delattr(template, '_filename')
+                        
+        path = find_package(template.filename)
+        filename = path.replace(os.path.sep, '.')
+
+        if filename in self.paths:
+            path = self.paths[filename]
+            
+            # save original filename
+            template._filename = template.filename
+
+            # save template and registry and assign path
+            template.filename = path
+            self.templates[template] = filename
+            
+GlobalTemplateManager = GlobalTemplateManager()
+
+def getGlobalTemplateManager():
+    return GlobalTemplateManager

Added: z3c.jbot/trunk/z3c/jbot/meta.zcml
===================================================================
--- z3c.jbot/trunk/z3c/jbot/meta.zcml	                        (rev 0)
+++ z3c.jbot/trunk/z3c/jbot/meta.zcml	2007-11-27 23:17:59 UTC (rev 81997)
@@ -0,0 +1,15 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:meta="http://namespaces.zope.org/meta">
+
+    <meta:directives namespace="http://namespaces.zope.org/browser">
+        
+      <meta:directive
+         name="templateOverrides"
+         schema=".metadirectives.ITemplateOverridesDirective"
+         handler=".metaconfigure.templateOverridesDirective"
+         />
+                   
+    </meta:directives>
+           
+</configure>

Added: z3c.jbot/trunk/z3c/jbot/metaconfigure.py
===================================================================
--- z3c.jbot/trunk/z3c/jbot/metaconfigure.py	                        (rev 0)
+++ z3c.jbot/trunk/z3c/jbot/metaconfigure.py	2007-11-27 23:17:59 UTC (rev 81997)
@@ -0,0 +1,5 @@
+from zope import component
+from z3c.jbot.manager import getGlobalTemplateManager
+
+def templateOverridesDirective(_context, directory):
+    getGlobalTemplateManager().registerDirectory(directory)

Added: z3c.jbot/trunk/z3c/jbot/metadirectives.py
===================================================================
--- z3c.jbot/trunk/z3c/jbot/metadirectives.py	                        (rev 0)
+++ z3c.jbot/trunk/z3c/jbot/metadirectives.py	2007-11-27 23:17:59 UTC (rev 81997)
@@ -0,0 +1,11 @@
+from zope.interface import Interface
+from zope.configuration import fields
+
+from Products.CMFPlone import PloneMessageFactory as _
+
+class ITemplateOverridesDirective(Interface):
+    """Directive which registers a directory with template overrides."""
+
+    directory = fields.Path(title=_(u"Path to directory"),
+                            required=True)
+

Added: z3c.jbot/trunk/z3c/jbot/tests/__init__.py
===================================================================

Added: z3c.jbot/trunk/z3c/jbot/tests/templates/example.pt
===================================================================
--- z3c.jbot/trunk/z3c/jbot/tests/templates/example.pt	                        (rev 0)
+++ z3c.jbot/trunk/z3c/jbot/tests/templates/example.pt	2007-11-27 23:17:59 UTC (rev 81997)
@@ -0,0 +1 @@
+This is an <span tal:replace="string:example" /> page template.

Added: z3c.jbot/trunk/z3c/jbot/tests/templates/z3c.jbot.tests.templates.example.pt
===================================================================
--- z3c.jbot/trunk/z3c/jbot/tests/templates/z3c.jbot.tests.templates.example.pt	                        (rev 0)
+++ z3c.jbot/trunk/z3c/jbot/tests/templates/z3c.jbot.tests.templates.example.pt	2007-11-27 23:17:59 UTC (rev 81997)
@@ -0,0 +1 @@
+This template will override the example template.

Added: z3c.jbot/trunk/z3c/jbot/tests/test_doctests.py
===================================================================
--- z3c.jbot/trunk/z3c/jbot/tests/test_doctests.py	                        (rev 0)
+++ z3c.jbot/trunk/z3c/jbot/tests/test_doctests.py	2007-11-27 23:17:59 UTC (rev 81997)
@@ -0,0 +1,28 @@
+import zope.testing
+import unittest
+
+OPTIONFLAGS = (zope.testing.doctest.REPORT_ONLY_FIRST_FAILURE |
+               zope.testing.doctest.ELLIPSIS |
+               zope.testing.doctest.NORMALIZE_WHITESPACE)
+
+import zope.component.testing
+
+def test_suite():
+    doctests = ['README.txt']
+
+    try:
+        import Products.Five
+        doctests.append('Five.txt')
+    except:
+        pass
+    
+    return unittest.TestSuite((
+        zope.testing.doctest.DocFileSuite(doctest,
+                                          optionflags=OPTIONFLAGS,
+                                          setUp=zope.component.testing.setUp,
+                                          tearDown=zope.component.testing.tearDown,
+                                          package="z3c.jbot") for doctest in doctests
+        ))
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')



More information about the Checkins mailing list