[Checkins] SVN: z3c.blobfile/tags/0.1.3/ Prepare the 0.1.3 release.

Dan Korostelev nadako at gmail.com
Mon Oct 20 04:37:14 EDT 2008


Log message for revision 92392:
  Prepare the 0.1.3 release.

Changed:
  A   z3c.blobfile/tags/0.1.3/
  D   z3c.blobfile/tags/0.1.3/CHANGES.txt
  A   z3c.blobfile/tags/0.1.3/CHANGES.txt
  D   z3c.blobfile/tags/0.1.3/setup.py
  A   z3c.blobfile/tags/0.1.3/setup.py
  D   z3c.blobfile/tags/0.1.3/src/z3c/blobfile/browser/configure.zcml
  A   z3c.blobfile/tags/0.1.3/src/z3c/blobfile/browser/configure.zcml
  D   z3c.blobfile/tags/0.1.3/src/z3c/blobfile/browser/file.py
  A   z3c.blobfile/tags/0.1.3/src/z3c/blobfile/browser/file.py
  D   z3c.blobfile/tags/0.1.3/src/z3c/blobfile/configure.zcml
  A   z3c.blobfile/tags/0.1.3/src/z3c/blobfile/configure.zcml
  D   z3c.blobfile/tags/0.1.3/src/z3c/blobfile/file.py
  A   z3c.blobfile/tags/0.1.3/src/z3c/blobfile/file.py
  D   z3c.blobfile/tags/0.1.3/src/z3c/blobfile/image.py
  A   z3c.blobfile/tags/0.1.3/src/z3c/blobfile/image.py
  D   z3c.blobfile/tags/0.1.3/src/z3c/blobfile/interfaces.py
  A   z3c.blobfile/tags/0.1.3/src/z3c/blobfile/interfaces.py

-=-
Copied: z3c.blobfile/tags/0.1.3 (from rev 92387, z3c.blobfile/trunk)

Deleted: z3c.blobfile/tags/0.1.3/CHANGES.txt
===================================================================
--- z3c.blobfile/trunk/CHANGES.txt	2008-10-19 15:49:40 UTC (rev 92387)
+++ z3c.blobfile/tags/0.1.3/CHANGES.txt	2008-10-20 08:37:13 UTC (rev 92392)
@@ -1,31 +0,0 @@
-=======
-CHANGES
-=======
-
-Version 0.1.3 (unreleased)
---------------------------
-
--
-
-Version 0.1.2 (2008-09-11)
---------------------------
-
-- Bug: Set i18n domain in "overrides.zcml" to avoid warnings.
-- Don't expose Blob implementation details in add/upload forms. Also, "zope"
-  translation domain has no translations for "Upload a File (Blob)", it just
-  has "Upload a File" translations, so use it.
-
-Version 0.1.1 (2008-09-08)
---------------------------
-
-- Bug: Register zope.app.wsgi.fileresult.FileResult as an adapter for BlobFile,
-  making optimized file views really work.
-- Bug: Also use optimized file view for z3c.blobfile.image.Image.
-- Bug: Make blob versions of File and Image implement IBlobFile and
-  IBlobImage interfaces respectively. This enables z3c.blobfile's views.
-- Bug: Use local ZopeMessageFactory. This fixes import error on Zope 2.10
-
-Version 0.1.0 (2008-02-27)
---------------------------
-
-- Initial Release

Copied: z3c.blobfile/tags/0.1.3/CHANGES.txt (from rev 92388, z3c.blobfile/trunk/CHANGES.txt)
===================================================================
--- z3c.blobfile/tags/0.1.3/CHANGES.txt	                        (rev 0)
+++ z3c.blobfile/tags/0.1.3/CHANGES.txt	2008-10-20 08:37:13 UTC (rev 92392)
@@ -0,0 +1,35 @@
+=======
+CHANGES
+=======
+
+Version 0.1.3 (2008-10-20)
+--------------------------
+
+- Bug: Don't get/set image data twice on Image initialization.
+- Cache file size and invalidate it on write access.
+- Download file/image using new openDetached method that provides
+  read-only file-like access to the blob, detached from the database
+  connection.
+
+Version 0.1.2 (2008-09-11)
+--------------------------
+
+- Bug: Set i18n domain in "overrides.zcml" to avoid warnings.
+- Don't expose Blob implementation details in add/upload forms. Also, "zope"
+  translation domain has no translations for "Upload a File (Blob)", it just
+  has "Upload a File" translations, so use it.
+
+Version 0.1.1 (2008-09-08)
+--------------------------
+
+- Bug: Register zope.app.wsgi.fileresult.FileResult as an adapter for BlobFile,
+  making optimized file views really work.
+- Bug: Also use optimized file view for z3c.blobfile.image.Image.
+- Bug: Make blob versions of File and Image implement IBlobFile and
+  IBlobImage interfaces respectively. This enables z3c.blobfile's views.
+- Bug: Use local ZopeMessageFactory. This fixes import error on Zope 2.10
+
+Version 0.1.0 (2008-02-27)
+--------------------------
+
+- Initial Release

Deleted: z3c.blobfile/tags/0.1.3/setup.py
===================================================================
--- z3c.blobfile/trunk/setup.py	2008-10-19 15:49:40 UTC (rev 92387)
+++ z3c.blobfile/tags/0.1.3/setup.py	2008-10-20 08:37:13 UTC (rev 92392)
@@ -1,82 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2008 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.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.
-#
-##############################################################################
-"""Setup for z3c.blobfile package
-
-$Id$
-"""
-import os
-from setuptools import setup, find_packages
-
-def read(*rnames):
-    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
-
-setup(name='z3c.blobfile',
-      version='0.1.3dev',
-      author = "Zope Community",
-      author_email = "zope3-dev at zope.org",
-      license = "ZPL 2.1",
-      keywords = "zope3 ZODB blob file image content",
-      url='http://pypi.python.org/pypi/z3c.blobfile',
-      description='File and Image Using Blob Support of ZODB -- Zope 3 Content Components',
-      long_description=(
-          read('README.txt')
-          + '\n\n' +
-          'Detailed Documentation\n' +
-          '----------------------\n'
-          + '\n\n' +
-          read('src', 'z3c', 'blobfile', 'blobfile.txt')
-          + '\n\n' +
-          read('CHANGES.txt')
-          ),
-      classifiers = [
-          'Development Status :: 4 - Beta',
-          'Environment :: Web Environment',
-          'Intended Audience :: Developers',
-          'License :: OSI Approved :: Zope Public License',
-          'Programming Language :: Python',
-          'Natural Language :: English',
-          'Operating System :: OS Independent',
-          'Topic :: Internet :: WWW/HTTP',
-          'Framework :: Zope3'],
-
-      packages=find_packages('src'),
-      package_dir = {'': 'src'},
-      
-      namespace_packages=['z3c'],
-      
-      extras_require = dict(test=['zope.app.file',
-                                  'zope.app.testing',
-                                  'zope.app.securitypolicy',
-                                  'zope.app.zcmlfiles',
-                                  'zope.testbrowser']),
-      install_requires=['setuptools',
-                        'ZODB3',
-                        'zope.app.publication',
-                        'zope.contenttype',
-                        'zope.datetime',
-                        'zope.dublincore',
-                        'zope.event',
-                        'zope.exceptions',
-                        'zope.i18nmessageid',
-                        'zope.interface',
-                        'zope.publisher',
-                        'zope.schema',
-                        'zope.size',
-                        'zope.app.file',
-                        
-                        ],
-      include_package_data = True,
-      zip_safe = False,
-      )
-

