[Checkins] SVN: z3c.filetype/trunk/ - Because tests failed and the author of the changes did not fixed them after

Juergen Kartnaller juergen at kartnaller.at
Mon Jan 19 07:42:05 EST 2009


Log message for revision 94829:
   - Because tests failed and the author of the changes did not fixed them after
     a year I reverted trunk to version 82160.
  

Changed:
  U   z3c.filetype/trunk/CHANGES.txt
  U   z3c.filetype/trunk/buildout.cfg
  UU  z3c.filetype/trunk/setup.py
  U   z3c.filetype/trunk/src/z3c/filetype/README.txt
  U   z3c.filetype/trunk/src/z3c/filetype/__init__.py
  U   z3c.filetype/trunk/src/z3c/filetype/adapters.py
  U   z3c.filetype/trunk/src/z3c/filetype/api.py
  U   z3c.filetype/trunk/src/z3c/filetype/configure.zcml
  D   z3c.filetype/trunk/src/z3c/filetype/converter.txt
  D   z3c.filetype/trunk/src/z3c/filetype/converters/
  A   z3c.filetype/trunk/src/z3c/filetype/event.py
  U   z3c.filetype/trunk/src/z3c/filetype/interfaces/__init__.py
  D   z3c.filetype/trunk/src/z3c/filetype/interfaces/api.py
  D   z3c.filetype/trunk/src/z3c/filetype/interfaces/converter.py
  U   z3c.filetype/trunk/src/z3c/filetype/interfaces/filetypes.py
  D   z3c.filetype/trunk/src/z3c/filetype/interfaces/magic.py
  U   z3c.filetype/trunk/src/z3c/filetype/magic.py
  U   z3c.filetype/trunk/src/z3c/filetype/size.py
  U   z3c.filetype/trunk/src/z3c/filetype/tests.py
  D   z3c.filetype/trunk/src/z3c/filetype/typeablefile.py

-=-
Modified: z3c.filetype/trunk/CHANGES.txt
===================================================================
--- z3c.filetype/trunk/CHANGES.txt	2009-01-19 12:31:16 UTC (rev 94828)
+++ z3c.filetype/trunk/CHANGES.txt	2009-01-19 12:42:04 UTC (rev 94829)
@@ -5,14 +5,9 @@
 After
 =====
 
-2007/12/19 1.2.0
-================
+ - Because tests failed and the author of the changes did not fixed them after
+   a year I reverted trunk to version 82160.
 
- - code cleanup
- - use IFileData interface for data access
- - mimetype converting
-
-
 2007/12/06 1.1.0
 ================
 
@@ -20,3 +15,4 @@
  - mimetype extension for audio/mpeg layer 3
  - removed setup.cfg
  - added CHANGES.txt
+

Modified: z3c.filetype/trunk/buildout.cfg
===================================================================
--- z3c.filetype/trunk/buildout.cfg	2009-01-19 12:31:16 UTC (rev 94828)
+++ z3c.filetype/trunk/buildout.cfg	2009-01-19 12:42:04 UTC (rev 94829)
@@ -5,4 +5,4 @@
 
 [test]
 recipe = zc.recipe.testrunner
-eggs = z3c.filetype [test]
+eggs = z3c.filetype

Modified: z3c.filetype/trunk/setup.py
===================================================================
--- z3c.filetype/trunk/setup.py	2009-01-19 12:31:16 UTC (rev 94828)
+++ z3c.filetype/trunk/setup.py	2009-01-19 12:42:04 UTC (rev 94829)
@@ -13,63 +13,33 @@
 ##############################################################################
 """Setup for z3c.filetype package
 
-$Id$
+$Id: setup.py 82381 2007-12-21 10:08:32Z jukart $
 """
-import sys, os
+
 from setuptools import setup, find_packages
 
-version = '1.2.0'
-
-def read(*rnames):
-    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
-
 setup(
-    name='z3c.filetype',
-    version=version,
-    description = 'Filetype Package',
-    long_description=(
-        'Detailed Dcoumentation\n' +
-        '======================\n'
-        + '\n\n' +
-        read('src', 'z3c', 'filetype', 'README.txt')
-        + '\n\n' +
-        read('CHANGES.txt')
-        ),
-    classifiers=[
-        'Development Status :: 5 - Production/Stable',
-        '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'],
-    author='Zope Community',
-    author_email='zope3-dev at zope.org',
-    url='http://svn.zope.org/z3c.filetype',
-    license='ZPL 2.1',
+    name="z3c.filetype",
+    version="1.1.0",
     namespace_packages=["z3c"],
     packages=find_packages("src"),
     package_dir={"": "src"},
     include_package_data=True,
     install_requires=[
         "setuptools",
+        "zope.cachedescriptors",
         "zope.component",
-        "zope.interface",
         "zope.contenttype",
         "zope.event",
         "zope.i18nmessageid",
+        "zope.interface",
         "zope.lifecycleevent",
         "zope.proxy",
         "zope.schema",
         "zope.size",
         ],
     extras_require={
-        "test": [
-            "zope.testing",
-            'zope.app.testing',
-            ],
+        "test": ["zope.testing"],
         },
     zip_safe=False,
     )


Property changes on: z3c.filetype/trunk/setup.py
___________________________________________________________________
Deleted: svn:keywords
   - Id

Modified: z3c.filetype/trunk/src/z3c/filetype/README.txt
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/README.txt	2009-01-19 12:31:16 UTC (rev 94828)
+++ z3c.filetype/trunk/src/z3c/filetype/README.txt	2009-01-19 12:42:04 UTC (rev 94829)
@@ -7,14 +7,12 @@
 This package provides a way to get interfaces that are provided based
 on their content, filename or mime-type.
 
-  >>> from z3c.filetype import api, typeablefile
-  >>> from zope import event, component
-  >>> from zope.component import eventtesting
+  >>> from z3c.filetype import api
 
 We take some files for demonstration from the testdata directory.
 
   >>> import os
-  >>> testData = os.path.join(os.path.dirname(api.__file__), 'testdata')
+  >>> testData = os.path.join(os.path.dirname(api.__file__),'testdata')
 
   >>> fileNames = sorted(os.listdir(testData))
 
@@ -70,10 +68,7 @@
   >>> sorted(api.getInterfacesFor(f))
   [<InterfaceClass z3c.filetype.interfaces.filetypes.ITARFile>]
 
-  >>> sorted(api.getInterfacesForFile(os.path.join(testData, 'test.tar')))
-  [<InterfaceClass z3c.filetype.interfaces.filetypes.ITARFile>]
-
-  >>> sorted(api.getInterfacesForFilename('x.png'))
+  >>> sorted(api.getInterfacesFor(filename="x.png"))
   [<InterfaceClass z3c.filetype.interfaces.filetypes.IPNGFile>]
 
   >>> sorted(api.getInterfacesFor(f, filename="x.png"))
@@ -92,7 +87,7 @@
 
   >>> f.name
   '...test.tar'
-  >>> sorted(api.getInterfacesForFilename(f.name))
+  >>> sorted(api.getInterfacesFor(f.name))
   [<InterfaceClass z3c.filetype.interfaces.filetypes.ITARFile>]
 
 
@@ -103,28 +98,34 @@
 object. This object needs to implement ITypeableFile. So let us setup
 the event handling.
 
+  >>> from zope.component import eventtesting
+  >>> eventtesting.setUp()
+
   >>> from z3c.filetype import interfaces
   >>> from zope import interface
   >>> class Foo(object):
   ...     interface.implements(interfaces.ITypeableFile)
   ...     def __init__(self, f):
-  ...         f.seek(0)
-  ...         self.data = f.read()
+  ...         self.data = f
   >>> foo = Foo(f)
 
 There is also an event handler registered for IObjectCreatedEvent and
-IObjectModified on ITypeableFile.
+IObjectModified on  ITypeableFile. We register them here in the test.
+
+  >>> from zope import component
+  >>> component.provideHandler(api.handleCreated)
+  >>> component.provideHandler(api.handleModified)
+
 So we need to fire an IObjectCreatedEvent. Which is normally done by a
 factory.
 
   >>> from zope.lifecycleevent import ObjectCreatedEvent
   >>> from zope.lifecycleevent import ObjectModifiedEvent
-
+  >>> from zope.event import notify
   >>> eventtesting.clearEvents()
-  >>> event.notify(ObjectCreatedEvent(foo))
-
+  >>> notify(ObjectCreatedEvent(foo))
   >>> sorted(eventtesting.getEvents())
-  [<z3c.filetype.interfaces.FileTypeModifiedEvent object at ...>,
+  [<z3c.filetype.event.FileTypeModifiedEvent object at ...>,
    <zope.app.event.objectevent.ObjectCreatedEvent object at ...>]
 
 The object now implements the according interface. This is achieved by
@@ -145,15 +146,16 @@
 If we change the object the interface changes too. We need to fire
 an IObjectModifiedevent. Which is normally done by the implementation.
 
-  >>> foo.data = file(os.path.join(testData,'test.flv'), 'rb').read()
+  >>> foo.data = file(os.path.join(testData,'test.flv'), 'rb')
   >>> eventtesting.clearEvents()
-  >>> event.notify(ObjectModifiedEvent(foo))
+  >>> 
+  >>> notify(ObjectModifiedEvent(foo))
 
 Now we have two events, one we fired and one from our handler.
 
   >>> eventtesting.getEvents()
   [<zope.app.event.objectevent.ObjectModifiedEvent object at ...>,
-   <z3c.filetype.interfaces.FileTypeModifiedEvent object at ...>]
+   <z3c.filetype.event.FileTypeModifiedEvent object at ...>]
 
 Now the file should implement another filetype.
 
@@ -161,22 +163,20 @@
   [<InterfaceClass z3c.filetype.interfaces.filetypes.IFLVFile>]
 
 
