[Checkins] SVN: CompositePage/trunk/ - Fixed test failures caused by 7 years of changes to Zope. This mostly

Shane Hathaway shane at hathawaymix.org
Mon Apr 11 19:46:04 EDT 2011


Log message for revision 121402:
  - Fixed test failures caused by 7 years of changes to Zope.  This mostly
    involved simple modernization:
  
      - Use zope.interface, zope.tales, and zope.pagetemplate rather than
        their predecessors.
  
      - Use absolute imports.
  
      - Use Unicode where possible.
  
  - Let's stop swallowing errors that occur when rendering the template
    to get the list of slots.  Error messages are friendlier than silent
    breakage.
  
  

Changed:
  U   CompositePage/trunk/CHANGES.txt
  U   CompositePage/trunk/composite.py
  U   CompositePage/trunk/designuis.py
  U   CompositePage/trunk/element.py
  U   CompositePage/trunk/interfaces.py
  U   CompositePage/trunk/perm_names.py
  U   CompositePage/trunk/slot.py
  U   CompositePage/trunk/slotclass.py
  U   CompositePage/trunk/slotexpr.py
  U   CompositePage/trunk/tests/test_composite.py
  U   CompositePage/trunk/tests/test_tool.py
  U   CompositePage/trunk/tool.py
  U   CompositePage/trunk/utils.py

-=-
Modified: CompositePage/trunk/CHANGES.txt
===================================================================
--- CompositePage/trunk/CHANGES.txt	2011-04-11 21:45:02 UTC (rev 121401)
+++ CompositePage/trunk/CHANGES.txt	2011-04-11 23:46:03 UTC (rev 121402)
@@ -1,9 +1,27 @@
-After Version 0.2
-  - allow to subclass rendering of target
-    change order of targets rendering
+Next Release
+------------
 
-Version 0.2
+- Fixed test failures caused by 7 years of changes to Zope.  This mostly
+  involved simple modernization:
 
+    - Use zope.interface, zope.tales, and zope.pagetemplate rather than
+      their predecessors.
+
+    - Use absolute imports.
+
+    - Use Unicode where possible.
+
+- Let's stop swallowing errors that occur when rendering the template
+  to get the list of slots.  Error messages are friendlier than silent
+  breakage.
+
+- Slots now show the add element interface only at the top and bottom
+  of the slot, not between elements.  (Hmm, should this be configurable?)
+
+
+0.2 (2004-06-16)
+----------------
+
   - Changed the UI to use images for elements and targets.
 
   - Added inline views.  You can now select templates to render objects.

Modified: CompositePage/trunk/composite.py
===================================================================
--- CompositePage/trunk/composite.py	2011-04-11 21:45:02 UTC (rev 121401)
+++ CompositePage/trunk/composite.py	2011-04-11 23:46:03 UTC (rev 121402)
@@ -20,22 +20,32 @@
 
 import Globals
 import Acquisition
-from Acquisition import aq_base, aq_inner, aq_parent, aq_get
+from Acquisition import aq_base
+from Acquisition import aq_inner
+from Acquisition import aq_parent
+from Acquisition import aq_get
 from OFS.Folder import Folder
 from OFS.SimpleItem import SimpleItem
-from Products.PageTemplates.PageTemplateFile import PageTemplateFile
 from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
 from AccessControl import ClassSecurityInfo
 from AccessControl.ZopeGuards import guarded_getattr
+from zope.interface import implements
+from zope.pagetemplate.pagetemplatefile import PageTemplateFile
 
-from interfaces import IComposite, ISlot, ISlotGenerator, CompositeError
-from slot import Slot, getIconURL, formatException
-import perm_names
+from Products.CompositePage.interfaces import IComposite
+from Products.CompositePage.interfaces import ISlot
+from Products.CompositePage.interfaces import ISlotGenerator
+from Products.CompositePage.interfaces import CompositeError
+from Products.CompositePage.slot import Slot
+from Products.CompositePage.slot import getIconURL
+from Products.CompositePage.slot import formatException
+from Products.CompositePage.perm_names import view_perm
+from Products.CompositePage.perm_names import change_composites_perm
 
 _www = os.path.join(os.path.dirname(__file__), "www")
 
 
-class SlotGenerator (Acquisition.Explicit):
+class SlotGenerator(Acquisition.Explicit):
     """Automatically makes slots available to the template.
 
     Note: instances of this class are shared across threads.
@@ -49,12 +59,13 @@
         template.  Assigns attributes (class_name and title) to the
         slot at the same time.
         """
+        name = str(name)
         composite = aq_parent(aq_inner(self))
         composite._usingSlot(name, class_name, title)
         slots = composite.filled_slots
-        try:
+        if slots.hasObject(name):
             return slots[name]
