[Zope-CVS] CVS: Products/PageDesign - BrokenPageElement.py:1.1 ElementReference.py:1.2

Shane Hathaway shane@cvs.zope.org
Thu, 15 Aug 2002 21:17:47 -0400


Update of /cvs-repository/Products/PageDesign
In directory cvs.zope.org:/tmp/cvs-serv21664

Modified Files:
	ElementReference.py 
Added Files:
	BrokenPageElement.py 
Log Message:
Fully relative references.


=== Added File Products/PageDesign/BrokenPageElement.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.
# 
##############################################################################

from IPageElement import IPageElement


class BrokenPageElement:

    __implements__ = IPageElement

    def __init__(self, path, exc):
        self._path = path
        self._exc = exc

    def render(self, design, editable, index):
        """Returns a string.
        """
        return '<code>Unable to locate "%s": %s</code>' % (
            '/'.join(self._path), self._exc)

    def getIconURL(self):
        """Returns an URL to an icon for this element if available.
        """
        return ''

    def getTitle(self):
        """Returns the title of this element.
        """
        return 'Broken Reference'

    def getEditURL(self):
        """Returns the URL for editing this element.
        """
        return None



=== Products/PageDesign/ElementReference.py 1.1 => 1.2 ===
--- Products/PageDesign/ElementReference.py:1.1	Thu Aug 15 20:29:35 2002
+++ Products/PageDesign/ElementReference.py	Thu Aug 15 21:17:47 2002
@@ -12,13 +12,17 @@
 # 
 ##############################################################################
 
+import sys
+
 import Acquisition
+from Acquisition import aq_inner, aq_parent
 from Persistence import Persistent
 from OFS.Traversable import Traversable
 
 from IElementReference import IElementReference
 from IPageElement import IPageElement
 from SimpleItemAsElement import SimpleItemAsElement
+from BrokenPageElement import BrokenPageElement
 
 
 class ElementReference (Persistent, Acquisition.Explicit, Traversable):
@@ -29,22 +33,75 @@
         self._path = ob.getPhysicalPath()
 
     def dereference(self):
-        root = self.getPhysicalRoot()
         try:
-            ob = root.restrictedTraverse(self._path)
+            base = self.getBaseObject()
+            ob = base.restrictedTraverse(self._path)
         except:
-            return BrokenPageElement(self._path)
+            t, v = sys.exc_info()[:2]
+            t = getattr(t, '__name__', t)
+            exc = '%s: %s' % (t, v)
+            return BrokenPageElement(self._path, exc)
         # The code below is essentially adapter lookup
         if IPageElement.isImplementedBy(ob):
             return ob
         else:
             return SimpleItemAsElement(ob)
 
-    def beforeDelete(self):
-        # Turn self._path into an absolute path
-        pass
+    def getBaseObject(self):
+        return aq_parent(aq_inner(aq_parent(aq_inner(self))))
 
     def afterAdd(self):
         # Turn self._path into a relative path
-        pass
+        bp = self.getBaseObject().getPhysicalPath()
+        self._path = makeRelativePath(bp, self._path)
+
+    def beforeDelete(self):
+        # Turn self._path into an absolute path
+        bp = self.getBaseObject().getPhysicalPath()
+        self._path = makeAbsolutePath(bp, self._path)
+
+
+# Utility tuple-path converters
+
+def makeRelativePath(src, dest):
+    """Converts a tuple of path elements to a relative path.
+
+    By convention, if the first item of path tuple is an empty string,
+    the path tuple is an absolute path.
+    """
+    assert tuple(src[:1]) == ('',), ('%s is not absolute' % src)
+
+    dest = list(dest)
+    if dest[:1] != ['']:
+        # Already relative.
+        return tuple(dest)
+    src = list(src)
+    # Simplify.
+    while src and dest:
+        if src[:1] == dest[:1]:
+            del src[0]
+            del dest[0]
+        else:
+            break
+    # Prepend a '..' to dest for every item remaining in src.
+    dest = ['..'] * len(src) + dest
+    return tuple(dest)
+
+
+def makeAbsolutePath(src, dest):
+    """Converts a tuple of path elements to an absolute path."""
+    assert tuple(src[:1]) == ('',), ('%s is not absolute' % src)
+
+    if tuple(dest[:1]) == ('',):
+        # Already absolute.
+        return tuple(dest)
+    src = list(src)
+    for item in dest:
+        if item == '..':
+            if src:
+                del src[-1]
+        else:
+            src.append(item)
+    return tuple(src)
+