[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>
+
+