-        except (KeyError, AttributeError):
+        else:
             # Generate a new slot.
             s = self._slot_class(name)
             if composite.isEditing():
@@ -73,8 +84,8 @@
     elements.  This base class provides the nuts and bolts of a
     composite editing interface.
     """
+    implements(IComposite)
     meta_type = "Composite"
-    __implements__ = IComposite
 
     security = ClassSecurityInfo()
 
@@ -87,7 +98,6 @@
     template_path = "template"
     _v_editing = 0
     _v_rendering = 0
-    _v_generating = 0
     _v_slot_specs = None  # [{'name', 'class', 'title'}]
 
     security.declarePublic("slots")
@@ -98,19 +108,19 @@
          "label": "Path to template"},
         )
 
-    security.declareProtected(perm_names.view, "hasTemplate")
+    security.declareProtected(view_perm, "hasTemplate")
     def hasTemplate(self):
         if self.template_path:
             return 1
         return 0
 
-    security.declareProtected(perm_names.view, "getTemplate")
+    security.declareProtected(view_perm, "getTemplate")
     def getTemplate(self):
         if not self.template_path:
             raise CompositeError("No template set")
         return self.restrictedTraverse(str(self.template_path))
 
-    security.declareProtected(perm_names.change_composites, "generateSlots")
+    security.declareProtected(change_composites_perm, "generateSlots")
     def generateSlots(self):
         """Creates the slots defined by the template.
         """
@@ -120,7 +130,7 @@
         finally:
             self._v_editing = 0
 
-    security.declareProtected(perm_names.view, "__call__")
+    security.declareProtected(view_perm, "__call__")
     def __call__(self):
         """Renders the composite.
         """
@@ -137,7 +147,7 @@
 
     index_html = None
 
-    security.declareProtected(perm_names.change_composites, "design")
+    security.declareProtected(change_composites_perm, "design")
     def design(self, ui=None):
         """Renders the composite with editing features.
         """
@@ -152,14 +162,13 @@
         finally:
             self._v_editing = 0
 
-    security.declareProtected(perm_names.change_composites,
-                              "manage_designForm")
+    security.declareProtected(change_composites_perm, "manage_designForm")
     def manage_designForm(self):
         """Renders the composite with editing and ZMI features.
         """
         return self.design("zmi")
 
-    security.declareProtected(perm_names.change_composites, "getUI")
+    security.declareProtected(change_composites_perm, "getUI")
     def getUI(self, ui=None):
         """Returns a UI object.
         """
@@ -186,7 +195,7 @@
                 'title': title,
                 })
 
-    security.declareProtected(perm_names.change_composites, "getSlotSpecs")
+    security.declareProtected(change_composites_perm, "getSlotSpecs")
     def getSlotSpecs(self):
         """Returns the slot specs within the template.
 
@@ -196,13 +205,13 @@
         self._v_slot_specs = []
         try:
             self()
+            slots = self._v_slot_specs
+            return slots
         finally:
             self._v_editing = 0
-            slots = self._v_slot_specs
             self._v_slot_specs = None
-            return slots
 
-    security.declareProtected(perm_names.change_composites, "getSlotClassName")
+    security.declareProtected(change_composites_perm, "getSlotClassName")
     def getSlotClassName(self, slot_name):
         """Returns the class_name of a slot.
 
@@ -215,7 +224,7 @@
                 return spec['class_name']
         raise KeyError(slot_name)
 
-    security.declareProtected(perm_names.change_composites, "getManifest")
+    security.declareProtected(change_composites_perm, "getManifest")
     def getManifest(self):
         """Returns a manifest of slot contents.
 
@@ -228,9 +237,9 @@
         if hasattr(self, 'portal_url'):
             icon_base_url = self.portal_url()
         else:
-            REQUEST = getattr(self, 'REQUEST', None)
-            if REQUEST is not None:
-                icon_base_url = self.REQUEST['BASEPATH1']
+            request = getattr(self, 'REQUEST', None)
+            if request is not None:
+                icon_base_url = request['BASEPATH1']
             else:
                 icon_base_url = ''
         for spec in specs:
@@ -287,7 +296,7 @@
             contents.append(slot_info)
         return contents
 
-    security.declareProtected(perm_names.view, "isEditing")
+    security.declareProtected(view_perm, "isEditing")
     def isEditing(self):
         """Returns true if currently rendering in design mode.
         """
@@ -334,7 +343,7 @@
     title = 'Error'
 
 
-addCompositeForm = PageTemplateFile("addCompositeForm", _www)
+addCompositeForm = PageTemplateFile("addCompositeForm.zpt", _www)
 
 def manage_addComposite(dispatcher, id, title="", create_sample="",
                         REQUEST=None):
