[Checkins] SVN: z3c.jbot/trunk/z3c/jbot/ Layer specialization is now observed such that template overrides are looked up in order of specialization.

Malthe Borch mborch at gmail.com
Tue Jul 15 12:40:41 EDT 2008


Log message for revision 88383:
  Layer specialization is now observed such that template overrides are looked up in order of specialization.

Changed:
  U   z3c.jbot/trunk/z3c/jbot/Five.txt
  U   z3c.jbot/trunk/z3c/jbot/README.txt
  U   z3c.jbot/trunk/z3c/jbot/__init__.py
  U   z3c.jbot/trunk/z3c/jbot/manager.py
  U   z3c.jbot/trunk/z3c/jbot/metaconfigure.py
  U   z3c.jbot/trunk/z3c/jbot/utility.py

-=-
Modified: z3c.jbot/trunk/z3c/jbot/Five.txt
===================================================================
--- z3c.jbot/trunk/z3c/jbot/Five.txt	2008-07-15 14:17:55 UTC (rev 88382)
+++ z3c.jbot/trunk/z3c/jbot/Five.txt	2008-07-15 16:40:39 UTC (rev 88383)
@@ -49,7 +49,8 @@
   >>> from zope.publisher.interfaces.browser import IHTTPRequest
   >>> factory = z3c.jbot.manager.TemplateManagerFactory()
   >>> component.provideAdapter(
-  ...     factory, (IHTTPRequest,), z3c.jbot.interfaces.ITemplateManager)
+  ...     factory, (IHTTPRequest,),
+  ...     z3c.jbot.interfaces.ITemplateManager, name='http')
 
   >>> manager = factory.manager
   >>> manager.registerDirectory(directory)
@@ -74,10 +75,11 @@
   >>> import z3c.jbot.utility
   >>> z3c.jbot.utility.getRequest()
   <zope.publisher.browser.TestRequest ...>
-  
-  >>> z3c.jbot.utility.getManager() is manager
-  True
 
+  >>> managers = tuple(z3c.jbot.utility.getManagers())
+  >>> len(managers)
+  2
+
 Verify that template attributes are set per request layer.
 
   >>> view.template._v_last_read is not False

Modified: z3c.jbot/trunk/z3c/jbot/README.txt
===================================================================
--- z3c.jbot/trunk/z3c/jbot/README.txt	2008-07-15 14:17:55 UTC (rev 88382)
+++ z3c.jbot/trunk/z3c/jbot/README.txt	2008-07-15 16:40:39 UTC (rev 88383)
@@ -37,7 +37,8 @@
   >>> import z3c.jbot.interfaces
   >>> factory = z3c.jbot.manager.TemplateManagerFactory()
   >>> component.provideAdapter(
-  ...     factory, (interface.Interface,), z3c.jbot.interfaces.ITemplateManager)
+  ...     factory, (interface.Interface,),
+  ...     z3c.jbot.interfaces.ITemplateManager)
 
 Register overrides directory.
   
@@ -79,7 +80,8 @@
   >>> from zope.publisher.interfaces.browser import IHTTPRequest
   >>> factory = z3c.jbot.manager.TemplateManagerFactory()
   >>> component.provideAdapter(
-  ...     factory, (IHTTPRequest,), z3c.jbot.interfaces.ITemplateManager)
+  ...     factory, (IHTTPRequest,),
+  ...     z3c.jbot.interfaces.ITemplateManager, name='http')
 
 Register overrides directory.
   
@@ -122,21 +124,22 @@
 Let's verify that we only cook once per template source.
 
   >>> import z3c.jbot.utility
-  >>> z3c.jbot.utility.getManager().registerTemplate(template)
+  >>> output = template()
   >>> template._v_last_read and template._v_cooked
   1
 
   >>> interface.alsoProvides(request, IHTTPRequest)
-  >>> z3c.jbot.utility.getManager().registerTemplate(template)
+  >>> output = template()
   >>> template._v_last_read and template._v_cooked
   1
 
   >>> template()
   u'This template will override the example template.\n'
 