-IContentType adapters
-=====================
+IFileType adapters
+==================
 
-There is also an adapter from ITypedFile to IContentType, which can be
+There is also an adapter from ITypedFile to IFileType, which can be
 used to get the default content type for the interface.
 
   >>> from z3c.filetype import adapters
-  >>> component.provideAdapter(adapters.ContentType)
-
+  >>> component.provideAdapter(adapters.TypedFileType)
   >>> for name in fileNames:
-  ...     if name==".svn":
-  ...        continue
+  ...     if name==".svn": continue
   ...     path = os.path.join(testData, name)
   ...     i =  Foo(file(path, 'rb'))
-  ...     event.notify(ObjectModifiedEvent(i))
-  ...     print name + " --> " + interfaces.IContentType(i).contentType
+  ...     notify(ObjectModifiedEvent(i))
+  ...     print name + " --> " + interfaces.IFileType(i).contentType
   DS_Store --> application/octet-stream
   IMG_0504.JPG --> image/jpeg
   faces_gray.avi --> video/x-msvideo
@@ -210,22 +210,24 @@
   >>> component.provideAdapter(size.PNGFileSized)
   >>> component.provideAdapter(size.JPGFileSized)
 
-  >>> foo.data = file(os.path.join(testData,'thumbnailImage_small.jpeg'), 'rb').read()
-  >>> event.notify(ObjectModifiedEvent(foo))
+  >>> foo.data = file(os.path.join(testData,'thumbnailImage_small.jpeg'), 'rb')
+  >>> notify(ObjectModifiedEvent(foo))
   >>> ISized(foo).sizeForDisplay().mapping
   {'width': '120', 'height': '90', 'size': '3'}
 
-  >>> foo.data = file(os.path.join(testData,'test.png'), 'rb').read()
-  >>> event.notify(ObjectModifiedEvent(foo))
+  >>> foo.data = file(os.path.join(testData,'test.png'), 'rb')
+  >>> notify(ObjectModifiedEvent(foo))
   >>> ISized(foo).sizeForDisplay().mapping
   {'width': '279', 'height': '19', 'size': '4'}
 
-  >>> foo.data = file(os.path.join(testData,'logo.gif'), 'rb').read()
-  >>> event.notify(ObjectModifiedEvent(foo))
+  >>> foo.data = file(os.path.join(testData,'logo.gif'), 'rb')
+  >>> notify(ObjectModifiedEvent(foo))
   >>> ISized(foo).sizeForDisplay().mapping
   {'width': '201', 'height': '54', 'size': '2'}
 
-  >>> foo.data = file(os.path.join(testData,'IMG_0504.JPG'), 'rb').read()
-  >>> event.notify(ObjectModifiedEvent(foo))
+  >>> foo.data = file(os.path.join(testData,'IMG_0504.JPG'), 'rb')
+  >>> notify(ObjectModifiedEvent(foo))
   >>> ISized(foo).sizeForDisplay().mapping
   {'width': '1600', 'height': '1200', 'size': '499'}
+
+

Modified: z3c.filetype/trunk/src/z3c/filetype/__init__.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/__init__.py	2009-01-19 12:31:16 UTC (rev 94828)
+++ z3c.filetype/trunk/src/z3c/filetype/__init__.py	2009-01-19 12:42:04 UTC (rev 94829)
@@ -1 +1 @@
-# This file is necessary to make this directory a package.
+#package

Modified: z3c.filetype/trunk/src/z3c/filetype/adapters.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/adapters.py	2009-01-19 12:31:16 UTC (rev 94828)
+++ z3c.filetype/trunk/src/z3c/filetype/adapters.py	2009-01-19 12:42:04 UTC (rev 94829)
@@ -1,29 +1,13 @@
-##############################################################################
-#
-# Copyright (c) 2007 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.
-#
-##############################################################################
-"""
-
-$Id$
-"""
-from zope import interface, component
-
+from zope.cachedescriptors.property import Lazy
 import interfaces
-from interfaces.filetypes import MT, ITypedFile
+from interfaces import filetypes
+from zope import interface
+from zope import component
 
+class TypedFileType(object):
 
-class ContentType(object):
-    component.adapts(ITypedFile)
-    interface.implements(interfaces.IContentType)
+    interface.implements(interfaces.IFileType)
+    component.adapts(filetypes.ITypedFile)
 
     def __init__(self, context):
         self.context = context
@@ -32,13 +16,10 @@
     def contentType(self):
         decl = interface.Declaration(
             *interface.directlyProvidedBy(self.context))
-
         for iface in decl.flattened():
-            if not iface.extends(ITypedFile):
+            if not issubclass(iface, filetypes.ITypedFile):
                 continue
-
-            mt = iface.queryTaggedValue(MT)
+            mt = iface.queryTaggedValue(filetypes.MT)
             if mt is not None:
                 return mt
 
-        return 'application/octet-stream'

Modified: z3c.filetype/trunk/src/z3c/filetype/api.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/api.py	2009-01-19 12:31:16 UTC (rev 94828)
+++ z3c.filetype/trunk/src/z3c/filetype/api.py	2009-01-19 12:42:04 UTC (rev 94829)
@@ -1,127 +1,71 @@
-##############################################################################
-#
-# Copyright (c) 2007 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.
-#
-##############################################################################
-"""
-
-$Id$
-"""
-from zope import interface
-from zope import component, event
-from zope.proxy import removeAllProxies
+from z3c.filetype import magic
+import interfaces
+from interfaces import filetypes
 from zope.contenttype import guess_content_type
+from zope import interface, component
+from zope.lifecycleevent.interfaces import IObjectModifiedEvent
+from zope.lifecycleevent.interfaces import IObjectCreatedEvent
+from zope.event import notify
+from event import FileTypeModifiedEvent
 
-from z3c.filetype import magic, interfaces
-from z3c.filetype.interfaces.api import IAPI
-from z3c.filetype.interfaces import filetypes
-from z3c.filetype.interfaces.converter import IConverter, ConverterNotFound
-
-
 magicFile = magic.MagicFile()
 
+def byMimeType(t):
 
-def byMimeType(mt):
     """returns interfaces implemented by mimeType"""