@@ -342,7 +351,7 @@
     """
     ob = Composite()
     ob._setId(id)
-    ob.title = string(title)
+    ob.title = unicode(title)
     dispatcher._setObject(ob.getId(), ob)
     if create_sample:
         ob = dispatcher.this()._getOb(ob.getId())
@@ -356,13 +365,3 @@
         ob._setObject(pt.getId(), pt)
     if REQUEST is not None:
         return dispatcher.manage_main(dispatcher, REQUEST)
-
-
-def string(s):
-    """Ensures an object is either a string or a unicode.
-    """
-    try:
-        return str(s)
-    except UnicodeEncodeError:
-        return unicode(s)
-

Modified: CompositePage/trunk/designuis.py
===================================================================
--- CompositePage/trunk/designuis.py	2011-04-11 21:45:02 UTC (rev 121401)
+++ CompositePage/trunk/designuis.py	2011-04-11 23:46:03 UTC (rev 121402)
@@ -22,12 +22,13 @@
 import Globals
 from Acquisition import aq_base, aq_inner, aq_parent
 from OFS.SimpleItem import SimpleItem
-from Products.PageTemplates.PageTemplateFile import PageTemplateFile
+from zope.pagetemplate.pagetemplatefile import PageTemplateFile
 from AccessControl import ClassSecurityInfo
 from AccessControl.ZopeGuards import guarded_getattr
 
-from rawfile import RawFile, InterpolatedFile
-from interfaces import ICompositeElement
+from Products.CompositePage.rawfile import RawFile
+from Products.CompositePage.rawfile import InterpolatedFile
+from Products.CompositePage.interfaces import ICompositeElement
 
 
 _common = os.path.join(os.path.dirname(__file__), "common")
@@ -58,7 +59,7 @@
 </html>
 '''
 
-class CommonUI (SimpleItem):
+class CommonUI(SimpleItem):
     """Basic page design UI.
 
     Adds editing features to a rendered composite.
@@ -148,7 +149,7 @@
         """
         root = self.getPhysicalRoot()
         obj = root.restrictedTraverse(path)
-        if ICompositeElement.isImplementedBy(obj):
+        if ICompositeElement.providedBy(obj):
             obj = obj.dereference()
         RESPONSE.redirect("%s/%s" % (
             obj.absolute_url(), self.workspace_view_name))
@@ -160,7 +161,7 @@
         """
         root = self.getPhysicalRoot()
         obj = root.restrictedTraverse(path)
-        if ICompositeElement.isImplementedBy(obj):
+        if ICompositeElement.providedBy(obj):
             obj = obj.dereference()
         RESPONSE.redirect(obj.absolute_url())
 
@@ -175,11 +176,7 @@
         parts = str(path).split('/')
         for name in parts:
             obj = obj.restrictedTraverse(name)
