[Checkins] SVN: zope.container/trunk/src/zope/container/ make filepresentation work for zope.container.folder.Folder

Jan-Wijbrand Kolman janwijbrand at gmail.com
Fri Jan 30 06:53:14 EST 2009


Log message for revision 95545:
  make filepresentation work for zope.container.folder.Folder

Changed:
  U   zope.container/trunk/src/zope/container/configure.zcml
  U   zope.container/trunk/src/zope/container/directory.py
  U   zope.container/trunk/src/zope/container/folder.py
  U   zope.container/trunk/src/zope/container/interfaces.py
  A   zope.container/trunk/src/zope/container/tests/directory.txt
  U   zope.container/trunk/src/zope/container/tests/test_directory.py

-=-
Modified: zope.container/trunk/src/zope/container/configure.zcml
===================================================================
--- zope.container/trunk/src/zope/container/configure.zcml	2009-01-30 11:27:03 UTC (rev 95544)
+++ zope.container/trunk/src/zope/container/configure.zcml	2009-01-30 11:53:13 UTC (rev 95545)
@@ -5,6 +5,11 @@
    i18n_domain="zope"
    >
 
+  <interface 
+      interface=".interfaces.IContentContainer" 
+      type="zope.app.content.interfaces.IContentType"
+      /> 
+
   <adapter
      provides=".interfaces.IFind"
      for=".interfaces.IReadContainer"
@@ -25,6 +30,20 @@
       />
 
   <adapter
+      for=".interfaces.IContentContainer"
+      provides="zope.filerepresentation.interfaces.IDirectoryFactory"
+      factory="zope.container.directory.Cloner"
+      permission="zope.ManageContent"
+      />
+
+  <adapter
+      for=".interfaces.IContentContainer"
+      provides="zope.filerepresentation.interfaces.IReadDirectory"
+      factory=".filerepresentation.ReadDirectory"
+      permission="zope.View"
+      />
+
+  <adapter
       factory="zope.container.traversal.ContainerTraversable"
       provides="zope.traversing.interfaces.ITraversable"
       for="zope.container.interfaces.IReadContainer"

Modified: zope.container/trunk/src/zope/container/directory.py
===================================================================
--- zope.container/trunk/src/zope/container/directory.py	2009-01-30 11:27:03 UTC (rev 95544)
+++ zope.container/trunk/src/zope/container/directory.py	2009-01-30 11:53:13 UTC (rev 95545)
@@ -25,10 +25,14 @@
 """
 __docformat__ = 'restructuredtext'
 
-import zope.filerepresentation.interfaces
-from zope.security.proxy import removeSecurityProxy
 from zope.interface import implements
 
+from zope.location.interfaces import ISite
+from zope.security.proxy import removeSecurityProxy
+import zope.filerepresentation.interfaces
+
+MARKER = object()
+
 def noop(container):
     """Adapt an `IContainer` to an `IWriteDirectory` by just returning it
 
@@ -60,3 +64,55 @@
         # exciting side effects as a result of instantiation. :)
 
         return removeSecurityProxy(self.context).__class__()
+
+
+class RootDirectoryFactory(object):
+
+    def __init__(self, context):
+        pass
+
+    def __call__(self, name):
+        return Folder()
+
+
+class ReadDirectory(object):
+    """Adapter to provide a file-system rendition of folders."""
+
+    def __init__(self, context):
+        self.context = context
+
+    def keys(self):
+        keys = self.context.keys()
+        if ISite.providedBy(self.context):
+            return list(keys) + ['++etc++site']
+        return keys
+
+    def get(self, key, default=None):
+        if key == '++etc++site' and ISite.providedBy(self.context):
+            return self.context.getSiteManager()
+        return self.context.get(key, default)
+
+    def __iter__(self):
+        return iter(self.keys())
+
+    def __getitem__(self, key):
+        v = self.get(key, MARKER)
+        if v is MARKER:
+            raise KeyError(key)
+        return v
+
+    def values(self):
+        return map(self.get, self.keys())
+
+    def __len__(self):
+        l = len(self.context)
+        if ISite.providedBy(self.context):
+            l += 1
+        return l
+
+    def items(self):
+        get = self.get
+        return [(key, get(key)) for key in self.keys()]
+
+    def __contains__(self, key):
+        return self.get(key) is not None