-    ifaces = [iface for name, iface in vars(filetypes).items()
+    
+    ifaces = [iface for name, iface in vars(filetypes).items() \
               if name.startswith("I")]
     res = InterfaceSet()
     for iface in ifaces:
         mtm = iface.queryTaggedValue(filetypes.MTM)
         if mtm is not None:
-            if mtm.match(mt):
+            if mtm.match(t):
                res.add(iface)
     return res
 
+def getInterfacesFor(file=None, filename=None, mimeType=None):
 
-def getInterfacesFor(file, filename=None, mimeType=None):
     """returns a sequence of interfaces that are provided by file like
-    objects (file argument) or string with an optional 
-    filename as name or mimeType as mime-type
+    objects (file argument) with an optional filename as name or
+    mimeType as mime-type
     """
-    file.seek(0)
-
+    
     ifaces = set()
-    for mt in magicFile.detect(file):
-        ifaces.update(byMimeType(mt))
-
+    if file is not None:
+        types = magicFile.detect(file)
+        for t in types:
+            ifaces.update(byMimeType(t))
     if mimeType is not None:
         ifaces.update(byMimeType(mimeType))
-
     if filename is not None and not ifaces:
-        mt = guess_content_type(filename)[0]
+        t = guess_content_type(filename)[0]
         # dont trust this here because zope does not recognize some
         # binary files.
-        if mt not in ('application/octet-stream', 
-                      'text/x-unknown-content-type'):
-            ifaces.update(byMimeType(mt))
-
+        if t and not t == 'text/x-unknown-content-type':
+            ifaces.update(byMimeType(t))
     if not ifaces:
-        ifaces.add(filetypes.IBinaryFile)
-
+        ifaces.add(interfaces.filetypes.IBinaryFile)
     return InterfaceSet(*ifaces)
 
-
-def getInterfacesForFile(filename, mimeType=None):
-    file = open(filename, 'r')
-    try:
-        ifaces = getInterfacesFor(file, filename, mimeType)
-    finally:
-        file.close()
-    return ifaces
-
-
-def getInterfacesForFilename(filename):
-    ifaces = set()
-    mt = guess_content_type(filename)[0]
-    if mt not in ('application/octet-stream', 
-                  'text/x-unknown-content-type'):
-        ifaces.update(byMimeType(mt))
-    if not ifaces:
-        ifaces.add(filetypes.IBinaryFile)
-    return InterfaceSet(*ifaces)        
-
-
 def applyInterfaces(obj):
-    raw = interfaces.IFileData(obj, None)
-    if raw is None:
-        return False
-
-    data  = raw.open('r')
-
-    ifaces = InterfaceSet(*getInterfacesFor(data))
+    assert(interfaces.ITypeableFile.providedBy(obj))
+    ifaces = InterfaceSet(*getInterfacesFor(obj.data))
     provided = set(interface.directlyProvidedBy(obj))
     for iface in provided:
-        if not issubclass(iface, filetypes.ITypedFile):
+        if not issubclass(iface, interfaces.filetypes.ITypedFile):
             ifaces.add(iface)
-
-    data.close()
-
-    ifaces = set(ifaces)
-    if ifaces and (ifaces != provided):
-        clean_obj = removeAllProxies(obj)
-
-        for iface in interface.directlyProvidedBy(clean_obj):
-            if not iface.isOrExtends(filetypes.ITypedFile):
-                ifaces.add(iface)
-
-        if ifaces:
-            interface.directlyProvides(clean_obj, ifaces)
-            event.notify(interfaces.FileTypeModifiedEvent(obj))
-            return True
-
+    if set(ifaces)!=provided:
+        from zope.proxy import removeAllProxies
+        obj = removeAllProxies(obj)
+        for iface in ifaces:
+            interface.directlyProvides(obj, iface)
+        notify(FileTypeModifiedEvent(obj))
+        return True
     return False
 
-
 class InterfaceSet(object):
+
     """a set that only holds most specific interfaces
 
     >>> s = InterfaceSet(filetypes.IBinaryFile, filetypes.IImageFile)
@@ -139,13 +83,14 @@
     >>> sorted(s)
     [<InterfaceClass z3c.filetype.interfaces.filetypes.IJPGFile>,
      <InterfaceClass z3c.filetype.interfaces.filetypes.ITextFile>]
+
     """
 
     def __init__(self, *ifaces):
         self._data = set()
         for iface in ifaces:
             self.add(iface)
-
+            
     def add(self, iface):
         assert(issubclass(iface, interface.Interface))
         toDelete = set()
@@ -156,37 +101,20 @@
                 toDelete.add(i)
         self._data.add(iface)
         self._data.difference_update(toDelete)
-
+        
     def __iter__(self):
+
         return iter(self._data)
 
+ at component.adapter(interfaces.ITypeableFile,IObjectModifiedEvent)
+def handleModified(typeableFile, event):
+    """handles modification of data"""
+    if interfaces.IFileTypeModifiedEvent.providedBy(event):
+        # do nothing if this is already a filetype modification event
+        return
+    applyInterfaces(typeableFile)
 
-def convert(obj, mimetype, name=None, converter=IConverter, *args, **kw):
-    from z3c.filetype import typeablefile
-
-    dest = typeablefile.TypeableFile()
-    interface.directlyProvides(dest, mimetype)
-
-    if name is None:
-        for name, converter in component.getAdapters((obj, dest), converter):
-            converter.convert(*args, **kw)
-            return dest
-        raise ConverterNotFound(
-            "converter not found for (%s, %s)"%(obj, mimetype))
-    else:
-        if isinstance(name, basestring):
-            name = [name]
-
-        for nm in name:
-            converter = component.queryMultiAdapter((obj, dest), converter, nm)
-            if converter is not None:
-                converter.convert(*args, **kw)
-                return dest
-
-        if converter is None:
-            raise ConverterNotFound(
-                "converter not found for (%s, %s)"%(obj, mimetype))
-
-
-interface.moduleProvides(IAPI)
-__all__ = tuple(IAPI)
+ at component.adapter(interfaces.ITypeableFile,IObjectCreatedEvent)
+def handleCreated(typeableFile, event):
+    """handles modification of data"""
+    applyInterfaces(typeableFile)

Modified: z3c.filetype/trunk/src/z3c/filetype/configure.zcml
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/configure.zcml	2009-01-19 12:31:16 UTC (rev 94828)
+++ z3c.filetype/trunk/src/z3c/filetype/configure.zcml	2009-01-19 12:42:04 UTC (rev 94829)
@@ -1,23 +1,22 @@
 <configure
-   xmlns="http://namespaces.zope.org/zope"
-   xmlns:zcml="http://namespaces.zope.org/zcml"
-   i18n_domain="zope">
+ xmlns="http://namespaces.zope.org/zope"
+ i18n_domain="zope"
+ >
 
-  <adapter factory=".adapters.ContentType" />
+ <subscriber for=".interfaces.ITypeableFile
+                  zope.lifecycleevent.interfaces.IObjectModifiedEvent"
+             handler=".api.handleModified"/>
 
-  <adapter factory=".typeablefile.TypeableFileData" />
-  <subscriber handler=".typeablefile.handleCreated" />
-  <subscriber handler=".typeablefile.handleModified" />
+ <subscriber for=".interfaces.ITypeableFile
+                  zope.lifecycleevent.interfaces.IObjectCreatedEvent"
+             handler=".api.handleCreated"/>
 
-  <adapter factory=".size.PNGFileSized" />
-  <adapter factory=".size.JPGFileSized" />
-  <adapter factory=".size.GIFFileSized" />
+ 
+ <adapter factory=".adapters.TypedFileType"/>
 
-  <class class="z3c.blobfile.file.File"
-	 zcml:condition="installed z3c.blobfile">
-    <implements interface=".interfaces.IFileData" />
-  </class>
+ <adapter factory=".size.PNGFileSized" />
+ <adapter factory=".size.JPGFileSized" />
+ <adapter factory=".size.GIFFileSized" />
 
-  <include package=".converters" />
-
+ 
 </configure>

Deleted: z3c.filetype/trunk/src/z3c/filetype/converter.txt
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/converter.txt	2009-01-19 12:31:16 UTC (rev 94828)
+++ z3c.filetype/trunk/src/z3c/filetype/converter.txt	2009-01-19 12:42:04 UTC (rev 94829)
@@ -1,72 +0,0 @@
-  Converting
-~~~~~~~~~~~~~~
-
-We can convert data, for this we should register converter for required types
-
-  >>> from zope import component, interface
-  >>> from z3c.filetype import api, interfaces
-  >>> from z3c.filetype.interfaces import filetypes
-  >>> from z3c.filetype.converters import jpggif
-
-Now we need load files
-
-  >>> import os.path
-  >>> testData = os.path.join(os.path.dirname(api.__file__), 'testdata')
-
-  >>> from z3c.filetype.typeablefile import TypeableFile
-  >>> img1 = TypeableFile(file(os.path.join(testData, 'logo.gif'), 'rb').read())
-
-  >>> sorted((interface.directlyProvidedBy(img1)))
-  [<InterfaceClass z3c.filetype.interfaces.filetypes.IGIFFile>]
-
-  >>> img2 = api.convert(img1, filetypes.IJPGFile)
-  Traceback (most recent call last):
-  ...
-  ConverterNotFound: ...
-
-Let's register simple image converters
-
-  >>> component.provideAdapter(jpggif.GIFtoJPEGConverter)
-  >>> component.provideAdapter(jpggif.JPEGtoGIFConverter)
-
-  >>> img2 = api.convert(img1, filetypes.IJPGFile)
-  >>> sorted((interface.directlyProvidedBy(img2)))
-  [<InterfaceClass z3c.filetype.interfaces.filetypes.IJPGFile>]
-
-Image converter can scale image
-
-  >>> interfaces.IImageSized(img2).getImageSize()
-  (201, 54)
-
-converter save width/height aspect retio
-
-  >>> img2 = api.convert(img1, filetypes.IJPGFile, width=100, height=54)
-  >>> interfaces.IImageSized(img2).getImageSize()
-  (100, 26)
-
-  >>> img2 = api.convert(img1, filetypes.IJPGFile, width=100, height=40)
-  >>> interfaces.IImageSized(img2).getImageSize()
-  (100, 26)
-
-  >>> img2 = api.convert(img1, filetypes.IJPGFile, scale=0.5)
-  >>> interfaces.IImageSized(img2).getImageSize()
-  (101, 27)
-
-Named converters, we can pass converter `name`. It can be string or sequence 
-of names.
-
-  >>> img2 = api.convert(img1, filetypes.IJPGFile, name='MyConverter')
-  Traceback (most recent call last):
-  ...
-  ConverterNotFound: ...
-
-  >>> component.provideAdapter(jpggif.GIFtoJPEGConverter, name='MyConverter')
-
-Simple case with only one name
-
-  >>> img2 = api.convert(img1, filetypes.IJPGFile, name='MyConverter')
-
-With multple names, it will try get `MyConverter` if it is not 
-exists it will try `PIL` etc.
-
-  >>> img2 = api.convert(img1, filetypes.IJPGFile, name=['MyConverter', 'PIL', ''])

Copied: z3c.filetype/trunk/src/z3c/filetype/event.py (from rev 82160, z3c.filetype/trunk/src/z3c/filetype/event.py)
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/event.py	                        (rev 0)
+++ z3c.filetype/trunk/src/z3c/filetype/event.py	2009-01-19 12:42:04 UTC (rev 94829)
@@ -0,0 +1,7 @@
+from zope.lifecycleevent import ObjectModifiedEvent
+from zope import interface
+import interfaces
+
+class FileTypeModifiedEvent(ObjectModifiedEvent):
+    interface.implements(interfaces.IFileTypeModifiedEvent)
+

Modified: z3c.filetype/trunk/src/z3c/filetype/interfaces/__init__.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/interfaces/__init__.py	2009-01-19 12:31:16 UTC (rev 94828)
+++ z3c.filetype/trunk/src/z3c/filetype/interfaces/__init__.py	2009-01-19 12:42:04 UTC (rev 94829)
@@ -1,57 +1,18 @@
-##############################################################################
-#
-# Copyright (c) 2007 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.
-#
-##############################################################################
-"""
-
-$Id$
-"""
-from zope import interface, schema
-from zope.size.interfaces import ISized
-from zope.lifecycleevent import ObjectModifiedEvent
 from zope.lifecycleevent.interfaces import IObjectModifiedEvent
+from zope import interface, schema
 
+class IFileType(interface.Interface):
 
-class IMimetypeType(interface.interfaces.IInterface):
-    """ mimetype type """
+    contentType = schema.TextLine(title = u'Content Type')
 
+class IFileTypeModifiedEvent(IObjectModifiedEvent):
 
-class IContentType(interface.Interface):
+    """This event is fired when the filetypes change on an object"""
 
-    contentType = schema.TextLine(
-        title = u'Content Type')
-
-
-class IFileData(interface.Interface):
-
-    def open(mode='r'):
-        """ Open file, returns file(-like) object for handling the data """
-
-
-class IImageSized(ISized):
-
-    def getImageSize():
-        """ return width, height of image """
-
-
 class ITypeableFile(interface.Interface):
+
     """A file object that is typeable"""
 
     data = interface.Attribute('Data of the file')
-
-
-class IFileTypeModifiedEvent(IObjectModifiedEvent):
-    """This event is fired when the filetypes change on an object"""
-
-
-class FileTypeModifiedEvent(ObjectModifiedEvent):
-    interface.implements(IFileTypeModifiedEvent)
+    
+    

Deleted: z3c.filetype/trunk/src/z3c/filetype/interfaces/api.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/interfaces/api.py	2009-01-19 12:31:16 UTC (rev 94828)
+++ z3c.filetype/trunk/src/z3c/filetype/interfaces/api.py	2009-01-19 12:42:04 UTC (rev 94829)
@@ -1,43 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2007 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.
-#
-##############################################################################
-""" api interfaces
-
-$Id$
-"""
-from zope import interface
-
-
-class IAPI(interface.Interface):
-    """ filetype api """
-
-    def byMimeType(mt):
-        """returns interfaces implemented by mimeType"""
-
-    def getInterfacesFor(file, filename=None, mimeType=None):
-        """ returns a sequence of interfaces that are provided by file like
-        objects (file argument) with an optional
-        filename as name or mimeType as mime-type """
-
-    def getInterfacesForFile(filename, mimeType=None):
-        """ returns a sequence of interfaces that are provided by file 
-        with filename as name and optional mimeType as mime-type """
-
-    def getInterfacesForFilename(filename):
-        """ returns a sequence of interfaces that are provided by filename """
-
-    def applyInterfaces(obj):
-        """ detect object mimetypes and set mimetype interfaces """
-
-    def convert(obj, mimetype):
-        """ convert obj to destination mimetype """

Deleted: z3c.filetype/trunk/src/z3c/filetype/interfaces/converter.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/interfaces/converter.py	2009-01-19 12:31:16 UTC (rev 94828)
+++ z3c.filetype/trunk/src/z3c/filetype/interfaces/converter.py	2009-01-19 12:42:04 UTC (rev 94829)
@@ -1,50 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2007 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.
-#
-##############################################################################
-""" converter interfaces
-
-$Id$
-"""
-from zope import interface
-
-
-class ConverterException(Exception):
-    """ base converter exception """
-
-
-class ConverterNotFound(Exception):
-    """ required converter not found """
-
-
-class IConverterModule(interface.Interface):
-    """ converter module """
-
-    def convert(context, mimetype):
-        """ convert `context` data to mimetype data, return ITypeableFile object """
-
-
-class IConverter(interface.Interface):
-    """ base interface for data converter """
-
-    def __init__(context, destination):
-        """ adapter """
-
-    def convert():
-        """ convert data """
-
-
-class ISimpleImageConverter(IConverter):
-    """ simple image converter """
-
-    def convert(width=None, height=None, scale=0):
-        """ convert image """

Modified: z3c.filetype/trunk/src/z3c/filetype/interfaces/filetypes.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/interfaces/filetypes.py	2009-01-19 12:31:16 UTC (rev 94828)
+++ z3c.filetype/trunk/src/z3c/filetype/interfaces/filetypes.py	2009-01-19 12:42:04 UTC (rev 94829)
@@ -1,157 +1,117 @@
-##############################################################################
-#
-# Copyright (c) 2007 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.
-#
-##############################################################################
-"""
-
-$Id$
-"""
-import re
 from zope import interface
+import re
 
 # mimeTypeMatch holds regular expression for matching mime-types
 MTM = 'mimeTypesMatch'
-
-# mimeType holds the preferred mime type to be returned for this interface
+# mimeType holds the preferred mime type to be returned for this
+# interface
 MT = "mimeType"
 
-
 class ITypedFile(interface.Interface):
     """A Type of a file"""
 
-
 class IBinaryFile(ITypedFile):
     """Binary file"""
 IBinaryFile.setTaggedValue(MTM,re.compile('application/octet-stream'))
 IBinaryFile.setTaggedValue(MT,'application/octet-stream')
 
-
 class IZIPFile(IBinaryFile):
     """Zip file"""
 IZIPFile.setTaggedValue(MTM,re.compile('application/x-zip'))
 IZIPFile.setTaggedValue(MT,'application/x-zip')
 
-
 class ITARFile(IBinaryFile):
     """Binary file"""
 ITARFile.setTaggedValue(MTM,re.compile('application/x-tar'))
 ITARFile.setTaggedValue(MT,'application/x-tar')
 
-
 class IBZIP2File(IBinaryFile):
     """BZIP2  file"""
 IBZIP2File.setTaggedValue(MTM,re.compile('application/x-bzip2'))
 IBZIP2File.setTaggedValue(MT,'application/x-bzip2')
 
-
 class IGZIPFile(IBinaryFile):
     """Binary file"""
 IGZIPFile.setTaggedValue(MTM,re.compile('application/x-gzip'))
 IGZIPFile.setTaggedValue(MT,'application/x-gzip')
 
-
 class ITextFile(ITypedFile):
     """text files"""
 ITextFile.setTaggedValue(MTM,re.compile('^text/.+$'))
 ITextFile.setTaggedValue(MT,'text/plain')
 
-
 class IImageFile(ITypedFile):
     """image files"""
 IImageFile.setTaggedValue(MTM,re.compile('^image/.+$'))
 
-
 class IPDFFile(IBinaryFile):
     """pdf files"""
 IPDFFile.setTaggedValue(MTM,re.compile('application/pdf'))
 IPDFFile.setTaggedValue(MT,'application/pdf')
 
-
 class IJPGFile(IImageFile, IBinaryFile):
     """jpeg file"""
 IJPGFile.setTaggedValue(MTM,re.compile('image/jpe?g'))
 IJPGFile.setTaggedValue(MT,'image/jpeg')
 
-
 class IPNGFile(IImageFile, IBinaryFile):
     """png file"""
 IPNGFile.setTaggedValue(MTM,re.compile('image/png'))
 IPNGFile.setTaggedValue(MT,'image/png')
 
-
 class IGIFFile(IImageFile, IBinaryFile):
     """gif file"""
 IGIFFile.setTaggedValue(MTM,re.compile('image/gif'))
 IGIFFile.setTaggedValue(MT,'image/gif')
 
-
 class IVideoFile(IBinaryFile):
     """video file"""
 IVideoFile.setTaggedValue(MTM,re.compile('^video/.+$'))
 
-
 class IQuickTimeFile(IVideoFile):
     """Quicktime Video File Format"""
 IQuickTimeFile.setTaggedValue(MTM,re.compile('video/quicktime'))
 IQuickTimeFile.setTaggedValue(MT,'video/quicktime')
 
-
 class IAVIFile(IVideoFile):
     """Quicktime Video File Format"""
 IAVIFile.setTaggedValue(MTM,re.compile('video/x-msvideo'))
 IAVIFile.setTaggedValue(MT,'video/x-msvideo')
 
-
 class IMPEGFile(IVideoFile):
     """MPEG Video File Format"""
 IMPEGFile.setTaggedValue(MTM,re.compile('video/mpe?g'))
 IMPEGFile.setTaggedValue(MT,'video/mpeg')
 
-
 class IMP4File(IQuickTimeFile):
     """IMP4File IPod Video File Format"""
 IMP4File.setTaggedValue(MTM,re.compile('video/mp4'))
 IMP4File.setTaggedValue(MT,'video/mp4')
 
-
 class IFLVFile(IVideoFile):
     """Macromedia Flash FLV Video File Format"""
 IFLVFile.setTaggedValue(MTM,re.compile('video/x-flv'))
 IFLVFile.setTaggedValue(MT,'video/x-flv')
 
-
 class IASFFile(IVideoFile):
     """Windows Media File Format"""
 IASFFile.setTaggedValue(MTM,re.compile('video/x-ms-asf'))
 IASFFile.setTaggedValue(MT,'video/x-ms-asf')
 
-
 class IAudioFile(ITypedFile):
     """audio file"""
 IAudioFile.setTaggedValue(MTM,re.compile('^audio/.+$'))
 
-
 class IAudioMPEGFile(IAudioFile):
     """audio file"""
 IAudioMPEGFile.setTaggedValue(MTM,re.compile('audio/mpeg'))
 IAudioMPEGFile.setTaggedValue(MT,'audio/mpeg')
 
-
 class IHTMLFile(ITextFile):
     """HTML file"""
 IHTMLFile.setTaggedValue(MTM,re.compile('text/html'))
 IHTMLFile.setTaggedValue(MT,'text/html')
 
-
 class IXMLFile(ITextFile):
     """XML File"""
 IXMLFile.setTaggedValue(MTM,re.compile('text/xml'))

Deleted: z3c.filetype/trunk/src/z3c/filetype/interfaces/magic.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/interfaces/magic.py	2009-01-19 12:31:16 UTC (rev 94828)
+++ z3c.filetype/trunk/src/z3c/filetype/interfaces/magic.py	2009-01-19 12:42:04 UTC (rev 94829)
@@ -1,32 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2007 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.
-#
-##############################################################################
-""" magic file interfaces
-
-$Id$
-"""
-
-class MagicError(Exception):
-    pass
-
-
-class MagicTestError(MagicError):
-    pass
-
-
-class OffsetError(MagicError): 
-    pass
-
-
-class MagicFileError(MagicError): 
-    pass

Modified: z3c.filetype/trunk/src/z3c/filetype/magic.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/magic.py	2009-01-19 12:31:16 UTC (rev 94828)
+++ z3c.filetype/trunk/src/z3c/filetype/magic.py	2009-01-19 12:42:04 UTC (rev 94829)
@@ -1,13 +1,11 @@
 # Found on a russian zope mailing list, and modified to fix bugs in parsing
-# the magic file and string making, cleanup
+# the magic file and string making
 # -- Daniel Berlin <dberlin at dberlin.org>
-import sys, os.path
-import struct, time, re, pprint
+import sys, struct, time, re, exceptions, pprint, stat, os
 
-from z3c.filetype.interfaces.magic import \
-    OffsetError, MagicFileError, MagicTestError
+_mew = 0
 
-default_magic = os.path.join(os.path.dirname(__file__), 'magic.mime')
+_magic = os.path.join(os.path.dirname(__file__),'magic.mime')
 
 mime = 1
 
@@ -15,64 +13,104 @@
 
 BUFFER_SIZE = 1024 * 128 # 128K should be enough...
 
+class MagicError(exceptions.Exception): pass
 
-def _handle(fmt='@x',adj=None): 
-    return fmt, struct.calcsize(fmt), adj
+def _handle(fmt='@x',adj=None): return fmt, struct.calcsize(fmt), adj
 
-
 KnownTypes = {
-    'byte': _handle('@b'),
-    'byte': _handle('@B'),
-    'ubyte': _handle('@B'),
-    'string': ('s', 0, None),
-    'pstring': _handle('p'),
-    'short': _handle('@h'),
-    'beshort': _handle('>h'),
-    'leshort': _handle('<h'),
-    'short': _handle('@H'),
-    'beshort': _handle('>H'),
-    'leshort': _handle('<H'),
-    'ushort': _handle('@H'),
-    'ubeshort': _handle('>H'),
-    'uleshort': _handle('<H'),
+    'byte':_handle('@b'),
+    'byte':_handle('@B'),
+    'ubyte':_handle('@B'),
+    'string':('s',0,None),
+    'pstring':_handle('p'),
+    'short':_handle('@h'),
+    'beshort':_handle('>h'),
+    'leshort':_handle('<h'),
+    'short':_handle('@H'),
+    'beshort':_handle('>H'),
+    'leshort':_handle('<H'),
+    'ushort':_handle('@H'),
+    'ubeshort':_handle('>H'),
+    'uleshort':_handle('<H'),
     
-    'long': _handle('@l'),
-    'belong': _handle('>l'),
-    'lelong': _handle('<l'),
-    'ulong': _handle('@L'),
-    'ubelong': _handle('>L'),
-    'ulelong': _handle('<L'),
+    'long':_handle('@l'),
+    'belong':_handle('>l'),
+    'lelong':_handle('<l'),
+    'ulong':_handle('@L'),
+    'ubelong':_handle('>L'),
+    'ulelong':_handle('<L'),
     
-    'date': _handle('=l'),
-    'bedate': _handle('>l'),
-    'ledate': _handle('<l'),
-    'ldate': _handle('=l', _ldate_adjust),
-    'beldate': _handle('>l', _ldate_adjust),
-    'leldate': _handle('<l', _ldate_adjust),
+    'date':_handle('=l'),
+    'bedate':_handle('>l'),
+    'ledate':_handle('<l'),
+    'ldate':_handle('=l',_ldate_adjust),
+    'beldate':_handle('>l',_ldate_adjust),
+    'leldate':_handle('<l',_ldate_adjust),
 }
 
+_mew_cnt = 0
+def mew(x):
+    global _mew_cnt
+    if _mew :
+        if x=='.' :
+            _mew_cnt += 1
+            if _mew_cnt % 64 == 0 : sys.stderr.write( '\n' )
+            sys.stderr.write( '.' )
+        else:
+            sys.stderr.write( '\b'+x )
 
 def has_format(s):
     n = 0
     l = None
-    for c in s:
-        if c == '%':
-            if l == '%': n -= 1
-            else       : n += 1
+    for c in s :
+        if c == '%' :
+            if l == '%' : n -= 1
+            else        : n += 1
         l = c
     return n
 
+def read_asciiz(file,size=None,pos=None):
+    s = []
+    if pos :
+        mew('s')
+        file.seek( pos, 0 )
+    mew('z')
+    if size is not None :
+        s = [file.read( size ).split('\0')[0]]
+    else:
+        while 1 :
+            c = file.read(1)
+            if (not c) or (ord(c)==0) or (c=='\n') : break
+            s.append (c)
+    mew('Z')
+    return ''.join(s)
 
+def a2i(v,base=0):
+    if v[-1:] in 'lL' : v = v[:-1]
+    return int( v, base )
+
+_cmap = {
+        '\\' : '\\',
+        '0' : '\0',
+}
+for c in range(ord('a'),ord('z')+1) :
+    try               : e = eval('"\\%c"' % chr(c))
+    except ValueError : pass
+    else              : _cmap[chr(c)] = e
+else:
+    del c
+    del e
+
 def make_string(s):
     # hack, is this the right way?
-    s = s.replace('\\<', '<')
-    s = s.replace('\\ ', ' ')
-    return eval('"%s"'%s.replace('"', '\\"'))
+    s = s.replace('\\<','<')
+    s = s.replace('\\ ',' ')
+    return eval( '"'+s.replace('"','\\"')+'"')
 
+class MagicTestError(MagicError): pass
 
 class MagicTest:
-
-    def __init__(self, offset, mtype, test, message, line=None, level=None):
+    def __init__(self,offset,mtype,test,message,line=None,level=None):
         self.line, self.level = line, level
         self.mtype = mtype
         self.mtest = test
@@ -81,46 +119,45 @@
         self.smod = None
         self.nmod = None
         self.offset, self.type, self.test, self.message = \
-            offset, mtype, test, message
-
-        if self.mtype == 'true':
-            return # XXX hack to enable level skips
-
-        if (test[-1:] == '\\') and (test[-2:] != '\\\\'):
+                        offset,mtype,test,message
+        if self.mtype == 'true' : return # XXX hack to enable level skips
+        if test[-1:]=='\\' and test[-2:]!='\\\\' :
             self.test += 'n' # looks like someone wanted EOL to match?
-
-        if mtype[:6] == 'string':
+        if mtype[:6]=='string' :
             if '/' in mtype : # for strings
                 self.type, self.smod = \
-                    mtype[:mtype.find('/')], mtype[mtype.find('/')+1:]
+                                        mtype[:mtype.find('/')], mtype[mtype.find('/')+1:]
         else:
-            for nm in '&+-':
-                if nm in mtype: # for integer-based
-                    self.nmod = nm
-                    self.type = mtype[:mtype.find(nm)]
-
-                    # convert mask to int, autodetect base
-                    self.mask = int(mtype[mtype.find(nm)+1:], 0)
+            for nm in '&+-' :
+                if nm in mtype : # for integer-based
+                    self.nmod, self.type, self.mask = (
+                            nm,
+                            mtype[:mtype.find(nm)],
+                            # convert mask to int, autodetect base
+                            int( mtype[mtype.find(nm)+1:], 0 )
+                    )
                     break
-
-        self.struct, self.size, self.cast = KnownTypes[self.type]
-
+        self.struct, self.size, self.cast = KnownTypes[ self.type ]
     def __str__(self):
         return '%s %s %s %s' % (
-            self.offset, self.mtype, self.mtest, self.message)
-
+                self.offset, self.mtype, self.mtest, self.message
+        )
     def __repr__(self):
         return 'MagicTest(%s,%s,%s,%s,line=%s,level=%s,subtests=\n%s%s)' % (
                 `self.offset`, `self.mtype`, `self.mtest`, `self.message`,
                 `self.line`, `self.level`,
                 '\t'*self.level, pprint.pformat(self.subtests)
         )