Copied: z3c.blobfile/tags/0.1.3/setup.py (from rev 92390, z3c.blobfile/trunk/setup.py)
===================================================================
--- z3c.blobfile/tags/0.1.3/setup.py	                        (rev 0)
+++ z3c.blobfile/tags/0.1.3/setup.py	2008-10-20 08:37:13 UTC (rev 92392)
@@ -0,0 +1,82 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.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.
+#
+##############################################################################
+"""Setup for z3c.blobfile package
+
+$Id$
+"""
+import os
+from setuptools import setup, find_packages
+
+def read(*rnames):
+    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+setup(name='z3c.blobfile',
+      version='0.1.3',
+      author = "Zope Community",
+      author_email = "zope3-dev at zope.org",
+      license = "ZPL 2.1",
+      keywords = "zope3 ZODB blob file image content",
+      url='http://pypi.python.org/pypi/z3c.blobfile',
+      description='File and Image Using Blob Support of ZODB -- Zope 3 Content Components',
+      long_description=(
+          read('README.txt')
+          + '\n\n' +
+          'Detailed Documentation\n' +
+          '----------------------\n'
+          + '\n\n' +
+          read('src', 'z3c', 'blobfile', 'blobfile.txt')
+          + '\n\n' +
+          read('CHANGES.txt')
+          ),
+      classifiers = [
+          'Development Status :: 4 - Beta',
+          'Environment :: Web Environment',
+          'Intended Audience :: Developers',
+          'License :: OSI Approved :: Zope Public License',
+          'Programming Language :: Python',
+          'Natural Language :: English',
+          'Operating System :: OS Independent',
+          'Topic :: Internet :: WWW/HTTP',
+          'Framework :: Zope3'],
+
+      packages=find_packages('src'),
+      package_dir = {'': 'src'},
+      
+      namespace_packages=['z3c'],
+      
+      extras_require = dict(test=['zope.app.file',
+                                  'zope.app.testing',
+                                  'zope.app.securitypolicy',
+                                  'zope.app.zcmlfiles',
+                                  'zope.testbrowser']),
+      install_requires=['setuptools',
+                        'ZODB3',
+                        'zope.app.publication',
+                        'zope.contenttype',
+                        'zope.datetime',
+                        'zope.dublincore',
+                        'zope.event',
+                        'zope.exceptions',
+                        'zope.i18nmessageid',
+                        'zope.interface',
+                        'zope.publisher',
+                        'zope.schema',
+                        'zope.size',
+                        'zope.app.file',
+                        
+                        ],
+      include_package_data = True,
+      zip_safe = False,
+      )
+

Deleted: z3c.blobfile/tags/0.1.3/src/z3c/blobfile/browser/configure.zcml
===================================================================
--- z3c.blobfile/trunk/src/z3c/blobfile/browser/configure.zcml	2008-10-19 15:49:40 UTC (rev 92387)
+++ z3c.blobfile/tags/0.1.3/src/z3c/blobfile/browser/configure.zcml	2008-10-20 08:37:13 UTC (rev 92392)
@@ -1,131 +0,0 @@
-<configure
-    xmlns="http://namespaces.zope.org/browser"
-    xmlns:zope="http://namespaces.zope.org/zope"
-    i18n_domain="zope"
-    >
-
-  <!-- IResult adapter for opened BlobFiles -->
-  <zope:adapter
-      for="ZODB.blob.BlobFile"
-      provides="zope.publisher.http.IResult"
-      factory="zope.app.wsgi.fileresult.FileResult"
-      />
-
-  <!-- directives for File -->
-  
-  <form
-      name="edit.html"
-      for="z3c.blobfile.interfaces.IBlobFile"
-      schema="zope.app.file.browser.file.IFileEditForm"
-      label="Change a file"
-      permission="zope.ManageContent"
-      class="zope.app.file.browser.file.FileEdit"
-      />
-
-  <menuItem
-      menu="zmi_views" title="Edit"
-      for="z3c.blobfile.interfaces.IBlobFile"
-      action="edit.html"
-      filter="python:context.contentType.startswith('text/')"
-      permission="zope.ManageContent"
-      />
-
-  <page
-      name="upload.html"
-      menu="zmi_views" title="Upload"
-      for="z3c.blobfile.interfaces.IBlobFile"
-      template="file_upload.pt"
-      class="zope.app.file.browser.file.FileUpload"
-      permission="zope.ManageContent"
-      />
-
-  <page
-      for="z3c.blobfile.interfaces.IBlobFile"
-      name="index.html"
-      permission="zope.View"
-      class="z3c.blobfile.browser.file.FileView"
-      attribute="show"
-      />
-
-  <addMenuItem
-      class="z3c.blobfile.file.File"
-      title="File"
-      description="A File"
-      permission="zope.ManageContent"
-      view="z3c.blobfile.file.File"
-      />
-
-  <page
-      name="z3c.blobfile.file.File"
-      for="zope.app.container.interfaces.IAdding"
-      template="file_add.pt"
-      class=".file.FileAdd"
-      permission="zope.ManageContent"
-      />
-
-  <icon
-      name="zmi_icon"
-      for="z3c.blobfile.interfaces.IBlobFile"
-      file="file_icon.gif"
-      />
-
-  <!-- Directives for Image -->
-
-  <editform
-      schema="z3c.blobfile.interfaces.IBlobImage"
-      name="upload.html"
-      menu="zmi_views" title="Upload"
-      label="Upload an image"
-      permission="zope.ManageContent"
-      class="zope.app.file.browser.image.ImageUpload"
-      template="image_edit.pt"
-      />
-
-  <page
-      name="index.html"
-      for="z3c.blobfile.interfaces.IBlobImage"
-      permission="zope.View"
-      allowed_attributes="__call__ tag"
-      class=".image.ImageData"
-      />
-
-  <icon
-      name="zmi_icon"
-      for="z3c.blobfile.interfaces.IBlobImage"
-      file="image_icon.gif"
-      />
-
-  <addMenuItem
-      class="z3c.blobfile.image.Image"
-      title="Image"
-      description="An Image"
-      permission="zope.ManageContent"
-      view="z3c.blobfile.image.Image"
-      />
-
-  <addform
-      schema="z3c.blobfile.interfaces.IBlobImage"
-      label="Add an Image"
-      content_factory="z3c.blobfile.image.Image"
-      class="zope.app.file.browser.image.ImageAdd"
-      name="z3c.blobfile.image.Image"
-      permission="zope.ManageContent"
-      />
-
-    <page
-        for="z3c.blobfile.interfaces.IBlobFile"
-        name="preview.html"
-        template="preview.pt"
-        permission="zope.ManageContent"
-        menu="zmi_views" title="Preview"
-        />
-
-    <page
-        for="z3c.blobfile.interfaces.IBlobImage"
-        name="preview.html"
-        template="preview.pt"
-        permission="zope.ManageContent"
-        menu="zmi_views" title="Preview"
-        />
-
-</configure>

