[Zope-CVS] CVS: Products/CompositePage - element.py:1.1 slotclass.py:1.1 __init__.py:1.6 designuis.py:1.5 interfaces.py:1.7 slot.py:1.17 tool.py:1.11 render.py:NONE slotdef.py:NONE

Shane Hathaway shane at zope.com
Tue Mar 2 15:42:15 EST 2004


Update of /cvs-repository/Products/CompositePage
In directory cvs.zope.org:/tmp/cvs-serv26507

Modified Files:
	__init__.py designuis.py interfaces.py slot.py tool.py 
Added Files:
	element.py slotclass.py 
Removed Files:
	render.py slotdef.py 
Log Message:
Switched to use composite element objects.

Composites no longer hold arbitrary objects.  They hold
composite elements, which reference arbitrary objects.  This makes
it unnecessary to store annotations, use any kind of adapter framework,
or depend on the References product.  Composite elements are
usually references.


=== Added File Products/CompositePage/element.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.  All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Composite element.

$Id: element.py,v 1.1 2004/03/02 20:41:44 shane Exp $
"""

import os

import Globals
from AccessControl.SecurityInfo import ClassSecurityInfo
from Acquisition import aq_get
from OFS.SimpleItem import SimpleItem
from OFS.PropertyManager import PropertyManager
from DocumentTemplate.DT_Util import safe_callable
from Products.PageTemplates.PageTemplateFile import PageTemplateFile

from interfaces import ICompositeElement

_www = os.path.join(os.path.dirname(__file__), "www")


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
    meta_type = "Composite Element"
    security = ClassSecurityInfo()
    manage_options = PropertyManager.manage_options + SimpleItem.manage_options

    _properties = (
        {'id': 'path', 'type': 'string', 'mode': 'w',},
        {'id': 'template_name', 'type': 'string', 'mode': 'w',},
        )

    template_name = ''

    def __init__(self, id, obj):
        self.id = id
        self.path = '/'.join(obj.getPhysicalPath())

    def dereference(self):
        """Returns the object referenced by this composite element.
        """
        return self.restrictedTraverse(self.path)

    def renderInline(self):
        """Returns a representation of this object as a string.
        """
        obj = self.dereference()
        name = self.template_name
        if not name:
            # Default to the first allowable inline template.
            names = self.listAllowableInlineTemplates()
            if names:
                name = names[0]
        if name and name != "call":
            template = obj.restrictedTraverse(str(name))
            return template()
        # Special template name "call" means to call the object.
        if safe_callable(obj):
            return obj()
        return str(obj)

    def getInlineTemplate(self):
        """Returns the name of the inline template this object uses.
        """
        return self.template_name

    def setInlineTemplate(self, template):
        """Sets the inline template for this object.
        """
        self.template_name = str(template_name)

    def listAllowableInlineTemplates(self):
        """Returns a list of inline template names allowable for this object.
        """
        tool = aq_get(self, "composite_tool", None, 1)
        if tool is not None:
            return tool.default_inline_templates
        # No tool found, so no inline templates are known.
        return ()

Globals.InitializeClass(CompositeElement)


addElementForm = PageTemplateFile("addElementForm", _www)

def manage_addElement(dispatcher, id, path, template_name=None, REQUEST=None):
    """Adds an element to a slot.
    """
    target = dispatcher.restrictedTraverse(path)
    ob = CompositeElement(str(id), target)
    if template_name:
        ob.template_name = str(template_name)
    dispatcher._setObject(ob.getId(), ob)
    if REQUEST is not None:
        return dispatcher.manage_main(dispatcher, REQUEST)


=== Added File Products/CompositePage/slotclass.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""Slot classes.

$Id: slotclass.py,v 1.1 2004/03/02 20:41:44 shane Exp $
"""

import os

from Acquisition import aq_inner, aq_parent
from OFS.SimpleItem import SimpleItem
from OFS.PropertyManager import PropertyManager
from Products.PageTemplates.PageTemplateFile import PageTemplateFile

from interfaces import ISlotClass


_www = os.path.join(os.path.dirname(__file__), "www")

class SlotClass(SimpleItem, PropertyManager):
    """Parameters and constraints for a slot.
    """
    __implements__ = ISlotClass
    meta_type = "Composite Slot Class"
    find_script = ""

    manage_options = (PropertyManager.manage_options
                      + SimpleItem.manage_options)

    _properties = (
        {'id': 'find_script', 'mode': 'w', 'type': 'string',
         'label': 'Script that finds available elements',},
        )

    def findAvailableElements(self, slot):
        if not self.find_script:
            return None
        tool = aq_parent(aq_inner(aq_parent(aq_inner(self))))
        s = tool.restrictedTraverse(self.find_script)
        return s(slot)


addSlotClassForm = PageTemplateFile("addSlotClassForm", _www)

def manage_addSlotClass(dispatcher, id, REQUEST=None):
    """Adds a slot class to a composite tool.
    """
    ob = SlotClass()
    ob._setId(id)
    dispatcher._setObject(ob.getId(), ob)
    if REQUEST is not None:
        return dispatcher.manage_main(dispatcher, REQUEST)