-
-    def run(self, file):
+    def run(self,file):
         result = ''
-
+        do_close = 0
         try:
-            if self.mtype != 'true':
+            if type(file) == type('x') :
+                file = open( file, 'r', BUFFER_SIZE )
+                do_close = 1
+#                       else:
+#                               saved_pos = file.tell()
+            if self.mtype != 'true' :
                 data = self.read(file)
                 try:
                     last = file.tell()
@@ -130,125 +167,92 @@
                     pass
             else:
                 data = last = None
-
-            if self.check(data):
-                result = self.message + ' '
-
-                if has_format(result):
-                    result %= data
-
-                for test in self.subtests:
+            if self.check( data ) :
+                result = self.message+' '
+                if has_format( result ) : result %= data
+                for test in self.subtests :
                     m = test.run(file)
-                    if m is not None:
-                        result += m
-
-                return make_string(result)
-        except Exception, e:
-            #log_info('Type detection: %s'%str(e)
-            pass
-
-    def a2i(self, v, base=0):
-        if v[-1:] in 'lL': 
-            v = v[:-1]
-        return int(v, base)
-
+                    if m is not None : result += m
+                return make_string( result )
+        finally:
+            if do_close :
+                file.close()
+#                       else:
+#                               file.seek( saved_pos, 0 )
     def get_mod_and_value(self):