Copied: z3c.blobfile/tags/0.1.3/src/z3c/blobfile/browser/configure.zcml (from rev 92388, z3c.blobfile/trunk/src/z3c/blobfile/browser/configure.zcml)
===================================================================
--- z3c.blobfile/tags/0.1.3/src/z3c/blobfile/browser/configure.zcml	                        (rev 0)
+++ z3c.blobfile/tags/0.1.3/src/z3c/blobfile/browser/configure.zcml	2008-10-20 08:37:13 UTC (rev 92392)
@@ -0,0 +1,120 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    i18n_domain="zope"
+    >
+
+	<!-- directives for File -->
+
+	<browser:addMenuItem
+	  class="z3c.blobfile.file.File"
+	  title="File"
+	  description="A File"
+	  permission="zope.ManageContent"
+	  view="z3c.blobfile.file.File"
+	  />
+
+	<browser:page
+	  for="zope.app.container.interfaces.IAdding"
+	  name="z3c.blobfile.file.File"
+	  permission="zope.ManageContent"
+	  class=".file.FileAdd"
+	  template="file_add.pt"
+	  />
+
+	<browser:page
+	  name="upload.html"
+	  menu="zmi_views"
+	  title="Upload"
+	  for="z3c.blobfile.interfaces.IBlobFile"
+	  template="file_upload.pt"
+	  class="zope.app.file.browser.file.FileUpload"
+	  permission="zope.ManageContent"
+	  />
+
+	<browser:menuItem
+	  menu="zmi_views"
+	  title="Edit"
+	  for="z3c.blobfile.interfaces.IBlobFile"
+	  action="edit.html"
+	  filter="python:context.contentType.startswith('text/')"
+	  permission="zope.ManageContent"
+	  />
+
+	<browser:form
+	  name="edit.html"
+	  for="z3c.blobfile.interfaces.IBlobFile"
+	  schema="zope.app.file.browser.file.IFileEditForm"
+	  label="Change a file"
+	  permission="zope.ManageContent"
+	  class="zope.app.file.browser.file.FileEdit"
+	  />
+
+	<browser:page
+	  for="z3c.blobfile.interfaces.IBlobFile"
+	  name="index.html"
+	  permission="zope.View"
+	  class="z3c.blobfile.browser.file.FileView"
+	  attribute="show"
+	  />
+
+	<browser:icon
+	  name="zmi_icon"
+	  for="z3c.blobfile.interfaces.IBlobFile"
+	  file="file_icon.gif"
+	  />
+
+	<browser:page
+	  for="z3c.blobfile.interfaces.IBlobFile"
+	  name="preview.html"
+	  template="preview.pt"
+	  permission="zope.ManageContent"
+	  menu="zmi_views"
+	  title="Preview"
+	  />
+
+	<!-- Directives for Image -->
+
+	<browser:addMenuItem
+	  class="z3c.blobfile.image.Image"
+	  title="Image"
+	  description="An Image"
+	  permission="zope.ManageContent"
+	  view="z3c.blobfile.image.Image"
+	  />
+
+	<browser:addform
+	  name="z3c.blobfile.image.Image"
+	  schema="z3c.blobfile.interfaces.IBlobImage"
+	  label="Add an Image"
+	  content_factory="z3c.blobfile.image.Image"
+	  class="zope.app.file.browser.image.ImageAdd"
+	  permission="zope.ManageContent"
+      />
+
+	<browser:editform
+	  schema="z3c.blobfile.interfaces.IBlobImage"
+	  name="upload.html"
+	  menu="zmi_views"
+	  title="Upload"
+	  label="Upload an image"
+	  permission="zope.ManageContent"
+	  class="zope.app.file.browser.image.ImageUpload"
+	  template="image_edit.pt"
+	  />
+
+	<browser:page
+	  name="index.html"
+	  for="z3c.blobfile.interfaces.IBlobImage"
+	  permission="zope.View"
+	  allowed_attributes="__call__ tag"
+	  class=".image.ImageData"
+	  />
+
+	<browser:icon
+	  name="zmi_icon"
+	  for="z3c.blobfile.interfaces.IBlobImage"
+	  file="image_icon.gif"
+	  />
+
+</configure>

