[Zope3-checkins] CVS: Zope3/src/zope/app/vfs/container - __init__.py:1.2 adding.py:1.2 configure.zcml:1.2 traverser.py:1.2 view.py:1.2

Jim Fulton jim@zope.com
Wed, 25 Dec 2002 09:13:59 -0500


Update of /cvs-repository/Zope3/src/zope/app/vfs/container
In directory cvs.zope.org:/tmp/cvs-serv15352/src/zope/app/vfs/container

Added Files:
	__init__.py adding.py configure.zcml traverser.py view.py 
Log Message:
Grand renaming:

- Renamed most files (especially python modules) to lower case.

- Moved views and interfaces into separate hierarchies within each
  project, where each top-level directory under the zope package
  is a separate project.

- Moved everything to src from lib/python.

  lib/python will eventually go away. I need access to the cvs
  repository to make this happen, however.

There are probably some bits that are broken. All tests pass
and zope runs, but I haven't tried everything. There are a number
of cleanups I'll work on tomorrow.



=== Zope3/src/zope/app/vfs/container/__init__.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:59 2002
+++ Zope3/src/zope/app/vfs/container/__init__.py	Wed Dec 25 09:13:28 2002
@@ -0,0 +1,2 @@
+#
+# This file is necessary to make this directory a package.