=== Products/CompositePage/__init__.py 1.5 => 1.6 ===
--- Products/CompositePage/__init__.py:1.5	Thu Feb 26 16:38:11 2004
+++ Products/CompositePage/__init__.py	Tue Mar  2 15:41:44 2004
@@ -15,7 +15,7 @@
 $Id$
 """
 
-import tool, composite, slot, slotdef, designuis, interfaces
+import tool, element, composite, slot, slotclass, designuis, interfaces
 
 tool.registerUI("common", designuis.CommonUI())
 tool.registerUI("zmi", designuis.ZMIUI())
@@ -32,11 +32,20 @@
         )
 
     context.registerClass(
-        slotdef.SlotDefinition,
-        constructors=(slotdef.addSlotDefForm,
-                      slotdef.manage_addSlotDef,
+        element.CompositeElement,
+        constructors=(element.addElementForm,
+                      element.manage_addElement,
                       ),
-        interfaces=(interfaces.ISlotDefinition,),
+        visibility=None,
+        icon="www/element.gif",
+        )
+
+    context.registerClass(
+        slotclass.SlotClass,
+        constructors=(slotclass.addSlotClassForm,
+                      slotclass.manage_addSlotClass,
+                      ),
+        interfaces=(interfaces.ISlotClass,),
         visibility=None,
         icon="www/slot.gif",
         )
@@ -58,4 +67,3 @@
         visibility=None,
         icon="www/slot.gif",
         )
-


=== Products/CompositePage/designuis.py 1.4 => 1.5 ===
--- Products/CompositePage/designuis.py:1.4	Tue Mar  2 10:28:38 2004
+++ Products/CompositePage/designuis.py	Tue Mar  2 15:41:44 2004
@@ -27,6 +27,7 @@
 from AccessControl.ZopeGuards import guarded_getattr
 
 from rawfile import RawFile, InterpolatedFile
+from interfaces import ICompositeElement
 
 
 _common = os.path.join(os.path.dirname(__file__), "common")
@@ -193,8 +194,8 @@
         for path in str(paths).split(':'):
             ob = root.restrictedTraverse(path)
             obs.append(ob)
-            renderer = tool.getRendererFor(ob)
-            m = guarded_getattr(renderer, "getInlineTemplate")
+            assert ICompositeElement.isImplementedBy(ob)
+            m = guarded_getattr(ob, "getInlineTemplate")
             template = m()
             if current is None:
                 current = template
@@ -203,7 +204,7 @@
                 # so there is no common current template.  Spell this condition
                 # using a non-string value.
                 current = 0
-            m = guarded_getattr(renderer, "listAllowableInlineTemplates")
+            m = guarded_getattr(ob, "listAllowableInlineTemplates")
             templates = m()
             d = {}
             for template in templates:
@@ -228,8 +229,8 @@
             raise KeyError("Template %s is not among the choices" % template)
         tool = aq_parent(aq_inner(self))
         for ob in info["obs"]:
-            renderer = tool.getRendererFor(ob)
-            m = guarded_getattr(renderer, "setInlineTemplate")
+            assert ICompositeElement.isImplementedBy(ob)
+            m = guarded_getattr(ob, "setInlineTemplate")
             m(template)
         if REQUEST is not None:
             return close_dialog_html


=== Products/CompositePage/interfaces.py 1.6 => 1.7 ===
--- Products/CompositePage/interfaces.py:1.6	Tue Mar  2 10:28:38 2004
+++ Products/CompositePage/interfaces.py	Tue Mar  2 15:41:44 2004
@@ -49,7 +49,7 @@
         """
 
 
-class ISlotDefinition(Interface):
+class ISlotClass(Interface):
     """Parameters and constraints for a slot.
     """
 
@@ -66,8 +66,8 @@
         """
 
 
-class IRenderableInline(Interface):
-    """Interface of objects that can be rendered inline (as page elements).
+class ICompositeElement(Interface):
+    """Interface of objects that can be part of a composite.
     """
 
     def renderInline():
@@ -86,16 +86,6 @@
         """Returns a list of inline template names allowable for this object.
         """
 
-
-class IAnnotations(Interface):
-    """Collection of annotations for an object.
-    """
-
-    def getAnnotation(name):
-        """Returns an annotation by name.
+    def dereference():
+        """Returns the object to be rendered.
         """
-
-    def setAnnotation(name, value):
-        """Sets an annotation by name.
-        """
-


=== Products/CompositePage/slot.py 1.16 => 1.17 ===
--- Products/CompositePage/slot.py:1.16	Tue Mar  2 10:28:38 2004
+++ Products/CompositePage/slot.py	Tue Mar  2 15:41:44 2004
@@ -21,15 +21,14 @@
 from cgi import escape
 
 import Globals
-from Acquisition import aq_base, aq_inner, aq_parent, aq_acquire
+from Acquisition import aq_base, aq_inner, aq_parent, aq_get
 from ZODB.POSException import ConflictError
 from OFS.SimpleItem import SimpleItem
 from Products.PageTemplates.PageTemplateFile import PageTemplateFile
 from AccessControl import ClassSecurityInfo
 from zLOG import LOG, ERROR
 
-from interfaces import IRenderableInline
-from render import adapt
+from interfaces import ICompositeElement
 
 
 try:
@@ -88,6 +87,10 @@
     def __init__(self, id):
         self.id = id
 
+    def all_meta_types(self):
+        return OrderedFolder.all_meta_types(
+            self, interfaces=(ICompositeElement,))
+
     security.declareProtected(perm_names.view, "single")
     def single(self):
         """Renders as a single-element slot.