Deleted: z3c.blobfile/tags/0.1.3/src/z3c/blobfile/browser/file.py
===================================================================
--- z3c.blobfile/trunk/src/z3c/blobfile/browser/file.py	2008-10-19 15:49:40 UTC (rev 92387)
+++ z3c.blobfile/tags/0.1.3/src/z3c/blobfile/browser/file.py	2008-10-20 08:37:13 UTC (rev 92392)
@@ -1,80 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2008 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.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.
-#
-##############################################################################
-"""File views.
-
-$Id$
-"""
-__docformat__ = 'restructuredtext'
-
-import zope.event
-from zope import lifecycleevent
-from zope.contenttype import guess_content_type
-from zope.publisher import contenttype
-from zope.schema import Text
-from zope.exceptions.interfaces import UserError
-
-from zope.app.file.interfaces import IFile
-from z3c.blobfile.i18n import ZopeMessageFactory as _
-from zope.dublincore.interfaces import IZopeDublinCore
-from zope.app.file.browser.file import FileUpdateView
-import zope.datetime
-
-import time
-from datetime import datetime
-
-import z3c.blobfile.file
-
-class FileView(object):
-
-    def show(self):
-        """Returns file handle for efficient streaming."""
-        
-        if self.request is not None:
-            self.request.response.setHeader('Content-Type',
-                                            self.context.contentType)
-            self.request.response.setHeader('Content-Length',
-                                            self.context.getSize())
-        try:
-            modified = IZopeDublinCore(self.context).modified
-        except TypeError:
-            modified=None
-        if modified is None or not isinstance(modified,datetime):
-            return self.context.open()
-
-        header= self.request.getHeader('If-Modified-Since', None)
-        lmt = zope.datetime.time(modified.isoformat())
-        if header is not None:
-            header = header.split(';')[0]
-            try:    mod_since=long(zope.datetime.time(header))
-            except: mod_since=None
-            if mod_since is not None:
-                if lmt <= mod_since:
-                    self.request.response.setStatus(304)
-                    return ''
-        self.request.response.setHeader('Last-Modified',
-                                        zope.datetime.rfc1123_date(lmt))
-
-        return self.context.open()
-
-
-class FileAdd(FileUpdateView):
-    """View that adds a new File object based on a file upload."""
-
-    def update_object(self, data, contenttype):
-        f = z3c.blobfile.file.File(data, contenttype)
-        zope.event.notify(lifecycleevent.ObjectCreatedEvent(f))
-        self.context.add(f)
-        self.request.response.redirect(self.context.nextURL())
-        return ''
-