Modified: zope.container/trunk/src/zope/container/folder.py
===================================================================
--- zope.container/trunk/src/zope/container/folder.py	2009-01-30 11:27:03 UTC (rev 95544)
+++ zope.container/trunk/src/zope/container/folder.py	2009-01-30 11:53:13 UTC (rev 95545)
@@ -19,15 +19,21 @@
 
 from BTrees.OOBTree import OOBTree
 from persistent import Persistent
-from zope.container.interfaces import IContainer
+from zope.container.interfaces import IContainer, IContentContainer
 from zope.container.contained import Contained, setitem, uncontained
 from zope.exceptions import DuplicationError
 from zope.interface import implements, directlyProvides
 
+# XXX This container implementation is really only used by 
+# zope.site.folder.Folder. Please do not use it. 
+
+# XXX Check whether this IContainer implementation cannot really
+# be replaced by the BTreeContainer.
+
 class Folder(Persistent, Contained):
     """The standard Zope Folder implementation."""
 
-    implements(IContainer)
+    implements(IContentContainer)
 
     def __init__(self):
         self.data = OOBTree()

Modified: zope.container/trunk/src/zope/container/interfaces.py
===================================================================
--- zope.container/trunk/src/zope/container/interfaces.py	2009-01-30 11:27:03 UTC (rev 95544)
+++ zope.container/trunk/src/zope/container/interfaces.py	2009-01-30 11:53:13 UTC (rev 95545)
@@ -126,6 +126,10 @@
     """Readable and writable content container."""
 
 
+class IContentContainer(IContainer):
+    """A container that is to be used as a content type."""
+
+
 class IBTreeContainer(IContainer):
     """Container that supports BTree semantics for some methods."""
 

Added: zope.container/trunk/src/zope/container/tests/directory.txt
===================================================================
--- zope.container/trunk/src/zope/container/tests/directory.txt	                        (rev 0)
+++ zope.container/trunk/src/zope/container/tests/directory.txt	2009-01-30 11:53:13 UTC (rev 95545)
@@ -0,0 +1,43 @@
+===============================
+File representation for folders
+===============================
+
+Folders can be represented in file-system-like protocols (e.g. FTP). An
+adapter abstracts some internals away and adds support for accessing the
+'++etc++site' folder from those protocols.
+
+  >>> from zope.container.folder import Folder
+  >>> from zope.container.directory import ReadDirectory
+  >>> folder = Folder()
+
+The new folder isn't a site manager and doesn't have any entries:
+
+  >>> fs_folder = ReadDirectory(folder)
+  >>> list(fs_folder.keys())
+  []
+  >>> fs_folder.get('test', )
+  >>> fs_folder['test']
+  Traceback (most recent call last):
+  KeyError: 'test'
+  >>> list(fs_folder.__iter__())
+  []
+  >>> fs_folder.values()
+  []
+  >>> len(fs_folder)
+  0
+  >>> fs_folder.items()
+  []
+  >>> 'test' in fs_folder
+  False
+
+This is a short regression test for #728: we get a KeyError when trying to
+access non-existing entries:
+
+  >>> from zope.security.proxy import ProxyFactory
+  >>> from zope.security.checker import NamesChecker
+  >>> proxied_folder = ProxyFactory(fs_folder, NamesChecker(('get',)))
+  >>> proxied_fs_folder = ReadDirectory(proxied_folder)
+  >>> print proxied_fs_folder['i dont exist']
+  Traceback (most recent call last):
+  KeyError: 'i dont exist'
+

Modified: zope.container/trunk/src/zope/container/tests/test_directory.py
===================================================================
--- zope.container/trunk/src/zope/container/tests/test_directory.py	2009-01-30 11:27:03 UTC (rev 95544)
+++ zope.container/trunk/src/zope/container/tests/test_directory.py	2009-01-30 11:53:13 UTC (rev 95545)
@@ -16,6 +16,9 @@
 $Id$
 """
 from unittest import TestCase, TestSuite, main, makeSuite
+from zope.testing import doctest
+from zope.container import testing
+
 import zope.container.directory
 
 class Directory(object):
@@ -31,8 +34,12 @@
         self.assertEqual(clone.__class__, d.__class__)
 
 def test_suite():
+    flags = doctest.ELLIPSIS|doctest.NORMALIZE_WHITESPACE
     return TestSuite((
         makeSuite(Test),
+        doctest.DocFileSuite("directory.txt",
+                             setUp=testing.setUp, tearDown=testing.tearDown,
+                             optionflags=flags),
         ))
 
 if __name__=='__main__':



More information about the Checkins mailing list