@@ -135,14 +138,6 @@
         objs = [info for info in self._objects if info["id"] != "null_element"]
         self._objects = tuple(objs)
 
-    security.declarePrivate('renderElement')
-    def renderElement(self, obj):
-        """Renders one composite element.
-        """
-        o = adapt(obj, IRenderableInline)
-        text = o.renderInline()
-        return text
-
     security.declareProtected(perm_names.view, "renderToList")
     def renderToList(self, allow_add):
         """Renders the items to a list.
@@ -165,7 +160,9 @@
                 res.append(target_tag % (myid, index, mypath, index))
 
             try:
-                text = self.renderElement(obj)
+                assert ICompositeElement.isImplementedBy(obj), (
+                    "Not a composite element: %s" % repr(obj))
+                text = obj.renderInline()
             except ConflictError:
                 # Ugly ZODB requirement: don't catch ConflictErrors
                 raise
@@ -173,8 +170,9 @@
                 text = self._handleError(editing)
 
             if editing:
-                icon = getIconURL(obj, icon_base_url)
-                title = obj.title_and_id()
+                o2 = obj.dereference()
+                icon = getIconURL(o2, icon_base_url)
+                title = o2.title_and_id()
                 path = escape('/'.join(obj.getPhysicalPath()))
                 res.append(edit_tag % (path,
                                        escape(icon), escape(title), text))
@@ -202,7 +200,7 @@
                 msg = ("An error occurred while generating "
                         "this part of the page.")
             try:
-                log = aq_acquire(self, '__error_log__', containment=1)
+                log = aq_get(self, '__error_log__', None, 1)
             except AttributeError:
                 LOG("Composite", ERROR, "Error in a page element",
                     error=exc_info)


=== Products/CompositePage/tool.py 1.10 => 1.11 ===
--- Products/CompositePage/tool.py:1.10	Tue Mar  2 10:28:38 2004
+++ Products/CompositePage/tool.py	Tue Mar  2 15:41:44 2004
@@ -24,9 +24,9 @@
 from AccessControl import ClassSecurityInfo
 from AccessControl.ZopeGuards import guarded_getattr
 
-from interfaces import ISlot, ISlotDefinition, IRenderableInline
+from interfaces import ISlot, ISlotClass, ICompositeElement
 from interfaces import CompositeError
-from render import adapt
+from element import CompositeElement
 from utils import copyOf
 
 
@@ -58,13 +58,13 @@
             raise AttributeError, name
 
 
-class SlotDefFolder(Folder):
-    """Container of slot definitions.
+class SlotClassFolder(Folder):
+    """Container of slot classes.
     """
-    meta_type = "Slot Definition Folder"
+    meta_type = "Slot Class Folder"
 
     def all_meta_types(self):
-        return Folder.all_meta_types(self, interfaces=(ISlotDefinition,))
+        return Folder.all_meta_types(self, interfaces=(ISlotClass,))
 
 
 class CompositeTool(Folder):
@@ -88,10 +88,10 @@
     _check_security = 1  # Turned off in unit tests
 
     def __init__(self):
-        sd = SlotDefFolder()
-        sd._setId("slot_defs")
-        self._setObject(sd.id, sd)
-        self._reserved_names = ('slot_defs',)
+        scf = SlotClassFolder()
+        scf._setId("slot_classes")
+        self._setObject(scf.id, scf)
+        self._reserved_names = ('slot_classes',)
 
     security.declarePublic("moveElements")
     def moveElements(self, source_paths, target_path, target_index, copy=0):
@@ -155,13 +155,9 @@
             # Add the elements and reorder.
             for element in elements:
 
-                # XXX Loose, ugly dependency on the Reference product.
-                d = getattr(element, "__dict__", None)
-                if d is not None:
-                    e = d.get("_Proxy__reference")
-                    if e is not None:
-                        # Move a reference object instead of the proxy.
-                        element = e
+                if not ICompositeElement.isImplementedBy(element):
+                    # Make a composite element wrapper.
+                    element = CompositeElement(element.getId(), element)
 
                 element = aq_base(element)
                 new_id = target._get_id(element.getId())
@@ -248,11 +244,6 @@
         else:
             raise ValueError("Clipboard function %s unknown" % func)
         resp.redirect(REQUEST["HTTP_REFERER"])
-
-
-    security.declarePublic("getRendererFor")
-    def getRendererFor(self, ob):
-        return adapt(ob, IRenderableInline)
 
 Globals.InitializeClass(CompositeTool)
 

=== Removed File Products/CompositePage/render.py ===

=== Removed File Products/CompositePage/slotdef.py ===




More information about the Zope-CVS mailing list