[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