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

Stephan Richter srichter@cbu.edu
Wed, 27 Mar 2002 10:54:36 -0500


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

Added Files:
      Tag: Zope-3x-branch
	File.py FileChunk.py FileEdit.py FileFields.py IFile.py 
	NaiveFile.py __init__.py edit.pt file.zcml 
Log Message:
New Content Objects:

- NaiveFile --> all the data is stored in one string
- File --> Uses a BTree to store the data in chunks (more efficient)
- Image --> Can store and display an image a la Z2 (based on File)
- ZPTPage --> A simple version of ZPT for the content space to allow some 
  dynamics data (please do not use this for scripting)

Also:

- Expansion of supported views
- all edit screens are Formulator supported



=== Added File Zope3/lib/python/Zope/App/OFS/Content/File/File.py ===
##############################################################################
#
# 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: File.py,v 1.1.2.1 2002/03/27 15:54:35 srichter Exp $
"""

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,
        IAttributeRolePermissionManageable,
        )      


    def __init__(self, data=None, 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'''
        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 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 < 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/Content/File/FileChunk.py ===
##############################################################################
#
# 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: FileChunk.py,v 1.1.2.1 2002/03/27 15:54:35 srichter Exp $
"""
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/Content/File/FileEdit.py ===
##############################################################################
#
# Copyright (c) 2001 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 view component for naive file editing.
"""

from Zope.App.Formulator.Form import Form
from Zope.PageTemplate.PageTemplateFile import PageTemplateFile


class FileEdit(Form):

    __implements__ = Form.__implements__

    name = 'editForm'     
    title = 'Edit Form'
    description = ('This edit form allows you to make changes to the ' +
                   'properties of this file.')

    _fieldViewNames = ['ContentTypeFieldView', 'DataFieldView']
    template = PageTemplateFile('edit.pt')



=== Added File Zope3/lib/python/Zope/App/OFS/Content/File/FileFields.py ===
##############################################################################
#
# 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: FileFields.py,v 1.1.2.1 2002/03/27 15:54:35 srichter Exp $
"""

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.',
    )


=== Added File Zope3/lib/python/Zope/App/OFS/Content/File/IFile.py ===
##############################################################################
#
# 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: IFile.py,v 1.1.2.1 2002/03/27 15:54:35 srichter Exp $
"""

from Interface import Interface


class IFile(Interface):
    """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.
        """
        


=== Added File Zope3/lib/python/Zope/App/OFS/Content/File/NaiveFile.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. 
# All Rights Reserved.
#
# 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.
##############################################################################
"""

$Id: NaiveFile.py,v 1.1.2.1 2002/03/27 15:54:35 srichter Exp $
"""

import Persistence
from IFile import IFile
from Zope.App.Security.IAttributeRolePermissionManageable \
     import IAttributeRolePermissionManageable


_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,
        IAttributeRolePermissionManageable)


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




=== Added File Zope3/lib/python/Zope/App/OFS/Content/File/__init__.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. 
# All Rights Reserved.
#
# 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.
##############################################################################
"""

$Id: __init__.py,v 1.1.2.1 2002/03/27 15:54:35 srichter Exp $
"""


=== Added File Zope3/lib/python/Zope/App/OFS/Content/File/edit.pt ===
<html metal:use-macro="views/standard_macros/page">
  <head>
    <style metal:fill-slot="headers" type="text/css">
      <!--
      .ContentIcon {
	  width: 20px;
      }
      
      .ContentTitle {
	  text-align: left;
      }
      -->
    </style>
  </head>

  <body>
    <div metal:fill-slot="body">

 
      <p tal:content="here/msg"
         tal:condition="python: hasattr(here, 'msg')">
        Message will go here.
      </p>

      <p tal:content="container/description">
        Description of the Form.
      </p>


      <div tal:condition="python: options.has_key('errors') and options['errors']">
        Errors:
        <div tal:repeat="error options/errors | nothing"
             tal:content="error">Foo </div>
      </div>

      <form action="action" method="post">

        <table class="EditTable">      
	  <tbody>   
  
	    <tr tal:repeat="fieldView python:container.getFieldViews(request)">
	      <th class="EditAttributeName"
                  tal:content="python: fieldView.getContext().getValue('title')">Title</th>
	      <td class="EditAttributeValue"
	          tal:content="structure fieldView/render"><input />
              </td>
	    </tr>
  
	  </tbody>     
      </table>

      <input type="submit" name="edit" value="Save Changes">

      </form> 

    </div>
  </body>
</html>




=== Added File Zope3/lib/python/Zope/App/OFS/Content/File/file.zcml ===
<zopeConfigure
   xmlns='http://namespaces.zope.org/zope'
   xmlns:security='http://namespaces.zope.org/security'
   xmlns:zmi='http://namespaces.zope.org/zmi'
>

  <!-- NaiveFile Directives -->

  <security:permission permission_id="Zope.AddNaiveFiles" 
                       title="Add Naive Files" />

  <zmi:provideClass name=".NaiveFile."
                    permission_id="Zope.AddNaiveFiles"
                    title="Naive File"
                    description="This is a simple file" />

  <security:protectClass name=".NaiveFile."
                         permission_id="Zope.View" />


  <!-- File Directives -->

  <security:permission permission_id="Zope.AddFiles" title="Add Files" />

  <zmi:provideClass name=".File."
                    permission_id="Zope.AddFiles"
                    title="File"
                    description="A File" />

  <security:protectClass name=".File."
                         permission_id="Zope.View" />


  <!-- tabs for folder -->

  <zmi:tabs for=".IFile.">
    <zmi:tab label="View" action=""/>
    <zmi:tab label="Edit" action="edit;view"/>
    <zmi:tab label="Role Permissions" action="RolePermissionsManagement;view"/>
  </zmi:tabs>

  <!-- Further Directives -->

  <include package=".Views" file="views.zcml" />

</zopeConfigure>