Copied: z3c.blobfile/tags/0.1.3/src/z3c/blobfile/browser/file.py (from rev 92388, z3c.blobfile/trunk/src/z3c/blobfile/browser/file.py)
===================================================================
--- z3c.blobfile/tags/0.1.3/src/z3c/blobfile/browser/file.py	                        (rev 0)
+++ z3c.blobfile/tags/0.1.3/src/z3c/blobfile/browser/file.py	2008-10-20 08:37:13 UTC (rev 92392)
@@ -0,0 +1,80 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.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.
+#
+##############################################################################
+"""File views.
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+import zope.event
+from zope import lifecycleevent
+from zope.contenttype import guess_content_type
+from zope.publisher import contenttype
+from zope.schema import Text
+from zope.exceptions.interfaces import UserError
+
+from zope.app.file.interfaces import IFile
+from z3c.blobfile.i18n import ZopeMessageFactory as _
+from zope.dublincore.interfaces import IZopeDublinCore
+from zope.app.file.browser.file import FileUpdateView
+import zope.datetime
+
+import time
+from datetime import datetime
+
+import z3c.blobfile.file
+
+class FileView(object):
+
+    def show(self):
+        """Returns file handle for efficient streaming."""
+        
+        if self.request is not None:
+            self.request.response.setHeader('Content-Type',
+                                            self.context.contentType)
+            self.request.response.setHeader('Content-Length',
+                                            self.context.getSize())
+        try:
+            modified = IZopeDublinCore(self.context).modified
+        except TypeError:
+            modified = None
+        if modified is None or not isinstance(modified, datetime):
+            return self.context.openDetached()
+
+        header= self.request.getHeader('If-Modified-Since', None)
+        lmt = zope.datetime.time(modified.isoformat())
+        if header is not None:
+            header = header.split(';')[0]
+            try:
+                mod_since = long(zope.datetime.time(header))
+            except:
+                mod_since = None
+            if mod_since is not None:
+                if lmt <= mod_since:
+                    self.request.response.setStatus(304)
+                    return ''
+
+        self.request.response.setHeader('Last-Modified', zope.datetime.rfc1123_date(lmt))
+
+        return self.context.openDetached()
+
+class FileAdd(FileUpdateView):
+    """View that adds a new File object based on a file upload."""
+
+    def update_object(self, data, contenttype):
+        f = z3c.blobfile.file.File(data, contenttype)
+        zope.event.notify(lifecycleevent.ObjectCreatedEvent(f))
+        self.context.add(f)
+        self.request.response.redirect(self.context.nextURL())
+        return ''

Deleted: z3c.blobfile/tags/0.1.3/src/z3c/blobfile/configure.zcml
===================================================================
--- z3c.blobfile/trunk/src/z3c/blobfile/configure.zcml	2008-10-19 15:49:40 UTC (rev 92387)
+++ z3c.blobfile/tags/0.1.3/src/z3c/blobfile/configure.zcml	2008-10-20 08:37:13 UTC (rev 92392)
@@ -1,119 +0,0 @@
-<configure
-    xmlns="http://namespaces.zope.org/zope"
-    i18n_domain='zope'
-    >
-
-
-  <!-- content classes -->
-
-  <!-- TODO: to decide later if BlobFiles and BlobImages shall appear 
-             in the add menu or not  
-  -->
-
-  <class class=".file.File">
-
-    <require
-        permission="zope.View"
-        interface=".interfaces.IBlobFile"
-        />
-
-    <require
-        permission="zope.ManageContent"
-        set_schema=".interfaces.IBlobFile"
-        />
-
-    <implements
-       interface="zope.annotation.interfaces.IAttributeAnnotatable"
-       />
-  </class>
-
-  <class class=".image.Image">
-
-    <require
-        permission="zope.View"
-        interface=".interfaces.IBlobImage"
-        />
-
-    <require
-        permission="zope.ManageContent"
-        set_schema="zope.app.file.interfaces.IFile"
-        />
-
-    <implements
-        interface="zope.annotation.interfaces.IAttributeAnnotatable"
-        />
-  </class>
-  
-  <!-- TODO: Improve schema manager
-  
-  <utility
-      component=".generations.BlobFileSchemaManager"
-      name="z3c.blobfile"
-      />
-
-  -->
-
-  <!-- `IStorage` utilities should be named with the dotted name
-       referencing the implementation. 
-  -->
-
-  <utility
-      name="__builtin__.str"
-      provides=".interfaces.IStorage"
-      factory=".storages.StringStorable"
-      />
-
-  <utility
-      name="__builtin__.unicode"
-      provides=".interfaces.IStorage"
-      factory=".storages.UnicodeStorable"
-      />
-
-  <utility
-      name="zope.app.file.file.FileChunk"
-      provides=".interfaces.IStorage"
-      factory=".storages.FileChunkStorable"
-      />
-
-  <utility
-      name="__builtin__.file"
-      provides=".interfaces.IStorage"
-      factory=".storages.FileDescriptorStorable"
-      />
-
-  <utility
-      name="zope.publisher.browser.FileUpload"
-      provides=".interfaces.IStorage"
-      factory=".storages.FileUploadStorable"
-      />
-
-  <adapter
-      for=".interfaces.IBlobImage"
-      provides="zope.size.interfaces.ISized"
-      factory=".image.ImageSized"
-      />
-
-  <adapter 
-      for=".interfaces.IBlobFile"
-      provides="zope.filerepresentation.interfaces.IReadFile"
-      factory=".file.FileReadFile"
-      permission="zope.View"
-      />
-
-  <adapter 
-      for=".interfaces.IBlobFile"
-      provides="zope.filerepresentation.interfaces.IWriteFile"
-      factory=".file.FileWriteFile"
-      permission="zope.ManageContent"
-      />
-
-  <!-- TODO: have a look later
-  <adapter
-      for="zope.app.folder.interfaces.IFolder"
-      provides="zope.filerepresentation.interfaces.IFileFactory"
-      factory=".image.FileFactory"
-      permission="zope.ManageContent"
-      />
-  -->
-
-</configure>

Copied: z3c.blobfile/tags/0.1.3/src/z3c/blobfile/configure.zcml (from rev 92388, z3c.blobfile/trunk/src/z3c/blobfile/configure.zcml)
===================================================================
--- z3c.blobfile/tags/0.1.3/src/z3c/blobfile/configure.zcml	                        (rev 0)
+++ z3c.blobfile/tags/0.1.3/src/z3c/blobfile/configure.zcml	2008-10-20 08:37:13 UTC (rev 92392)
@@ -0,0 +1,120 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    i18n_domain="zope"
+    >
+
+  <!-- content classes -->
+
+  <!-- TODO: to decide later if BlobFiles and BlobImages shall appear 
+             in the add menu or not  
+  -->
+
+  <class class=".file.File">
+
+    <require
+        permission="zope.View"
+        attributes="contentType data getSize openDetached"
+        />
+
+    <require
+        permission="zope.ManageContent"
+        attributes="open"
+        set_attributes="contentType data"
+        />
+
+    <implements
+       interface="zope.annotation.interfaces.IAttributeAnnotatable"
+       />
+  </class>
+
+  <class class=".image.Image">
+
+    <require
+        permission="zope.View"
+        attributes="contentType data getSize getImageSize openDetached"
+        />
+
+    <require
+        permission="zope.ManageContent"
+        set_attributes="contentType data"
+        attributes="open"
+        />
+
+    <implements
+        interface="zope.annotation.interfaces.IAttributeAnnotatable"
+        />
+  </class>
+  
+  <!-- TODO: Improve schema manager
+  
+  <utility
+      component=".generations.BlobFileSchemaManager"
+      name="z3c.blobfile"
+      />
+
+  -->
+
+  <!-- `IStorage` utilities should be named with the dotted name
+       referencing the implementation. 
+  -->
+
+  <utility
+      name="__builtin__.str"
+      provides=".interfaces.IStorage"
+      factory=".storages.StringStorable"
+      />
+
+  <utility
+      name="__builtin__.unicode"
+      provides=".interfaces.IStorage"
+      factory=".storages.UnicodeStorable"
+      />
+
+  <utility
+      name="zope.app.file.file.FileChunk"
+      provides=".interfaces.IStorage"
+      factory=".storages.FileChunkStorable"
+      />
+
+  <utility
+      name="__builtin__.file"
+      provides=".interfaces.IStorage"
+      factory=".storages.FileDescriptorStorable"
+      />
+
+  <utility
+      name="zope.publisher.browser.FileUpload"
+      provides=".interfaces.IStorage"
+      factory=".storages.FileUploadStorable"
+      />
+
+  <adapter
+      for=".interfaces.IBlobImage"
+      provides="zope.size.interfaces.ISized"
+      factory=".image.ImageSized"
+      />
+
+  <adapter 
+      for=".interfaces.IBlobFile"
+      provides="zope.filerepresentation.interfaces.IReadFile"
+      factory=".file.FileReadFile"
+      permission="zope.View"
+      />
+
+  <adapter 
+      for=".interfaces.IBlobFile"
+      provides="zope.filerepresentation.interfaces.IWriteFile"
+      factory=".file.FileWriteFile"
+      permission="zope.ManageContent"
+      />
+
+  <!-- TODO: have a look later
+  <adapter
+      for="zope.app.folder.interfaces.IFolder"
+      provides="zope.filerepresentation.interfaces.IFileFactory"
+      factory=".image.FileFactory"
+      permission="zope.ManageContent"
+      />
+  -->
+
+</configure>

Deleted: z3c.blobfile/tags/0.1.3/src/z3c/blobfile/file.py
===================================================================
--- z3c.blobfile/trunk/src/z3c/blobfile/file.py	2008-10-19 15:49:40 UTC (rev 92387)
+++ z3c.blobfile/tags/0.1.3/src/z3c/blobfile/file.py	2008-10-20 08:37:13 UTC (rev 92392)
@@ -1,106 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2008 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.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.
-#
-##############################################################################
-"""File content component
-
-$Id$
-"""
-__docformat__ = 'restructuredtext'
-
-from persistent import Persistent
-import transaction
-from zope.interface import implements
-import zope.component
-import zope.component.interfaces
-import zope.app.publication.interfaces
-
-from ZODB.blob import Blob
-
-import interfaces
-
-class File(Persistent):
-    """A persistent content component storing binary file data."""
-
-    implements(zope.app.publication.interfaces.IFileContent, 
-               interfaces.IBlobFile)
-
-    size = 0
-    
-    def __init__(self, data='', contentType=''):
-        self._blob = Blob()
-        self.contentType = contentType
-        self._setData(data)
-
-    def open(self, mode="r"):
-        return self._blob.open(mode)
-
-    def _setData(self, data):
-        # Search for a storable that is able to store the data
-        dottedName = ".".join((data.__class__.__module__,
-                               data.__class__.__name__))
-        storable = zope.component.getUtility(interfaces.IStorage, 
-                                             name=dottedName)
-        storable.store(data, self._blob)
-
-    def _getData(self):
-        fp = self._blob.open('r')
-        data = fp.read()
-        fp.close()
-        return data
-        
-    _data = property(_getData, _setData)   
-    data = property(_getData, _setData)    
-
-    @property
-    def size(self):
-        if self._blob == "":
-            return 0
-        reader = self._blob.open()
-        reader.seek(0,2)
-        size = int(reader.tell())
-        reader.close()
-        return size
-
-    def getSize(self):
-        return self.size
-
-class FileReadFile(object):
-    """Adapter for file-system style read access."""
-    
-    def __init__(self, context):
-        self.context = context
-
-    def read(self, bytes=-1):
-        return self.context.data
-
-    def size(self):
-        return self.context.size
-
-
-class FileWriteFile(object):
-    """Adapter for file-system style write access."""
-    
-    def __init__(self, context):
-        self.context = context
-
-    def write(self, data):
-        self.context._setData(data)
-
-class FileReplacedEvent(zope.component.interfaces.ObjectEvent):
-    """Notifies about the replacement of a zope.app.file with a z3c.blobfile."""
-    
-    def __init__(self, object, blobfile):
-        super(FileReplacedEvent, self).__init__(object)
-        self.blobfile = blobfile
-
-    
\ No newline at end of file

Copied: z3c.blobfile/tags/0.1.3/src/z3c/blobfile/file.py (from rev 92388, z3c.blobfile/trunk/src/z3c/blobfile/file.py)
===================================================================
--- z3c.blobfile/tags/0.1.3/src/z3c/blobfile/file.py	                        (rev 0)
+++ z3c.blobfile/tags/0.1.3/src/z3c/blobfile/file.py	2008-10-20 08:37:13 UTC (rev 92392)
@@ -0,0 +1,115 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.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.
+#
+##############################################################################
+"""File content component
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+from persistent import Persistent
+import transaction
+from zope.interface import implements
+import zope.component
+import zope.component.interfaces
+import zope.app.publication.interfaces
+
+from ZODB.blob import Blob
+
+import interfaces
+
+class File(Persistent):
+    """A persistent content component storing binary file data."""
+
+    implements(zope.app.publication.interfaces.IFileContent, 
+               interfaces.IBlobFile)
+
+    def __init__(self, data='', contentType=''):
+        self.contentType = contentType
+        self._blob = Blob()
+        f = self._blob.open('w')
+        f.write('')
+        f.close()
+        self._setData(data)
+
+    def open(self, mode='r'):
+        if mode != 'r' and 'size' in self.__dict__:
+            del self.__dict__['size']
+        return self._blob.open(mode)
+
+    def openDetached(self):
+        return open(self._blob.committed(), 'rb')
+
+    def _setData(self, data):
+        if 'size' in self.__dict__:
+            del self.__dict__['size']
+        # Search for a storable that is able to store the data
+        dottedName = ".".join((data.__class__.__module__,
+                               data.__class__.__name__))
+        storable = zope.component.getUtility(interfaces.IStorage, 
+                                             name=dottedName)
+        storable.store(data, self._blob)
+
+    def _getData(self):
+        fp = self._blob.open('r')
+        data = fp.read()
+        fp.close()
+        return data
+        
+    _data = property(_getData, _setData)   
+    data = property(_getData, _setData)    
+
+    @property
+    def size(self):
+        if 'size' in self.__dict__:
+            return self.__dict__['size']
+        reader = self._blob.open()
+        reader.seek(0,2)
+        size = int(reader.tell())
+        reader.close()
+        self.__dict__['size'] = size
+        return size
+
+    def getSize(self):
+        return self.size
+
+class FileReadFile(object):
+    """Adapter for file-system style read access."""
+    
+    def __init__(self, context):
+        self.context = context
+
+    def read(self, bytes=-1):
+        return self.context.data
+
+    def size(self):
+        return self.context.size
+
+
+class FileWriteFile(object):
+    """Adapter for file-system style write access."""
+    
+    def __init__(self, context):
+        self.context = context
+
+    def write(self, data):
+        self.context._setData(data)
+
+class FileReplacedEvent(zope.component.interfaces.ObjectEvent):
+    """Notifies about the replacement of a zope.app.file with a z3c.blobfile."""
+    
+    def __init__(self, object, blobfile):
+        super(FileReplacedEvent, self).__init__(object)
+        self.blobfile = blobfile
+
+    
\ No newline at end of file