-        if self.type[-6:] == 'string':
-            if self.test[0] in '=<>':
-                mod = self.test[0]
-                value = make_string(self.test[1:])
+        if self.type[-6:] == 'string' :
+#             if 'ustar' in self.test:
+#                 import pdb;pdb.set_trace()
+            # "something like\tthis\n"
+            if self.test[0] in '=<>' :
+                mod, value = self.test[0], make_string( self.test[1:] )
             else:
-                mod = '='
-                value = make_string( self.test )
+                mod, value = '=', make_string( self.test )
         else:
-            if self.test[0] in '=<>&^':
-                mod = self.test[0]
-                value = self.a2i(self.test[1:])
+            if self.test[0] in '=<>&^' :
+                mod, value = self.test[0], a2i(self.test[1:])
             elif self.test[0] == 'x':
                 mod = self.test[0]
                 value = 0
             else:
-                mod = '='
-                value = self.a2i(self.test)
+                mod, value = '=', a2i(self.test)
         return mod, value
-
-    def read(self, file):
-        file.seek(self.offset(file), 0) # SEEK_SET
+    def read(self,file):
+        mew( 's' )
+        file.seek( self.offset(file), 0 ) # SEEK_SET
+        mew( 'r' )
         try:
             data = rdata = None
             # XXX self.size might be 0 here...
