[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/OFS/Content/File - File.py:1.2 FileChunk.py:1.2 FileFields.py:1.2 IFile.py:1.2 NaiveFile.py:1.2 __init__.py:1.2 file.zcml:1.2

Jim Fulton jim@zope.com
Mon, 10 Jun 2002 19:28:28 -0400


Update of /cvs-repository/Zope3/lib/python/Zope/App/OFS/Content/File
In directory cvs.zope.org:/tmp/cvs-serv17445/lib/python/Zope/App/OFS/Content/File

Added Files:
	File.py FileChunk.py FileFields.py IFile.py NaiveFile.py 
	__init__.py file.zcml 
Log Message:
Merged Zope-3x-branch into newly forked Zope3 CVS Tree.


=== Zope3/lib/python/Zope/App/OFS/Content/File/File.py 1.1 => 1.2 ===
+#
+# 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.
+# 
+##############################################################################
+"""
+
+$Id$
+"""
+
+import Persistence
+from types import StringType, NoneType
+from FileChunk import FileChunk
+from IFile import IFile
+
+# set the size of the chunks
+MAXCHUNKSIZE = 1 << 16
+
+class File(Persistence.Persistent):
+    """ """
+
+    __implements__ = IFile
+
+    def __init__(self, data='', contentType=None):
+        """ """
+
+        self.setData(data)
+
+        if contentType is None:
+            self._contentType = ''
+        else:
+            self._contentType = contentType
+        
+
+    def __len__(self):
+        return self.getSize()
+
+
+    ############################################################
+    # Implementation methods for interface
+    # Zope.App.OFS.IFile.IFile
+
+    def setContentType(self, contentType):
+        '''See interface IFile'''
+        self._contentType = contentType
+
+        
+    def getContentType(self):
+        '''See interface IFile'''
+        return self._contentType
+
+        
+    def edit(self, data, contentType=None):
+        '''See interface IFile'''
+
+        # XXX This seems broken to me, as setData can override the
+        # content type explicitly passed in.
+        
+        if contentType is not None:
+            self._contentType = contentType
+        self.setData(data)
+
+
+    def getData(self):
+        '''See interface IFile'''
+        if ( hasattr(self._data, '__class__')
+         and self._data.__class__ is FileChunk ):
+            return str(self._data)
+        else:
+            return self._data
+
+
+    def setData(self, data):
+        '''See interface IFile'''
+
+        # Handle case when data is a string
+        if isinstance(data, StringType):
+            size = len(data)
+            if size < MAXCHUNKSIZE:
+                self._data, self._size = FileChunk(data), size
+                return None
+            self._data, self._size = FileChunk(data), size
+            return None
+
+        # Handle case when data is a string
+        if isinstance(data, NoneType):
+            self._data, self._size = None, 0
+            return None
+
+        # Handle case when data is already a FileChunk
+        if hasattr(data, '__class__') and data.__class__ is FileChunk:
+            size = len(data)
+            self._data, self._size = data, size
+            return None
+
+        # Handle case when File is a file object
+        seek = data.seek
+        read = data.read
+        
+        seek(0, 2)
+        size = end = data.tell()
+
+        if size <= 2*MAXCHUNKSIZE:
+            seek(0)
+            if size < MAXCHUNKSIZE:
+                self._data, self._size = read(size), size
+                return None
+            self._data, self._size = FileChunk(read(size)), size
+            return None
+
+        # Make sure we have an _p_jar, even if we are a new object, by
+        # doing a sub-transaction commit.
+        get_transaction().commit(1)
+        
+        jar = self._p_jar
+        
+        if jar is None:
+            # Ugh
+            seek(0)
+            self._data, self._size = FileChunk(read(size)), size
+            return None
+
+        # Now we're going to build a linked list from back
+        # to front to minimize the number of database updates
+        # and to allow us to get things out of memory as soon as
+        # possible.
+        next = None
+        while end > 0:
+            pos = end - MAXCHUNKSIZE
+            if pos < MAXCHUNKSIZE:
+                pos = 0 # we always want at least MAXCHUNKSIZE bytes
+            seek(pos)
+            data = FileChunk(read(end - pos))
+            
+            # Woooop Woooop Woooop! This is a trick.
+            # We stuff the data directly into our jar to reduce the
+            # number of updates necessary.
+            data._p_jar = jar
+
+            # This is needed and has side benefit of getting
+            # the thing registered:
+            data.next = next
+            
+            # Now make it get saved in a sub-transaction!
+            get_transaction().commit(1)
+
+            # Now make it a ghost to free the memory.  We
+            # don't need it anymore!
+            data._p_changed = None
+            
+            next = data
+            end = pos
+        
+        self._data, self._size = next, size
+        return None
+
+
+    def getSize(self):
+        '''See interface IFile'''
+        return self._size
+
+    #
+    ############################################################
+
+


=== Zope3/lib/python/Zope/App/OFS/Content/File/FileChunk.py 1.1 => 1.2 ===
+#
+# 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.
+# 
+##############################################################################
+"""
+
+$Id$
+"""
+import Persistence
+
+class FileChunk(Persistence.Persistent):
+    # Wrapper for possibly large data
+
+    next = None
+    
+    def __init__(self, data):
+        self._data = data
+
+
+    def __getslice__(self, i, j):
+        return self._data[i:j]
+
+
+    def __len__(self):
+        data = str(self)
+        return len(data)
+
+
+    def __str__(self):
+        next = self.next
+        if next is None:
+            return self._data
+
+        result = [self.data]
+        while next is not None:
+            self = next
+            r.append(self._data)
+            next = self.next
+        
+        return ''.join(r)


=== Zope3/lib/python/Zope/App/OFS/Content/File/FileFields.py 1.1 => 1.2 ===
+#
+# 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.
+# 
+##############################################################################
+"""
+
+$Id$
+"""
+
+from Zope.App.Formulator.FieldRegistry import getField
+from Zope.App.Formulator.ValidatorRegistry import getValidator
+
+
+ContentTypeField = getField('StringField')(
+    id = 'contentType',
+    title = 'Content Type',
+    description = 'The content type identifies the type of data.',
+    default = 'text/plain',
+    )
+
+
+DataField = getField('FileField')(
+    id = 'data',
+    title = 'Data',
+    description = 'The actual content of the object.',
+    )


=== Zope3/lib/python/Zope/App/OFS/Content/File/IFile.py 1.1 => 1.2 ===
+#
+# 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.
+# 
+##############################################################################
+"""
+
+$Id$
+"""
+
+from Interface import Interface
+from Zope.App.OFS.Content.IFileContent import IFileContent
+
+class IReadFile(IFileContent):
+    
+
+    def getData():
+        """Returns the bits (data) of the File itself."""
+
+
+    def getContentType():
+        """Returns the content type of the file using mime-types syntax."""
+
+
+    def getSize():
+        """Return the size of the file.
+
+        Note that only the file's content is counted and not the entire
+        Python object.
+        """
+
+class IWriteFile(Interface):
+
+
+    def edit(data, contentType=None):
+        """Sets the data and the content type for the object.
+
+           Since some implementations will provide their content type
+           through the data, it is good to leave the argument optional.
+        """
+
+
+    def setData(data):
+        """Sets ONLY the data without changing the content type."""
+
+
+    def setContentType(contentType):
+        """Sets the content type of the file."""
+
+
+class IFile(IReadFile, IWriteFile):
+    """The basic methods that are required to implement
+       a file as a Zope Content object.
+
+    """
+        


=== Zope3/lib/python/Zope/App/OFS/Content/File/NaiveFile.py 1.1 => 1.2 ===
+#
+# 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.
+# 
+##############################################################################
+"""
+
+$Id$
+"""
+
+import Persistence
+from IFile import IFile
+from Zope.App.OFS.Annotation.IAnnotatable import IAnnotatable
+
+
+_RAISE_KEYERROR = []
+
+
+class NaiveFile:
+    """This is a very simple implementation of a file.
+
+    WARNING: This implementation should not be used to save large amounts
+             of Data.
+    """
+
+    __implements__ = (
+        IFile,
+        IAnnotatable)
+
+
+    def __init__(self, data='', contentType=None):
+        """ """
+
+        self.setData(data)
+
+        if contentType is None:
+            self._contentType = ''
+        else:
+            self._contentType = contentType
+
+
+    def __str__(self):
+        return self.getData()
+
+
+    def __len__(self):
+        return 1
+        
+
+    ############################################################
+    # Implementation methods for interface
+    # Zope.App.OFS.File.IFile
+
+    def setContentType(self, contentType):
+        '''See interface IFile'''
+        self._contentType = contentType
+
+        
+    def getContentType(self):
+        '''See interface IFile'''
+        return self._contentType
+
+        
+    def edit(self, data, contentType=None):
+        '''See interface IFile'''
+        self._data = data
+        if contentType is not None:
+            self._contentType = contentType
+
+
+    def getData(self):
+        '''See interface IFile'''
+        return self._data
+
+
+    def setData(self, data):
+        '''See interface IFile'''
+        if data is not None:
+            self._size = len(data)
+        else:
+            self._size = 0
+        self._data = data
+
+
+    def getSize(self):
+        '''See interface IFile'''
+        return self._size
+        
+    #
+    ############################################################
+
+


=== Zope3/lib/python/Zope/App/OFS/Content/File/__init__.py 1.1 => 1.2 ===
+#
+# 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.
+# 
+##############################################################################
+"""
+
+$Id$
+"""


=== Zope3/lib/python/Zope/App/OFS/Content/File/file.zcml 1.1 => 1.2 ===
+   xmlns='http://namespaces.zope.org/zope'
+   xmlns:security='http://namespaces.zope.org/security'
+   xmlns:zmi='http://namespaces.zope.org/zmi'
+>
+
+  <!-- NaiveFile Directives -->
+
+  <security:permission id="Zope.AddNaiveFiles" 
+                       title="Add Naive Files" />
+
+  <content class=".NaiveFile.">
+    <zmi:factory
+        id="NaiveFile"
+        permission="Zope.AddNaiveFiles"
+        title="Naive File"
+        description="This is a simple file" />
+    <security:require
+        permission="Zope.View" />
+  </content>
+
+
+  <!-- File Directives -->
+
+  <security:permission id="Zope.AddFiles" title="Add Files" />
+
+  <content class=".File.">
+    <zmi:factory
+        id="File"
+        permission="Zope.ManageContent"
+        title="File"
+        description="A File" />
+    <security:require
+        permission="Zope.View" />
+    <security:require
+        permission="Zope.View"
+        interface=".IFile.IReadFile" />
+    <security:require
+        permission="Zope.ManageContent"
+        interface=".IFile.IWriteFile" />
+  </content>
+
+  <adapter
+      factory="Zope.App.OFS.Annotation.AttributeAnnotations."
+      provides="Zope.App.OFS.Annotation.IAnnotations."
+      for=".IFile." />
+
+
+  <!-- tabs for folder -->
+
+  <zmi:tabs for=".IFile.">
+    <zmi:tab label="View" action="."/>
+    <zmi:tab label="Edit" action="editForm.html"/>
+    <zmi:tab label="Role Permissions" 
+             action="AllRolePermissions.html"/>
+  </zmi:tabs>
+
+  <!-- Further Directives -->
+
+  <include package=".Views" file="views.zcml" />
+
+</zopeConfigure>
+
+