Deleted: z3c.blobfile/tags/0.1.3/src/z3c/blobfile/image.py
===================================================================
--- z3c.blobfile/trunk/src/z3c/blobfile/image.py	2008-10-19 15:49:40 UTC (rev 92387)
+++ z3c.blobfile/tags/0.1.3/src/z3c/blobfile/image.py	2008-10-20 08:37:13 UTC (rev 92392)
@@ -1,180 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2008 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.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.
-#
-##############################################################################
-"""Image content type implementation
-
-$Id$
-"""
-__docformat__ = 'restructuredtext'
-
-import struct
-from cStringIO import StringIO
-
-from zope.interface import implements
-from zope.size.interfaces import ISized
-from zope.size import byteDisplay
-from zope.contenttype import guess_content_type
-
-from z3c.blobfile.i18n import ZopeMessageFactory as _
-from z3c.blobfile.file import File
-
-from ZODB.blob import Blob
-
-import interfaces
-
-IMAGE_INFO_BYTES = 1024
-
-class Image(File):
-    implements(interfaces.IBlobImage)
-
-    def __init__(self, data=''):
-        '''See interface `IFile`'''
-        self._blob = Blob()
-        self.data = data
-        firstbytes = self.getFirstBytes()
-        self.contentType, self._width, self._height = getImageInfo(firstbytes)
-
-    def _setData(self, data):
-        super(Image, self)._setData(data)
-        firstbytes = self.getFirstBytes()
-        contentType, self._width, self._height = getImageInfo(firstbytes)
-        if contentType:
-            self.contentType = contentType
-
-    def getFirstBytes(self):
-        """Returns the first bytes of the file.
-        
-        Returns an amount which is sufficient to determine the image type.
-        """
-        fp = self.open('r')
-        firstbytes = fp.read(IMAGE_INFO_BYTES)
-        fp.close()
-        return firstbytes
-    
-    def getImageSize(self):
-        """See interface `IImage`"""
-        return (self._width, self._height)
-
-    data = property(File._getData, _setData)
-
-
-class ImageSized(object):
-    implements(ISized)
-
-    def __init__(self, image):
-        self._image = image
-
-    def sizeForSorting(self):
-        '''See `ISized`'''
-        return ('byte', self._image.getSize())
-
-    def sizeForDisplay(self):
-        '''See `ISized`'''
-        w, h = self._image.getImageSize()
-        if w < 0:
-            w = '?'
-        if h < 0:
-            h = '?'
-        bytes = self._image.getSize()
-        byte_size = byteDisplay(bytes)
-        mapping = byte_size.mapping
-        if mapping is None:
-            mapping = {}
-        mapping.update({'width': str(w), 'height': str(h)})
-        #TODO the way this message id is defined, it won't be picked up by
-        # i18nextract and never show up in message catalogs
-        return _(byte_size + ' ${width}x${height}', mapping=mapping)
-
-
-class FileFactory(object):
-
-    def __init__(self, context):
-        self.context = context
-
-    def __call__(self, name, content_type, data):
-        if not content_type and data:
-            content_type, width, height = getImageInfo(data)
-        if not content_type:
-            content_type, encoding = guess_content_type(name, data, '')
-        if content_type.startswith('image/'):
-            return Image(data)
-        return File(data, content_type)
-
-
-def getImageInfo(data):
-    data = str(data)
-    size = len(data)
-    height = -1
-    width = -1
-    content_type = ''
-
-    # handle GIFs
-    if (size >= 10) and data[:6] in ('GIF87a', 'GIF89a'):
-        # Check to see if content_type is correct
-        content_type = 'image/gif'
-        w, h = struct.unpack("<HH", data[6:10])
-        width = int(w)
-        height = int(h)
-
-    # See PNG 2. Edition spec (http://www.w3.org/TR/PNG/)
-    # Bytes 0-7 are below, 4-byte chunk length, then 'IHDR'
-    # and finally the 4-byte width, height
-    elif ((size >= 24) and data.startswith('\211PNG\r\n\032\n')
-          and (data[12:16] == 'IHDR')):
-        content_type = 'image/png'
-        w, h = struct.unpack(">LL", data[16:24])
-        width = int(w)
-        height = int(h)
-
-    # Maybe this is for an older PNG version.
-    elif (size >= 16) and data.startswith('\211PNG\r\n\032\n'):
-        # Check to see if we have the right content type
-        content_type = 'image/png'
-        w, h = struct.unpack(">LL", data[8:16])
-        width = int(w)
-        height = int(h)
-
-    # handle JPEGs
-    elif (size >= 2) and data.startswith('\377\330'):
-        content_type = 'image/jpeg'
-        jpeg = StringIO(data)
-        jpeg.read(2)
-        b = jpeg.read(1)
-        try:
-            w = -1
-            h = -1
-            while (b and ord(b) != 0xDA):
-                while (ord(b) != 0xFF): b = jpeg.read(1)
-                while (ord(b) == 0xFF): b = jpeg.read(1)
-                if (ord(b) >= 0xC0 and ord(b) <= 0xC3):
-                    jpeg.read(3)
-                    h, w = struct.unpack(">HH", jpeg.read(4))
-                    break
-                else:
-                    jpeg.read(int(struct.unpack(">H", jpeg.read(2))[0])-2)
-                b = jpeg.read(1)
-            width = int(w)
-            height = int(h)
-        except struct.error:
-            pass
-        except ValueError:
-            pass
-
-    # handle BMPs
-    elif (size >= 30) and data.startswith('BM'):
-        kind = struct.unpack("<H", data[14:16])[0]
-        if kind == 40: # Windows 3.x bitmap
-            content_type = 'image/x-ms-bmp'
-            width, height = struct.unpack("<LL", data[18:26])
-
-    return content_type, width, height

