[Zope3-checkins] CVS: Zope3/lib/python/Zope/App/OFS/Container/Views/VFS - VFSContainerView.py:1.4
Stephan Richter
srichter@cbu.edu
Fri, 20 Dec 2002 04:26:08 -0500
Update of /cvs-repository/Zope3/lib/python/Zope/App/OFS/Container/Views/VFS
In directory cvs.zope.org:/tmp/cvs-serv31450/Zope/App/OFS/Container/Views/VFS
Modified Files:
VFSContainerView.py
Log Message:
Refactoring and fixing VFS and FTP
I am glad to make this commit that fixes up a lot of the FTP
implementation. I fixed the behavior of many of the FTP commands,
including LIST, SIZE, and CWD.
I moved the original VFSFile/DirectoryView into abstract classes and wrote
a special implementation for each content type, which makes the code much
more flexible.
Also I finally implemented a smart way of adding files via VFS through
file extension introspection, based on Jim's ExtensionViewName proposal.
I am adding documentation in the DevelCookbook right now and will later
add a README file.
TODOs:
- make VFS View names flexible, so that file extensions specify views.
- Simplify ZCML directives, so that one can add new extensions for Add views
quicker. A solution might look like that:
<vfs:view
name=".dtml"
for="Zope.App.OFS.Container.IAdding."
factory=".DTMLPageAdd."
permission="Zope.ManageContent">
<vfs:extension name=".html" />
<vfs:extension name=".xul" />
<vfs:extension name=".xml" />
...
</vfs:view>
This method would also be good for defining a default fiel extension.
- Show an object with its default file extension.
=== Zope3/lib/python/Zope/App/OFS/Container/Views/VFS/VFSContainerView.py 1.3 => 1.4 ===
--- Zope3/lib/python/Zope/App/OFS/Container/Views/VFS/VFSContainerView.py:1.3 Sat Jun 29 11:41:37 2002
+++ Zope3/lib/python/Zope/App/OFS/Container/Views/VFS/VFSContainerView.py Fri Dec 20 04:25:37 2002
@@ -11,30 +11,39 @@
# 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 time
+import datetime
+zerotime = datetime.datetime.fromtimestamp(0)
+
+from Zope.ComponentArchitecture import \
+ getView, queryView, getAdapter, queryAdapter, createObject
+
+from Zope.Proxy.ProxyIntrospection import removeAllProxies
-from Zope.ComponentArchitecture import getView
+from Zope.Publisher.Exceptions import NotFound
from Zope.Publisher.VFS.VFSView import VFSView
from Zope.Publisher.VFS.IVFSPublisher import IVFSPublisher
from Zope.Publisher.VFS.VFSRequest import VFSRequest
-
from Zope.Publisher.VFS.IVFSDirectoryPublisher import IVFSDirectoryPublisher
-from Zope.App.OFS.Container.IContainer import IContainer
-# XXX hard coded object types.
-from Zope.App.OFS.Content.File.File import File
-from Zope.App.OFS.Content.Folder.Folder import Folder
+from Zope.App.OFS.Container.IContainer import IContainer
+from Zope.App.DublinCore.IZopeDublinCore 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'
############################################################
# Implementation methods for interface
@@ -42,12 +51,14 @@
def exists(self, name):
'See Zope.Publisher.VFS.IVFSDirectoryPublisher.IVFSDirectoryPublisher'
- return name in self.context
-
+ try:
+ self.publishTraverse(self.request, name)
+ except NotFound:
+ return 0
+ return 1
def listdir(self, with_stats=0, pattern='*'):
'See Zope.Publisher.VFS.IVFSDirectoryPublisher.IVFSDirectoryPublisher'
- t = time.time()
file_list = self.context.keys()
# filter them using the pattern
file_list = list(
@@ -61,55 +72,67 @@
result = []
for file in file_list:
obj = self.context[file]
- size = 0
- # XXX Should be much nicer
- if IContainer.isImplementedBy(obj):
- dir_mode = 16384 + 511
+ view = queryView(obj, 'vfs', self.request)
+ if view is not None:
+ stat = view.stat()
else:
- dir_mode = 511
- if hasattr(obj, 'getSize'):
- size = obj.getSize()
- stat = (dir_mode, 0, 0, 0, 0, 0, size, t, t, t)
- if stat is not None:
- result.append((file, stat))
+ # 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 Zope.Publisher.VFS.IVFSDirectoryPublisher.IVFSDirectoryPublisher'
if not (name in self.context):
- obj = Folder()
- self.context.setObject(name, obj)
+ adding = getView(self.context, "+", self.request)
+ adding.setContentName(name)
+ add = queryView(adding, self._directory_type, self.request)
+ add()
def remove(self, name):
'See Zope.Publisher.VFS.IVFSDirectoryPublisher.IVFSDirectoryPublisher'
- del self.context[name]
+ container = removeAllProxies(self.context)
+ container.__delitem__(name)
+ # XXX: We should have a ObjectRemovedEvent here
def rmdir(self, name):
'See Zope.Publisher.VFS.IVFSDirectoryPublisher.IVFSDirectoryPublisher'
- del self.context[name]
+ self.remove(name)
def rename(self, old, new):
'See Zope.Publisher.VFS.IVFSDirectoryPublisher.IVFSDirectoryPublisher'
- obj = self.context[old]
- del self.context[old]
- self.context.setObject(new, obj)
-
+ 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 Zope.Publisher.VFS.IVFSDirectoryPublisher.IVFSDirectoryPublisher'
- # XXX This should become much, much smarter later. Based on the
- # data and the file ending, it should pick the right object type.
- # *** Waiting for Jim's file extension proposal and code to land ***
- if not (name in self.context):
- obj = File()
- self.context.setObject(name, obj)
+ # Find the extension
+ ext_start = name.rfind('.')
+ if ext_start > 0:
+ ext = name[ext_start:]
else:
- obj = self.context[name]
+ ext = "."
- vfs_view = getView(obj, 'vfs', self.request)
- vfs_view.write(mode, instream, start)
+ # 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 Zope.Publisher.VFS.IVFSDirectoryPublisher.IVFSDirectoryPublisher'
# XXX Cheesy band aid :-)
@@ -129,11 +152,25 @@
def stat(self):
'See Zope.Publisher.VFS.IVFSObjectPublisher.IVFSObjectPublisher'
- dir_mode = 16384
- t = time.time()
- uid = 0
- gid = 0
- return (dir_mode+512, 0, 0, 0, uid, gid, 4096, t, t, t)
+ dc = getAdapter(self.context, IZopeDublinCore)
+ if dc is not None:
+ created = dc.created
+ modified = dc.modified
+ else:
+ created = zerotime
+ modified = 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)
######################################
@@ -141,7 +178,12 @@
def publishTraverse(self, request, name):
'See Zope.Publisher.VFS.IVFSPublisher.IVFSPublisher'
- return getattr(self, name)
+ # 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)
#
############################################################
+
+