[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/OFS/File - File.py:1.1.2.1 FileChunk.py:1.1.2.1 FileEdit.py:1.1.2.1 IFile.py:1.1.2.1 NaiveFile.py:1.1.2.2 NaiveFileEdit.py:NONE

Stephan Richter srichter@cbu.edu
Mon, 21 Jan 2002 12:42:07 -0500


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

Modified Files:
      Tag: Zope-3x-branch
	NaiveFile.py 
Added Files:
      Tag: Zope-3x-branch
	File.py FileChunk.py FileEdit.py IFile.py 
Removed Files:
      Tag: Zope-3x-branch
	NaiveFileEdit.py 
Log Message:
NaiveFile and File:

- I fixed the Interface to also return the size of the file
- Implemented a real file that saves data chunks a la Zope 2
- Cleaned up the API, so that both NaiveFile and File can use the same 
  views, which I think is what Zope 3 is all about.
- TODO: Support File upload from the Web.

Image:

- Cleaned up API and methods
- renamed Interface method getSize() to getImageSize()
- Image now inherits File instead of NaiveFile



=== Added File Zope3/lib/python/Zope/App/OFS/File/File.py ===
# This software is subject to the provisions of the Zope Public License,
# Version 1.1 (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.

import Persistence
from types import StringType, NoneType
from FileChunk import FileChunk
from IFile import IFile
from Zope.App.Security.IAttributeRolePermissionManageable \
     import IAttributeRolePermissionManageable

# set the size of the chunks
MAXCHUNKSIZE = 1 << 16

class File(Persistence.Persistent):
    """ """

    __implements__ = IFile


    def __init__(self, data=None, 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.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'''
        self.setData(data)
        if contentType is not None:
            self._contentType = contentType


    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 type(data) is 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 type(data) is 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 < n:
                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

    #
    ############################################################
                                                                                



=== Added File Zope3/lib/python/Zope/App/OFS/File/FileChunk.py ===
# This software is subject to the provisions of the Zope Public License,
# Version 1.1 (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.

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)


=== Added File Zope3/lib/python/Zope/App/OFS/File/FileEdit.py ===
# This software is subject to the provisions of the Zope Public License,
# Version 1.1 (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 view component for naive file editing.
"""

import os

from Zope.Publisher.Browser.AttributePublisher import AttributePublisher
from Zope.PageTemplate.PageTemplateFile import PageTemplateFile


class FileEdit( AttributePublisher ):

    __implements__ = AttributePublisher.__implements__
    
    def __init__( self, file ):
        self._file = file


    def edit(self, data, contentType, REQUEST=None):

        file = self.getContext()
        file.edit(data, contentType)

        if REQUEST is not None:
            return self.index(REQUEST, msg='File Edited.')


    def getContext( self ):
        return self._file

    index = PageTemplateFile('edit.pt')


=== Added File Zope3/lib/python/Zope/App/OFS/File/IFile.py ===
# This software is subject to the provisions of the Zope Public License,
# Version 1.1 (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 Interface import Interface


class IFile(Interface):
    """This interface describes the basic methods that are required to implement
    a file as a Zope Content object.

    """


    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 getData():
        """Returns the bits (data) of the File itself."""


    def setContentType(contentType):
        """Sets the content type of the file."""


    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.
        """
        


=== Zope3/lib/python/Zope/App/OFS/File/NaiveFile.py 1.1.2.1 => 1.1.2.2 ===
 
 import Persistence
-from Interface import Interface
+from IFile import IFile
 from Zope.App.Security.IAttributeRolePermissionManageable \
      import IAttributeRolePermissionManageable
 
 
-class INaiveFile(Interface):
-    """This is a simple implementation of a File in Zope.
-
-    Warning: You should not use this interface to implement large data
-             files.
-    """
-
-    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 getData():
-        """Returns the bits (data) of the File itself."""
-
-
-    def setContentType(contentType):
-        """Sets the content type of the file."""
-
-
-    def getContentType():
-        """Returns the content type of the file using mime-types syntax."""
-
-
-
 _RAISE_KEYERROR = []
 
 
-class NaiveFile(Persistence.Persistent):
-    """ """
+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__ = INaiveFile
+    __implements__ = IFile
 
 
     def __init__(self, data=None, contentType=None):
         """ """
 
-        self._data = data
+        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.NaiveFile.INaiveFile
+    # Zope.App.OFS.File.IFile
 
     def setContentType(self, contentType):
-        '''See interface INaiveFile'''
+        '''See interface IFile'''
         self._contentType = contentType
 
         
     def getContentType(self):
-        '''See interface INaiveFile'''
+        '''See interface IFile'''
         return self._contentType
 
         
     def edit(self, data, contentType=None):
-        '''See interface INaiveFile'''
+        '''See interface IFile'''
         self._data = data
         if contentType is not None:
             self._contentType = contentType
 
 
     def getData(self):
-        '''See interface INaiveFile'''
+        '''See interface IFile'''
         return self._data
 
 
     def setData(self, data):
-        '''See interface INaiveFile'''
+        '''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
         
     #
     ############################################################

=== Removed File Zope3/lib/python/Zope/App/OFS/File/NaiveFileEdit.py ===