Copied: z3c.blobfile/tags/0.1.3/src/z3c/blobfile/image.py (from rev 92388, z3c.blobfile/trunk/src/z3c/blobfile/image.py)
===================================================================
--- z3c.blobfile/tags/0.1.3/src/z3c/blobfile/image.py	                        (rev 0)
+++ z3c.blobfile/tags/0.1.3/src/z3c/blobfile/image.py	2008-10-20 08:37:13 UTC (rev 92392)
@@ -0,0 +1,172 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.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.
+#
+##############################################################################
+"""Image content type implementation
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+import struct
+from cStringIO import StringIO
+
+from zope.interface import implements
+from zope.size.interfaces import ISized
+from zope.size import byteDisplay
+from zope.contenttype import guess_content_type
+
+from z3c.blobfile.i18n import ZopeMessageFactory as _
+from z3c.blobfile.file import File
+
+from ZODB.blob import Blob
+
+import interfaces
+
+IMAGE_INFO_BYTES = 1024
+
+class Image(File):
+    implements(interfaces.IBlobImage)
+
+    def _setData(self, data):
+        super(Image, self)._setData(data)
+        firstbytes = self.getFirstBytes()
+        contentType, self._width, self._height = getImageInfo(firstbytes)
+        if contentType:
+            self.contentType = contentType
+
+    data = property(File._getData, _setData)
+
+    def getFirstBytes(self):
+        """Returns the first bytes of the file.
+        
+        Returns an amount which is sufficient to determine the image type.
+        """
+        fp = self.open('r')
+        firstbytes = fp.read(IMAGE_INFO_BYTES)
+        fp.close()
+        return firstbytes
+    
+    def getImageSize(self):
+        """See interface `IImage`"""
+        return (self._width, self._height)
+
+class ImageSized(object):
+    implements(ISized)
+
+    def __init__(self, image):
+        self._image = image
+
+    def sizeForSorting(self):
+        '''See `ISized`'''
+        return ('byte', self._image.getSize())
+
+    def sizeForDisplay(self):
+        '''See `ISized`'''
+        w, h = self._image.getImageSize()
+        if w < 0:
+            w = '?'
+        if h < 0:
+            h = '?'
+        bytes = self._image.getSize()
+        byte_size = byteDisplay(bytes)
+        mapping = byte_size.mapping
+        if mapping is None:
+            mapping = {}
+        mapping.update({'width': str(w), 'height': str(h)})
+        #TODO the way this message id is defined, it won't be picked up by
+        # i18nextract and never show up in message catalogs
+        return _(byte_size + ' ${width}x${height}', mapping=mapping)
+
+
+class FileFactory(object):
+
+    def __init__(self, context):
+        self.context = context
+
+    def __call__(self, name, content_type, data):
+        if not content_type and data:
+            content_type, width, height = getImageInfo(data)
+        if not content_type:
+            content_type, encoding = guess_content_type(name, data, '')
+        if content_type.startswith('image/'):
+            return Image(data)
+        return File(data, content_type)
+
+
+def getImageInfo(data):
+    data = str(data)
+    size = len(data)
+    height = -1
+    width = -1
+    content_type = ''
+
+    # handle GIFs
+    if (size >= 10) and data[:6] in ('GIF87a', 'GIF89a'):
+        # Check to see if content_type is correct
+        content_type = 'image/gif'
+        w, h = struct.unpack("<HH", data[6:10])
+        width = int(w)
+        height = int(h)
+
+    # See PNG 2. Edition spec (http://www.w3.org/TR/PNG/)
+    # Bytes 0-7 are below, 4-byte chunk length, then 'IHDR'
+    # and finally the 4-byte width, height
+    elif ((size >= 24) and data.startswith('\211PNG\r\n\032\n')
+          and (data[12:16] == 'IHDR')):
+        content_type = 'image/png'
+        w, h = struct.unpack(">LL", data[16:24])
+        width = int(w)
+        height = int(h)
+
+    # Maybe this is for an older PNG version.
+    elif (size >= 16) and data.startswith('\211PNG\r\n\032\n'):
+        # Check to see if we have the right content type
+        content_type = 'image/png'
+        w, h = struct.unpack(">LL", data[8:16])
+        width = int(w)
+        height = int(h)
+
+    # handle JPEGs
+    elif (size >= 2) and data.startswith('\377\330'):
+        content_type = 'image/jpeg'
+        jpeg = StringIO(data)
+        jpeg.read(2)
+        b = jpeg.read(1)
+        try:
+            w = -1
+            h = -1
+            while (b and ord(b) != 0xDA):
+                while (ord(b) != 0xFF): b = jpeg.read(1)
+                while (ord(b) == 0xFF): b = jpeg.read(1)
+                if (ord(b) >= 0xC0 and ord(b) <= 0xC3):
+                    jpeg.read(3)
+                    h, w = struct.unpack(">HH", jpeg.read(4))
+                    break
+                else:
+                    jpeg.read(int(struct.unpack(">H", jpeg.read(2))[0])-2)
+                b = jpeg.read(1)
+            width = int(w)
+            height = int(h)
+        except struct.error:
+            pass
+        except ValueError:
+            pass
+
+    # handle BMPs
+    elif (size >= 30) and data.startswith('BM'):
+        kind = struct.unpack("<H", data[14:16])[0]
+        if kind == 40: # Windows 3.x bitmap
+            content_type = 'image/x-ms-bmp'
+            width, height = struct.unpack("<LL", data[18:26])
+
+    return content_type, width, height

Deleted: z3c.blobfile/tags/0.1.3/src/z3c/blobfile/interfaces.py
===================================================================
--- z3c.blobfile/trunk/src/z3c/blobfile/interfaces.py	2008-10-19 15:49:40 UTC (rev 92387)
+++ z3c.blobfile/tags/0.1.3/src/z3c/blobfile/interfaces.py	2008-10-20 08:37:13 UTC (rev 92392)
@@ -1,55 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2008 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.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.
-#
-##############################################################################
-"""File interfaces
-
-$Id$
-"""
-__docformat__ = 'restructuredtext'
-
-import zope.interface
-import zope.component.interfaces
-import zope.app.file.interfaces
-
-class IOpenable(zope.interface.Interface):
-    """Openable file
-    """
-
-    def open(mode):
-        """Open file and return the file descriptor
-        """
-
-class IBlobFile(zope.app.file.interfaces.IFile, IOpenable):
-    """A file that uses Blobs as data storage."""
-
-
-class IBlobImage(zope.app.file.interfaces.IImage, IOpenable):
-    """An image that uses Blobs as data storage."""
-
-    
-class IStorage(zope.interface.Interface):
-    """Store file data
-    """
-
-    def store(data, blob):
-        """Store the data into the blob
-
-	    Raises NonStorable if data is not storable.
-        """
-
-class NotStorable(Exception):
-    """Data is not storable
-    """
-
-class IFileReplacedEvent(zope.component.interfaces.IObjectEvent):
-    """A zope.app.file has been replaced by it's blobfile counterpart."""