-            if self.size == 0:
+            if self.size == 0 :
                 # this is an ASCIIZ string...
                 size = None
-                if self.test != '>\\0': # magic's hack for string read...
+                if self.test != '>\\0' : # magic's hack for string read...
                     value = self.get_mod_and_value()[1]
                     size = (value=='\0') and None or len(value)
-
-                rdata = data = self.read_asciiz(file, size=size)
+                rdata = data = read_asciiz( file, size=size )
             else:
-                rdata = file.read(self.size)
-                if not rdata or (len(rdata) != self.size):
-                    return None
-
-                data = struct.unpack(self.struct, rdata)[0] # XXX hack??
+                rdata = file.read( self.size )
+                if not rdata or (len(rdata)!=self.size) : return None
+                data = struct.unpack( self.struct, rdata )[0] # XXX hack??
         except:
-            raise MagicTestError('@%s struct=%s size=%d rdata=%s' % (
-                    self.offset, `self.struct`, self.size, `rdata`))
-
-        if self.cast:
-            data = self.cast(data)
-
-        if self.mask:
+            print >>sys.stderr, self
+            print >>sys.stderr, '@%s struct=%s size=%d rdata=%s' % (
+                    self.offset, `self.struct`, self.size,`rdata`)
+            raise
+        mew( 'R' )
+        if self.cast : data = self.cast( data )
+        if self.mask :
             try:
-                if self.nmod == '&':
-                    data &= self.mask
-                elif self.nmod == '+':
-                    data += self.mask
-                elif self.nmod == '-':
-                    data -= self.mask
-                else: 
-                    raise MagicTestError(self.nmod)
+                if   self.nmod == '&' : data &= self.mask
+                elif self.nmod == '+' : data += self.mask
+                elif self.nmod == '-' : data -= self.mask
+                else: raise MagicTestError(self.nmod)
             except:
-                raise MagicTestError('data=%s nmod=%s mask=%s' % (
-                        `data`, `self.nmod`, `self.mask`))
-
+                print >>sys.stderr,'data=%s nmod=%s mask=%s' % (
+                        `data`, `self.nmod`, `self.mask`
+                )
+                raise
         return data
-
-    def read_asciiz(self, file, size=None):
-        s = []
-        if size is not None :
-            s = [file.read(size).split('\0')[0]]
-        else:
-            while 1:
-                c = file.read(1)
-                if (not c) or (ord(c) == 0) or (c == '\n'):
-                    break
-            s.append (c)
-
-        return ''.join(s)
-
-    def check(self, data):
+    def check(self,data):
+        mew('.')
         if self.mtype == 'true' :
             return '' # not None !
-
         mod, value = self.get_mod_and_value()
         if self.type[-6:] == 'string' :
             # "something like\tthis\n"
             if self.smod:
+                #import pdb;pdb.set_trace()
                 xdata = data
-
-                if 'b' in self.smod: # all blanks are optional
-                    xdata = ''.join(data.split())
-                    value = ''.join(value.split())
-
-                if 'c' in self.smod: # all blanks are optional
+                if 'b' in self.smod : # all blanks are optional
+                    xdata = ''.join( data.split() )
+                    value = ''.join( value.split() )
+                if 'c' in self.smod : # all blanks are optional
                     xdata = xdata.upper()
                     value = value.upper()
-
-                if 'B' in self.smod: # compact blanks
-                    data = ' '.join(data.split())
-                    if ' ' not in data:
-                        return None
+                if 'B' in self.smod : # compact blanks
+                    data = ' '.join( data.split() )
+                    if ' ' not in data : return None
             else:
                 xdata = data
         try:
@@ -258,50 +262,46 @@
             elif mod == '&' : result = data & value
             elif mod == '^' : result = (data & (~value)) == 0
             elif mod == 'x' : result = 1
-            else: 
-                raise MagicTestError(self.test)
-
-            if result:
+            else            : raise MagicTestError(self.test)
+            if result :
                 zdata, zval = `data`, `value`
-
-                if self.mtype[-6:] != 'string':
-                    try: 
-                        zdata = hex(data)
-                        zval = hex(value)
-                    except: 
-                        zdata = `data`
-                        zval = `value`
-
+                if self.mtype[-6:]!='string' :
+                    try: zdata, zval = hex(data), hex(value)
+                    except: zdata, zval = `data`, `value`
+                if 0 : print >>sys.stderr, '%s @%s %s:%s %s %s => %s (%s)' % (
+                        '>'*self.level, self.offset,
+                        zdata, self.mtype, `mod`, zval, `result`,
+                        self.message
+                )
             return result
         except:
-            raise MagicTestError('mtype=%s data=%s mod=%s value=%s' % (
-                    `self.mtype`, `data`, `mod`, `value`))
-
+            print >>sys.stderr,'mtype=%s data=%s mod=%s value=%s' % (
+                    `self.mtype`, `data`, `mod`, `value`
+            )
+            raise
     def add(self,mt):
-        if not isinstance(mt, MagicTest):
-            raise MagicTestError((mt, 'incorrect subtest type %s'%(type(mt),)))
-
-        if mt.level == self.level+1:
-            self.subtests.append(mt)
-
-        elif self.subtests:
-            self.subtests[-1].add(mt)
-
-        elif mt.level > self.level+1:
+        if not isinstance(mt,MagicTest) :
+            raise MagicTestError((mt,'incorrect subtest type %s'%(type(mt),)))
+        if mt.level == self.level+1 :
+            self.subtests.append( mt )
+        elif self.subtests :
+            self.subtests[-1].add( mt )
+        elif mt.level > self.level+1 :
             # it's possible to get level 3 just after level 1 !!! :-(
             level = self.level + 1
-            while level < mt.level:
-                xmt = MagicTest(None, 'true', 'x', '', line=self.line, level=level)
-                self.add(xmt)
+            while level < mt.level :
+                xmt = MagicTest(None,'true','x','',line=self.line,level=level)
+                self.add( xmt )
                 level += 1
             else:
-                self.add(mt) # retry...
+                self.add( mt ) # retry...
         else:
-            raise MagicTestError((mt, 'incorrect subtest level %s'%(`mt.level`,)))
-
+            raise MagicTestError((mt,'incorrect subtest level %s'%(`mt.level`,)))
     def last_test(self):
         return self.subtests[-1]
+#end class MagicTest
 
+class OffsetError(MagicError): pass
 
 class Offset:
     pos_format = {'b':'<B','B':'>B','s':'<H','S':'>H','l':'<I','L':'>I',}