-  >>> z3c.jbot.utility.getManager().unregisterDirectory("%s/templates" % directory)
+  >>> for manager in z3c.jbot.utility.getManagers():
+  ...     manager.unregisterDirectory("%s/templates" % directory)
+  
   >>> interface.noLongerProvides(request, IHTTPRequest)
-  >>> z3c.jbot.utility.getManager().unregisterDirectory("%s/templates" % directory)
   
 Configuring template override directories in ZCML
 -------------------------------------------------
@@ -161,8 +164,21 @@
   >>> template()
   u'This template will override the example template.\n'
 
-  >>> z3c.jbot.utility.getManager().unregisterDirectory("%s/templates" % directory)
+Providing the HTTP-request layer does not change this.
 
+  >>> interface.alsoProvides(request, IHTTPRequest)
+
+  >>> template()
+  u'This template will override the example template.\n'
+
+Unregister overrides.
+  
+  >>> manager = tuple(z3c.jbot.utility.getManagers())[0]
+  >>> manager.unregisterDirectory("%s/templates" % directory)
+  
+  >>> template()
+  u'This is an example page template.\n'
+    
 Let's register overrides for the HTTP-request layer.
 
   >>> xmlconfig.xmlconfig(StringIO("""
@@ -173,11 +189,8 @@
   ... </configure>
   ... """ % directory))
 
-  >>> template()
-  u'This is an example page template.\n'
+If we now provide the HTTP-request layer, the override becomes active.
 
-If we now provide the HTTP-request layer, the override becomes active.
-  
-  >>> interface.alsoProvides(request, IHTTPRequest)
   >>> template()
   u'This template will override the example template.\n'
+

Modified: z3c.jbot/trunk/z3c/jbot/__init__.py
===================================================================
--- z3c.jbot/trunk/z3c/jbot/__init__.py	2008-07-15 14:17:55 UTC (rev 88382)
+++ z3c.jbot/trunk/z3c/jbot/__init__.py	2008-07-15 16:40:39 UTC (rev 88383)
@@ -1,13 +1,17 @@
 from zope.pagetemplate.pagetemplatefile import PageTemplateFile
 
-import manager
 import utility
+import logging
 
+logger = logging.getLogger('jbot')
+
 PT_CLASSES = [PageTemplateFile]
 
-if utility.ZOPE_2:
+try:
     import Products.PageTemplates.PageTemplateFile
     PT_CLASSES.append(Products.PageTemplates.PageTemplateFile.PageTemplateFile)