Copied: z3c.blobfile/tags/0.1.3/src/z3c/blobfile/interfaces.py (from rev 92388, z3c.blobfile/trunk/src/z3c/blobfile/interfaces.py)
===================================================================
--- z3c.blobfile/tags/0.1.3/src/z3c/blobfile/interfaces.py	                        (rev 0)
+++ z3c.blobfile/tags/0.1.3/src/z3c/blobfile/interfaces.py	2008-10-20 08:37:13 UTC (rev 92392)
@@ -0,0 +1,58 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.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.
+#
+##############################################################################
+"""File interfaces
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+import zope.interface
+import zope.component.interfaces
+import zope.app.file.interfaces
+
+class IOpenable(zope.interface.Interface):
+    """Openable file
+    """
+
+    def open(mode='r'):
+        """Open file and return the file descriptor
+        """
+
+    def openDetached():
+        '''Return a read-only file descriptor, detached from ZODB connection'''
+
+class IBlobFile(zope.app.file.interfaces.IFile, IOpenable):
+    """A file that uses Blobs as data storage."""
+
+
+class IBlobImage(zope.app.file.interfaces.IImage, IOpenable):
+    """An image that uses Blobs as data storage."""
+
+    
+class IStorage(zope.interface.Interface):
+    """Store file data
+    """
+
+    def store(data, blob):
+        """Store the data into the blob
+
+	    Raises NonStorable if data is not storable.
+        """
+
+class NotStorable(Exception):
+    """Data is not storable
+    """
+
+class IFileReplacedEvent(zope.component.interfaces.IObjectEvent):
+    """A zope.app.file has been replaced by it's blobfile counterpart."""



More information about the Checkins mailing list