@@ -337,137 +337,134 @@
                 )?
                 \)$''', re.X|re.I
     )
-
     def __init__(self,s):
         self.source = s
         self.value  = None
-        self.relative = False
+        self.relative = 0
         self.base = self.type = self.sign = self.offs = None
-
-        m = Offset.pattern0.match(s)
-        if m: # just a number
-            if s[0] == '&':
-                self.relative = True
-                self.value = int(s[1:], 0)
+        m = Offset.pattern0.match( s )
+        if m : # just a number
+            if s[0] == '&' :
+                self.relative, self.value = 1, int( s[1:], 0 )
             else:
                 self.value = int( s, 0 )
             return
-
-        m = Offset.pattern1.match(s)
-        if m: # real indirect offset
+        m = Offset.pattern1.match( s )
+        if m : # real indirect offset
             try:
                 self.base = m.group('base')
-                if self.base[0] == '&':
-                    self.relative = True
-                    self.base = int(self.base[1:], 0)
+                if self.base[0] == '&' :
+                    self.relative, self.base = 1, int( self.base[1:], 0 )
                 else:
-                    self.base = int(self.base, 0)
-
-                if m.group('type'): 
-                    self.type = m.group('type')[1:]
-
+                    self.base = int( self.base, 0 )
+                if m.group('type') : self.type = m.group('type')[1:]
                 self.sign = m.group('sign')
-                if m.group('off'):
-                    self.offs = int( m.group('off'), 0 )
-
-                if self.sign == '-':
-                    self.offs = 0 - self.offs
+                if m.group('off') : self.offs = int( m.group('off'), 0 )
+                if self.sign == '-' : self.offs = 0 - self.offs
             except:
-                raise OffsetError(m.groupdict())
-
+                print >>sys.stderr, '$$', m.groupdict()
+                raise
             return
         raise OffsetError(`s`)
-
-    def __call__(self, file=None):
-        if self.value is not None:
-            return self.value
-
+    def __call__(self,file=None):
+        if self.value is not None : return self.value
         pos = file.tell()
         try:
-            if not self.relative:
-                file.seek(self.offset, 0)
-
-            frmt = Offset.pos_format.get(self.type, 'I')
-            size = struct.calcsize(frmt)
-            data = struct.unpack(frmt, file.read(size))
-
-            if self.offs:
-                data += self.offs
-
+            if not self.relative : file.seek( self.offset, 0 )
+            frmt = Offset.pos_format.get( self.type, 'I' )
+            size = struct.calcsize( frmt )
+            data = struct.unpack( frmt, file.read( size ) )
+            if self.offs : data += self.offs
             return data
         finally:
-            file.seek(pos, 0)
+            file.seek( pos, 0 )
+    def __str__(self): return self.source
+    def __repr__(self): return 'Offset(%s)' % `self.source`
+#end class Offset
 
-    def __str__(self): 
-        return self.source
+class MagicFileError(MagicError): pass
 
-    def __repr__(self): 
-        return 'Offset(%s)' % `self.source`
-
-
-class MagicFile(object):
-
-    def __init__(self, filename=default_magic):
+class MagicFile:
+    def __init__(self,filename=_magic):
+        self.file = None
         self.tests = []
         self.total_tests = 0
-        self.load(filename)
-
-    def load(self, filename=None):
-        file = open(filename, 'r', BUFFER_SIZE)
-        self.parse(file)
-        file.close()
-
-    def parse(self, data):
+        self.load( filename )
+        self.ack_tests = None
+        self.nak_tests = None
+    def __del__(self):
+        self.close()
+    def load(self,filename=None):
+        self.open( filename )
+        self.parse()
+        self.close()
+    def open(self,filename=None):
+        self.close()
+        if filename is not None :
+            self.filename = filename
+        self.file = open( self.filename, 'r', BUFFER_SIZE )
+    def close(self):
+        if self.file :
+            self.file.close()
+            self.file = None
+    def parse(self):
         line_no = 0
-        for line in data:
+        for line in self.file.xreadlines() :
             line_no += 1
-
-            data = self.parse_line(line)
-            if data is None:
-                continue
-
+            if not line or line[0]=='#' : continue
+            line = line.lstrip().rstrip('\r\n')
+            if not line or line[0]=='#' : continue
+            try:
+                x = self.parse_line( line )
+                if x is None :
+                    print >>sys.stderr, '#[%04d]#'%line_no, line
+                    continue
+            except:
+                print >>sys.stderr, '###[%04d]###'%line_no, line
+                raise
             self.total_tests += 1
-
-            level = data[0]
-            new_test = MagicTest(*data[1:], **{'line': line_no, 'level': data[0]})
+            level, offset, mtype, test, message = x
+            new_test = MagicTest(offset,mtype,test,message,
+                    line=line_no,level=level)
             try:
                 if level == 0 :
                     self.tests.append( new_test )
                 else:
                     self.tests[-1].add( new_test )
             except:
-                raise MagicFileError('total tests=%s, level=%s, tests=%s'%(
-                        len(self.total_tests), 
-                        level, pprint.pformat(self.tests)))
+                if 1 :
+                    print >>sys.stderr, 'total tests=%s' % (
+                            `self.total_tests`,
+                    )
+                    print >>sys.stderr, 'level=%s' % (
+                            `level`,
+                    )
+                    print >>sys.stderr, 'tests=%s' % (
+                            pprint.pformat(self.tests),
+                    )
+                raise
         else:
             while self.tests[-1].level > 0 :
                 self.tests.pop()
-
-    def parse_line(self, line):
-        line = line.lstrip().rstrip('\r\n')
-
-        if not line or line[0]=='#':
-            return None
-
+    def parse_line(self,line):
+        # print >>sys.stderr, 'line=[%s]' % line
+        if (not line) or line[0]=='#' : return None
         level = 0
         offset = mtype = test = message = ''
-
+        mask = None
         # get optional level (count leading '>')
-        while line and line[0]=='>':
+        while line and line[0]=='>' :
             line, level = line[1:], level+1
-
         # get offset
-        while line and not line[0].isspace():
+        while line and not line[0].isspace() :
             offset, line = offset+line[0], line[1:]
-
         try:
             offset = Offset(offset)
         except:
-            raise MagicFileError('line=[%s]' % line)
-
+            print >>sys.stderr, 'line=[%s]' % line
+            raise
         # skip spaces
         line = line.lstrip()
-
         # get type
         c = None
         while line :
@@ -478,10 +475,8 @@
                 mtype += c
                 if last_c == '\\' :
                     c = None # don't fuck my brain with sequential backslashes
-
         # skip spaces
         line = line.lstrip()
-
         # get test
         c = None
         while line :
@@ -492,23 +487,235 @@
                 test += c
                 if last_c == '\\' :
                     c = None # don't fuck my brain with sequential backslashes
-
         # skip spaces
         line = line.lstrip()
-
         # get message
         message = line
         if mime and line.find("\t") != -1:
-            message = line[0:line.find("\t")]
-
+            message=line[0:line.find("\t")]
+        #
+        # print '>>', level, offset, mtype, test, message
         return level, offset, mtype, test, message
-
-    def detect(self, file):
+    def detect(self,file):
+        self.ack_tests = 0
+        self.nak_tests = 0
         answers = set()
-        for test in self.tests:
-            message = test.run(file)
+        for test in self.tests :
+            message = test.run( file )
             if message and message.strip():
-                msg = message.strip().split()[0]
-                if msg not in answers:
-                    answers.add(msg)
-                    yield msg
+                self.ack_tests += 1
+                answers.add( message.strip().split()[0] )
+            else:
+                self.nak_tests += 1
+        return answers
+
+#end class MagicFile
+
+def username(uid):
+    try:
+        import pwd
+        return pwd.getpwuid( uid )[0]
+    except:
+        return '#%s'%uid
+
+def groupname(gid):
+    try:
+        import grp
+        return grp.getgrgid( gid )[0]
+    except:
+        return '#%s'%gid
+
+def get_file_type(fname,follow):
+    t = None
+    if not follow :
+        try:
+            st = os.lstat( fname ) # stat that entry, don't follow links!
+        except os.error, why :
+            pass
+        else:
+            if stat.S_ISLNK(st[stat.ST_MODE]) :
+                t = 'symbolic link'
+                try:
+                    lnk = os.readlink( fname )
+                except:
+                    t += ' (unreadable)'
+                else:
+                    t += ' to '+lnk
+    if t is None :
+        try:
+            st = os.stat( fname )
+        except os.error, why :
+            return "can't stat `%s' (%s)." % (why.filename,why.strerror)
+
+    dmaj, dmin = (st.st_rdev>>8)&0x0FF, st.st_rdev&0x0FF
+
+    if 0 : pass
+    elif stat.S_ISSOCK(st.st_mode) : t = 'socket'
+    elif stat.S_ISLNK (st.st_mode) : t = follow and 'symbolic link' or t
+    elif stat.S_ISREG (st.st_mode) : t = 'file'
+    elif stat.S_ISBLK (st.st_mode) : t = 'block special (%d/%d)'%(dmaj,dmin)
+    elif stat.S_ISDIR (st.st_mode) : t = 'directory'
+    elif stat.S_ISCHR (st.st_mode) : t = 'character special (%d/%d)'%(dmaj,dmin)
+    elif stat.S_ISFIFO(st.st_mode) : t = 'pipe'
+    else: t = '<unknown>'
+
+    if st.st_mode & stat.S_ISUID :
+        t = 'setuid(%d=%s) %s'%(st.st_uid,username(st.st_uid),t)
+    if st.st_mode & stat.S_ISGID :
+        t = 'setgid(%d=%s) %s'%(st.st_gid,groupname(st.st_gid),t)
+    if st.st_mode & stat.S_ISVTX :
+        t = 'sticky '+t
+
+    return t
+
+HELP = '''%s [options] [files...]
+
+Options:
+
+        -?, --help -- this help
+        -m, --magic=<file> -- use this magic <file> instead of %s
+        -f, --files=<namefile> -- read filenames for <namefile>
+*       -C, --compile -- write "compiled" magic file
+        -b, --brief -- don't prepend filenames to output lines
++       -c, --check -- check the magic file
+        -i, --mime -- output MIME types
+*       -k, --keep-going -- don't stop st the first match
+        -n, --flush -- flush stdout after each line
+        -v, --verson -- print version and exit
+*       -z, --compressed -- try to look inside compressed files
+        -L, --follow -- follow symlinks
+        -s, --special -- don't skip special files
+
+*       -- not implemented so far ;-)
++       -- implemented, but in another way...
+'''
+
+def main():
+    import getopt
+    global _magic
+    try:
+        brief = 0
+        flush = 0
+        follow= 0
+        mime  = 0
+        check = 0
+        special=0
+        try:
+            opts, args = getopt.getopt(
+                    sys.argv[1:],
+                    '?m:f:CbciknvzLs',
+                    (       'help',
+                            'magic=',
+                            'names=',
+                            'compile',
+                            'brief',
+                            'check',
+                            'mime',
+                            'keep-going',
+                            'flush',
+                            'version',
+                            'compressed',
+                            'follow',
+                            'special',
+                    )
+            )
+        except getopt.error, why:
+            print >>sys.stderr, sys.argv[0], why
+            return 1
+        else:
+            files = None
+            for o,v in opts :
+                if o in ('-?','--help'):
+                    print HELP % (
+                            sys.argv[0],
+                            _magic,
+                    )
+                    return 0
+                elif o in ('-f','--files='):
+                    files = v
+                elif o in ('-m','--magic='):
+                    _magic = v[:]
+                elif o in ('-C','--compile'):
+                    pass
+                elif o in ('-b','--brief'):
+                    brief = 1
+                elif o in ('-c','--check'):
+                    check = 1
+                elif o in ('-i','--mime'):
+                    mime = 1
+                    if os.path.exists( _magic+'.mime' ) :
+                        _magic += '.mime'
+                        print >>sys.stderr,sys.argv[0]+':',\
+                                                        "Using regular magic file `%s'" % _magic
+                elif o in ('-k','--keep-going'):
+                    pass
+                elif o in ('-n','--flush'):
+                    flush = 1
+                elif o in ('-v','--version'):
+                    print 'VERSION'
+                    return 0
+                elif o in ('-z','--compressed'):
+                    pass
+                elif o in ('-L','--follow'):
+                    follow = 1
+                elif o in ('-s','--special'):
+                    special = 1
+            else:
+                if files :
+                    files = map(lambda x: x.strip(), v.split(','))
+                    if '-' in files and '-' in args :
+                        error( 1, 'cannot use STDIN simultaneously for file list and data' )
+                    for file in files :
+                        for name in (
+                                        (file=='-')
+                                                and sys.stdin
+                                                or open(file,'r',BUFFER_SIZE)
+                        ).xreadlines():
+                            name = name.strip()
+                            if name not in args :
+                                args.append( name )
+        try:
+            if check : print >>sys.stderr, 'Loading magic database...'
+            t0 = time.time()
+            m = MagicFile(_magic)
+            t1 = time.time()
+            if check :
+                print >>sys.stderr, \
+                                        m.total_tests, 'tests loaded', \
+                                        'for', '%.2f' % (t1-t0), 'seconds'
+                print >>sys.stderr, len(m.tests), 'tests at top level'
+                return 0 # XXX "shortened" form ;-)
+
+            mlen = max( map(len, args) )+1
+            for arg in args :
+                if not brief : print (arg + ':').ljust(mlen),
+                ftype = get_file_type( arg, follow )
+                if (special and ftype.find('special')>=0) \
+                                or ftype[-4:] == 'file' :
+                    t0 = time.time()
+                    try:
+                        t = m.detect( arg )
+                    except (IOError,os.error), why:
+                        t = "can't read `%s' (%s)" % (why.filename,why.strerror)
+                    if ftype[-4:] == 'file' : t = ftype[:-4] + t
+                    t1 = time.time()
+                    print t and t or 'data'
+                    if 0 : print \
+                                                        '#\t%d tests ok, %d tests failed for %.2f seconds'%\
+                                                        (m.ack_tests, m.nak_tests, t1-t0)
+                else:
+                    print mime and 'application/x-not-regular-file' or ftype
+                if flush : sys.stdout.flush()
+        # print >>sys.stderr, 'DONE'
+        except:
+            if check : return 1
+            raise
+        else:
+            return 0
+    finally:
+        pass
+
+if __name__ == '__main__' :
+    sys.exit( main() )
+# vim:ai
+# EOF #

Modified: z3c.filetype/trunk/src/z3c/filetype/size.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/size.py	2009-01-19 12:31:16 UTC (rev 94828)
+++ z3c.filetype/trunk/src/z3c/filetype/size.py	2009-01-19 12:42:04 UTC (rev 94829)
@@ -1,44 +1,34 @@
-##############################################################################
-#
-# Copyright (c) 2007 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.
-#
-##############################################################################
-"""
-
-$Id$
-"""
-import os, struct
 import zope.i18nmessageid
-from zope import component, interface
+
+from zope.size.interfaces import ISized
+
 from zope.size import byteDisplay
-from zope.cachedescriptors.property import Lazy
-from z3c.filetype.interfaces import filetypes, IImageSized, IFileData
+from interfaces import filetypes
+from zope import component, interface
+import os
+import stat
+import struct
 
+
 _ = zope.i18nmessageid.MessageFactory("zope")
 
 
 class ImageFileSized(object):
-    interface.implements(IImageSized)
+
+    interface.implements(ISized)
     
-    def __init__(self, context):
-        self.context = context
+    def __init__(self, image):
+        self._image = image
 
-    @Lazy
+    @property
     def bytes(self):
-        file = IFileData(self.context).open('r')
-        file.seek(0, 2)
-        len = file.tell()
-        file.close()
-        return len
-
+        try:
+            return len(self._image.data)
+        except TypeError:
+            data = self._image.data
+            return int(os.fstat(data.fileno())[stat.ST_SIZE])
+        raise NotImplementedError
+    
     def sizeForSorting(self):
         '''See `ISized`'''
         return ('byte', self.bytes)
@@ -48,12 +38,12 @@
 
     def sizeForDisplay(self):
         '''See `ISized`'''
+
         w, h = self.getImageSize()
         if w < 0:
             w = '?'
         if h < 0:
             h = '?'
-
         byte_size = byteDisplay(self.bytes)
         mapping = byte_size.mapping
         if mapping is None:
@@ -65,14 +55,14 @@
 
 
 class GIFFileSized(ImageFileSized):
+
+    interface.implements(ISized)
     component.adapts(filetypes.IGIFFile)
 
     def getImageSize(self):
-        file = IFileData(self.context).open('r')
-        file.seek(0)
-        data = file.read(24)
-        file.close()
-
+        data = self._image.data
+        data.seek(0)
+        data = data.read(24)
         size = len(data)
         width = -1
         height = -1
@@ -81,19 +71,17 @@
             w, h = struct.unpack("<HH", data[6:10])
             width = int(w)
             height = int(h)
-
         return width, height
-
-
+    
 class PNGFileSized(ImageFileSized):
-    component.adapts(filetypes.IPNGFile)
 
+    interface.implements(ISized)
+    component.adapts(filetypes.IPNGFile)
+    
     def getImageSize(self):
-        file = IFileData(self.context).open('r')
-        file.seek(0)
-        data = file.read(24)
-        file.close()
-
+        data = self._image.data
+        data.seek(0)
+        data = data.read(24)
         size = len(data)
         height = -1
         width = -1
@@ -112,14 +100,14 @@
             height = int(h)
         return width, height
 
-
 class JPGFileSized(ImageFileSized):
-    component.adapts(filetypes.IJPGFile)
 
+    interface.implements(ISized)
+    component.adapts(filetypes.IJPGFile)
+    
     def getImageSize(self):
-        data = IFileData(self.context).open('r')
+        data = self._image.data
         data.seek(2)
-
         size = self.bytes
         height = -1
         width = -1
@@ -128,28 +116,19 @@
             w = -1
             h = -1
             while (b and ord(b) != 0xDA):
-                while (ord(b) != 0xFF):
-                    b = data.read(1)
-
-                while (ord(b) == 0xFF):
-                    b = data.read(1)
-
+                while (ord(b) != 0xFF): b = data.read(1)
+                while (ord(b) == 0xFF): b = data.read(1)
                 if (ord(b) >= 0xC0 and ord(b) <= 0xC3):
                     data.read(3)
                     h, w = struct.unpack(">HH", data.read(4))
                     break
                 else:
                     data.read(int(struct.unpack(">H", data.read(2))[0])-2)
-
                 b = data.read(1)
-
             width = int(w)
             height = int(h)
-
         except struct.error:
             pass
         except ValueError:
             pass
-
-        data.close()
         return width, height

Modified: z3c.filetype/trunk/src/z3c/filetype/tests.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/tests.py	2009-01-19 12:31:16 UTC (rev 94828)
+++ z3c.filetype/trunk/src/z3c/filetype/tests.py	2009-01-19 12:42:04 UTC (rev 94829)
@@ -1,57 +1,22 @@
-##############################################################################
-#
-# Copyright (c) 2007 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.
-#
-##############################################################################
-""" tests setup
+import doctest
+import unittest
+from zope.testing.doctestunit import DocFileSuite, DocTestSuite
 
-$Id$
-"""
-import doctest, unittest
-from zope.app.testing import setup
-from zope import component
-
-from z3c.filetype import size, typeablefile
+def test_suite():
     
+    return unittest.TestSuite(
+        (
+        DocFileSuite('README.txt',
+                     optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+                     ),
+        DocFileSuite('magic.txt',
+                     optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+                     ),
+        DocTestSuite('z3c.filetype.api',
+                     optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+                     ),
+        ))
 
-def setUp(test):
-    setup.placelessSetUp()
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
 
-    component.provideAdapter(size.JPGFileSized)
-    component.provideAdapter(size.GIFFileSized)
-    component.provideAdapter(size.PNGFileSized)
-
-    component.provideAdapter(typeablefile.TypeableFileData)
-    component.provideHandler(typeablefile.handleCreated)
-    component.provideHandler(typeablefile.handleModified)
-
-
-def test_suite():
-    return unittest.TestSuite((
-            doctest.DocFileSuite(
-                'README.txt',
-                setUp=setUp, tearDown=setup.placelessTearDown,
-                optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
-                ),
-            doctest.DocFileSuite(
-                'converter.txt',
-                setUp=setUp, tearDown=setup.placelessTearDown,
-                optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
-                ),
-            doctest.DocFileSuite(
-                'magic.txt',
-                optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
-                ),
-            doctest.DocTestSuite(
-                'z3c.filetype.api',
-                optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
-                ),
-            ))

Deleted: z3c.filetype/trunk/src/z3c/filetype/typeablefile.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/typeablefile.py	2009-01-19 12:31:16 UTC (rev 94828)
+++ z3c.filetype/trunk/src/z3c/filetype/typeablefile.py	2009-01-19 12:42:04 UTC (rev 94829)
@@ -1,57 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2007 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.
-#
-##############################################################################
-""" ITypeableFile implementation
-
-$Id$
-"""
-from cStringIO import StringIO
-from zope import interface, component
-from zope.lifecycleevent.interfaces import IObjectCreatedEvent
-from zope.lifecycleevent.interfaces import IObjectModifiedEvent
-
-from z3c.filetype import api, interfaces
-
-
-class TypeableFile(object):
-    interface.implements(interfaces.ITypeableFile)
-
-    def __init__(self, data=''):
-        self.data = data
-        if data:
-            api.applyInterfaces(self)
-
-
-class TypeableFileData(object):
-    interface.implements(interfaces.IFileData)
-    component.adapts(interfaces.ITypeableFile)
-
-    def __init__(self, context):
-        self.context = context
-
-    def open(self, mode=''):
-        return StringIO(self.context.data)
-
-
- at component.adapter(interfaces.ITypeableFile, IObjectCreatedEvent)
-def handleCreated(typeableFile, event):
-    """handles modification of data"""
-    api.applyInterfaces(typeableFile)
-
-
- at component.adapter(interfaces.ITypeableFile, IObjectModifiedEvent)
-def handleModified(typeableFile, event):
-    """handles modification of data"""
-    if interfaces.IFileTypeModifiedEvent.providedBy(event):
-        return
-    api.applyInterfaces(typeableFile)



More information about the Checkins mailing list