=== Zope3/src/zope/app/vfs/container/adding.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:59 2002
+++ Zope3/src/zope/app/vfs/container/adding.py	Wed Dec 25 09:13:28 2002
@@ -0,0 +1,59 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Adding View for IContentContainer
+
+This
+
+$Id$
+"""
+from zope.component import getAdapter
+
+from zope.event import publish
+from zope.app.event.objectevent import ObjectAddedEvent
+
+from zope.publisher.interfaces import IPublishTraverse
+from zope.publisher.vfs import VFSView
+
+from zope.app.interfaces.container import IAdding
+from zope.app.interfaces.container import IContainerNamesContainer
+from zope.app.interfaces.container import IZopeContainer
+
+
+class Adding(VFSView):
+
+    __implements__ =  IAdding, VFSView.__implements__
+
+    ############################################################
+    # Implementation methods for interface
+    # IAdding.py
+
+    def add(self, content):
+        'See IAdding'
+        container = self.context
+        container = getAdapter(container, IZopeContainer)
+        name = container.setObject(self.contentName, content)
+        publish(self.context, ObjectAddedEvent(container[name]))
+        return container[name]
+
+    def setContentName(self, name):
+        self.contentName = name
+
+    # See IAdding
+    contentName = None # usually set by setContentName
+
+    # See IPresentation
+    request = None # set in VFSView.__init__
+
+    # See IContextDependent
+    context = None # set in VFSView.__init__


=== Zope3/src/zope/app/vfs/container/configure.zcml 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:59 2002
+++ Zope3/src/zope/app/vfs/container/configure.zcml	Wed Dec 25 09:13:28 2002
@@ -0,0 +1,32 @@
+<zopeConfigure
+   xmlns="http://namespaces.zope.org/zope"
+   xmlns:vfs="http://namespaces.zope.org/vfs">
+
+  <vfs:view 
+      name="_traverse" 
+      for="zope.app.interfaces.container.IItemContainer"
+      factory="zope.app.vfs.container.traverser.ItemTraverser" />
+
+  <vfs:view 
+      name="_traverse" 
+      for="zope.app.interfaces.container.IReadContainer"
+      factory="zope.app.vfs.container.traverser.ContainerTraverser" />
+
+
+   <vfs:view
+       for="zope.app.interfaces.container.IContentContainer"
+       name="+"  
+       factory="zope.app.vfs.container.adding.Adding"
+       allowed_attributes="setContentName add"
+       permission="zope.ManageContent" />
+ 
+  <!-- Generic VFS Container View -->
+  <vfs:view
+      name="vfs"
+      for="zope.app.interfaces.container.IContainer"
+      permission="zope.ManageContent" 
+      allowed_interface="zope.publisher.interfaces.vfs.IVFSDirectoryPublisher" 
+      factory="zope.app.vfs.container.view.VFSContainerView" 
+      />
+
+</zopeConfigure>


=== Zope3/src/zope/app/vfs/container/traverser.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:59 2002
+++ Zope3/src/zope/app/vfs/container/traverser.py	Wed Dec 25 09:13:28 2002
@@ -0,0 +1,89 @@
+##############################################################################
+#
+# Copyright (c) 2001, 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.
+#
+##############################################################################
+"""Define VFS View Traverser for folder contents.
+
+$Id$
+"""
+
+from zope.publisher.interfaces.vfs import IVFSPublisher
+from zope.publisher.interfaces import NotFound
+from zope.app.interfaces.container import \
+     ISimpleReadContainer, IItemContainer
+from zope.component import queryView
+
+
+class ContainerTraverser:
+
+    __implements__ = IVFSPublisher
+    __used_for__ = ISimpleReadContainer
+
+    def __init__(self, container, request):
+        """Initialize Traverser."""
+        self.context = container
+        self.request = request
+
+    def _splitExtension(self, name):
+        """Split the possible extension from the name"""
+        ext_start = name.rfind(".")
+        if ext_start > 0:
+            return name[:ext_start], name[ext_start:]
+        return name, ""
+
+    def publishTraverse(self, request, name):
+        """See IPublishTraverse."""
+        context = self.context
+
+        # First, try to resolve the name as we get it.
+        subob = context.get(name, None)
+
+        if subob is None:
+            # It did not work the first time, so let's try without the
+            # extension.
+            name, ext = self._splitExtension(name)
+            subob = context.get(name, None)
+
+        if subob is None:
+            view = queryView(context, name, request)
+            if view is not None:
+                return view
+
+            raise NotFound(context, name, request)
+
+        return subob
+
+
+class ItemTraverser(ContainerTraverser):
+
+    __used_for__ = IItemContainer
+
+    def publishTraverse(self, request, name):
+        """See IPublishTraverse."""
+        context = self.context
+
+        # First, try to resolve the name as we get it.
+        try:
+            return context[name]
+        except KeyError:
+            pass
+
+        # It did not work the first time, so let's try without the extension.
+        name, ext = self._splitExtension(name)
+        try:
+            return context[name]
+        except KeyError:
+            view = queryView(context, name, request)
+            if view is not None:
+                return view
+
+        raise NotFound(context, name, request)


=== Zope3/src/zope/app/vfs/container/view.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:59 2002
+++ Zope3/src/zope/app/vfs/container/view.py	Wed Dec 25 09:13:28 2002
@@ -0,0 +1,176 @@
+##############################################################################
+#
+# Copyright (c) 2001, 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.
+#
+##############################################################################
+"""VFS-View for IContainer
+
+VFS-view implementation for a generic container. It should really work for
+all container-like objects. There is not much that can be done differently.
+
+$Id$
+"""
+import fnmatch
+import datetime
+zerotime = datetime.datetime.fromtimestamp(0)
+
+from zope.component import \
+     getView, queryView, getAdapter, queryAdapter, createObject
+
+from zope.proxy.introspection import removeAllProxies
+
+from zope.publisher.interfaces import NotFound
+from zope.publisher.vfs import VFSView
+from zope.publisher.interfaces.vfs import IVFSPublisher
+from zope.publisher.vfs import VFSRequest
+from zope.publisher.interfaces.vfs import IVFSDirectoryPublisher
+
+from zope.app.interfaces.container import IContainer
+from zope.app.interfaces.dublincore import IZopeDublinCore
+
+
+class VFSContainerView(VFSView):
+
+    __implements__ =  IVFSDirectoryPublisher, VFSView.__implements__
+
+    # This attribute specifies which type of container (factory id) should be
+    # used when a directory is created.
+    _directory_type = 'Container'
+
+    def exists(self, name):
+        'See IVFSDirectoryPublisher'
+        try:
+            self.publishTraverse(self.request, name)
+        except NotFound:
+            return False
+        return True
+
+    def listdir(self, with_stats=0, pattern='*'):
+        'See IVFSDirectoryPublisher'
+        file_list = self.context.keys()
+        # filter them using the pattern
+        file_list = list(
+            filter(lambda f, p=pattern, fnm=fnmatch.fnmatch: fnm(f, p),
+                   file_list))
+        # sort them alphabetically
+        file_list.sort()
+        if not with_stats:
+            result = file_list
+        else:
+            result = []
+            for file in file_list:
+                obj = self.context[file]
+                view = queryView(obj, 'vfs', self.request)
+                if view is not None:
+                    stat = view.stat()
+                else:
+                    # Even though this object has no VFS view, we should
+                    # display it.
+                    stat = (16384+511, 0, 0, 0, "nouser", "nogroup", 0,
+                            zerotime, zerotime, zerotime)
+                result.append((file, stat))
+
+        return result
+
+
+    def mkdir(self, name, mode=777):
+        'See IVFSDirectoryPublisher'
+        if not (name in self.context):
+            adding = getView(self.context, "+", self.request)
+            adding.setContentName(name)
+            add = queryView(adding, self._directory_type, self.request)
+            add()
+
+    def remove(self, name):
+        'See IVFSDirectoryPublisher'
+        container = removeAllProxies(self.context)
+        container.__delitem__(name)
+        # XXX: We should have a ObjectRemovedEvent here
+
+    def rmdir(self, name):
+        'See IVFSDirectoryPublisher'
+        self.remove(name)
+
+    def rename(self, old, new):
+        'See IVFSDirectoryPublisher'
+        container = self.context
+        content = container[old]
+        self.remove(old)
+        # Re-add the object
+        adding = getView(container, "+", self.request)
+        adding.setContentName(new)
+        content = adding.add(content)
+
+    def writefile(self, name, mode, instream, start=0):
+        'See IVFSDirectoryPublisher'
+        # Find the extension
+        ext_start = name.rfind('.')
+        if ext_start > 0:
+            ext = name[ext_start:]
+        else:
+            ext = "."
+
+        # Create and add a new content object.
+        adding = getView(self.context, "+", self.request)
+        adding.setContentName(name)
+        add = queryView(adding, ext, self.request)
+        if add is None:
+            # We do not know about this content type, so choose the generic
+            # one.
+            add = queryView(adding, ".", self.request)
+
+        add(mode, instream, start)
+
+    def check_writable(self, name):
+        'See IVFSDirectoryPublisher'
+        # XXX Cheesy band aid :-)
+        return 1
+
+    def isdir(self):
+        'See IVFSObjectPublisher'
+        return 1
+
+    def isfile(self):
+        'See IVFSObjectPublisher'
+        return 0
+
+    def stat(self):
+        'See IVFSObjectPublisher'
+        dc = getAdapter(self.context, IZopeDublinCore)
+        if dc is not None:
+            created = dc.created
+            modified = dc.modified
+        else:
+            created = zerotime
+            modified = zerotime
+
+        # Sometimes this value is not set, but we need to return a datetime
+        if created is None:
+            created = zerotime
+        # It happens that modified might still be None, so make sure we return
+        # a date. *nix then uses the created date as the modified one, which we
+        # do too. ;)
+        if modified is None:
+            modified = created
+
+        dir_mode = 16384 + 504
+        uid = "nouser"
+        gid = "nogroup"
+        return (dir_mode, 0, 0, 0, uid, gid, 4096, modified, modified,
+                created)
+
+
+    def publishTraverse(self, request, name):
+        'See IVFSPublisher'
+        # This is a nice way of doing the name lookup; this way we can keep
+        # all the extension handeling code in the Traverser code.
+        traverser = getView(self.context, '_traverse', request)
+        return traverser.publishTraverse(request, name)