-            try:
-                is_comp = isinstance(obj, Composite)
-            except TypeError:
-                is_comp = 0  # Python 2.1 bug
-            if is_comp:
+            if IComposite.providedBy(obj):
                 gen = guarded_getattr(obj, "generateSlots")
                 gen()
         RESPONSE.redirect("%s/%s" % (
@@ -198,7 +195,7 @@
         for path in str(paths).split(':'):
             ob = root.unrestrictedTraverse(path)
             obs.append(ob)
-            if not ICompositeElement.isImplementedBy(ob):
+            if not ICompositeElement.providedBy(ob):
                 raise ValueError("Not a composite element: %s" % path)
             m = guarded_getattr(ob, "queryInlineTemplate")
             template = m()
@@ -236,7 +233,7 @@
             raise KeyError("Template %s is not among the choices" % template)
         tool = aq_parent(aq_inner(self))
         for ob in info["obs"]:
-            assert ICompositeElement.isImplementedBy(ob)
+            assert ICompositeElement.providedBy(ob)
             m = guarded_getattr(ob, "setInlineTemplate")
             m(template)
         if REQUEST is not None:

Modified: CompositePage/trunk/element.py
===================================================================
--- CompositePage/trunk/element.py	2011-04-11 21:45:02 UTC (rev 121401)
+++ CompositePage/trunk/element.py	2011-04-11 23:46:03 UTC (rev 121402)
@@ -23,19 +23,20 @@
 from OFS.SimpleItem import SimpleItem
 from OFS.PropertyManager import PropertyManager
 from DocumentTemplate.DT_Util import safe_callable
-from Products.PageTemplates.PageTemplateFile import PageTemplateFile
+from zope.pagetemplate.pagetemplatefile import PageTemplateFile
+from zope.interface import implements
 
-from interfaces import ICompositeElement
+from Products.CompositePage.interfaces import ICompositeElement
 
 _www = os.path.join(os.path.dirname(__file__), "www")
 
 
-class CompositeElement (SimpleItem, PropertyManager):
+class CompositeElement(SimpleItem, PropertyManager):
     """A simple path-based reference to an object and a template.
 
     You can render it and choose which template to apply for rendering.
     """
-    __implements__ = ICompositeElement
+    implements(ICompositeElement)
     meta_type = "Composite Element"
     security = ClassSecurityInfo()
     manage_options = PropertyManager.manage_options + SimpleItem.manage_options
@@ -72,7 +73,7 @@
         # Special template name "call" means to call the object.
         if safe_callable(obj):
             return obj()
-        return str(obj)
+        return unicode(obj)
 
     def queryInlineTemplate(self, slot_class_name=None):
         """Returns the name of the inline template this object uses.
@@ -100,7 +101,7 @@
 Globals.InitializeClass(CompositeElement)
 
 
-addElementForm = PageTemplateFile("addElementForm", _www)
+addElementForm = PageTemplateFile("addElementForm.zpt", _www)
 
 def manage_addElement(dispatcher, id, path, template_name=None, REQUEST=None):
     """Adds an element to a slot.

Modified: CompositePage/trunk/interfaces.py
===================================================================
--- CompositePage/trunk/interfaces.py	2011-04-11 21:45:02 UTC (rev 121401)
+++ CompositePage/trunk/interfaces.py	2011-04-11 23:46:03 UTC (rev 121402)
@@ -15,9 +15,10 @@
 $Id: interfaces.py,v 1.14 2004/04/15 22:13:44 shane Exp $
 """
 
-from Interface import Interface
-from Interface.Attribute import Attribute
+from zope.interface import Attribute
+from zope.interface import Interface
 
+
 class CompositeError(Exception):
     """An error in constructing a composite
     """

Modified: CompositePage/trunk/perm_names.py
===================================================================
--- CompositePage/trunk/perm_names.py	2011-04-11 21:45:02 UTC (rev 121401)
+++ CompositePage/trunk/perm_names.py	2011-04-11 23:46:03 UTC (rev 121402)
@@ -16,6 +16,6 @@
 $Id: perm_names.py,v 1.1 2003/10/01 18:59:31 shane Exp $
 """
 
-change_composites = "Change Composites"
-view = "View"
+change_composites_perm = "Change Composites"
+view_perm = "View"
 

Modified: CompositePage/trunk/slot.py
===================================================================
--- CompositePage/trunk/slot.py	2011-04-11 21:45:02 UTC (rev 121401)
+++ CompositePage/trunk/slot.py	2011-04-11 23:46:03 UTC (rev 121402)
@@ -21,14 +21,21 @@
 from cgi import escape
 
 import Globals
-from Acquisition import aq_base, aq_inner, aq_parent, aq_get
+from Acquisition import aq_base
+from Acquisition import aq_inner
+from Acquisition import aq_parent
+from Acquisition import aq_get
 from ZODB.POSException import ConflictError
 from OFS.SimpleItem import SimpleItem
-from Products.PageTemplates.PageTemplateFile import PageTemplateFile
+from zope.pagetemplate.pagetemplatefile import PageTemplateFile
 from AccessControl import ClassSecurityInfo
 from zLOG import LOG, ERROR
+from zope.interface import implements
 
-from interfaces import ICompositeElement
+from Products.CompositePage.interfaces import ICompositeElement
+from Products.CompositePage.interfaces import ISlot
+from Products.CompositePage.perm_names import view_perm
+from Products.CompositePage.perm_names import change_composites_perm
 
 
 try:
@@ -38,9 +45,6 @@
     # Fall back to normal folders, which happen to retain order anyway.
     from OFS.Folder import Folder as OrderedFolder
 
-from interfaces import ISlot
-import perm_names
-
 _www = os.path.join(os.path.dirname(__file__), "www")
 
 target_tag = '''<div class="slot_target" title="Slot: %s [%d]"
@@ -63,20 +67,20 @@
 
 
 class NullElement(SimpleItem):
-    """Temporary slot content
+    """Empty placeholder for slot content
     """
-    meta_type = "Temporary Null Page Element"
+    meta_type = "Temporary Empty Slot Content"
 
     def __init__(self, id):
         self.id = id
 
+
 class Slot(OrderedFolder):
     """A slot in a composite.
     """
+    implements(ISlot)
     meta_type = "Composite Slot"
 
-    __implements__ = ISlot, OrderedFolder.__implements__
-
     security = ClassSecurityInfo()
 
     null_element = NullElement("null_element")
@@ -89,7 +93,7 @@
         return OrderedFolder.all_meta_types(
             self, interfaces=(ICompositeElement,))
 
-    security.declareProtected(perm_names.view, "single")
+    security.declareProtected(view_perm, "single")
     def single(self):
         """Renders as a single-element slot.
 
@@ -100,7 +104,7 @@
         allow_add = (not self._objects)
         return "".join(self.renderToList(allow_add))
 
-    security.declareProtected(perm_names.view, "multiple")
+    security.declareProtected(view_perm, "multiple")
     def multiple(self):
         """Renders as a list containing multiple elements.
         """
@@ -111,7 +115,9 @@
         """
         return "".join(self.renderToList(1))
 
-    security.declareProtected(perm_names.change_composites, "reorder")
+    __unicode__ = __str__
+
+    security.declareProtected(change_composites_perm, "reorder")
     def reorder(self, name, new_index):
         if name not in self.objectIds():
             raise KeyError, name
@@ -120,7 +126,7 @@
                     {'id': name, 'meta_type': getattr(self, name).meta_type})
         self._objects = tuple(objs)
 
-    security.declareProtected(perm_names.change_composites, "nullify")
+    security.declareProtected(change_composites_perm, "nullify")
     def nullify(self, name):
         res = self[name]
         objs = list(self._objects)
@@ -131,12 +137,12 @@
         delattr(self, name)
         return res
 
-    security.declareProtected(perm_names.change_composites, "nullify")
+    security.declareProtected(change_composites_perm, "nullify")
     def pack(self):
         objs = [info for info in self._objects if info["id"] != "null_element"]
         self._objects = tuple(objs)
 
-    security.declareProtected(perm_names.view, "renderToList")
+    security.declareProtected(view_perm, "renderToList")
     def renderToList(self, allow_add):
         """Renders the items to a list.
         """
@@ -149,20 +155,21 @@
             myid = self.getId()
             if hasattr(self, 'portal_url'):
                 icon_base_url = self.portal_url()
-            elif hasattr(self, 'REQUEST'):
-                icon_base_url = self.REQUEST['BASEPATH1']
             else:
-                icon_base_url = '/'
-       
+                request = getattr(self, 'REQUEST', None)
+                if request is not None:
+                    icon_base_url = request['BASEPATH1']
+                else:
+                    icon_base_url = '/'
+
         if editing and allow_add:
             res.append(self._render_add_target(myid, 0, mypath))
-        
+
         for index in range(len(items)):
             name, obj = items[index]
 
-
             try:
-                assert ICompositeElement.isImplementedBy(obj), (
+                assert ICompositeElement.providedBy(obj), (
                     "Not a composite element: %s" % repr(obj))
                 text = obj.renderInline()
             except ConflictError:
@@ -199,9 +206,9 @@
 def getIconURL(obj, icon_base_url):
     base = aq_base(obj)
     if hasattr(base, 'getIcon'):
-        icon = str(obj.getIcon())
+        icon = obj.getIcon()
     elif hasattr(base, 'icon'):
-        icon = str(obj.icon)
+        icon = obj.icon
     else:
         icon = ""
     if icon and '://' not in icon:
@@ -230,18 +237,22 @@
                     "this part of the page.")
         try:
             log = aq_get(context, '__error_log__', None, 1)
+            raising = getattr(log, 'raising', None)
         except AttributeError:
+            raising = None
+
+        if raising is not None:
+            error_log_url = raising(exc_info)
+            return error_tag % (msg, error_log_url)
+        else:
             LOG("Composite", ERROR, "Error in a page element",
                 error=exc_info)
             return msg
-        else:
-            error_log_url = log.raising(exc_info)
-            return error_tag % (msg, error_log_url)
     finally:
         del exc_info
 
 
-addSlotForm = PageTemplateFile("addSlotForm", _www)
+addSlotForm = PageTemplateFile("addSlotForm.zpt", _www)
 
 def manage_addSlot(dispatcher, id, REQUEST=None):
     """Adds a slot to a composite.

Modified: CompositePage/trunk/slotclass.py
===================================================================
--- CompositePage/trunk/slotclass.py	2011-04-11 21:45:02 UTC (rev 121401)
+++ CompositePage/trunk/slotclass.py	2011-04-11 23:46:03 UTC (rev 121402)
@@ -21,17 +21,19 @@
 from Acquisition import aq_inner, aq_parent
 from OFS.SimpleItem import SimpleItem
 from OFS.PropertyManager import PropertyManager
-from Products.PageTemplates.PageTemplateFile import PageTemplateFile
+from zope.pagetemplate.pagetemplatefile import PageTemplateFile
+from zope.interface import implements
 
-from interfaces import ISlotClass
+from Products.CompositePage.interfaces import ISlotClass
 
 
 _www = os.path.join(os.path.dirname(__file__), "www")
 
+
 class SlotClass(SimpleItem, PropertyManager):
     """Parameters and constraints for a slot.
     """
-    __implements__ = ISlotClass
+    implements(ISlotClass)
     meta_type = "Composite Slot Class"
     find_script = ""
 
@@ -51,7 +53,7 @@
         return s(slot)
 
 
-addSlotClassForm = PageTemplateFile("addSlotClassForm", _www)
+addSlotClassForm = PageTemplateFile("addSlotClassForm.zpt", _www)
 
 def manage_addSlotClass(dispatcher, id, REQUEST=None):
     """Adds a slot class to a composite tool.

Modified: CompositePage/trunk/slotexpr.py
===================================================================
--- CompositePage/trunk/slotexpr.py	2011-04-11 21:45:02 UTC (rev 121401)
+++ CompositePage/trunk/slotexpr.py	2011-04-11 23:46:03 UTC (rev 121402)
@@ -17,18 +17,21 @@
 $Id: slotexpr.py,v 1.5 2004/05/03 16:02:40 sidnei Exp $
 """
 
+import logging
 import re
 
-from Products.PageTemplates.TALES import CompilerError, Default
+from zope.tales.tales import CompilerError
 
-from interfaces import IComposite
+from Products.CompositePage.interfaces import IComposite
 
 name_re = re.compile("\s*([a-zA-Z][a-zA-Z0-9_]*)")
 class_name_re = re.compile("\s*[(]([a-zA-Z][a-zA-Z0-9_]*)[)]")
 title_re = re.compile("\s*[']([^']+)[']")
 
+log = logging.getLogger(__name__)
 
-class SlotExpr:
+
+class SlotExpr(object):
     """Slot expression type.
 
     Provides a concise syntax for specifying composite slots in
@@ -38,7 +41,7 @@
     """
 
     def __init__(self, name, expr, engine):
-        self._s = s = expr
+        self._s = s = expr.strip()
         mo = name_re.match(s)
         if mo is None:
             raise CompilerError('Invalid slot expression "%s"' % s)
@@ -60,29 +63,43 @@
             # Can't interpret some of the expression
             raise CompilerError(
                 'Slot expression syntax error near %s' % repr(s))
-    
+
     def __call__(self, econtext):
         context = econtext.contexts.get('options')
         if context is None:
             raise RuntimeError("Could not find options")
         composite = context.get('composite')
-        if IComposite.isImplementedBy(composite):
+        if IComposite.providedBy(composite):
             slot = composite.slots.get(
                 self._name, self._class_name, self._title)
             # Render the slot
-            return "".join(slot.multiple())
+            return unicode(slot)
         else:
             # Show the default content
-            return Default
+            return econtext.getDefault()
 
     def __repr__(self):
-        return 'slot:%s' % self._s
+        return '<SlotExpr %s>' % repr(self._s)
 
 
 def registerSlotExprType():
     # Register the 'slot:' expression type.
-    from Products.PageTemplates.Expressions import getEngine
-    # Avoid registering twice.
-    engine = getEngine()
-    if not engine.getTypes().has_key('slot'):
-        engine.registerType('slot', SlotExpr)
+
+    # Register with Products.PageTemplates.
+    try:
+        from Products.PageTemplates.Expressions import getEngine
+    except ImportError:
+        log.exception("Unable to register the slot expression type")
+    else:
+        engine = getEngine()
+        if not engine.getTypes().has_key('slot'):
+            engine.registerType('slot', SlotExpr)
+
+    # Register with zope.tales.
+    try:
+        from zope.tales.engine import Engine
+    except ImportError:
+        log.exception("Unable to register the slot expression type")
+    else:
+        if not Engine.getTypes().has_key('slot'):
+            Engine.registerType('slot', SlotExpr)

Modified: CompositePage/trunk/tests/test_composite.py
===================================================================
--- CompositePage/trunk/tests/test_composite.py	2011-04-11 21:45:02 UTC (rev 121401)
+++ CompositePage/trunk/tests/test_composite.py	2011-04-11 23:46:03 UTC (rev 121402)
@@ -17,27 +17,15 @@
 """
 
 import unittest
+from zope.testing.cleanup import cleanUp
 
-import ZODB
-from OFS.Folder import Folder
-from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
-from TAL.TALDefs import TALError
-from Products.CompositePage.slot import Slot
-from Products.CompositePage.composite import Composite
-from Products.CompositePage.element import CompositeElement
-from AccessControl.SecurityManagement import noSecurityManager
-from AccessControl.SecurityManager import setSecurityPolicy
-import AccessControl.User  # Get the "nobody" user defined
 
-from Products.CompositePage.tests.test_tool import PermissiveSecurityPolicy
-
-
 template_text = '''\
 <html>
 <body>
 <div tal:replace="structure slot: slot_a (top) 'Top News Stories'">slot_a</div>
 <span tal:replace="structure slot: slot_b 'Other News'">slot_b</span>
-<div tal:replace="structure here/slots/slot_c">slot_c</div>
+<div tal:replace="structure context/slots/slot_c">slot_c</div>
 </body>
 </html>
 '''
@@ -46,37 +34,62 @@
 class CompositeTests(unittest.TestCase):
 
     def setUp(self):
+        cleanUp()
+        from AccessControl.SecurityManagement import noSecurityManager
+        from AccessControl.SecurityManager import setSecurityPolicy
+        from Products.CompositePage.tests.test_tool import PermissiveSecurityPolicy
+        self.old_policy = setSecurityPolicy(PermissiveSecurityPolicy())
+        noSecurityManager()
+
+    def tearDown(self):
+        from AccessControl.SecurityManagement import noSecurityManager
+        from AccessControl.SecurityManager import setSecurityPolicy
+        setSecurityPolicy(self.old_policy)
+        noSecurityManager()
+        cleanUp()
+
+    def _make_composite(self):
+        from OFS.Folder import Folder
         f = Folder()
         f.getPhysicalPath = lambda: ()
         f.getPhysicalRoot = lambda f=f: f
+        from ZPublisher.HTTPRequest import HTTPRequest
+        f.REQUEST = HTTPRequest('', dict(HTTP_HOST='localhost:8080'), {})
+        from Products.CompositePage.composite import Composite
         f.composite = Composite()
         f.composite._setId("composite")
+        from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
         t = ZopePageTemplate(
             id="template", text=template_text, content_type="text/html")
+        f.composite.template = t
+        from Products.CompositePage.slot import Slot
+        f.composite.filled_slots.slot_a = slot_a = Slot("slot_a")
+        t = f.composite.template
         if t.pt_errors():
             raise SyntaxError(t.pt_errors())
-        f.composite.template = t
-        f.composite.filled_slots.slot_a = slot_a = Slot("slot_a")
         a1 = ZopePageTemplate(id="a1", text="<b>Slot A</b>")
         f._setObject(a1.id, a1)
+        from Products.CompositePage.element import CompositeElement
         e1 = CompositeElement('e1', f.a1)
         slot_a._setObject(e1.id, e1)
-        self.composite = f.composite
-        self.old_policy = setSecurityPolicy(PermissiveSecurityPolicy())
-        noSecurityManager()
+        return f.composite
 
-    def tearDown(self):
-        setSecurityPolicy(self.old_policy)
-        noSecurityManager()
+    def _registerTraversable(self):
+        from zope.component import getGlobalSiteManager
+        from zope.interface import Interface
+        from zope.traversing.interfaces import ITraversable
+        from zope.traversing.adapters import DefaultTraversable
+        getGlobalSiteManager().registerAdapter(
+            DefaultTraversable, [Interface], ITraversable)
 
     def assertTextEqual(self, a, b):
         a = a.strip().replace("\n", "")
         b = b.strip().replace("\n", "")
         self.assertEqual(a, b)
 
-
     def testRender(self):
-        rendered = self.composite()
+        self._registerTraversable()
+        rendered = self._make_composite()()
         expected = ('<html><body>'
                     '<div class="slot_header"></div><div><b>Slot A</b></div>'
                     '<div class="slot_header"></div>'
@@ -85,7 +98,8 @@
         self.assertTextEqual(rendered, expected)
 
     def testGetManifest(self):
-        manifest = self.composite.getManifest()
+        self._registerTraversable()
+        manifest = self._make_composite().getManifest()
         self.assertEqual(len(manifest), 3)
         self.assertEqual(manifest[0]['name'], 'slot_a')
         self.assertEqual(manifest[0]['title'], 'Top News Stories')
@@ -110,25 +124,28 @@
 
     def testSlotExprCompilerError(self):
         # Bad slot expressions should produce a reasonable error.
+        from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
+        from zope.tal.taldefs import TALError
         text = '<div tal:content="structure slot: a b" />'
         try:
             t = ZopePageTemplate(
                 id="template", text=text, content_type="text/html")
         except TALError, e:
-            msg = str(e)
+            msg = unicode(e)
         else:
             msg = ' '.join(t.pt_errors())
             if not msg:
                 raise AssertionError("Expected a syntax error")
-        substr = "near ' b'"
-        self.assert_(msg.find(substr) >= 0)
+        self.assertTrue("syntax error" in msg)
 
     def testGetSlotClassName(self):
-        self.assertEqual(self.composite.getSlotClassName('slot_a'), 'top')
-        self.assertEqual(self.composite.getSlotClassName('slot_b'), None)
-        self.assertEqual(self.composite.getSlotClassName('slot_c'), None)
+        self._registerTraversable()
+        composite = self._make_composite()
+        self.assertEqual(composite.getSlotClassName('slot_a'), 'top')
+        self.assertEqual(composite.getSlotClassName('slot_b'), None)
+        self.assertEqual(composite.getSlotClassName('slot_c'), None)
         self.assertRaises(
-            KeyError, self.composite.getSlotClassName, 'nonexistent_slot')
+            KeyError, composite.getSlotClassName, 'nonexistent_slot')
 
 def test_suite():
     suite = unittest.TestSuite()

Modified: CompositePage/trunk/tests/test_tool.py
===================================================================
--- CompositePage/trunk/tests/test_tool.py	2011-04-11 21:45:02 UTC (rev 121401)
+++ CompositePage/trunk/tests/test_tool.py	2011-04-11 23:46:03 UTC (rev 121402)
@@ -18,17 +18,16 @@
 
 import unittest
 
-import ZODB
 from OFS.Folder import Folder
-from Products.CompositePage.tool import CompositeTool
-from Products.CompositePage.slot import Slot
-from Products.CompositePage.interfaces import CompositeError
-
 from AccessControl.SecurityManagement import noSecurityManager
 from AccessControl.SecurityManager import setSecurityPolicy
 import AccessControl.User  # Get the "nobody" user defined
 
+from Products.CompositePage.tool import CompositeTool
+from Products.CompositePage.slot import Slot
+from Products.CompositePage.interfaces import CompositeError
 
+
 class PermissiveSecurityPolicy:
     def validate(*args, **kw):
         return 1
@@ -37,7 +36,6 @@
         return 1
 
 
-
 class ToolTests(unittest.TestCase):
 
     def setUp(self):

Modified: CompositePage/trunk/tool.py
===================================================================
--- CompositePage/trunk/tool.py	2011-04-11 21:45:02 UTC (rev 121401)
+++ CompositePage/trunk/tool.py	2011-04-11 23:46:03 UTC (rev 121402)
@@ -24,10 +24,12 @@
 from AccessControl import ClassSecurityInfo
 from AccessControl.ZopeGuards import guarded_getattr
 
-from interfaces import ISlot, ISlotClass, ICompositeElement
-from interfaces import CompositeError
-from element import CompositeElement
-from utils import copyOf
+from Products.CompositePage.interfaces import ICompositeElement
+from Products.CompositePage.interfaces import ISlot
+from Products.CompositePage.interfaces import ISlotClass
+from Products.CompositePage.interfaces import CompositeError
+from Products.CompositePage.element import CompositeElement
+from Products.CompositePage.utils import copyOf
 
 
 _uis = {}
@@ -129,10 +131,10 @@
         root = self.getPhysicalRoot()
         elements = []
         target = root.restrictedTraverse(target_path)
-        assert ISlot.isImplementedBy(target), repr(target)
+        assert ISlot.providedBy(target), repr(target)
         for source in sources:
             slot = root.restrictedTraverse(source[:-1])
-            assert ISlot.isImplementedBy(slot), repr(slot)
+            assert ISlot.providedBy(slot), repr(slot)
             element = slot.restrictedTraverse(source[-1])
             elements.append(element)
             if self._check_security:
@@ -155,7 +157,7 @@
             # Add the elements and reorder.
             for element in elements:
 
-                if not ICompositeElement.isImplementedBy(element):
+                if not ICompositeElement.providedBy(element):
                     # Make a composite element wrapper.
                     element = CompositeElement(element.getId(), element)
 
@@ -189,7 +191,7 @@
         try:
             for source in sources:
                 slot = self.restrictedTraverse(source[:-1])
-                assert ISlot.isImplementedBy(slot), repr(slot)
+                assert ISlot.providedBy(slot), repr(slot)
                 slot_id = id(aq_base(slot))
                 if not orig_slots.has_key(slot_id):
                     orig_slots[slot_id] = slot

Modified: CompositePage/trunk/utils.py
===================================================================
--- CompositePage/trunk/utils.py	2011-04-11 21:45:02 UTC (rev 121401)
+++ CompositePage/trunk/utils.py	2011-04-11 23:46:03 UTC (rev 121402)
@@ -20,7 +20,6 @@
 
 from cStringIO import StringIO
 from cPickle import Pickler, Unpickler
-from types import StringType
 
 
 def copyOf(source):
@@ -40,7 +39,7 @@
         if hasattr(ob, '__bases__'):
             m = getattr(ob, '__module__', None)
             if (m is not None
-                and isinstance(m, StringType)
+                and isinstance(m, basestring)
                 and m.startswith('*')):
                 n = getattr(ob, '__name__', None)
                 if n is not None:



More information about the checkins mailing list