+except:
+    pass
 
 class LayerProperty(property):
     """Layer-specific property class.
@@ -54,18 +58,23 @@
 # registration hook to template manager
 def jbot(func):
     def patch(self, *args, **kwargs):
-        manager = utility.getManager()
-        if manager is not None:
-            manager.registerTemplate(self)
-        
+        for manager in utility.getManagers():
+            # register template; this call returns ``True`` if
+            # template was invalidated
+            if manager.registerTemplate(self):
+                break
+            
         return func(self, *args, **kwargs)        
     return patch
 
+logger.info("Patching page template classes...")
+
+# patch ``_cook_check``-method to insert jbot-logic
 for pt_class in PT_CLASSES:
-    # patch ``_cook_check``-method to insert jbot-logic
     pt_class._cook_check = jbot(pt_class._cook_check)
 
-    # munge per-layer attribute descriptors on class
+# munge per-layer attribute descriptors on class
+for pt_class in PT_CLASSES:
     for name in ('_v_macros', '_v_program', '_v_cooked', '_v_errors',
                  '_v_last_read', '_v_warning', '_text_',
                  'filename', 'content_type', 'is_html'):

Modified: z3c.jbot/trunk/z3c/jbot/manager.py
===================================================================
--- z3c.jbot/trunk/z3c/jbot/manager.py	2008-07-15 14:17:55 UTC (rev 88382)
+++ z3c.jbot/trunk/z3c/jbot/manager.py	2008-07-15 16:40:39 UTC (rev 88383)
@@ -1,8 +1,9 @@
 from zope import interface
 
+import os
 import sys
-import os.path
 
+import utility
 import interfaces
 
 IGNORE = object()
@@ -70,8 +71,9 @@
                 del self.paths[filename]
 
         for template in templates:
-            template._v_last_read = False
-        
+            self.registerTemplate(template)
+            del self.templates[template]
+            
     def registerTemplate(self, template):
         # only register templates that have a filename attribute
         if not hasattr(template, 'filename'):
@@ -116,3 +118,5 @@
 
         # force cook
         template._v_last_read = False
+
+        return True

Modified: z3c.jbot/trunk/z3c/jbot/metaconfigure.py
===================================================================
--- z3c.jbot/trunk/z3c/jbot/metaconfigure.py	2008-07-15 14:17:55 UTC (rev 88382)
+++ z3c.jbot/trunk/z3c/jbot/metaconfigure.py	2008-07-15 16:40:39 UTC (rev 88383)
@@ -8,14 +8,26 @@
     gsm = component.getGlobalSiteManager()
 
     # check if a template manager already exists
-    factory = gsm.adapters.lookup((layer,), interfaces.ITemplateManager)
+    factories = set(factory for name, factory in gsm.adapters.lookupAll(
+        (layer,), interfaces.ITemplateManager))
 
-    if factory is None:
+    # if factory is available on the interface bases of the layer we
+    # discard it and register a new manager specialized to the layer
+    if layer is interface.Interface:
+        base_factories = set()
+    else:
+        base_factories = set(factory for name, factory in gsm.adapters.lookupAll(
+            (interface.implementedBy(layer.__bases__),), interfaces.ITemplateManager))
+
+    try:
+        factory = factories.difference(base_factories).pop()
+    except KeyError:
         factory = manager.TemplateManagerFactory()
-        component.provideAdapter(factory, (layer,), interfaces.ITemplateManager)
+        component.provideAdapter(
+            factory, (layer,), interfaces.ITemplateManager, name=directory)
 
-    factory.manager.registerDirectory(directory)
-
+    factory(layer).registerDirectory(directory)
+    
 def templateOverridesDirective(_context, directory, layer=interface.Interface):
     _context.action(
         discriminator = ('override', directory, layer),

Modified: z3c.jbot/trunk/z3c/jbot/utility.py
===================================================================
--- z3c.jbot/trunk/z3c/jbot/utility.py	2008-07-15 14:17:55 UTC (rev 88382)
+++ z3c.jbot/trunk/z3c/jbot/utility.py	2008-07-15 16:40:39 UTC (rev 88383)
@@ -10,26 +10,27 @@
 import interfaces
 
 try:
-    import Products.PageTemplates
+    import Acquisition
     ZOPE_2 = True
-except ImportError:
+except:
     ZOPE_2 = False
 
 def getRequest():
-    try:
-        i = zope.security.management.getInteraction()
-        for p in i.participations:
-            if IRequest.providedBy(p):
-                return p
-    except zope.security.interfaces.NoInteraction:
-        pass
-    
     if ZOPE_2:
         # get request by acquisition
         site = getSite()
         if site is not None:
             return site.REQUEST
-    
+
+    try:
+        i = zope.security.management.getInteraction()
+    except zope.security.interfaces.NoInteraction:
+        return
+
+    for p in i.participations:
+        if IRequest.providedBy(p):
+            return p
+
 def getLayer():
     request = getRequest()
 
@@ -38,10 +39,9 @@
 
     return interface.Interface
 
-def getManager():
+def getManagers():
     layer = getLayer()
     gsm = component.getGlobalSiteManager()
         
-    factory = gsm.adapters.lookup((layer,), interfaces.ITemplateManager)
-    if factory is not None:
-        return factory.manager
+    for name, factory in gsm.adapters.lookupAll((layer,), interfaces.ITemplateManager):
+        yield factory(layer)



More information about the Checkins mailing list